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 }