vitess.io/vitess@v0.16.2/go/netutil/netutil_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package netutil
    18  
    19  import (
    20  	"fmt"
    21  	"math/rand"
    22  	"net"
    23  	"reflect"
    24  	"testing"
    25  )
    26  
    27  func checkDistribution(t *testing.T, data []*net.SRV, margin float64) {
    28  	sum := 0
    29  	for _, srv := range data {
    30  		sum += int(srv.Weight)
    31  	}
    32  
    33  	results := make(map[string]int)
    34  
    35  	count := 1000
    36  	for j := 0; j < count; j++ {
    37  		d := make([]*net.SRV, len(data))
    38  		copy(d, data)
    39  		byPriorityWeight(d).shuffleByWeight()
    40  		key := d[0].Target
    41  		results[key] = results[key] + 1
    42  	}
    43  
    44  	actual := results[data[0].Target]
    45  	expected := float64(count) * float64(data[0].Weight) / float64(sum)
    46  	diff := float64(actual) - expected
    47  	t.Logf("actual: %v diff: %v e: %v m: %v", actual, diff, expected, margin)
    48  	if diff < 0 {
    49  		diff = -diff
    50  	}
    51  	if diff > (expected * margin) {
    52  		t.Errorf("missed target weight: expected %v, %v", expected, actual)
    53  	}
    54  }
    55  
    56  func testUniformity(t *testing.T, size int, margin float64) {
    57  	rand.Seed(1)
    58  	data := make([]*net.SRV, size)
    59  	for i := 0; i < size; i++ {
    60  		data[i] = &net.SRV{Target: fmt.Sprintf("%c", 'a'+i), Weight: 1}
    61  	}
    62  	checkDistribution(t, data, margin)
    63  }
    64  
    65  func TestUniformity(t *testing.T) {
    66  	testUniformity(t, 2, 0.05)
    67  	testUniformity(t, 3, 0.10)
    68  	testUniformity(t, 10, 0.20)
    69  	testWeighting(t, 0.05)
    70  }
    71  
    72  func testWeighting(t *testing.T, margin float64) {
    73  	rand.Seed(1)
    74  	data := []*net.SRV{
    75  		{Target: "a", Weight: 60},
    76  		{Target: "b", Weight: 30},
    77  		{Target: "c", Weight: 10},
    78  	}
    79  	checkDistribution(t, data, margin)
    80  }
    81  
    82  func TestWeighting(t *testing.T) {
    83  	testWeighting(t, 0.05)
    84  }
    85  
    86  func TestSplitHostPort(t *testing.T) {
    87  	type addr struct {
    88  		host string
    89  		port int
    90  	}
    91  	table := map[string]addr{
    92  		"host-name:132":  {host: "host-name", port: 132},
    93  		"hostname:65535": {host: "hostname", port: 65535},
    94  		"[::1]:321":      {host: "::1", port: 321},
    95  		"::1:432":        {host: "::1", port: 432},
    96  	}
    97  	for input, want := range table {
    98  		gotHost, gotPort, err := SplitHostPort(input)
    99  		if err != nil {
   100  			t.Errorf("SplitHostPort error: %v", err)
   101  		}
   102  		if gotHost != want.host || gotPort != want.port {
   103  			t.Errorf("SplitHostPort(%#v) = (%v, %v), want (%v, %v)", input, gotHost, gotPort, want.host, want.port)
   104  		}
   105  	}
   106  }
   107  
   108  func TestSplitHostPortFail(t *testing.T) {
   109  	// These cases should all fail to parse.
   110  	inputs := []string{
   111  		"host-name",
   112  		"host-name:123abc",
   113  	}
   114  	for _, input := range inputs {
   115  		_, _, err := SplitHostPort(input)
   116  		if err == nil {
   117  			t.Errorf("expected error from SplitHostPort(%q), but got none", input)
   118  		}
   119  	}
   120  }
   121  
   122  func TestJoinHostPort(t *testing.T) {
   123  	type addr struct {
   124  		host string
   125  		port int32
   126  	}
   127  	table := map[string]addr{
   128  		"host-name:132": {host: "host-name", port: 132},
   129  		"[::1]:321":     {host: "::1", port: 321},
   130  	}
   131  	for want, input := range table {
   132  		if got := JoinHostPort(input.host, input.port); got != want {
   133  			t.Errorf("SplitHostPort(%v, %v) = %#v, want %#v", input.host, input.port, got, want)
   134  		}
   135  	}
   136  }
   137  
   138  func TestResolveIPv4Addrs(t *testing.T) {
   139  	cases := []struct {
   140  		address       string
   141  		expected      []string
   142  		expectedError bool
   143  	}{
   144  		{
   145  			address:  "localhost:3306",
   146  			expected: []string{"127.0.0.1:3306"},
   147  		},
   148  		{
   149  			address:       "127.0.0.256:3306",
   150  			expectedError: true,
   151  		},
   152  		{
   153  			address:       "localhost",
   154  			expectedError: true,
   155  		},
   156  		{
   157  			address:       "InvalidHost:3306",
   158  			expectedError: true,
   159  		},
   160  	}
   161  
   162  	for _, c := range cases {
   163  		t.Run(c.address, func(t *testing.T) {
   164  			got, err := ResolveIPv4Addrs(c.address)
   165  			if (err != nil) != c.expectedError {
   166  				t.Errorf("expected error but got: %v", err)
   167  			}
   168  			if !reflect.DeepEqual(got, c.expected) {
   169  				t.Errorf("expected: %v, got: %v", c.expected, got)
   170  			}
   171  		})
   172  	}
   173  }
   174  
   175  func TestNormalizeIP(t *testing.T) {
   176  	table := map[string]string{
   177  		"1.2.3.4":   "1.2.3.4",
   178  		"127.0.0.1": "127.0.0.1",
   179  		"127.0.1.1": "127.0.0.1",
   180  		// IPv6 must be mapped to IPv4.
   181  		"::1": "127.0.0.1",
   182  		// An unparseable IP should be returned as is.
   183  		"127.": "127.",
   184  	}
   185  	for input, want := range table {
   186  		if got := NormalizeIP(input); got != want {
   187  			t.Errorf("NormalizeIP(%#v) = %#v, want %#v", input, got, want)
   188  		}
   189  	}
   190  }