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  }