1/*
2Copyright 2014 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package net
18
19import (
20	"net"
21	"reflect"
22	"sort"
23	"testing"
24)
25
26func parseIPNet(s string) *net.IPNet {
27	_, net, err := ParseCIDRSloppy(s)
28	if err != nil {
29		panic(err)
30	}
31	return net
32}
33
34func TestIPNets(t *testing.T) {
35	s := IPNetSet{}
36	s2 := IPNetSet{}
37	if len(s) != 0 {
38		t.Errorf("Expected len=0: %d", len(s))
39	}
40	a := parseIPNet("1.0.0.0/8")
41	b := parseIPNet("2.0.0.0/8")
42	c := parseIPNet("3.0.0.0/8")
43	d := parseIPNet("4.0.0.0/8")
44
45	s.Insert(a, b)
46	if len(s) != 2 {
47		t.Errorf("Expected len=2: %d", len(s))
48	}
49	s.Insert(c)
50	if s.Has(d) {
51		t.Errorf("Unexpected contents: %#v", s)
52	}
53	if !s.Has(a) {
54		t.Errorf("Missing contents: %#v", s)
55	}
56	s.Delete(a)
57	if s.Has(a) {
58		t.Errorf("Unexpected contents: %#v", s)
59	}
60	s.Insert(a)
61	if s.HasAll(a, b, d) {
62		t.Errorf("Unexpected contents: %#v", s)
63	}
64	if !s.HasAll(a, b) {
65		t.Errorf("Missing contents: %#v", s)
66	}
67	s2.Insert(a, b, d)
68	if s.IsSuperset(s2) {
69		t.Errorf("Unexpected contents: %#v", s)
70	}
71	s2.Delete(d)
72	if !s.IsSuperset(s2) {
73		t.Errorf("Missing contents: %#v", s)
74	}
75}
76
77func TestIPNetSetDeleteMultiples(t *testing.T) {
78	s := IPNetSet{}
79	a := parseIPNet("1.0.0.0/8")
80	b := parseIPNet("2.0.0.0/8")
81	c := parseIPNet("3.0.0.0/8")
82
83	s.Insert(a, b, c)
84	if len(s) != 3 {
85		t.Errorf("Expected len=3: %d", len(s))
86	}
87
88	s.Delete(a, c)
89	if len(s) != 1 {
90		t.Errorf("Expected len=1: %d", len(s))
91	}
92	if s.Has(a) {
93		t.Errorf("Unexpected contents: %#v", s)
94	}
95	if s.Has(c) {
96		t.Errorf("Unexpected contents: %#v", s)
97	}
98	if !s.Has(b) {
99		t.Errorf("Missing contents: %#v", s)
100	}
101}
102
103func TestNewIPNetSet(t *testing.T) {
104	s, err := ParseIPNets("1.0.0.0/8", "2.0.0.0/8", "3.0.0.0/8")
105	if err != nil {
106		t.Errorf("error parsing IPNets: %v", err)
107	}
108	if len(s) != 3 {
109		t.Errorf("Expected len=3: %d", len(s))
110	}
111	a := parseIPNet("1.0.0.0/8")
112	b := parseIPNet("2.0.0.0/8")
113	c := parseIPNet("3.0.0.0/8")
114
115	if !s.Has(a) || !s.Has(b) || !s.Has(c) {
116		t.Errorf("Unexpected contents: %#v", s)
117	}
118}
119
120func TestIPNetSetDifference(t *testing.T) {
121	l, err := ParseIPNets("1.0.0.0/8", "2.0.0.0/8", "3.0.0.0/8")
122	if err != nil {
123		t.Errorf("error parsing IPNets: %v", err)
124	}
125	r, err := ParseIPNets("1.0.0.0/8", "2.0.0.0/8", "4.0.0.0/8", "5.0.0.0/8")
126	if err != nil {
127		t.Errorf("error parsing IPNets: %v", err)
128	}
129	c := l.Difference(r)
130	d := r.Difference(l)
131	if len(c) != 1 {
132		t.Errorf("Expected len=1: %d", len(c))
133	}
134	if !c.Has(parseIPNet("3.0.0.0/8")) {
135		t.Errorf("Unexpected contents: %#v", c)
136	}
137	if len(d) != 2 {
138		t.Errorf("Expected len=2: %d", len(d))
139	}
140	if !d.Has(parseIPNet("4.0.0.0/8")) || !d.Has(parseIPNet("5.0.0.0/8")) {
141		t.Errorf("Unexpected contents: %#v", d)
142	}
143}
144
145func TestIPNetSetList(t *testing.T) {
146	s, err := ParseIPNets("3.0.0.0/8", "1.0.0.0/8", "2.0.0.0/8")
147	if err != nil {
148		t.Errorf("error parsing IPNets: %v", err)
149	}
150	l := s.StringSlice()
151	sort.Strings(l)
152	if !reflect.DeepEqual(l, []string{"1.0.0.0/8", "2.0.0.0/8", "3.0.0.0/8"}) {
153		t.Errorf("List gave unexpected result: %#v", l)
154	}
155}
156
157func TestIPSet(t *testing.T) {
158	s := IPSet{}
159	s2 := IPSet{}
160
161	a := ParseIPSloppy("1.0.0.0")
162	b := ParseIPSloppy("2.0.0.0")
163	c := ParseIPSloppy("3.0.0.0")
164	d := ParseIPSloppy("4.0.0.0")
165
166	s.Insert(a, b)
167	if len(s) != 2 {
168		t.Errorf("Expected len=2: %d", len(s))
169	}
170	if !s.Has(a) {
171		t.Errorf("Missing contents: %#v", s)
172	}
173
174	s.Insert(c)
175	if s.Has(d) {
176		t.Errorf("Unexpected contents: %#v", s)
177	}
178
179	s.Delete(a)
180	if s.Has(a) {
181		t.Errorf("Unexpected contents: %#v", s)
182	}
183	s.Insert(a)
184	if s.HasAll(a, b, d) {
185		t.Errorf("Unexpected contents: %#v", s)
186	}
187	if !s.HasAll(a, b) {
188		t.Errorf("Missing contents: %#v", s)
189	}
190	s2.Insert(a, b, d)
191	if s.IsSuperset(s2) {
192		t.Errorf("Unexpected contents: %#v", s)
193	}
194	s2.Delete(d)
195	if !s.IsSuperset(s2) {
196		t.Errorf("Missing contents: %#v", s)
197	}
198}
199
200func TestIPSetDeleteMultiples(t *testing.T) {
201	s := IPSet{}
202	a := ParseIPSloppy("1.0.0.0")
203	b := ParseIPSloppy("2.0.0.0")
204	c := ParseIPSloppy("3.0.0.0")
205
206	s.Insert(a, b, c)
207	if len(s) != 3 {
208		t.Errorf("Expected len=3: %d", len(s))
209	}
210
211	s.Delete(a, c)
212	if len(s) != 1 {
213		t.Errorf("Expected len=1: %d", len(s))
214	}
215	if s.Has(a) {
216		t.Errorf("Unexpected contents: %#v", s)
217	}
218	if s.Has(c) {
219		t.Errorf("Unexpected contents: %#v", s)
220	}
221	if !s.Has(b) {
222		t.Errorf("Missing contents: %#v", s)
223	}
224}
225
226func TestParseIPSet(t *testing.T) {
227	s, err := ParseIPSet("1.0.0.0", "2.0.0.0", "3.0.0.0", "::ffff:4.0.0.0")
228	if err != nil {
229		t.Errorf("error parsing IPSet: %v", err)
230	}
231	if len(s) != 4 {
232		t.Errorf("Expected len=3: %d", len(s))
233	}
234	a := ParseIPSloppy("1.0.0.0")
235	b := ParseIPSloppy("2.0.0.0")
236	c := ParseIPSloppy("3.0.0.0")
237	d := ParseIPSloppy("::ffff:4.0.0.0")
238	e := ParseIPSloppy("4.0.0.0")
239
240	if !s.Has(a) || !s.Has(b) || !s.Has(c) || !s.Has(d) || !s.Has(e) {
241		t.Errorf("Unexpected contents: %#v", s)
242	}
243}
244
245func TestIPSetDifference(t *testing.T) {
246	l, err := ParseIPSet("1.0.0.0", "2.0.0.0", "3.0.0.0")
247	if err != nil {
248		t.Errorf("error parsing IPSet: %v", err)
249	}
250	r, err := ParseIPSet("1.0.0.0", "2.0.0.0", "4.0.0.0", "5.0.0.0")
251	if err != nil {
252		t.Errorf("error parsing IPSet: %v", err)
253	}
254	c := l.Difference(r)
255	d := r.Difference(l)
256	if len(c) != 1 {
257		t.Errorf("Expected len=1: %d", len(c))
258	}
259	if !c.Has(ParseIPSloppy("3.0.0.0")) {
260		t.Errorf("Unexpected contents: %#v", c)
261	}
262	if len(d) != 2 {
263		t.Errorf("Expected len=2: %d", len(d))
264	}
265	if !d.Has(ParseIPSloppy("4.0.0.0")) || !d.Has(ParseIPSloppy("5.0.0.0")) {
266		t.Errorf("Unexpected contents: %#v", d)
267	}
268}
269
270func TestIPSetList(t *testing.T) {
271	// NOTE: IPv4-in-IPv6 addresses are represented as IPv4 in its string value
272	s, err := ParseIPSet("3.0.0.0", "1.0.0.0", "2.0.0.0", "::ffff:1.2.3.4")
273	if err != nil {
274		t.Errorf("error parsing IPSet: %v", err)
275	}
276
277	l := s.StringSlice()
278	sort.Strings(l)
279	if !reflect.DeepEqual(l, []string{"1.0.0.0", "1.2.3.4", "2.0.0.0", "3.0.0.0"}) {
280		t.Errorf("List gave unexpected result: %#v", l)
281	}
282}
283
284func TestIPSetEqual(t *testing.T) {
285	// IPv4-in-IPv6 addresses are equal to their IPv4 equivalents
286	set1, err := ParseIPSet("1.0.0.0", "2.0.0.0", "3.0.0.0", "::ffff:4.0.0.0")
287	if err != nil {
288		t.Errorf("error parsing IPSet: %v", err)
289	}
290
291	set2, err := ParseIPSet("1.0.0.0", "2.0.0.0", "3.0.0.0", "4.0.0.0")
292	if err != nil {
293		t.Errorf("error parsing IPSet: %v", err)
294	}
295
296	if !set1.Equal(set2) {
297		t.Errorf("sets %v and %v are not equal", set1, set2)
298	}
299
300	// order shouldn't matter
301	set1, err = ParseIPSet("1.0.0.0", "2.0.0.0", "3.0.0.0")
302	if err != nil {
303		t.Errorf("error parsing IPSet: %v", err)
304	}
305
306	set2, err = ParseIPSet("3.0.0.0", "1.0.0.0", "2.0.0.0")
307	if err != nil {
308		t.Errorf("error parsing IPSet: %v", err)
309	}
310
311	if !set1.Equal(set2) {
312		t.Errorf("sets %v and %v are not equal", set1, set2)
313	}
314}
315