Independent Samples T-Test Dialog: Fix Crash
[pspp.git] / tests / libpspp / llx-test.c
blob7d95474d49b541edd6eea022585d0766f17aa58c
1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2006, 2010 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* This is a test program for the llx_* routines defined in
18 ll.c. This test program aims to be as comprehensive as
19 possible. "gcov -b" should report 100% coverage of lines and
20 branches in llx.c and llx.h. "valgrind --leak-check=yes
21 --show-reachable=yes" should give a clean report.
23 This test program depends only on ll.c, llx.c, and the
24 standard C library.
26 See ll-test.c for a similar program for the ll_* routines. */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
32 #include <libpspp/llx.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
37 /* Support preliminaries. */
38 #if __GNUC__ >= 2 && !defined UNUSED
39 #define UNUSED __attribute__ ((unused))
40 #else
41 #define UNUSED
42 #endif
44 /* Exit with a failure code.
45 (Place a breakpoint on this function while debugging.) */
46 static void
47 check_die (void)
49 exit (EXIT_FAILURE);
52 /* If OK is not true, prints a message about failure on the
53 current source file and the given LINE and terminates. */
54 static void
55 check_func (bool ok, int line)
57 if (!ok)
59 fprintf (stderr, "%s:%d: check failed\n", __FILE__, line);
60 check_die ();
64 /* Verifies that EXPR evaluates to true.
65 If not, prints a message citing the calling line number and
66 terminates. */
67 #define check(EXPR) check_func ((EXPR), __LINE__)
69 /* Prints a message about memory exhaustion and exits with a
70 failure code. */
71 static void
72 xalloc_die (void)
74 printf ("virtual memory exhausted\n");
75 exit (EXIT_FAILURE);
78 /* Allocates and returns N bytes of memory. */
79 static void *
80 xmalloc (size_t n)
82 if (n != 0)
84 void *p = malloc (n);
85 if (p == NULL)
86 xalloc_die ();
88 return p;
90 else
91 return NULL;
94 /* Allocates and returns N * M bytes of memory. */
95 static void *
96 xnmalloc (size_t n, size_t m)
98 if ((size_t) -1 / m <= n)
99 xalloc_die ();
100 return xmalloc (n * m);
103 /* Always returns a null pointer, failing allocation. */
104 static struct llx *
105 null_allocate_node (void *aux UNUSED)
107 return NULL;
110 /* Does nothing. */
111 static void
112 null_release_node (struct llx *llx UNUSED, void *aux UNUSED)
116 /* Memory manager that fails all allocations and does nothing on
117 free. */
118 static const struct llx_manager llx_null_mgr =
120 null_allocate_node,
121 null_release_node,
122 NULL,
125 /* List type and support routines. */
127 /* Test data element. */
128 struct element
130 int x; /* Primary value. */
131 int y; /* Secondary value. */
134 static int aux_data;
136 /* Prints the elements in LIST. */
137 static void UNUSED
138 print_list (struct llx_list *list)
140 struct llx *x;
142 printf ("list:");
143 for (x = llx_head (list); x != llx_null (list); x = llx_next (x))
145 const struct element *e = llx_data (x);
146 printf (" %d", e->x);
148 printf ("\n");
151 /* Prints the value returned by PREDICATE given auxiliary data
152 AUX for each element in LIST. */
153 static void UNUSED
154 print_pred (struct llx_list *list,
155 llx_predicate_func *predicate, void *aux UNUSED)
157 struct llx *x;
159 printf ("pred:");
160 for (x = llx_head (list); x != llx_null (list); x = llx_next (x))
161 printf (" %d", predicate (x, aux));
162 printf ("\n");
165 /* Prints the N numbers in VALUES. */
166 static void UNUSED
167 print_array (int values[], size_t n)
169 size_t i;
171 printf ("arry:");
172 for (i = 0; i < n; i++)
173 printf (" %d", values[i]);
174 printf ("\n");
177 /* Compares the `x' values in A and B and returns a strcmp-type
178 return value. Verifies that AUX points to aux_data. */
179 static int
180 compare_elements (const void *a_, const void *b_, void *aux)
182 const struct element *a = a_;
183 const struct element *b = b_;
185 check (aux == &aux_data);
186 return a->x < b->x ? -1 : a->x > b->x;
189 /* Compares the `x' and `y' values in A and B and returns a
190 strcmp-type return value. Verifies that AUX points to
191 aux_data. */
192 static int
193 compare_elements_x_y (const void *a_, const void *b_, void *aux)
195 const struct element *a = a_;
196 const struct element *b = b_;
198 check (aux == &aux_data);
199 if (a->x != b->x)
200 return a->x < b->x ? -1 : 1;
201 else if (a->y != b->y)
202 return a->y < b->y ? -1 : 1;
203 else
204 return 0;
207 /* Compares the `y' values in A and B and returns a strcmp-type
208 return value. Verifies that AUX points to aux_data. */
209 static int
210 compare_elements_y (const void *a_, const void *b_, void *aux)
212 const struct element *a = a_;
213 const struct element *b = b_;
215 check (aux == &aux_data);
216 return a->y < b->y ? -1 : a->y > b->y;
219 /* Returns true if the bit in *PATTERN indicated by `x in
220 *ELEMENT is set, false otherwise. */
221 static bool
222 pattern_pred (const void *element_, void *pattern_)
224 const struct element *element = element_;
225 unsigned int *pattern = pattern_;
227 return (*pattern & (1u << element->x)) != 0;
230 /* Allocates N elements in *ELEMS.
231 Adds the elements to LIST, if it is nonnull.
232 Puts pointers to the elements' list elements in *ELEMP,
233 followed by a pointer to the list null element, if ELEMP is
234 nonnull.
235 Allocates space for N values in *VALUES, if VALUES is
236 nonnull. */
237 static void
238 allocate_elements (size_t n,
239 struct llx_list *list,
240 struct element ***elems,
241 struct llx ***elemp,
242 int **values)
244 size_t i;
246 if (list != NULL)
247 llx_init (list);
249 *elems = xnmalloc (n, sizeof **elems);
250 if (elemp != NULL)
252 *elemp = xnmalloc (n + 1, sizeof *elemp);
253 (*elemp)[n] = llx_null (list);
256 for (i = 0; i < n; i++)
258 (*elems)[i] = xmalloc (sizeof ***elems);
259 if (list != NULL)
261 struct llx *llx = llx_push_tail (list, (*elems)[i], &llx_malloc_mgr);
262 if (elemp != NULL)
263 (*elemp)[i] = llx;
267 if (values != NULL)
268 *values = xnmalloc (n, sizeof *values);
271 /* Copies the N values of `x' from LIST into VALUES[]. */
272 static void
273 extract_values (struct llx_list *list, int values[], size_t n)
275 struct llx *x;
277 check (llx_count (list) == n);
278 for (x = llx_head (list); x != llx_null (list); x = llx_next (x))
280 struct element *e = llx_data (x);
281 *values++ = e->x;
285 /* As allocate_elements, but sets ascending values, starting
286 from 0, in `x' values in *ELEMS and in *VALUES (if
287 nonnull). */
288 static void
289 allocate_ascending (size_t n,
290 struct llx_list *list,
291 struct element ***elems,
292 struct llx ***elemp,
293 int **values)
295 size_t i;
297 allocate_elements (n, list, elems, elemp, values);
299 for (i = 0; i < n; i++)
300 (*elems)[i]->x = i;
301 if (values != NULL)
302 extract_values (list, *values, n);
305 /* As allocate_elements, but sets binary values extracted from
306 successive bits in PATTERN in `x' values in *ELEMS and in
307 *VALUES (if nonnull). */
308 static void
309 allocate_pattern (size_t n,
310 int pattern,
311 struct llx_list *list,
312 struct element ***elems,
313 struct llx ***elemp,
314 int **values)
316 size_t i;
318 allocate_elements (n, list, elems, elemp, values);
320 for (i = 0; i < n; i++)
321 (*elems)[i]->x = (pattern & (1 << i)) != 0;
322 if (values != NULL)
323 extract_values (list, *values, n);
326 /* Randomly shuffles the N elements in ARRAY, each of which is
327 SIZE bytes in size. */
328 static void
329 random_shuffle (void *array_, size_t n, size_t size)
331 char *array = array_;
332 char *tmp = xmalloc (size);
333 size_t i;
335 for (i = 0; i < n; i++)
337 size_t j = rand () % (n - i) + i;
338 if (i != j)
340 memcpy (tmp, array + j * size, size);
341 memcpy (array + j * size, array + i * size, size);
342 memcpy (array + i * size, tmp, size);
346 free (tmp);
349 /* As allocate_ascending, but orders the values randomly. */
350 static void
351 allocate_random (size_t n,
352 struct llx_list *list,
353 struct element ***elems,
354 struct llx ***elemp,
355 int **values)
357 size_t i;
359 allocate_elements (n, list, elems, elemp, values);
361 for (i = 0; i < n; i++)
362 (*elems)[i]->x = i;
363 random_shuffle (*elems, n, sizeof **elems);
364 if (values != NULL)
365 extract_values (list, *values, n);
368 /* Frees LIST, the N elements of ELEMS, ELEMP, and VALUES. */
369 static void
370 free_elements (size_t n,
371 struct llx_list *list,
372 struct element **elems,
373 struct llx **elemp,
374 int *values)
376 size_t i;
378 if (list != NULL)
379 llx_destroy (list, NULL, NULL, &llx_malloc_mgr);
380 for (i = 0; i < n; i++)
381 free (elems[i]);
382 free (elems);
383 free (elemp);
384 free (values);
387 /* Compares A and B and returns a strcmp-type return value. */
388 static int
389 compare_ints (const void *a_, const void *b_, void *aux UNUSED)
391 const int *a = a_;
392 const int *b = b_;
394 return *a < *b ? -1 : *a > *b;
397 /* Compares A and B and returns a strcmp-type return value. */
398 static int
399 compare_ints_noaux (const void *a_, const void *b_)
401 const int *a = a_;
402 const int *b = b_;
404 return *a < *b ? -1 : *a > *b;
407 /* Checks that LIST contains the N values in ELEMENTS. */
408 static void
409 check_list_contents (struct llx_list *list, int elements[], size_t n)
411 struct llx *llx;
412 size_t i;
414 check ((n == 0) == llx_is_empty (list));
416 /* Iterate in forward order. */
417 for (llx = llx_head (list), i = 0; i < n; llx = llx_next (llx), i++)
419 struct element *e = llx_data (llx);
420 check (elements[i] == e->x);
421 check (llx != llx_null (list));
423 check (llx == llx_null (list));
425 /* Iterate in reverse order. */
426 for (llx = llx_tail (list), i = 0; i < n; llx = llx_prev (llx), i++)
428 struct element *e = llx_data (llx);
429 check (elements[n - i - 1] == e->x);
430 check (llx != llx_null (list));
432 check (llx == llx_null (list));
434 check (llx_count (list) == n);
437 /* Lexicographicallxy compares ARRAY1, which contains COUNT1
438 elements of SIZE bytes each, to ARRAY2, which contains COUNT2
439 elements of SIZE bytes, according to COMPARE. Returns a
440 strcmp-type result. AUX is passed to COMPARE as auxiliary
441 data. */
442 static int
443 lexicographical_compare_3way (const void *array1, size_t count1,
444 const void *array2, size_t count2,
445 size_t size,
446 int (*compare) (const void *, const void *,
447 void *aux),
448 void *aux)
450 const char *first1 = array1;
451 const char *first2 = array2;
452 size_t min_count = count1 < count2 ? count1 : count2;
454 while (min_count > 0)
456 int cmp = compare (first1, first2, aux);
457 if (cmp != 0)
458 return cmp;
460 first1 += size;
461 first2 += size;
462 min_count--;
465 return count1 < count2 ? -1 : count1 > count2;
468 /* Tests. */
470 /* Tests list push and pop operations. */
471 static void
472 test_push_pop (void)
474 const int max_elems = 1024;
476 struct llx_list list;
477 struct element **elems;
478 int *values;
480 int i;
482 allocate_elements (max_elems, NULL, &elems, NULL, &values);
484 /* Push on tail. */
485 llx_init (&list);
486 check_list_contents (&list, NULL, 0);
487 for (i = 0; i < max_elems; i++)
489 values[i] = elems[i]->x = i;
490 llx_push_tail (&list, elems[i], &llx_malloc_mgr);
491 check_list_contents (&list, values, i + 1);
494 /* Remove from tail. */
495 for (i = 0; i < max_elems; i++)
497 struct element *e = llx_pop_tail (&list, &llx_malloc_mgr);
498 check (e->x == max_elems - i - 1);
499 check_list_contents (&list, values, max_elems - i - 1);
502 /* Push at start. */
503 check_list_contents (&list, NULL, 0);
504 for (i = 0; i < max_elems; i++)
506 values[max_elems - i - 1] = elems[i]->x = max_elems - i - 1;
507 llx_push_head (&list, elems[i], &llx_malloc_mgr);
508 check_list_contents (&list, &values[max_elems - i - 1], i + 1);
511 /* Remove from start. */
512 for (i = 0; i < max_elems; i++)
514 struct element *e = llx_pop_head (&list, &llx_malloc_mgr);
515 check (e->x == (int) i);
516 check_list_contents (&list, &values[i + 1], max_elems - i - 1);
519 free_elements (max_elems, &list, elems, NULL, values);
522 /* Tests insertion and removal at arbitrary positions. */
523 static void
524 test_insert_remove (void)
526 const int max_elems = 16;
527 int n;
529 for (n = 0; n < max_elems; n++)
531 struct element **elems;
532 struct llx **elemp;
533 int *values = xnmalloc (n + 1, sizeof *values);
535 struct llx_list list;
536 struct element extra;
537 struct llx *extra_llx;
538 int pos;
540 allocate_ascending (n, &list, &elems, &elemp, NULL);
541 extra.x = -1;
542 for (pos = 0; pos <= n; pos++)
544 int i, j;
546 extra_llx = llx_insert (elemp[pos], &extra, &llx_malloc_mgr);
547 check (extra_llx != NULL);
549 j = 0;
550 for (i = 0; i < pos; i++)
551 values[j++] = i;
552 values[j++] = -1;
553 for (; i < n; i++)
554 values[j++] = i;
555 check_list_contents (&list, values, n + 1);
557 llx_remove (extra_llx, &llx_malloc_mgr);
559 check_list_contents (&list, values, n);
561 free_elements (n, &list, elems, elemp, values);
565 /* Tests swapping individual elements. */
566 static void
567 test_swap (void)
569 const int max_elems = 8;
570 int n;
572 for (n = 0; n <= max_elems; n++)
574 struct llx_list list;
575 struct element **elems;
576 struct llx **elemp;
577 int *values;
579 int i, j, k;
581 allocate_ascending (n, &list, &elems, &elemp, &values);
582 check_list_contents (&list, values, n);
584 for (i = 0; i < n; i++)
585 for (j = 0; j < n; j++)
586 for (k = 0; k < 2; k++)
588 int t;
590 llx_swap (elemp[i], elemp[j]);
591 t = values[i];
592 values[i] = values[j];
593 values[j] = t;
594 check_list_contents (&list, values, n);
597 free_elements (n, &list, elems, elemp, values);
601 /* Tests swapping ranges of list elements. */
602 static void
603 test_swap_range (void)
605 const int max_elems = 8;
606 int n, a0, a1, b0, b1, r;
608 for (n = 0; n <= max_elems; n++)
609 for (a0 = 0; a0 <= n; a0++)
610 for (a1 = a0; a1 <= n; a1++)
611 for (b0 = a1; b0 <= n; b0++)
612 for (b1 = b0; b1 <= n; b1++)
613 for (r = 0; r < 2; r++)
615 struct llx_list list;
616 struct element **elems;
617 struct llx **elemp;
618 int *values;
620 int i, j;
622 allocate_ascending (n, &list, &elems, &elemp, &values);
623 check_list_contents (&list, values, n);
625 j = 0;
626 for (i = 0; i < a0; i++)
627 values[j++] = i;
628 for (i = b0; i < b1; i++)
629 values[j++] = i;
630 for (i = a1; i < b0; i++)
631 values[j++] = i;
632 for (i = a0; i < a1; i++)
633 values[j++] = i;
634 for (i = b1; i < n; i++)
635 values[j++] = i;
636 check (j == n);
638 if (r == 0)
639 llx_swap_range (elemp[a0], elemp[a1], elemp[b0], elemp[b1]);
640 else
641 llx_swap_range (elemp[b0], elemp[b1], elemp[a0], elemp[a1]);
642 check_list_contents (&list, values, n);
644 free_elements (n, &list, elems, elemp, values);
648 /* Tests removing ranges of list elements. */
649 static void
650 test_remove_range (void)
652 const int max_elems = 8;
654 int n, r0, r1;
656 for (n = 0; n <= max_elems; n++)
657 for (r0 = 0; r0 <= n; r0++)
658 for (r1 = r0; r1 <= n; r1++)
660 struct llx_list list;
661 struct element **elems;
662 struct llx **elemp;
663 int *values;
665 int i, j;
667 allocate_ascending (n, &list, &elems, &elemp, &values);
668 check_list_contents (&list, values, n);
670 j = 0;
671 for (i = 0; i < r0; i++)
672 values[j++] = i;
673 for (i = r1; i < n; i++)
674 values[j++] = i;
676 llx_remove_range (elemp[r0], elemp[r1], &llx_malloc_mgr);
677 check_list_contents (&list, values, j);
679 free_elements (n, &list, elems, elemp, values);
683 /* Tests llx_remove_equal. */
684 static void
685 test_remove_equal (void)
687 const int max_elems = 8;
689 int n, r0, r1, eq_pat;
691 for (n = 0; n <= max_elems; n++)
692 for (r0 = 0; r0 <= n; r0++)
693 for (r1 = r0; r1 <= n; r1++)
694 for (eq_pat = 0; eq_pat <= 1 << n; eq_pat++)
696 struct llx_list list;
697 struct element **elems;
698 struct llx **elemp;
699 int *values;
701 struct element to_remove;
702 int remaining;
703 int i;
705 allocate_elements (n, &list, &elems, &elemp, &values);
707 remaining = 0;
708 for (i = 0; i < n; i++)
710 int x = eq_pat & (1 << i) ? -1 : i;
711 bool delete = x == -1 && r0 <= i && i < r1;
712 elems[i]->x = x;
713 if (!delete)
714 values[remaining++] = x;
717 to_remove.x = -1;
718 check ((int) llx_remove_equal (elemp[r0], elemp[r1], &to_remove,
719 compare_elements, &aux_data,
720 &llx_malloc_mgr)
721 == n - remaining);
722 check_list_contents (&list, values, remaining);
724 free_elements (n, &list, elems, elemp, values);
728 /* Tests llx_remove_if. */
729 static void
730 test_remove_if (void)
732 const int max_elems = 8;
734 int n, r0, r1, pattern;
736 for (n = 0; n <= max_elems; n++)
737 for (r0 = 0; r0 <= n; r0++)
738 for (r1 = r0; r1 <= n; r1++)
739 for (pattern = 0; pattern <= 1 << n; pattern++)
741 struct llx_list list;
742 struct element **elems;
743 struct llx **elemp;
744 int *values;
746 int remaining;
747 int i;
749 allocate_ascending (n, &list, &elems, &elemp, &values);
751 remaining = 0;
752 for (i = 0; i < n; i++)
754 bool delete = (pattern & (1 << i)) && r0 <= i && i < r1;
755 if (!delete)
756 values[remaining++] = i;
759 check ((int) llx_remove_if (elemp[r0], elemp[r1],
760 pattern_pred, &pattern,
761 &llx_malloc_mgr)
762 == n - remaining);
763 check_list_contents (&list, values, remaining);
765 free_elements (n, &list, elems, elemp, values);
769 /* Tests, via HELPER, a function that looks at list elements
770 equal to some specified element. */
771 static void
772 test_examine_equal_range (void (*helper) (int r0, int r1, int eq_pat,
773 const void *to_find,
774 struct llx **elemp))
776 const int max_elems = 8;
778 int n, r0, r1, eq_pat;
780 for (n = 0; n <= max_elems; n++)
781 for (eq_pat = 0; eq_pat <= 1 << n; eq_pat++)
783 struct llx_list list;
784 struct element **elems;
785 struct llx **elemp;
786 int *values;
788 struct element to_find;
790 int i;
792 allocate_ascending (n, &list, &elems, &elemp, &values);
794 for (i = 0; i < n; i++)
795 if (eq_pat & (1 << i))
796 values[i] = elems[i]->x = -1;
798 to_find.x = -1;
799 for (r0 = 0; r0 <= n; r0++)
800 for (r1 = r0; r1 <= n; r1++)
801 helper (r0, r1, eq_pat, &to_find, elemp);
803 check_list_contents (&list, values, n);
805 free_elements (n, &list, elems, elemp, values);
809 /* Tests, via HELPER, a function that looks at list elements for
810 which a given predicate returns true. */
811 static void
812 test_examine_if_range (void (*helper) (int r0, int r1, int eq_pat,
813 struct llx **elemp))
815 const int max_elems = 8;
817 int n, r0, r1, eq_pat;
819 for (n = 0; n <= max_elems; n++)
820 for (eq_pat = 0; eq_pat <= 1 << n; eq_pat++)
822 struct llx_list list;
823 struct element **elems;
824 struct llx **elemp;
825 int *values;
827 allocate_ascending (n, &list, &elems, &elemp, &values);
829 for (r0 = 0; r0 <= n; r0++)
830 for (r1 = r0; r1 <= n; r1++)
831 helper (r0, r1, eq_pat, elemp);
833 check_list_contents (&list, values, n);
835 free_elements (n, &list, elems, elemp, values);
839 /* Helper function for testing llx_find_equal. */
840 static void
841 test_find_equal_helper (int r0, int r1, int eq_pat,
842 const void *to_find, struct llx **elemp)
844 struct llx *match;
845 int i;
847 match = llx_find_equal (elemp[r0], elemp[r1], to_find,
848 compare_elements, &aux_data);
849 for (i = r0; i < r1; i++)
850 if (eq_pat & (1 << i))
851 break;
853 check (match == elemp[i]);
856 /* Tests llx_find_equal. */
857 static void
858 test_find_equal (void)
860 test_examine_equal_range (test_find_equal_helper);
863 /* Tests llx_find(). */
864 static void
865 test_find (void)
867 const int max_elems = 8;
869 int n;
871 for (n = 0; n <= max_elems; n++)
873 struct llx_list list;
874 struct element **elems;
875 struct llx **elemp;
876 int *values;
878 int i;
880 allocate_ascending (n, &list, &elems, &elemp, &values);
882 for (i = 0; i < n; i++)
883 check (llx_find (llx_head (&list), llx_null (&list), elems[i])
884 == elemp[i]);
885 check (llx_find (llx_head (&list), llx_null (&list), NULL) == NULL);
887 free_elements (n, &list, elems, elemp, values);
891 /* Helper function for testing llx_find_if. */
892 static void
893 test_find_if_helper (int r0, int r1, int eq_pat, struct llx **elemp)
895 struct llx *match = llx_find_if (elemp[r0], elemp[r1],
896 pattern_pred, &eq_pat);
897 int i;
899 for (i = r0; i < r1; i++)
900 if (eq_pat & (1 << i))
901 break;
903 check (match == elemp[i]);
906 /* Tests llx_find_if. */
907 static void
908 test_find_if (void)
910 test_examine_if_range (test_find_if_helper);
913 /* Tests llx_find_adjacent_equal. */
914 static void
915 test_find_adjacent_equal (void)
917 const int max_elems = 8;
919 int n, eq_pat;
921 for (n = 0; n <= max_elems; n++)
922 for (eq_pat = 0; eq_pat <= 1 << n; eq_pat++)
924 struct llx_list list;
925 struct element **elems;
926 struct llx **elemp;
927 int *values;
928 int match;
930 int i;
932 allocate_ascending (n, &list, &elems, &elemp, &values);
934 match = -1;
935 for (i = 0; i < n - 1; i++)
937 elems[i]->y = i;
938 if (eq_pat & (1 << i))
940 values[i] = elems[i]->x = match;
941 values[i + 1] = elems[i + 1]->x = match;
943 else
944 match--;
947 for (i = 0; i <= n; i++)
949 struct llx *llx1 = llx_find_adjacent_equal (elemp[i], llx_null (&list),
950 compare_elements,
951 &aux_data);
952 struct llx *llx2;
953 int j;
955 llx2 = llx_null (&list);
956 for (j = i; j < n - 1; j++)
957 if (eq_pat & (1 << j))
959 llx2 = elemp[j];
960 break;
962 check (llx1 == llx2);
964 check_list_contents (&list, values, n);
966 free_elements (n, &list, elems, elemp, values);
970 /* Helper function for testing llx_count_range. */
971 static void
972 test_count_range_helper (int r0, int r1, int eq_pat UNUSED, struct llx **elemp)
974 check ((int) llx_count_range (elemp[r0], elemp[r1]) == r1 - r0);
977 /* Tests llx_count_range. */
978 static void
979 test_count_range (void)
981 test_examine_if_range (test_count_range_helper);
984 /* Helper function for testing llx_count_equal. */
985 static void
986 test_count_equal_helper (int r0, int r1, int eq_pat,
987 const void *to_find, struct llx **elemp)
989 int count1, count2;
990 int i;
992 count1 = llx_count_equal (elemp[r0], elemp[r1], to_find,
993 compare_elements, &aux_data);
994 count2 = 0;
995 for (i = r0; i < r1; i++)
996 if (eq_pat & (1 << i))
997 count2++;
999 check (count1 == count2);
1002 /* Tests llx_count_equal. */
1003 static void
1004 test_count_equal (void)
1006 test_examine_equal_range (test_count_equal_helper);
1009 /* Helper function for testing llx_count_if. */
1010 static void
1011 test_count_if_helper (int r0, int r1, int eq_pat, struct llx **elemp)
1013 int count1;
1014 int count2;
1015 int i;
1017 count1 = llx_count_if (elemp[r0], elemp[r1], pattern_pred, &eq_pat);
1019 count2 = 0;
1020 for (i = r0; i < r1; i++)
1021 if (eq_pat & (1 << i))
1022 count2++;
1024 check (count1 == count2);
1027 /* Tests llx_count_if. */
1028 static void
1029 test_count_if (void)
1031 test_examine_if_range (test_count_if_helper);
1034 /* Returns N!. */
1035 static unsigned int
1036 factorial (unsigned int n)
1038 unsigned int value = 1;
1039 while (n > 1)
1040 value *= n--;
1041 return value;
1044 /* Returns the number of permutations of the N values in
1045 VALUES. If VALUES contains duplicates, they must be
1046 adjacent. */
1047 static unsigned int
1048 expected_perms (int *values, size_t n)
1050 size_t i, j;
1051 unsigned int n_perms;
1053 n_perms = factorial (n);
1054 for (i = 0; i < n; i = j)
1056 for (j = i + 1; j < n; j++)
1057 if (values[i] != values[j])
1058 break;
1059 n_perms /= factorial (j - i);
1061 return n_perms;
1064 /* Tests llx_min and llx_max. */
1065 static void
1066 test_min_max (void)
1068 const int max_elems = 6;
1069 int n;
1071 for (n = 0; n <= max_elems; n++)
1073 struct llx_list list;
1074 struct element **elems;
1075 struct llx **elemp;
1076 int *values;
1077 int *new_values = xnmalloc (n, sizeof *values);
1079 size_t n_perms;
1081 allocate_ascending (n, &list, &elems, &elemp, &values);
1083 n_perms = 1;
1084 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1085 compare_elements, &aux_data))
1087 int r0, r1;
1088 struct llx *x;
1089 int i;
1091 for (i = 0, x = llx_head (&list); x != llx_null (&list);
1092 x = llx_next (x), i++)
1094 struct element *e = llx_data (x);
1095 elemp[i] = x;
1096 new_values[i] = e->x;
1098 for (r0 = 0; r0 <= n; r0++)
1099 for (r1 = r0; r1 <= n; r1++)
1101 struct llx *min = llx_min (elemp[r0], elemp[r1],
1102 compare_elements, &aux_data);
1103 struct llx *max = llx_max (elemp[r0], elemp[r1],
1104 compare_elements, &aux_data);
1105 if (r0 == r1)
1107 check (min == elemp[r1]);
1108 check (max == elemp[r1]);
1110 else
1112 struct element *min_elem = llx_data (min);
1113 struct element *max_elem = llx_data (max);
1114 int min_int, max_int;
1115 int i;
1117 min_int = max_int = new_values[r0];
1118 for (i = r0; i < r1; i++)
1120 int value = new_values[i];
1121 if (value < min_int)
1122 min_int = value;
1123 if (value > max_int)
1124 max_int = value;
1126 check (min != elemp[r1] && min_elem->x == min_int);
1127 check (max != elemp[r1] && max_elem->x == max_int);
1130 n_perms++;
1132 check (n_perms == factorial (n));
1133 check_list_contents (&list, values, n);
1135 free_elements (n, &list, elems, elemp, values);
1136 free (new_values);
1140 /* Tests llx_lexicographical_compare_3way. */
1141 static void
1142 test_lexicographical_compare_3way (void)
1144 const int max_elems = 4;
1146 int n_a, pat_a, n_b, pat_b;
1148 for (n_a = 0; n_a <= max_elems; n_a++)
1149 for (pat_a = 0; pat_a <= 1 << n_a; pat_a++)
1150 for (n_b = 0; n_b <= max_elems; n_b++)
1151 for (pat_b = 0; pat_b <= 1 << n_b; pat_b++)
1153 struct llx_list list_a, list_b;
1154 struct element **elems_a, **elems_b;
1155 struct llx **elemp_a, **elemp_b;
1156 int *values_a, *values_b;
1158 int a0, a1, b0, b1;
1160 allocate_pattern (n_a, pat_a,
1161 &list_a, &elems_a, &elemp_a, &values_a);
1162 allocate_pattern (n_b, pat_b,
1163 &list_b, &elems_b, &elemp_b, &values_b);
1165 for (a0 = 0; a0 <= n_a; a0++)
1166 for (a1 = a0; a1 <= n_a; a1++)
1167 for (b0 = 0; b0 <= n_b; b0++)
1168 for (b1 = b0; b1 <= n_b; b1++)
1170 int a_ordering = lexicographical_compare_3way (
1171 values_a + a0, a1 - a0,
1172 values_b + b0, b1 - b0,
1173 sizeof *values_a,
1174 compare_ints, NULL);
1176 int b_ordering = llx_lexicographical_compare_3way (
1177 elemp_a[a0], elemp_a[a1],
1178 elemp_b[b0], elemp_b[b1],
1179 compare_elements, &aux_data);
1181 check (a_ordering == b_ordering);
1184 free_elements (n_a, &list_a, elems_a, elemp_a, values_a);
1185 free_elements (n_b, &list_b, elems_b, elemp_b, values_b);
1189 /* Appends the `x' value in element E to the array pointed to by
1190 NEXT_OUTPUT, and advances NEXT_OUTPUT to the next position. */
1191 static void
1192 apply_func (void *e_, void *next_output_)
1194 struct element *e = e_;
1195 int **next_output = next_output_;
1197 *(*next_output)++ = e->x;
1200 /* Tests llx_apply. */
1201 static void
1202 test_apply (void)
1204 const int max_elems = 8;
1206 int n, r0, r1;
1208 for (n = 0; n <= max_elems; n++)
1209 for (r0 = 0; r0 <= n; r0++)
1210 for (r1 = r0; r1 <= n; r1++)
1212 struct llx_list list;
1213 struct element **elems;
1214 struct llx **elemp;
1215 int *values;
1217 int *output;
1218 int *next_output;
1219 int j;
1221 allocate_ascending (n, &list, &elems, &elemp, &values);
1222 check_list_contents (&list, values, n);
1224 output = next_output = xnmalloc (n, sizeof *output);
1225 llx_apply (elemp[r0], elemp[r1], apply_func, &next_output);
1226 check_list_contents (&list, values, n);
1227 llx_destroy (&list, NULL, NULL, &llx_malloc_mgr);
1229 check (r1 - r0 == next_output - output);
1230 for (j = 0; j < r1 - r0; j++)
1231 check (output[j] == r0 + j);
1233 free_elements (n, NULL, elems, elemp, values);
1234 free (output);
1238 /* Tests llx_destroy. */
1239 static void
1240 test_destroy (void)
1242 const int max_elems = 8;
1244 int n;
1246 for (n = 0; n <= max_elems; n++)
1248 struct llx_list list;
1249 struct element **elems;
1250 struct llx **elemp;
1251 int *values;
1253 int *output;
1254 int *next_output;
1255 int j;
1257 allocate_ascending (n, &list, &elems, &elemp, &values);
1258 check_list_contents (&list, values, n);
1260 output = next_output = xnmalloc (n, sizeof *output);
1261 llx_destroy (&list, apply_func, &next_output, &llx_malloc_mgr);
1263 check (n == next_output - output);
1264 for (j = 0; j < n; j++)
1265 check (output[j] == j);
1267 free_elements (n, NULL, elems, elemp, values);
1268 free (output);
1272 /* Tests llx_reverse. */
1273 static void
1274 test_reverse (void)
1276 const int max_elems = 8;
1278 int n, r0, r1;
1280 for (n = 0; n <= max_elems; n++)
1281 for (r0 = 0; r0 <= n; r0++)
1282 for (r1 = r0; r1 <= n; r1++)
1284 struct llx_list list;
1285 struct element **elems;
1286 struct llx **elemp;
1287 int *values;
1289 int i, j;
1291 allocate_ascending (n, &list, &elems, &elemp, &values);
1292 check_list_contents (&list, values, n);
1294 j = 0;
1295 for (i = 0; i < r0; i++)
1296 values[j++] = i;
1297 for (i = r1 - 1; i >= r0; i--)
1298 values[j++] = i;
1299 for (i = r1; i < n; i++)
1300 values[j++] = i;
1302 llx_reverse (elemp[r0], elemp[r1]);
1303 check_list_contents (&list, values, n);
1305 free_elements (n, &list, elems, elemp, values);
1309 /* Tests llx_next_permutation and llx_prev_permutation when the
1310 permuted values have no duplicates. */
1311 static void
1312 test_permutations_no_dups (void)
1314 const int max_elems = 8;
1315 int n;
1317 for (n = 0; n <= max_elems; n++)
1319 struct llx_list list;
1320 struct element **elems;
1321 int *values;
1322 int *old_values = xnmalloc (n, sizeof *values);
1323 int *new_values = xnmalloc (n, sizeof *values);
1325 size_t n_perms;
1327 allocate_ascending (n, &list, &elems, NULL, &values);
1329 n_perms = 1;
1330 extract_values (&list, old_values, n);
1331 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1332 compare_elements, &aux_data))
1334 extract_values (&list, new_values, n);
1335 check (lexicographical_compare_3way (new_values, n,
1336 old_values, n,
1337 sizeof *new_values,
1338 compare_ints, NULL) > 0);
1339 memcpy (old_values, new_values, (n) * sizeof *old_values);
1340 n_perms++;
1342 check (n_perms == factorial (n));
1343 check_list_contents (&list, values, n);
1345 n_perms = 1;
1346 llx_reverse (llx_head (&list), llx_null (&list));
1347 extract_values (&list, old_values, n);
1348 while (llx_prev_permutation (llx_head (&list), llx_null (&list),
1349 compare_elements, &aux_data))
1351 extract_values (&list, new_values, n);
1352 check (lexicographical_compare_3way (new_values, n,
1353 old_values, n,
1354 sizeof *new_values,
1355 compare_ints, NULL) < 0);
1356 memcpy (old_values, new_values, (n) * sizeof *old_values);
1357 n_perms++;
1359 check (n_perms == factorial (n));
1360 llx_reverse (llx_head (&list), llx_null (&list));
1361 check_list_contents (&list, values, n);
1363 free_elements (n, &list, elems, NULL, values);
1364 free (old_values);
1365 free (new_values);
1369 /* Tests llx_next_permutation and llx_prev_permutation when the
1370 permuted values contain duplicates. */
1371 static void
1372 test_permutations_with_dups (void)
1374 const int max_elems = 8;
1375 const int max_dup = 3;
1376 const int repetitions = 1024;
1378 for (int repeat = 0; repeat < repetitions; repeat++)
1379 for (int n_elems = 0; n_elems < max_elems; n_elems++)
1381 struct llx_list list;
1382 struct element **elems;
1383 struct llx **elemp;
1384 int *values;
1385 int *old_values = xnmalloc (max_elems, sizeof *values);
1386 int *new_values = xnmalloc (max_elems, sizeof *values);
1388 unsigned int n_permutations;
1389 int left = n_elems;
1390 int value = 0;
1392 allocate_elements (n_elems, &list, &elems, &elemp, &values);
1394 value = 0;
1395 while (left > 0)
1397 int max = left < max_dup ? left : max_dup;
1398 int n = rand () % max + 1;
1399 while (n-- > 0)
1401 int idx = n_elems - left--;
1402 values[idx] = elems[idx]->x = value;
1404 value++;
1407 n_permutations = 1;
1408 extract_values (&list, old_values, n_elems);
1409 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1410 compare_elements, &aux_data))
1412 extract_values (&list, new_values, n_elems);
1413 check (lexicographical_compare_3way (new_values, n_elems,
1414 old_values, n_elems,
1415 sizeof *new_values,
1416 compare_ints, NULL) > 0);
1417 memcpy (old_values, new_values, n_elems * sizeof *old_values);
1418 n_permutations++;
1420 check (n_permutations == expected_perms (values, n_elems));
1421 check_list_contents (&list, values, n_elems);
1423 n_permutations = 1;
1424 llx_reverse (llx_head (&list), llx_null (&list));
1425 extract_values (&list, old_values, n_elems);
1426 while (llx_prev_permutation (llx_head (&list), llx_null (&list),
1427 compare_elements, &aux_data))
1429 extract_values (&list, new_values, n_elems);
1430 check (lexicographical_compare_3way (new_values, n_elems,
1431 old_values, n_elems,
1432 sizeof *new_values,
1433 compare_ints, NULL) < 0);
1434 n_permutations++;
1436 llx_reverse (llx_head (&list), llx_null (&list));
1437 check (n_permutations == expected_perms (values, n_elems));
1438 check_list_contents (&list, values, n_elems);
1440 free_elements (n_elems, &list, elems, elemp, values);
1441 free (old_values);
1442 free (new_values);
1446 /* Tests llx_merge when no equal values are to be merged. */
1447 static void
1448 test_merge_no_dups (void)
1450 const int max_elems = 8;
1451 const int max_fillxer = 3;
1453 int n_merges, pattern, pfx, gap, sfx, order;
1455 for (n_merges = 0; n_merges < max_elems; n_merges++)
1456 for (pattern = 0; pattern <= (1 << n_merges); pattern++)
1457 for (pfx = 0; pfx < max_fillxer; pfx++)
1458 for (gap = 0; gap < max_fillxer; gap++)
1459 for (sfx = 0; sfx < max_fillxer; sfx++)
1460 for (order = 0; order < 2; order++)
1462 struct llx_list list;
1463 struct element **elems;
1464 struct llx **elemp;
1465 int *values;
1467 int n_lists = pfx + n_merges + gap + sfx;
1468 int a0, a1, b0, b1;
1469 int i, j;
1471 allocate_elements (n_lists, &list,
1472 &elems, &elemp, &values);
1474 j = 0;
1475 for (i = 0; i < pfx; i++)
1476 elems[j++]->x = 100 + i;
1477 a0 = j;
1478 for (i = 0; i < n_merges; i++)
1479 if (pattern & (1u << i))
1480 elems[j++]->x = i;
1481 a1 = j;
1482 for (i = 0; i < gap; i++)
1483 elems[j++]->x = 200 + i;
1484 b0 = j;
1485 for (i = 0; i < n_merges; i++)
1486 if (!(pattern & (1u << i)))
1487 elems[j++]->x = i;
1488 b1 = j;
1489 for (i = 0; i < sfx; i++)
1490 elems[j++]->x = 300 + i;
1491 check (n_lists == j);
1493 j = 0;
1494 for (i = 0; i < pfx; i++)
1495 values[j++] = 100 + i;
1496 if (order == 0)
1497 for (i = 0; i < n_merges; i++)
1498 values[j++] = i;
1499 for (i = 0; i < gap; i++)
1500 values[j++] = 200 + i;
1501 if (order == 1)
1502 for (i = 0; i < n_merges; i++)
1503 values[j++] = i;
1504 for (i = 0; i < sfx; i++)
1505 values[j++] = 300 + i;
1506 check (n_lists == j);
1508 if (order == 0)
1509 llx_merge (elemp[a0], elemp[a1], elemp[b0], elemp[b1],
1510 compare_elements, &aux_data);
1511 else
1512 llx_merge (elemp[b0], elemp[b1], elemp[a0], elemp[a1],
1513 compare_elements, &aux_data);
1515 check_list_contents (&list, values, n_lists);
1517 free_elements (n_lists, &list, elems, elemp, values);
1521 /* Tests llx_merge when equal values are to be merged. */
1522 static void
1523 test_merge_with_dups (void)
1525 const int max_elems = 8;
1527 int n, merge_pat, inc_pat, order;
1529 for (n = 0; n <= max_elems; n++)
1530 for (merge_pat = 0; merge_pat <= (1 << n); merge_pat++)
1531 for (inc_pat = 0; inc_pat <= (1 << n); inc_pat++)
1532 for (order = 0; order < 2; order++)
1534 struct llx_list list;
1535 struct element **elems;
1536 struct llx **elemp;
1537 int *values;
1539 int mid;
1540 int i, j, k;
1542 allocate_elements (n, &list, &elems, &elemp, &values);
1544 j = 0;
1545 for (i = k = 0; i < n; i++)
1547 if (merge_pat & (1u << i))
1548 elems[j++]->x = k;
1549 if (inc_pat & (1u << i))
1550 k++;
1552 mid = j;
1553 for (i = k = 0; i < n; i++)
1555 if (!(merge_pat & (1u << i)))
1556 elems[j++]->x = k;
1557 if (inc_pat & (1u << i))
1558 k++;
1560 check (n == j);
1562 if (order == 0)
1564 for (i = 0; i < n; i++)
1565 elems[i]->y = i;
1567 else
1569 for (i = 0; i < mid; i++)
1570 elems[i]->y = 100 + i;
1571 for (i = mid; i < n; i++)
1572 elems[i]->y = i;
1575 j = 0;
1576 for (i = k = 0; i < n; i++)
1578 values[j++] = k;
1579 if (inc_pat & (1u << i))
1580 k++;
1582 check (n == j);
1584 if (order == 0)
1585 llx_merge (elemp[0], elemp[mid], elemp[mid], elemp[n],
1586 compare_elements, &aux_data);
1587 else
1588 llx_merge (elemp[mid], elemp[n], elemp[0], elemp[mid],
1589 compare_elements, &aux_data);
1591 check_list_contents (&list, values, n);
1592 check (llx_is_sorted (llx_head (&list), llx_null (&list),
1593 compare_elements_x_y, &aux_data));
1595 free_elements (n, &list, elems, elemp, values);
1599 /* Tests llx_sort on all permutations up to a maximum number of
1600 elements. */
1601 static void
1602 test_sort_exhaustive (void)
1604 const int max_elems = 8;
1605 int n;
1607 for (n = 0; n <= max_elems; n++)
1609 struct llx_list list;
1610 struct element **elems;
1611 int *values;
1613 struct element **perm_elems;
1614 int *perm_values;
1616 size_t n_perms;
1618 allocate_ascending (n, &list, &elems, NULL, &values);
1619 allocate_elements (n, NULL, &perm_elems, NULL, &perm_values);
1621 n_perms = 1;
1622 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1623 compare_elements, &aux_data))
1625 struct llx_list perm_list;
1626 int j;
1628 extract_values (&list, perm_values, n);
1629 llx_init (&perm_list);
1630 for (j = 0; j < n; j++)
1632 perm_elems[j]->x = perm_values[j];
1633 llx_push_tail (&perm_list, perm_elems[j], &llx_malloc_mgr);
1635 llx_sort (llx_head (&perm_list), llx_null (&perm_list),
1636 compare_elements, &aux_data);
1637 check_list_contents (&perm_list, values, n);
1638 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1639 compare_elements, &aux_data));
1640 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1641 n_perms++;
1643 check (n_perms == factorial (n));
1645 free_elements (n, &list, elems, NULL, values);
1646 free_elements (n, NULL, perm_elems, NULL, perm_values);
1650 /* Tests that llx_sort is stable in the presence of equal
1651 values. */
1652 static void
1653 test_sort_stable (void)
1655 const int max_elems = 6;
1656 int n, inc_pat;
1658 for (n = 0; n <= max_elems; n++)
1659 for (inc_pat = 0; inc_pat <= 1 << n; inc_pat++)
1661 struct llx_list list;
1662 struct element **elems;
1663 int *values;
1665 struct element **perm_elems;
1666 int *perm_values;
1668 size_t n_perms;
1669 int i, j;
1671 allocate_elements (n, &list, &elems, NULL, &values);
1672 allocate_elements (n, NULL, &perm_elems, NULL, &perm_values);
1674 j = 0;
1675 for (i = 0; i < n; i++)
1677 elems[i]->x = values[i] = j;
1678 if (inc_pat & (1 << i))
1679 j++;
1680 elems[i]->y = i;
1683 n_perms = 1;
1684 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1685 compare_elements_y, &aux_data))
1687 struct llx_list perm_list;
1689 extract_values (&list, perm_values, n);
1690 llx_init (&perm_list);
1691 for (i = 0; i < n; i++)
1693 perm_elems[i]->x = perm_values[i];
1694 perm_elems[i]->y = i;
1695 llx_push_tail (&perm_list, perm_elems[i], &llx_malloc_mgr);
1697 llx_sort (llx_head (&perm_list), llx_null (&perm_list),
1698 compare_elements, &aux_data);
1699 check_list_contents (&perm_list, values, n);
1700 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1701 compare_elements_x_y, &aux_data));
1702 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1703 n_perms++;
1705 check (n_perms == factorial (n));
1707 free_elements (n, &list, elems, NULL, values);
1708 free_elements (n, NULL, perm_elems, NULL, perm_values);
1712 /* Tests that llx_sort does not disturb elements outside the
1713 range sorted. */
1714 static void
1715 test_sort_subset (void)
1717 const int max_elems = 8;
1719 int n, r0, r1, repeat;
1721 for (n = 0; n <= max_elems; n++)
1722 for (repeat = 0; repeat < 100; repeat++)
1723 for (r0 = 0; r0 <= n; r0++)
1724 for (r1 = r0; r1 <= n; r1++)
1726 struct llx_list list;
1727 struct element **elems;
1728 struct llx **elemp;
1729 int *values;
1731 allocate_random (n, &list, &elems, &elemp, &values);
1733 qsort (&values[r0], r1 - r0, sizeof *values, compare_ints_noaux);
1734 llx_sort (elemp[r0], elemp[r1], compare_elements, &aux_data);
1735 check_list_contents (&list, values, n);
1737 free_elements (n, &list, elems, elemp, values);
1741 /* Tests that llx_sort works with large lists. */
1742 static void
1743 test_sort_big (void)
1745 const int max_elems = 1024;
1747 int n;
1749 for (n = 0; n < max_elems; n++)
1751 struct llx_list list;
1752 struct element **elems;
1753 int *values;
1755 allocate_random (n, &list, &elems, NULL, &values);
1757 qsort (values, n, sizeof *values, compare_ints_noaux);
1758 llx_sort (llx_head (&list), llx_null (&list), compare_elements, &aux_data);
1759 check_list_contents (&list, values, n);
1761 free_elements (n, &list, elems, NULL, values);
1765 /* Tests llx_unique. */
1766 static void
1767 test_unique (void)
1769 const int max_elems = 10;
1771 int *ascending = xnmalloc (max_elems, sizeof *ascending);
1773 int n, inc_pat, i, j, unique_values;
1775 for (i = 0; i < max_elems; i++)
1776 ascending[i] = i;
1778 for (n = 0; n < max_elems; n++)
1779 for (inc_pat = 0; inc_pat < (1 << n); inc_pat++)
1781 struct llx_list list, dups;
1782 struct element **elems;
1783 int *values;
1785 allocate_elements (n, &list, &elems, NULL, &values);
1787 j = unique_values = 0;
1788 for (i = 0; i < n; i++)
1790 unique_values = j + 1;
1791 elems[i]->x = values[i] = j;
1792 if (inc_pat & (1 << i))
1793 j++;
1795 check_list_contents (&list, values, n);
1797 llx_init (&dups);
1798 check (llx_unique (llx_head (&list), llx_null (&list),
1799 llx_null (&dups),
1800 compare_elements, &aux_data,
1801 &llx_malloc_mgr)
1802 == (size_t) unique_values);
1803 check_list_contents (&list, ascending, unique_values);
1805 llx_splice (llx_null (&list), llx_head (&dups), llx_null (&dups));
1806 llx_sort (llx_head (&list), llx_null (&list), compare_elements, &aux_data);
1807 check_list_contents (&list, values, n);
1809 llx_destroy (&dups, NULL, NULL, &llx_malloc_mgr);
1810 free_elements (n, &list, elems, NULL, values);
1813 free (ascending);
1816 /* Tests llx_sort_unique. */
1817 static void
1818 test_sort_unique (void)
1820 const int max_elems = 7;
1821 int n, inc_pat;
1823 for (n = 0; n <= max_elems; n++)
1824 for (inc_pat = 0; inc_pat <= 1 << n; inc_pat++)
1826 struct llx_list list;
1827 struct element **elems;
1828 int *values;
1830 struct element **perm_elems;
1831 int *perm_values;
1833 int n_uniques;
1834 int *unique_values;
1836 size_t n_perms;
1837 int i, j;
1839 allocate_elements (n, &list, &elems, NULL, &values);
1840 allocate_elements (n, NULL, &perm_elems, NULL, &perm_values);
1842 j = n_uniques = 0;
1843 for (i = 0; i < n; i++)
1845 elems[i]->x = values[i] = j;
1846 n_uniques = j + 1;
1847 if (inc_pat & (1 << i))
1848 j++;
1851 unique_values = xnmalloc (n_uniques, sizeof *unique_values);
1852 for (i = 0; i < n_uniques; i++)
1853 unique_values[i] = i;
1855 n_perms = 1;
1856 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1857 compare_elements, &aux_data))
1859 struct llx_list perm_list;
1861 extract_values (&list, perm_values, n);
1862 llx_init (&perm_list);
1863 for (i = 0; i < n; i++)
1865 perm_elems[i]->x = perm_values[i];
1866 perm_elems[i]->y = i;
1867 llx_push_tail (&perm_list, perm_elems[i], &llx_malloc_mgr);
1869 llx_sort_unique (llx_head (&perm_list), llx_null (&perm_list), NULL,
1870 compare_elements, &aux_data,
1871 &llx_malloc_mgr);
1872 check_list_contents (&perm_list, unique_values, n_uniques);
1873 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1874 compare_elements_x_y, &aux_data));
1875 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1876 n_perms++;
1878 check (n_perms == expected_perms (values, n));
1880 free_elements (n, &list, elems, NULL, values);
1881 free_elements (n, NULL, perm_elems, NULL, perm_values);
1882 free (unique_values);
1886 /* Tests llx_insert_ordered. */
1887 static void
1888 test_insert_ordered (void)
1890 const int max_elems = 6;
1891 int n, inc_pat;
1893 for (n = 0; n <= max_elems; n++)
1894 for (inc_pat = 0; inc_pat <= 1 << n; inc_pat++)
1896 struct llx_list list;
1897 struct element **elems;
1898 int *values;
1900 struct element **perm_elems;
1901 int *perm_values;
1903 size_t n_perms;
1904 int i, j;
1906 allocate_elements (n, &list, &elems, NULL, &values);
1907 allocate_elements (n, NULL, &perm_elems, NULL, &perm_values);
1909 j = 0;
1910 for (i = 0; i < n; i++)
1912 elems[i]->x = values[i] = j;
1913 if (inc_pat & (1 << i))
1914 j++;
1915 elems[i]->y = i;
1918 n_perms = 1;
1919 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1920 compare_elements_y, &aux_data))
1922 struct llx_list perm_list;
1924 extract_values (&list, perm_values, n);
1925 llx_init (&perm_list);
1926 for (i = 0; i < n; i++)
1928 perm_elems[i]->x = perm_values[i];
1929 perm_elems[i]->y = i;
1930 llx_insert_ordered (llx_head (&perm_list),
1931 llx_null (&perm_list),
1932 perm_elems[i],
1933 compare_elements, &aux_data,
1934 &llx_malloc_mgr);
1936 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1937 compare_elements_x_y, &aux_data));
1938 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1939 n_perms++;
1941 check (n_perms == factorial (n));
1943 free_elements (n, &list, elems, NULL, values);
1944 free_elements (n, NULL, perm_elems, NULL, perm_values);
1948 /* Tests llx_partition. */
1949 static void
1950 test_partition (void)
1952 const int max_elems = 10;
1954 int n;
1955 unsigned int pbase;
1956 int r0, r1;
1958 for (n = 0; n < max_elems; n++)
1959 for (r0 = 0; r0 <= n; r0++)
1960 for (r1 = r0; r1 <= n; r1++)
1961 for (pbase = 0; pbase <= (1u << (r1 - r0)); pbase++)
1963 struct llx_list list;
1964 struct element **elems;
1965 struct llx **elemp;
1966 int *values;
1968 unsigned int pattern = pbase << r0;
1969 int i, j;
1970 int first_false;
1971 struct llx *part_llx;
1973 allocate_ascending (n, &list, &elems, &elemp, &values);
1975 /* Check that llx_find_partition works okay in every
1976 case. We use it after partitioning, too, but that
1977 only tests cases where it returns non-null. */
1978 for (i = r0; i < r1; i++)
1979 if (!(pattern & (1u << i)))
1980 break;
1981 j = i;
1982 for (; i < r1; i++)
1983 if (pattern & (1u << i))
1984 break;
1985 part_llx = llx_find_partition (elemp[r0], elemp[r1],
1986 pattern_pred,
1987 &pattern);
1988 if (i == r1)
1989 check (part_llx == elemp[j]);
1990 else
1991 check (part_llx == NULL);
1993 /* Figure out expected results. */
1994 j = 0;
1995 first_false = -1;
1996 for (i = 0; i < r0; i++)
1997 values[j++] = i;
1998 for (i = r0; i < r1; i++)
1999 if (pattern & (1u << i))
2000 values[j++] = i;
2001 for (i = r0; i < r1; i++)
2002 if (!(pattern & (1u << i)))
2004 if (first_false == -1)
2005 first_false = i;
2006 values[j++] = i;
2008 if (first_false == -1)
2009 first_false = r1;
2010 for (i = r1; i < n; i++)
2011 values[j++] = i;
2012 check (j == n);
2014 /* Partition and check for expected results. */
2015 check (llx_partition (elemp[r0], elemp[r1],
2016 pattern_pred, &pattern)
2017 == elemp[first_false]);
2018 check (llx_find_partition (elemp[r0], elemp[r1],
2019 pattern_pred, &pattern)
2020 == elemp[first_false]);
2021 check_list_contents (&list, values, n);
2022 check ((int) llx_count (&list) == n);
2024 free_elements (n, &list, elems, elemp, values);
2028 /* Tests that allocation failure is gracefully handled. */
2029 static void
2030 test_allocation_failure (void)
2032 struct llx_list list;
2034 llx_init (&list);
2035 check (llx_push_head (&list, NULL, &llx_null_mgr) == NULL);
2036 check (llx_push_tail (&list, NULL, &llx_null_mgr) == NULL);
2037 check (llx_insert (llx_null (&list), NULL, &llx_null_mgr) == NULL);
2038 check_list_contents (&list, NULL, 0);
2041 /* Main program. */
2043 struct test
2045 const char *name;
2046 const char *description;
2047 void (*function) (void);
2050 static const struct test tests[] =
2053 "push-pop",
2054 "push/pop",
2055 test_push_pop
2058 "insert-remove",
2059 "insert/remove",
2060 test_insert_remove
2063 "swap",
2064 "swap",
2065 test_swap
2068 "swap-range",
2069 "swap_range",
2070 test_swap_range
2073 "remove-range",
2074 "remove_range",
2075 test_remove_range
2078 "remove-equal",
2079 "remove_equal",
2080 test_remove_equal
2083 "remove-if",
2084 "remove_if",
2085 test_remove_if
2088 "find-equal",
2089 "find_equal",
2090 test_find_equal
2093 "find",
2094 "find",
2095 test_find
2098 "find-if",
2099 "find_if",
2100 test_find_if
2103 "find-adjacent-equal",
2104 "find_adjacent_equal",
2105 test_find_adjacent_equal
2108 "count-range",
2109 "count_range",
2110 test_count_range
2113 "count-equal",
2114 "count_equal",
2115 test_count_equal
2118 "count-if",
2119 "count_if",
2120 test_count_if
2123 "min-max",
2124 "min/max",
2125 test_min_max
2128 "lexicographical-compare-3way",
2129 "lexicographical_compare_3way",
2130 test_lexicographical_compare_3way
2133 "apply",
2134 "apply",
2135 test_apply
2138 "destroy",
2139 "destroy",
2140 test_destroy
2143 "reverse",
2144 "reverse",
2145 test_reverse
2148 "permutations-no-dups",
2149 "permutations (no dups)",
2150 test_permutations_no_dups
2153 "permutations-with-dups",
2154 "permutations (with dups)",
2155 test_permutations_with_dups
2158 "merge-no-dups",
2159 "merge (no dups)",
2160 test_merge_no_dups
2163 "merge-with-dups",
2164 "merge (with dups)",
2165 test_merge_with_dups
2168 "sort-exhaustive",
2169 "sort (exhaustive)",
2170 test_sort_exhaustive
2173 "sort-stable",
2174 "sort (stability)",
2175 test_sort_stable
2178 "sort-subset",
2179 "sort (subset)",
2180 test_sort_subset
2183 "sort-big",
2184 "sort (big)",
2185 test_sort_big
2188 "unique",
2189 "unique",
2190 test_unique
2193 "sort-unique",
2194 "sort_unique",
2195 test_sort_unique
2198 "insert-ordered",
2199 "insert_ordered",
2200 test_insert_ordered
2203 "partition",
2204 "partition",
2205 test_partition
2208 "allocation-failure",
2209 "allocation failure",
2210 test_allocation_failure
2214 enum { N_TESTS = sizeof tests / sizeof *tests };
2217 main (int argc, char *argv[])
2219 int i;
2221 if (argc != 2)
2223 fprintf (stderr, "exactly one argument required; use --help for help\n");
2224 return EXIT_FAILURE;
2226 else if (!strcmp (argv[1], "--help"))
2228 printf ("%s: test doubly linked list of pointers (llx) library\n"
2229 "usage: %s TEST-NAME\n"
2230 "where TEST-NAME is one of the following:\n",
2231 argv[0], argv[0]);
2232 for (i = 0; i < N_TESTS; i++)
2233 printf (" %s\n %s\n", tests[i].name, tests[i].description);
2234 return 0;
2236 else
2238 for (i = 0; i < N_TESTS; i++)
2239 if (!strcmp (argv[1], tests[i].name))
2241 tests[i].function ();
2242 return 0;
2245 fprintf (stderr, "unknown test %s; use --help for help\n", argv[1]);
2246 return EXIT_FAILURE;