]>
git.proxmox.com Git - mirror_frr.git/blob - tests/lib/test_nexthop_iter.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Recursive Nexthop Iterator test.
4 * This tests the ALL_NEXTHOPS macro.
6 * Copyright (C) 2012 by Open Source Routing.
7 * Copyright (C) 2012 by Internet Systems Consortium, Inc. ("ISC")
9 * This file is part of Quagga
13 #include "zebra/rib.h"
16 struct thread_master
*master
;
19 static void str_append(char **buf
, const char *repr
)
22 *buf
= realloc(*buf
, strlen(*buf
) + strlen(repr
) + 1);
24 strncpy((*buf
) + strlen(*buf
), repr
, strlen(repr
) + 1);
32 static void str_appendf(char **buf
, const char *format
, ...)
39 rv
= vasprintf(&pbuf
, format
, ap
);
43 str_append(buf
, pbuf
);
47 /* This structure contains a nexthop chain
48 * and its expected representation */
49 struct nexthop_chain
{
50 /* Head of the chain */
51 struct nexthop_group head
;
52 /* Last nexthop in top chain */
53 struct nexthop
*current_top
;
54 /* Last nexthop in current recursive chain */
55 struct nexthop
*current_recursive
;
56 /* Expected string representation. */
60 static struct nexthop_chain
*nexthop_chain_new(void)
62 struct nexthop_chain
*rv
;
64 rv
= calloc(sizeof(*rv
), 1);
69 static void nexthop_chain_add_top(struct nexthop_chain
*nc
)
73 nh
= calloc(sizeof(*nh
), 1);
76 if (nc
->head
.nexthop
) {
77 nc
->current_top
->next
= nh
;
78 nh
->prev
= nc
->current_top
;
81 nc
->head
.nexthop
= nc
->current_top
= nh
;
83 nc
->current_recursive
= NULL
;
84 str_appendf(&nc
->repr
, "%p\n", nh
);
87 static void add_string_representation(char **repr
, struct nexthop
*nh
)
89 struct nexthop
*parent
;
91 /* add indentations first */
94 str_appendf(repr
, " ");
95 parent
= parent
->rparent
;
97 str_appendf(repr
, "%p\n", nh
);
100 static void start_recursive_chain(struct nexthop_chain
*nc
, struct nexthop
*nh
)
102 SET_FLAG(nc
->current_top
->flags
, NEXTHOP_FLAG_RECURSIVE
);
103 nc
->current_top
->resolved
= nh
;
104 nh
->rparent
= nc
->current_top
;
105 nc
->current_recursive
= nh
;
107 static void nexthop_chain_add_recursive(struct nexthop_chain
*nc
)
111 nh
= calloc(sizeof(*nh
), 1);
114 assert(nc
->current_top
);
115 if (nc
->current_recursive
) {
116 nc
->current_recursive
->next
= nh
;
117 nh
->prev
= nc
->current_recursive
;
118 nh
->rparent
= nc
->current_recursive
->rparent
;
119 nc
->current_recursive
= nh
;
121 start_recursive_chain(nc
, nh
);
123 add_string_representation(&nc
->repr
, nh
);
126 static void nexthop_chain_add_recursive_level(struct nexthop_chain
*nc
)
130 nh
= calloc(sizeof(*nh
), 1);
133 assert(nc
->current_top
);
134 if (nc
->current_recursive
) {
135 SET_FLAG(nc
->current_recursive
->flags
, NEXTHOP_FLAG_RECURSIVE
);
136 nc
->current_recursive
->resolved
= nh
;
137 nh
->rparent
= nc
->current_recursive
;
138 nc
->current_recursive
= nh
;
140 start_recursive_chain(nc
, nh
);
142 add_string_representation(&nc
->repr
, nh
);
145 static void nexthop_clear_recursive(struct nexthop
*tcur
)
149 if (CHECK_FLAG(tcur
->flags
, NEXTHOP_FLAG_RECURSIVE
))
150 nexthop_clear_recursive(tcur
->resolved
);
152 nexthop_clear_recursive(tcur
->next
);
155 static void nexthop_chain_clear(struct nexthop_chain
*nc
)
157 nexthop_clear_recursive(nc
->head
.nexthop
);
158 nc
->head
.nexthop
= nc
->current_top
= nc
->current_recursive
= NULL
;
163 static void nexthop_chain_free(struct nexthop_chain
*nc
)
167 nexthop_chain_clear(nc
);
171 /* This function builds a string representation of
172 * the nexthop chain using the ALL_NEXTHOPS macro.
173 * It verifies that the ALL_NEXTHOPS macro iterated
174 * correctly over the nexthop chain by comparing the
175 * generated representation with the expected representation.
177 static void nexthop_chain_verify_iter(struct nexthop_chain
*nc
)
182 for (ALL_NEXTHOPS(nc
->head
, nh
))
183 add_string_representation(&repr
, nh
);
186 printf("===\n%s", repr
);
187 assert((!repr
&& !nc
->repr
)
188 || (repr
&& nc
->repr
&& !strcmp(repr
, nc
->repr
)));
192 /* This test run builds a simple nexthop chain
193 * with some recursive nexthops and verifies that
194 * the iterator works correctly in each stage along
197 static void test_run_first(void)
199 struct nexthop_chain
*nc
;
201 nc
= nexthop_chain_new();
202 nexthop_chain_verify_iter(nc
);
204 nexthop_chain_add_top(nc
);
205 nexthop_chain_verify_iter(nc
);
207 nexthop_chain_add_top(nc
);
208 nexthop_chain_verify_iter(nc
);
210 nexthop_chain_add_recursive(nc
);
211 nexthop_chain_verify_iter(nc
);
213 nexthop_chain_add_recursive(nc
);
214 nexthop_chain_verify_iter(nc
);
216 nexthop_chain_add_top(nc
);
217 nexthop_chain_verify_iter(nc
);
219 nexthop_chain_add_top(nc
);
220 nexthop_chain_verify_iter(nc
);
222 nexthop_chain_add_top(nc
);
223 nexthop_chain_verify_iter(nc
);
225 nexthop_chain_add_recursive(nc
);
226 nexthop_chain_verify_iter(nc
);
228 nexthop_chain_add_recursive(nc
);
229 nexthop_chain_verify_iter(nc
);
231 nexthop_chain_add_recursive(nc
);
232 nexthop_chain_verify_iter(nc
);
234 nexthop_chain_add_recursive_level(nc
);
235 nexthop_chain_verify_iter(nc
);
237 nexthop_chain_add_recursive(nc
);
238 nexthop_chain_verify_iter(nc
);
240 nexthop_chain_add_recursive(nc
);
241 nexthop_chain_verify_iter(nc
);
243 nexthop_chain_add_top(nc
);
244 nexthop_chain_verify_iter(nc
);
246 nexthop_chain_free(nc
);
249 /* This test run builds numerous random
250 * nexthop chain configurations and verifies
251 * that the iterator correctly progresses
253 static void test_run_prng(void)
255 struct nexthop_chain
*nc
;
259 nc
= nexthop_chain_new();
262 for (i
= 0; i
< 1000000; i
++) {
263 switch (prng_rand(prng
) % 10) {
265 nexthop_chain_clear(nc
);
272 nexthop_chain_add_top(nc
);
278 nexthop_chain_add_recursive(nc
);
282 nexthop_chain_add_recursive_level(nc
);
285 nexthop_chain_verify_iter(nc
);
287 nexthop_chain_free(nc
);
291 int main(int argc
, char **argv
)
293 if (argc
>= 2 && !strcmp("-v", argv
[1]))
296 printf("Simple test passed.\n");
298 printf("PRNG test passed.\n");