github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/ipaddr/ipaddr_test.go (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package ipaddr
    12  
    13  import (
    14  	"math"
    15  	"net"
    16  	"strings"
    17  	"testing"
    18  
    19  	"github.com/cockroachdb/cockroach/pkg/util/uint128"
    20  )
    21  
    22  func TestIPAddrParseInet(t *testing.T) {
    23  	testCases := []struct {
    24  		s   string
    25  		exp *IPAddr
    26  		err string
    27  	}{
    28  		// Basic IPv4.
    29  		{"192.168.1.2", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 32}, ""},
    30  		// Test we preserve masked bits.
    31  		{"192.168.1.2/16", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 16}, ""},
    32  		// Test the ability to have following '.'.
    33  		{"192.168.1.2.", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 32}, ""},
    34  		{"192.168.1.2./10", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 10}, ""},
    35  		// Basic IPv6.
    36  		{"2001:4f8:3:ba::/64", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("2001:4f8:3:ba::")))), Mask: 64}, ""},
    37  		{"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("2001:4f8:3:ba:2e0:81ff:fe22:d1f1")))), Mask: 128}, ""},
    38  		{"::ffff:1.2.3.1/120", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 120}, ""},
    39  		{"::ffff:1.2.3.1/128", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 128}, ""},
    40  		{"::ffff:1.2.3.1/128", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 128}, ""},
    41  		{"::ffff:1.2.3.1/20", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 20}, ""},
    42  		{"::ffff:1.2.3.1/120", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 120}, ""},
    43  		{"::1", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::1")))), Mask: 128}, ""},
    44  		{"9ec6:78fc:c3ae:a65a:9ac7:2081:ac81:e0aa/101", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("9ec6:78fc:c3ae:a65a:9ac7:2081:ac81:e0aa")))), Mask: 101}, ""},
    45  
    46  		// Test bad IPs.
    47  		{"abc", nil, "invalid IP"},
    48  		{"", nil, "invalid IP"},
    49  		{"20000", nil, "invalid IP"},
    50  		{"123.abc", nil, "invalid IP"},
    51  		{"123.2000", nil, "invalid IP"},
    52  		{"192.168", nil, "invalid IP"},
    53  		{"192.168.0.0.0", nil, "invalid IP"},
    54  		{"192.168.0.2/a", nil, "invalid mask"},
    55  		{"192.168.0.2/100", nil, "invalid mask"},
    56  		{"192.168.0.a/20", nil, "invalid IP"},
    57  
    58  		// Edge cases.
    59  		{"0.0.0.0", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4zero))), Mask: 32}, ""},
    60  		{"0.0.0.0/32", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4zero))), Mask: 32}, ""},
    61  		{"0.0.0.0/0", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4zero))), Mask: 0}, ""},
    62  		{"0.0.0.0/10", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4zero))), Mask: 10}, ""},
    63  
    64  		{"255.255.255.255", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4bcast))), Mask: 32}, ""},
    65  		{"255.255.255.255/32", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4bcast))), Mask: 32}, ""},
    66  		{"255.255.255.255/0", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4bcast))), Mask: 0}, ""},
    67  		{"255.255.255.255/10", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.IPv4bcast))), Mask: 10}, ""},
    68  
    69  		{"::0", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.IPv6zero))), Mask: 128}, ""},
    70  		{"::0/0", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.IPv6zero))), Mask: 0}, ""},
    71  		{"::0/10", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.IPv6zero))), Mask: 10}, ""},
    72  
    73  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")))), Mask: 128}, ""},
    74  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/0", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")))), Mask: 0}, ""},
    75  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/10", &IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")))), Mask: 10}, ""},
    76  
    77  		// Postgres compatibility edge cases: IPv4 missing octets.
    78  		{"192.168/24", nil, "mask is larger than provided octets"},
    79  		{"192/10", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.0.0.0")))), Mask: 10}, ""},
    80  		{"192.168/23", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.0.0")))), Mask: 23}, ""},
    81  		{"192.168./10", &IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.0.0")))), Mask: 10}, ""},
    82  	}
    83  	for i, testCase := range testCases {
    84  		var actual IPAddr
    85  		if err := ParseINet(testCase.s, &actual); err != nil {
    86  			if len(testCase.err) > 0 {
    87  				if !strings.Contains(err.Error(), testCase.err) {
    88  					t.Errorf("%d: ParseINet(%s) caused an incorrect error actual:%s, expected:%s", i, testCase.s,
    89  						err, testCase.err)
    90  				}
    91  			} else {
    92  				t.Errorf("%d: ParseINet(%s) caused an unexpected error:%s", i, testCase.s, err)
    93  			}
    94  		} else if testCase.exp != nil && !actual.Equal(testCase.exp) {
    95  			t.Errorf("%d: ParseINet(%s) actual:%v does not match expected:%v", i, testCase.s, actual,
    96  				testCase.exp)
    97  		}
    98  	}
    99  }
   100  
   101  func TestIPAddrBinaryMarshalling(t *testing.T) {
   102  	testCases := []struct {
   103  		input *IPAddr
   104  	}{
   105  		{&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 32}},
   106  		{&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 16}},
   107  		{&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 32}},
   108  		{&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.1.2")))), Mask: 10}},
   109  		{&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("2001:4f8:3:ba::")))), Mask: 64}},
   110  		{&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("2001:4f8:3:ba:2e0:81ff:fe22:d1f1")))), Mask: 128}},
   111  		{&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 120}},
   112  		{&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 128}},
   113  		{&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::ffff:1.2.3.1")))), Mask: 128}},
   114  		{&IPAddr{Family: IPv6family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("::1")))), Mask: 128}},
   115  		{&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.0.0")))), Mask: 23}},
   116  		{&IPAddr{Family: IPv4family, Addr: Addr(uint128.FromBytes([]byte(net.ParseIP("192.168.0.0")))), Mask: 10}},
   117  	}
   118  	for i, testCase := range testCases {
   119  		var data []byte
   120  		data = testCase.input.ToBuffer(data)
   121  		var actual IPAddr
   122  		if remaining, err := actual.FromBuffer(data); err != nil {
   123  			t.Errorf("%d: UnmarshalBinary(%s) caused an unexpected error:%s", i, testCase.input, err)
   124  		} else if !actual.Equal(testCase.input) {
   125  			t.Errorf("%d: Binary marshaling round trip failed. actual:%v does not match expected:%v", i, actual, testCase.input)
   126  		} else if len(remaining) != 0 {
   127  			t.Errorf("%d: Binary marshaling left extraneous bytes in buffer. Leftover len: %d bytes: %s", i, len(remaining), remaining)
   128  		}
   129  	}
   130  }
   131  
   132  func TestIPAddrGetFamily(t *testing.T) {
   133  	testCases := []struct {
   134  		s   string
   135  		exp IPFamily
   136  	}{
   137  		// Basic IPv4
   138  		{"192.168.1.2", IPv4family},
   139  		{"192.168.1.2/16", IPv4family},
   140  		// Basic IPv6
   141  		{"2001:4f8:3:ba::/64", IPv6family},
   142  		{"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", IPv6family},
   143  		{"::ffff:1.2.3.1/120", IPv6family},
   144  		{"::ffff:1.2.3.1/128", IPv6family},
   145  		{"::ffff:1.2.3.1/128", IPv6family},
   146  		{"::1", IPv6family},
   147  
   148  		// Postgres compatibility edge cases: IPv4 missing octets
   149  		{"192.168/24", IPv4family},
   150  		{"192/10", IPv4family},
   151  		{"192.168/23", IPv4family},
   152  		{"192.168./10", IPv4family},
   153  	}
   154  	for i, testCase := range testCases {
   155  		actual := getFamily(testCase.s)
   156  
   157  		if actual != testCase.exp {
   158  			t.Errorf("%d: getFamily(%q) actual:%v does not match expected:%v", i, testCase.s, actual,
   159  				testCase.exp)
   160  		}
   161  	}
   162  }
   163  
   164  func TestIPAddrCompare(t *testing.T) {
   165  	testCases := []struct {
   166  		s1  string
   167  		s2  string
   168  		exp int
   169  	}{
   170  		// Basic IPv4
   171  		{"192.168.1.2", "192.168.1.2", 0},
   172  		{"192.168.1.2", "192.168.1.3", -1},
   173  		{"192.168.1.2", "192.168.1.1", 1},
   174  		{"192.168.1.2", "192.168.0.2", 1},
   175  		{"192.168.1.2", "192.168.1.2/16", 1},
   176  		{"192.168.1.2/17", "192.168.1.2/16", 1},
   177  		{"192.168.1.2/17", "192.168.1.3/1", 1},
   178  		{"192.168.1.2/1", "192.168.1.3/17", -1},
   179  		{"192.168.1.2", "::ffff:192.168.1.2", -1},
   180  		{"::ffff:192.168.1.2", "192.168.1.2", 1},
   181  		{"::ffff:192.168.1.2", "::ffff:192.168.1.2", 0},
   182  		{"c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", 0},
   183  		{"6e32:8a01:373b:c9ce:8ed5:9f7f:dc7e:5cfc", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", -1},
   184  		{"192.168.1.2", "192.168.1.2", 0},
   185  	}
   186  	for i, testCase := range testCases {
   187  		var ip1 IPAddr
   188  		var ip2 IPAddr
   189  		if err := ParseINet(testCase.s1, &ip1); err != nil {
   190  			t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1)
   191  		}
   192  		if err := ParseINet(testCase.s2, &ip2); err != nil {
   193  			t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2)
   194  		}
   195  
   196  		if actual := ip1.Compare(&ip2); actual != testCase.exp {
   197  			t.Errorf("%d: Compare(%q, %q) actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual,
   198  				testCase.exp)
   199  		}
   200  	}
   201  }
   202  
   203  func TestIPAddrEqual(t *testing.T) {
   204  	testCases := []struct {
   205  		s1  string
   206  		s2  string
   207  		exp bool
   208  	}{
   209  		// Basic IPv4
   210  		{"192.168.1.2", "192.168.1.2", true},
   211  		{"192.168.1.2", "192.168.1.3", false},
   212  		{"192.168.1.2", "192.168.1.2/10", false},
   213  		{"192.168.1.2", "::ffff:192.168.1.2", false},
   214  		{"192.168.1.2", "::ffff:192.168.1.2", false},
   215  		{"0.0.0.0", "0.0.0.0", true},
   216  		{"0.0.0.0/0", "0.0.0.0/0", true},
   217  		{"0.0.0.0/0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128", false},
   218  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128", true},
   219  	}
   220  	for i, testCase := range testCases {
   221  		var ip1 IPAddr
   222  		var ip2 IPAddr
   223  		if err := ParseINet(testCase.s1, &ip1); err != nil {
   224  			t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1)
   225  		}
   226  		if err := ParseINet(testCase.s2, &ip2); err != nil {
   227  			t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2)
   228  		}
   229  
   230  		if actual := ip1.Equal(&ip2); actual != testCase.exp {
   231  			t.Errorf("%d: Equal(%q, %q) actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual,
   232  				testCase.exp)
   233  		}
   234  	}
   235  }
   236  
   237  func TestIPAddrString(t *testing.T) {
   238  	testCases := []struct {
   239  		s   string
   240  		exp string
   241  	}{
   242  		{"0.0.0.0", "0.0.0.0"},
   243  		{"::0", "::"},
   244  		{"255.255.255.255", "255.255.255.255"},
   245  		{"192.168.1.2", "192.168.1.2"},
   246  		{"192.168.1.2/10", "192.168.1.2/10"},
   247  		// Test omission of mask
   248  		{"192.168.1.2/32", "192.168.1.2"},
   249  		{"::ffff/128", "::ffff"},
   250  
   251  		// Test retention of IPv6 format if IPv4-mapped IPv6 for postgres compatibility
   252  		{"::ffff:192.168.1.2", "::ffff:192.168.1.2"},
   253  		{"::ffff:192.168.1.2/120", "::ffff:192.168.1.2/120"},
   254  	}
   255  	for i, testCase := range testCases {
   256  		var ip IPAddr
   257  		if err := ParseINet(testCase.s, &ip); err != nil {
   258  			t.Fatalf("%d: Bad test input s:%s", i, testCase.s)
   259  		}
   260  		actual := ip.String()
   261  		if actual != testCase.exp {
   262  			t.Errorf("%d: String(%q) actual:%v does not match expected:%v", i, testCase.s, actual,
   263  				testCase.exp)
   264  		}
   265  	}
   266  }
   267  
   268  func TestIPAddrBroadcast(t *testing.T) {
   269  	testCases := []struct {
   270  		s   string
   271  		exp string
   272  	}{
   273  		// Basic IPv4
   274  		{"192.168.1.2", "192.168.1.2"},
   275  		{"192.168.1.2/16", "192.168.255.255/16"},
   276  		{"192.168.1.2/10", "192.191.255.255/10"},
   277  		{"192.0.0.0/10", "192.63.255.255/10"},
   278  		// Basic IPv6
   279  		{"2001:4f8:3:ba::/64", "2001:4f8:3:ba:ffff:ffff:ffff:ffff/64"},
   280  		{"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", "2001:4f8:3:ba:2e0:81ff:fe22:d1f1"},
   281  		{"::ffff:1.2.3.1/120", "::ffff:1.2.3.255/120"},
   282  		{"::ffff:1.2.3.1/128", "::ffff:1.2.3.1"},
   283  		{"::ffff:1.2.3.1/20", "0:fff:ffff:ffff:ffff:ffff:ffff:ffff/20"},
   284  		{"::1", "::1"},
   285  	}
   286  	for i, testCase := range testCases {
   287  		var ip IPAddr
   288  		if err := ParseINet(testCase.s, &ip); err != nil {
   289  			t.Fatalf("%d: bad test case: %s got error %s", i, testCase.s, err)
   290  		}
   291  		actual := ip.Broadcast()
   292  		if actual.String() != testCase.exp {
   293  			t.Errorf("%d: Broadcast(%s) actual:%s does not match expected:%s", i, testCase.s, actual.String(),
   294  				testCase.exp)
   295  		}
   296  	}
   297  }
   298  
   299  func TestIPAddrHostmask(t *testing.T) {
   300  	testCases := []struct {
   301  		s   string
   302  		exp string
   303  	}{
   304  		// Basic IPv4
   305  		{"192.168.1.2", "0.0.0.0"},
   306  		{"192.168.1.2/16", "0.0.255.255"},
   307  		{"192.168.1.2/10", "0.63.255.255"},
   308  		{"192.168.1.2/0", "255.255.255.255"},
   309  		// Basic IPv6
   310  		{"2001:4f8:3:ba::/64", "::ffff:ffff:ffff:ffff"},
   311  		{"2001:4f8:3:ba::/0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"},
   312  		{"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", "::"},
   313  		{"::ffff:1.2.3.1/120", "::ff"},
   314  		{"::ffff:1.2.3.1/128", "::"},
   315  		{"::ffff:1.2.3.1/20", "0:fff:ffff:ffff:ffff:ffff:ffff:ffff"},
   316  	}
   317  	for i, testCase := range testCases {
   318  		var ip IPAddr
   319  		if err := ParseINet(testCase.s, &ip); err != nil {
   320  			t.Fatalf("%d: bad test case: %s got error %s", i, testCase.s, err)
   321  		}
   322  
   323  		var expIP IPAddr
   324  		if err := ParseINet(testCase.exp, &expIP); err != nil {
   325  			t.Fatalf("%d: bad test case: %s got error %s", i, testCase.exp, err)
   326  		}
   327  
   328  		actual := ip.Hostmask()
   329  		if actual.String() != testCase.exp {
   330  			t.Errorf("%d: Hostmask(%s) actual:%#v does not match expected:%#v", i, testCase.s, actual,
   331  				expIP)
   332  		}
   333  	}
   334  }
   335  
   336  func TestIPAddrNetmask(t *testing.T) {
   337  	testCases := []struct {
   338  		s   string
   339  		exp string
   340  	}{
   341  		// Basic IPv4
   342  		{"192.168.1.2", "255.255.255.255"},
   343  		{"192.168.1.2/16", "255.255.0.0"},
   344  		{"192.168.1.2/10", "255.192.0.0"},
   345  		{"192.168.1.2/0", "0.0.0.0"},
   346  		// Basic IPv6
   347  		{"2001:4f8:3:ba::/64", "ffff:ffff:ffff:ffff::"},
   348  		{"2001:4f8:3:ba::/0", "::"},
   349  		{"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"},
   350  		{"::ffff:1.2.3.1/120", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00"},
   351  		{"::ffff:1.2.3.1/20", "ffff:f000::"},
   352  	}
   353  	for i, testCase := range testCases {
   354  		var ip IPAddr
   355  		if err := ParseINet(testCase.s, &ip); err != nil {
   356  			t.Fatalf("%d: bad test case: %s got error %s", i, testCase.s, err)
   357  		}
   358  
   359  		actual := ip.Netmask()
   360  		if actual.String() != testCase.exp {
   361  			t.Errorf("%d: Netmask(%s) actual:%s does not match expected:%s", i, testCase.s, actual,
   362  				testCase.exp)
   363  		}
   364  	}
   365  }
   366  
   367  func TestComplement(t *testing.T) {
   368  	testCases := []struct {
   369  		s   string
   370  		exp string
   371  	}{
   372  		{"192.168.1.2", "63.87.254.253"},
   373  		{"192.168.1.2/16", "63.87.254.253/16"},
   374  		{"192.168.1.2/10", "63.87.254.253/10"},
   375  		{"192.168.1.2/0", "63.87.254.253/0"},
   376  		// Basic IPv6
   377  		{"2001:4f8:3:ba::/64", "dffe:fb07:fffc:ff45:ffff:ffff:ffff:ffff/64"},
   378  		{"2001:4f8:3:ba::/0", "dffe:fb07:fffc:ff45:ffff:ffff:ffff:ffff/0"},
   379  		{"2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128", "dffe:fb07:fffc:ff45:fd1f:7e00:1dd:2e0e"},
   380  		{"::ffff:1.2.3.1/120", "ffff:ffff:ffff:ffff:ffff:0:fefd:fcfe/120"},
   381  		{"::ffff:1.2.3.1/20", "ffff:ffff:ffff:ffff:ffff:0:fefd:fcfe/20"},
   382  	}
   383  	for i, testCase := range testCases {
   384  		var ip IPAddr
   385  		if err := ParseINet(testCase.s, &ip); err != nil {
   386  			t.Fatalf("%d: bad test case: %s got error %s", i, testCase.s, err)
   387  		}
   388  
   389  		actual := ip.Complement()
   390  		if actual.String() != testCase.exp {
   391  			t.Errorf("%d: Complement(%s) actual:%s does not match expected:%s", i, testCase.s, actual,
   392  				testCase.exp)
   393  		}
   394  	}
   395  }
   396  
   397  func TestAnd(t *testing.T) {
   398  	testCases := []struct {
   399  		s1  string
   400  		s2  string
   401  		exp string
   402  	}{
   403  		{"192.168.1.2", "192.168.1.2", "192.168.1.2"},
   404  		{"255.255.255.250", "0.0.0.5", "0.0.0.0"},
   405  		{"255.255.255.250/2", "0.5.0.5/17", "0.5.0.0/17"},
   406  		{"192.168.1.2/17", "192.168.1.2/16", "192.168.1.2/17"},
   407  		{"192.168.1.2/17", "192.168.1.3/1", "192.168.1.2/17"},
   408  		{"192.168.1.2/1", "192.168.1.3/17", "192.168.1.2/17"},
   409  		{"::ffff:192.168.1.2", "::ffff:192.168.1.2", "::ffff:192.168.1.2"},
   410  		{"0000:0564:0000:0aab:0000:0000:0060:0005", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005", "0:564:0:aab::60:5"},
   411  		{"c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d/99", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d"},
   412  		{"6e32:8a01:373b:c9ce:8ed5:9f7f:dc7e:5cfc", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", "4232:8801:1418:c082:290:8b79:c424:47c"},
   413  		{"8000:0000:0000:0000:0000:0000:0000:0005/68", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005/7", "8000::5/68"},
   414  	}
   415  	for i, testCase := range testCases {
   416  		var ip1, ip2, exp IPAddr
   417  		if err := ParseINet(testCase.s1, &ip1); err != nil {
   418  			t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1)
   419  		}
   420  		if err := ParseINet(testCase.s2, &ip2); err != nil {
   421  			t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2)
   422  		}
   423  		if err := ParseINet(testCase.exp, &exp); err != nil {
   424  			t.Fatalf("%d: Bad test input exp:%s", i, testCase.exp)
   425  		}
   426  
   427  		actual, err := ip1.And(&ip2)
   428  		if err != nil {
   429  			t.Fatalf("%d: Bad test input s1:%s AND s2:%s", i, testCase.s1, testCase.s2)
   430  		}
   431  		if !actual.Equal(&exp) {
   432  			t.Errorf("%d: And(%q, %q) actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual,
   433  				testCase.exp)
   434  		}
   435  	}
   436  }
   437  
   438  func TestOr(t *testing.T) {
   439  	testCases := []struct {
   440  		s1  string
   441  		s2  string
   442  		exp string
   443  	}{
   444  		{"192.168.1.2", "192.168.1.2", "192.168.1.2"},
   445  		{"255.255.255.250", "0.0.0.5", "255.255.255.255"},
   446  		{"255.255.255.250/2", "0.5.0.5/17", "255.255.255.255/17"},
   447  		{"192.168.1.2/17", "192.168.1.2/16", "192.168.1.2/17"},
   448  		{"192.168.1.2/17", "192.168.1.3/1", "192.168.1.3/17"},
   449  		{"192.168.1.2/1", "192.168.1.3/17", "192.168.1.3/17"},
   450  		{"::ffff:192.168.1.2", "::ffff:192.168.1.2", "::ffff:192.168.1.2"},
   451  		{"0000:0564:0000:0aab:0000:0000:0060:0005", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:5"},
   452  		{"c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d/99", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d"},
   453  		{"6e32:8a01:373b:c9ce:8ed5:9f7f:dc7e:5cfc", "c33e:9867:5c98:f0a2:2b2:abf9:c7a5:67d", "ef3e:9a67:7fbb:f9ee:8ef7:bfff:dfff:5efd"},
   454  		{"8000:0000:0000:0000:0000:0000:0000:0005/68", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005/7", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:5/68"},
   455  	}
   456  	for i, testCase := range testCases {
   457  		var ip1, ip2, exp IPAddr
   458  		if err := ParseINet(testCase.s1, &ip1); err != nil {
   459  			t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1)
   460  		}
   461  		if err := ParseINet(testCase.s2, &ip2); err != nil {
   462  			t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2)
   463  		}
   464  		if err := ParseINet(testCase.exp, &exp); err != nil {
   465  			t.Fatalf("%d: Bad test input exp:%s", i, testCase.exp)
   466  		}
   467  
   468  		actual, err := ip1.Or(&ip2)
   469  		if err != nil {
   470  			t.Fatalf("%d: Bad test input s1:%s AND s2:%s", i, testCase.s1, testCase.s2)
   471  		}
   472  		if !actual.Equal(&exp) {
   473  			t.Errorf("%d: Or(%q, %q) actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual,
   474  				testCase.exp)
   475  		}
   476  	}
   477  }
   478  
   479  func TestAdd(t *testing.T) {
   480  	testCases := []struct {
   481  		s   string
   482  		i   int64
   483  		exp string
   484  	}{
   485  		{"0.0.0.0", 4294967295, "255.255.255.255"},
   486  		{"255.255.255.255", -4294967295, "0.0.0.0"},
   487  		{"192.168.1.2", 184836468, "203.172.98.118"},
   488  		{"192.168.1.2/17", 184836468, "203.172.98.118/17"},
   489  		{"::ffff:192.168.1.2", 4684658846864486648, "::4104:4066:5de7:b1fa"},
   490  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", -9223372036854775807, "ffff:ffff:ffff:ffff:8000::"},
   491  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", -9223372036854775808, "ffff:ffff:ffff:ffff:7fff:ffff:ffff:ffff"},
   492  		{"ffff:ffff:ffff:ffff:8000::/99", 9223372036854775807, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/99"},
   493  		{"0:0:0:0000:8000:0:0:0", math.MinInt64, "::"},
   494  		{"8000:0000:0000:0000:0000:0000:0000:0005/68", -5, "8000::/68"},
   495  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005/7", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:000f/7"},
   496  		{"::5/68", -5, "::/68"},
   497  		{"::5/68", 5, "::a/68"},
   498  	}
   499  	for i, testCase := range testCases {
   500  		var ip1, exp IPAddr
   501  		if err := ParseINet(testCase.s, &ip1); err != nil {
   502  			t.Fatalf("%d: Bad test input s:%s", i, testCase.s)
   503  		}
   504  		if err := ParseINet(testCase.exp, &exp); err != nil {
   505  			t.Fatalf("%d: Bad test input exp:%s", i, testCase.exp)
   506  		}
   507  
   508  		actual, err := ip1.Add(testCase.i)
   509  		if err != nil {
   510  			t.Fatalf("%d: Bad test input s:%s + i:%d", i, testCase.s, testCase.i)
   511  		}
   512  		if !actual.Equal(&exp) {
   513  			t.Errorf("%d: %q + %d actual:%v does not match expected:%v", i, testCase.s, testCase.i, actual,
   514  				testCase.exp)
   515  		}
   516  	}
   517  
   518  	errTestCases := []struct {
   519  		s string
   520  		i int64
   521  	}{
   522  		{"0.0.0.0", 4294967296},
   523  		{"255.255.255.255", -4294967296},
   524  		{"192.168.1.2", 1848364646486484868},
   525  		{"192.168.1.2/17", -18483646544568},
   526  		{"::ffff:192.168.1.2", -4684658846864486648},
   527  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 9223372036854775807},
   528  		{"ffff:ffff:ffff:ffff:8000:0000:0000:0001/99", 9223372036854775807},
   529  		{"0:0:0:0:7fff:ffff:ffff:ffff", -9223372036854775808},
   530  		{"0:0:0:0:7fff:ffff:ffff:ffff/48", -9223372036854775808},
   531  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 1},
   532  		{"0:0:0:0000:0800:0:0:0", math.MinInt64},
   533  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005/7", 4484545610},
   534  		{"::5/68", -6},
   535  	}
   536  	for i, errTestCase := range errTestCases {
   537  		var ip1 IPAddr
   538  		if err := ParseINet(errTestCase.s, &ip1); err != nil {
   539  			t.Fatalf("%d: Bad test input s:%s", i, errTestCase.s)
   540  		}
   541  
   542  		actual, err1 := ip1.Add(errTestCase.i)
   543  		if err1 == nil {
   544  			t.Fatalf("%d: s:%s + i:%d should return Error, but return valid INet value: %v", i, errTestCase.s, errTestCase.i, actual)
   545  		}
   546  	}
   547  }
   548  
   549  func TestSub(t *testing.T) {
   550  	testCases := []struct {
   551  		s   string
   552  		i   int64
   553  		exp string
   554  	}{
   555  		{"0.0.0.0", -4294967295, "255.255.255.255"},
   556  		{"255.255.255.255", 4294967295, "0.0.0.0"},
   557  		{"192.168.1.2", -184836468, "203.172.98.118"},
   558  		{"203.172.98.118/30", 184836468, "192.168.1.2/30"},
   559  		{"::4104:4066:5de7:b1fa", 4684658846864486648, "::ffff:192.168.1.2"},
   560  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 9223372036854775807, "ffff:ffff:ffff:ffff:8000::"},
   561  		{"ffff:ffff:ffff:ffff:7fff:ffff:ffff:ffff", -9223372036854775808, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"},
   562  		{"ffff:ffff:ffff:ffff:8000::/1", -9223372036854775807, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/1"},
   563  		{"0:0:0:0000:8000:0:0:0", math.MinInt64, "0:0:0:0001::"},
   564  		{"8000:0000:0000:0000:0000:0000:0000:0005/68", 5, "8000::/68"},
   565  		{"::5/128", 5, "::"},
   566  		{"::5/0", -5, "::a/0"},
   567  	}
   568  	for i, testCase := range testCases {
   569  		var ip1, exp IPAddr
   570  		if err := ParseINet(testCase.s, &ip1); err != nil {
   571  			t.Fatalf("%d: Bad test input s:%s", i, testCase.s)
   572  		}
   573  		if err := ParseINet(testCase.exp, &exp); err != nil {
   574  			t.Fatalf("%d: Bad test input exp:%s", i, testCase.exp)
   575  		}
   576  
   577  		actual, err := ip1.Sub(testCase.i)
   578  		if err != nil {
   579  			t.Fatalf("%d: Bad test input s:%s + i:%d", i, testCase.s, testCase.i)
   580  		}
   581  		if !actual.Equal(&exp) {
   582  			t.Errorf("%d: %q - %d actual:%v does not match expected:%v", i, testCase.s, testCase.i, actual,
   583  				testCase.exp)
   584  		}
   585  	}
   586  }
   587  
   588  func TestContains(t *testing.T) {
   589  	testCases := []struct {
   590  		s1  string
   591  		s2  string
   592  		exp bool
   593  	}{
   594  		{"192.168.162.1", "192.168.162.1", false},
   595  		{"192.168.162.1/20", "192.168.162.1", true},
   596  
   597  		{"192.168.200.95", "192.168.162.1", false},
   598  		{"192.168.200.95/8", "192.168.162.1", true},
   599  		{"192.168.200.95/16", "192.168.162.1", true},
   600  		{"192.168.200.95/17", "192.168.162.1", true},
   601  		{"192.168.200.95/18", "192.168.162.1", false},
   602  		{"192.168.200.95/24", "192.168.162.1", false},
   603  		{"192.168.200.95/32", "192.168.162.1", false},
   604  
   605  		{"192.168.200.95", "192.168.2.1/24", false},
   606  		{"192.168.200.95/8", "192.168.2.1/24", true},
   607  		{"192.168.200.95/16", "192.168.2.1/24", true},
   608  		{"192.168.200.95/17", "192.168.2.1/24", false},
   609  		{"192.168.200.95/18", "192.168.2.1/24", false},
   610  		{"192.168.200.95/24", "192.168.2.1/24", false},
   611  		{"192.168.200.95/32", "192.168.2.1/24", false},
   612  
   613  		{"192.168.200.95", "192.168.2.1/8", false},
   614  		{"192.168.200.95/8", "192.168.2.1/8", false},
   615  		{"192.168.200.95/16", "192.168.2.1/8", false},
   616  		{"192.168.200.95/17", "192.168.2.1/8", false},
   617  		{"192.168.200.95/18", "192.168.2.1/8", false},
   618  		{"192.168.200.95/24", "192.168.2.1/8", false},
   619  		{"192.168.200.95/32", "192.168.2.1/8", false},
   620  		{"2001:0db8:0500:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false},
   621  		{"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", true},
   622  		{"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0500:5000:0000:0001/50", false},
   623  	}
   624  	for i, testCase := range testCases {
   625  		var ip1, ip2 IPAddr
   626  		if err := ParseINet(testCase.s1, &ip1); err != nil {
   627  			t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1)
   628  		}
   629  		if err := ParseINet(testCase.s2, &ip2); err != nil {
   630  			t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2)
   631  		}
   632  
   633  		actual := ip1.Contains(&ip2)
   634  
   635  		if actual != testCase.exp {
   636  			t.Errorf("%d: %q >> %q actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual,
   637  				testCase.exp)
   638  		}
   639  	}
   640  }
   641  
   642  func TestContainsOrEquals(t *testing.T) {
   643  	testCases := []struct {
   644  		s1  string
   645  		s2  string
   646  		exp bool
   647  	}{
   648  		{"192.168.162.1", "192.168.162.1", true},
   649  		{"192.168.162.1/20", "192.168.162.1", true},
   650  
   651  		{"192.168.200.95", "192.168.162.1", false},
   652  		{"192.168.200.95/8", "192.168.162.1", true},
   653  		{"192.168.200.95/16", "192.168.162.1", true},
   654  		{"192.168.200.95/17", "192.168.162.1", true},
   655  		{"192.168.200.95/18", "192.168.162.1", false},
   656  		{"192.168.200.95/24", "192.168.162.1", false},
   657  		{"192.168.200.95/32", "192.168.162.1", false},
   658  
   659  		{"192.168.200.95", "192.168.2.1/24", false},
   660  		{"192.168.200.95/8", "192.168.2.1/24", true},
   661  		{"192.168.200.95/16", "192.168.2.1/24", true},
   662  		{"192.168.200.95/17", "192.168.2.1/24", false},
   663  		{"192.168.200.95/18", "192.168.2.1/24", false},
   664  		{"192.168.200.95/24", "192.168.2.1/24", false},
   665  		{"192.168.200.95/32", "192.168.2.1/24", false},
   666  
   667  		{"192.168.200.95", "192.168.2.1/8", false},
   668  		{"192.168.200.95/8", "192.168.2.1/8", true},
   669  		{"192.168.200.95/16", "192.168.2.1/8", false},
   670  		{"192.168.200.95/17", "192.168.2.1/8", false},
   671  		{"192.168.200.95/18", "192.168.2.1/8", false},
   672  		{"192.168.200.95/24", "192.168.2.1/8", false},
   673  		{"192.168.200.95/32", "192.168.2.1/8", false},
   674  		{"2001:0db8:0500:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false},
   675  		{"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", true},
   676  		{"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0500:5000:0000:0001/50", true},
   677  	}
   678  	for i, testCase := range testCases {
   679  		var ip1, ip2 IPAddr
   680  		if err := ParseINet(testCase.s1, &ip1); err != nil {
   681  			t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1)
   682  		}
   683  		if err := ParseINet(testCase.s2, &ip2); err != nil {
   684  			t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2)
   685  		}
   686  
   687  		actual := ip1.ContainsOrEquals(&ip2)
   688  
   689  		if actual != testCase.exp {
   690  			t.Errorf("%d: %q >>= %q actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual,
   691  				testCase.exp)
   692  		}
   693  	}
   694  }
   695  
   696  func TestContainedBy(t *testing.T) {
   697  	testCases := []struct {
   698  		s1  string
   699  		s2  string
   700  		exp bool
   701  	}{
   702  		{"192.168.162.1", "192.168.162.1", false},
   703  		{"192.168.162.1/20", "192.168.162.1", false},
   704  
   705  		{"192.168.200.95", "192.168.162.1", false},
   706  		{"192.168.200.95/8", "192.168.162.1", false},
   707  		{"192.168.200.95/16", "192.168.162.1", false},
   708  		{"192.168.200.95/17", "192.168.162.1", false},
   709  		{"192.168.200.95/18", "192.168.162.1", false},
   710  		{"192.168.200.95/24", "192.168.162.1", false},
   711  		{"192.168.200.95/32", "192.168.162.1", false},
   712  
   713  		{"192.168.200.95", "192.168.2.1/24", false},
   714  		{"192.168.200.95/8", "192.168.2.1/24", false},
   715  		{"192.168.200.95/16", "192.168.2.1/24", false},
   716  		{"192.168.200.95/17", "192.168.2.1/24", false},
   717  		{"192.168.200.95/18", "192.168.2.1/24", false},
   718  		{"192.168.200.95/24", "192.168.2.1/24", false},
   719  		{"192.168.200.95/32", "192.168.2.1/24", false},
   720  
   721  		{"192.168.200.95", "192.168.2.1/8", true},
   722  		{"192.168.200.95/8", "192.168.2.1/8", false},
   723  		{"192.168.200.95/16", "192.168.2.1/8", true},
   724  		{"192.168.200.95/17", "192.168.2.1/8", true},
   725  		{"192.168.200.95/18", "192.168.2.1/8", true},
   726  		{"192.168.200.95/24", "192.168.2.1/8", true},
   727  		{"192.168.200.95/32", "192.168.2.1/8", true},
   728  		{"2001:0db8:0500:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false},
   729  		{"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false},
   730  		{"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0500:5000:0000:0001/50", false},
   731  	}
   732  	for i, testCase := range testCases {
   733  		var ip1, ip2 IPAddr
   734  		if err := ParseINet(testCase.s1, &ip1); err != nil {
   735  			t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1)
   736  		}
   737  		if err := ParseINet(testCase.s2, &ip2); err != nil {
   738  			t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2)
   739  		}
   740  
   741  		actual := ip1.ContainedBy(&ip2)
   742  
   743  		if actual != testCase.exp {
   744  			t.Errorf("%d: %q << %q actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual,
   745  				testCase.exp)
   746  		}
   747  	}
   748  }
   749  
   750  func TestContainedByOrEquals(t *testing.T) {
   751  	testCases := []struct {
   752  		s1  string
   753  		s2  string
   754  		exp bool
   755  	}{
   756  		{"192.168.162.1", "192.168.162.1", true},
   757  		{"192.168.162.1/20", "192.168.162.1", false},
   758  
   759  		{"192.168.200.95", "192.168.162.1", false},
   760  		{"192.168.200.95/8", "192.168.162.1", false},
   761  		{"192.168.200.95/16", "192.168.162.1", false},
   762  		{"192.168.200.95/17", "192.168.162.1", false},
   763  		{"192.168.200.95/18", "192.168.162.1", false},
   764  		{"192.168.200.95/24", "192.168.162.1", false},
   765  		{"192.168.200.95/32", "192.168.162.1", false},
   766  
   767  		{"192.168.200.95", "192.168.2.1/24", false},
   768  		{"192.168.200.95/8", "192.168.2.1/24", false},
   769  		{"192.168.200.95/16", "192.168.2.1/24", false},
   770  		{"192.168.200.95/17", "192.168.2.1/24", false},
   771  		{"192.168.200.95/18", "192.168.2.1/24", false},
   772  		{"192.168.200.95/24", "192.168.2.1/24", false},
   773  		{"192.168.200.95/32", "192.168.2.1/24", false},
   774  
   775  		{"192.168.200.95", "192.168.2.1/8", true},
   776  		{"192.168.200.95/8", "192.168.2.1/8", true},
   777  		{"192.168.200.95/16", "192.168.2.1/8", true},
   778  		{"192.168.200.95/17", "192.168.2.1/8", true},
   779  		{"192.168.200.95/18", "192.168.2.1/8", true},
   780  		{"192.168.200.95/24", "192.168.2.1/8", true},
   781  		{"192.168.200.95/32", "192.168.2.1/8", true},
   782  		{"2001:0db8:0500:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false},
   783  		{"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false},
   784  		{"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0500:5000:0000:0001/50", true},
   785  	}
   786  	for i, testCase := range testCases {
   787  		var ip1, ip2 IPAddr
   788  		if err := ParseINet(testCase.s1, &ip1); err != nil {
   789  			t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1)
   790  		}
   791  		if err := ParseINet(testCase.s2, &ip2); err != nil {
   792  			t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2)
   793  		}
   794  
   795  		actual := ip1.ContainedByOrEquals(&ip2)
   796  
   797  		if actual != testCase.exp {
   798  			t.Errorf("%d: %q <<= %q actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual,
   799  				testCase.exp)
   800  		}
   801  	}
   802  }
   803  
   804  func TestContainsOrContainedBy(t *testing.T) {
   805  	testCases := []struct {
   806  		s1  string
   807  		s2  string
   808  		exp bool
   809  	}{
   810  		{"192.168.162.1", "192.168.162.1", true},
   811  		{"192.168.162.1/20", "192.168.162.1", true},
   812  
   813  		{"192.168.200.95", "192.168.162.1", false},
   814  		{"192.168.200.95/8", "192.168.162.1", true},
   815  		{"192.168.200.95/16", "192.168.162.1", true},
   816  		{"192.168.200.95/17", "192.168.162.1", true},
   817  		{"192.168.200.95/18", "192.168.162.1", false},
   818  		{"192.168.200.95/24", "192.168.162.1", false},
   819  		{"192.168.200.95/32", "192.168.162.1", false},
   820  
   821  		{"192.168.200.95", "192.168.2.1/24", false},
   822  		{"192.168.200.95/8", "192.168.2.1/24", true},
   823  		{"192.168.200.95/16", "192.168.2.1/24", true},
   824  		{"192.168.200.95/17", "192.168.2.1/24", false},
   825  		{"192.168.200.95/18", "192.168.2.1/24", false},
   826  		{"192.168.200.95/24", "192.168.2.1/24", false},
   827  		{"192.168.200.95/32", "192.168.2.1/24", false},
   828  
   829  		{"192.168.200.95", "192.168.2.1/8", true},
   830  		{"192.168.200.95/8", "192.168.2.1/8", true},
   831  		{"192.168.200.95/16", "192.168.2.1/8", true},
   832  		{"192.168.200.95/17", "192.168.2.1/8", true},
   833  		{"192.168.200.95/18", "192.168.2.1/8", true},
   834  		{"192.168.200.95/24", "192.168.2.1/8", true},
   835  		{"192.168.200.95/32", "192.168.2.1/8", true},
   836  		{"192.168.200.95/32", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false},
   837  		{"2001:0db8:0500:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", false},
   838  		{"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0000:0000:0000:0001/100", true},
   839  		{"2001:0db8:0000:0000:0500:5000:0000:0001/50", "2001:0db8:0000:0000:0500:5000:0000:0001/50", true},
   840  	}
   841  	for i, testCase := range testCases {
   842  		var ip1, ip2 IPAddr
   843  		if err := ParseINet(testCase.s1, &ip1); err != nil {
   844  			t.Fatalf("%d: Bad test input s1:%s", i, testCase.s1)
   845  		}
   846  		if err := ParseINet(testCase.s2, &ip2); err != nil {
   847  			t.Fatalf("%d: Bad test input s2:%s", i, testCase.s2)
   848  		}
   849  
   850  		actual := ip1.ContainsOrContainedBy(&ip2)
   851  
   852  		if actual != testCase.exp {
   853  			t.Errorf("%d: %q && %q actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual,
   854  				testCase.exp)
   855  		}
   856  	}
   857  }
   858  
   859  func TestSubIPAddr(t *testing.T) {
   860  	testCases := []struct {
   861  		s1  string
   862  		s2  string
   863  		exp int64
   864  	}{
   865  		{"0.0.0.0", "255.255.255.255", -4294967295},
   866  		{"255.255.255.255", "0.0.0.0", 4294967295},
   867  		{"192.168.1.2", "203.172.98.118", -184836468},
   868  		{"203.172.98.118/17", "192.168.1.2/1", 184836468},
   869  		{"::4104:4066:5de7:b1fa", "::ffff:192.168.1.2/44", 4684658846864486648},
   870  		{"ffff:ffff:ffff:ffff:8000::/7", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", -9223372036854775807},
   871  		{"ffff:ffff:ffff:ffff:7fff:ffff:ffff:ffff", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", -9223372036854775808},
   872  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/91", "ffff:ffff:ffff:ffff:8000::/99", 9223372036854775807},
   873  		{"::", "0:0:0:0000:8000:0:0:0", math.MinInt64},
   874  		{"8000::/68", "8000:0000:0000:0000:0000:0000:0000:0005/68", -5},
   875  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:000f/57", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0005/7", 10},
   876  		{"::/68", "::5/68", -5},
   877  		{"::a/68", "::5/68", 5},
   878  	}
   879  	for i, testCase := range testCases {
   880  		var ip1, ip2 IPAddr
   881  		if err := ParseINet(testCase.s1, &ip1); err != nil {
   882  			t.Fatalf("%d: Bad test input s:%s", i, testCase.s1)
   883  		}
   884  		if err := ParseINet(testCase.s2, &ip2); err != nil {
   885  			t.Fatalf("%d: Bad test input exp:%s", i, testCase.s2)
   886  		}
   887  
   888  		actual, err := ip1.SubIPAddr(&ip2)
   889  		if err != nil {
   890  			t.Fatalf("%d: Bad test input s1: %s - s2: %s", i, testCase.s1, testCase.s2)
   891  		}
   892  		if actual != testCase.exp {
   893  			t.Errorf("%d: %s - %s actual:%v does not match expected:%v", i, testCase.s1, testCase.s2, actual,
   894  				testCase.exp)
   895  		}
   896  	}
   897  
   898  	errTestCases := []struct {
   899  		s1 string
   900  		s2 string
   901  	}{
   902  		{"2323:5475:9894:8745:4104:4066:5de7:b1fa", "::ffff:192.168.1.2"},
   903  		{"ffff:ffff:ffff:ffff:7fff:ffff:ffff:fffe", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/99"},
   904  		{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/99", "ffff:ffff:ffff:ffff:7fff:ffff:ffff:ffff/91"},
   905  		{"::", "0:0:0:0000:8000:0:0:0001"},
   906  		{"0:0:0:0000:8000:0:0:0000", "::"},
   907  		{"192.168.1.2/5", "::"},
   908  		{"0:0:0:0000:8000:0:0:0000/4", "192.168.1.2"},
   909  		{"10:0:0:0000:8000:0:0:0000", "10::"},
   910  		{"10::", "10:0:0:0000:8000:0:0:0001"},
   911  	}
   912  	for i, errTestCase := range errTestCases {
   913  		var ip1, ip2 IPAddr
   914  		if err := ParseINet(errTestCase.s1, &ip1); err != nil {
   915  			t.Fatalf("%d: Bad test input s:%s", i, errTestCase.s1)
   916  		}
   917  		if err := ParseINet(errTestCase.s2, &ip2); err != nil {
   918  			t.Fatalf("%d: Bad test input s:%s", i, errTestCase.s2)
   919  		}
   920  
   921  		actual, err1 := ip1.SubIPAddr(&ip2)
   922  		if err1 == nil {
   923  			t.Fatalf("%d: s:%s - s:%s should return Error, but returns int64:%v", i, errTestCase.s1, errTestCase.s2, actual)
   924  		}
   925  	}
   926  }