test(http): cover transport isolation, TLS clone, and must-style panic
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
oesni committed
May 4, 2026 at 14:28 UTC
385463c5ef05b96f24463a6d5efc37d2d9aef53d
1 file changed
+83
utils/http_test.go
new
+83
@@ -0,0 +1,83 @@
1
+package utils
2
+
3
+import (
4
+ "crypto/tls"
5
+ "net/http"
6
+ "testing"
7
+)
8
+
9
+func TestNewHTTPClientTransportIsolation(t *testing.T) {
10
+ t.Parallel()
11
+
12
+ a := NewHTTPClient()
13
+ b := NewHTTPClient()
14
+
15
+ ta := mustTransportOf(a)
16
+ tb := mustTransportOf(b)
17
+
18
+ if ta == tb {
19
+ t.Fatalf("NewHTTPClient() returned clients sharing the same *http.Transport")
20
+ }
21
+ if ta == baseTransport {
22
+ t.Fatalf("NewHTTPClient() transport aliases baseTransport; mutations would leak across all clients")
23
+ }
24
+ if ta == mustTransportOf(DefaultHTTPClient) {
25
+ t.Fatalf("NewHTTPClient() transport aliases DefaultHTTPClient's transport")
26
+ }
27
+
28
+ // Mutating one client's transport must not affect the other.
29
+ ta.MaxIdleConns = 7
30
+ if tb.MaxIdleConns == 7 {
31
+ t.Fatalf("mutation on client A leaked into client B (MaxIdleConns)")
32
+ }
33
+}
34
+
35
+func TestWithHTTPTLSConfigClonesInput(t *testing.T) {
36
+ t.Parallel()
37
+
38
+ original := &tls.Config{ServerName: "before", InsecureSkipVerify: false}
39
+ c := NewHTTPClient(WithHTTPTLSConfig(original))
40
+
41
+ // Mutate the caller's config after the option was applied; the transport
42
+ // must not observe the change because WithHTTPTLSConfig clones the input.
43
+ original.ServerName = "after"
44
+ original.InsecureSkipVerify = true
45
+
46
+ got := mustTransportOf(c).TLSClientConfig
47
+ if got == original {
48
+ t.Fatalf("WithHTTPTLSConfig stored the caller's *tls.Config by reference")
49
+ }
50
+ if got.ServerName != "before" || got.InsecureSkipVerify {
51
+ t.Fatalf("WithHTTPTLSConfig did not clone tls.Config: got %+v", got)
52
+ }
53
+}
54
+
55
+func TestWithHTTPTLSConfigNilClearsTransportConfig(t *testing.T) {
56
+ t.Parallel()
57
+
58
+ c := NewHTTPClient(WithHTTPTLSConfig(&tls.Config{ServerName: "x"}))
59
+ WithHTTPTLSConfig(nil)(c)
60
+
61
+ if mustTransportOf(c).TLSClientConfig != nil {
62
+ t.Fatalf("WithHTTPTLSConfig(nil) did not clear TLSClientConfig")
63
+ }
64
+}
65
+
66
+func TestMustTransportOfPanicsOnForeignTransport(t *testing.T) {
67
+ t.Parallel()
68
+
69
+ defer func() {
70
+ if r := recover(); r == nil {
71
+ t.Fatalf("mustTransportOf did not panic on non-*http.Transport RoundTripper")
72
+ }
73
+ }()
74
+
75
+ c := &http.Client{Transport: roundTripperFunc(func(*http.Request) (*http.Response, error) {
76
+ return nil, nil
77
+ })}
78
+ _ = mustTransportOf(c)
79
+}
80
+
81
+type roundTripperFunc func(*http.Request) (*http.Response, error)
82
+
83
+func (f roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) }