github.com/ethereum/go-ethereum@v1.16.1/p2p/netutil/net_test.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser 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 // The go-ethereum library 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 Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package netutil 18 19 import ( 20 "fmt" 21 "math/rand" 22 "net" 23 "net/netip" 24 "reflect" 25 "testing" 26 "testing/quick" 27 28 "github.com/davecgh/go-spew/spew" 29 ) 30 31 func TestParseNetlist(t *testing.T) { 32 var tests = []struct { 33 input string 34 wantErr string 35 wantList *Netlist 36 }{ 37 { 38 input: "", 39 wantList: &Netlist{}, 40 }, 41 { 42 input: "127.0.0.0/8", 43 wantList: &Netlist{netip.MustParsePrefix("127.0.0.0/8")}, 44 }, 45 { 46 input: "127.0.0.0/44", 47 wantErr: `netip.ParsePrefix("127.0.0.0/44"): prefix length out of range`, 48 }, 49 { 50 input: "127.0.0.0/16, 23.23.23.23/24,", 51 wantList: &Netlist{ 52 netip.MustParsePrefix("127.0.0.0/16"), 53 netip.MustParsePrefix("23.23.23.23/24"), 54 }, 55 }, 56 } 57 58 for _, test := range tests { 59 l, err := ParseNetlist(test.input) 60 if err == nil && test.wantErr != "" { 61 t.Errorf("%q: got no error, expected %q", test.input, test.wantErr) 62 continue 63 } else if err != nil && err.Error() != test.wantErr { 64 t.Errorf("%q: got error %q, want %q", test.input, err, test.wantErr) 65 continue 66 } 67 if !reflect.DeepEqual(l, test.wantList) { 68 spew.Dump(l) 69 spew.Dump(test.wantList) 70 t.Errorf("%q: got %v, want %v", test.input, l, test.wantList) 71 } 72 } 73 } 74 75 func TestNilNetListContains(t *testing.T) { 76 var list *Netlist 77 checkContains(t, list.Contains, list.ContainsAddr, nil, []string{"1.2.3.4"}) 78 } 79 80 func TestIsLAN(t *testing.T) { 81 checkContains(t, IsLAN, AddrIsLAN, 82 []string{ // included 83 "127.0.0.1", 84 "10.0.1.1", 85 "10.22.0.3", 86 "172.31.252.251", 87 "192.168.1.4", 88 "fe80::f4a1:8eff:fec5:9d9d", 89 "febf::ab32:2233", 90 "fc00::4", 91 // 4-in-6 92 "::ffff:127.0.0.1", 93 "::ffff:10.10.0.2", 94 }, 95 []string{ // excluded 96 "192.0.2.1", 97 "1.0.0.0", 98 "172.32.0.1", 99 "fec0::2233", 100 // 4-in-6 101 "::ffff:88.99.100.2", 102 }, 103 ) 104 } 105 106 func TestIsSpecialNetwork(t *testing.T) { 107 checkContains(t, IsSpecialNetwork, AddrIsSpecialNetwork, 108 []string{ // included 109 "0.0.0.0", 110 "0.2.0.8", 111 "192.0.2.1", 112 "192.0.2.44", 113 "2001:db8:85a3:8d3:1319:8a2e:370:7348", 114 "255.255.255.255", 115 "224.0.0.22", // IPv4 multicast 116 "ff05::1:3", // IPv6 multicast 117 // 4-in-6 118 "::ffff:255.255.255.255", 119 "::ffff:192.0.2.1", 120 }, 121 []string{ // excluded 122 "192.0.3.1", 123 "1.0.0.0", 124 "172.32.0.1", 125 "fec0::2233", 126 }, 127 ) 128 } 129 130 func checkContains(t *testing.T, fn func(net.IP) bool, fn2 func(netip.Addr) bool, inc, exc []string) { 131 for _, s := range inc { 132 if !fn(parseIP(s)) { 133 t.Error("returned false for included net.IP", s) 134 } 135 if !fn2(netip.MustParseAddr(s)) { 136 t.Error("returned false for included netip.Addr", s) 137 } 138 } 139 for _, s := range exc { 140 if fn(parseIP(s)) { 141 t.Error("returned true for excluded net.IP", s) 142 } 143 if fn2(netip.MustParseAddr(s)) { 144 t.Error("returned true for excluded netip.Addr", s) 145 } 146 } 147 } 148 149 func parseIP(s string) net.IP { 150 ip := net.ParseIP(s) 151 if ip == nil { 152 panic("invalid " + s) 153 } 154 return ip 155 } 156 157 func TestCheckRelayIP(t *testing.T) { 158 tests := []struct { 159 sender, addr string 160 want error 161 }{ 162 {"127.0.0.1", "0.0.0.0", errUnspecified}, 163 {"192.168.0.1", "0.0.0.0", errUnspecified}, 164 {"23.55.1.242", "0.0.0.0", errUnspecified}, 165 {"127.0.0.1", "255.255.255.255", errSpecial}, 166 {"192.168.0.1", "255.255.255.255", errSpecial}, 167 {"23.55.1.242", "255.255.255.255", errSpecial}, 168 {"192.168.0.1", "127.0.2.19", errLoopback}, 169 {"23.55.1.242", "192.168.0.1", errLAN}, 170 171 {"127.0.0.1", "127.0.2.19", nil}, 172 {"127.0.0.1", "192.168.0.1", nil}, 173 {"127.0.0.1", "23.55.1.242", nil}, 174 {"192.168.0.1", "192.168.0.1", nil}, 175 {"192.168.0.1", "23.55.1.242", nil}, 176 {"23.55.1.242", "23.55.1.242", nil}, 177 } 178 179 for _, test := range tests { 180 err := CheckRelayIP(parseIP(test.sender), parseIP(test.addr)) 181 if err != test.want { 182 t.Errorf("%s from %s: got %q, want %q", test.addr, test.sender, err, test.want) 183 } 184 } 185 } 186 187 func BenchmarkCheckRelayIP(b *testing.B) { 188 sender := parseIP("23.55.1.242") 189 addr := parseIP("23.55.1.2") 190 for i := 0; i < b.N; i++ { 191 CheckRelayIP(sender, addr) 192 } 193 } 194 195 func TestSameNet(t *testing.T) { 196 tests := []struct { 197 ip, other string 198 bits uint 199 want bool 200 }{ 201 {"0.0.0.0", "0.0.0.0", 32, true}, 202 {"0.0.0.0", "0.0.0.1", 0, true}, 203 {"0.0.0.0", "0.0.0.1", 31, true}, 204 {"0.0.0.0", "0.0.0.1", 32, false}, 205 {"0.33.0.1", "0.34.0.2", 8, true}, 206 {"0.33.0.1", "0.34.0.2", 13, true}, 207 {"0.33.0.1", "0.34.0.2", 15, false}, 208 } 209 210 for _, test := range tests { 211 if ok := SameNet(test.bits, parseIP(test.ip), parseIP(test.other)); ok != test.want { 212 t.Errorf("SameNet(%d, %s, %s) == %t, want %t", test.bits, test.ip, test.other, ok, test.want) 213 } 214 } 215 } 216 217 func ExampleSameNet() { 218 // This returns true because the IPs are in the same /24 network: 219 fmt.Println(SameNet(24, net.IP{127, 0, 0, 1}, net.IP{127, 0, 0, 3})) 220 // This call returns false: 221 fmt.Println(SameNet(24, net.IP{127, 3, 0, 1}, net.IP{127, 5, 0, 3})) 222 // Output: 223 // true 224 // false 225 } 226 227 func TestDistinctNetSet(t *testing.T) { 228 ops := []struct { 229 add, remove string 230 fails bool 231 }{ 232 {add: "127.0.0.1"}, 233 {add: "127.0.0.2"}, 234 {add: "127.0.0.3", fails: true}, 235 {add: "127.32.0.1"}, 236 {add: "127.32.0.2"}, 237 {add: "127.32.0.3", fails: true}, 238 {add: "127.33.0.1", fails: true}, 239 {add: "127.34.0.1"}, 240 {add: "127.34.0.2"}, 241 {add: "127.34.0.3", fails: true}, 242 // Make room for an address, then add again. 243 {remove: "127.0.0.1"}, 244 {add: "127.0.0.3"}, 245 {add: "127.0.0.3", fails: true}, 246 } 247 248 set := DistinctNetSet{Subnet: 15, Limit: 2} 249 for _, op := range ops { 250 var desc string 251 if op.add != "" { 252 desc = fmt.Sprintf("Add(%s)", op.add) 253 if ok := set.Add(parseIP(op.add)); ok != !op.fails { 254 t.Errorf("%s == %t, want %t", desc, ok, !op.fails) 255 } 256 } else { 257 desc = fmt.Sprintf("Remove(%s)", op.remove) 258 set.Remove(parseIP(op.remove)) 259 } 260 t.Logf("%s: %v", desc, set) 261 } 262 } 263 264 func TestDistinctNetSetAddRemove(t *testing.T) { 265 cfg := &quick.Config{ 266 Values: func(s []reflect.Value, rng *rand.Rand) { 267 slice := make([]netip.Addr, rng.Intn(20)+1) 268 for i := range slice { 269 slice[i] = RandomAddr(rng, false) 270 } 271 s[0] = reflect.ValueOf(slice) 272 }, 273 } 274 fn := func(ips []netip.Addr) bool { 275 s := DistinctNetSet{Limit: 3, Subnet: 2} 276 for _, ip := range ips { 277 s.AddAddr(ip) 278 } 279 for _, ip := range ips { 280 s.RemoveAddr(ip) 281 } 282 return s.Len() == 0 283 } 284 285 if err := quick.Check(fn, cfg); err != nil { 286 t.Fatal(err) 287 } 288 }