| | |
| | |
| | |
| |
|
| | |
| |
|
| | package http |
| |
|
| | import ( |
| | "bytes" |
| | "internal/testenv" |
| | "io/fs" |
| | "net/url" |
| | "os" |
| | "regexp" |
| | "slices" |
| | "strings" |
| | "testing" |
| | ) |
| |
|
| | func TestForeachHeaderElement(t *testing.T) { |
| | tests := []struct { |
| | in string |
| | want []string |
| | }{ |
| | {"Foo", []string{"Foo"}}, |
| | {" Foo", []string{"Foo"}}, |
| | {"Foo ", []string{"Foo"}}, |
| | {" Foo ", []string{"Foo"}}, |
| |
|
| | {"foo", []string{"foo"}}, |
| | {"anY-cAsE", []string{"anY-cAsE"}}, |
| |
|
| | {"", nil}, |
| | {",,,, , ,, ,,, ,", nil}, |
| |
|
| | {" Foo,Bar, Baz,lower,,Quux ", []string{"Foo", "Bar", "Baz", "lower", "Quux"}}, |
| | } |
| | for _, tt := range tests { |
| | var got []string |
| | foreachHeaderElement(tt.in, func(v string) { |
| | got = append(got, v) |
| | }) |
| | if !slices.Equal(got, tt.want) { |
| | t.Errorf("foreachHeaderElement(%q) = %q; want %q", tt.in, got, tt.want) |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | func TestCmdGoNoHTTPServer(t *testing.T) { |
| | t.Parallel() |
| | goBin := testenv.GoToolPath(t) |
| | out, err := testenv.Command(t, goBin, "tool", "nm", goBin).CombinedOutput() |
| | if err != nil { |
| | t.Fatalf("go tool nm: %v: %s", err, out) |
| | } |
| | wantSym := map[string]bool{ |
| | |
| | "net/http.(*Client).do": true, |
| | "net/http.(*Transport).RoundTrip": true, |
| |
|
| | |
| | "net/http.http2Server": false, |
| | "net/http.(*Server).Serve": false, |
| | "net/http.(*ServeMux).ServeHTTP": false, |
| | "net/http.DefaultServeMux": false, |
| | } |
| | for sym, want := range wantSym { |
| | got := bytes.Contains(out, []byte(sym)) |
| | if !want && got { |
| | t.Errorf("cmd/go unexpectedly links in HTTP server code; found symbol %q in cmd/go", sym) |
| | } |
| | if want && !got { |
| | t.Errorf("expected to find symbol %q in cmd/go; not found", sym) |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | func TestOmitHTTP2(t *testing.T) { |
| | if testing.Short() { |
| | t.Skip("skipping in short mode") |
| | } |
| | t.Parallel() |
| | goTool := testenv.GoToolPath(t) |
| | out, err := testenv.Command(t, goTool, "test", "-short", "-tags=nethttpomithttp2", "net/http").CombinedOutput() |
| | if err != nil { |
| | t.Fatalf("go test -short failed: %v, %s", err, out) |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | func TestOmitHTTP2Vet(t *testing.T) { |
| | t.Parallel() |
| | goTool := testenv.GoToolPath(t) |
| | out, err := testenv.Command(t, goTool, "vet", "-tags=nethttpomithttp2", "net/http").CombinedOutput() |
| | if err != nil { |
| | t.Fatalf("go vet failed: %v, %s", err, out) |
| | } |
| | } |
| |
|
| | var valuesCount int |
| |
|
| | func BenchmarkCopyValues(b *testing.B) { |
| | b.ReportAllocs() |
| | src := url.Values{ |
| | "a": {"1", "2", "3", "4", "5"}, |
| | "b": {"2", "2", "3", "4", "5"}, |
| | "c": {"3", "2", "3", "4", "5"}, |
| | "d": {"4", "2", "3", "4", "5"}, |
| | "e": {"1", "1", "2", "3", "4", "5", "6", "7", "abcdef", "l", "a", "b", "c", "d", "z"}, |
| | "j": {"1", "2"}, |
| | "m": nil, |
| | } |
| | for i := 0; i < b.N; i++ { |
| | dst := url.Values{"a": {"b"}, "b": {"2"}, "c": {"3"}, "d": {"4"}, "j": nil, "m": {"x"}} |
| | copyValues(dst, src) |
| | if valuesCount = len(dst["a"]); valuesCount != 6 { |
| | b.Fatalf(`%d items in dst["a"] but expected 6`, valuesCount) |
| | } |
| | } |
| | if valuesCount == 0 { |
| | b.Fatal("Benchmark wasn't run") |
| | } |
| | } |
| |
|
| | var forbiddenStringsFunctions = map[string]bool{ |
| | |
| | "EqualFold": true, |
| | "Title": true, |
| | "ToLower": true, |
| | "ToLowerSpecial": true, |
| | "ToTitle": true, |
| | "ToTitleSpecial": true, |
| | "ToUpper": true, |
| | "ToUpperSpecial": true, |
| |
|
| | |
| | "Fields": true, |
| | "TrimSpace": true, |
| | } |
| |
|
| | |
| | |
| | |
| | func TestNoUnicodeStrings(t *testing.T) { |
| | testenv.MustHaveSource(t) |
| |
|
| | re := regexp.MustCompile(`(strings|bytes).([A-Za-z]+)`) |
| | if err := fs.WalkDir(os.DirFS("."), ".", func(path string, d fs.DirEntry, err error) error { |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| |
|
| | if path == "internal/ascii" { |
| | return fs.SkipDir |
| | } |
| | if !strings.HasSuffix(path, ".go") || |
| | strings.HasSuffix(path, "_test.go") || |
| | path == "h2_bundle.go" || |
| | path == "internal/httpcommon/httpcommon.go" || |
| | d.IsDir() { |
| | return nil |
| | } |
| |
|
| | contents, err := os.ReadFile(path) |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| | for lineNum, line := range strings.Split(string(contents), "\n") { |
| | for _, match := range re.FindAllStringSubmatch(line, -1) { |
| | if !forbiddenStringsFunctions[match[2]] { |
| | continue |
| | } |
| | t.Errorf("disallowed call to %s at %s:%d", match[0], path, lineNum+1) |
| | } |
| | } |
| |
|
| | return nil |
| | }); err != nil { |
| | t.Fatal(err) |
| | } |
| | } |
| |
|
| | func TestProtocols(t *testing.T) { |
| | var p Protocols |
| | if p.HTTP1() { |
| | t.Errorf("zero-value protocols: p.HTTP1() = true, want false") |
| | } |
| | p.SetHTTP1(true) |
| | p.SetHTTP2(true) |
| | if !p.HTTP1() { |
| | t.Errorf("initialized protocols: p.HTTP1() = false, want true") |
| | } |
| | if !p.HTTP2() { |
| | t.Errorf("initialized protocols: p.HTTP2() = false, want true") |
| | } |
| | p.SetHTTP1(false) |
| | if p.HTTP1() { |
| | t.Errorf("after unsetting HTTP1: p.HTTP1() = true, want false") |
| | } |
| | if !p.HTTP2() { |
| | t.Errorf("after unsetting HTTP1: p.HTTP2() = false, want true") |
| | } |
| | } |
| |
|
| | const redirectURL = "/thisaredirect细雪withasciilettersのけぶabcdefghijk.html" |
| |
|
| | func BenchmarkHexEscapeNonASCII(b *testing.B) { |
| | b.ReportAllocs() |
| |
|
| | for i := 0; i < b.N; i++ { |
| | hexEscapeNonASCII(redirectURL) |
| | } |
| | } |
| |
|