Annotation of embedaddon/quagga/tests/test-commands.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Test code for lib/command.c
! 3: *
! 4: * Copyright (C) 2013 by Open Source Routing.
! 5: * Copyright (C) 2013 by Internet Systems Consortium, Inc. ("ISC")
! 6: *
! 7: * This program reads in a list of commandlines from stdin
! 8: * and calls all the public functions of lib/command.c for
! 9: * both the given command lines and fuzzed versions thereof.
! 10: *
! 11: * The output is currently not validated but only logged. It can
! 12: * be diffed to find regressions between versions.
! 13: *
! 14: * Quagga is free software; you can redistribute it and/or modify it
! 15: * under the terms of the GNU General Public License as published by the
! 16: * Free Software Foundation; either version 2, or (at your option) any
! 17: * later version.
! 18: *
! 19: * Quagga is distributed in the hope that it will be useful, but
! 20: * WITHOUT ANY WARRANTY; without even the implied warranty of
! 21: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 22: * General Public License for more details.
! 23: *
! 24: * You should have received a copy of the GNU General Public License
! 25: * along with Quagga; see the file COPYING. If not, write to the Free
! 26: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
! 27: * 02111-1307, USA.
! 28: */
! 29:
! 30: #define REALLY_NEED_PLAIN_GETOPT 1
! 31:
! 32: #include <zebra.h>
! 33:
! 34: #include <stdio.h>
! 35: #include <stdlib.h>
! 36: #include <unistd.h>
! 37:
! 38: #include "command.h"
! 39: #include "memory.h"
! 40: #include "vector.h"
! 41: #include "prng.h"
! 42:
! 43: extern vector cmdvec;
! 44: extern struct cmd_node vty_node;
! 45: extern void test_init_cmd(void); /* provided in test-commands-defun.c */
! 46:
! 47: struct thread_master *master; /* dummy for libzebra*/
! 48:
! 49: static vector test_cmds;
! 50: static char test_buf[32768];
! 51:
! 52: static struct cmd_node bgp_node =
! 53: {
! 54: BGP_NODE,
! 55: "%s(config-router)# ",
! 56: };
! 57:
! 58: static struct cmd_node rip_node =
! 59: {
! 60: RIP_NODE,
! 61: "%s(config-router)# ",
! 62: };
! 63:
! 64: static struct cmd_node isis_node =
! 65: {
! 66: ISIS_NODE,
! 67: "%s(config-router)# ",
! 68: };
! 69:
! 70: static struct cmd_node interface_node =
! 71: {
! 72: INTERFACE_NODE,
! 73: "%s(config-if)# ",
! 74: };
! 75:
! 76: static struct cmd_node rmap_node =
! 77: {
! 78: RMAP_NODE,
! 79: "%s(config-route-map)# "
! 80: };
! 81:
! 82: static struct cmd_node zebra_node =
! 83: {
! 84: ZEBRA_NODE,
! 85: "%s(config-router)# "
! 86: };
! 87:
! 88: static struct cmd_node bgp_vpnv4_node =
! 89: {
! 90: BGP_VPNV4_NODE,
! 91: "%s(config-router-af)# "
! 92: };
! 93:
! 94: static struct cmd_node bgp_ipv4_node =
! 95: {
! 96: BGP_IPV4_NODE,
! 97: "%s(config-router-af)# "
! 98: };
! 99:
! 100: static struct cmd_node bgp_ipv4m_node =
! 101: {
! 102: BGP_IPV4M_NODE,
! 103: "%s(config-router-af)# "
! 104: };
! 105:
! 106: static struct cmd_node bgp_ipv6_node =
! 107: {
! 108: BGP_IPV6_NODE,
! 109: "%s(config-router-af)# "
! 110: };
! 111:
! 112: static struct cmd_node bgp_ipv6m_node =
! 113: {
! 114: BGP_IPV6M_NODE,
! 115: "%s(config-router-af)# "
! 116: };
! 117:
! 118: static struct cmd_node ospf_node =
! 119: {
! 120: OSPF_NODE,
! 121: "%s(config-router)# "
! 122: };
! 123:
! 124: static struct cmd_node ripng_node =
! 125: {
! 126: RIPNG_NODE,
! 127: "%s(config-router)# "
! 128: };
! 129:
! 130: static struct cmd_node ospf6_node =
! 131: {
! 132: OSPF6_NODE,
! 133: "%s(config-ospf6)# "
! 134: };
! 135:
! 136: static struct cmd_node babel_node =
! 137: {
! 138: BABEL_NODE,
! 139: "%s(config-babel)# "
! 140: };
! 141:
! 142: static struct cmd_node keychain_node =
! 143: {
! 144: KEYCHAIN_NODE,
! 145: "%s(config-keychain)# "
! 146: };
! 147:
! 148: static struct cmd_node keychain_key_node =
! 149: {
! 150: KEYCHAIN_KEY_NODE,
! 151: "%s(config-keychain-key)# "
! 152: };
! 153:
! 154: static int
! 155: test_callback(struct cmd_element *cmd, struct vty *vty, int argc, const char *argv[])
! 156: {
! 157: int offset;
! 158: int rv;
! 159: int i;
! 160:
! 161: offset = 0;
! 162: rv = snprintf(test_buf, sizeof(test_buf), "'%s'", cmd->string);
! 163: if (rv < 0)
! 164: abort();
! 165:
! 166: offset += rv;
! 167:
! 168: for (i = 0; i < argc; i++)
! 169: {
! 170: rv = snprintf(test_buf + offset, sizeof(test_buf) - offset, "%s'%s'",
! 171: (i == 0) ? ": " : ", ", argv[i]);
! 172: if (rv < 0)
! 173: abort();
! 174: offset += rv;
! 175: }
! 176:
! 177: return CMD_SUCCESS;
! 178: }
! 179:
! 180: static void
! 181: test_load(void)
! 182: {
! 183: char line[4096];
! 184:
! 185: test_cmds = vector_init(VECTOR_MIN_SIZE);
! 186:
! 187: while (fgets(line, sizeof(line), stdin) != NULL)
! 188: {
! 189: if (strlen(line))
! 190: line[strlen(line) - 1] = '\0';
! 191: if (line[0] == '#')
! 192: continue;
! 193: vector_set(test_cmds, XSTRDUP(MTYPE_STRVEC, line));
! 194: }
! 195: }
! 196:
! 197: static void
! 198: test_init(void)
! 199: {
! 200: unsigned int node;
! 201: unsigned int i;
! 202: struct cmd_node *cnode;
! 203: struct cmd_element *cmd;
! 204:
! 205: cmd_init(1);
! 206:
! 207: install_node (&bgp_node, NULL);
! 208: install_node (&rip_node, NULL);
! 209: install_node (&interface_node, NULL);
! 210: install_node (&rmap_node, NULL);
! 211: install_node (&zebra_node, NULL);
! 212: install_node (&bgp_vpnv4_node, NULL);
! 213: install_node (&bgp_ipv4_node, NULL);
! 214: install_node (&bgp_ipv4m_node, NULL);
! 215: install_node (&bgp_ipv6_node, NULL);
! 216: install_node (&bgp_ipv6m_node, NULL);
! 217: install_node (&ospf_node, NULL);
! 218: install_node (&ripng_node, NULL);
! 219: install_node (&ospf6_node, NULL);
! 220: install_node (&babel_node, NULL);
! 221: install_node (&keychain_node, NULL);
! 222: install_node (&keychain_key_node, NULL);
! 223: install_node (&isis_node, NULL);
! 224: install_node (&vty_node, NULL);
! 225:
! 226: test_init_cmd();
! 227:
! 228: for (node = 0; node < vector_active(cmdvec); node++)
! 229: if ((cnode = vector_slot(cmdvec, node)) != NULL)
! 230: for (i = 0; i < vector_active(cnode->cmd_vector); i++)
! 231: if ((cmd = vector_slot(cnode->cmd_vector, i)) != NULL)
! 232: {
! 233: cmd->daemon = 0;
! 234: cmd->func = test_callback;
! 235: }
! 236: test_load();
! 237: vty_init_vtysh();
! 238: }
! 239:
! 240: static void
! 241: test_terminate(void)
! 242: {
! 243: unsigned int i;
! 244:
! 245: vty_terminate();
! 246: for (i = 0; i < vector_active(test_cmds); i++)
! 247: XFREE(MTYPE_STRVEC, vector_slot(test_cmds, i));
! 248: vector_free(test_cmds);
! 249: cmd_terminate();
! 250: }
! 251:
! 252: static void
! 253: test_run(struct prng *prng, struct vty *vty, const char *cmd, unsigned int edit_dist, unsigned int node_index, int verbose)
! 254: {
! 255: const char *test_str;
! 256: vector vline;
! 257: int ret;
! 258: unsigned int i;
! 259: char **completions;
! 260: unsigned int j;
! 261: struct cmd_node *cnode;
! 262: vector descriptions;
! 263: int appended_null;
! 264: int no_match;
! 265:
! 266: test_str = prng_fuzz(prng, cmd, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_:. /", edit_dist);
! 267: vline = cmd_make_strvec(test_str);
! 268:
! 269: if (vline == NULL)
! 270: return;
! 271:
! 272: appended_null = 0;
! 273: for (i = 0; i < vector_active(cmdvec); i++)
! 274: if ((cnode = vector_slot(cmdvec, i)) != NULL)
! 275: {
! 276: if (node_index != (unsigned int)-1 && i != node_index)
! 277: continue;
! 278:
! 279: if (appended_null)
! 280: {
! 281: vector_unset(vline, vector_active(vline) - 1);
! 282: appended_null = 0;
! 283: }
! 284: vty->node = cnode->node;
! 285: test_buf[0] = '\0';
! 286: ret = cmd_execute_command(vline, vty, NULL, 0);
! 287: no_match = (ret == CMD_ERR_NO_MATCH);
! 288: if (verbose || !no_match)
! 289: printf("execute relaxed '%s'@%d: rv==%d%s%s\n",
! 290: test_str,
! 291: cnode->node,
! 292: ret,
! 293: (test_buf[0] != '\0') ? ", " : "",
! 294: test_buf);
! 295:
! 296: vty->node = cnode->node;
! 297: test_buf[0] = '\0';
! 298: ret = cmd_execute_command_strict(vline, vty, NULL);
! 299: if (verbose || !no_match)
! 300: printf("execute strict '%s'@%d: rv==%d%s%s\n",
! 301: test_str,
! 302: cnode->node,
! 303: ret,
! 304: (test_buf[0] != '\0') ? ", " : "",
! 305: test_buf);
! 306:
! 307: if (isspace((int) test_str[strlen(test_str) - 1]))
! 308: {
! 309: vector_set (vline, NULL);
! 310: appended_null = 1;
! 311: }
! 312:
! 313: vty->node = cnode->node;
! 314: completions = cmd_complete_command(vline, vty, &ret);
! 315: if (verbose || !no_match)
! 316: printf("complete '%s'@%d: rv==%d\n",
! 317: test_str,
! 318: cnode->node,
! 319: ret);
! 320: if (completions != NULL)
! 321: {
! 322: for (j = 0; completions[j] != NULL; j++)
! 323: {
! 324: printf(" '%s'\n", completions[j]);
! 325: XFREE(MTYPE_TMP, completions[j]);
! 326: }
! 327: XFREE(MTYPE_VECTOR_INDEX, completions);
! 328: }
! 329:
! 330: vty->node = cnode->node;
! 331: descriptions = cmd_describe_command(vline, vty, &ret);
! 332: if (verbose || !no_match)
! 333: printf("describe '%s'@%d: rv==%d\n",
! 334: test_str,
! 335: cnode->node,
! 336: ret);
! 337: if (descriptions != NULL)
! 338: {
! 339: for (j = 0; j < vector_active(descriptions); j++)
! 340: {
! 341: struct cmd_token *cmd = vector_slot(descriptions, j);
! 342: printf(" '%s' '%s'\n", cmd->cmd, cmd->desc);
! 343: }
! 344: vector_free(descriptions);
! 345: }
! 346: }
! 347: cmd_free_strvec(vline);
! 348: }
! 349:
! 350: int
! 351: main(int argc, char **argv)
! 352: {
! 353: int opt;
! 354: struct prng *prng;
! 355: struct vty *vty;
! 356: unsigned int edit_distance;
! 357: unsigned int max_edit_distance;
! 358: unsigned int node_index;
! 359: int verbose;
! 360: unsigned int test_cmd;
! 361: unsigned int iteration;
! 362: unsigned int num_iterations;
! 363:
! 364: max_edit_distance = 3;
! 365: node_index = -1;
! 366: verbose = 0;
! 367:
! 368: while ((opt = getopt(argc, argv, "e:n:v")) != -1)
! 369: {
! 370: switch (opt)
! 371: {
! 372: case 'e':
! 373: max_edit_distance = atoi(optarg);
! 374: break;
! 375: case 'n':
! 376: node_index = atoi(optarg);
! 377: break;
! 378: case 'v':
! 379: verbose++;
! 380: break;
! 381: default:
! 382: fprintf(stderr, "Usage: %s [-e <edit_dist>] [-n <node_idx>] [-v]\n", argv[0]);
! 383: exit(1);
! 384: break;
! 385: }
! 386: }
! 387:
! 388: test_init();
! 389: prng = prng_new(0);
! 390:
! 391: vty = vty_new();
! 392: vty->type = VTY_TERM;
! 393:
! 394: fprintf(stderr, "Progress:\n0/%u", vector_active(test_cmds));
! 395: for (test_cmd = 0; test_cmd < vector_active(test_cmds); test_cmd++)
! 396: {
! 397: for (edit_distance = 0;
! 398: edit_distance <= max_edit_distance;
! 399: edit_distance++)
! 400: {
! 401: num_iterations = 1 << edit_distance;
! 402: num_iterations *= num_iterations * num_iterations;
! 403:
! 404: for (iteration = 0; iteration < num_iterations; iteration++)
! 405: test_run(prng, vty, vector_slot(test_cmds, test_cmd), edit_distance, node_index, verbose);
! 406: }
! 407: fprintf(stderr, "\r%u/%u", test_cmd + 1, vector_active(test_cmds));
! 408: }
! 409: fprintf(stderr, "\nDone.\n");
! 410:
! 411: vty_close(vty);
! 412: prng_free(prng);
! 413: test_terminate();
! 414: return 0;
! 415: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>