From 3b7d6fe6fd192dac55eff9019e360d2887976adb Mon Sep 17 00:00:00 2001 From: Carl Baldwin Date: Tue, 4 Jun 2024 17:34:02 -0600 Subject: [PATCH 1/5] build tests before attempting to run them --- .gitignore | 1 + Makefile | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9ed3b07 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.test diff --git a/Makefile b/Makefile index c012fce..4052254 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,13 @@ -all: test vet fmt +all: build test vet fmt + +build: + go build ./... +.PHONY: build test: + go test -c ./ip + go test -c ./ipv4 + go test -c ./ipv6 go test -v ./... .PHONY: test From ac52b8be9df1b22c003abe0292990920364b7cd6 Mon Sep 17 00:00:00 2001 From: Carl Baldwin Date: Tue, 4 Jun 2024 17:46:05 -0600 Subject: [PATCH 2/5] notice a mispelling in the test error messages --- ipv4/address_test.go | 2 +- ipv4/mask_test.go | 2 +- ipv4/prefix_test.go | 6 +++--- ipv4/range_test.go | 2 +- ipv6/address_test.go | 2 +- ipv6/mask_test.go | 2 +- ipv6/prefix_test.go | 6 +++--- ipv6/range_test.go | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ipv4/address_test.go b/ipv4/address_test.go index 6e1d017..fbec924 100644 --- a/ipv4/address_test.go +++ b/ipv4/address_test.go @@ -11,7 +11,7 @@ import ( func _a(str string) Address { addr, err := AddressFromString(str) if err != nil { - panic("only use this is happy cases") + panic("only use this in happy cases") } return addr } diff --git a/ipv4/mask_test.go b/ipv4/mask_test.go index c12b017..63de0de 100644 --- a/ipv4/mask_test.go +++ b/ipv4/mask_test.go @@ -44,7 +44,7 @@ func TestMaskLength(t *testing.T) { func _m(length int) Mask { m, err := MaskFromLength(length) if err != nil { - panic("only use this is happy cases") + panic("only use this in happy cases") } return m } diff --git a/ipv4/prefix_test.go b/ipv4/prefix_test.go index 7bfbcb6..f891297 100644 --- a/ipv4/prefix_test.go +++ b/ipv4/prefix_test.go @@ -12,7 +12,7 @@ import ( func _p(cidr string) Prefix { prefix, err := PrefixFromString(cidr) if err != nil { - panic("only use this is happy cases") + panic("only use this in happy cases") } return prefix } @@ -20,7 +20,7 @@ func _p(cidr string) Prefix { func unsafePrefixFromUint32(ip uint32, length int) Prefix { mask, err := MaskFromLength(length) if err != nil { - panic("only use this is happy cases") + panic("only use this in happy cases") } return PrefixFromAddressMask(Address{ip}, mask) } @@ -28,7 +28,7 @@ func unsafePrefixFromUint32(ip uint32, length int) Prefix { func unsafeParseNet(prefix string) *net.IPNet { ipNet, err := parseNet(prefix) if err != nil { - panic("only use this is happy cases") + panic("only use this in happy cases") } return ipNet } diff --git a/ipv4/range_test.go b/ipv4/range_test.go index 2c76da9..07e1342 100644 --- a/ipv4/range_test.go +++ b/ipv4/range_test.go @@ -9,7 +9,7 @@ import ( func _r(first, last Address) Range { r, empty := RangeFromAddresses(first, last) if empty { - panic("only use this is non-empty cases") + panic("only use this in non-empty cases") } return r } diff --git a/ipv6/address_test.go b/ipv6/address_test.go index d0dbbc3..46c8911 100644 --- a/ipv6/address_test.go +++ b/ipv6/address_test.go @@ -11,7 +11,7 @@ import ( func _a(str string) Address { addr, err := AddressFromString(str) if err != nil { - panic("only use this is happy cases") + panic("only use this in happy cases") } return addr } diff --git a/ipv6/mask_test.go b/ipv6/mask_test.go index d6be7fd..c89b1ec 100644 --- a/ipv6/mask_test.go +++ b/ipv6/mask_test.go @@ -47,7 +47,7 @@ func TestMaskLength(t *testing.T) { func _m(length int) Mask { m, err := MaskFromLength(length) if err != nil { - panic("only use this is happy cases") + panic("only use this in happy cases") } return m } diff --git a/ipv6/prefix_test.go b/ipv6/prefix_test.go index c9c4844..b921ff8 100644 --- a/ipv6/prefix_test.go +++ b/ipv6/prefix_test.go @@ -12,7 +12,7 @@ import ( func _p(cidr string) Prefix { prefix, err := PrefixFromString(cidr) if err != nil { - panic("only use this is happy cases") + panic("only use this in happy cases") } return prefix } @@ -20,7 +20,7 @@ func _p(cidr string) Prefix { func unsafePrefixFromUint64(high, low uint64, length int) Prefix { mask, err := MaskFromLength(length) if err != nil { - panic("only use this is happy cases") + panic("only use this in happy cases") } return PrefixFromAddressMask(Address{uint128{high, low}}, mask) } @@ -28,7 +28,7 @@ func unsafePrefixFromUint64(high, low uint64, length int) Prefix { func unsafeParseNet(prefix string) *net.IPNet { ipNet, err := parseNet(prefix) if err != nil { - panic("only use this is happy cases") + panic("only use this in happy cases") } return ipNet } diff --git a/ipv6/range_test.go b/ipv6/range_test.go index 74d272c..d22aca6 100644 --- a/ipv6/range_test.go +++ b/ipv6/range_test.go @@ -9,7 +9,7 @@ import ( func _r(first, last Address) Range { r, empty := RangeFromAddresses(first, last) if empty { - panic("only use this is non-empty cases") + panic("only use this in non-empty cases") } return r } From 9568b9fbf08286067d51d4d6be3654d449e324e6 Mon Sep 17 00:00:00 2001 From: Carl Baldwin Date: Tue, 4 Jun 2024 17:46:38 -0600 Subject: [PATCH 3/5] implement Range.Contains for IPv6 --- ipv6/range.go | 5 +++++ ipv6/range_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/ipv6/range.go b/ipv6/range.go index abd841b..f956533 100644 --- a/ipv6/range.go +++ b/ipv6/range.go @@ -42,6 +42,11 @@ func (me Range) String() string { return fmt.Sprintf("[%s,%s]", me.first, me.last) } +// Contains returns true iff this range entirely contains the given other range +func (me Range) Contains(other SetI) bool { + return me.Set().Contains(other) +} + // Minus returns a slice of ranges resulting from subtracting the given range // The slice will contain from 0 to 2 new ranges depending on how they overlap func (me Range) Minus(other Range) []Range { diff --git a/ipv6/range_test.go b/ipv6/range_test.go index d22aca6..a3926c4 100644 --- a/ipv6/range_test.go +++ b/ipv6/range_test.go @@ -91,6 +91,31 @@ func TestRangeFirstLast(t *testing.T) { } } +func TestRangeContains(t *testing.T) { + tests := []struct { + description string + a, b Range + }{ + { + description: "larger", + a: _p("::ffff:10.224.24.1/118").Range(), + b: _p("::ffff:10.224.26.1/120").Range(), + }, + { + description: "unaligned", + a: _r(Address{ui: uint128{low: 0xffff12345678}}, Address{ui: uint128{low: 0xffff23456789}}), + b: _p("::ffff:20.224.26.1/120").Range(), + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + assert.True(t, tt.a.Contains(tt.b)) + // If they're equal then containership goes the other way too. + assert.Equal(t, tt.a == tt.b, tt.b.Contains(tt.a)) + }) + } +} + func TestRangeMinus(t *testing.T) { tests := []struct { description string From a4e41dcda51fdc52009db00ab1e67ee146186b8f Mon Sep 17 00:00:00 2001 From: Carl Baldwin Date: Tue, 4 Jun 2024 17:50:11 -0600 Subject: [PATCH 4/5] implement build --- ipv6/set.go | 15 +++++++++++++++ ipv6/set_test.go | 10 ++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/ipv6/set.go b/ipv6/set.go index e3ccfa7..01b7c1d 100644 --- a/ipv6/set.go +++ b/ipv6/set.go @@ -30,6 +30,21 @@ func (me Set_) Set() Set { } } +// Build is a convenience method for making modifications to a set within a +// defined scope. It calls the given callback passing a modifiable clone of +// itself. The callback can make any changes to it. After it returns true, Build +// returns the fixed snapshot of the result. +// +// If the callback returns false, modifications are aborted and the original +// fixed table is returned. +func (me Set) Build(builder func(Set_) bool) Set { + s_ := me.Set_() + if builder(s_) { + return s_.Set() + } + return me +} + // mutate should be called by any method that modifies the set in any way func (me Set_) mutate(mutator func() (ok bool, newNode *setNode)) { oldNode := me.s.trie diff --git a/ipv6/set_test.go b/ipv6/set_test.go index 6342036..ad3f259 100644 --- a/ipv6/set_test.go +++ b/ipv6/set_test.go @@ -215,8 +215,14 @@ func TestSetRemoveNil(t *testing.T) { } func TestFixedSetContainsPrefix(t *testing.T) { - s := NewSet_() - s.Insert(_p("2001::/64")) + s := Set{}.Build(func(s_ Set_) bool { + s_.Insert(_p("2001::/64")) + return true + }) + s = s.Build(func(s_ Set_) bool { + s_.Insert(_p("2001:ffff::/64")) + return false + }) assert.True(t, s.Set().Contains(_p("2001::/112"))) assert.True(t, s.Set().Contains(_p("2001::1234:0/115"))) assert.True(t, s.Set().Contains(_p("2001:0:0:0:8000:0:0:0/65"))) From 0bdb33d3e9a386cb40e27fff598dde8824f85492 Mon Sep 17 00:00:00 2001 From: Carl Baldwin Date: Tue, 4 Jun 2024 17:59:40 -0600 Subject: [PATCH 5/5] add trivial implementations of IsEmpty to IPv4 --- ipv4/set.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ipv4/set.go b/ipv4/set.go index ae4fe5f..b046f4f 100644 --- a/ipv4/set.go +++ b/ipv4/set.go @@ -72,6 +72,11 @@ func (me Set_) Remove(other SetI) { }) } +// IsEmpty returns whether the number of IP addresses is equal to zero +func (me Set_) IsEmpty() bool { + return me.NumAddresses() == 0 +} + // NumAddresses returns the number of IP addresses func (me Set_) NumAddresses() int64 { if me.s == nil { @@ -186,6 +191,11 @@ func (me Set) Set() Set { return me } +// IsEmpty returns whether the number of IP addresses is equal to zero +func (me Set) IsEmpty() bool { + return me.NumAddresses() == 0 +} + // NumAddresses returns the number of IP addresses func (me Set) NumAddresses() int64 { return me.trie.NumAddresses()