root/maint/gnulib/tests/test-rbtree_list.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_equals
  2. check_equals_by_forward_iteration
  3. check_equals_by_backward_iteration
  4. check_all
  5. main

   1 /* Test of sequential list data type implementation.
   2    Copyright (C) 2006-2021 Free Software Foundation, Inc.
   3    Written by Bruno Haible <bruno@clisp.org>, 2006.
   4 
   5    This program is free software: you can redistribute it and/or modify
   6    it under the terms of the GNU General Public License as published by
   7    the Free Software Foundation; either version 3 of the License, or
   8    (at your option) any later version.
   9 
  10    This program is distributed in the hope that it will be useful,
  11    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13    GNU General Public License for more details.
  14 
  15    You should have received a copy of the GNU General Public License
  16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  17 
  18 #include <config.h>
  19 
  20 #include "gl_rbtree_list.h"
  21 
  22 #include <stdlib.h>
  23 
  24 #include "gl_array_list.h"
  25 #include "macros.h"
  26 
  27 extern void gl_rbtree_list_check_invariants (gl_list_t list);
  28 
  29 static const char *objects[15] =
  30   {
  31     "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o"
  32   };
  33 
  34 #define RANDOM(n) (rand () % (n))
  35 #define RANDOM_OBJECT() objects[RANDOM (SIZEOF (objects))]
  36 
  37 static void
  38 check_equals (gl_list_t list1, gl_list_t list2)
     /* [previous][next][first][last][top][bottom][index][help] */
  39 {
  40   size_t n, i;
  41 
  42   n = gl_list_size (list1);
  43   ASSERT (n == gl_list_size (list2));
  44   for (i = 0; i < n; i++)
  45     {
  46       ASSERT (gl_list_get_at (list1, i) == gl_list_get_at (list2, i));
  47     }
  48 }
  49 
  50 static void
  51 check_equals_by_forward_iteration (gl_list_t list1, gl_list_t list2)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53   gl_list_node_t node1 = gl_list_first_node (list1);
  54   gl_list_node_t node2 = gl_list_first_node (list2);
  55   while (node1 != NULL && node2 != NULL)
  56     {
  57       ASSERT (gl_list_node_value (list1, node1)
  58               == gl_list_node_value (list2, node2));
  59       node1 = gl_list_next_node (list1, node1);
  60       node2 = gl_list_next_node (list2, node2);
  61     }
  62   ASSERT ((node1 == NULL) == (node2 == NULL));
  63 }
  64 
  65 static void
  66 check_equals_by_backward_iteration (gl_list_t list1, gl_list_t list2)
     /* [previous][next][first][last][top][bottom][index][help] */
  67 {
  68   gl_list_node_t node1 = gl_list_last_node (list1);
  69   gl_list_node_t node2 = gl_list_last_node (list2);
  70   while (node1 != NULL && node2 != NULL)
  71     {
  72       ASSERT (gl_list_node_value (list1, node1)
  73               == gl_list_node_value (list2, node2));
  74       node1 = gl_list_previous_node (list1, node1);
  75       node2 = gl_list_previous_node (list2, node2);
  76     }
  77   ASSERT ((node1 == NULL) == (node2 == NULL));
  78 }
  79 
  80 static void
  81 check_all (gl_list_t list1, gl_list_t list2, gl_list_t list3)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83   gl_rbtree_list_check_invariants (list2);
  84   gl_rbtree_list_check_invariants (list3);
  85   check_equals (list1, list2);
  86   check_equals (list1, list3);
  87 }
  88 
  89 int
  90 main (int argc, char *argv[])
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92   gl_list_t list1, list2, list3;
  93 
  94   /* Allow the user to provide a non-default random seed on the command line.  */
  95   if (argc > 1)
  96     srand (atoi (argv[1]));
  97 
  98   {
  99     size_t initial_size = RANDOM (50);
 100     const void **contents =
 101       (const void **) malloc (initial_size * sizeof (const void *));
 102     size_t i;
 103     unsigned int repeat;
 104 
 105     for (i = 0; i < initial_size; i++)
 106       contents[i] = RANDOM_OBJECT ();
 107 
 108     /* Create list1.  */
 109     list1 = gl_list_nx_create (GL_ARRAY_LIST, NULL, NULL, NULL, true,
 110                                initial_size, contents);
 111     ASSERT (list1 != NULL);
 112     /* Create list2.  */
 113     list2 = gl_list_nx_create_empty (GL_RBTREE_LIST, NULL, NULL, NULL, true);
 114     ASSERT (list2 != NULL);
 115     for (i = 0; i < initial_size; i++)
 116       ASSERT (gl_list_nx_add_last (list2, contents[i]) != NULL);
 117 
 118     /* Create list3.  */
 119     list3 = gl_list_nx_create (GL_RBTREE_LIST, NULL, NULL, NULL, true,
 120                                initial_size, contents);
 121     ASSERT (list3 != NULL);
 122 
 123     check_all (list1, list2, list3);
 124 
 125     check_equals_by_forward_iteration (list1, list2);
 126     check_equals_by_backward_iteration (list1, list2);
 127 
 128     for (repeat = 0; repeat < 10000; repeat++)
 129       {
 130         unsigned int operation = RANDOM (18);
 131         switch (operation)
 132           {
 133           case 0:
 134             if (gl_list_size (list1) > 0)
 135               {
 136                 size_t index = RANDOM (gl_list_size (list1));
 137                 const char *obj = RANDOM_OBJECT ();
 138                 gl_list_node_t node1, node2, node3;
 139 
 140                 node1 = gl_list_nx_set_at (list1, index, obj);
 141                 ASSERT (node1 != NULL);
 142                 ASSERT (gl_list_get_at (list1, index) == obj);
 143                 ASSERT (gl_list_node_value (list1, node1) == obj);
 144 
 145                 node2 = gl_list_nx_set_at (list2, index, obj);
 146                 ASSERT (node2 != NULL);
 147                 ASSERT (gl_list_get_at (list2, index) == obj);
 148                 ASSERT (gl_list_node_value (list2, node2) == obj);
 149 
 150                 node3 = gl_list_nx_set_at (list3, index, obj);
 151                 ASSERT (node3 != NULL);
 152                 ASSERT (gl_list_get_at (list3, index) == obj);
 153                 ASSERT (gl_list_node_value (list3, node3) == obj);
 154 
 155                 if (index > 0)
 156                   {
 157                     ASSERT (gl_list_node_value (list1, gl_list_previous_node (list1, node1))
 158                             == gl_list_get_at (list1, index - 1));
 159                     ASSERT (gl_list_node_value (list2, gl_list_previous_node (list3, node3))
 160                             == gl_list_get_at (list2, index - 1));
 161                     ASSERT (gl_list_node_value (list3, gl_list_previous_node (list3, node3))
 162                             == gl_list_get_at (list2, index - 1));
 163                   }
 164                 if (index + 1 < gl_list_size (list1))
 165                   {
 166                     ASSERT (gl_list_node_value (list1, gl_list_next_node (list1, node1))
 167                             == gl_list_get_at (list1, index + 1));
 168                     ASSERT (gl_list_node_value (list2, gl_list_next_node (list3, node3))
 169                             == gl_list_get_at (list2, index + 1));
 170                     ASSERT (gl_list_node_value (list3, gl_list_next_node (list3, node3))
 171                             == gl_list_get_at (list2, index + 1));
 172                   }
 173               }
 174             break;
 175           case 1:
 176             {
 177               const char *obj = RANDOM_OBJECT ();
 178               gl_list_node_t node1, node2, node3;
 179               node1 = gl_list_search (list1, obj);
 180               node2 = gl_list_search (list2, obj);
 181               node3 = gl_list_search (list3, obj);
 182               if (node1 == NULL)
 183                 {
 184                   ASSERT (node2 == NULL);
 185                   ASSERT (node3 == NULL);
 186                 }
 187               else
 188                 {
 189                   ASSERT (node2 != NULL);
 190                   ASSERT (node3 != NULL);
 191                   ASSERT (gl_list_node_value (list1, node1) == obj);
 192                   ASSERT (gl_list_node_value (list2, node2) == obj);
 193                   ASSERT (gl_list_node_value (list3, node3) == obj);
 194                 }
 195             }
 196             break;
 197           case 2:
 198             {
 199               const char *obj = RANDOM_OBJECT ();
 200               size_t index1, index2, index3;
 201               index1 = gl_list_indexof (list1, obj);
 202               index2 = gl_list_indexof (list2, obj);
 203               index3 = gl_list_indexof (list3, obj);
 204               if (index1 == (size_t)(-1))
 205                 {
 206                   ASSERT (index2 == (size_t)(-1));
 207                   ASSERT (index3 == (size_t)(-1));
 208                 }
 209               else
 210                 {
 211                   ASSERT (index2 != (size_t)(-1));
 212                   ASSERT (index3 != (size_t)(-1));
 213                   ASSERT (gl_list_get_at (list1, index1) == obj);
 214                   ASSERT (gl_list_get_at (list2, index2) == obj);
 215                   ASSERT (gl_list_get_at (list3, index3) == obj);
 216                   ASSERT (index2 == index1);
 217                   ASSERT (index3 == index1);
 218                 }
 219             }
 220             break;
 221           case 3: /* add 1 element */
 222             {
 223               const char *obj = RANDOM_OBJECT ();
 224               gl_list_node_t node1, node2, node3;
 225               node1 = gl_list_nx_add_first (list1, obj);
 226               ASSERT (node1 != NULL);
 227               node2 = gl_list_nx_add_first (list2, obj);
 228               ASSERT (node2 != NULL);
 229               node3 = gl_list_nx_add_first (list3, obj);
 230               ASSERT (node3 != NULL);
 231               ASSERT (gl_list_node_value (list1, node1) == obj);
 232               ASSERT (gl_list_node_value (list2, node2) == obj);
 233               ASSERT (gl_list_node_value (list3, node3) == obj);
 234               ASSERT (gl_list_get_at (list1, 0) == obj);
 235               ASSERT (gl_list_get_at (list2, 0) == obj);
 236               ASSERT (gl_list_get_at (list3, 0) == obj);
 237             }
 238             break;
 239           case 4: /* add 1 element */
 240             {
 241               const char *obj = RANDOM_OBJECT ();
 242               gl_list_node_t node1, node2, node3;
 243               node1 = gl_list_nx_add_last (list1, obj);
 244               ASSERT (node1 != NULL);
 245               node2 = gl_list_nx_add_last (list2, obj);
 246               ASSERT (node2 != NULL);
 247               node3 = gl_list_nx_add_last (list3, obj);
 248               ASSERT (node3 != NULL);
 249               ASSERT (gl_list_node_value (list1, node1) == obj);
 250               ASSERT (gl_list_node_value (list2, node2) == obj);
 251               ASSERT (gl_list_node_value (list3, node3) == obj);
 252               ASSERT (gl_list_get_at (list1, gl_list_size (list1) - 1) == obj);
 253               ASSERT (gl_list_get_at (list2, gl_list_size (list2) - 1) == obj);
 254               ASSERT (gl_list_get_at (list3, gl_list_size (list3) - 1) == obj);
 255             }
 256             break;
 257           case 5: /* add 3 elements */
 258             {
 259               const char *obj0 = RANDOM_OBJECT ();
 260               const char *obj1 = RANDOM_OBJECT ();
 261               const char *obj2 = RANDOM_OBJECT ();
 262               gl_list_node_t node1, node2, node3;
 263               node1 = gl_list_nx_add_first (list1, obj2);
 264               ASSERT (node1 != NULL);
 265               node1 = gl_list_nx_add_before (list1, node1, obj0);
 266               ASSERT (node1 != NULL);
 267               node1 = gl_list_nx_add_after (list1, node1, obj1);
 268               ASSERT (node1 != NULL);
 269               node2 = gl_list_nx_add_first (list2, obj2);
 270               ASSERT (node2 != NULL);
 271               node2 = gl_list_nx_add_before (list2, node2, obj0);
 272               ASSERT (node2 != NULL);
 273               node2 = gl_list_nx_add_after (list2, node2, obj1);
 274               ASSERT (node2 != NULL);
 275               node3 = gl_list_nx_add_first (list3, obj2);
 276               ASSERT (node3 != NULL);
 277               node3 = gl_list_nx_add_before (list3, node3, obj0);
 278               ASSERT (node3 != NULL);
 279               node3 = gl_list_nx_add_after (list3, node3, obj1);
 280               ASSERT (node3 != NULL);
 281               ASSERT (gl_list_node_value (list1, node1) == obj1);
 282               ASSERT (gl_list_node_value (list2, node2) == obj1);
 283               ASSERT (gl_list_node_value (list3, node3) == obj1);
 284               ASSERT (gl_list_get_at (list1, 0) == obj0);
 285               ASSERT (gl_list_get_at (list1, 1) == obj1);
 286               ASSERT (gl_list_get_at (list1, 2) == obj2);
 287               ASSERT (gl_list_get_at (list2, 0) == obj0);
 288               ASSERT (gl_list_get_at (list2, 1) == obj1);
 289               ASSERT (gl_list_get_at (list2, 2) == obj2);
 290               ASSERT (gl_list_get_at (list3, 0) == obj0);
 291               ASSERT (gl_list_get_at (list3, 1) == obj1);
 292               ASSERT (gl_list_get_at (list3, 2) == obj2);
 293             }
 294             break;
 295           case 6: /* add 1 element */
 296             {
 297               size_t index = RANDOM (gl_list_size (list1) + 1);
 298               const char *obj = RANDOM_OBJECT ();
 299               gl_list_node_t node1, node2, node3;
 300               node1 = gl_list_nx_add_at (list1, index, obj);
 301               ASSERT (node1 != NULL);
 302               node2 = gl_list_nx_add_at (list2, index, obj);
 303               ASSERT (node2 != NULL);
 304               node3 = gl_list_nx_add_at (list3, index, obj);
 305               ASSERT (node3 != NULL);
 306               ASSERT (gl_list_get_at (list1, index) == obj);
 307               ASSERT (gl_list_node_value (list1, node1) == obj);
 308               ASSERT (gl_list_get_at (list2, index) == obj);
 309               ASSERT (gl_list_node_value (list2, node2) == obj);
 310               ASSERT (gl_list_get_at (list3, index) == obj);
 311               ASSERT (gl_list_node_value (list3, node3) == obj);
 312               if (index > 0)
 313                 {
 314                   ASSERT (gl_list_node_value (list1, gl_list_previous_node (list1, node1))
 315                           == gl_list_get_at (list1, index - 1));
 316                   ASSERT (gl_list_node_value (list2, gl_list_previous_node (list3, node3))
 317                           == gl_list_get_at (list2, index - 1));
 318                   ASSERT (gl_list_node_value (list3, gl_list_previous_node (list3, node3))
 319                           == gl_list_get_at (list2, index - 1));
 320                 }
 321               if (index + 1 < gl_list_size (list1))
 322                 {
 323                   ASSERT (gl_list_node_value (list1, gl_list_next_node (list1, node1))
 324                           == gl_list_get_at (list1, index + 1));
 325                   ASSERT (gl_list_node_value (list2, gl_list_next_node (list3, node3))
 326                           == gl_list_get_at (list2, index + 1));
 327                   ASSERT (gl_list_node_value (list3, gl_list_next_node (list3, node3))
 328                           == gl_list_get_at (list2, index + 1));
 329                 }
 330             }
 331             break;
 332           case 7: case 8: /* remove 1 element */
 333             if (gl_list_size (list1) > 0)
 334               {
 335                 size_t n = gl_list_size (list1);
 336                 const char *obj = gl_list_get_at (list1, RANDOM (n));
 337                 gl_list_node_t node1, node2, node3;
 338                 node1 = gl_list_search (list1, obj);
 339                 node2 = gl_list_search (list2, obj);
 340                 node3 = gl_list_search (list3, obj);
 341                 ASSERT (node1 != NULL);
 342                 ASSERT (node2 != NULL);
 343                 ASSERT (node3 != NULL);
 344                 ASSERT (gl_list_remove_node (list1, node1));
 345                 ASSERT (gl_list_remove_node (list2, node2));
 346                 ASSERT (gl_list_remove_node (list3, node3));
 347                 ASSERT (gl_list_size (list1) == n - 1);
 348               }
 349             break;
 350           case 9: case 10: /* remove 1 element */
 351             if (gl_list_size (list1) > 0)
 352               {
 353                 size_t n = gl_list_size (list1);
 354                 size_t index = RANDOM (n);
 355                 ASSERT (gl_list_remove_at (list1, index));
 356                 ASSERT (gl_list_remove_at (list2, index));
 357                 ASSERT (gl_list_remove_at (list3, index));
 358                 ASSERT (gl_list_size (list1) == n - 1);
 359               }
 360             break;
 361           case 11: /* remove first element */
 362             {
 363               size_t n = gl_list_size (list1);
 364               bool removed1 = gl_list_remove_first (list1);
 365               ASSERT (gl_list_remove_first (list2) == removed1);
 366               ASSERT (gl_list_remove_first (list3) == removed1);
 367               ASSERT (gl_list_size (list1) == n - (int) removed1);
 368             }
 369             break;
 370           case 12: /* remove last element */
 371             {
 372               size_t n = gl_list_size (list1);
 373               bool removed1 = gl_list_remove_last (list1);
 374               ASSERT (gl_list_remove_last (list2) == removed1);
 375               ASSERT (gl_list_remove_last (list3) == removed1);
 376               ASSERT (gl_list_size (list1) == n - (int) removed1);
 377             }
 378             break;
 379           case 13: case 14: /* remove 1 element */
 380             if (gl_list_size (list1) > 0)
 381               {
 382                 size_t n = gl_list_size (list1);
 383                 const char *obj = gl_list_get_at (list1, RANDOM (n));
 384                 ASSERT (gl_list_remove (list1, obj));
 385                 ASSERT (gl_list_remove (list2, obj));
 386                 ASSERT (gl_list_remove (list3, obj));
 387                 ASSERT (gl_list_size (list1) == n - 1);
 388               }
 389             break;
 390           case 15:
 391             if (gl_list_size (list1) > 0)
 392               {
 393                 size_t n = gl_list_size (list1);
 394                 const char *obj = "xyzzy";
 395                 ASSERT (!gl_list_remove (list1, obj));
 396                 ASSERT (!gl_list_remove (list2, obj));
 397                 ASSERT (!gl_list_remove (list3, obj));
 398                 ASSERT (gl_list_size (list1) == n);
 399               }
 400             break;
 401           case 16:
 402             {
 403               size_t n = gl_list_size (list1);
 404               gl_list_iterator_t iter1, iter2, iter3;
 405               const void *elt;
 406               iter1 = gl_list_iterator (list1);
 407               iter2 = gl_list_iterator (list2);
 408               iter3 = gl_list_iterator (list3);
 409               for (i = 0; i < n; i++)
 410                 {
 411                   ASSERT (gl_list_iterator_next (&iter1, &elt, NULL));
 412                   ASSERT (gl_list_get_at (list1, i) == elt);
 413                   ASSERT (gl_list_iterator_next (&iter2, &elt, NULL));
 414                   ASSERT (gl_list_get_at (list2, i) == elt);
 415                   ASSERT (gl_list_iterator_next (&iter3, &elt, NULL));
 416                   ASSERT (gl_list_get_at (list3, i) == elt);
 417                 }
 418               ASSERT (!gl_list_iterator_next (&iter1, &elt, NULL));
 419               ASSERT (!gl_list_iterator_next (&iter2, &elt, NULL));
 420               ASSERT (!gl_list_iterator_next (&iter3, &elt, NULL));
 421               gl_list_iterator_free (&iter1);
 422               gl_list_iterator_free (&iter2);
 423               gl_list_iterator_free (&iter3);
 424             }
 425             break;
 426           case 17:
 427             {
 428               size_t end = RANDOM (gl_list_size (list1) + 1);
 429               size_t start = RANDOM (end + 1);
 430               gl_list_iterator_t iter1, iter2, iter3;
 431               const void *elt;
 432               iter1 = gl_list_iterator_from_to (list1, start, end);
 433               iter2 = gl_list_iterator_from_to (list2, start, end);
 434               iter3 = gl_list_iterator_from_to (list3, start, end);
 435               for (i = start; i < end; i++)
 436                 {
 437                   ASSERT (gl_list_iterator_next (&iter1, &elt, NULL));
 438                   ASSERT (gl_list_get_at (list1, i) == elt);
 439                   ASSERT (gl_list_iterator_next (&iter2, &elt, NULL));
 440                   ASSERT (gl_list_get_at (list2, i) == elt);
 441                   ASSERT (gl_list_iterator_next (&iter3, &elt, NULL));
 442                   ASSERT (gl_list_get_at (list3, i) == elt);
 443                 }
 444               ASSERT (!gl_list_iterator_next (&iter1, &elt, NULL));
 445               ASSERT (!gl_list_iterator_next (&iter2, &elt, NULL));
 446               ASSERT (!gl_list_iterator_next (&iter3, &elt, NULL));
 447               gl_list_iterator_free (&iter1);
 448               gl_list_iterator_free (&iter2);
 449               gl_list_iterator_free (&iter3);
 450             }
 451             break;
 452           }
 453         check_all (list1, list2, list3);
 454       }
 455 
 456     gl_list_free (list1);
 457     gl_list_free (list2);
 458     gl_list_free (list3);
 459     free (contents);
 460   }
 461 
 462   return 0;
 463 }

/* [previous][next][first][last][top][bottom][index][help] */