go.etcd.io/etcd@v3.3.27+incompatible/pkg/netutil/netutil_test.go (about)

     1  // Copyright 2015 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package netutil
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"net"
    21  	"net/url"
    22  	"reflect"
    23  	"strconv"
    24  	"testing"
    25  	"time"
    26  )
    27  
    28  func TestResolveTCPAddrs(t *testing.T) {
    29  	defer func() { resolveTCPAddr = resolveTCPAddrDefault }()
    30  	tests := []struct {
    31  		urls     [][]url.URL
    32  		expected [][]url.URL
    33  		hostMap  map[string]string
    34  		hasError bool
    35  	}{
    36  		{
    37  			urls: [][]url.URL{
    38  				{
    39  					{Scheme: "http", Host: "127.0.0.1:4001"},
    40  					{Scheme: "http", Host: "127.0.0.1:2379"},
    41  				},
    42  				{
    43  					{Scheme: "http", Host: "127.0.0.1:7001"},
    44  					{Scheme: "http", Host: "127.0.0.1:2380"},
    45  				},
    46  			},
    47  			expected: [][]url.URL{
    48  				{
    49  					{Scheme: "http", Host: "127.0.0.1:4001"},
    50  					{Scheme: "http", Host: "127.0.0.1:2379"},
    51  				},
    52  				{
    53  					{Scheme: "http", Host: "127.0.0.1:7001"},
    54  					{Scheme: "http", Host: "127.0.0.1:2380"},
    55  				},
    56  			},
    57  		},
    58  		{
    59  			urls: [][]url.URL{
    60  				{
    61  					{Scheme: "http", Host: "infra0.example.com:4001"},
    62  					{Scheme: "http", Host: "infra0.example.com:2379"},
    63  				},
    64  				{
    65  					{Scheme: "http", Host: "infra0.example.com:7001"},
    66  					{Scheme: "http", Host: "infra0.example.com:2380"},
    67  				},
    68  			},
    69  			expected: [][]url.URL{
    70  				{
    71  					{Scheme: "http", Host: "10.0.1.10:4001"},
    72  					{Scheme: "http", Host: "10.0.1.10:2379"},
    73  				},
    74  				{
    75  					{Scheme: "http", Host: "10.0.1.10:7001"},
    76  					{Scheme: "http", Host: "10.0.1.10:2380"},
    77  				},
    78  			},
    79  			hostMap: map[string]string{
    80  				"infra0.example.com": "10.0.1.10",
    81  			},
    82  			hasError: false,
    83  		},
    84  		{
    85  			urls: [][]url.URL{
    86  				{
    87  					{Scheme: "http", Host: "infra0.example.com:4001"},
    88  					{Scheme: "http", Host: "infra0.example.com:2379"},
    89  				},
    90  				{
    91  					{Scheme: "http", Host: "infra0.example.com:7001"},
    92  					{Scheme: "http", Host: "infra0.example.com:2380"},
    93  				},
    94  			},
    95  			hostMap: map[string]string{
    96  				"infra0.example.com": "",
    97  			},
    98  			hasError: true,
    99  		},
   100  		{
   101  			urls: [][]url.URL{
   102  				{
   103  					{Scheme: "http", Host: "ssh://infra0.example.com:4001"},
   104  					{Scheme: "http", Host: "ssh://infra0.example.com:2379"},
   105  				},
   106  				{
   107  					{Scheme: "http", Host: "ssh://infra0.example.com:7001"},
   108  					{Scheme: "http", Host: "ssh://infra0.example.com:2380"},
   109  				},
   110  			},
   111  			hasError: true,
   112  		},
   113  	}
   114  	for _, tt := range tests {
   115  		resolveTCPAddr = func(ctx context.Context, addr string) (*net.TCPAddr, error) {
   116  			host, port, err := net.SplitHostPort(addr)
   117  			if err != nil {
   118  				return nil, err
   119  			}
   120  			if tt.hostMap[host] == "" {
   121  				return nil, errors.New("cannot resolve host.")
   122  			}
   123  			i, err := strconv.Atoi(port)
   124  			if err != nil {
   125  				return nil, err
   126  			}
   127  			return &net.TCPAddr{IP: net.ParseIP(tt.hostMap[host]), Port: i, Zone: ""}, nil
   128  		}
   129  		ctx, cancel := context.WithTimeout(context.TODO(), time.Second)
   130  		urls, err := resolveTCPAddrs(ctx, tt.urls)
   131  		cancel()
   132  		if tt.hasError {
   133  			if err == nil {
   134  				t.Errorf("expected error")
   135  			}
   136  			continue
   137  		}
   138  		if !reflect.DeepEqual(urls, tt.expected) {
   139  			t.Errorf("expected: %v, got %v", tt.expected, urls)
   140  		}
   141  	}
   142  }
   143  
   144  func TestURLsEqual(t *testing.T) {
   145  	defer func() { resolveTCPAddr = resolveTCPAddrDefault }()
   146  	hostm := map[string]string{
   147  		"example.com": "10.0.10.1",
   148  		"first.com":   "10.0.11.1",
   149  		"second.com":  "10.0.11.2",
   150  	}
   151  	resolveTCPAddr = func(ctx context.Context, addr string) (*net.TCPAddr, error) {
   152  		host, port, herr := net.SplitHostPort(addr)
   153  		if herr != nil {
   154  			return nil, herr
   155  		}
   156  		if _, ok := hostm[host]; !ok {
   157  			return nil, errors.New("cannot resolve host.")
   158  		}
   159  		i, err := strconv.Atoi(port)
   160  		if err != nil {
   161  			return nil, err
   162  		}
   163  		return &net.TCPAddr{IP: net.ParseIP(hostm[host]), Port: i, Zone: ""}, nil
   164  	}
   165  
   166  	tests := []struct {
   167  		a      []url.URL
   168  		b      []url.URL
   169  		expect bool
   170  		err    error
   171  	}{
   172  		{
   173  			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2379"}},
   174  			b:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2379"}},
   175  			expect: true,
   176  		},
   177  		{
   178  			a:      []url.URL{{Scheme: "http", Host: "example.com:2379"}},
   179  			b:      []url.URL{{Scheme: "http", Host: "10.0.10.1:2379"}},
   180  			expect: true,
   181  		},
   182  		{
   183  			a:      []url.URL{{Scheme: "http", Host: "example.com:2379"}},
   184  			b:      []url.URL{{Scheme: "https", Host: "10.0.10.1:2379"}},
   185  			expect: false,
   186  			err:    errors.New(`"http://10.0.10.1:2379"(resolved from "http://example.com:2379") != "https://10.0.10.1:2379"(resolved from "https://10.0.10.1:2379")`),
   187  		},
   188  		{
   189  			a:      []url.URL{{Scheme: "https", Host: "example.com:2379"}},
   190  			b:      []url.URL{{Scheme: "http", Host: "10.0.10.1:2379"}},
   191  			expect: false,
   192  			err:    errors.New(`"https://10.0.10.1:2379"(resolved from "https://example.com:2379") != "http://10.0.10.1:2379"(resolved from "http://10.0.10.1:2379")`),
   193  		},
   194  		{
   195  			a:      []url.URL{{Scheme: "unix", Host: "abc:2379"}},
   196  			b:      []url.URL{{Scheme: "unix", Host: "abc:2379"}},
   197  			expect: true,
   198  		},
   199  		{
   200  			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   201  			b:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   202  			expect: true,
   203  		},
   204  		{
   205  			a:      []url.URL{{Scheme: "http", Host: "example.com:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   206  			b:      []url.URL{{Scheme: "http", Host: "example.com:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   207  			expect: true,
   208  		},
   209  		{
   210  			a:      []url.URL{{Scheme: "http", Host: "10.0.10.1:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   211  			b:      []url.URL{{Scheme: "http", Host: "example.com:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   212  			expect: true,
   213  		},
   214  		{
   215  			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2379"}},
   216  			b:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2380"}},
   217  			expect: false,
   218  			err:    errors.New(`"http://127.0.0.1:2379"(resolved from "http://127.0.0.1:2379") != "http://127.0.0.1:2380"(resolved from "http://127.0.0.1:2380")`),
   219  		},
   220  		{
   221  			a:      []url.URL{{Scheme: "http", Host: "example.com:2380"}},
   222  			b:      []url.URL{{Scheme: "http", Host: "10.0.10.1:2379"}},
   223  			expect: false,
   224  			err:    errors.New(`"http://10.0.10.1:2380"(resolved from "http://example.com:2380") != "http://10.0.10.1:2379"(resolved from "http://10.0.10.1:2379")`),
   225  		},
   226  		{
   227  			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2379"}},
   228  			b:      []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}},
   229  			expect: false,
   230  			err:    errors.New(`"http://127.0.0.1:2379"(resolved from "http://127.0.0.1:2379") != "http://10.0.0.1:2379"(resolved from "http://10.0.0.1:2379")`),
   231  		},
   232  		{
   233  			a:      []url.URL{{Scheme: "http", Host: "example.com:2379"}},
   234  			b:      []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}},
   235  			expect: false,
   236  			err:    errors.New(`"http://10.0.10.1:2379"(resolved from "http://example.com:2379") != "http://10.0.0.1:2379"(resolved from "http://10.0.0.1:2379")`),
   237  		},
   238  		{
   239  			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   240  			b:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2380"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   241  			expect: false,
   242  			err:    errors.New(`"http://127.0.0.1:2379"(resolved from "http://127.0.0.1:2379") != "http://127.0.0.1:2380"(resolved from "http://127.0.0.1:2380")`),
   243  		},
   244  		{
   245  			a:      []url.URL{{Scheme: "http", Host: "example.com:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   246  			b:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2380"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   247  			expect: false,
   248  			err:    errors.New(`"http://10.0.10.1:2379"(resolved from "http://example.com:2379") != "http://127.0.0.1:2380"(resolved from "http://127.0.0.1:2380")`),
   249  		},
   250  		{
   251  			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   252  			b:      []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   253  			expect: false,
   254  			err:    errors.New(`"http://127.0.0.1:2379"(resolved from "http://127.0.0.1:2379") != "http://10.0.0.1:2379"(resolved from "http://10.0.0.1:2379")`),
   255  		},
   256  		{
   257  			a:      []url.URL{{Scheme: "http", Host: "example.com:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   258  			b:      []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   259  			expect: false,
   260  			err:    errors.New(`"http://10.0.10.1:2379"(resolved from "http://example.com:2379") != "http://10.0.0.1:2379"(resolved from "http://10.0.0.1:2379")`),
   261  		},
   262  		{
   263  			a:      []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}},
   264  			b:      []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}, {Scheme: "http", Host: "127.0.0.1:2380"}},
   265  			expect: false,
   266  			err:    errors.New(`len(["http://10.0.0.1:2379"]) != len(["http://10.0.0.1:2379" "http://127.0.0.1:2380"])`),
   267  		},
   268  		{
   269  			a:      []url.URL{{Scheme: "http", Host: "first.com:2379"}, {Scheme: "http", Host: "second.com:2380"}},
   270  			b:      []url.URL{{Scheme: "http", Host: "10.0.11.1:2379"}, {Scheme: "http", Host: "10.0.11.2:2380"}},
   271  			expect: true,
   272  		},
   273  		{
   274  			a:      []url.URL{{Scheme: "http", Host: "second.com:2380"}, {Scheme: "http", Host: "first.com:2379"}},
   275  			b:      []url.URL{{Scheme: "http", Host: "10.0.11.1:2379"}, {Scheme: "http", Host: "10.0.11.2:2380"}},
   276  			expect: true,
   277  		},
   278  	}
   279  
   280  	for i, test := range tests {
   281  		result, err := urlsEqual(context.TODO(), test.a, test.b)
   282  		if result != test.expect {
   283  			t.Errorf("#%d: a:%v b:%v, expected %v but %v", i, test.a, test.b, test.expect, result)
   284  		}
   285  		if test.err != nil {
   286  			if err.Error() != test.err.Error() {
   287  				t.Errorf("#%d: err expected %v but %v", i, test.err, err)
   288  			}
   289  		}
   290  	}
   291  }
   292  func TestURLStringsEqual(t *testing.T) {
   293  	result, err := URLStringsEqual(context.TODO(), []string{"http://127.0.0.1:8080"}, []string{"http://127.0.0.1:8080"})
   294  	if !result {
   295  		t.Errorf("unexpected result %v", result)
   296  	}
   297  	if err != nil {
   298  		t.Errorf("unexpected error %v", err)
   299  	}
   300  }