github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/requests/dialer_swarm_test.go (about) 1 /* 2 * Copyright (C) 2020 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package requests 19 20 import ( 21 "context" 22 "net" 23 "sync" 24 "testing" 25 "time" 26 27 "github.com/stretchr/testify/assert" 28 29 "github.com/mysteriumnetwork/node/requests/resolver" 30 ) 31 32 func Test_DialerSwarm_UsesDefaultResolver(t *testing.T) { 33 // given 34 ln, err := net.Listen("tcp", "127.0.0.1:0") 35 if err != nil { 36 t.Fatal(err) 37 } 38 defer ln.Close() 39 40 // when 41 dialer := NewDialerSwarm("127.0.0.1", 0) 42 conn, err := dialer.DialContext(context.Background(), ln.Addr().Network(), ln.Addr().String()) 43 44 // then 45 assert.NotNil(t, conn) 46 assert.NoError(t, err) 47 } 48 49 func Test_DialerSwarm_CustomResolverSuccessfully(t *testing.T) { 50 // given 51 ln, err := net.Listen("tcp", "127.0.0.1:12345") 52 if err != nil { 53 t.Fatal(err) 54 } 55 defer ln.Close() 56 57 dialer := NewDialerSwarm("127.0.0.1", 0) 58 dialer.ResolveContext = resolver.NewResolverMap(map[string][]string{ 59 "dns-is-faked.golang": {"127.0.0.1", "2001:db8::a3"}, 60 }) 61 62 // when 63 conn, err := dialer.DialContext(context.Background(), "tcp", "dns-is-faked.golang:12345") 64 65 // then 66 assert.NotNil(t, conn) 67 assert.NoError(t, err) 68 } 69 70 func Test_DialerSwarm_CustomResolverWithSomeUnreachableIPs(t *testing.T) { 71 // given 72 ln, err := net.Listen("tcp", "127.0.0.1:12345") 73 if err != nil { 74 t.Fatal(err) 75 } 76 defer ln.Close() 77 78 dialer := NewDialerSwarm("127.0.0.1", 0) 79 dialer.ResolveContext = resolver.NewResolverMap(map[string][]string{ 80 "dns-is-faked.golang": {"2001:db8::a3", "127.0.0.1"}, 81 }) 82 83 // when 84 conn, err := dialer.DialContext(context.Background(), "tcp", "dns-is-faked.golang:12345") 85 86 // then 87 assert.NotNil(t, conn) 88 assert.NoError(t, err) 89 } 90 91 func Test_DialerSwarm_CustomResolverWithAllUnreachableIPs(t *testing.T) { 92 dialer := NewDialerSwarm("127.0.0.1", 0) 93 dialer.ResolveContext = resolver.NewResolverMap(map[string][]string{ 94 "dns-is-faked.golang": {"2001:db8::a1", "2001:db8::a3"}, 95 }) 96 97 // when 98 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 99 defer cancel() 100 conn, err := dialer.DialContext(ctx, "tcp", "dns-is-faked.golang:12345") 101 102 // then 103 assert.Nil(t, conn) 104 assert.Error(t, err) 105 106 if dialErr, ok := err.(*ErrorSwarmDial); ok { 107 assert.Equal(t, "dns-is-faked.golang:12345", dialErr.OriginalAddr) 108 assert.Equal(t, ErrAllDialsFailed, dialErr.Cause) 109 assert.Len(t, dialErr.DialErrors, 3) 110 } else { 111 assert.Failf(t, "expected to fail with ErrorSwarmDial", "but got: %v", err) 112 } 113 } 114 115 func Test_DialerSwarm_CustomDialingIsCancelable(t *testing.T) { 116 // configure lagging dialer 117 dialer := NewDialerSwarm("127.0.0.1", 0) 118 dialer.ResolveContext = resolver.NewResolverMap(map[string][]string{}) 119 dialer.Dialer = func(ctx context.Context, _, _ string) (net.Conn, error) { 120 select { 121 case <-ctx.Done(): 122 return nil, ctx.Err() 123 case <-time.After(time.Second): 124 return nil, nil 125 } 126 } 127 128 // when 129 ctx, cancel := context.WithCancel(context.Background()) 130 131 wg := sync.WaitGroup{} 132 wg.Add(1) 133 134 go func() { 135 time.Sleep(1 * time.Millisecond) 136 cancel() 137 wg.Done() 138 }() 139 140 conn, err := dialer.DialContext(ctx, "tcp", "dns-is-faked.golang:12345") 141 142 // then 143 assert.Nil(t, conn) 144 assert.Error(t, err) 145 146 if dialErr, ok := err.(*ErrorSwarmDial); ok { 147 assert.Equal(t, "dns-is-faked.golang:12345", dialErr.OriginalAddr) 148 assert.Equal(t, context.Canceled, dialErr.Cause) 149 } else { 150 assert.Failf(t, "expected to fail with ErrorSwarmDial", "but got: %v", err) 151 } 152 153 wg.Wait() 154 } 155 156 func Test_DialerSwarm_CustomResolvingIsCancelable(t *testing.T) { 157 // configure lagging dialer 158 dialer := NewDialerSwarm("127.0.0.1", 0) 159 dialer.ResolveContext = func(ctx context.Context, _, _ string) ([]string, error) { 160 select { 161 case <-ctx.Done(): 162 return nil, ctx.Err() 163 case <-time.After(time.Second): 164 return nil, nil 165 } 166 } 167 168 // when 169 ctx, cancel := context.WithCancel(context.Background()) 170 171 wg := sync.WaitGroup{} 172 wg.Add(1) 173 174 go func() { 175 time.Sleep(4 * time.Millisecond) 176 cancel() 177 wg.Done() 178 }() 179 180 conn, err := dialer.DialContext(ctx, "tcp", "dns-is-faked.golang:12345") 181 182 // then 183 assert.Nil(t, conn) 184 assert.Equal(t, &net.OpError{Op: "dial", Net: "tcp", Source: nil, Addr: nil, Err: context.Canceled}, err) 185 186 wg.Wait() 187 } 188 189 func Test_isIP(t *testing.T) { 190 type args struct { 191 addr string 192 } 193 tests := []struct { 194 name string 195 args args 196 want bool 197 }{ 198 { 199 name: "detects ipv4 correctly", 200 args: args{ 201 addr: "95.216.204.232:443", 202 }, 203 want: true, 204 }, 205 { 206 name: "detects ipv6 correctly", 207 args: args{ 208 addr: "[2001:db8::1]:8080", 209 }, 210 want: true, 211 }, 212 { 213 name: "detects ipv4 with no port correctly", 214 args: args{ 215 addr: "95.216.204.232", 216 }, 217 want: true, 218 }, 219 { 220 name: "detects ipv6 with no port correctly", 221 args: args{ 222 addr: "::1", 223 }, 224 want: true, 225 }, 226 { 227 name: "detects url correctly", 228 args: args{ 229 addr: "testnet3-location.mysterium.network:443", 230 }, 231 want: false, 232 }, 233 { 234 name: "detects url with no port correctly", 235 args: args{ 236 addr: "testnet3-location.mysterium.network", 237 }, 238 want: false, 239 }, 240 } 241 for _, tt := range tests { 242 t.Run(tt.name, func(t *testing.T) { 243 if got := isIP(tt.args.addr); got != tt.want { 244 t.Errorf("isIP() = %v, want %v", got, tt.want) 245 } 246 }) 247 } 248 }