package httpc import ( "context" "io" "net/http" "net/http/httptest" "strings" "testing" ) type benchmarkTransport struct { payload string status int } func (t benchmarkTransport) RoundTrip(r *http.Request) (*http.Response, error) { if r.Body != nil { _ = r.Body.Close() } return &http.Response{StatusCode: t.status, Header: make(http.Header), Body: io.NopCloser(strings.NewReader(t.payload)), ContentLength: int64(len(t.payload)), Request: r}, nil } func BenchmarkHTTPClient(b *testing.B) { for _, size := range []int{128, 4096, 65536} { for _, discard := range []bool{false, true} { label := map[int]string{128: "128B", 4096: "4KiB", 65536: "64KiB"}[size] if discard { label += "/discard" } else { label += "/decode" } b.Run(label, func(b *testing.B) { c, err := New(Config{Transport: benchmarkTransport{`{"value":"` + strings.Repeat("x", size) + `"}`, 200}, DisableLogging: true}) if err != nil { b.Fatal(err) } defer c.Close() var output struct { Value string `json:"value"` } var target any = &output if discard { target = nil } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { if err := c.JSON(context.Background(), "GET", "http://example.invalid/item", nil, target); err != nil { b.Fatal(err) } } }) } } b.Run("Do", func(b *testing.B) { c, _ := New(Config{Transport: benchmarkTransport{"", 200}, DisableLogging: true}) defer c.Close() r, _ := http.NewRequest("GET", "http://example.invalid/item", nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { res, err := c.Do(r) if err != nil { b.Fatal(err) } res.Body.Close() } }) } func BenchmarkHTTPPool(b *testing.B) { for _, status := range []int{200, 401} { b.Run(http.StatusText(status), func(b *testing.B) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(status); io.WriteString(w, `{"ok":true}`) })) defer s.Close() c, _ := New(Config{DisableLogging: true}) defer c.Close() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { err := c.JSON(context.Background(), "GET", s.URL, nil, nil) if status == 200 && err != nil { b.Fatal(err) } } }) } } func BenchmarkHTTPHeaders(b *testing.B) { c, _ := New(Config{Transport: benchmarkTransport{`{"ok":true}`, 200}, DisableLogging: true}) defer c.Close() option := WithHeaders(http.Header{"Authorization": []string{"Bearer example"}, "X-Request-Id": []string{"example-request"}}) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { if err := c.JSON(context.Background(), "GET", "http://example.invalid", nil, nil, option); err != nil { b.Fatal(err) } } }