Annotation of embedaddon/quagga/tests/test-nexthop-iter.c, revision 1.1.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>