/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ package netaddr_test import ( "bytes" "sort" "testing" . "idiolink/go/netaddr" ) func TestIPParsesCIDR(t *testing.T) { actual, _ := IP("192.0.2.0/24") expected := &NetAddr{Address: []byte{192, 0, 2, 0}, Length: byte(24)} if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPParsesTruncatedPrefix(t *testing.T) { actual, err := IP("192.0.2/24") if err != nil { t.Errorf("failed to parse input: %v", err) return } expected := &NetAddr{Address: []byte{192, 0, 2, 0}, Length: byte(24)} if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPParsesOtherTruncatedPrefix(t *testing.T) { actual, err := IP("0/0") if err != nil { t.Errorf("failed to parse input: %v", err) return } expected := &NetAddr{Address: []byte{0, 0, 0, 0}, Length: byte(0)} if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPParsesAnotherTruncatedPrefix(t *testing.T) { actual, err := IP("0/8") if err != nil { t.Errorf("failed to parse input: %v", err) return } expected := &NetAddr{Address: []byte{0, 0, 0, 0}, Length: byte(8)} if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPParsesYetAnotherTruncatedPrefix(t *testing.T) { actual, err := IP("0/32") if err != nil { t.Errorf("failed to parse input: %v", err) return } expected := &NetAddr{Address: []byte{0, 0, 0, 0}, Length: byte(32)} if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPParsesStillAnotherTruncatedPrefix(t *testing.T) { actual, err := IP("10/8") if err != nil { t.Errorf("failed to parse input: %v", err) return } expected := &NetAddr{Address: []byte{10, 0, 0, 0}, Length: byte(8)} if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPParsesIPv4AddressWithContext(t *testing.T) { actual, _ := IP("192.0.2.1/24") expected := &NetAddr{Address: []byte{192, 0, 2, 1}, Length: byte(24)} if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPParsesIPv4AddressWithoutContext(t *testing.T) { actual, _ := IP("192.0.2.1") expected := &NetAddr{Address: []byte{192, 0, 2, 1}, Length: byte(32)} if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPParsesOtherIPv4AddressWithoutContext(t *testing.T) { actual, err := IP("172.31.254.5") if err != nil { t.Errorf("got error: %v", err) return } expected := &NetAddr{Address: []byte{172, 31, 254, 5}, Length: byte(32)} if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPParsesIPv6AddressWithContext(t *testing.T) { actual, _ := IP("2001:db8::1/64") expected := &NetAddr{ Address: []byte{ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, Length: byte(64), } if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPParsesIPv6AddressWithoutContext(t *testing.T) { actual, _ := IP("2001:db8::1") expected := &NetAddr{ Address: []byte{ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, Length: byte(128), } if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIPFailsToParseJunk(t *testing.T) { _, err := IP("256.0.0.0") if err == nil { t.Error("Expected error but got nil") } } func TestIPFailsToParseOtherJunk(t *testing.T) { _, err := IP("255.0.0.0.0") if err == nil { t.Error("Expected error but got nil") } } func TestContainsIsNotStrict(t *testing.T) { na, _ := IP("192.0.2.0/24") actual := Contains(na, na) expected := true if actual != expected { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestContainsReturnsTrue(t *testing.T) { na1, _ := IP("192.0.2.0/24") na2, _ := IP("192.0.2.0/25") actual := Contains(na1, na2) expected := true if actual != expected { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestContainsReturnsFalseOnShorterLen(t *testing.T) { na1, _ := IP("192.0.2.0/24") na2, _ := IP("192.0.2.0/25") actual := Contains(na2, na1) expected := false if actual != expected { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestContainsReturnsFalseOnAdjacent(t *testing.T) { na1, _ := IP("192.0.2.0/25") na2, _ := IP("192.0.2.128/25") actual := Contains(na1, na2) expected := false if actual != expected { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIsSubsetIsNotStrict(t *testing.T) { na, _ := IP("192.0.2.0/24") actual := IsSubset(na, na) expected := true if actual != expected { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIsSubsetReturnsTrue(t *testing.T) { na1, _ := IP("192.0.2.0/24") na2, _ := IP("192.0.2.0/25") actual := IsSubset(na2, na1) expected := true if actual != expected { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIsSubsetReturnsFalseOnShorterLen(t *testing.T) { na1, _ := IP("192.0.2.0/24") na2, _ := IP("192.0.2.0/25") actual := IsSubset(na1, na2) expected := false if actual != expected { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestIsSubsetReturnsFalseOnAdjacent(t *testing.T) { na1, _ := IP("192.0.2.0/25") na2, _ := IP("192.0.2.128/25") actual := IsSubset(na2, na1) expected := false if actual != expected { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestFirstAddressWorks(t *testing.T) { na, _ := IP("192.0.2.127/27") actual := na.FirstAddress() expected := &NetAddr{ Address: []byte{192, 0, 2, 96}, Length: byte(27), } if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestLastAddressWorks(t *testing.T) { na, _ := IP("192.0.2.96/27") actual := na.LastAddress() expected := &NetAddr{ Address: []byte{192, 0, 2, 127}, Length: byte(27), } if !IsEqual(actual, expected) { t.Errorf("Expected %+v but got %+v", expected, actual) } } func TestStringWorksForIPv4(t *testing.T) { expected := "192.0.2.1/24" na, _ := IP(expected) actual := na.String() if actual != expected { t.Errorf("Expected %+v but got %v", expected, actual) } } func TestStringWorksForIPv6(t *testing.T) { expected := "fe80::1/64" na, _ := IP(expected) actual := na.String() if actual != expected { t.Errorf("Expected %+v but got %v", expected, actual) } } func TestIsRFC1918DetectsPrivate(t *testing.T) { expected := true na, _ := IP("10.255.255.255/32") actual := na.IsRFC1918() if actual != expected { t.Errorf("Expected %+v but got %v", expected, actual) } } func TestIsRFC1918DetectsOtherPrivate(t *testing.T) { expected := true na, _ := IP("172.31.255.255/32") actual := na.IsRFC1918() if actual != expected { t.Errorf("Expected %+v but got %v", expected, actual) } } func TestIsRFC1918DetectsYetAnotherPrivate(t *testing.T) { expected := true na, _ := IP("192.168.255.255/32") actual := na.IsRFC1918() if actual != expected { t.Errorf("Expected %+v but got %v", expected, actual) } } func TestIsRFC1918DetectsNonPrivates(t *testing.T) { expected := false na, _ := IP("192.0.2.133/27") actual := na.IsRFC1918() if actual != expected { t.Errorf("Expected %+v but got %v", expected, actual) } } func TestMaskGeneratesCorrectMasks(t *testing.T) { na, _ := IP("192.0.2.0/24") expected := []byte{255, 255, 255, 0} if !bytes.Equal(na.Mask(), expected) { t.Errorf("Expected %v but got %v", expected, na.Mask()) } expected = []byte{255, 255, 255, 128} na = SetLength(na, na.Length+1) if !bytes.Equal(na.Mask(), expected) { t.Errorf("Expected %v but got %v", expected, na.Mask()) } expected = []byte{255, 255, 255, 192} na = SetLength(na, na.Length+1) if !bytes.Equal(na.Mask(), expected) { t.Errorf("Expected %v but got %v", expected, na.Mask()) } expected = []byte{255, 255, 255, 224} na = SetLength(na, na.Length+1) if !bytes.Equal(na.Mask(), expected) { t.Errorf("Expected %v but got %v", expected, na.Mask()) } expected = []byte{255, 255, 255, 240} na = SetLength(na, na.Length+1) if !bytes.Equal(na.Mask(), expected) { t.Errorf("Expected %v but got %v", expected, na.Mask()) } expected = []byte{255, 255, 255, 248} na = SetLength(na, na.Length+1) if !bytes.Equal(na.Mask(), expected) { t.Errorf("Expected %v but got %v", expected, na.Mask()) } expected = []byte{255, 255, 255, 252} na = SetLength(na, na.Length+1) if !bytes.Equal(na.Mask(), expected) { t.Errorf("Expected %v but got %v", expected, na.Mask()) } expected = []byte{255, 255, 255, 254} na = SetLength(na, na.Length+1) if !bytes.Equal(na.Mask(), expected) { t.Errorf("Expected %v but got %v", expected, na.Mask()) } expected = []byte{255, 255, 255, 255} na = SetLength(na, na.Length+1) if !bytes.Equal(na.Mask(), expected) { t.Errorf("Expected %v but got %v", expected, na.Mask()) } } func TestLessThanDoesTheObvious(t *testing.T) { na1, _ := IP("192.0.2.0/24") na2, _ := IP("192.0.2.0/25") if LessThan(na1, na2) { t.Errorf("Expected %s >= %s", na1, na2) } if !LessThan(na2, na1) { t.Errorf("Expected %s < %s", na2, na1) } na3, _ := IP("192.0.2.0/24") na4, _ := IP("198.51.100.0/24") if !LessThan(na3, na4) { t.Errorf("Expected %s < %s", na3, na4) } } func TestLessThanSortsIntegersInOrder(t *testing.T) { cnt := 257 prefixes := make([]*NetAddr, 0, cnt) for i := 0; i < cnt; i++ { o2 := i & 255 o1 := (i - o2) >> 8 na := &NetAddr{ Address: []byte{byte(o1), byte(o2)}, Length: byte(16), } prefixes = append(prefixes, na) } sort.Slice(prefixes, func(i, j int) bool { return LessThan(prefixes[i], prefixes[j]) }) for i, p := range prefixes { o2 := i & 255 o1 := (i - o2) >> 8 na := &NetAddr{ Address: []byte{byte(o1), byte(o2)}, Length: byte(16), } dec := int(p.Address[0])<<8 + int(p.Address[1]) if i != dec { t.Errorf("Expected %d (%s) == %d (%s)", i, na, dec, p) } } } func TestOverlapsDoesTheObvious(t *testing.T) { na1, _ := IP("192.0.2.0/24") na2, _ := IP("192.0.2.0/25") if !Overlaps(na1, na2) { t.Errorf("Expected %s to overlap %s", na1, na2) } if !Overlaps(na2, na1) { t.Errorf("Expected %s to overlap %s", na2, na1) } na3, _ := IP("192.0.2.128/25") if Overlaps(na2, na3) { t.Errorf("Expected %s to not overlap %s", na2, na3) } if Overlaps(na3, na2) { t.Errorf("Expected %s to not overlap %s", na3, na2) } }