1 /* Test of sequential list data type implementation.
2 Copyright (C) 2006-2024 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
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.
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.
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/>. */
20 #include "gl_avltreehash_list.h"
26 #include "gl_array_list.h"
29 extern void gl_avltreehash_list_check_invariants (gl_list_t list
);
31 static const char *objects
[15] =
33 "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o"
36 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
39 string_equals (const void *x1
, const void *x2
)
43 return strcmp (s1
, s2
) == 0;
46 /* A hash function for NUL-terminated char* strings using
47 the method described by Bruno Haible.
48 See https://www.haible.de/bruno/hashfunc.html. */
50 string_hash (const void *x
)
56 h
= *s
+ ((h
<< 9) | (h
>> (SIZE_BITS
- 9)));
61 #define RANDOM(n) (rand () % (n))
62 #define RANDOM_OBJECT() objects[RANDOM (SIZEOF (objects))]
65 check_equals (gl_list_t list1
, gl_list_t list2
)
69 n
= gl_list_size (list1
);
70 ASSERT (n
== gl_list_size (list2
));
71 for (i
= 0; i
< n
; i
++)
73 ASSERT (gl_list_get_at (list1
, i
) == gl_list_get_at (list2
, i
));
78 check_equals_by_forward_iteration (gl_list_t list1
, gl_list_t list2
)
80 gl_list_node_t node1
= gl_list_first_node (list1
);
81 gl_list_node_t node2
= gl_list_first_node (list2
);
82 while (node1
!= NULL
&& node2
!= NULL
)
84 ASSERT (gl_list_node_value (list1
, node1
)
85 == gl_list_node_value (list2
, node2
));
86 node1
= gl_list_next_node (list1
, node1
);
87 node2
= gl_list_next_node (list2
, node2
);
89 ASSERT ((node1
== NULL
) == (node2
== NULL
));
93 check_equals_by_backward_iteration (gl_list_t list1
, gl_list_t list2
)
95 gl_list_node_t node1
= gl_list_last_node (list1
);
96 gl_list_node_t node2
= gl_list_last_node (list2
);
97 while (node1
!= NULL
&& node2
!= NULL
)
99 ASSERT (gl_list_node_value (list1
, node1
)
100 == gl_list_node_value (list2
, node2
));
101 node1
= gl_list_previous_node (list1
, node1
);
102 node2
= gl_list_previous_node (list2
, node2
);
104 ASSERT ((node1
== NULL
) == (node2
== NULL
));
108 check_all (gl_list_t list1
, gl_list_t list2
, gl_list_t list3
)
110 gl_avltreehash_list_check_invariants (list2
);
111 gl_avltreehash_list_check_invariants (list3
);
112 check_equals (list1
, list2
);
113 check_equals (list1
, list3
);
117 main (int argc
, char *argv
[])
119 gl_list_t list1
, list2
, list3
;
121 /* Allow the user to provide a non-default random seed on the command line. */
123 srand (atoi (argv
[1]));
126 size_t initial_size
= RANDOM (50);
127 const void **contents
=
128 (const void **) malloc (initial_size
* sizeof (const void *));
132 for (i
= 0; i
< initial_size
; i
++)
133 contents
[i
] = RANDOM_OBJECT ();
136 list1
= gl_list_nx_create (GL_ARRAY_LIST
,
137 string_equals
, string_hash
, NULL
, true,
138 initial_size
, contents
);
139 ASSERT (list1
!= NULL
);
141 list2
= gl_list_nx_create_empty (GL_AVLTREEHASH_LIST
,
142 string_equals
, string_hash
, NULL
, true);
143 ASSERT (list2
!= NULL
);
144 for (i
= 0; i
< initial_size
; i
++)
145 ASSERT (gl_list_nx_add_last (list2
, contents
[i
]) != NULL
);
148 list3
= gl_list_nx_create (GL_AVLTREEHASH_LIST
,
149 string_equals
, string_hash
, NULL
, true,
150 initial_size
, contents
);
151 ASSERT (list3
!= NULL
);
153 check_all (list1
, list2
, list3
);
155 check_equals_by_forward_iteration (list1
, list2
);
156 check_equals_by_backward_iteration (list1
, list2
);
158 for (repeat
= 0; repeat
< 10000; repeat
++)
160 unsigned int operation
= RANDOM (18);
164 if (gl_list_size (list1
) > 0)
166 size_t index
= RANDOM (gl_list_size (list1
));
167 const char *obj
= RANDOM_OBJECT ();
168 gl_list_node_t node1
, node2
, node3
;
170 node1
= gl_list_nx_set_at (list1
, index
, obj
);
171 ASSERT (node1
!= NULL
);
172 ASSERT (gl_list_get_at (list1
, index
) == obj
);
173 ASSERT (gl_list_node_value (list1
, node1
) == obj
);
175 node2
= gl_list_nx_set_at (list2
, index
, obj
);
176 ASSERT (node2
!= NULL
);
177 ASSERT (gl_list_get_at (list2
, index
) == obj
);
178 ASSERT (gl_list_node_value (list2
, node2
) == obj
);
180 node3
= gl_list_nx_set_at (list3
, index
, obj
);
181 ASSERT (node3
!= NULL
);
182 ASSERT (gl_list_get_at (list3
, index
) == obj
);
183 ASSERT (gl_list_node_value (list3
, node3
) == obj
);
187 ASSERT (gl_list_node_value (list1
, gl_list_previous_node (list1
, node1
))
188 == gl_list_get_at (list1
, index
- 1));
189 ASSERT (gl_list_node_value (list2
, gl_list_previous_node (list3
, node3
))
190 == gl_list_get_at (list2
, index
- 1));
191 ASSERT (gl_list_node_value (list3
, gl_list_previous_node (list3
, node3
))
192 == gl_list_get_at (list2
, index
- 1));
194 if (index
+ 1 < gl_list_size (list1
))
196 ASSERT (gl_list_node_value (list1
, gl_list_next_node (list1
, node1
))
197 == gl_list_get_at (list1
, index
+ 1));
198 ASSERT (gl_list_node_value (list2
, gl_list_next_node (list3
, node3
))
199 == gl_list_get_at (list2
, index
+ 1));
200 ASSERT (gl_list_node_value (list3
, gl_list_next_node (list3
, node3
))
201 == gl_list_get_at (list2
, index
+ 1));
207 const char *obj
= RANDOM_OBJECT ();
208 gl_list_node_t node1
, node2
, node3
;
209 node1
= gl_list_search (list1
, obj
);
210 node2
= gl_list_search (list2
, obj
);
211 node3
= gl_list_search (list3
, obj
);
214 ASSERT (node2
== NULL
);
215 ASSERT (node3
== NULL
);
219 ASSERT (node2
!= NULL
);
220 ASSERT (node3
!= NULL
);
221 ASSERT (gl_list_node_value (list1
, node1
) == obj
);
222 ASSERT (gl_list_node_value (list2
, node2
) == obj
);
223 ASSERT (gl_list_node_value (list3
, node3
) == obj
);
229 const char *obj
= RANDOM_OBJECT ();
230 size_t index1
, index2
, index3
;
231 index1
= gl_list_indexof (list1
, obj
);
232 index2
= gl_list_indexof (list2
, obj
);
233 index3
= gl_list_indexof (list3
, obj
);
234 if (index1
== (size_t)(-1))
236 ASSERT (index2
== (size_t)(-1));
237 ASSERT (index3
== (size_t)(-1));
241 ASSERT (index2
!= (size_t)(-1));
242 ASSERT (index3
!= (size_t)(-1));
243 ASSERT (gl_list_get_at (list1
, index1
) == obj
);
244 ASSERT (gl_list_get_at (list2
, index2
) == obj
);
245 ASSERT (gl_list_get_at (list3
, index3
) == obj
);
246 ASSERT (index2
== index1
);
247 ASSERT (index3
== index1
);
251 case 3: /* add 1 element */
253 const char *obj
= RANDOM_OBJECT ();
254 gl_list_node_t node1
, node2
, node3
;
255 node1
= gl_list_nx_add_first (list1
, obj
);
256 ASSERT (node1
!= NULL
);
257 node2
= gl_list_nx_add_first (list2
, obj
);
258 ASSERT (node2
!= NULL
);
259 node3
= gl_list_nx_add_first (list3
, obj
);
260 ASSERT (node3
!= NULL
);
261 ASSERT (gl_list_node_value (list1
, node1
) == obj
);
262 ASSERT (gl_list_node_value (list2
, node2
) == obj
);
263 ASSERT (gl_list_node_value (list3
, node3
) == obj
);
264 ASSERT (gl_list_get_at (list1
, 0) == obj
);
265 ASSERT (gl_list_get_at (list2
, 0) == obj
);
266 ASSERT (gl_list_get_at (list3
, 0) == obj
);
269 case 4: /* add 1 element */
271 const char *obj
= RANDOM_OBJECT ();
272 gl_list_node_t node1
, node2
, node3
;
273 node1
= gl_list_nx_add_last (list1
, obj
);
274 ASSERT (node1
!= NULL
);
275 node2
= gl_list_nx_add_last (list2
, obj
);
276 ASSERT (node2
!= NULL
);
277 node3
= gl_list_nx_add_last (list3
, obj
);
278 ASSERT (node3
!= NULL
);
279 ASSERT (gl_list_node_value (list1
, node1
) == obj
);
280 ASSERT (gl_list_node_value (list2
, node2
) == obj
);
281 ASSERT (gl_list_node_value (list3
, node3
) == obj
);
282 ASSERT (gl_list_get_at (list1
, gl_list_size (list1
) - 1) == obj
);
283 ASSERT (gl_list_get_at (list2
, gl_list_size (list2
) - 1) == obj
);
284 ASSERT (gl_list_get_at (list3
, gl_list_size (list3
) - 1) == obj
);
287 case 5: /* add 3 elements */
289 const char *obj0
= RANDOM_OBJECT ();
290 const char *obj1
= RANDOM_OBJECT ();
291 const char *obj2
= RANDOM_OBJECT ();
292 gl_list_node_t node1
, node2
, node3
;
293 node1
= gl_list_nx_add_first (list1
, obj2
);
294 ASSERT (node1
!= NULL
);
295 node1
= gl_list_nx_add_before (list1
, node1
, obj0
);
296 ASSERT (node1
!= NULL
);
297 node1
= gl_list_nx_add_after (list1
, node1
, obj1
);
298 ASSERT (node1
!= NULL
);
299 node2
= gl_list_nx_add_first (list2
, obj2
);
300 ASSERT (node2
!= NULL
);
301 node2
= gl_list_nx_add_before (list2
, node2
, obj0
);
302 ASSERT (node2
!= NULL
);
303 node2
= gl_list_nx_add_after (list2
, node2
, obj1
);
304 ASSERT (node2
!= NULL
);
305 node3
= gl_list_nx_add_first (list3
, obj2
);
306 ASSERT (node3
!= NULL
);
307 node3
= gl_list_nx_add_before (list3
, node3
, obj0
);
308 ASSERT (node3
!= NULL
);
309 node3
= gl_list_nx_add_after (list3
, node3
, obj1
);
310 ASSERT (node3
!= NULL
);
311 ASSERT (gl_list_node_value (list1
, node1
) == obj1
);
312 ASSERT (gl_list_node_value (list2
, node2
) == obj1
);
313 ASSERT (gl_list_node_value (list3
, node3
) == obj1
);
314 ASSERT (gl_list_get_at (list1
, 0) == obj0
);
315 ASSERT (gl_list_get_at (list1
, 1) == obj1
);
316 ASSERT (gl_list_get_at (list1
, 2) == obj2
);
317 ASSERT (gl_list_get_at (list2
, 0) == obj0
);
318 ASSERT (gl_list_get_at (list2
, 1) == obj1
);
319 ASSERT (gl_list_get_at (list2
, 2) == obj2
);
320 ASSERT (gl_list_get_at (list3
, 0) == obj0
);
321 ASSERT (gl_list_get_at (list3
, 1) == obj1
);
322 ASSERT (gl_list_get_at (list3
, 2) == obj2
);
325 case 6: /* add 1 element */
327 size_t index
= RANDOM (gl_list_size (list1
) + 1);
328 const char *obj
= RANDOM_OBJECT ();
329 gl_list_node_t node1
, node2
, node3
;
330 node1
= gl_list_nx_add_at (list1
, index
, obj
);
331 ASSERT (node1
!= NULL
);
332 node2
= gl_list_nx_add_at (list2
, index
, obj
);
333 ASSERT (node2
!= NULL
);
334 node3
= gl_list_nx_add_at (list3
, index
, obj
);
335 ASSERT (node3
!= NULL
);
336 ASSERT (gl_list_get_at (list1
, index
) == obj
);
337 ASSERT (gl_list_node_value (list1
, node1
) == obj
);
338 ASSERT (gl_list_get_at (list2
, index
) == obj
);
339 ASSERT (gl_list_node_value (list2
, node2
) == obj
);
340 ASSERT (gl_list_get_at (list3
, index
) == obj
);
341 ASSERT (gl_list_node_value (list3
, node3
) == obj
);
344 ASSERT (gl_list_node_value (list1
, gl_list_previous_node (list1
, node1
))
345 == gl_list_get_at (list1
, index
- 1));
346 ASSERT (gl_list_node_value (list2
, gl_list_previous_node (list3
, node3
))
347 == gl_list_get_at (list2
, index
- 1));
348 ASSERT (gl_list_node_value (list3
, gl_list_previous_node (list3
, node3
))
349 == gl_list_get_at (list2
, index
- 1));
351 if (index
+ 1 < gl_list_size (list1
))
353 ASSERT (gl_list_node_value (list1
, gl_list_next_node (list1
, node1
))
354 == gl_list_get_at (list1
, index
+ 1));
355 ASSERT (gl_list_node_value (list2
, gl_list_next_node (list3
, node3
))
356 == gl_list_get_at (list2
, index
+ 1));
357 ASSERT (gl_list_node_value (list3
, gl_list_next_node (list3
, node3
))
358 == gl_list_get_at (list2
, index
+ 1));
362 case 7: case 8: /* remove 1 element */
363 if (gl_list_size (list1
) > 0)
365 size_t n
= gl_list_size (list1
);
366 const char *obj
= gl_list_get_at (list1
, RANDOM (n
));
367 gl_list_node_t node1
, node2
, node3
;
368 node1
= gl_list_search (list1
, obj
);
369 node2
= gl_list_search (list2
, obj
);
370 node3
= gl_list_search (list3
, obj
);
371 ASSERT (node1
!= NULL
);
372 ASSERT (node2
!= NULL
);
373 ASSERT (node3
!= NULL
);
374 ASSERT (gl_list_remove_node (list1
, node1
));
375 ASSERT (gl_list_remove_node (list2
, node2
));
376 ASSERT (gl_list_remove_node (list3
, node3
));
377 ASSERT (gl_list_size (list1
) == n
- 1);
380 case 9: case 10: /* remove 1 element */
381 if (gl_list_size (list1
) > 0)
383 size_t n
= gl_list_size (list1
);
384 size_t index
= RANDOM (n
);
385 ASSERT (gl_list_remove_at (list1
, index
));
386 ASSERT (gl_list_remove_at (list2
, index
));
387 ASSERT (gl_list_remove_at (list3
, index
));
388 ASSERT (gl_list_size (list1
) == n
- 1);
391 case 11: /* remove first element */
393 size_t n
= gl_list_size (list1
);
394 bool removed1
= gl_list_remove_first (list1
);
395 ASSERT (gl_list_remove_first (list2
) == removed1
);
396 ASSERT (gl_list_remove_first (list3
) == removed1
);
397 ASSERT (gl_list_size (list1
) == n
- (int) removed1
);
400 case 12: /* remove last element */
402 size_t n
= gl_list_size (list1
);
403 bool removed1
= gl_list_remove_last (list1
);
404 ASSERT (gl_list_remove_last (list2
) == removed1
);
405 ASSERT (gl_list_remove_last (list3
) == removed1
);
406 ASSERT (gl_list_size (list1
) == n
- (int) removed1
);
409 case 13: case 14: /* remove 1 element */
410 if (gl_list_size (list1
) > 0)
412 size_t n
= gl_list_size (list1
);
413 const char *obj
= gl_list_get_at (list1
, RANDOM (n
));
414 ASSERT (gl_list_remove (list1
, obj
));
415 ASSERT (gl_list_remove (list2
, obj
));
416 ASSERT (gl_list_remove (list3
, obj
));
417 ASSERT (gl_list_size (list1
) == n
- 1);
421 if (gl_list_size (list1
) > 0)
423 size_t n
= gl_list_size (list1
);
424 const char *obj
= "xyzzy";
425 ASSERT (!gl_list_remove (list1
, obj
));
426 ASSERT (!gl_list_remove (list2
, obj
));
427 ASSERT (!gl_list_remove (list3
, obj
));
428 ASSERT (gl_list_size (list1
) == n
);
433 size_t n
= gl_list_size (list1
);
434 gl_list_iterator_t iter1
, iter2
, iter3
;
436 iter1
= gl_list_iterator (list1
);
437 iter2
= gl_list_iterator (list2
);
438 iter3
= gl_list_iterator (list3
);
439 for (i
= 0; i
< n
; i
++)
441 ASSERT (gl_list_iterator_next (&iter1
, &elt
, NULL
));
442 ASSERT (gl_list_get_at (list1
, i
) == elt
);
443 ASSERT (gl_list_iterator_next (&iter2
, &elt
, NULL
));
444 ASSERT (gl_list_get_at (list2
, i
) == elt
);
445 ASSERT (gl_list_iterator_next (&iter3
, &elt
, NULL
));
446 ASSERT (gl_list_get_at (list3
, i
) == elt
);
448 ASSERT (!gl_list_iterator_next (&iter1
, &elt
, NULL
));
449 ASSERT (!gl_list_iterator_next (&iter2
, &elt
, NULL
));
450 ASSERT (!gl_list_iterator_next (&iter3
, &elt
, NULL
));
451 gl_list_iterator_free (&iter1
);
452 gl_list_iterator_free (&iter2
);
453 gl_list_iterator_free (&iter3
);
458 size_t end
= RANDOM (gl_list_size (list1
) + 1);
459 size_t start
= RANDOM (end
+ 1);
460 gl_list_iterator_t iter1
, iter2
, iter3
;
462 iter1
= gl_list_iterator_from_to (list1
, start
, end
);
463 iter2
= gl_list_iterator_from_to (list2
, start
, end
);
464 iter3
= gl_list_iterator_from_to (list3
, start
, end
);
465 for (i
= start
; i
< end
; i
++)
467 ASSERT (gl_list_iterator_next (&iter1
, &elt
, NULL
));
468 ASSERT (gl_list_get_at (list1
, i
) == elt
);
469 ASSERT (gl_list_iterator_next (&iter2
, &elt
, NULL
));
470 ASSERT (gl_list_get_at (list2
, i
) == elt
);
471 ASSERT (gl_list_iterator_next (&iter3
, &elt
, NULL
));
472 ASSERT (gl_list_get_at (list3
, i
) == elt
);
474 ASSERT (!gl_list_iterator_next (&iter1
, &elt
, NULL
));
475 ASSERT (!gl_list_iterator_next (&iter2
, &elt
, NULL
));
476 ASSERT (!gl_list_iterator_next (&iter3
, &elt
, NULL
));
477 gl_list_iterator_free (&iter1
);
478 gl_list_iterator_free (&iter2
);
479 gl_list_iterator_free (&iter3
);
483 check_all (list1
, list2
, list3
);
486 gl_list_free (list1
);
487 gl_list_free (list2
);
488 gl_list_free (list3
);
492 return test_exit_status
;