Skip to content

Commit 2c3cc99

Browse files
committed
Merge branch 'chore-add-many-tests-hbyqa' into main
2 parents bda00de + ba08200 commit 2c3cc99

File tree

7 files changed

+1432
-0
lines changed

7 files changed

+1432
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package httpapi
2+
3+
import (
4+
"bytes"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
"time"
9+
10+
mem "network-debugger/internal/adapters/storage/memory"
11+
cfgpkg "network-debugger/internal/infrastructure/config"
12+
obs "network-debugger/internal/infrastructure/observability"
13+
"network-debugger/internal/usecase"
14+
)
15+
16+
func TestHandleConnectTunnel_Success(t *testing.T) {
17+
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
18+
w.WriteHeader(http.StatusOK)
19+
_, _ = w.Write([]byte("ok"))
20+
}))
21+
defer upstream.Close()
22+
23+
store := mem.NewStore(16, 16, 0)
24+
d := &Deps{
25+
Cfg: cfgpkg.Config{PreviewMaxBytes: 512},
26+
Metrics: obs.NewMetrics(),
27+
Monitor: NewMonitorHub(),
28+
Svc: usecase.NewSessionService(store, store, store),
29+
}
30+
31+
rr := &testHijackableWriter{out: &bytes.Buffer{}}
32+
req := httptest.NewRequest(http.MethodConnect, "http://"+upstream.URL[7:], nil)
33+
req.Host = upstream.URL[7:]
34+
35+
d.handleConnectTunnel(rr, req)
36+
37+
if !bytes.Contains(rr.out.Bytes(), []byte("200 Connection Established")) {
38+
t.Fatalf("expected 200 Connection Established")
39+
}
40+
}
41+
42+
func TestHandleConnectTunnel_NoHijack(t *testing.T) {
43+
store := mem.NewStore(16, 16, 0)
44+
d := &Deps{
45+
Cfg: cfgpkg.Config{PreviewMaxBytes: 512},
46+
Metrics: obs.NewMetrics(),
47+
Monitor: NewMonitorHub(),
48+
Svc: usecase.NewSessionService(store, store, store),
49+
}
50+
51+
rr := httptest.NewRecorder()
52+
req := httptest.NewRequest(http.MethodConnect, "http://example.com:443", nil)
53+
54+
d.handleConnectTunnel(rr, req)
55+
56+
if rr.Code != http.StatusInternalServerError {
57+
t.Fatalf("expected 500, got %d", rr.Code)
58+
}
59+
}
60+
61+
func TestHandleConnectTunnel_InvalidHost(t *testing.T) {
62+
store := mem.NewStore(16, 16, 0)
63+
d := &Deps{
64+
Cfg: cfgpkg.Config{PreviewMaxBytes: 512},
65+
Metrics: obs.NewMetrics(),
66+
Monitor: NewMonitorHub(),
67+
Svc: usecase.NewSessionService(store, store, store),
68+
}
69+
70+
rr := &testHijackableWriter{out: &bytes.Buffer{}}
71+
req := httptest.NewRequest(http.MethodConnect, "http://invalid-host:99999", nil)
72+
req.Host = "invalid-host:99999"
73+
74+
d.handleConnectTunnel(rr, req)
75+
76+
if !bytes.Contains(rr.out.Bytes(), []byte("502 Bad Gateway")) {
77+
t.Fatalf("expected 502 error")
78+
}
79+
}
80+
81+
func TestHandleConnectTunnel_UnreachableHost(t *testing.T) {
82+
store := mem.NewStore(16, 16, 0)
83+
d := &Deps{
84+
Cfg: cfgpkg.Config{PreviewMaxBytes: 512},
85+
Metrics: obs.NewMetrics(),
86+
Monitor: NewMonitorHub(),
87+
Svc: usecase.NewSessionService(store, store, store),
88+
}
89+
90+
rr := &testHijackableWriter{out: &bytes.Buffer{}}
91+
req := httptest.NewRequest(http.MethodConnect, "http://127.0.0.1:1", nil)
92+
req.Host = "127.0.0.1:1"
93+
94+
d.handleConnectTunnel(rr, req)
95+
96+
if !bytes.Contains(rr.out.Bytes(), []byte("502 Bad Gateway")) {
97+
t.Fatalf("expected 502 error")
98+
}
99+
}
100+
101+
func TestHandleConnectTunnel_HTTPSHost(t *testing.T) {
102+
upstream := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
103+
w.WriteHeader(http.StatusOK)
104+
}))
105+
defer upstream.Close()
106+
107+
store := mem.NewStore(16, 16, 0)
108+
d := &Deps{
109+
Cfg: cfgpkg.Config{PreviewMaxBytes: 512},
110+
Metrics: obs.NewMetrics(),
111+
Monitor: NewMonitorHub(),
112+
Svc: usecase.NewSessionService(store, store, store),
113+
}
114+
115+
rr := &testHijackableWriter{out: &bytes.Buffer{}}
116+
req := httptest.NewRequest(http.MethodConnect, "https://example.com:443", nil)
117+
req.Host = "example.com:443"
118+
119+
d.handleConnectTunnel(rr, req)
120+
}
121+
122+
func TestHandleConnectTunnel_DataTransfer(t *testing.T) {
123+
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
124+
w.WriteHeader(http.StatusOK)
125+
_, _ = w.Write([]byte("response"))
126+
}))
127+
defer upstream.Close()
128+
129+
store := mem.NewStore(16, 16, 0)
130+
d := &Deps{
131+
Cfg: cfgpkg.Config{PreviewMaxBytes: 512},
132+
Metrics: obs.NewMetrics(),
133+
Monitor: NewMonitorHub(),
134+
Svc: usecase.NewSessionService(store, store, store),
135+
}
136+
137+
rr := &testHijackableWriter{out: &bytes.Buffer{}}
138+
req := httptest.NewRequest(http.MethodConnect, "http://"+upstream.URL[7:], nil)
139+
req.Host = upstream.URL[7:]
140+
141+
go func() {
142+
time.Sleep(100 * time.Millisecond)
143+
}()
144+
145+
d.handleConnectTunnel(rr, req)
146+
147+
if !bytes.Contains(rr.out.Bytes(), []byte("200 Connection Established")) {
148+
t.Fatalf("expected 200 Connection Established")
149+
}
150+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package httpapi
2+
3+
import (
4+
"bytes"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
9+
mem "network-debugger/internal/adapters/storage/memory"
10+
cfgpkg "network-debugger/internal/infrastructure/config"
11+
obs "network-debugger/internal/infrastructure/observability"
12+
"network-debugger/internal/usecase"
13+
)
14+
15+
func TestHandleConnectMITM_CertificateError(t *testing.T) {
16+
certPEM, keyPEM, err := GenerateDevCA("dev", 1)
17+
if err != nil {
18+
t.Fatalf("ca gen: %v", err)
19+
}
20+
ca, err := LoadCertAuthorityFromPEM(certPEM, keyPEM)
21+
if err != nil {
22+
t.Fatalf("load ca: %v", err)
23+
}
24+
25+
store := mem.NewStore(16, 16, 0)
26+
d := &Deps{
27+
MITM: &MITM{CA: ca},
28+
Cfg: cfgpkg.Config{PreviewMaxBytes: 512},
29+
Metrics: obs.NewMetrics(),
30+
Monitor: NewMonitorHub(),
31+
Svc: usecase.NewSessionService(store, store, store),
32+
}
33+
34+
rr := &testHijackableWriter{out: &bytes.Buffer{}}
35+
req := httptest.NewRequest(http.MethodConnect, "http://invalid-host:443", nil)
36+
req.Host = "invalid-host:443"
37+
38+
d.handleConnectMITM(rr, req)
39+
}
40+
41+
func TestHandleConnectMITM_UpstreamDialError(t *testing.T) {
42+
certPEM, keyPEM, err := GenerateDevCA("dev", 1)
43+
if err != nil {
44+
t.Fatalf("ca gen: %v", err)
45+
}
46+
ca, err := LoadCertAuthorityFromPEM(certPEM, keyPEM)
47+
if err != nil {
48+
t.Fatalf("load ca: %v", err)
49+
}
50+
51+
store := mem.NewStore(16, 16, 0)
52+
d := &Deps{
53+
MITM: &MITM{CA: ca},
54+
Cfg: cfgpkg.Config{PreviewMaxBytes: 512},
55+
Metrics: obs.NewMetrics(),
56+
Monitor: NewMonitorHub(),
57+
Svc: usecase.NewSessionService(store, store, store),
58+
}
59+
60+
rr := &testHijackableWriter{out: &bytes.Buffer{}}
61+
req := httptest.NewRequest(http.MethodConnect, "http://127.0.0.1:1", nil)
62+
req.Host = "127.0.0.1:1"
63+
64+
d.handleConnectMITM(rr, req)
65+
}
66+
67+
func TestHandleConnectMITM_ShouldIntercept(t *testing.T) {
68+
certPEM, keyPEM, err := GenerateDevCA("dev", 1)
69+
if err != nil {
70+
t.Fatalf("ca gen: %v", err)
71+
}
72+
ca, err := LoadCertAuthorityFromPEM(certPEM, keyPEM)
73+
if err != nil {
74+
t.Fatalf("load ca: %v", err)
75+
}
76+
77+
mitm := &MITM{CA: ca, AllowSuffix: []string{"example.com"}}
78+
79+
store := mem.NewStore(16, 16, 0)
80+
d := &Deps{
81+
MITM: mitm,
82+
Cfg: cfgpkg.Config{PreviewMaxBytes: 512},
83+
Metrics: obs.NewMetrics(),
84+
Monitor: NewMonitorHub(),
85+
Svc: usecase.NewSessionService(store, store, store),
86+
}
87+
88+
rr := &testHijackableWriter{out: &bytes.Buffer{}}
89+
req := httptest.NewRequest(http.MethodConnect, "http://example.com:443", nil)
90+
req.Host = "example.com:443"
91+
92+
d.handleConnectMITM(rr, req)
93+
}
94+
95+
func TestHandleConnectMITM_ShouldNotIntercept(t *testing.T) {
96+
certPEM, keyPEM, err := GenerateDevCA("dev", 1)
97+
if err != nil {
98+
t.Fatalf("ca gen: %v", err)
99+
}
100+
ca, err := LoadCertAuthorityFromPEM(certPEM, keyPEM)
101+
if err != nil {
102+
t.Fatalf("load ca: %v", err)
103+
}
104+
105+
mitm := &MITM{CA: ca, AllowSuffix: []string{"example.com"}}
106+
107+
store := mem.NewStore(16, 16, 0)
108+
d := &Deps{
109+
MITM: mitm,
110+
Cfg: cfgpkg.Config{PreviewMaxBytes: 512},
111+
Metrics: obs.NewMetrics(),
112+
Monitor: NewMonitorHub(),
113+
Svc: usecase.NewSessionService(store, store, store),
114+
}
115+
116+
rr := &testHijackableWriter{out: &bytes.Buffer{}}
117+
req := httptest.NewRequest(http.MethodConnect, "http://other.com:443", nil)
118+
req.Host = "other.com:443"
119+
120+
d.handleConnectMITM(rr, req)
121+
}

0 commit comments

Comments
 (0)