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  }