libavl/avl_test.c
00001 /* Produced by texiweb from libavl.w. */
00002 
00003 /* libavl - library for manipulation of binary trees.
00004    Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc.
00005 
00006    This program is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU General Public License as
00008    published by the Free Software Foundation; either version 2 of the
00009    License, or (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful, but
00012    WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00014    See the GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00019    02111-1307, USA.
00020 
00021    The author may be contacted at <blp@gnu.org> on the Internet, or
00022    write to Ben Pfaff, Stanford University, Computer Science Dept., 353
00023    Serra Mall, Stanford CA 94305, USA.
00024 */
00025 
00026 #include <assert.h>
00027 #include <limits.h>
00028 #include <stdio.h>
00029 #include "avl.h"
00030 #include "test.h"
00031 
00032 /* Prints the structure of |node|,
00033    which is |level| levels from the top of the tree. */
00034 static void
00035 print_tree_structure (const struct avl_node *node, int level)
00036 {
00037   /* You can set the maximum level as high as you like.
00038      Most of the time, you'll want to debug code using small trees,
00039      so that a large |level| indicates a ``loop'', which is a bug. */
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 /* Prints the entire structure of |tree| with the given |title|. */
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 /* Checks that the current item at |trav| is |i|
00075    and that its previous and next items are as they should be.
00076    |label| is a name for the traverser used in reporting messages.
00077    There should be |n| items in the tree numbered |0|@dots{}|n - 1|.
00078    Returns nonzero only if there is an error. */
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 /* Compares binary trees rooted at |a| and |b|,
00117    making sure that they are identical. */
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 /* Examines the binary tree rooted at |node|.
00162    Zeroes |*okay| if an error occurs.
00163    Otherwise, does not modify |*okay|.
00164    Sets |*count| to the number of nodes in that tree,
00165    including |node| itself if |node != NULL|.
00166    Sets |*height| to the tree's height.
00167    All the nodes in the tree are verified to be at least |min|
00168    but no greater than |max|. */
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;                /* Value of this node's data. */
00174   size_t subcount[2];   /* Number of nodes in subtrees. */
00175   int subheight[2];     /* Heights of subtrees. */
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 /* Checks that |tree| is well-formed
00219    and verifies that the values in |array[]| are actually in |tree|.
00220    There must be |n| elements in |array[]| and |tree|.
00221    Returns nonzero only if no errors detected. */
00222 static int
00223 verify_tree (struct avl_table *tree, int array[], size_t n)
00224 {
00225   int okay = 1;
00226 
00227   /* Check |tree|'s bst_count against that supplied. */
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       /* Recursively verify tree structure. */
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       /* Check that all the values in |array[]| are in |tree|. */
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       /* Check that |avl_t_first()| and |avl_t_next()| work properly. */
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       /* Check that |avl_t_last()| and |avl_t_prev()| work properly. */
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       /* Check that |avl_t_init()| works properly. */
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 /* Tests tree functions.
00363    |insert[]| and |delete[]| must contain some permutation of values
00364    |0|@dots{}|n - 1|.
00365    Uses |allocator| as the allocator for tree and node data.
00366    Higher values of |verbosity| produce more debug output. */
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   /* Test creating a AVL and inserting into it. */
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       /* Add the |i|th element to the tree. */
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   /* Test AVL traversal during modifications. */
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   /* Test deleting nodes from the tree and making copies of it. */
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       /* Copy the tree and make sure it's identical. */
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   /* Test destroying the tree. */
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 /* Tests the tree routines for proper handling of overflows.
00650    Inserting the |n| elements of |order[]| should produce a tree
00651    with height greater than |AVL_MAX_HEIGHT|.
00652    Uses |allocator| as the allocator for tree and node data.
00653    Use |verbosity| to set the level of chatter on |stdout|. */
00654 int
00655 test_overflow (struct libavl_allocator *allocator,
00656                int order[], int n, int verbosity)
00657 {
00658   /* An overflow tester function. */
00659   typedef int test_func (struct avl_table *, int n);
00660 
00661   /* An overflow tester. */
00662   struct test
00663     {
00664       test_func *func;                  /* Tester function. */
00665       const char *name;                 /* Test name. */
00666     };
00667 
00668   /* All the overflow testers. */
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;                 /* Iterator. */
00681 
00682   /* Run all the overflow testers. */
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 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines