4.14.3 Testing Overflow |
Testing for overflow requires an entirely different set of test functions. The idea is to create a too-tall tree using one of the pathological insertion orders (ascending, descending, zig-zag, shifted ascending), then try out each of the functions that can overflow on it and make sure that they behave as they should.
There is a separate test function for each function that can overflow a stack but which is not tested by test(). These functions are called by driver function test_overflow(), which also takes care of creating, populating, and destroying the tree.
123. <BST overflow test function 123> = <Overflow testers 125> /* Tests the tree routines for proper handling of overflows. Inserting the n elements of order[] should produce a tree with height greater than BST_MAX_HEIGHT. Uses allocator as the allocator for tree and node data. Use verbosity to set the level of chatter on stdout. */ int
test_overflow (struct libavl_allocator *allocator,
int order[], int n, int verbosity)
{ /* An overflow tester function. */ typedef int test_func (struct bst_table *, int n); /* An overflow tester. */ struct test
{ test_func *func; /* Tester function. */ const char *name; /* Test name. */ }; /* All the overflow testers. */ static const struct test test[] =
{ {test_bst_t_first, "first item"}, {test_bst_t_last, "last item"}, {test_bst_t_find, "find item"}, {test_bst_t_insert, "insert item"}, {test_bst_t_next, "next item"}, {test_bst_t_prev, "previous item"}, {test_bst_copy, "copy tree"}, }; const struct test *i; /* Iterator. */ /* Run all the overflow testers. */ for (i = test; i < test + sizeof test / sizeof *test; i++)
{ struct bst_table *tree; int j; if (verbosity >= 2)
printf (" Running %s test...\n", i->name); tree = bst_create (compare_ints, NULL, allocator); if (tree == NULL)
{ printf (" Out of memory creating tree.\n"); return 1; } for (j = 0; j < n; j++)
{ void **p = bst_probe (tree, &order[j]); if (p == NULL || *p != &order[j])
{ if (p == NULL && verbosity >= 0) printf (" Out of memory in insertion.\n"); else if (p != NULL)
printf (" Duplicate item in tree!\n"); bst_destroy (tree, NULL); return p == NULL; } } if (i->func (tree, n) == 0) return 0; if (verify_tree (tree, order, n) == 0) return 0; bst_destroy (tree, NULL); } return 1; }
This code is included in 99, 188, 240, 292, 332, 370, 413, 451, 484, 517, 550, and 585.
124. <Test prototypes 102> += int test_overflow (struct libavl_allocator *, int order[], int n,
int verbosity);
There is an overflow tester for almost every function that can overflow. Here is one example:
125. <Overflow testers 125> = static int
test_bst_t_first (struct bst_table *tree, int n)
{ struct bst_traverser trav; int *first; first = bst_t_first (&trav, tree); if (first == NULL || *first != 0)
{ printf (" First item test failed: expected 0, got %d\n", first != NULL ? *first : -1); return 0; } return 1; }
See also 646.
Exercises:
1. Write the rest of the overflow tester functions. (The test_overflow() function lists all of them.) [answer]