@@ -7,8 +7,9 @@ package proxy
77import (
88 "context"
99 "errors"
10+ "fmt"
1011 "net"
11- "reflect "
12+ "slices "
1213 "testing"
1314)
1415
@@ -22,55 +23,118 @@ func (r *recordingProxy) Dial(network, addr string) (net.Conn, error) {
2223}
2324
2425func TestPerHost (t * testing.T ) {
25- expectedDef := []string {
26- "example.com:123" ,
27- "1.2.3.4:123" ,
28- "[1001::]:123" ,
29- }
30- expectedBypass := []string {
31- "localhost:123" ,
32- "zone:123" ,
33- "foo.zone:123" ,
34- "127.0.0.1:123" ,
35- "10.1.2.3:123" ,
36- "[1000::]:123" ,
37- }
38-
39- t .Run ("Dial" , func (t * testing.T ) {
40- var def , bypass recordingProxy
41- perHost := NewPerHost (& def , & bypass )
42- perHost .AddFromString ("localhost,*.zone,127.0.0.1,10.0.0.1/8,1000::/16" )
43- for _ , addr := range expectedDef {
44- perHost .Dial ("tcp" , addr )
26+ for _ , test := range []struct {
27+ config string // passed to PerHost.AddFromString
28+ nomatch []string // addrs using the default dialer
29+ match []string // addrs using the bypass dialer
30+ }{{
31+ config : "localhost,*.zone,127.0.0.1,10.0.0.1/8,1000::/16" ,
32+ nomatch : []string {
33+ "example.com:123" ,
34+ "1.2.3.4:123" ,
35+ "[1001::]:123" ,
36+ },
37+ match : []string {
38+ "localhost:123" ,
39+ "zone:123" ,
40+ "foo.zone:123" ,
41+ "127.0.0.1:123" ,
42+ "10.1.2.3:123" ,
43+ "[1000::]:123" ,
44+ "[1000::%25.example.com]:123" ,
45+ },
46+ }, {
47+ config : "localhost" ,
48+ nomatch : []string {
49+ "127.0.0.1:80" ,
50+ },
51+ match : []string {
52+ "localhost:80" ,
53+ },
54+ }, {
55+ config : "*.zone" ,
56+ nomatch : []string {
57+ "foo.com:80" ,
58+ },
59+ match : []string {
60+ "foo.zone:80" ,
61+ "foo.bar.zone:80" ,
62+ },
63+ }, {
64+ config : "1.2.3.4" ,
65+ nomatch : []string {
66+ "127.0.0.1:80" ,
67+ "11.2.3.4:80" ,
68+ },
69+ match : []string {
70+ "1.2.3.4:80" ,
71+ },
72+ }, {
73+ config : "10.0.0.0/24" ,
74+ nomatch : []string {
75+ "10.0.1.1:80" ,
76+ },
77+ match : []string {
78+ "10.0.0.1:80" ,
79+ "10.0.0.255:80" ,
80+ },
81+ }, {
82+ config : "fe80::/10" ,
83+ nomatch : []string {
84+ "[fec0::1]:80" ,
85+ "[fec0::1%en0]:80" ,
86+ },
87+ match : []string {
88+ "[fe80::1]:80" ,
89+ "[fe80::1%en0]:80" ,
90+ },
91+ }, {
92+ // We don't allow zone IDs in network prefixes,
93+ // so this config matches nothing.
94+ config : "fe80::%en0/10" ,
95+ nomatch : []string {
96+ "[fec0::1]:80" ,
97+ "[fec0::1%en0]:80" ,
98+ "[fe80::1]:80" ,
99+ "[fe80::1%en0]:80" ,
100+ "[fe80::1%en1]:80" ,
101+ },
102+ }} {
103+ for _ , addr := range test .match {
104+ testPerHost (t , test .config , addr , true )
45105 }
46- for _ , addr := range expectedBypass {
47- perHost . Dial ( "tcp" , addr )
106+ for _ , addr := range test . nomatch {
107+ testPerHost ( t , test . config , addr , false )
48108 }
109+ }
110+ }
49111
50- if ! reflect .DeepEqual (expectedDef , def .addrs ) {
51- t .Errorf ("Hosts which went to the default proxy didn't match. Got %v, want %v" , def .addrs , expectedDef )
52- }
53- if ! reflect .DeepEqual (expectedBypass , bypass .addrs ) {
54- t .Errorf ("Hosts which went to the bypass proxy didn't match. Got %v, want %v" , bypass .addrs , expectedBypass )
55- }
56- })
112+ func testPerHost (t * testing.T , config , addr string , wantMatch bool ) {
113+ name := fmt .Sprintf ("config %q, dial %q" , config , addr )
57114
58- t .Run ("DialContext" , func (t * testing.T ) {
59- var def , bypass recordingProxy
60- perHost := NewPerHost (& def , & bypass )
61- perHost .AddFromString ("localhost,*.zone,127.0.0.1,10.0.0.1/8,1000::/16" )
62- for _ , addr := range expectedDef {
63- perHost .DialContext (context .Background (), "tcp" , addr )
64- }
65- for _ , addr := range expectedBypass {
66- perHost .DialContext (context .Background (), "tcp" , addr )
67- }
115+ var def , bypass recordingProxy
116+ perHost := NewPerHost (& def , & bypass )
117+ perHost .AddFromString (config )
118+ perHost .Dial ("tcp" , addr )
68119
69- if ! reflect .DeepEqual (expectedDef , def .addrs ) {
70- t .Errorf ("Hosts which went to the default proxy didn't match. Got %v, want %v" , def .addrs , expectedDef )
71- }
72- if ! reflect .DeepEqual (expectedBypass , bypass .addrs ) {
73- t .Errorf ("Hosts which went to the bypass proxy didn't match. Got %v, want %v" , bypass .addrs , expectedBypass )
74- }
75- })
120+ // Dial and DialContext should have the same results.
121+ var defc , bypassc recordingProxy
122+ perHostc := NewPerHost (& defc , & bypassc )
123+ perHostc .AddFromString (config )
124+ perHostc .DialContext (context .Background (), "tcp" , addr )
125+ if ! slices .Equal (def .addrs , defc .addrs ) {
126+ t .Errorf ("%v: Dial default=%v, bypass=%v; DialContext default=%v, bypass=%v" , name , def .addrs , bypass .addrs , defc .addrs , bypass .addrs )
127+ return
128+ }
129+
130+ if got , want := slices .Concat (def .addrs , bypass .addrs ), []string {addr }; ! slices .Equal (got , want ) {
131+ t .Errorf ("%v: dialed %q, want %q" , name , got , want )
132+ return
133+ }
134+
135+ gotMatch := len (bypass .addrs ) > 0
136+ if gotMatch != wantMatch {
137+ t .Errorf ("%v: matched=%v, want %v" , name , gotMatch , wantMatch )
138+ return
139+ }
76140}
0 commit comments