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_rbtree_list.h"
24 #include "gl_array_list.h"
27 extern void gl_rbtree_list_check_invariants (gl_list_t list
);
29 static const char *objects
[15] =
31 "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o"
34 #define RANDOM(n) (rand () % (n))
35 #define RANDOM_OBJECT() objects[RANDOM (SIZEOF (objects))]
38 check_equals (gl_list_t list1
, gl_list_t list2
)
42 n
= gl_list_size (list1
);
43 ASSERT (n
== gl_list_size (list2
));
44 for (i
= 0; i
< n
; i
++)
46 ASSERT (gl_list_get_at (list1
, i
) == gl_list_get_at (list2
, i
));
51 check_equals_by_forward_iteration (gl_list_t list1
, gl_list_t list2
)
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
)
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
);
62 ASSERT ((node1
== NULL
) == (node2
== NULL
));
66 check_equals_by_backward_iteration (gl_list_t list1
, gl_list_t list2
)
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
)
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
);
77 ASSERT ((node1
== NULL
) == (node2
== NULL
));
81 check_all (gl_list_t list1
, gl_list_t list2
, gl_list_t list3
)
83 gl_rbtree_list_check_invariants (list2
);
84 gl_rbtree_list_check_invariants (list3
);
85 check_equals (list1
, list2
);
86 check_equals (list1
, list3
);
90 main (int argc
, char *argv
[])
92 gl_list_t list1
, list2
, list3
;
94 /* Allow the user to provide a non-default random seed on the command line. */
96 srand (atoi (argv
[1]));
99 size_t initial_size
= RANDOM (50);
100 const void **contents
=
101 (const void **) malloc (initial_size
* sizeof (const void *));
105 for (i
= 0; i
< initial_size
; i
++)
106 contents
[i
] = RANDOM_OBJECT ();
109 list1
= gl_list_nx_create (GL_ARRAY_LIST
, NULL
, NULL
, NULL
, true,
110 initial_size
, contents
);
111 ASSERT (list1
!= NULL
);
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
);
119 list3
= gl_list_nx_create (GL_RBTREE_LIST
, NULL
, NULL
, NULL
, true,
120 initial_size
, contents
);
121 ASSERT (list3
!= NULL
);
123 check_all (list1
, list2
, list3
);
125 check_equals_by_forward_iteration (list1
, list2
);
126 check_equals_by_backward_iteration (list1
, list2
);
128 for (repeat
= 0; repeat
< 10000; repeat
++)
130 unsigned int operation
= RANDOM (18);
134 if (gl_list_size (list1
) > 0)
136 size_t index
= RANDOM (gl_list_size (list1
));
137 const char *obj
= RANDOM_OBJECT ();
138 gl_list_node_t node1
, node2
, node3
;
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
);
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
);
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
);
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));
164 if (index
+ 1 < gl_list_size (list1
))
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));
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
);
184 ASSERT (node2
== NULL
);
185 ASSERT (node3
== NULL
);
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
);
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))
206 ASSERT (index2
== (size_t)(-1));
207 ASSERT (index3
== (size_t)(-1));
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
);
221 case 3: /* add 1 element */
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
);
239 case 4: /* add 1 element */
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
);
257 case 5: /* add 3 elements */
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
);
295 case 6: /* add 1 element */
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
);
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));
321 if (index
+ 1 < gl_list_size (list1
))
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));
332 case 7: case 8: /* remove 1 element */
333 if (gl_list_size (list1
) > 0)
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);
350 case 9: case 10: /* remove 1 element */
351 if (gl_list_size (list1
) > 0)
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);
361 case 11: /* remove first element */
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
);
370 case 12: /* remove last element */
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
);
379 case 13: case 14: /* remove 1 element */
380 if (gl_list_size (list1
) > 0)
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);
391 if (gl_list_size (list1
) > 0)
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
);
403 size_t n
= gl_list_size (list1
);
404 gl_list_iterator_t iter1
, iter2
, iter3
;
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
++)
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
);
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
);
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
;
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
++)
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
);
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
);
453 check_all (list1
, list2
, list3
);
456 gl_list_free (list1
);
457 gl_list_free (list2
);
458 gl_list_free (list3
);
462 return test_exit_status
;