Merge branch 'upstream' into stable
[gnulib.git] / tests / test-avltree_list.c
1 /* Test of sequential list data type implementation.
2    Copyright (C) 2006-2009 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 <http://www.gnu.org/licenses/>.  */
17
18 #include <config.h>
19
20 #include "gl_avltree_list.h"
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include "gl_array_list.h"
26 #include "progname.h"
27
28 extern void gl_avltree_list_check_invariants (gl_list_t list);
29
30 static const char *objects[15] =
31   {
32     "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o"
33   };
34
35 #define SIZEOF(array) (sizeof (array) / sizeof (array[0]))
36 #define ASSERT(expr) \
37   do                                                                         \
38     {                                                                        \
39       if (!(expr))                                                           \
40         {                                                                    \
41           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
42           fflush (stderr);                                                   \
43           abort ();                                                          \
44         }                                                                    \
45     }                                                                        \
46   while (0)
47 #define RANDOM(n) (rand () % (n))
48 #define RANDOM_OBJECT() objects[RANDOM (SIZEOF (objects))]
49
50 static void
51 check_equals (gl_list_t list1, gl_list_t list2)
52 {
53   size_t n, i;
54
55   n = gl_list_size (list1);
56   ASSERT (n == gl_list_size (list2));
57   for (i = 0; i < n; i++)
58     {
59       ASSERT (gl_list_get_at (list1, i) == gl_list_get_at (list2, i));
60     }
61 }
62
63 static void
64 check_all (gl_list_t list1, gl_list_t list2, gl_list_t list3)
65 {
66   gl_avltree_list_check_invariants (list2);
67   gl_avltree_list_check_invariants (list3);
68   check_equals (list1, list2);
69   check_equals (list1, list3);
70 }
71
72 int
73 main (int argc, char *argv[])
74 {
75   gl_list_t list1, list2, list3;
76
77   set_program_name (argv[0]);
78
79   /* Allow the user to provide a non-default random seed on the command line.  */
80   if (argc > 1)
81     srand (atoi (argv[1]));
82
83   {
84     size_t initial_size = RANDOM (50);
85     const void **contents =
86       (const void **) malloc (initial_size * sizeof (const void *));
87     size_t i;
88     unsigned int repeat;
89
90     for (i = 0; i < initial_size; i++)
91       contents[i] = RANDOM_OBJECT ();
92
93     /* Create list1.  */
94     list1 = gl_list_nx_create (GL_ARRAY_LIST, NULL, NULL, NULL, true,
95                                initial_size, contents);
96     ASSERT (list1 != NULL);
97     /* Create list2.  */
98     list2 = gl_list_nx_create_empty (GL_AVLTREE_LIST, NULL, NULL, NULL, true);
99     ASSERT (list2 != NULL);
100     for (i = 0; i < initial_size; i++)
101       ASSERT (gl_list_nx_add_last (list2, contents[i]) != NULL);
102
103     /* Create list3.  */
104     list3 = gl_list_nx_create (GL_AVLTREE_LIST, NULL, NULL, NULL, true,
105                                initial_size, contents);
106     ASSERT (list3 != NULL);
107
108     check_all (list1, list2, list3);
109
110     for (repeat = 0; repeat < 10000; repeat++)
111       {
112         unsigned int operation = RANDOM (16);
113         switch (operation)
114           {
115           case 0:
116             if (gl_list_size (list1) > 0)
117               {
118                 size_t index = RANDOM (gl_list_size (list1));
119                 const char *obj = RANDOM_OBJECT ();
120                 gl_list_node_t node1, node2, node3;
121
122                 node1 = gl_list_nx_set_at (list1, index, obj);
123                 ASSERT (node1 != NULL);
124                 ASSERT (gl_list_get_at (list1, index) == obj);
125                 ASSERT (gl_list_node_value (list1, node1) == obj);
126
127                 node2 = gl_list_nx_set_at (list2, index, obj);
128                 ASSERT (node2 != NULL);
129                 ASSERT (gl_list_get_at (list2, index) == obj);
130                 ASSERT (gl_list_node_value (list2, node2) == obj);
131
132                 node3 = gl_list_nx_set_at (list3, index, obj);
133                 ASSERT (node3 != NULL);
134                 ASSERT (gl_list_get_at (list3, index) == obj);
135                 ASSERT (gl_list_node_value (list3, node3) == obj);
136
137                 if (index > 0)
138                   {
139                     ASSERT (gl_list_node_value (list1, gl_list_previous_node (list1, node1))
140                             == gl_list_get_at (list1, index - 1));
141                     ASSERT (gl_list_node_value (list2, gl_list_previous_node (list3, node3))
142                             == gl_list_get_at (list2, index - 1));
143                     ASSERT (gl_list_node_value (list3, gl_list_previous_node (list3, node3))
144                             == gl_list_get_at (list2, index - 1));
145                   }
146                 if (index + 1 < gl_list_size (list1))
147                   {
148                     ASSERT (gl_list_node_value (list1, gl_list_next_node (list1, node1))
149                             == gl_list_get_at (list1, index + 1));
150                     ASSERT (gl_list_node_value (list2, gl_list_next_node (list3, node3))
151                             == gl_list_get_at (list2, index + 1));
152                     ASSERT (gl_list_node_value (list3, gl_list_next_node (list3, node3))
153                             == gl_list_get_at (list2, index + 1));
154                   }
155               }
156             break;
157           case 1:
158             {
159               const char *obj = RANDOM_OBJECT ();
160               gl_list_node_t node1, node2, node3;
161               node1 = gl_list_search (list1, obj);
162               node2 = gl_list_search (list2, obj);
163               node3 = gl_list_search (list3, obj);
164               if (node1 == NULL)
165                 {
166                   ASSERT (node2 == NULL);
167                   ASSERT (node3 == NULL);
168                 }
169               else
170                 {
171                   ASSERT (node2 != NULL);
172                   ASSERT (node3 != NULL);
173                   ASSERT (gl_list_node_value (list1, node1) == obj);
174                   ASSERT (gl_list_node_value (list2, node2) == obj);
175                   ASSERT (gl_list_node_value (list3, node3) == obj);
176                 }
177             }
178             break;
179           case 2:
180             {
181               const char *obj = RANDOM_OBJECT ();
182               size_t index1, index2, index3;
183               index1 = gl_list_indexof (list1, obj);
184               index2 = gl_list_indexof (list2, obj);
185               index3 = gl_list_indexof (list3, obj);
186               if (index1 == (size_t)(-1))
187                 {
188                   ASSERT (index2 == (size_t)(-1));
189                   ASSERT (index3 == (size_t)(-1));
190                 }
191               else
192                 {
193                   ASSERT (index2 != (size_t)(-1));
194                   ASSERT (index3 != (size_t)(-1));
195                   ASSERT (gl_list_get_at (list1, index1) == obj);
196                   ASSERT (gl_list_get_at (list2, index2) == obj);
197                   ASSERT (gl_list_get_at (list3, index3) == obj);
198                   ASSERT (index2 == index1);
199                   ASSERT (index3 == index1);
200                 }
201             }
202             break;
203           case 3: /* add 1 element */
204             {
205               const char *obj = RANDOM_OBJECT ();
206               gl_list_node_t node1, node2, node3;
207               node1 = gl_list_nx_add_first (list1, obj);
208               ASSERT (node1 != NULL);
209               node2 = gl_list_nx_add_first (list2, obj);
210               ASSERT (node2 != NULL);
211               node3 = gl_list_nx_add_first (list3, obj);
212               ASSERT (node3 != NULL);
213               ASSERT (gl_list_node_value (list1, node1) == obj);
214               ASSERT (gl_list_node_value (list2, node2) == obj);
215               ASSERT (gl_list_node_value (list3, node3) == obj);
216               ASSERT (gl_list_get_at (list1, 0) == obj);
217               ASSERT (gl_list_get_at (list2, 0) == obj);
218               ASSERT (gl_list_get_at (list3, 0) == obj);
219             }
220             break;
221           case 4: /* add 1 element */
222             {
223               const char *obj = RANDOM_OBJECT ();
224               gl_list_node_t node1, node2, node3;
225               node1 = gl_list_nx_add_last (list1, obj);
226               ASSERT (node1 != NULL);
227               node2 = gl_list_nx_add_last (list2, obj);
228               ASSERT (node2 != NULL);
229               node3 = gl_list_nx_add_last (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, gl_list_size (list1) - 1) == obj);
235               ASSERT (gl_list_get_at (list2, gl_list_size (list2) - 1) == obj);
236               ASSERT (gl_list_get_at (list3, gl_list_size (list3) - 1) == obj);
237             }
238             break;
239           case 5: /* add 3 elements */
240             {
241               const char *obj0 = RANDOM_OBJECT ();
242               const char *obj1 = RANDOM_OBJECT ();
243               const char *obj2 = RANDOM_OBJECT ();
244               gl_list_node_t node1, node2, node3;
245               node1 = gl_list_nx_add_first (list1, obj2);
246               ASSERT (node1 != NULL);
247               node1 = gl_list_nx_add_before (list1, node1, obj0);
248               ASSERT (node1 != NULL);
249               node1 = gl_list_nx_add_after (list1, node1, obj1);
250               ASSERT (node1 != NULL);
251               node2 = gl_list_nx_add_first (list2, obj2);
252               ASSERT (node2 != NULL);
253               node2 = gl_list_nx_add_before (list2, node2, obj0);
254               ASSERT (node2 != NULL);
255               node2 = gl_list_nx_add_after (list2, node2, obj1);
256               ASSERT (node2 != NULL);
257               node3 = gl_list_nx_add_first (list3, obj2);
258               ASSERT (node3 != NULL);
259               node3 = gl_list_nx_add_before (list3, node3, obj0);
260               ASSERT (node3 != NULL);
261               node3 = gl_list_nx_add_after (list3, node3, obj1);
262               ASSERT (node3 != NULL);
263               ASSERT (gl_list_node_value (list1, node1) == obj1);
264               ASSERT (gl_list_node_value (list2, node2) == obj1);
265               ASSERT (gl_list_node_value (list3, node3) == obj1);
266               ASSERT (gl_list_get_at (list1, 0) == obj0);
267               ASSERT (gl_list_get_at (list1, 1) == obj1);
268               ASSERT (gl_list_get_at (list1, 2) == obj2);
269               ASSERT (gl_list_get_at (list2, 0) == obj0);
270               ASSERT (gl_list_get_at (list2, 1) == obj1);
271               ASSERT (gl_list_get_at (list2, 2) == obj2);
272               ASSERT (gl_list_get_at (list3, 0) == obj0);
273               ASSERT (gl_list_get_at (list3, 1) == obj1);
274               ASSERT (gl_list_get_at (list3, 2) == obj2);
275             }
276             break;
277           case 6: /* add 1 element */
278             {
279               size_t index = RANDOM (gl_list_size (list1) + 1);
280               const char *obj = RANDOM_OBJECT ();
281               gl_list_node_t node1, node2, node3;
282               node1 = gl_list_nx_add_at (list1, index, obj);
283               ASSERT (node1 != NULL);
284               node2 = gl_list_nx_add_at (list2, index, obj);
285               ASSERT (node2 != NULL);
286               node3 = gl_list_nx_add_at (list3, index, obj);
287               ASSERT (node3 != NULL);
288               ASSERT (gl_list_get_at (list1, index) == obj);
289               ASSERT (gl_list_node_value (list1, node1) == obj);
290               ASSERT (gl_list_get_at (list2, index) == obj);
291               ASSERT (gl_list_node_value (list2, node2) == obj);
292               ASSERT (gl_list_get_at (list3, index) == obj);
293               ASSERT (gl_list_node_value (list3, node3) == obj);
294               if (index > 0)
295                 {
296                   ASSERT (gl_list_node_value (list1, gl_list_previous_node (list1, node1))
297                           == gl_list_get_at (list1, index - 1));
298                   ASSERT (gl_list_node_value (list2, gl_list_previous_node (list3, node3))
299                           == gl_list_get_at (list2, index - 1));
300                   ASSERT (gl_list_node_value (list3, gl_list_previous_node (list3, node3))
301                           == gl_list_get_at (list2, index - 1));
302                 }
303               if (index + 1 < gl_list_size (list1))
304                 {
305                   ASSERT (gl_list_node_value (list1, gl_list_next_node (list1, node1))
306                           == gl_list_get_at (list1, index + 1));
307                   ASSERT (gl_list_node_value (list2, gl_list_next_node (list3, node3))
308                           == gl_list_get_at (list2, index + 1));
309                   ASSERT (gl_list_node_value (list3, gl_list_next_node (list3, node3))
310                           == gl_list_get_at (list2, index + 1));
311                 }
312             }
313             break;
314           case 7: case 8: /* remove 1 element */
315             if (gl_list_size (list1) > 0)
316               {
317                 size_t n = gl_list_size (list1);
318                 const char *obj = gl_list_get_at (list1, RANDOM (n));
319                 gl_list_node_t node1, node2, node3;
320                 node1 = gl_list_search (list1, obj);
321                 node2 = gl_list_search (list2, obj);
322                 node3 = gl_list_search (list3, obj);
323                 ASSERT (node1 != NULL);
324                 ASSERT (node2 != NULL);
325                 ASSERT (node3 != NULL);
326                 ASSERT (gl_list_remove_node (list1, node1));
327                 ASSERT (gl_list_remove_node (list2, node2));
328                 ASSERT (gl_list_remove_node (list3, node3));
329                 ASSERT (gl_list_size (list1) == n - 1);
330               }
331             break;
332           case 9: case 10: /* remove 1 element */
333             if (gl_list_size (list1) > 0)
334               {
335                 size_t n = gl_list_size (list1);
336                 size_t index = RANDOM (n);
337                 ASSERT (gl_list_remove_at (list1, index));
338                 ASSERT (gl_list_remove_at (list2, index));
339                 ASSERT (gl_list_remove_at (list3, index));
340                 ASSERT (gl_list_size (list1) == n - 1);
341               }
342             break;
343           case 11: case 12: /* remove 1 element */
344             if (gl_list_size (list1) > 0)
345               {
346                 size_t n = gl_list_size (list1);
347                 const char *obj = gl_list_get_at (list1, RANDOM (n));
348                 ASSERT (gl_list_remove (list1, obj));
349                 ASSERT (gl_list_remove (list2, obj));
350                 ASSERT (gl_list_remove (list3, obj));
351                 ASSERT (gl_list_size (list1) == n - 1);
352               }
353             break;
354           case 13:
355             if (gl_list_size (list1) > 0)
356               {
357                 size_t n = gl_list_size (list1);
358                 const char *obj = "xyzzy";
359                 ASSERT (!gl_list_remove (list1, obj));
360                 ASSERT (!gl_list_remove (list2, obj));
361                 ASSERT (!gl_list_remove (list3, obj));
362                 ASSERT (gl_list_size (list1) == n);
363               }
364             break;
365           case 14:
366             {
367               size_t n = gl_list_size (list1);
368               gl_list_iterator_t iter1, iter2, iter3;
369               const void *elt;
370               iter1 = gl_list_iterator (list1);
371               iter2 = gl_list_iterator (list2);
372               iter3 = gl_list_iterator (list3);
373               for (i = 0; i < n; i++)
374                 {
375                   ASSERT (gl_list_iterator_next (&iter1, &elt, NULL));
376                   ASSERT (gl_list_get_at (list1, i) == elt);
377                   ASSERT (gl_list_iterator_next (&iter2, &elt, NULL));
378                   ASSERT (gl_list_get_at (list2, i) == elt);
379                   ASSERT (gl_list_iterator_next (&iter3, &elt, NULL));
380                   ASSERT (gl_list_get_at (list3, i) == elt);
381                 }
382               ASSERT (!gl_list_iterator_next (&iter1, &elt, NULL));
383               ASSERT (!gl_list_iterator_next (&iter2, &elt, NULL));
384               ASSERT (!gl_list_iterator_next (&iter3, &elt, NULL));
385               gl_list_iterator_free (&iter1);
386               gl_list_iterator_free (&iter2);
387               gl_list_iterator_free (&iter3);
388             }
389             break;
390           case 15:
391             {
392               size_t end = RANDOM (gl_list_size (list1) + 1);
393               size_t start = RANDOM (end + 1);
394               gl_list_iterator_t iter1, iter2, iter3;
395               const void *elt;
396               iter1 = gl_list_iterator_from_to (list1, start, end);
397               iter2 = gl_list_iterator_from_to (list2, start, end);
398               iter3 = gl_list_iterator_from_to (list3, start, end);
399               for (i = start; i < end; i++)
400                 {
401                   ASSERT (gl_list_iterator_next (&iter1, &elt, NULL));
402                   ASSERT (gl_list_get_at (list1, i) == elt);
403                   ASSERT (gl_list_iterator_next (&iter2, &elt, NULL));
404                   ASSERT (gl_list_get_at (list2, i) == elt);
405                   ASSERT (gl_list_iterator_next (&iter3, &elt, NULL));
406                   ASSERT (gl_list_get_at (list3, i) == elt);
407                 }
408               ASSERT (!gl_list_iterator_next (&iter1, &elt, NULL));
409               ASSERT (!gl_list_iterator_next (&iter2, &elt, NULL));
410               ASSERT (!gl_list_iterator_next (&iter3, &elt, NULL));
411               gl_list_iterator_free (&iter1);
412               gl_list_iterator_free (&iter2);
413               gl_list_iterator_free (&iter3);
414             }
415             break;
416           }
417         check_all (list1, list2, list3);
418       }
419
420     gl_list_free (list1);
421     gl_list_free (list2);
422     gl_list_free (list3);
423     free (contents);
424   }
425
426   return 0;
427 }