1 /* Test of sequential list data type implementation.
2 Copyright (C) 2006-2020 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_linkedhash_list.h"
26 #include "gl_array_list.h"
29 static const char *objects
[15] =
31 "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o"
34 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
37 string_equals (const void *x1
, const void *x2
)
41 return strcmp (s1
, s2
) == 0;
44 /* A hash function for NUL-terminated char* strings using
45 the method described by Bruno Haible.
46 See https://www.haible.de/bruno/hashfunc.html. */
48 string_hash (const void *x
)
54 h
= *s
+ ((h
<< 9) | (h
>> (SIZE_BITS
- 9)));
59 #define RANDOM(n) (rand () % (n))
60 #define RANDOM_OBJECT() objects[RANDOM (SIZEOF (objects))]
63 check_equals (gl_list_t list1
, gl_list_t list2
)
67 n
= gl_list_size (list1
);
68 ASSERT (n
== gl_list_size (list2
));
69 for (i
= 0; i
< n
; i
++)
71 ASSERT (gl_list_get_at (list1
, i
) == gl_list_get_at (list2
, i
));
76 check_all (gl_list_t list1
, gl_list_t list2
, gl_list_t list3
)
78 check_equals (list1
, list2
);
79 check_equals (list1
, list3
);
83 main (int argc
, char *argv
[])
85 gl_list_t list1
, list2
, list3
;
87 /* Allow the user to provide a non-default random seed on the command line. */
89 srand (atoi (argv
[1]));
92 size_t initial_size
= RANDOM (50);
93 const void **contents
=
94 (const void **) malloc (initial_size
* sizeof (const void *));
98 for (i
= 0; i
< initial_size
; i
++)
99 contents
[i
] = RANDOM_OBJECT ();
102 list1
= gl_list_nx_create (GL_ARRAY_LIST
,
103 string_equals
, string_hash
, NULL
, true,
104 initial_size
, contents
);
105 ASSERT (list1
!= NULL
);
107 list2
= gl_list_nx_create_empty (GL_LINKEDHASH_LIST
,
108 string_equals
, string_hash
, NULL
, true);
109 ASSERT (list2
!= NULL
);
110 for (i
= 0; i
< initial_size
; i
++)
111 ASSERT (gl_list_nx_add_last (list2
, contents
[i
]) != NULL
);
114 list3
= gl_list_nx_create (GL_LINKEDHASH_LIST
,
115 string_equals
, string_hash
, NULL
, true,
116 initial_size
, contents
);
117 ASSERT (list3
!= NULL
);
119 check_all (list1
, list2
, list3
);
121 for (repeat
= 0; repeat
< 10000; repeat
++)
123 unsigned int operation
= RANDOM (18);
127 if (gl_list_size (list1
) > 0)
129 size_t index
= RANDOM (gl_list_size (list1
));
130 const char *obj
= RANDOM_OBJECT ();
131 gl_list_node_t node1
, node2
, node3
;
133 node1
= gl_list_nx_set_at (list1
, index
, obj
);
134 ASSERT (node1
!= NULL
);
135 ASSERT (gl_list_get_at (list1
, index
) == obj
);
136 ASSERT (gl_list_node_value (list1
, node1
) == obj
);
138 node2
= gl_list_nx_set_at (list2
, index
, obj
);
139 ASSERT (node2
!= NULL
);
140 ASSERT (gl_list_get_at (list2
, index
) == obj
);
141 ASSERT (gl_list_node_value (list2
, node2
) == obj
);
143 node3
= gl_list_nx_set_at (list3
, index
, obj
);
144 ASSERT (node3
!= NULL
);
145 ASSERT (gl_list_get_at (list3
, index
) == obj
);
146 ASSERT (gl_list_node_value (list3
, node3
) == obj
);
150 ASSERT (gl_list_node_value (list1
, gl_list_previous_node (list1
, node1
))
151 == gl_list_get_at (list1
, index
- 1));
152 ASSERT (gl_list_node_value (list2
, gl_list_previous_node (list3
, node3
))
153 == gl_list_get_at (list2
, index
- 1));
154 ASSERT (gl_list_node_value (list3
, gl_list_previous_node (list3
, node3
))
155 == gl_list_get_at (list2
, index
- 1));
157 if (index
+ 1 < gl_list_size (list1
))
159 ASSERT (gl_list_node_value (list1
, gl_list_next_node (list1
, node1
))
160 == gl_list_get_at (list1
, index
+ 1));
161 ASSERT (gl_list_node_value (list2
, gl_list_next_node (list3
, node3
))
162 == gl_list_get_at (list2
, index
+ 1));
163 ASSERT (gl_list_node_value (list3
, gl_list_next_node (list3
, node3
))
164 == gl_list_get_at (list2
, index
+ 1));
170 const char *obj
= RANDOM_OBJECT ();
171 gl_list_node_t node1
, node2
, node3
;
172 node1
= gl_list_search (list1
, obj
);
173 node2
= gl_list_search (list2
, obj
);
174 node3
= gl_list_search (list3
, obj
);
177 ASSERT (node2
== NULL
);
178 ASSERT (node3
== NULL
);
182 ASSERT (node2
!= NULL
);
183 ASSERT (node3
!= NULL
);
184 ASSERT (gl_list_node_value (list1
, node1
) == obj
);
185 ASSERT (gl_list_node_value (list2
, node2
) == obj
);
186 ASSERT (gl_list_node_value (list3
, node3
) == obj
);
192 const char *obj
= RANDOM_OBJECT ();
193 size_t index1
, index2
, index3
;
194 index1
= gl_list_indexof (list1
, obj
);
195 index2
= gl_list_indexof (list2
, obj
);
196 index3
= gl_list_indexof (list3
, obj
);
197 if (index1
== (size_t)(-1))
199 ASSERT (index2
== (size_t)(-1));
200 ASSERT (index3
== (size_t)(-1));
204 ASSERT (index2
!= (size_t)(-1));
205 ASSERT (index3
!= (size_t)(-1));
206 ASSERT (gl_list_get_at (list1
, index1
) == obj
);
207 ASSERT (gl_list_get_at (list2
, index2
) == obj
);
208 ASSERT (gl_list_get_at (list3
, index3
) == obj
);
209 ASSERT (index2
== index1
);
210 ASSERT (index3
== index1
);
214 case 3: /* add 1 element */
216 const char *obj
= RANDOM_OBJECT ();
217 gl_list_node_t node1
, node2
, node3
;
218 node1
= gl_list_nx_add_first (list1
, obj
);
219 ASSERT (node1
!= NULL
);
220 node2
= gl_list_nx_add_first (list2
, obj
);
221 ASSERT (node2
!= NULL
);
222 node3
= gl_list_nx_add_first (list3
, obj
);
223 ASSERT (node3
!= NULL
);
224 ASSERT (gl_list_node_value (list1
, node1
) == obj
);
225 ASSERT (gl_list_node_value (list2
, node2
) == obj
);
226 ASSERT (gl_list_node_value (list3
, node3
) == obj
);
227 ASSERT (gl_list_get_at (list1
, 0) == obj
);
228 ASSERT (gl_list_get_at (list2
, 0) == obj
);
229 ASSERT (gl_list_get_at (list3
, 0) == obj
);
232 case 4: /* add 1 element */
234 const char *obj
= RANDOM_OBJECT ();
235 gl_list_node_t node1
, node2
, node3
;
236 node1
= gl_list_nx_add_last (list1
, obj
);
237 ASSERT (node1
!= NULL
);
238 node2
= gl_list_nx_add_last (list2
, obj
);
239 ASSERT (node2
!= NULL
);
240 node3
= gl_list_nx_add_last (list3
, obj
);
241 ASSERT (node3
!= NULL
);
242 ASSERT (gl_list_node_value (list1
, node1
) == obj
);
243 ASSERT (gl_list_node_value (list2
, node2
) == obj
);
244 ASSERT (gl_list_node_value (list3
, node3
) == obj
);
245 ASSERT (gl_list_get_at (list1
, gl_list_size (list1
) - 1) == obj
);
246 ASSERT (gl_list_get_at (list2
, gl_list_size (list2
) - 1) == obj
);
247 ASSERT (gl_list_get_at (list3
, gl_list_size (list3
) - 1) == obj
);
250 case 5: /* add 3 elements */
252 const char *obj0
= RANDOM_OBJECT ();
253 const char *obj1
= RANDOM_OBJECT ();
254 const char *obj2
= RANDOM_OBJECT ();
255 gl_list_node_t node1
, node2
, node3
;
256 node1
= gl_list_nx_add_first (list1
, obj2
);
257 ASSERT (node1
!= NULL
);
258 node1
= gl_list_nx_add_before (list1
, node1
, obj0
);
259 ASSERT (node1
!= NULL
);
260 node1
= gl_list_nx_add_after (list1
, node1
, obj1
);
261 ASSERT (node1
!= NULL
);
262 node2
= gl_list_nx_add_first (list2
, obj2
);
263 ASSERT (node2
!= NULL
);
264 node2
= gl_list_nx_add_before (list2
, node2
, obj0
);
265 ASSERT (node2
!= NULL
);
266 node2
= gl_list_nx_add_after (list2
, node2
, obj1
);
267 ASSERT (node2
!= NULL
);
268 node3
= gl_list_nx_add_first (list3
, obj2
);
269 ASSERT (node3
!= NULL
);
270 node3
= gl_list_nx_add_before (list3
, node3
, obj0
);
271 ASSERT (node3
!= NULL
);
272 node3
= gl_list_nx_add_after (list3
, node3
, obj1
);
273 ASSERT (node3
!= NULL
);
274 ASSERT (gl_list_node_value (list1
, node1
) == obj1
);
275 ASSERT (gl_list_node_value (list2
, node2
) == obj1
);
276 ASSERT (gl_list_node_value (list3
, node3
) == obj1
);
277 ASSERT (gl_list_get_at (list1
, 0) == obj0
);
278 ASSERT (gl_list_get_at (list1
, 1) == obj1
);
279 ASSERT (gl_list_get_at (list1
, 2) == obj2
);
280 ASSERT (gl_list_get_at (list2
, 0) == obj0
);
281 ASSERT (gl_list_get_at (list2
, 1) == obj1
);
282 ASSERT (gl_list_get_at (list2
, 2) == obj2
);
283 ASSERT (gl_list_get_at (list3
, 0) == obj0
);
284 ASSERT (gl_list_get_at (list3
, 1) == obj1
);
285 ASSERT (gl_list_get_at (list3
, 2) == obj2
);
288 case 6: /* add 1 element */
290 size_t index
= RANDOM (gl_list_size (list1
) + 1);
291 const char *obj
= RANDOM_OBJECT ();
292 gl_list_node_t node1
, node2
, node3
;
293 node1
= gl_list_nx_add_at (list1
, index
, obj
);
294 ASSERT (node1
!= NULL
);
295 node2
= gl_list_nx_add_at (list2
, index
, obj
);
296 ASSERT (node2
!= NULL
);
297 node3
= gl_list_nx_add_at (list3
, index
, obj
);
298 ASSERT (node3
!= NULL
);
299 ASSERT (gl_list_get_at (list1
, index
) == obj
);
300 ASSERT (gl_list_node_value (list1
, node1
) == obj
);
301 ASSERT (gl_list_get_at (list2
, index
) == obj
);
302 ASSERT (gl_list_node_value (list2
, node2
) == obj
);
303 ASSERT (gl_list_get_at (list3
, index
) == obj
);
304 ASSERT (gl_list_node_value (list3
, node3
) == obj
);
307 ASSERT (gl_list_node_value (list1
, gl_list_previous_node (list1
, node1
))
308 == gl_list_get_at (list1
, index
- 1));
309 ASSERT (gl_list_node_value (list2
, gl_list_previous_node (list3
, node3
))
310 == gl_list_get_at (list2
, index
- 1));
311 ASSERT (gl_list_node_value (list3
, gl_list_previous_node (list3
, node3
))
312 == gl_list_get_at (list2
, index
- 1));
314 if (index
+ 1 < gl_list_size (list1
))
316 ASSERT (gl_list_node_value (list1
, gl_list_next_node (list1
, node1
))
317 == gl_list_get_at (list1
, index
+ 1));
318 ASSERT (gl_list_node_value (list2
, gl_list_next_node (list3
, node3
))
319 == gl_list_get_at (list2
, index
+ 1));
320 ASSERT (gl_list_node_value (list3
, gl_list_next_node (list3
, node3
))
321 == gl_list_get_at (list2
, index
+ 1));
325 case 7: case 8: /* remove 1 element */
326 if (gl_list_size (list1
) > 0)
328 size_t n
= gl_list_size (list1
);
329 const char *obj
= gl_list_get_at (list1
, RANDOM (n
));
330 gl_list_node_t node1
, node2
, node3
;
331 node1
= gl_list_search (list1
, obj
);
332 node2
= gl_list_search (list2
, obj
);
333 node3
= gl_list_search (list3
, obj
);
334 ASSERT (node1
!= NULL
);
335 ASSERT (node2
!= NULL
);
336 ASSERT (node3
!= NULL
);
337 ASSERT (gl_list_remove_node (list1
, node1
));
338 ASSERT (gl_list_remove_node (list2
, node2
));
339 ASSERT (gl_list_remove_node (list3
, node3
));
340 ASSERT (gl_list_size (list1
) == n
- 1);
343 case 9: case 10: /* remove 1 element */
344 if (gl_list_size (list1
) > 0)
346 size_t n
= gl_list_size (list1
);
347 size_t index
= RANDOM (n
);
348 ASSERT (gl_list_remove_at (list1
, index
));
349 ASSERT (gl_list_remove_at (list2
, index
));
350 ASSERT (gl_list_remove_at (list3
, index
));
351 ASSERT (gl_list_size (list1
) == n
- 1);
354 case 11: /* remove first element */
356 size_t n
= gl_list_size (list1
);
357 bool removed1
= gl_list_remove_first (list1
);
358 ASSERT (gl_list_remove_first (list2
) == removed1
);
359 ASSERT (gl_list_remove_first (list3
) == removed1
);
360 ASSERT (gl_list_size (list1
) == n
- (int) removed1
);
363 case 12: /* remove last element */
365 size_t n
= gl_list_size (list1
);
366 bool removed1
= gl_list_remove_last (list1
);
367 ASSERT (gl_list_remove_last (list2
) == removed1
);
368 ASSERT (gl_list_remove_last (list3
) == removed1
);
369 ASSERT (gl_list_size (list1
) == n
- (int) removed1
);
372 case 13: case 14: /* remove 1 element */
373 if (gl_list_size (list1
) > 0)
375 size_t n
= gl_list_size (list1
);
376 const char *obj
= gl_list_get_at (list1
, RANDOM (n
));
377 ASSERT (gl_list_remove (list1
, obj
));
378 ASSERT (gl_list_remove (list2
, obj
));
379 ASSERT (gl_list_remove (list3
, obj
));
380 ASSERT (gl_list_size (list1
) == n
- 1);
384 if (gl_list_size (list1
) > 0)
386 size_t n
= gl_list_size (list1
);
387 const char *obj
= "xyzzy";
388 ASSERT (!gl_list_remove (list1
, obj
));
389 ASSERT (!gl_list_remove (list2
, obj
));
390 ASSERT (!gl_list_remove (list3
, obj
));
391 ASSERT (gl_list_size (list1
) == n
);
396 size_t n
= gl_list_size (list1
);
397 gl_list_iterator_t iter1
, iter2
, iter3
;
399 iter1
= gl_list_iterator (list1
);
400 iter2
= gl_list_iterator (list2
);
401 iter3
= gl_list_iterator (list3
);
402 for (i
= 0; i
< n
; i
++)
404 ASSERT (gl_list_iterator_next (&iter1
, &elt
, NULL
));
405 ASSERT (gl_list_get_at (list1
, i
) == elt
);
406 ASSERT (gl_list_iterator_next (&iter2
, &elt
, NULL
));
407 ASSERT (gl_list_get_at (list2
, i
) == elt
);
408 ASSERT (gl_list_iterator_next (&iter3
, &elt
, NULL
));
409 ASSERT (gl_list_get_at (list3
, i
) == elt
);
411 ASSERT (!gl_list_iterator_next (&iter1
, &elt
, NULL
));
412 ASSERT (!gl_list_iterator_next (&iter2
, &elt
, NULL
));
413 ASSERT (!gl_list_iterator_next (&iter3
, &elt
, NULL
));
414 gl_list_iterator_free (&iter1
);
415 gl_list_iterator_free (&iter2
);
416 gl_list_iterator_free (&iter3
);
421 size_t end
= RANDOM (gl_list_size (list1
) + 1);
422 size_t start
= RANDOM (end
+ 1);
423 gl_list_iterator_t iter1
, iter2
, iter3
;
425 iter1
= gl_list_iterator_from_to (list1
, start
, end
);
426 iter2
= gl_list_iterator_from_to (list2
, start
, end
);
427 iter3
= gl_list_iterator_from_to (list3
, start
, end
);
428 for (i
= start
; i
< end
; i
++)
430 ASSERT (gl_list_iterator_next (&iter1
, &elt
, NULL
));
431 ASSERT (gl_list_get_at (list1
, i
) == elt
);
432 ASSERT (gl_list_iterator_next (&iter2
, &elt
, NULL
));
433 ASSERT (gl_list_get_at (list2
, i
) == elt
);
434 ASSERT (gl_list_iterator_next (&iter3
, &elt
, NULL
));
435 ASSERT (gl_list_get_at (list3
, i
) == elt
);
437 ASSERT (!gl_list_iterator_next (&iter1
, &elt
, NULL
));
438 ASSERT (!gl_list_iterator_next (&iter2
, &elt
, NULL
));
439 ASSERT (!gl_list_iterator_next (&iter3
, &elt
, NULL
));
440 gl_list_iterator_free (&iter1
);
441 gl_list_iterator_free (&iter2
);
442 gl_list_iterator_free (&iter3
);
446 check_all (list1
, list2
, list3
);
449 gl_list_free (list1
);
450 gl_list_free (list2
);
451 gl_list_free (list3
);