2 * Filters: Utility Functions Tests
4 * (c) 2015 CZ.NIC z.s.p.o.
6 * Can be freely distributed and used under the terms of the GNU GPL.
9 #include "test/birdtest.h"
10 #include "test/bt-utils.h"
12 #include "filter/filter.h"
13 #include "filter/data.h"
14 #include "conf/conf.h"
17 #define PREFIXES_NUM 32
18 #define PREFIX_TESTS_NUM 10000
19 #define PREFIX_BENCH_NUM 100000000
21 #define TRIE_BUFFER_SIZE 1024
22 #define TEST_BUFFER_SIZE (1024*1024)
23 #define BIG_BUFFER_SIZE 10000
25 /* Wrapping structure for storing f_prefixes structures in list */
26 struct f_prefix_node
{
28 struct f_prefix prefix
;
36 for (r
= bt_random(); r
& 1; r
= r
>> 1)
43 compare_prefixes(const void *a
, const void *b
)
45 return net_compare(&((const struct f_prefix
*) a
)->net
,
46 &((const struct f_prefix
*) b
)->net
);
50 matching_ip4_nets(const net_addr_ip4
*a
, const net_addr_ip4
*b
)
52 ip4_addr cmask
= ip4_mkmask(MIN(a
->pxlen
, b
->pxlen
));
53 return ip4_compare(ip4_and(a
->prefix
, cmask
), ip4_and(b
->prefix
, cmask
)) == 0;
57 matching_ip6_nets(const net_addr_ip6
*a
, const net_addr_ip6
*b
)
59 ip6_addr cmask
= ip6_mkmask(MIN(a
->pxlen
, b
->pxlen
));
60 return ip6_compare(ip6_and(a
->prefix
, cmask
), ip6_and(b
->prefix
, cmask
)) == 0;
64 matching_nets(const net_addr
*a
, const net_addr
*b
)
66 if (a
->type
!= b
->type
)
69 return (a
->type
== NET_IP4
) ?
70 matching_ip4_nets((const net_addr_ip4
*) a
, (const net_addr_ip4
*) b
) :
71 matching_ip6_nets((const net_addr_ip6
*) a
, (const net_addr_ip6
*) b
);
75 is_prefix_included(list
*prefixes
, const net_addr
*needle
)
77 struct f_prefix_node
*n
;
78 WALK_LIST(n
, *prefixes
)
79 if (matching_nets(&n
->prefix
.net
, needle
) &&
80 (n
->prefix
.lo
<= needle
->pxlen
) && (needle
->pxlen
<= n
->prefix
.hi
))
83 bt_format_net(buf
, 64, &n
->prefix
.net
);
84 bt_debug("FOUND %s %d-%d\n", buf
, n
->prefix
.lo
, n
->prefix
.hi
);
93 get_random_prefix(struct f_prefix
*px
, int v6
, int tight
)
95 bt_random_net(&px
->net
, !v6
? NET_IP4
: NET_IP6
);
99 px
->lo
= px
->hi
= px
->net
.pxlen
;
101 else if (bt_random() % 2)
104 px
->hi
= px
->net
.pxlen
;
108 px
->lo
= px
->net
.pxlen
;
109 px
->hi
= net_max_prefix_length
[px
->net
.type
];
114 get_random_ip4_subnet(net_addr_ip4
*net
, const net_addr_ip4
*src
, int pxlen
)
116 *net
= NET_ADDR_IP4(ip4_and(src
->prefix
, ip4_mkmask(pxlen
)), pxlen
);
118 if (pxlen
> src
->pxlen
)
120 ip4_addr rnd
= ip4_from_u32((u32
) bt_random());
121 ip4_addr mask
= ip4_xor(ip4_mkmask(src
->pxlen
), ip4_mkmask(pxlen
));
122 net
->prefix
= ip4_or(net
->prefix
, ip4_and(rnd
, mask
));
127 get_random_ip6_subnet(net_addr_ip6
*net
, const net_addr_ip6
*src
, int pxlen
)
129 *net
= NET_ADDR_IP6(ip6_and(src
->prefix
, ip6_mkmask(pxlen
)), pxlen
);
131 if (pxlen
> src
->pxlen
)
133 ip6_addr rnd
= ip6_build(bt_random(), bt_random(), bt_random(), bt_random());
134 ip6_addr mask
= ip6_xor(ip6_mkmask(src
->pxlen
), ip6_mkmask(pxlen
));
135 net
->prefix
= ip6_or(net
->prefix
, ip6_and(rnd
, mask
));
140 get_random_subnet(net_addr
*net
, const net_addr
*src
, int pxlen
)
142 if (src
->type
== NET_IP4
)
143 get_random_ip4_subnet((net_addr_ip4
*) net
, (const net_addr_ip4
*) src
, pxlen
);
145 get_random_ip6_subnet((net_addr_ip6
*) net
, (const net_addr_ip6
*) src
, pxlen
);
149 get_inner_net(net_addr
*net
, const struct f_prefix
*src
)
155 step
= get_exp_random();
156 step
= MIN(step
, src
->hi
- src
->lo
);
157 pxlen
= (bt_random() % 2) ? (src
->lo
+ step
) : (src
->hi
- step
);
160 pxlen
= src
->lo
+ bt_random() % (src
->hi
- src
->lo
+ 1);
162 get_random_subnet(net
, &src
->net
, pxlen
);
166 swap_random_bits_ip4(net_addr_ip4
*net
, int num
)
168 for (int i
= 0; i
< num
; i
++)
170 ip4_addr swap
= IP4_NONE
;
171 ip4_setbit(&swap
, bt_random() % net
->pxlen
);
172 net
->prefix
= ip4_xor(net
->prefix
, swap
);
177 swap_random_bits_ip6(net_addr_ip6
*net
, int num
)
179 for (int i
= 0; i
< num
; i
++)
181 ip6_addr swap
= IP6_NONE
;
182 ip6_setbit(&swap
, bt_random() % net
->pxlen
);
183 net
->prefix
= ip6_xor(net
->prefix
, swap
);
188 swap_random_bits(net_addr
*net
, int num
)
190 if (net
->type
== NET_IP4
)
191 swap_random_bits_ip4((net_addr_ip4
*) net
, num
);
193 swap_random_bits_ip6((net_addr_ip6
*) net
, num
);
197 get_outer_net(net_addr
*net
, const struct f_prefix
*src
)
201 int max
= net_max_prefix_length
[src
->net
.type
];
203 if ((src
->lo
> 0) && (bt_random() % 3))
205 step
= 1 + get_exp_random();
206 step
= MIN(step
, src
->lo
);
207 pxlen
= src
->lo
- step
;
209 else if ((src
->hi
< max
) && (bt_random() % 2))
211 step
= 1 + get_exp_random();
212 step
= MIN(step
, max
- src
->hi
);
213 pxlen
= src
->hi
+ step
;
217 pxlen
= src
->lo
+ bt_random() % (src
->hi
- src
->lo
+ 1);
221 get_random_subnet(net
, &src
->net
, pxlen
);
223 /* Perhaps swap some bits in prefix */
224 if ((net
->pxlen
> 0) && (inside
|| (bt_random() % 4)))
225 swap_random_bits(net
, 1 + get_exp_random());
229 make_random_prefix_list(int num
, int v6
, int tight
)
231 list
*prefixes
= lp_allocz(tmp_linpool
, sizeof(struct f_prefix_node
));
234 for (int i
= 0; i
< num
; i
++)
236 struct f_prefix_node
*px
= lp_allocz(tmp_linpool
, sizeof(struct f_prefix_node
));
237 get_random_prefix(&px
->prefix
, v6
, tight
);
238 add_tail(prefixes
, &px
->n
);
241 bt_format_net(buf
, 64, &px
->prefix
.net
);
242 bt_debug("ADD %s{%d,%d}\n", buf
, px
->prefix
.lo
, px
->prefix
.hi
);
248 static struct f_trie
*
249 make_trie_from_prefix_list(list
*prefixes
)
251 struct f_trie
*trie
= f_new_trie(tmp_linpool
, 0);
253 struct f_prefix_node
*n
;
254 WALK_LIST(n
, *prefixes
)
255 trie_add_prefix(trie
, &n
->prefix
.net
, n
->prefix
.lo
, n
->prefix
.hi
);
261 * Read sequence of prefixes from file handle and return prefix list.
262 * Each prefix is on one line, sequence terminated by empty line or eof.
263 * Arg @plus means prefix should include all longer ones.
266 read_prefix_list(FILE *f
, int v6
, int plus
)
270 uint a0
, a1
, a2
, a3
, pl
;
274 list
*pxlist
= lp_allocz(tmp_linpool
, sizeof(struct f_prefix_node
));
278 while (fgets(s
, 32, f
))
283 n
= sscanf(s
, "%u.%u.%u.%u/%u", &a0
, &a1
, &a2
, &a3
, &pl
);
286 bt_abort_msg("Invalid content of trie_data");
288 struct f_prefix_node
*px
= lp_allocz(tmp_linpool
, sizeof(struct f_prefix_node
));
289 net_fill_ip4(&px
->prefix
.net
, ip4_build(a0
, a1
, a2
, a3
), pl
);
291 px
->prefix
.hi
= plus
? IP4_MAX_PREFIX_LENGTH
: pl
;
292 add_tail(pxlist
, &px
->n
);
295 bt_format_net(buf
, 64, &px
->prefix
.net
);
296 bt_debug("ADD %s{%d,%d}\n", buf
, px
->prefix
.lo
, px
->prefix
.hi
);
299 bt_syscall(errno
, "fgets()");
300 return EMPTY_LIST(*pxlist
) ? NULL
: pxlist
;
304 * Open file, read multiple sequences of prefixes from it. Fill @data with
305 * prefix lists and @trie with generated tries. Return number of sequences /
306 * tries. Use separate linpool @lp0 for prefix lists and @lp1 for tries.
307 * Arg @plus means prefix should include all longer ones.
310 read_prefix_file(const char *filename
, int plus
,
311 list
*data
[], struct f_trie
*trie
[])
313 FILE *f
= fopen(filename
, "r");
314 bt_syscall(!f
, "fopen(%s)", filename
);
318 while (pxlist
= read_prefix_list(f
, 0, plus
))
321 trie
[n
] = make_trie_from_prefix_list(pxlist
);
327 bt_debug("DONE reading %d tries\n", n
);
333 * Select random subset of @dn prefixes from prefix list @src of length @sn,
334 * and store them to buffer @dst (of size @dn). Prefixes may be chosen multiple
335 * times. Randomize order of prefixes in @dst buffer.
338 select_random_prefix_subset(list
*src
[], net_addr dst
[], int sn
, int dn
)
345 /* Compute total prefix number */
346 for (int i
= 0; i
< sn
; i
++)
347 pn
+= list_length(src
[i
]);
349 /* Change of selecting a prefix */
350 int rnd
= (pn
/ dn
) + 10;
353 /* Iterate indefinitely over src array */
354 for (int i
= 0; 1; i
++, i
= (i
< sn
) ? i
: 0)
356 struct f_prefix_node
*px
;
357 WALK_LIST(px
, *src
[i
])
359 if (bt_random_n(rnd
) != 0)
362 net_copy(&dst
[n
], &px
->prefix
.net
);
372 /* Shuffle networks */
373 for (int i
= 0; i
< dn
; i
++)
375 int j
= bt_random_n(dn
);
381 net_copy(&tmp
, &dst
[i
]);
382 net_copy(&dst
[i
], &dst
[j
]);
383 net_copy(&dst
[j
], &tmp
);
387 /* Fill @dst buffer with @dn randomly generated /32 prefixes */
389 make_random_addresses(net_addr dst
[], int dn
)
391 for (int i
= 0; i
< dn
; i
++)
392 net_fill_ip4(&dst
[i
], ip4_from_u32((u32
) bt_random()), IP4_MAX_PREFIX_LENGTH
);
396 test_match_net(list
*prefixes
, struct f_trie
*trie
, const net_addr
*net
)
399 bt_format_net(buf
, 64, net
);
400 bt_debug("TEST %s\n", buf
);
402 int should_be
= is_prefix_included(prefixes
, net
);
403 int is_there
= trie_match_net(trie
, net
);
405 bt_assert_msg(should_be
== is_there
, "Prefix %s %s match", buf
,
406 (should_be
? "should" : "should not"));
410 t_match_random_net(void)
413 bt_config_parse(BT_CONFIG_SIMPLE
);
416 for (int round
= 0; round
< TESTS_NUM
; round
++)
418 list
*prefixes
= make_random_prefix_list(PREFIXES_NUM
, v6
, 0);
419 struct f_trie
*trie
= make_trie_from_prefix_list(prefixes
);
421 for (int i
= 0; i
< PREFIX_TESTS_NUM
; i
++)
424 bt_random_net(&net
, !v6
? NET_IP4
: NET_IP6
);
425 test_match_net(prefixes
, trie
, &net
);
437 t_match_inner_net(void)
440 bt_config_parse(BT_CONFIG_SIMPLE
);
443 for (int round
= 0; round
< TESTS_NUM
; round
++)
445 list
*prefixes
= make_random_prefix_list(PREFIXES_NUM
, v6
, 0);
446 struct f_trie
*trie
= make_trie_from_prefix_list(prefixes
);
448 struct f_prefix_node
*n
= HEAD(*prefixes
);
449 for (int i
= 0; i
< PREFIX_TESTS_NUM
; i
++)
452 get_inner_net(&net
, &n
->prefix
);
453 test_match_net(prefixes
, trie
, &net
);
455 n
= NODE_VALID(NODE_NEXT(n
)) ? NODE_NEXT(n
) : HEAD(*prefixes
);
467 t_match_outer_net(void)
470 bt_config_parse(BT_CONFIG_SIMPLE
);
473 for (int round
= 0; round
< TESTS_NUM
; round
++)
475 list
*prefixes
= make_random_prefix_list(PREFIXES_NUM
, v6
, 0);
476 struct f_trie
*trie
= make_trie_from_prefix_list(prefixes
);
478 struct f_prefix_node
*n
= HEAD(*prefixes
);
479 for (int i
= 0; i
< PREFIX_TESTS_NUM
; i
++)
482 get_outer_net(&net
, &n
->prefix
);
483 test_match_net(prefixes
, trie
, &net
);
485 n
= NODE_VALID(NODE_NEXT(n
)) ? NODE_NEXT(n
) : HEAD(*prefixes
);
498 * Read prefixes from @filename, build set of tries, prepare test data and do
499 * PREFIX_BENCH_NUM trie lookups. With @plus = 0, use random subset of known
500 * prefixes as test data, with @plus = 1, use randomly generated /32 prefixes
504 benchmark_trie_dataset(const char *filename
, int plus
)
507 list
*data
[TRIE_BUFFER_SIZE
];
508 struct f_trie
*trie
[TRIE_BUFFER_SIZE
];
511 bt_reset_suite_case_timer();
512 bt_log_suite_case_result(1, "Reading %s", filename
, n
);
513 n
= read_prefix_file(filename
, plus
, data
, trie
);
514 bt_log_suite_case_result(1, "Read prefix data, %d lists, ", n
);
516 size_t trie_size
= rmemsize(tmp_linpool
).effective
* 1000 / (1024*1024);
517 bt_log_suite_case_result(1, "Trie size %u.%03u MB",
518 (uint
) (trie_size
/ 1000), (uint
) (trie_size
% 1000));
520 int t
= PREFIX_BENCH_NUM
/ n
;
521 int tb
= MIN(t
, TEST_BUFFER_SIZE
);
522 nets
= tmp_alloc(tb
* sizeof(net_addr
));
525 select_random_prefix_subset(data
, nets
, n
, tb
);
527 make_random_addresses(nets
, tb
);
529 bt_log_suite_case_result(1, "Make test data, %d (%d) tests", t
, tb
);
530 bt_reset_suite_case_timer();
534 for (int i = 0; i < t; i++)
535 for (int j = 0; j < n; j++)
536 test_match_net(data[j], trie[j], &nets[i]);
540 for (int i
= 0; i
< t
; i
++)
541 for (int j
= 0; j
< n
; j
++)
542 if (trie_match_net(trie
[j
], &nets
[i
% TEST_BUFFER_SIZE
]))
545 bt_log_suite_case_result(1, "Matching done, %d / %d matches", match
, t
* n
);
552 t_bench_trie_datasets_subset(void)
555 bt_config_parse(BT_CONFIG_SIMPLE
);
557 /* Specific datasets, not included */
558 benchmark_trie_dataset("trie-data-bgp-1", 0);
559 benchmark_trie_dataset("trie-data-bgp-10", 0);
560 benchmark_trie_dataset("trie-data-bgp-100", 0);
561 benchmark_trie_dataset("trie-data-bgp-1000", 0);
569 t_bench_trie_datasets_random(void)
572 bt_config_parse(BT_CONFIG_SIMPLE
);
574 /* Specific datasets, not included */
575 benchmark_trie_dataset("trie-data-bgp-1", 1);
576 benchmark_trie_dataset("trie-data-bgp-10", 1);
577 benchmark_trie_dataset("trie-data-bgp-100", 1);
578 benchmark_trie_dataset("trie-data-bgp-1000", 1);
590 bt_config_parse(BT_CONFIG_SIMPLE
);
593 for (int round
= 0; round
< TESTS_NUM
*4; round
++)
595 list
*prefixes
= make_random_prefix_list(100 * PREFIXES_NUM
, v6
, 0);
596 struct f_trie
*trie1
= f_new_trie(tmp_linpool
, 0);
597 struct f_trie
*trie2
= f_new_trie(tmp_linpool
, 0);
599 struct f_prefix_node
*n
;
600 WALK_LIST(n
, *prefixes
)
601 trie_add_prefix(trie1
, &n
->prefix
.net
, n
->prefix
.lo
, n
->prefix
.hi
);
603 WALK_LIST_BACKWARDS(n
, *prefixes
)
604 trie_add_prefix(trie2
, &n
->prefix
.net
, n
->prefix
.lo
, n
->prefix
.hi
);
606 bt_assert(trie_same(trie1
, trie2
));
617 log_networks(const net_addr
*a
, const net_addr
*b
)
619 if (bt_verbose
>= BT_VERBOSE_ABSOLUTELY_ALL
)
623 bt_format_net(buf0
, 64, a
);
624 bt_format_net(buf1
, 64, b
);
625 bt_debug("Found %s expected %s\n", buf0
, buf1
);
633 bt_config_parse(BT_CONFIG_SIMPLE
);
635 for (int round
= 0; round
< TESTS_NUM
*8; round
++)
637 int level
= round
/ TESTS_NUM
;
639 int num
= PREFIXES_NUM
* (int[]){1, 10, 100, 1000}[level
/ 2];
640 int pos
= 0, end
= 0;
641 list
*prefixes
= make_random_prefix_list(num
, v6
, 1);
642 struct f_trie
*trie
= make_trie_from_prefix_list(prefixes
);
643 struct f_prefix
*pxset
= malloc((num
+ 1) * sizeof(struct f_prefix
));
645 struct f_prefix_node
*n
;
646 WALK_LIST(n
, *prefixes
)
647 pxset
[pos
++] = n
->prefix
;
648 memset(&pxset
[pos
], 0, sizeof (struct f_prefix
));
650 qsort(pxset
, num
, sizeof(struct f_prefix
), compare_prefixes
);
654 bt_debug("Full walk (round %d, %d nets)\n", round
, num
);
658 TRIE_WALK(trie
, net
, NULL
)
660 log_networks(&net
, &pxset
[pos
].net
);
661 bt_assert(net_equal(&net
, &pxset
[pos
].net
));
663 /* Skip possible duplicates */
664 while (net_equal(&pxset
[pos
].net
, &pxset
[pos
+ 1].net
))
672 bt_assert(pos
== num
);
673 bt_assert(pxc
== trie
->prefix_count
);
674 bt_debug("Full walk done\n");
677 /* Prepare net for subnet walk - start with random prefix */
678 pos
= bt_random() % num
;
679 end
= pos
+ (int[]){2, 2, 3, 4}[level
/ 2];
682 struct f_prefix from
= pxset
[pos
];
684 /* Find a common superprefix to several subsequent prefixes */
685 for (; pos
< end
; pos
++)
687 if (net_equal(&from
.net
, &pxset
[pos
].net
))
691 ip4_pxlen(net4_prefix(&from
.net
), net4_prefix(&pxset
[pos
].net
)) :
692 ip6_pxlen(net6_prefix(&from
.net
), net6_prefix(&pxset
[pos
].net
));
693 from
.net
.pxlen
= MIN(from
.net
.pxlen
, common
);
696 ((net_addr_ip4
*) &from
.net
)->prefix
=
697 ip4_and(net4_prefix(&from
.net
), net4_prefix(&pxset
[pos
].net
));
699 ((net_addr_ip6
*) &from
.net
)->prefix
=
700 ip6_and(net6_prefix(&from
.net
), net6_prefix(&pxset
[pos
].net
));
703 /* Fix irrelevant bits */
705 ((net_addr_ip4
*) &from
.net
)->prefix
=
706 ip4_and(net4_prefix(&from
.net
), ip4_mkmask(net4_pxlen(&from
.net
)));
708 ((net_addr_ip6
*) &from
.net
)->prefix
=
709 ip6_and(net6_prefix(&from
.net
), ip6_mkmask(net6_pxlen(&from
.net
)));
712 /* Find initial position for final prefix */
713 for (pos
= 0; pos
< num
; pos
++)
714 if (compare_prefixes(&pxset
[pos
], &from
) >= 0)
719 bt_format_net(buf0
, 64, &from
.net
);
720 bt_debug("Subnet walk for %s (round %d, %d nets)\n", buf0
, round
, num
);
723 TRIE_WALK(trie
, net
, &from
.net
)
725 log_networks(&net
, &pxset
[pos
].net
);
726 bt_assert(net_equal(&net
, &pxset
[pos
].net
));
727 bt_assert(net_in_netX(&net
, &from
.net
));
729 /* Skip possible duplicates */
730 while (net_equal(&pxset
[pos
].net
, &pxset
[pos
+ 1].net
))
737 bt_assert((pos
== num
) || !net_in_netX(&pxset
[pos
].net
, &from
.net
));
738 bt_debug("Subnet walk done for %s (found %d nets)\n", buf0
, pos
- p0
);
748 find_covering_nets(struct f_prefix
*prefixes
, int num
, const net_addr
*net
, net_addr
*found
)
751 net_addr
*n
= &key
.net
;
758 struct f_prefix
*px
=
759 bsearch(&key
, prefixes
, num
, sizeof(struct f_prefix
), compare_prefixes
);
763 net_copy(&found
[found_num
], n
);
772 if (n
->type
== NET_IP4
)
773 ip4_clrbit(&((net_addr_ip4
*) n
)->prefix
, n
->pxlen
);
775 ip6_clrbit(&((net_addr_ip6
*) n
)->prefix
, n
->pxlen
);
780 t_trie_walk_to_root(void)
783 bt_config_parse(BT_CONFIG_SIMPLE
);
785 for (int round
= 0; round
< TESTS_NUM
* 4; round
++)
787 int level
= round
/ TESTS_NUM
;
789 int num
= PREFIXES_NUM
* (int[]){32, 512}[level
/ 2];
791 int st
= 0, sn
= 0, sm
= 0;
793 list
*prefixes
= make_random_prefix_list(num
, v6
, 1);
794 struct f_trie
*trie
= make_trie_from_prefix_list(prefixes
);
795 struct f_prefix
*pxset
= malloc((num
+ 1) * sizeof(struct f_prefix
));
797 struct f_prefix_node
*pxn
;
798 WALK_LIST(pxn
, *prefixes
)
799 pxset
[pos
++] = pxn
->prefix
;
800 memset(&pxset
[pos
], 0, sizeof (struct f_prefix
));
802 qsort(pxset
, num
, sizeof(struct f_prefix
), compare_prefixes
);
805 for (i
= 0; i
< (PREFIX_TESTS_NUM
/ 10); i
++)
808 bt_random_net(&from
, !v6
? NET_IP4
: NET_IP6
);
811 int found_num
= find_covering_nets(pxset
, num
, &from
, found
);
814 if (bt_verbose
>= BT_VERBOSE_ABSOLUTELY_ALL
)
817 bt_format_net(buf
, 64, &from
);
818 bt_debug("Lookup for %s (expect %d)\n", buf
, found_num
);
821 /* Walk to root, separate for IPv4 and IPv6 */
824 TRIE_WALK_TO_ROOT_IP4(trie
, (net_addr_ip4
*) &from
, net
)
826 log_networks((net_addr
*) &net
, &found
[n
]);
827 bt_assert((n
< found_num
) && net_equal((net_addr
*) &net
, &found
[n
]));
830 TRIE_WALK_TO_ROOT_END
;
834 TRIE_WALK_TO_ROOT_IP6(trie
, (net_addr_ip6
*) &from
, net
)
836 log_networks((net_addr
*) &net
, &found
[n
]);
837 bt_assert((n
< found_num
) && net_equal((net_addr
*) &net
, &found
[n
]));
840 TRIE_WALK_TO_ROOT_END
;
843 bt_assert(n
== found_num
);
851 bt_debug("Success in %d / %d, sum %d, max %d\n", sn
, i
, st
, sm
);
861 main(int argc
, char *argv
[])
865 bt_test_suite(t_match_random_net
, "Testing random prefix matching");
866 bt_test_suite(t_match_inner_net
, "Testing random inner prefix matching");
867 bt_test_suite(t_match_outer_net
, "Testing random outer prefix matching");
868 bt_test_suite(t_trie_same
, "A trie filled forward should be same with a trie filled backward.");
869 bt_test_suite(t_trie_walk
, "Testing TRIE_WALK() on random tries");
870 bt_test_suite(t_trie_walk_to_root
, "Testing TRIE_WALK_TO_ROOT() on random tries");
872 // bt_test_suite(t_bench_trie_datasets_subset, "Benchmark tries from datasets by random subset of nets");
873 // bt_test_suite(t_bench_trie_datasets_random, "Benchmark tries from datasets by generated addresses");
875 return bt_exit_value();