Skip to content

Commit bebb2ee

Browse files
authored
test: add comprehensive tests for HTTP header parsing and transport (#236)
* test: add comprehensive tests for HTTP header parsing and transport - Add tests for parsing header strings into http.Header, covering normal input, invalid format, duplicate keys, and empty/nil input - Add tests for DefaultHeaderTransport to verify attaching custom headers, handling empty app info, propagating errors, and supporting multiple header values Signed-off-by: appleboy <[email protected]> * test: improve HTTP test robustness and resource management - Use NewRequestWithContext with a background context in tests instead of NewRequest - Add error handling and fail tests immediately if RoundTrip returns an error - Ensure HTTP response bodies are closed after each test to prevent resource leaks Signed-off-by: appleboy <[email protected]> --------- Signed-off-by: appleboy <[email protected]>
1 parent c4d6669 commit bebb2ee

File tree

2 files changed

+183
-0
lines changed

2 files changed

+183
-0
lines changed

core/transport/headers_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package transport
2+
3+
import (
4+
"net/http"
5+
"reflect"
6+
"testing"
7+
)
8+
9+
func TestNewHeaders_NormalInput(t *testing.T) {
10+
input := []string{"Content-Type=application/json", "Accept=*/*"}
11+
want := http.Header{
12+
"Content-Type": {"application/json"},
13+
"Accept": {"*/*"},
14+
}
15+
got := NewHeaders(input)
16+
if !reflect.DeepEqual(got, want) {
17+
t.Errorf("NewHeaders() = %v, want %v", got, want)
18+
}
19+
}
20+
21+
func TestNewHeaders_InvalidFormat(t *testing.T) {
22+
input := []string{"invalid-header", "AnotherOne"}
23+
want := http.Header{}
24+
got := NewHeaders(input)
25+
if !reflect.DeepEqual(got, want) {
26+
t.Errorf("NewHeaders() = %v, want %v", got, want)
27+
}
28+
}
29+
30+
func TestNewHeaders_DuplicateKeys(t *testing.T) {
31+
input := []string{"X-Test=1", "X-Test=2"}
32+
want := http.Header{
33+
"X-Test": {"1", "2"},
34+
}
35+
got := NewHeaders(input)
36+
if !reflect.DeepEqual(got, want) {
37+
t.Errorf("NewHeaders() = %v, want %v", got, want)
38+
}
39+
}
40+
41+
func TestNewHeaders_EmptyOrNilInput(t *testing.T) {
42+
var inputNil []string
43+
inputEmpty := []string{}
44+
want := http.Header{}
45+
46+
gotNil := NewHeaders(inputNil)
47+
if !reflect.DeepEqual(gotNil, want) {
48+
t.Errorf("NewHeaders(nil) = %v, want %v", gotNil, want)
49+
}
50+
51+
gotEmpty := NewHeaders(inputEmpty)
52+
if !reflect.DeepEqual(gotEmpty, want) {
53+
t.Errorf("NewHeaders(empty) = %v, want %v", gotEmpty, want)
54+
}
55+
}

core/transport/transport_test.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package transport
2+
3+
import (
4+
"context"
5+
"errors"
6+
"net/http"
7+
"reflect"
8+
"testing"
9+
)
10+
11+
// mockRoundTripper is used to intercept requests and record headers
12+
type mockRoundTripper struct {
13+
lastReq *http.Request
14+
resp *http.Response
15+
err error
16+
}
17+
18+
func (m *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
19+
m.lastReq = req
20+
if m.resp != nil || m.err != nil {
21+
return m.resp, m.err
22+
}
23+
return &http.Response{StatusCode: 200, Body: http.NoBody, Request: req}, nil
24+
}
25+
26+
func TestDefaultHeaderTransport_CustomHeaders(t *testing.T) {
27+
mock := &mockRoundTripper{}
28+
tr := &DefaultHeaderTransport{
29+
Origin: mock,
30+
Header: http.Header{
31+
"X-Test": {"abc"},
32+
"Foo": {"bar"},
33+
},
34+
AppName: "myapp",
35+
AppVersion: "1.2.3",
36+
}
37+
req, _ := http.NewRequestWithContext(context.Background(), "GET", "http://example.com", nil)
38+
resp, err := tr.RoundTrip(req)
39+
if err != nil {
40+
t.Fatalf("RoundTrip error: %v", err)
41+
}
42+
if resp != nil && resp.Body != nil {
43+
resp.Body.Close()
44+
}
45+
46+
want := http.Header{
47+
"X-Test": {"abc"},
48+
"Foo": {"bar"},
49+
"X-App-Name": {"myapp"},
50+
"X-App-Version": {"1.2.3"},
51+
}
52+
for k, v := range want {
53+
got := req.Header.Values(k)
54+
if !reflect.DeepEqual(got, v) {
55+
t.Errorf("Header %q = %v, want %v", k, got, v)
56+
}
57+
}
58+
}
59+
60+
func TestDefaultHeaderTransport_EmptyHeadersAndAppInfo(t *testing.T) {
61+
mock := &mockRoundTripper{}
62+
tr := &DefaultHeaderTransport{
63+
Origin: mock,
64+
Header: http.Header{},
65+
AppName: "",
66+
AppVersion: "",
67+
}
68+
req, _ := http.NewRequestWithContext(context.Background(), "GET", "http://example.com", nil)
69+
resp, err := tr.RoundTrip(req)
70+
if err != nil {
71+
t.Fatalf("RoundTrip error: %v", err)
72+
}
73+
if resp != nil && resp.Body != nil {
74+
resp.Body.Close()
75+
}
76+
77+
// x-app-name/version should not be present
78+
if req.Header.Get("x-app-name") != "" {
79+
t.Errorf("x-app-name should be empty")
80+
}
81+
if req.Header.Get("x-app-version") != "" {
82+
t.Errorf("x-app-version should be empty")
83+
}
84+
}
85+
86+
func TestDefaultHeaderTransport_OriginErrorPropagation(t *testing.T) {
87+
mock := &mockRoundTripper{err: errors.New("mock error")}
88+
tr := &DefaultHeaderTransport{
89+
Origin: mock,
90+
Header: http.Header{},
91+
AppName: "",
92+
AppVersion: "",
93+
}
94+
req, _ := http.NewRequestWithContext(context.Background(), "GET", "http://example.com", nil)
95+
resp, err := tr.RoundTrip(req)
96+
if resp != nil && resp.Body != nil {
97+
resp.Body.Close()
98+
}
99+
if err == nil || err.Error() != "mock error" {
100+
t.Errorf("Expected error 'mock error', got %v", err)
101+
}
102+
}
103+
104+
func TestDefaultHeaderTransport_MultipleHeaderValues(t *testing.T) {
105+
mock := &mockRoundTripper{}
106+
tr := &DefaultHeaderTransport{
107+
Origin: mock,
108+
Header: http.Header{
109+
"X-Multi": {"a", "b"},
110+
},
111+
AppName: "app",
112+
AppVersion: "v",
113+
}
114+
req, _ := http.NewRequestWithContext(context.Background(), "GET", "http://example.com", nil)
115+
resp, err := tr.RoundTrip(req)
116+
if err != nil {
117+
t.Fatalf("RoundTrip error: %v", err)
118+
}
119+
if resp != nil && resp.Body != nil {
120+
resp.Body.Close()
121+
}
122+
123+
got := req.Header.Values("X-Multi")
124+
want := []string{"a", "b"}
125+
if !reflect.DeepEqual(got, want) {
126+
t.Errorf("X-Multi header = %v, want %v", got, want)
127+
}
128+
}

0 commit comments

Comments
 (0)