]>
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_RO 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
21 * along with Quagga; see the file COPYING. If not, write to the Free
22 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 #include "zebra/rib.h"
30 struct thread_master
*master
;
33 static void str_append(char **buf
, const char *repr
)
36 *buf
= realloc(*buf
, strlen(*buf
) + strlen(repr
) + 1);
38 strncpy((*buf
) + strlen(*buf
), repr
, strlen(repr
) + 1);
45 static void str_appendf(char **buf
, const char *format
, ...)
52 rv
= vasprintf(&pbuf
, format
, ap
);
56 str_append(buf
, pbuf
);
60 /* This structure contains a nexthop chain
61 * and its expected representation */
62 struct nexthop_chain
{
63 /* Head of the chain */
65 /* Last nexthop in top chain */
66 struct nexthop
*current_top
;
67 /* Last nexthop in current recursive chain */
68 struct nexthop
*current_recursive
;
69 /* Expected string representation. */
73 static struct nexthop_chain
*nexthop_chain_new(void)
75 struct nexthop_chain
*rv
;
77 rv
= calloc(sizeof(*rv
), 1);
82 static void nexthop_chain_add_top(struct nexthop_chain
*nc
)
86 nh
= calloc(sizeof(*nh
), 1);
90 nc
->current_top
->next
= nh
;
91 nh
->prev
= nc
->current_top
;
94 nc
->head
= nc
->current_top
= nh
;
96 nc
->current_recursive
= NULL
;
97 str_appendf(&nc
->repr
, "%p\n", nh
);
100 static void nexthop_chain_add_recursive(struct nexthop_chain
*nc
)
104 nh
= calloc(sizeof(*nh
), 1);
107 assert(nc
->current_top
);
108 if (nc
->current_recursive
) {
109 nc
->current_recursive
->next
= nh
;
110 nh
->prev
= nc
->current_recursive
;
111 nc
->current_recursive
= nh
;
113 SET_FLAG(nc
->current_top
->flags
, NEXTHOP_FLAG_RECURSIVE
);
114 nc
->current_top
->resolved
= nh
;
115 nc
->current_recursive
= nh
;
117 str_appendf(&nc
->repr
, " %p\n", nh
);
120 static void nexthop_chain_clear(struct nexthop_chain
*nc
)
122 struct nexthop
*tcur
, *tnext
;
124 for (tcur
= nc
->head
; tcur
; tcur
= tnext
) {
126 if (CHECK_FLAG(tcur
->flags
, NEXTHOP_FLAG_RECURSIVE
)) {
127 struct nexthop
*rcur
, *rnext
;
128 for (rcur
= tcur
->resolved
; rcur
; rcur
= rnext
) {
135 nc
->head
= nc
->current_top
= nc
->current_recursive
= NULL
;
140 static void nexthop_chain_free(struct nexthop_chain
*nc
)
144 nexthop_chain_clear(nc
);
148 /* This function builds a string representation of
149 * the nexthop chain using the ALL_NEXTHOPS_RO macro.
150 * It verifies that the ALL_NEXTHOPS_RO macro iterated
151 * correctly over the nexthop chain by comparing the
152 * generated representation with the expected representation.
154 static void nexthop_chain_verify_iter(struct nexthop_chain
*nc
)
156 struct nexthop
*nh
, *tnh
;
160 for (ALL_NEXTHOPS_RO(nc
->head
, nh
, tnh
, recursing
)) {
162 str_appendf(&repr
, " %p\n", nh
);
164 str_appendf(&repr
, "%p\n", nh
);
168 printf("===\n%s", repr
);
169 assert((!repr
&& !nc
->repr
)
170 || (repr
&& nc
->repr
&& !strcmp(repr
, nc
->repr
)));
174 /* This test run builds a simple nexthop chain
175 * with some recursive nexthops and verifies that
176 * the iterator works correctly in each stage along
179 static void test_run_first(void)
181 struct nexthop_chain
*nc
;
183 nc
= nexthop_chain_new();
184 nexthop_chain_verify_iter(nc
);
186 nexthop_chain_add_top(nc
);
187 nexthop_chain_verify_iter(nc
);
189 nexthop_chain_add_top(nc
);
190 nexthop_chain_verify_iter(nc
);
192 nexthop_chain_add_recursive(nc
);
193 nexthop_chain_verify_iter(nc
);
195 nexthop_chain_add_recursive(nc
);
196 nexthop_chain_verify_iter(nc
);
198 nexthop_chain_add_top(nc
);
199 nexthop_chain_verify_iter(nc
);
201 nexthop_chain_add_top(nc
);
202 nexthop_chain_verify_iter(nc
);
204 nexthop_chain_add_top(nc
);
205 nexthop_chain_verify_iter(nc
);
207 nexthop_chain_add_recursive(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_free(nc
);
219 /* This test run builds numerous random
220 * nexthop chain configurations and verifies
221 * that the iterator correctly progresses
223 static void test_run_prng(void)
225 struct nexthop_chain
*nc
;
229 nc
= nexthop_chain_new();
232 for (i
= 0; i
< 1000000; i
++) {
233 switch (prng_rand(prng
) % 10) {
235 nexthop_chain_clear(nc
);
242 nexthop_chain_add_top(nc
);
249 nexthop_chain_add_recursive(nc
);
252 nexthop_chain_verify_iter(nc
);
254 nexthop_chain_free(nc
);
258 int main(int argc
, char **argv
)
260 if (argc
>= 2 && !strcmp("-v", argv
[1]))
263 printf("Simple test passed.\n");
265 printf("PRNG test passed.\n");