Line data Source code
1 : /* test_addr_range.cpp
2 : * Copyright (c) 2011-2018 Made to Order Software Corp. All Rights Reserved
3 : *
4 : * Project: https://snapwebsites.org/project/libaddr
5 : *
6 : * Permission is hereby granted, free of charge, to any
7 : * person obtaining a copy of this software and
8 : * associated documentation files (the "Software"), to
9 : * deal in the Software without restriction, including
10 : * without limitation the rights to use, copy, modify,
11 : * merge, publish, distribute, sublicense, and/or sell
12 : * copies of the Software, and to permit persons to whom
13 : * the Software is furnished to do so, subject to the
14 : * following conditions:
15 : *
16 : * The above copyright notice and this permission notice
17 : * shall be included in all copies or substantial
18 : * portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
21 : * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22 : * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
23 : * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
24 : * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 : * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 : * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 : * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 : * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 : * SOFTWARE.
30 : */
31 :
32 : /** \file
33 : * \brief Check the addr_range class basics.
34 : *
35 : * This set of unit tests do basic verification of the range class.
36 : *
37 : * The point here is to test the range functionality and not the
38 : * addr_parser class.
39 : */
40 :
41 : #include "test_addr_main.h"
42 :
43 :
44 :
45 :
46 7 : TEST_CASE( "ipv4::range", "[ipv4]" )
47 : {
48 10 : GIVEN("addr_range()")
49 : {
50 6 : addr::addr_range range;
51 :
52 6 : SECTION("verify defaults")
53 : {
54 2 : addr::addr a;
55 :
56 1 : REQUIRE_FALSE(range.has_from());
57 1 : REQUIRE_FALSE(range.has_to());
58 1 : REQUIRE_FALSE(range.is_range());
59 1 : REQUIRE_FALSE(range.is_empty());
60 : //std::cerr << "++++++++++++++++++ " << a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT) << "\n";
61 : //std::cerr << "++++++++++++++++++ " << range.get_from().to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT) << "\n";
62 : //
63 : //struct sockaddr_in6 in6_a;
64 : //a.get_ipv6(in6_a);
65 : //std::cerr << "++++++++++++++++++ in6 --" << std::hex;
66 : //for(size_t idx(0); idx < sizeof(in6_a); ++idx)
67 : // std::cerr << " " << static_cast<int>(reinterpret_cast<char *>(&in6_a)[idx]);
68 : //std::cerr << "\n";
69 : //
70 : //struct sockaddr_in6 in6_b;
71 : //range.get_from().get_ipv6(in6_b);
72 : //std::cerr << "++++++++++++++++++ in6 --" << std::hex;
73 : //for(size_t idx(0); idx < sizeof(in6_b); ++idx)
74 : // std::cerr << " " << static_cast<int>(reinterpret_cast<char *>(&in6_b)[idx]);
75 : //std::cerr << "\n";
76 1 : REQUIRE(range.get_from() == a);
77 1 : REQUIRE(range.get_to() == a);
78 :
79 : // to use the const version of the get_from/to() functions
80 : // we have to define a const refence to range
81 : //
82 1 : auto const & r(range);
83 1 : REQUIRE(r.get_from() == a);
84 1 : REQUIRE(r.get_to() == a);
85 :
86 2 : addr::addr other;
87 1 : REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state_exception);
88 1 : REQUIRE_THROWS_AS(r.is_in(other), addr::addr_invalid_state_exception);
89 : }
90 :
91 6 : SECTION("test normal range (from <= to)")
92 : {
93 2 : addr::addr a;
94 2 : addr::addr other;
95 :
96 : // from is set to 10.0.0.1
97 1 : struct sockaddr_in fin = sockaddr_in();
98 1 : fin.sin_family = AF_INET;
99 1 : fin.sin_port = htons(rand());
100 : uint32_t faddress((10 << 24)
101 : | (0 << 16)
102 : | (0 << 8)
103 1 : | 1);
104 1 : fin.sin_addr.s_addr = htonl(faddress);
105 2 : addr::addr f;
106 1 : f.set_ipv4(fin);
107 :
108 : // from is set to 10.0.0.254
109 1 : struct sockaddr_in tin = sockaddr_in();
110 1 : tin.sin_family = AF_INET;
111 1 : tin.sin_port = htons(rand());
112 : uint32_t taddress((10 << 24)
113 : | (0 << 16)
114 : | (0 << 8)
115 1 : | 254);
116 1 : tin.sin_addr.s_addr = htonl(taddress);
117 2 : addr::addr t;
118 1 : t.set_ipv4(tin);
119 :
120 : // test defaults first
121 : //
122 1 : REQUIRE_FALSE(range.has_from());
123 1 : REQUIRE_FALSE(range.has_to());
124 1 : REQUIRE_FALSE(range.is_range());
125 1 : REQUIRE_FALSE(range.is_empty());
126 1 : REQUIRE(range.get_from() == a);
127 1 : REQUIRE(range.get_to() == a);
128 1 : auto const & r1(range);
129 1 : REQUIRE(r1.get_from() == a);
130 1 : REQUIRE(r1.get_to() == a);
131 1 : REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state_exception);
132 1 : REQUIRE_THROWS_AS(r1.is_in(other), addr::addr_invalid_state_exception);
133 1 : REQUIRE(range.match(a));
134 1 : REQUIRE_FALSE(range.match(f));
135 1 : REQUIRE_FALSE(range.match(t));
136 :
137 1 : range.set_from(f);
138 :
139 : // defined "from", test the results
140 : //
141 1 : REQUIRE(range.has_from());
142 1 : REQUIRE_FALSE(range.has_to());
143 1 : REQUIRE_FALSE(range.is_range());
144 1 : REQUIRE_FALSE(range.is_empty());
145 1 : REQUIRE(range.get_from() == f);
146 1 : REQUIRE(range.get_to() == a);
147 1 : auto const & r2(range);
148 1 : REQUIRE(r2.get_from() == f);
149 1 : REQUIRE(r2.get_to() == a);
150 1 : REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state_exception);
151 1 : REQUIRE_THROWS_AS(r2.is_in(other), addr::addr_invalid_state_exception);
152 1 : REQUIRE_FALSE(range.match(a));
153 1 : REQUIRE(range.match(f));
154 1 : REQUIRE_FALSE(range.match(t));
155 :
156 1 : range.set_to(t);
157 :
158 : // defined "to", test the results
159 : //
160 1 : REQUIRE(range.has_from());
161 1 : REQUIRE(range.has_to());
162 1 : REQUIRE(range.is_range());
163 1 : REQUIRE_FALSE(range.is_empty());
164 1 : REQUIRE(range.get_from() == f);
165 1 : REQUIRE(range.get_to() == t);
166 1 : auto const & r3(range);
167 1 : REQUIRE(r3.get_from() == f);
168 1 : REQUIRE(r3.get_to() == t);
169 1 : REQUIRE_FALSE(range.match(a));
170 1 : REQUIRE(range.match(f));
171 1 : REQUIRE(range.match(t));
172 :
173 : // IP before range
174 : {
175 1 : struct sockaddr_in bin = sockaddr_in();
176 1 : bin.sin_family = AF_INET;
177 1 : bin.sin_port = htons(rand());
178 : uint32_t baddress((10 << 24)
179 : | (0 << 16)
180 : | (0 << 8)
181 1 : | 0);
182 1 : bin.sin_addr.s_addr = htonl(baddress);
183 2 : addr::addr b;
184 1 : b.set_ipv4(bin);
185 :
186 1 : REQUIRE_FALSE(range.is_in(b));
187 : }
188 :
189 11 : for(int idx(0); idx < 10; ++idx)
190 : {
191 10 : struct sockaddr_in bin = sockaddr_in();
192 10 : bin.sin_family = AF_INET;
193 10 : bin.sin_port = htons(rand());
194 10 : uint32_t baddress(((rand() % 10) << 24)
195 10 : | ((rand() & 255) << 16)
196 10 : | ((rand() & 255) << 8)
197 10 : | (rand() & 255));
198 10 : bin.sin_addr.s_addr = htonl(baddress);
199 20 : addr::addr b;
200 10 : b.set_ipv4(bin);
201 :
202 10 : REQUIRE_FALSE(range.is_in(b));
203 : }
204 :
205 : // IP after range
206 : {
207 1 : struct sockaddr_in ain = sockaddr_in();
208 1 : ain.sin_family = AF_INET;
209 1 : ain.sin_port = htons(rand());
210 : uint32_t aaddress((10 << 24)
211 : | (0 << 16)
212 : | (0 << 8)
213 1 : | 255);
214 1 : ain.sin_addr.s_addr = htonl(aaddress);
215 2 : addr::addr after;
216 1 : after.set_ipv4(ain);
217 :
218 1 : REQUIRE_FALSE(range.is_in(after));
219 : }
220 :
221 11 : for(int idx(0); idx < 10; ++idx)
222 : {
223 10 : struct sockaddr_in ain = sockaddr_in();
224 10 : ain.sin_family = AF_INET;
225 10 : ain.sin_port = htons(rand());
226 10 : uint32_t aaddress(((rand() % (256 - 11) + 11) << 24)
227 10 : | ((rand() & 255) << 16)
228 10 : | ((rand() & 255) << 8)
229 10 : | (rand() & 255));
230 10 : ain.sin_addr.s_addr = htonl(aaddress);
231 20 : addr::addr after;
232 10 : after.set_ipv4(ain);
233 :
234 10 : REQUIRE_FALSE(range.is_in(after));
235 : }
236 :
237 : // IP in range
238 : //
239 255 : for(int idx(1); idx < 255; ++idx)
240 : {
241 254 : struct sockaddr_in iin = sockaddr_in();
242 254 : iin.sin_family = AF_INET;
243 254 : iin.sin_port = htons(rand());
244 : uint32_t iaddress((10 << 24)
245 : | (0 << 16)
246 : | (0 << 8)
247 254 : | idx);
248 254 : iin.sin_addr.s_addr = htonl(iaddress);
249 508 : addr::addr i;
250 254 : i.set_ipv4(iin);
251 :
252 254 : REQUIRE(range.is_in(i));
253 : }
254 : }
255 :
256 6 : SECTION("test empty range (from > to)")
257 : {
258 2 : addr::addr a;
259 2 : addr::addr other;
260 :
261 : // from is set to 10.0.0.254
262 1 : struct sockaddr_in fin = sockaddr_in();
263 1 : fin.sin_family = AF_INET;
264 1 : fin.sin_port = htons(rand());
265 : uint32_t faddress((10 << 24)
266 : | (0 << 16)
267 : | (0 << 8)
268 1 : | 254);
269 1 : fin.sin_addr.s_addr = htonl(faddress);
270 2 : addr::addr f;
271 1 : f.set_ipv4(fin);
272 :
273 : // from is set to 10.0.0.1
274 1 : struct sockaddr_in tin = sockaddr_in();
275 1 : tin.sin_family = AF_INET;
276 1 : tin.sin_port = htons(rand());
277 : uint32_t taddress((10 << 24)
278 : | (0 << 16)
279 : | (0 << 8)
280 1 : | 1);
281 1 : tin.sin_addr.s_addr = htonl(taddress);
282 2 : addr::addr t;
283 1 : t.set_ipv4(tin);
284 :
285 : // test defaults first
286 : //
287 1 : REQUIRE_FALSE(range.has_from());
288 1 : REQUIRE_FALSE(range.has_to());
289 1 : REQUIRE_FALSE(range.is_range());
290 1 : REQUIRE_FALSE(range.is_empty());
291 1 : REQUIRE(range.get_from() == a);
292 1 : REQUIRE(range.get_to() == a);
293 1 : auto const & r1(range);
294 1 : REQUIRE(r1.get_from() == a);
295 1 : REQUIRE(r1.get_to() == a);
296 1 : REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state_exception);
297 1 : REQUIRE_THROWS_AS(r1.is_in(other), addr::addr_invalid_state_exception);
298 1 : REQUIRE(range.match(a));
299 1 : REQUIRE_FALSE(range.match(f));
300 1 : REQUIRE_FALSE(range.match(t));
301 :
302 1 : range.set_from(f);
303 :
304 : // defined "from", test the results
305 : //
306 1 : REQUIRE(range.has_from());
307 1 : REQUIRE_FALSE(range.has_to());
308 1 : REQUIRE_FALSE(range.is_range());
309 1 : REQUIRE_FALSE(range.is_empty());
310 1 : REQUIRE(range.get_from() == f);
311 1 : REQUIRE(range.get_to() == a);
312 1 : auto const & r2(range);
313 1 : REQUIRE(r2.get_from() == f);
314 1 : REQUIRE(r2.get_to() == a);
315 1 : REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state_exception);
316 1 : REQUIRE_THROWS_AS(r2.is_in(other), addr::addr_invalid_state_exception);
317 1 : REQUIRE_FALSE(range.match(a));
318 1 : REQUIRE(range.match(f));
319 1 : REQUIRE_FALSE(range.match(t));
320 :
321 1 : range.set_to(t);
322 :
323 : // defined "to", test the results
324 : //
325 1 : REQUIRE(range.has_from());
326 1 : REQUIRE(range.has_to());
327 1 : REQUIRE(range.is_range());
328 1 : REQUIRE(range.is_empty());
329 1 : REQUIRE(range.get_from() == f);
330 1 : REQUIRE(range.get_to() == t);
331 1 : auto const & r3(range);
332 1 : REQUIRE(r3.get_from() == f);
333 1 : REQUIRE(r3.get_to() == t);
334 1 : REQUIRE_FALSE(range.match(a));
335 1 : REQUIRE_FALSE(range.match(f));
336 1 : REQUIRE_FALSE(range.match(t));
337 :
338 : // IP before range
339 : {
340 1 : struct sockaddr_in bin = sockaddr_in();
341 1 : bin.sin_family = AF_INET;
342 1 : bin.sin_port = htons(rand());
343 : uint32_t baddress((10 << 24)
344 : | (0 << 16)
345 : | (0 << 8)
346 1 : | 0);
347 1 : bin.sin_addr.s_addr = htonl(baddress);
348 2 : addr::addr b;
349 1 : b.set_ipv4(bin);
350 :
351 1 : REQUIRE_FALSE(range.is_in(b));
352 : }
353 :
354 11 : for(int idx(0); idx < 10; ++idx)
355 : {
356 10 : struct sockaddr_in bin = sockaddr_in();
357 10 : bin.sin_family = AF_INET;
358 10 : bin.sin_port = htons(rand());
359 10 : uint32_t baddress(((rand() % 10) << 24)
360 10 : | ((rand() & 255) << 16)
361 10 : | ((rand() & 255) << 8)
362 10 : | (rand() & 255));
363 10 : bin.sin_addr.s_addr = htonl(baddress);
364 20 : addr::addr b;
365 10 : b.set_ipv4(bin);
366 :
367 10 : REQUIRE_FALSE(range.is_in(b));
368 : }
369 :
370 : // IP after range
371 : {
372 1 : struct sockaddr_in ain = sockaddr_in();
373 1 : ain.sin_family = AF_INET;
374 1 : ain.sin_port = htons(rand());
375 : uint32_t aaddress((10 << 24)
376 : | (0 << 16)
377 : | (0 << 8)
378 1 : | 255);
379 1 : ain.sin_addr.s_addr = htonl(aaddress);
380 2 : addr::addr after;
381 1 : after.set_ipv4(ain);
382 :
383 1 : REQUIRE_FALSE(range.is_in(after));
384 : }
385 :
386 11 : for(int idx(0); idx < 10; ++idx)
387 : {
388 10 : struct sockaddr_in ain = sockaddr_in();
389 10 : ain.sin_family = AF_INET;
390 10 : ain.sin_port = htons(rand());
391 10 : uint32_t aaddress(((rand() % (256 - 11) + 11) << 24)
392 10 : | ((rand() & 255) << 16)
393 10 : | ((rand() & 255) << 8)
394 10 : | (rand() & 255));
395 10 : ain.sin_addr.s_addr = htonl(aaddress);
396 20 : addr::addr after;
397 10 : after.set_ipv4(ain);
398 :
399 10 : REQUIRE_FALSE(range.is_in(after));
400 : }
401 :
402 : // IP in range
403 : //
404 101 : for(int idx(0); idx < 100; ++idx)
405 : {
406 100 : struct sockaddr_in iin = sockaddr_in();
407 100 : iin.sin_family = AF_INET;
408 100 : iin.sin_port = htons(rand());
409 : uint32_t iaddress((10 << 24)
410 : | (0 << 16)
411 : | (0 << 8)
412 100 : | ((rand() & 253) + 1));
413 100 : iin.sin_addr.s_addr = htonl(iaddress);
414 200 : addr::addr i;
415 100 : i.set_ipv4(iin);
416 :
417 100 : REQUIRE_FALSE(range.is_in(i));
418 : }
419 : }
420 : }
421 :
422 10 : GIVEN("compute intersection of two ranges")
423 : {
424 4 : SECTION("two ranges that overlap")
425 : {
426 : // from is set to 10.1.0.0
427 1 : struct sockaddr_in f1in = sockaddr_in();
428 1 : f1in.sin_family = AF_INET;
429 1 : f1in.sin_port = htons(rand());
430 : uint32_t f1address((10 << 24)
431 : | (1 << 16)
432 : | (0 << 8)
433 1 : | 0);
434 1 : f1in.sin_addr.s_addr = htonl(f1address);
435 2 : addr::addr f1;
436 1 : f1.set_ipv4(f1in);
437 :
438 : // from is set to 10.5.255.255
439 1 : struct sockaddr_in t1in = sockaddr_in();
440 1 : t1in.sin_family = AF_INET;
441 1 : t1in.sin_port = htons(rand());
442 : uint32_t t1address((10 << 24)
443 : | (5 << 16)
444 : | (255 << 8)
445 1 : | 255);
446 1 : t1in.sin_addr.s_addr = htonl(t1address);
447 2 : addr::addr t1;
448 1 : t1.set_ipv4(t1in);
449 :
450 : // from is set to 10.2.0.0
451 1 : struct sockaddr_in f2in = sockaddr_in();
452 1 : f2in.sin_family = AF_INET;
453 1 : f2in.sin_port = htons(rand());
454 : uint32_t f2address((10 << 24)
455 : | (2 << 16)
456 : | (0 << 8)
457 1 : | 0);
458 1 : f2in.sin_addr.s_addr = htonl(f2address);
459 2 : addr::addr f2;
460 1 : f2.set_ipv4(f2in);
461 :
462 : // from is set to 10.10.255.255
463 1 : struct sockaddr_in t2in = sockaddr_in();
464 1 : t2in.sin_family = AF_INET;
465 1 : t2in.sin_port = htons(rand());
466 : uint32_t t2address((10 << 24)
467 : | (10 << 16)
468 : | (255 << 8)
469 1 : | 255);
470 1 : t2in.sin_addr.s_addr = htonl(t2address);
471 2 : addr::addr t2;
472 1 : t2.set_ipv4(t2in);
473 :
474 2 : addr::addr_range range1;
475 1 : range1.set_from(f1);
476 1 : range1.set_to(t1);
477 :
478 2 : addr::addr_range range2;
479 1 : range2.set_from(f2);
480 1 : range2.set_to(t2);
481 :
482 1 : REQUIRE(range1.is_range());
483 1 : REQUIRE_FALSE(range1.is_empty());
484 1 : REQUIRE(range2.is_range());
485 1 : REQUIRE_FALSE(range2.is_empty());
486 :
487 2 : addr::addr_range range3(range1.intersection(range2));
488 :
489 1 : REQUIRE(range3.is_range());
490 1 : REQUIRE_FALSE(range3.is_empty());
491 :
492 1 : REQUIRE(range3.get_from().to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.2.0.0");
493 1 : REQUIRE(range3.get_to().to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
494 : }
495 :
496 4 : SECTION("two ranges that do not overlap")
497 : {
498 : // from is set to 10.1.0.0
499 1 : struct sockaddr_in f1in = sockaddr_in();
500 1 : f1in.sin_family = AF_INET;
501 1 : f1in.sin_port = htons(rand());
502 : uint32_t f1address((10 << 24)
503 : | (1 << 16)
504 : | (0 << 8)
505 1 : | 0);
506 1 : f1in.sin_addr.s_addr = htonl(f1address);
507 2 : addr::addr f1;
508 1 : f1.set_ipv4(f1in);
509 :
510 : // from is set to 10.5.255.255
511 1 : struct sockaddr_in t1in = sockaddr_in();
512 1 : t1in.sin_family = AF_INET;
513 1 : t1in.sin_port = htons(rand());
514 : uint32_t t1address((10 << 24)
515 : | (5 << 16)
516 : | (255 << 8)
517 1 : | 255);
518 1 : t1in.sin_addr.s_addr = htonl(t1address);
519 2 : addr::addr t1;
520 1 : t1.set_ipv4(t1in);
521 :
522 : // from is set to 10.10.0.0
523 1 : struct sockaddr_in f2in = sockaddr_in();
524 1 : f2in.sin_family = AF_INET;
525 1 : f2in.sin_port = htons(rand());
526 : uint32_t f2address((10 << 24)
527 : | (10 << 16)
528 : | (0 << 8)
529 1 : | 0);
530 1 : f2in.sin_addr.s_addr = htonl(f2address);
531 2 : addr::addr f2;
532 1 : f2.set_ipv4(f2in);
533 :
534 : // from is set to 10.20.255.255
535 1 : struct sockaddr_in t2in = sockaddr_in();
536 1 : t2in.sin_family = AF_INET;
537 1 : t2in.sin_port = htons(rand());
538 : uint32_t t2address((10 << 24)
539 : | (20 << 16)
540 : | (255 << 8)
541 1 : | 255);
542 1 : t2in.sin_addr.s_addr = htonl(t2address);
543 2 : addr::addr t2;
544 1 : t2.set_ipv4(t2in);
545 :
546 2 : addr::addr_range range1;
547 1 : range1.set_from(f1);
548 1 : range1.set_to(t1);
549 :
550 2 : addr::addr_range range2;
551 1 : range2.set_from(f2);
552 1 : range2.set_to(t2);
553 :
554 1 : REQUIRE(range1.is_range());
555 1 : REQUIRE_FALSE(range1.is_empty());
556 1 : REQUIRE(range2.is_range());
557 1 : REQUIRE_FALSE(range2.is_empty());
558 :
559 2 : addr::addr_range range3(range1.intersection(range2));
560 :
561 1 : REQUIRE(range3.is_range());
562 1 : REQUIRE(range3.is_empty());
563 :
564 : // although it is "empty" we know the IPs and can test them
565 : //
566 1 : REQUIRE(range3.get_from().to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.10.0.0");
567 1 : REQUIRE(range3.get_to().to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
568 :
569 2 : addr::addr_range::vector_t rlist;
570 1 : rlist.push_back(range1);
571 1 : rlist.push_back(range2);
572 1 : REQUIRE(addr::address_match_ranges(rlist, f1));
573 1 : REQUIRE(addr::address_match_ranges(rlist, f2));
574 1 : REQUIRE(addr::address_match_ranges(rlist, t1));
575 1 : REQUIRE(addr::address_match_ranges(rlist, t2));
576 : }
577 : }
578 11 : }
579 :
580 :
581 :
582 :
583 :
584 : // vim: ts=4 sw=4 et
|