]>
git.proxmox.com Git - mirror_frr.git/blob - tests/lib/test_nexthop_iter.c
2 * Recursive Nexthop Iterator test.
3 * This tests the ALL_NEXTHOPS macro.
5 * Copyright (C) 2012 by Open Source Routing.
6 * Copyright (C) 2012 by Internet Systems Consortium, Inc. ("ISC")
8 * This file is part of Quagga
10 * Quagga is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2, or (at your option) any
15 * Quagga is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; see the file COPYING; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "zebra/rib.h"
29 struct thread_master
*master
;
32 static void str_append(char **buf
, const char *repr
)
35 *buf
= realloc(*buf
, strlen(*buf
) + strlen(repr
) + 1);
37 strncpy((*buf
) + strlen(*buf
), repr
, strlen(repr
) + 1);
44 static void str_appendf(char **buf
, const char *format
, ...)
51 rv
= vasprintf(&pbuf
, format
, ap
);
55 str_append(buf
, pbuf
);
59 /* This structure contains a nexthop chain
60 * and its expected representation */
61 struct nexthop_chain
{
62 /* Head of the chain */
64 /* Last nexthop in top chain */
65 struct nexthop
*current_top
;
66 /* Last nexthop in current recursive chain */
67 struct nexthop
*current_recursive
;
68 /* Expected string representation. */
72 static struct nexthop_chain
*nexthop_chain_new(void)
74 struct nexthop_chain
*rv
;
76 rv
= calloc(sizeof(*rv
), 1);
81 static void nexthop_chain_add_top(struct nexthop_chain
*nc
)
85 nh
= calloc(sizeof(*nh
), 1);
89 nc
->current_top
->next
= nh
;
90 nh
->prev
= nc
->current_top
;
93 nc
->head
= nc
->current_top
= nh
;
95 nc
->current_recursive
= NULL
;
96 str_appendf(&nc
->repr
, "%p\n", nh
);
99 static void add_string_representation(char **repr
, struct nexthop
*nh
)
101 struct nexthop
*parent
;
103 /* add indentations first */
104 parent
= nh
->rparent
;
106 str_appendf(repr
, " ");
107 parent
= parent
->rparent
;
109 str_appendf(repr
, "%p\n", nh
);
112 static void start_recursive_chain(struct nexthop_chain
*nc
, struct nexthop
*nh
)
114 SET_FLAG(nc
->current_top
->flags
, NEXTHOP_FLAG_RECURSIVE
);
115 nc
->current_top
->resolved
= nh
;
116 nh
->rparent
= nc
->current_top
;
117 nc
->current_recursive
= nh
;
119 static void nexthop_chain_add_recursive(struct nexthop_chain
*nc
)
123 nh
= calloc(sizeof(*nh
), 1);
126 assert(nc
->current_top
);
127 if (nc
->current_recursive
) {
128 nc
->current_recursive
->next
= nh
;
129 nh
->prev
= nc
->current_recursive
;
130 nh
->rparent
= nc
->current_recursive
->rparent
;
131 nc
->current_recursive
= nh
;
133 start_recursive_chain(nc
, nh
);
135 add_string_representation(&nc
->repr
, nh
);
138 static void nexthop_chain_add_recursive_level(struct nexthop_chain
*nc
)
142 nh
= calloc(sizeof(*nh
), 1);
145 assert(nc
->current_top
);
146 if (nc
->current_recursive
) {
147 SET_FLAG(nc
->current_recursive
->flags
, NEXTHOP_FLAG_RECURSIVE
);
148 nc
->current_recursive
->resolved
= nh
;
149 nh
->rparent
= nc
->current_recursive
;
150 nc
->current_recursive
= nh
;
152 start_recursive_chain(nc
, nh
);
154 add_string_representation(&nc
->repr
, nh
);
157 static void nexthop_clear_recursive(struct nexthop
*tcur
)
161 if (CHECK_FLAG(tcur
->flags
, NEXTHOP_FLAG_RECURSIVE
))
162 nexthop_clear_recursive(tcur
->resolved
);
164 nexthop_clear_recursive(tcur
->next
);
167 static void nexthop_chain_clear(struct nexthop_chain
*nc
)
169 nexthop_clear_recursive(nc
->head
);
170 nc
->head
= nc
->current_top
= nc
->current_recursive
= NULL
;
175 static void nexthop_chain_free(struct nexthop_chain
*nc
)
179 nexthop_chain_clear(nc
);
183 /* This function builds a string representation of
184 * the nexthop chain using the ALL_NEXTHOPS macro.
185 * It verifies that the ALL_NEXTHOPS macro iterated
186 * correctly over the nexthop chain by comparing the
187 * generated representation with the expected representation.
189 static void nexthop_chain_verify_iter(struct nexthop_chain
*nc
)
194 for (ALL_NEXTHOPS(nc
->head
, nh
))
195 add_string_representation(&repr
, nh
);
198 printf("===\n%s", repr
);
199 assert((!repr
&& !nc
->repr
)
200 || (repr
&& nc
->repr
&& !strcmp(repr
, nc
->repr
)));
204 /* This test run builds a simple nexthop chain
205 * with some recursive nexthops and verifies that
206 * the iterator works correctly in each stage along
209 static void test_run_first(void)
211 struct nexthop_chain
*nc
;
213 nc
= nexthop_chain_new();
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_recursive(nc
);
223 nexthop_chain_verify_iter(nc
);
225 nexthop_chain_add_recursive(nc
);
226 nexthop_chain_verify_iter(nc
);
228 nexthop_chain_add_top(nc
);
229 nexthop_chain_verify_iter(nc
);
231 nexthop_chain_add_top(nc
);
232 nexthop_chain_verify_iter(nc
);
234 nexthop_chain_add_top(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_recursive(nc
);
244 nexthop_chain_verify_iter(nc
);
246 nexthop_chain_add_recursive_level(nc
);
247 nexthop_chain_verify_iter(nc
);
249 nexthop_chain_add_recursive(nc
);
250 nexthop_chain_verify_iter(nc
);
252 nexthop_chain_add_recursive(nc
);
253 nexthop_chain_verify_iter(nc
);
255 nexthop_chain_add_top(nc
);
256 nexthop_chain_verify_iter(nc
);
258 nexthop_chain_free(nc
);
261 /* This test run builds numerous random
262 * nexthop chain configurations and verifies
263 * that the iterator correctly progresses
265 static void test_run_prng(void)
267 struct nexthop_chain
*nc
;
271 nc
= nexthop_chain_new();
274 for (i
= 0; i
< 1000000; i
++) {
275 switch (prng_rand(prng
) % 10) {
277 nexthop_chain_clear(nc
);
284 nexthop_chain_add_top(nc
);
290 nexthop_chain_add_recursive(nc
);
294 nexthop_chain_add_recursive_level(nc
);
297 nexthop_chain_verify_iter(nc
);
299 nexthop_chain_free(nc
);
303 int main(int argc
, char **argv
)
305 if (argc
>= 2 && !strcmp("-v", argv
[1]))
308 printf("Simple test passed.\n");
310 printf("PRNG test passed.\n");