00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <assert.h>
00027 #include <limits.h>
00028 #include <stdio.h>
00029 #include "avl.h"
00030 #include "test.h"
00031
00032
00033
00034 static void
00035 print_tree_structure (const struct avl_node *node, int level)
00036 {
00037
00038
00039
00040 if (level > 16)
00041 {
00042 printf ("[...]");
00043 return;
00044 }
00045
00046 if (node == NULL)
00047 return;
00048
00049 printf ("%d", *(int *) node->avl_data);
00050 if (node->avl_link[0] != NULL || node->avl_link[1] != NULL)
00051 {
00052 putchar ('(');
00053
00054 print_tree_structure (node->avl_link[0], level + 1);
00055 if (node->avl_link[1] != NULL)
00056 {
00057 putchar (',');
00058 print_tree_structure (node->avl_link[1], level + 1);
00059 }
00060
00061 putchar (')');
00062 }
00063 }
00064
00065
00066 void
00067 print_whole_tree (const struct avl_table *tree, const char *title)
00068 {
00069 printf ("%s: ", title);
00070 print_tree_structure (tree->avl_root, 0);
00071 putchar ('\n');
00072 }
00073
00074
00075
00076
00077
00078
00079 static int
00080 check_traverser (struct avl_traverser *trav, int i, int n, const char *label)
00081 {
00082 int okay = 1;
00083 int *cur, *prev, *next;
00084
00085 prev = avl_t_prev (trav);
00086 if ((i == 0 && prev != NULL)
00087 || (i > 0 && (prev == NULL || *prev != i - 1)))
00088 {
00089 printf (" %s traverser ahead of %d, but should be ahead of %d.\n",
00090 label, prev != NULL ? *prev : -1, i == 0 ? -1 : i - 1);
00091 okay = 0;
00092 }
00093 avl_t_next (trav);
00094
00095 cur = avl_t_cur (trav);
00096 if (cur == NULL || *cur != i)
00097 {
00098 printf (" %s traverser at %d, but should be at %d.\n",
00099 label, cur != NULL ? *cur : -1, i);
00100 okay = 0;
00101 }
00102
00103 next = avl_t_next (trav);
00104 if ((i == n - 1 && next != NULL)
00105 || (i != n - 1 && (next == NULL || *next != i + 1)))
00106 {
00107 printf (" %s traverser behind %d, but should be behind %d.\n",
00108 label, next != NULL ? *next : -1, i == n - 1 ? -1 : i + 1);
00109 okay = 0;
00110 }
00111 avl_t_prev (trav);
00112
00113 return okay;
00114 }
00115
00116
00117
00118 static int
00119 compare_trees (struct avl_node *a, struct avl_node *b)
00120 {
00121 int okay;
00122
00123 if (a == NULL || b == NULL)
00124 {
00125 assert (a == NULL && b == NULL);
00126 return 1;
00127 }
00128
00129 if (*(int *) a->avl_data != *(int *) b->avl_data
00130 || ((a->avl_link[0] != NULL) != (b->avl_link[0] != NULL))
00131 || ((a->avl_link[1] != NULL) != (b->avl_link[1] != NULL))
00132 || a->avl_balance != b->avl_balance)
00133 {
00134 printf (" Copied nodes differ: a=%d (bal=%d) b=%d (bal=%d) a:",
00135 *(int *) a->avl_data, a->avl_balance,
00136 *(int *) b->avl_data, b->avl_balance);
00137
00138 if (a->avl_link[0] != NULL)
00139 printf ("l");
00140 if (a->avl_link[1] != NULL)
00141 printf ("r");
00142
00143 printf (" b:");
00144 if (b->avl_link[0] != NULL)
00145 printf ("l");
00146 if (b->avl_link[1] != NULL)
00147 printf ("r");
00148
00149 printf ("\n");
00150 return 0;
00151 }
00152
00153 okay = 1;
00154 if (a->avl_link[0] != NULL)
00155 okay &= compare_trees (a->avl_link[0], b->avl_link[0]);
00156 if (a->avl_link[1] != NULL)
00157 okay &= compare_trees (a->avl_link[1], b->avl_link[1]);
00158 return okay;
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 static void
00170 recurse_verify_tree (struct avl_node *node, int *okay, size_t *count,
00171 int min, int max, int *height)
00172 {
00173 int d;
00174 size_t subcount[2];
00175 int subheight[2];
00176
00177 if (node == NULL)
00178 {
00179 *count = 0;
00180 *height = 0;
00181 return;
00182 }
00183 d = *(int *) node->avl_data;
00184
00185 if (min > max)
00186 {
00187 printf (" Parents of node %d constrain it to empty range %d...%d.\n",
00188 d, min, max);
00189 *okay = 0;
00190 }
00191 else if (d < min || d > max)
00192 {
00193 printf (" Node %d is not in range %d...%d implied by its parents.\n",
00194 d, min, max);
00195 *okay = 0;
00196 }
00197
00198 recurse_verify_tree (node->avl_link[0], okay, &subcount[0],
00199 min, d - 1, &subheight[0]);
00200 recurse_verify_tree (node->avl_link[1], okay, &subcount[1],
00201 d + 1, max, &subheight[1]);
00202 *count = 1 + subcount[0] + subcount[1];
00203 *height = 1 + (subheight[0] > subheight[1] ? subheight[0] : subheight[1]);
00204
00205 if (subheight[1] - subheight[0] != node->avl_balance)
00206 {
00207 printf (" Balance factor of node %d is %d, but should be %d.\n",
00208 d, node->avl_balance, subheight[1] - subheight[0]);
00209 *okay = 0;
00210 }
00211 else if (node->avl_balance < -1 || node->avl_balance > +1)
00212 {
00213 printf (" Balance factor of node %d is %d.\n", d, node->avl_balance);
00214 *okay = 0;
00215 }
00216 }
00217
00218
00219
00220
00221
00222 static int
00223 verify_tree (struct avl_table *tree, int array[], size_t n)
00224 {
00225 int okay = 1;
00226
00227
00228 if (avl_count (tree) != n)
00229 {
00230 printf (" Tree count is %lu, but should be %lu.\n",
00231 (unsigned long) avl_count (tree), (unsigned long) n);
00232 okay = 0;
00233 }
00234
00235 if (okay)
00236 {
00237
00238 size_t count;
00239 int height;
00240
00241 recurse_verify_tree (tree->avl_root, &okay, &count,
00242 0, INT_MAX, &height);
00243 if (count != n)
00244 {
00245 printf (" Tree has %lu nodes, but should have %lu.\n",
00246 (unsigned long) count, (unsigned long) n);
00247 okay = 0;
00248 }
00249 }
00250
00251 if (okay)
00252 {
00253
00254 size_t i;
00255
00256 for (i = 0; i < n; i++)
00257 if (avl_find (tree, &array[i]) == NULL)
00258 {
00259 printf (" Tree does not contain expected value %d.\n", array[i]);
00260 okay = 0;
00261 }
00262 }
00263
00264 if (okay)
00265 {
00266
00267 struct avl_traverser trav;
00268 size_t i;
00269 int prev = -1;
00270 int *item;
00271
00272 for (i = 0, item = avl_t_first (&trav, tree); i < 2 * n && item != NULL;
00273 i++, item = avl_t_next (&trav))
00274 {
00275 if (*item <= prev)
00276 {
00277 printf (" Tree out of order: %d follows %d in traversal\n",
00278 *item, prev);
00279 okay = 0;
00280 }
00281
00282 prev = *item;
00283 }
00284
00285 if (i != n)
00286 {
00287 printf (" Tree should have %lu items, but has %lu in traversal\n",
00288 (unsigned long) n, (unsigned long) i);
00289 okay = 0;
00290 }
00291 }
00292
00293 if (okay)
00294 {
00295
00296 struct avl_traverser trav;
00297 size_t i;
00298 int next = INT_MAX;
00299 int *item;
00300
00301 for (i = 0, item = avl_t_last (&trav, tree); i < 2 * n && item != NULL;
00302 i++, item = avl_t_prev (&trav))
00303 {
00304 if (*item >= next)
00305 {
00306 printf (" Tree out of order: %d precedes %d in traversal\n",
00307 *item, next);
00308 okay = 0;
00309 }
00310
00311 next = *item;
00312 }
00313
00314 if (i != n)
00315 {
00316 printf (" Tree should have %lu items, but has %lu in reverse\n",
00317 (unsigned long) n, (unsigned long) i);
00318 okay = 0;
00319 }
00320 }
00321
00322 if (okay)
00323 {
00324
00325 struct avl_traverser init, first, last;
00326 int *cur, *prev, *next;
00327
00328 avl_t_init (&init, tree);
00329 avl_t_first (&first, tree);
00330 avl_t_last (&last, tree);
00331
00332 cur = avl_t_cur (&init);
00333 if (cur != NULL)
00334 {
00335 printf (" Inited traverser should be null, but is actually %d.\n",
00336 *cur);
00337 okay = 0;
00338 }
00339
00340 next = avl_t_next (&init);
00341 if (next != avl_t_cur (&first))
00342 {
00343 printf (" Next after null should be %d, but is actually %d.\n",
00344 *(int *) avl_t_cur (&first), *next);
00345 okay = 0;
00346 }
00347 avl_t_prev (&init);
00348
00349 prev = avl_t_prev (&init);
00350 if (prev != avl_t_cur (&last))
00351 {
00352 printf (" Previous before null should be %d, but is actually %d.\n",
00353 *(int *) avl_t_cur (&last), *prev);
00354 okay = 0;
00355 }
00356 avl_t_next (&init);
00357 }
00358
00359 return okay;
00360 }
00361
00362
00363
00364
00365
00366
00367 int
00368 test_correctness (struct libavl_allocator *allocator,
00369 int insert[], int delete[], int n, int verbosity)
00370 {
00371 struct avl_table *tree;
00372 int okay = 1;
00373 int i;
00374
00375
00376 tree = avl_create (compare_ints, NULL, allocator);
00377 if (tree == NULL)
00378 {
00379 if (verbosity >= 0)
00380 printf (" Out of memory creating tree.\n");
00381 return 1;
00382 }
00383
00384 for (i = 0; i < n; i++)
00385 {
00386 if (verbosity >= 2)
00387 printf (" Inserting %d...\n", insert[i]);
00388
00389
00390 {
00391 void **p = avl_probe (tree, &insert[i]);
00392 if (p == NULL)
00393 {
00394 if (verbosity >= 0)
00395 printf (" Out of memory in insertion.\n");
00396 avl_destroy (tree, NULL);
00397 return 1;
00398 }
00399 if (*p != &insert[i])
00400 printf (" Duplicate item in tree!\n");
00401 }
00402
00403 if (verbosity >= 3)
00404 print_whole_tree (tree, " Afterward");
00405
00406 if (!verify_tree (tree, insert, i + 1))
00407 return 0;
00408 }
00409
00410
00411 for (i = 0; i < n; i++)
00412 {
00413 struct avl_traverser x, y, z;
00414 int *deleted;
00415
00416 if (insert[i] == delete[i])
00417 continue;
00418
00419 if (verbosity >= 2)
00420 printf (" Checking traversal from item %d...\n", insert[i]);
00421
00422 if (avl_t_find (&x, tree, &insert[i]) == NULL)
00423 {
00424 printf (" Can't find item %d in tree!\n", insert[i]);
00425 continue;
00426 }
00427
00428 okay &= check_traverser (&x, insert[i], n, "Predeletion");
00429
00430 if (verbosity >= 3)
00431 printf (" Deleting item %d.\n", delete[i]);
00432
00433 deleted = avl_delete (tree, &delete[i]);
00434 if (deleted == NULL || *deleted != delete[i])
00435 {
00436 okay = 0;
00437 if (deleted == NULL)
00438 printf (" Deletion failed.\n");
00439 else
00440 printf (" Wrong node %d returned.\n", *deleted);
00441 }
00442
00443 avl_t_copy (&y, &x);
00444
00445 if (verbosity >= 3)
00446 printf (" Re-inserting item %d.\n", delete[i]);
00447 if (avl_t_insert (&z, tree, &delete[i]) == NULL)
00448 {
00449 if (verbosity >= 0)
00450 printf (" Out of memory re-inserting item.\n");
00451 avl_destroy (tree, NULL);
00452 return 1;
00453 }
00454
00455 okay &= check_traverser (&x, insert[i], n, "Postdeletion");
00456 okay &= check_traverser (&y, insert[i], n, "Copied");
00457 okay &= check_traverser (&z, delete[i], n, "Insertion");
00458
00459 if (!verify_tree (tree, insert, n))
00460 return 0;
00461 }
00462
00463
00464 for (i = 0; i < n; i++)
00465 {
00466 int *deleted;
00467
00468 if (verbosity >= 2)
00469 printf (" Deleting %d...\n", delete[i]);
00470
00471 deleted = avl_delete (tree, &delete[i]);
00472 if (deleted == NULL || *deleted != delete[i])
00473 {
00474 okay = 0;
00475 if (deleted == NULL)
00476 printf (" Deletion failed.\n");
00477 else
00478 printf (" Wrong node %d returned.\n", *deleted);
00479 }
00480
00481 if (verbosity >= 3)
00482 print_whole_tree (tree, " Afterward");
00483
00484 if (!verify_tree (tree, delete + i + 1, n - i - 1))
00485 return 0;
00486
00487 if (verbosity >= 2)
00488 printf (" Copying tree and comparing...\n");
00489
00490
00491 {
00492 struct avl_table *copy = avl_copy (tree, NULL, NULL, NULL);
00493 if (copy == NULL)
00494 {
00495 if (verbosity >= 0)
00496 printf (" Out of memory in copy\n");
00497 avl_destroy (tree, NULL);
00498 return 1;
00499 }
00500
00501 okay &= compare_trees (tree->avl_root, copy->avl_root);
00502 avl_destroy (copy, NULL);
00503 }
00504 }
00505
00506 if (avl_delete (tree, &insert[0]) != NULL)
00507 {
00508 printf (" Deletion from empty tree succeeded.\n");
00509 okay = 0;
00510 }
00511
00512
00513 avl_destroy (tree, NULL);
00514
00515 return okay;
00516 }
00517
00518 static int
00519 test_bst_t_first (struct avl_table *tree, int n)
00520 {
00521 struct avl_traverser trav;
00522 int *first;
00523
00524 first = avl_t_first (&trav, tree);
00525 if (first == NULL || *first != 0)
00526 {
00527 printf (" First item test failed: expected 0, got %d\n",
00528 first != NULL ? *first : -1);
00529 return 0;
00530 }
00531
00532 return 1;
00533 }
00534
00535 static int
00536 test_bst_t_last (struct avl_table *tree, int n)
00537 {
00538 struct avl_traverser trav;
00539 int *last;
00540
00541 last = avl_t_last (&trav, tree);
00542 if (last == NULL || *last != n - 1)
00543 {
00544 printf (" Last item test failed: expected %d, got %d\n",
00545 n - 1, last != NULL ? *last : -1);
00546 return 0;
00547 }
00548
00549 return 1;
00550 }
00551
00552 static int
00553 test_bst_t_find (struct avl_table *tree, int n)
00554 {
00555 int i;
00556
00557 for (i = 0; i < n; i++)
00558 {
00559 struct avl_traverser trav;
00560 int *iter;
00561
00562 iter = avl_t_find (&trav, tree, &i);
00563 if (iter == NULL || *iter != i)
00564 {
00565 printf (" Find item test failed: looked for %d, got %d\n",
00566 i, iter != NULL ? *iter : -1);
00567 return 0;
00568 }
00569 }
00570
00571 return 1;
00572 }
00573
00574 static int
00575 test_bst_t_insert (struct avl_table *tree, int n)
00576 {
00577 int i;
00578
00579 for (i = 0; i < n; i++)
00580 {
00581 struct avl_traverser trav;
00582 int *iter;
00583
00584 iter = avl_t_insert (&trav, tree, &i);
00585 if (iter == NULL || iter == &i || *iter != i)
00586 {
00587 printf (" Insert item test failed: inserted dup %d, got %d\n",
00588 i, iter != NULL ? *iter : -1);
00589 return 0;
00590 }
00591 }
00592
00593 return 1;
00594 }
00595
00596 static int
00597 test_bst_t_next (struct avl_table *tree, int n)
00598 {
00599 struct avl_traverser trav;
00600 int i;
00601
00602 avl_t_init (&trav, tree);
00603 for (i = 0; i < n; i++)
00604 {
00605 int *iter = avl_t_next (&trav);
00606 if (iter == NULL || *iter != i)
00607 {
00608 printf (" Next item test failed: expected %d, got %d\n",
00609 i, iter != NULL ? *iter : -1);
00610 return 0;
00611 }
00612 }
00613
00614 return 1;
00615 }
00616
00617 static int
00618 test_bst_t_prev (struct avl_table *tree, int n)
00619 {
00620 struct avl_traverser trav;
00621 int i;
00622
00623 avl_t_init (&trav, tree);
00624 for (i = n - 1; i >= 0; i--)
00625 {
00626 int *iter = avl_t_prev (&trav);
00627 if (iter == NULL || *iter != i)
00628 {
00629 printf (" Previous item test failed: expected %d, got %d\n",
00630 i, iter != NULL ? *iter : -1);
00631 return 0;
00632 }
00633 }
00634
00635 return 1;
00636 }
00637
00638 static int
00639 test_bst_copy (struct avl_table *tree, int n)
00640 {
00641 struct avl_table *copy = avl_copy (tree, NULL, NULL, NULL);
00642 int okay = compare_trees (tree->avl_root, copy->avl_root);
00643
00644 avl_destroy (copy, NULL);
00645
00646 return okay;
00647 }
00648
00649
00650
00651
00652
00653
00654 int
00655 test_overflow (struct libavl_allocator *allocator,
00656 int order[], int n, int verbosity)
00657 {
00658
00659 typedef int test_func (struct avl_table *, int n);
00660
00661
00662 struct test
00663 {
00664 test_func *func;
00665 const char *name;
00666 };
00667
00668
00669 static const struct test test[] =
00670 {
00671 {test_bst_t_first, "first item"},
00672 {test_bst_t_last, "last item"},
00673 {test_bst_t_find, "find item"},
00674 {test_bst_t_insert, "insert item"},
00675 {test_bst_t_next, "next item"},
00676 {test_bst_t_prev, "previous item"},
00677 {test_bst_copy, "copy tree"},
00678 };
00679
00680 const struct test *i;
00681
00682
00683 for (i = test; i < test + sizeof test / sizeof *test; i++)
00684 {
00685 struct avl_table *tree;
00686 int j;
00687
00688 if (verbosity >= 2)
00689 printf (" Running %s test...\n", i->name);
00690
00691 tree = avl_create (compare_ints, NULL, allocator);
00692 if (tree == NULL)
00693 {
00694 printf (" Out of memory creating tree.\n");
00695 return 1;
00696 }
00697
00698 for (j = 0; j < n; j++)
00699 {
00700 void **p = avl_probe (tree, &order[j]);
00701 if (p == NULL || *p != &order[j])
00702 {
00703 if (p == NULL && verbosity >= 0)
00704 printf (" Out of memory in insertion.\n");
00705 else if (p != NULL)
00706 printf (" Duplicate item in tree!\n");
00707 avl_destroy (tree, NULL);
00708 return p == NULL;
00709 }
00710 }
00711
00712 if (i->func (tree, n) == 0)
00713 return 0;
00714
00715 if (verify_tree (tree, order, n) == 0)
00716 return 0;
00717 avl_destroy (tree, NULL);
00718 }
00719
00720 return 1;
00721 }