Annotation of embedaddon/quagga/tests/test-nexthop-iter.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Recursive Nexthop Iterator test.
! 3: * This tests the ALL_NEXTHOPS_RO macro.
! 4: *
! 5: * Copyright (C) 2012 by Open Source Routing.
! 6: * Copyright (C) 2012 by Internet Systems Consortium, Inc. ("ISC")
! 7: *
! 8: * This file is part of Quagga
! 9: *
! 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
! 13: * later version.
! 14: *
! 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.
! 19: *
! 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
! 23: * 02111-1307, USA.
! 24: */
! 25:
! 26: #include <zebra.h>
! 27: #include "zebra/rib.h"
! 28: #include "prng.h"
! 29:
! 30: struct thread_master *master;
! 31: static int verbose;
! 32:
! 33: static void
! 34: str_append(char **buf, const char *repr)
! 35: {
! 36: if (*buf)
! 37: {
! 38: *buf = realloc(*buf, strlen(*buf) + strlen(repr) + 1);
! 39: assert(*buf);
! 40: strncpy((*buf) + strlen(*buf), repr, strlen(repr) + 1);
! 41: }
! 42: else
! 43: {
! 44: *buf = strdup(repr);
! 45: assert(*buf);
! 46: }
! 47: }
! 48:
! 49: static void
! 50: str_appendf(char **buf, const char *format, ...)
! 51: {
! 52: va_list ap;
! 53: int rv;
! 54: char *pbuf;
! 55:
! 56: va_start(ap, format);
! 57: rv = vasprintf(&pbuf, format, ap);
! 58: va_end(ap);
! 59: assert(rv >= 0);
! 60:
! 61: str_append(buf, pbuf);
! 62: free(pbuf);
! 63: }
! 64:
! 65: /* This structure contains a nexthop chain
! 66: * and its expected representation */
! 67: struct nexthop_chain
! 68: {
! 69: /* Head of the chain */
! 70: struct nexthop *head;
! 71: /* Last nexthop in top chain */
! 72: struct nexthop *current_top;
! 73: /* Last nexthop in current recursive chain */
! 74: struct nexthop *current_recursive;
! 75: /* Expected string representation. */
! 76: char *repr;
! 77: };
! 78:
! 79: static struct nexthop_chain*
! 80: nexthop_chain_new(void)
! 81: {
! 82: struct nexthop_chain *rv;
! 83:
! 84: rv = calloc(sizeof(*rv), 1);
! 85: assert(rv);
! 86: return rv;
! 87: }
! 88:
! 89: static void
! 90: nexthop_chain_add_top(struct nexthop_chain *nc)
! 91: {
! 92: struct nexthop *nh;
! 93:
! 94: nh = calloc(sizeof(*nh), 1);
! 95: assert(nh);
! 96:
! 97: if (nc->head)
! 98: {
! 99: nc->current_top->next = nh;
! 100: nh->prev = nc->current_top;
! 101: nc->current_top = nh;
! 102: }
! 103: else
! 104: {
! 105: nc->head = nc->current_top = nh;
! 106: }
! 107: nc->current_recursive = NULL;
! 108: str_appendf(&nc->repr, "%p\n", nh);
! 109: }
! 110:
! 111: static void
! 112: nexthop_chain_add_recursive(struct nexthop_chain *nc)
! 113: {
! 114: struct nexthop *nh;
! 115:
! 116: nh = calloc(sizeof(*nh), 1);
! 117: assert(nh);
! 118:
! 119: assert(nc->current_top);
! 120: if (nc->current_recursive)
! 121: {
! 122: nc->current_recursive->next = nh;
! 123: nh->prev = nc->current_recursive;
! 124: nc->current_recursive = nh;
! 125: }
! 126: else
! 127: {
! 128: SET_FLAG(nc->current_top->flags, NEXTHOP_FLAG_RECURSIVE);
! 129: nc->current_top->resolved = nh;
! 130: nc->current_recursive = nh;
! 131: }
! 132: str_appendf(&nc->repr, " %p\n", nh);
! 133: }
! 134:
! 135: static void
! 136: nexthop_chain_clear(struct nexthop_chain *nc)
! 137: {
! 138: struct nexthop *tcur, *tnext;
! 139:
! 140: for (tcur = nc->head; tcur; tcur = tnext)
! 141: {
! 142: tnext = tcur->next;
! 143: if (CHECK_FLAG(tcur->flags, NEXTHOP_FLAG_RECURSIVE))
! 144: {
! 145: struct nexthop *rcur, *rnext;
! 146: for (rcur = tcur->resolved; rcur; rcur = rnext)
! 147: {
! 148: rnext = rcur->next;
! 149: free(rcur);
! 150: }
! 151: }
! 152: free(tcur);
! 153: }
! 154: nc->head = nc->current_top = nc->current_recursive = NULL;
! 155: free(nc->repr);
! 156: nc->repr = NULL;
! 157: }
! 158:
! 159: static void
! 160: nexthop_chain_free(struct nexthop_chain *nc)
! 161: {
! 162: if (!nc)
! 163: return;
! 164: nexthop_chain_clear(nc);
! 165: free(nc);
! 166: }
! 167:
! 168: /* This function builds a string representation of
! 169: * the nexthop chain using the ALL_NEXTHOPS_RO macro.
! 170: * It verifies that the ALL_NEXTHOPS_RO macro iterated
! 171: * correctly over the nexthop chain by comparing the
! 172: * generated representation with the expected representation.
! 173: */
! 174: static void
! 175: nexthop_chain_verify_iter(struct nexthop_chain *nc)
! 176: {
! 177: struct nexthop *nh, *tnh;
! 178: int recursing;
! 179: char *repr = NULL;
! 180:
! 181: for (ALL_NEXTHOPS_RO(nc->head, nh, tnh, recursing))
! 182: {
! 183: if (recursing)
! 184: str_appendf(&repr, " %p\n", nh);
! 185: else
! 186: str_appendf(&repr, "%p\n", nh);
! 187: }
! 188:
! 189: if (repr && verbose)
! 190: printf("===\n%s", repr);
! 191: assert((!repr && !nc->repr) || (repr && nc->repr && !strcmp(repr, nc->repr)));
! 192: free(repr);
! 193: }
! 194:
! 195: /* This test run builds a simple nexthop chain
! 196: * with some recursive nexthops and verifies that
! 197: * the iterator works correctly in each stage along
! 198: * the way.
! 199: */
! 200: static void
! 201: test_run_first(void)
! 202: {
! 203: struct nexthop_chain *nc;
! 204:
! 205: nc = nexthop_chain_new();
! 206: nexthop_chain_verify_iter(nc);
! 207:
! 208: nexthop_chain_add_top(nc);
! 209: nexthop_chain_verify_iter(nc);
! 210:
! 211: nexthop_chain_add_top(nc);
! 212: nexthop_chain_verify_iter(nc);
! 213:
! 214: nexthop_chain_add_recursive(nc);
! 215: nexthop_chain_verify_iter(nc);
! 216:
! 217: nexthop_chain_add_recursive(nc);
! 218: nexthop_chain_verify_iter(nc);
! 219:
! 220: nexthop_chain_add_top(nc);
! 221: nexthop_chain_verify_iter(nc);
! 222:
! 223: nexthop_chain_add_top(nc);
! 224: nexthop_chain_verify_iter(nc);
! 225:
! 226: nexthop_chain_add_top(nc);
! 227: nexthop_chain_verify_iter(nc);
! 228:
! 229: nexthop_chain_add_recursive(nc);
! 230: nexthop_chain_verify_iter(nc);
! 231:
! 232: nexthop_chain_add_recursive(nc);
! 233: nexthop_chain_verify_iter(nc);
! 234:
! 235: nexthop_chain_add_recursive(nc);
! 236: nexthop_chain_verify_iter(nc);
! 237:
! 238: nexthop_chain_free(nc);
! 239: }
! 240:
! 241: /* This test run builds numerous random
! 242: * nexthop chain configurations and verifies
! 243: * that the iterator correctly progresses
! 244: * through each. */
! 245: static void
! 246: test_run_prng(void)
! 247: {
! 248: struct nexthop_chain *nc;
! 249: struct prng *prng;
! 250: int i;
! 251:
! 252: nc = nexthop_chain_new();
! 253: prng = prng_new(0);
! 254:
! 255: for (i = 0; i < 1000000; i++)
! 256: {
! 257: switch (prng_rand(prng) % 10)
! 258: {
! 259: case 0:
! 260: nexthop_chain_clear(nc);
! 261: break;
! 262: case 1:
! 263: case 2:
! 264: case 3:
! 265: case 4:
! 266: case 5:
! 267: nexthop_chain_add_top(nc);
! 268: break;
! 269: case 6:
! 270: case 7:
! 271: case 8:
! 272: case 9:
! 273: if (nc->current_top)
! 274: nexthop_chain_add_recursive(nc);
! 275: break;
! 276: }
! 277: nexthop_chain_verify_iter(nc);
! 278: }
! 279: nexthop_chain_free(nc);
! 280: prng_free(prng);
! 281: }
! 282:
! 283: int main(int argc, char **argv)
! 284: {
! 285: if (argc >= 2 && !strcmp("-v", argv[1]))
! 286: verbose = 1;
! 287: test_run_first();
! 288: printf("Simple test passed.\n");
! 289: test_run_prng();
! 290: printf("PRNG test passed.\n");
! 291: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>