File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / tests / test-nexthop-iter.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:12 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    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>