4.14.7 Main Program |
Everything comes together in the main program. The test itself (default or overflow) is selected with enum test:
138. <Test declarations 121> += /* Test to perform. */ enum test
{ TST_CORRECTNESS, /* Default tests. */ TST_OVERFLOW, /* Stack overflow test. */ TST_NULL /* No test, just overhead. */ };
The program's entire behavior is controlled by struct test_options, defined as follows:
139. <Test declarations 121> += /* Program options. */ struct test_options
{ enum test test; /* Test to perform. */ enum insert_order insert_order; /* Insertion order. */ enum delete_order delete_order; /* Deletion order. */ enum mt_policy alloc_policy; /* Allocation policy. */ int alloc_arg[2]; /* Policy arguments. */ int alloc_incr; /* Amount to increment alloc_arg each iteration. */ int node_cnt; /* Number of nodes in tree. */ int iter_cnt; /* Number of runs. */ int seed_given; /* Seed provided on command line? */ unsigned seed; /* Random number seed. */ int verbosity; /* Verbosity level, 0=default. */ int nonstop; /* Don't stop after one error? */ };
The main() function for the test program is perhaps a bit long, but simple. It begins by parsing the command line and allocating memory, then repeats a loop once for each repetition of the test. Within the loop, an insertion and a deletion order are selected, the memory tracker is set up, and test function (either test() or test_overflow()) is called.
140. <Test main program 140> = int
main (int argc, char *argv[])
{ struct test_options opts; /* Command-line options. */ int *insert, *delete; /* Insertion and deletion orders. */ int success; /* Everything okay so far? */ /* Initialize pgm_name, using argv[0] if sensible. */ pgm_name = argv[0] != NULL && argv[0][0] != '\0' ? argv[0] : "bsttest"; /* Parse command line into options. */ parse_command_line (argv, &opts); if (opts.verbosity >= 0) fputs ("bsttest for GNU libavl 2.0.2; use -help to get help.\n", stdout); if (!opts.seed_given)
opts.seed = time_seed () % 32768u; insert = xmalloc (sizeof *insert * opts.node_cnt); delete = xmalloc (sizeof *delete * opts.node_cnt); /* Run the tests. */ success = 1; while (opts.iter_cnt–)
{ struct mt_allocator *alloc; if (opts.verbosity >= 0)
{ printf ("Testing seed=%u", opts.seed); if (opts.alloc_incr)
printf (", alloc arg=%d", opts.alloc_arg[0]); printf ("...\n"); fflush (stdout); } /* Generate insertion and deletion order. Seed them separately to ensure deletion order is independent of insertion order. */ srand (opts.seed); gen_insertions (opts.node_cnt, opts.insert_order, insert); srand (++opts.seed); gen_deletions (opts.node_cnt, opts.delete_order, insert, delete); if (opts.verbosity >= 1)
{ int i; printf (" Insertion order:"); for (i = 0; i < opts.node_cnt; i++) printf (" %d", insert[i]); printf (".\n"); if (opts.test == TST_CORRECTNESS)
{ printf ("Deletion order:"); for (i = 0; i < opts.node_cnt; i++) printf (" %d", delete[i]); printf (".\n"); } } alloc = mt_create (opts.alloc_policy, opts.alloc_arg, opts.verbosity); { int okay; struct libavl_allocator *a = mt_allocator (alloc); switch (opts.test)
{ case TST_CORRECTNESS: okay = test_correctness (a, insert, delete, opts.node_cnt,
opts.verbosity); break; case TST_OVERFLOW: okay = test_overflow (a, insert, opts.node_cnt, opts.verbosity); break; case TST_NULL:
okay = 1;
break; default:
assert (0); } if (okay)
{ if (opts.verbosity >= 1) printf (" No errors.\n"); }
else
{ success = 0; printf (" Error!\n"); } } mt_destroy (alloc); opts.alloc_arg[0] += opts.alloc_incr; if (!success && !opts.nonstop) break; } free (delete); free (insert); return success ? EXIT_SUCCESS : EXIT_FAILURE; }
This code is included in 97.
The main program initializes our single global variable, pgm_name, which receives the name of the program at start of execution:
141. <Test declarations 121> += /* Program name. */ char *pgm_name;