2 #include "../../src/subnet.h"
4 typedef struct net_str_testcase {
9 static void test_subnet_compare_different_types(void **state) {
12 const subnet_t ipv4 = {.type = SUBNET_IPV4};
13 const subnet_t ipv6 = {.type = SUBNET_IPV6};
14 const subnet_t mac = {.type = SUBNET_MAC};
16 assert_int_not_equal(0, subnet_compare(&ipv4, &ipv6));
17 assert_int_not_equal(0, subnet_compare(&ipv4, &mac));
18 assert_int_not_equal(0, subnet_compare(&ipv6, &mac));
21 static const mac_t mac1 = {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}};
22 static const mac_t mac2 = {{0x42, 0x01, 0x02, 0x03, 0x04, 0x05}};
24 static const subnet_ipv4_t ipv4_1 = {.address = {{0x01, 0x02, 0x03, 0x04}}, .prefixlength = 24};
25 static const subnet_ipv4_t ipv4_1_pref = {.address = {{0x01, 0x02, 0x03, 0x04}}, .prefixlength = 16};
26 static const subnet_ipv4_t ipv4_2 = {.address = {{0x11, 0x22, 0x33, 0x44}}, .prefixlength = 16};
28 static const subnet_ipv6_t ipv6_1 = {
29 .address = {{0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04}},
33 static const subnet_ipv6_t ipv6_1_pref = {
34 .address = {{0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04}},
38 static const subnet_ipv6_t ipv6_2 = {
39 .address = {{0x11, 0x22, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04}},
43 static void test_maskcmp(void **state) {
46 const ipv4_t a = {{1, 2, 3, 4}};
47 const ipv4_t b = {{1, 2, 3, 0xff}};
49 for(int mask = 0; mask <= 24; ++mask) {
50 assert_int_equal(0, maskcmp(&a, &b, mask));
53 for(int mask = 25; mask <= 32; ++mask) {
54 assert_true(maskcmp(&a, &b, mask) != 0);
58 static void test_mask(void **state) {
61 ipv4_t dst = {{0xff, 0xff, 0xff, 0xff}};
62 mask(&dst, 23, sizeof(dst));
64 const ipv4_t ref = {{0xff, 0xff, 0xfe, 0x00}};
65 assert_memory_equal(&ref, &dst, sizeof(dst));
68 static void test_maskcpy(void **state) {
71 const ipv4_t src = {{0xff, 0xff, 0xff, 0xff}};
72 const ipv4_t ref = {{0xff, 0xff, 0xfe, 0x00}};
75 maskcpy(&dst, &src, 23, sizeof(src));
77 assert_memory_equal(&ref, &dst, sizeof(dst));
80 static void test_subnet_compare_mac_eq(void **state) {
83 node_t owner = {.name = strdup("foobar")};
84 const subnet_t a = {.type = SUBNET_MAC, .net.mac.address = mac1, .weight = 42, .owner = &owner};
85 const subnet_t b = {.type = SUBNET_MAC, .net.mac.address = mac1, .weight = 42, .owner = &owner};
87 assert_int_equal(0, subnet_compare(&a, &a));
88 assert_int_equal(0, subnet_compare(&a, &b));
89 assert_int_equal(0, subnet_compare(&b, &a));
94 static void test_subnet_compare_mac_neq_address(void **state) {
97 node_t owner = {.name = strdup("foobar")};
98 const subnet_t a = {.type = SUBNET_MAC, .net.mac.address = mac1, .weight = 10, .owner = &owner};
99 const subnet_t b = {.type = SUBNET_MAC, .net.mac.address = mac2, .weight = 10, .owner = &owner};
101 assert_true(subnet_compare(&a, &b) < 0);
102 assert_true(subnet_compare(&b, &a) > 0);
107 static void test_subnet_compare_mac_weight(void **state) {
110 node_t owner = {.name = strdup("foobar")};
111 const subnet_t a = {.type = SUBNET_MAC, .net.mac.address = mac1, .weight = 42, .owner = &owner};
112 const subnet_t b = {.type = SUBNET_MAC, .net.mac.address = mac1, .weight = 42, .owner = &owner};
113 const subnet_t c = {.type = SUBNET_MAC, .net.mac.address = mac1, .weight = 10, .owner = &owner};
115 assert_int_equal(0, subnet_compare(&a, &a));
116 assert_int_equal(0, subnet_compare(&a, &b));
117 assert_int_equal(0, subnet_compare(&b, &a));
119 assert_true(subnet_compare(&a, &c) > 0);
120 assert_true(subnet_compare(&c, &a) < 0);
125 static void test_subnet_compare_mac_owners(void **state) {
128 node_t foo = {.name = strdup("foo")};
129 node_t bar = {.name = strdup("bar")};
131 const subnet_t a = {.type = SUBNET_MAC, .net.mac.address = mac1, .weight = 42, .owner = &foo};
132 const subnet_t b = {.type = SUBNET_MAC, .net.mac.address = mac1, .weight = 42, .owner = &bar};
134 assert_int_equal(0, subnet_compare(&a, &a));
135 assert_int_equal(0, subnet_compare(&b, &b));
137 assert_true(subnet_compare(&a, &b) > 0);
138 assert_true(subnet_compare(&b, &a) < 0);
145 static void test_subnet_compare_ipv4_eq(void **state) {
148 const subnet_t a = {.type = SUBNET_IPV4, .net.ipv4 = ipv4_1};
149 const subnet_t b = {.type = SUBNET_IPV4, .net.ipv4 = ipv4_1};
151 assert_int_equal(0, subnet_compare(&a, &b));
152 assert_int_equal(0, subnet_compare(&b, &a));
155 static void test_subnet_compare_ipv4_neq(void **state) {
158 const subnet_t a = {.type = SUBNET_IPV4, .net.ipv4 = ipv4_1};
159 const subnet_t b = {.type = SUBNET_IPV4, .net.ipv4 = ipv4_1_pref};
160 const subnet_t c = {.type = SUBNET_IPV4, .net.ipv4 = ipv4_2};
162 assert_true(subnet_compare(&a, &b) < 0);
163 assert_true(subnet_compare(&b, &a) > 0);
165 assert_true(subnet_compare(&a, &c) < 0);
166 assert_true(subnet_compare(&b, &c) < 0);
169 static void test_subnet_compare_ipv4_weight(void **state) {
172 const subnet_t a = {.type = SUBNET_IPV4, .net.ipv4 = ipv4_1, .weight = 1};
173 const subnet_t b = {.type = SUBNET_IPV4, .net.ipv4 = ipv4_1, .weight = 2};
175 assert_true(subnet_compare(&a, &b) < 0);
178 static void test_subnet_compare_ipv4_owners(void **state) {
181 node_t foo = {.name = strdup("foo")};
182 node_t bar = {.name = strdup("bar")};
184 const subnet_t a = {.type = SUBNET_IPV4, .net.ipv4 = ipv4_1, .owner = &foo};
185 const subnet_t b = {.type = SUBNET_IPV4, .net.ipv4 = ipv4_1, .owner = &foo};
186 const subnet_t c = {.type = SUBNET_IPV4, .net.ipv4 = ipv4_1, .owner = &bar};
188 assert_int_equal(0, subnet_compare(&a, &b));
189 assert_true(subnet_compare(&a, &c) > 0);
195 static void test_subnet_compare_ipv6_eq(void **state) {
198 const subnet_t a = {.type = SUBNET_IPV6, .net.ipv6 = ipv6_1};
199 const subnet_t b = {.type = SUBNET_IPV6, .net.ipv6 = ipv6_1};
201 assert_int_equal(0, subnet_compare(&a, &b));
202 assert_int_equal(0, subnet_compare(&b, &a));
205 static void test_subnet_compare_ipv6_neq(void **state) {
208 const subnet_t a = {.type = SUBNET_IPV6, .net.ipv6 = ipv6_1};
209 const subnet_t b = {.type = SUBNET_IPV6, .net.ipv6 = ipv6_1_pref};
210 const subnet_t c = {.type = SUBNET_IPV6, .net.ipv6 = ipv6_2};
212 assert_true(subnet_compare(&a, &b) < 0);
213 assert_true(subnet_compare(&b, &a) > 0);
215 assert_true(subnet_compare(&a, &c) < 0);
216 assert_true(subnet_compare(&b, &c) > 0);
219 static void test_subnet_compare_ipv6_weight(void **state) {
222 const subnet_t a = {.type = SUBNET_IPV6, .net.ipv6 = ipv6_1, .weight = 1};
223 const subnet_t b = {.type = SUBNET_IPV6, .net.ipv6 = ipv6_1, .weight = 2};
225 assert_true(subnet_compare(&a, &b) < 0);
228 static void test_subnet_compare_ipv6_owners(void **state) {
231 node_t foo = {.name = strdup("foo")};
232 node_t bar = {.name = strdup("bar")};
234 const subnet_t a = {.type = SUBNET_IPV6, .net.ipv6 = ipv6_1, .owner = &foo};
235 const subnet_t b = {.type = SUBNET_IPV6, .net.ipv6 = ipv6_1, .owner = &foo};
236 const subnet_t c = {.type = SUBNET_IPV6, .net.ipv6 = ipv6_1, .owner = &bar};
238 assert_int_equal(0, subnet_compare(&a, &b));
239 assert_true(subnet_compare(&a, &c) > 0);
245 static void test_str2net_valid(void **state) {
248 const net_str_testcase testcases[] = {
250 .text = "1.2.3.0/24#42",
265 .text = "04fb:7deb:78db:1950:2d21:258d:40b6:f0d7/128#999",
273 htons(0x04fb), htons(0x7deb), htons(0x78db), htons(0x1950),
274 htons(0x2d21), htons(0x258d), htons(0x40b6), htons(0xf0d7),
283 .text = "fe80::16dd:a9ff:fe7e:b4c2/64",
291 htons(0xfe80), htons(0x0000), htons(0x0000), htons(0x0000),
292 htons(0x16dd), htons(0xa9ff), htons(0xfe7e), htons(0xb4c2),
301 .text = "57:04:13:01:f9:26#60",
308 .x = {0x57, 0x04, 0x13, 0x01, 0xf9, 0x26},
316 for(size_t i = 0; i < sizeof(testcases) / sizeof(*testcases); ++i) {
317 const char *text = testcases[i].text;
318 const subnet_t *ref = &testcases[i].data;
321 bool ok = str2net(&sub, text);
323 // Split into separate assertions for more clear failures
325 assert_int_equal(ref->type, sub.type);
326 assert_int_equal(ref->weight, sub.weight);
330 assert_memory_equal(&ref->net.mac.address, &sub.net.mac.address, sizeof(mac_t));
334 assert_int_equal(ref->net.ipv4.prefixlength, sub.net.ipv4.prefixlength);
335 assert_memory_equal(&ref->net.ipv4.address, &sub.net.ipv4.address, sizeof(ipv4_t));
339 assert_int_equal(ref->net.ipv6.prefixlength, sub.net.ipv6.prefixlength);
340 assert_memory_equal(&ref->net.ipv6.address, &sub.net.ipv6.address, sizeof(ipv6_t));
344 fail_msg("unknown subnet type %d", ref->type);
349 static void test_str2net_invalid(void **state) {
354 const char *test_cases[] = {
364 "cb:0c:1b:60:ed:7a/1",
376 for(const char **str = test_cases; *str; ++str) {
377 bool ok = str2net(&sub, *str);
382 static void test_net2str_valid(void **state) {
385 const net_str_testcase testcases[] = {
387 .text = "12:fe:ff:3a:28:90#42",
394 .x = {0x12, 0xfe, 0xff, 0x3a, 0x28, 0x90}
416 .text = "181.35.16.0/27#1",
423 .x = {181, 35, 16, 0}
431 .text = "5fbf:5cfe:0:fdd2:fd76::/96#900",
439 htons(0x5fbf), htons(0x5cfe), htons(0x0000), htons(0xfdd2),
440 htons(0xfd76), htons(0x0000), htons(0x0000), htons(0x0000),
450 for(size_t i = 0; i < sizeof(testcases) / sizeof(*testcases); ++i) {
451 const char *text = testcases[i].text;
452 const subnet_t *ref = &testcases[i].data;
455 bool ok = net2str(buf, sizeof(buf), ref);
458 assert_string_equal(text, buf);
462 static void test_net2str_invalid(void **state) {
465 const subnet_t sub = {0};
467 assert_false(net2str(NULL, sizeof(buf), &sub));
468 assert_false(net2str(buf, sizeof(buf), NULL));
471 static void test_maskcheck_valid_ipv4(void **state) {
474 const ipv4_t a = {{10, 0, 0, 0}};
475 const ipv4_t b = {{192, 168, 0, 0}};
476 const ipv4_t c = {{192, 168, 24, 0}};
478 assert_true(maskcheck(&a, 8, sizeof(a)));
479 assert_true(maskcheck(&b, 16, sizeof(b)));
480 assert_true(maskcheck(&c, 24, sizeof(c)));
483 static void test_maskcheck_valid_ipv6(void **state) {
486 const ipv6_t a = {{10, 0, 0, 0, 0, 0, 0, 0}};
487 assert_true(maskcheck(&a, 8, sizeof(a)));
489 const ipv6_t b = {{10, 20, 0, 0, 0, 0, 0, 0}};
490 assert_true(maskcheck(&b, 32, sizeof(b)));
492 const ipv6_t c = {{192, 168, 24, 0, 0, 0, 0, 0}};
493 assert_true(maskcheck(&c, 48, sizeof(c)));
496 static void test_maskcheck_invalid_ipv4(void **state) {
499 const ipv4_t a = {{10, 20, 0, 0}};
500 const ipv4_t b = {{10, 20, 30, 0}};
502 assert_false(maskcheck(&a, 8, sizeof(a)));
503 assert_false(maskcheck(&b, 16, sizeof(b)));
506 static void test_maskcheck_invalid_ipv6(void **state) {
509 const ipv6_t a = {{1, 2, 3, 4, 5, 6, 7, 0xAABB}};
511 for(int mask = 0; mask < 128; mask += 8) {
512 assert_false(maskcheck(&a, mask, sizeof(a)));
517 const struct CMUnitTest tests[] = {
518 cmocka_unit_test(test_maskcmp),
519 cmocka_unit_test(test_mask),
520 cmocka_unit_test(test_maskcpy),
522 cmocka_unit_test(test_subnet_compare_different_types),
524 cmocka_unit_test(test_subnet_compare_mac_eq),
525 cmocka_unit_test(test_subnet_compare_mac_neq_address),
526 cmocka_unit_test(test_subnet_compare_mac_weight),
527 cmocka_unit_test(test_subnet_compare_mac_owners),
529 cmocka_unit_test(test_subnet_compare_ipv4_eq),
530 cmocka_unit_test(test_subnet_compare_ipv4_neq),
531 cmocka_unit_test(test_subnet_compare_ipv4_weight),
532 cmocka_unit_test(test_subnet_compare_ipv4_owners),
534 cmocka_unit_test(test_subnet_compare_ipv6_eq),
535 cmocka_unit_test(test_subnet_compare_ipv6_neq),
536 cmocka_unit_test(test_subnet_compare_ipv6_weight),
537 cmocka_unit_test(test_subnet_compare_ipv6_owners),
539 cmocka_unit_test(test_str2net_valid),
540 cmocka_unit_test(test_str2net_invalid),
542 cmocka_unit_test(test_net2str_valid),
543 cmocka_unit_test(test_net2str_invalid),
545 cmocka_unit_test(test_maskcheck_valid_ipv4),
546 cmocka_unit_test(test_maskcheck_valid_ipv6),
547 cmocka_unit_test(test_maskcheck_invalid_ipv4),
548 cmocka_unit_test(test_maskcheck_invalid_ipv6),
550 return cmocka_run_group_tests(tests, NULL, NULL);