Skip to content

Commit 9d77f34

Browse files
Merge pull request #51 from bschaatsbergen/add-tests
Add core pkg tests
2 parents 38aceac + 6ce3ec4 commit 9d77f34

File tree

6 files changed

+210
-9
lines changed

6 files changed

+210
-9
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ This also works with a IPv6 CIDR range, for example:
4848

4949
```
5050
$ cidr count 2001:db8:1234:1a00::/106
51-
4194304
51+
4194302
5252
```
5353

5454
Or with a large prefix like a point-to-point link CIDR range:

cmd/contains.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ var (
3434
fmt.Println("See 'cidr contains -h' for help and examples")
3535
os.Exit(1)
3636
}
37-
ip := core.ParseIP(args[1])
37+
ip := net.ParseIP(args[1])
3838
if ip == nil {
3939
fmt.Printf("error: invalid IP address: %s\n", args[1])
4040
fmt.Println("See 'cidr contains -h' for help and examples")

go.mod

+7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@ go 1.19
44

55
require github.com/spf13/cobra v1.5.0
66

7+
require (
8+
github.com/davecgh/go-spew v1.1.1 // indirect
9+
github.com/pmezard/go-difflib v1.0.0 // indirect
10+
gopkg.in/yaml.v3 v3.0.1 // indirect
11+
)
12+
713
require (
814
github.com/inconshreveable/mousetrap v1.0.0 // indirect
915
github.com/spf13/pflag v1.0.5 // indirect
16+
github.com/stretchr/testify v1.8.0
1017
)

go.sum

+13
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
25
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
36
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
7+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
8+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
49
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
510
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
611
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
712
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
813
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
14+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
15+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
16+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
17+
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
18+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
919
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1020
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
21+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
22+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
23+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

pkg/core/core.go

+5-7
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ func AddressCount(network *net.IPNet) uint64 {
1111
if network.Mask != nil {
1212
// Handle edge cases
1313
switch prefixLen {
14-
case 32: return 1
15-
case 31: return 2
14+
case 32:
15+
return 1
16+
case 31:
17+
return 2
1618
}
1719
}
1820

1921
// Remember to subtract the network address and broadcast address
20-
return 1 << (uint64(bits) - uint64(prefixLen)) - 2
22+
return 1<<(uint64(bits)-uint64(prefixLen)) - 2
2123
}
2224

2325
func ParseCIDR(network string) (*net.IPNet, error) {
@@ -28,10 +30,6 @@ func ParseCIDR(network string) (*net.IPNet, error) {
2830
return ip, err
2931
}
3032

31-
func ParseIP(ip string) net.IP {
32-
return net.ParseIP(ip)
33-
}
34-
3533
func ContainsAddress(network *net.IPNet, ip net.IP) bool {
3634
return network.Contains(ip)
3735
}

pkg/core/core_test.go

+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package core
2+
3+
import (
4+
"net"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestAddressCount(t *testing.T) {
11+
IPv4CIDR, err := ParseCIDR("10.0.0.0/16")
12+
if err != nil {
13+
t.Log(err)
14+
t.Fail()
15+
}
16+
17+
IPv6CIDR, err := ParseCIDR("2001:db8:1234:1a00::/106")
18+
if err != nil {
19+
t.Log(err)
20+
t.Fail()
21+
}
22+
23+
largeIPv4PrefixCIDR, err := ParseCIDR("172.16.18.0/31")
24+
if err != nil {
25+
t.Log(err)
26+
t.Fail()
27+
}
28+
29+
largestIPv4PrefixCIDR, err := ParseCIDR("172.16.18.0/32")
30+
if err != nil {
31+
t.Log(err)
32+
t.Fail()
33+
}
34+
35+
tests := []struct {
36+
name string
37+
cidr *net.IPNet
38+
expectedCount uint64
39+
}{
40+
{
41+
name: "Return the count of all distinct host addresses in a common IPv4 CIDR",
42+
cidr: IPv4CIDR,
43+
expectedCount: 65534,
44+
},
45+
{
46+
name: "Return the count of all distinct host addresses in a common IPv6 CIDR",
47+
cidr: IPv6CIDR,
48+
expectedCount: 4194302,
49+
},
50+
{
51+
name: "Return the count of all distinct host addresses in an uncommon (large prefix) IPv4 CIDR",
52+
cidr: largeIPv4PrefixCIDR,
53+
expectedCount: 2,
54+
},
55+
{
56+
name: "Return the count of all distinct host addresses in an uncommon (largest prefix) IPv4 CIDR",
57+
cidr: largestIPv4PrefixCIDR,
58+
expectedCount: 1,
59+
},
60+
}
61+
for _, tt := range tests {
62+
t.Run(tt.name, func(t *testing.T) {
63+
count := AddressCount(tt.cidr)
64+
assert.Equal(t, int(tt.expectedCount), int(count), "Both address counts should be equal")
65+
})
66+
}
67+
}
68+
69+
func TestOverlaps(t *testing.T) {
70+
firstIPv4CIDR, err := ParseCIDR("10.0.0.0/16")
71+
if err != nil {
72+
t.Log(err)
73+
t.Fail()
74+
}
75+
76+
secondIPv4CIDR, err := ParseCIDR("10.0.14.0/22")
77+
if err != nil {
78+
t.Log(err)
79+
t.Fail()
80+
}
81+
82+
thirdIPv4CIDR, err := ParseCIDR("10.1.0.0/28")
83+
if err != nil {
84+
t.Log(err)
85+
t.Fail()
86+
}
87+
88+
firstIPv6CIDR, err := ParseCIDR("2001:db8:1111:2222:1::/80")
89+
if err != nil {
90+
t.Log(err)
91+
t.Fail()
92+
}
93+
94+
secondIPv6CIDR, err := ParseCIDR("2001:db8:1111:2222:1:1::/96")
95+
if err != nil {
96+
t.Log(err)
97+
t.Fail()
98+
}
99+
100+
tests := []struct {
101+
name string
102+
cidrA *net.IPNet
103+
cidrB *net.IPNet
104+
overlaps bool
105+
}{
106+
{
107+
name: "2 IPv4 CIDR ranges should overlap",
108+
cidrA: firstIPv4CIDR,
109+
cidrB: secondIPv4CIDR,
110+
overlaps: true,
111+
},
112+
{
113+
name: "2 IPv4 CIDR ranges should NOT overlap",
114+
cidrA: firstIPv4CIDR,
115+
cidrB: thirdIPv4CIDR,
116+
overlaps: false,
117+
},
118+
{
119+
name: "2 IPv6 CIDR ranges should overlap",
120+
cidrA: firstIPv6CIDR,
121+
cidrB: secondIPv6CIDR,
122+
overlaps: true,
123+
},
124+
}
125+
for _, tt := range tests {
126+
t.Run(tt.name, func(t *testing.T) {
127+
overlaps := Overlaps(tt.cidrA, tt.cidrB)
128+
assert.Equal(t, tt.overlaps, overlaps, "Given CIDRs should overlap")
129+
})
130+
}
131+
}
132+
133+
func TestContainsAddress(t *testing.T) {
134+
IPv4CIDR, err := ParseCIDR("10.0.0.0/16")
135+
if err != nil {
136+
t.Log(err)
137+
t.Fail()
138+
}
139+
140+
IPv6CIDR, err := ParseCIDR("2001:db8:1234:1a00::/106")
141+
if err != nil {
142+
t.Log(err)
143+
t.Fail()
144+
}
145+
146+
tests := []struct {
147+
name string
148+
cidr *net.IPNet
149+
ip net.IP
150+
contains bool
151+
}{
152+
{
153+
name: "IPv4 CIDR that does contain an IPv4 IP",
154+
cidr: IPv4CIDR,
155+
ip: net.ParseIP("10.0.14.5"),
156+
contains: true,
157+
},
158+
{
159+
name: "IPv4 CIDR that does NOT contain an IPv4 IP",
160+
cidr: IPv4CIDR,
161+
ip: net.ParseIP("10.1.55.5"),
162+
contains: false,
163+
},
164+
{
165+
name: "IPv6 CIDR that does contain an IPv6 IP",
166+
cidr: IPv6CIDR,
167+
ip: net.ParseIP("2001:db8:1234:1a00::"),
168+
contains: true,
169+
},
170+
{
171+
name: "IPv6 CIDR that does NOT contain an IPv6 IP",
172+
cidr: IPv6CIDR,
173+
ip: net.ParseIP("2001:af1:1222:1a20::"),
174+
contains: false,
175+
},
176+
}
177+
for _, tt := range tests {
178+
t.Run(tt.name, func(t *testing.T) {
179+
overlaps := ContainsAddress(tt.cidr, tt.ip)
180+
assert.Equal(t, tt.contains, overlaps, "Given IP address should be part of the given CIDR")
181+
})
182+
}
183+
}

0 commit comments

Comments
 (0)