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>