Windows build: Adapted icon names to org.fsf.pspp naming
[pspp.git] / tests / libpspp / ll-test.c
blob86a0c5cb11c7cedacd8148e607f194aa37f2ed9f
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 ll_* 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 the ll_* routines. "valgrind --leak-check=yes
21 --show-reachable=yes" should give a clean report.
23 This test program depends only on ll.c and the standard C
24 library.
26 See llx-test.c for a similar program for the llx_*
27 routines. */
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
33 #include <libpspp/ll.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
38 /* Support preliminaries. */
39 #if __GNUC__ >= 2 && !defined UNUSED
40 #define UNUSED __attribute__ ((unused))
41 #else
42 #define UNUSED
43 #endif
45 /* Exit with a failure code.
46 (Place a breakpoint on this function while debugging.) */
47 static void
48 check_die (void)
50 exit (EXIT_FAILURE);
53 /* If OK is not true, prints a message about failure on the
54 current source file and the given LINE and terminates. */
55 static void
56 check_func (bool ok, int line)
58 if (!ok)
60 fprintf (stderr, "%s:%d: check failed\n", __FILE__, line);
61 check_die ();
65 /* Verifies that EXPR evaluates to true.
66 If not, prints a message citing the calling line number and
67 terminates. */
68 #define check(EXPR) check_func ((EXPR), __LINE__)
70 /* Prints a message about memory exhaustion and exits with a
71 failure code. */
72 static void
73 xalloc_die (void)
75 printf ("virtual memory exhausted\n");
76 exit (EXIT_FAILURE);
79 /* Allocates and returns N bytes of memory. */
80 static void *
81 xmalloc (size_t n)
83 if (n != 0)
85 void *p = malloc (n);
86 if (p == NULL)
87 xalloc_die ();
89 return p;
91 else
92 return NULL;
95 /* Allocates and returns N * M bytes of memory. */
96 static void *
97 xnmalloc (size_t n, size_t m)
99 if ((size_t) -1 / m <= n)
100 xalloc_die ();
101 return xmalloc (n * m);
104 /* List type and support routines. */
106 /* Test data element. */
107 struct element
109 struct ll ll; /* Embedded list element. */
110 int x; /* Primary value. */
111 int y; /* Secondary value. */
114 static int aux_data;
116 /* Returns the `struct element' that LL is embedded within. */
117 static struct element *
118 ll_to_element (const struct ll *ll)
120 return ll_data (ll, struct element, ll);
123 /* Prints the elements in LIST. */
124 static void UNUSED
125 print_list (struct ll_list *list)
127 struct ll *x;
129 printf ("list:");
130 for (x = ll_head (list); x != ll_null (list); x = ll_next (x))
132 struct element *e = ll_to_element (x);
133 printf (" %d", e->x);
135 printf ("\n");
138 /* Prints the value returned by PREDICATE given auxiliary data
139 AUX for each element in LIST. */
140 static void UNUSED
141 print_pred (struct ll_list *list,
142 ll_predicate_func *predicate, void *aux UNUSED)
144 struct ll *x;
146 printf ("pred:");
147 for (x = ll_head (list); x != ll_null (list); x = ll_next (x))
148 printf (" %d", predicate (x, aux));
149 printf ("\n");
152 /* Prints the N numbers in VALUES. */
153 static void UNUSED
154 print_array (int values[], size_t n)
156 size_t i;
158 printf ("arry:");
159 for (i = 0; i < n; i++)
160 printf (" %d", values[i]);
161 printf ("\n");
164 /* Compares the `x' values in A and B and returns a strcmp-type
165 return value. Verifies that AUX points to aux_data. */
166 static int
167 compare_elements (const struct ll *a_, const struct ll *b_, void *aux)
169 const struct element *a = ll_to_element (a_);
170 const struct element *b = ll_to_element (b_);
172 check (aux == &aux_data);
173 return a->x < b->x ? -1 : a->x > b->x;
176 /* Compares the `x' and `y' values in A and B and returns a
177 strcmp-type return value. Verifies that AUX points to
178 aux_data. */
179 static int
180 compare_elements_x_y (const struct ll *a_, const struct ll *b_, void *aux)
182 const struct element *a = ll_to_element (a_);
183 const struct element *b = ll_to_element (b_);
185 check (aux == &aux_data);
186 if (a->x != b->x)
187 return a->x < b->x ? -1 : 1;
188 else if (a->y != b->y)
189 return a->y < b->y ? -1 : 1;
190 else
191 return 0;
194 /* Compares the `y' values in A and B and returns a strcmp-type
195 return value. Verifies that AUX points to aux_data. */
196 static int
197 compare_elements_y (const struct ll *a_, const struct ll *b_, void *aux)
199 const struct element *a = ll_to_element (a_);
200 const struct element *b = ll_to_element (b_);
202 check (aux == &aux_data);
203 return a->y < b->y ? -1 : a->y > b->y;
206 /* Returns true if the bit in *PATTERN indicated by `x in
207 *ELEMENT is set, false otherwise. */
208 static bool
209 pattern_pred (const struct ll *element_, void *pattern_)
211 const struct element *element = ll_to_element (element_);
212 unsigned int *pattern = pattern_;
214 return (*pattern & (1u << element->x)) != 0;
217 /* Allocates N elements in *ELEMS.
218 Adds the elements to LIST, if it is nonnull.
219 Puts pointers to the elements' list elements in *ELEMP,
220 followed by a pointer to the list null element, if ELEMP is
221 nonnull.
222 Allocates space for N values in *VALUES, if VALUES is
223 nonnull. */
224 static void
225 allocate_elements (size_t n,
226 struct ll_list *list,
227 struct element ***elems,
228 struct ll ***elemp,
229 int **values)
231 size_t i;
233 if (list != NULL)
234 ll_init (list);
236 *elems = xnmalloc (n, sizeof **elems);
237 for (i = 0; i < n; i++)
239 (*elems)[i] = xmalloc (sizeof ***elems);
240 if (list != NULL)
241 ll_push_tail (list, &(*elems)[i]->ll);
244 if (elemp != NULL)
246 *elemp = xnmalloc (n + 1, sizeof *elemp);
247 for (i = 0; i < n; i++)
248 (*elemp)[i] = &(*elems)[i]->ll;
249 (*elemp)[n] = ll_null (list);
252 if (values != NULL)
253 *values = xnmalloc (n, sizeof *values);
256 /* Copies the N values of `x' from LIST into VALUES[]. */
257 static void
258 extract_values (struct ll_list *list, int values[], size_t n)
260 struct ll *x;
262 check (ll_count (list) == n);
263 for (x = ll_head (list); x != ll_null (list); x = ll_next (x))
265 struct element *e = ll_to_element (x);
266 *values++ = e->x;
270 /* As allocate_elements, but sets ascending values, starting
271 from 0, in `x' values in *ELEMS and in *VALUES (if
272 nonnull). */
273 static void
274 allocate_ascending (size_t n,
275 struct ll_list *list,
276 struct element ***elems,
277 struct ll ***elemp,
278 int **values)
280 size_t i;
282 allocate_elements (n, list, elems, elemp, values);
284 for (i = 0; i < n; i++)
285 (*elems)[i]->x = i;
286 if (values != NULL)
287 extract_values (list, *values, n);
290 /* As allocate_elements, but sets binary values extracted from
291 successive bits in PATTERN in `x' values in *ELEMS and in
292 *VALUES (if nonnull). */
293 static void
294 allocate_pattern (size_t n,
295 int pattern,
296 struct ll_list *list,
297 struct element ***elems,
298 struct ll ***elemp,
299 int **values)
301 size_t i;
303 allocate_elements (n, list, elems, elemp, values);
305 for (i = 0; i < n; i++)
306 (*elems)[i]->x = (pattern & (1 << i)) != 0;
307 if (values != NULL)
308 extract_values (list, *values, n);
311 /* Randomly shuffles the N elements in ARRAY, each of which is
312 SIZE bytes in size. */
313 static void
314 random_shuffle (void *array_, size_t n, size_t size)
316 char *array = array_;
317 char *tmp = xmalloc (size);
318 size_t i;
320 for (i = 0; i < n; i++)
322 size_t j = rand () % (n - i) + i;
323 if (i != j)
325 memcpy (tmp, array + j * size, size);
326 memcpy (array + j * size, array + i * size, size);
327 memcpy (array + i * size, tmp, size);
331 free (tmp);
334 /* As allocate_ascending, but orders the values randomly. */
335 static void
336 allocate_random (size_t n,
337 struct ll_list *list,
338 struct element ***elems,
339 struct ll ***elemp,
340 int **values)
342 size_t i;
344 allocate_elements (n, list, elems, elemp, values);
346 for (i = 0; i < n; i++)
347 (*elems)[i]->x = i;
348 random_shuffle (*elems, n, sizeof **elems);
349 if (values != NULL)
350 extract_values (list, *values, n);
353 /* Frees the N elements of ELEMS, ELEMP, and VALUES. */
354 static void
355 free_elements (size_t n,
356 struct element **elems,
357 struct ll **elemp,
358 int *values)
360 size_t i;
362 for (i = 0; i < n; i++)
363 free (elems[i]);
364 free (elems);
365 free (elemp);
366 free (values);
369 /* Compares A and B and returns a strcmp-type return value. */
370 static int
371 compare_ints (const void *a_, const void *b_, void *aux UNUSED)
373 const int *a = a_;
374 const int *b = b_;
376 return *a < *b ? -1 : *a > *b;
379 /* Compares A and B and returns a strcmp-type return value. */
380 static int
381 compare_ints_noaux (const void *a_, const void *b_)
383 const int *a = a_;
384 const int *b = b_;
386 return *a < *b ? -1 : *a > *b;
389 /* Checks that LIST contains the N values in ELEMENTS. */
390 static void
391 check_list_contents (struct ll_list *list, int elements[], size_t n)
393 struct ll *ll;
394 size_t i;
396 check ((n == 0) == ll_is_empty (list));
398 /* Iterate in forward order. */
399 for (ll = ll_head (list), i = 0; i < n; ll = ll_next (ll), i++)
401 struct element *e = ll_to_element (ll);
402 check (elements[i] == e->x);
403 check (ll != ll_null (list));
405 check (ll == ll_null (list));
407 /* Iterate in reverse order. */
408 for (ll = ll_tail (list), i = 0; i < n; ll = ll_prev (ll), i++)
410 struct element *e = ll_to_element (ll);
411 check (elements[n - i - 1] == e->x);
412 check (ll != ll_null (list));
414 check (ll == ll_null (list));
416 check (ll_count (list) == n);
419 /* Lexicographically compares ARRAY1, which contains COUNT1
420 elements of SIZE bytes each, to ARRAY2, which contains COUNT2
421 elements of SIZE bytes, according to COMPARE. Returns a
422 strcmp-type result. AUX is passed to COMPARE as auxiliary
423 data. */
424 static int
425 lexicographical_compare_3way (const void *array1, size_t count1,
426 const void *array2, size_t count2,
427 size_t size,
428 int (*compare) (const void *, const void *,
429 void *aux),
430 void *aux)
432 const char *first1 = array1;
433 const char *first2 = array2;
434 size_t min_count = count1 < count2 ? count1 : count2;
436 while (min_count > 0)
438 int cmp = compare (first1, first2, aux);
439 if (cmp != 0)
440 return cmp;
442 first1 += size;
443 first2 += size;
444 min_count--;
447 return count1 < count2 ? -1 : count1 > count2;
450 /* Tests. */
452 /* Tests list push and pop operations. */
453 static void
454 test_push_pop (void)
456 const int max_elems = 1024;
458 struct ll_list list;
459 struct element **elems;
460 int *values;
462 int i;
464 allocate_elements (max_elems, NULL, &elems, NULL, &values);
466 /* Push on tail. */
467 ll_init (&list);
468 check_list_contents (&list, NULL, 0);
469 for (i = 0; i < max_elems; i++)
471 values[i] = elems[i]->x = i;
472 ll_push_tail (&list, &elems[i]->ll);
473 check_list_contents (&list, values, i + 1);
476 /* Remove from tail. */
477 for (i = 0; i < max_elems; i++)
479 struct element *e = ll_to_element (ll_pop_tail (&list));
480 check (e->x == max_elems - i - 1);
481 check_list_contents (&list, values, max_elems - i - 1);
484 /* Push at start. */
485 check_list_contents (&list, NULL, 0);
486 for (i = 0; i < max_elems; i++)
488 values[max_elems - i - 1] = elems[i]->x = max_elems - i - 1;
489 ll_push_head (&list, &elems[i]->ll);
490 check_list_contents (&list, &values[max_elems - i - 1], i + 1);
493 /* Remove from start. */
494 for (i = 0; i < max_elems; i++)
496 struct element *e = ll_to_element (ll_pop_head (&list));
497 check (e->x == (int) i);
498 check_list_contents (&list, &values[i + 1], max_elems - i - 1);
501 free_elements (max_elems, elems, NULL, values);
504 /* Tests insertion and removal at arbitrary positions. */
505 static void
506 test_insert_remove (void)
508 const int max_elems = 16;
509 int n;
511 for (n = 0; n < max_elems; n++)
513 struct element **elems;
514 struct ll **elemp;
515 int *values = xnmalloc (n + 1, sizeof *values);
517 struct ll_list list;
518 struct element extra;
519 int pos;
521 allocate_ascending (n, &list, &elems, &elemp, NULL);
522 extra.x = -1;
523 for (pos = 0; pos <= n; pos++)
525 int i, j;
527 ll_insert (elemp[pos], &extra.ll);
529 j = 0;
530 for (i = 0; i < pos; i++)
531 values[j++] = i;
532 values[j++] = -1;
533 for (; i < n; i++)
534 values[j++] = i;
535 check_list_contents (&list, values, n + 1);
537 ll_remove (&extra.ll);
539 check_list_contents (&list, values, n);
541 free_elements (n, elems, elemp, values);
545 /* Tests swapping individual elements. */
546 static void
547 test_swap (void)
549 const int max_elems = 8;
550 int n;
552 for (n = 0; n <= max_elems; n++)
554 struct ll_list list;
555 struct element **elems;
556 int *values;
558 int i, j, k;
560 allocate_ascending (n, &list, &elems, NULL, &values);
561 check_list_contents (&list, values, n);
563 for (i = 0; i < n; i++)
564 for (j = 0; j < n; j++)
565 for (k = 0; k < 2; k++)
567 int t;
569 ll_swap (&elems[i]->ll, &elems[j]->ll);
570 t = values[i];
571 values[i] = values[j];
572 values[j] = t;
573 check_list_contents (&list, values, n);
576 free_elements (n, elems, NULL, values);
580 /* Tests swapping ranges of list elements. */
581 static void
582 test_swap_range (void)
584 const int max_elems = 8;
585 int n, a0, a1, b0, b1, r;
587 for (n = 0; n <= max_elems; n++)
588 for (a0 = 0; a0 <= n; a0++)
589 for (a1 = a0; a1 <= n; a1++)
590 for (b0 = a1; b0 <= n; b0++)
591 for (b1 = b0; b1 <= n; b1++)
592 for (r = 0; r < 2; r++)
594 struct ll_list list;
595 struct element **elems;
596 struct ll **elemp;
597 int *values;
599 int i, j;
601 allocate_ascending (n, &list, &elems, &elemp, &values);
602 check_list_contents (&list, values, n);
604 j = 0;
605 for (i = 0; i < a0; i++)
606 values[j++] = i;
607 for (i = b0; i < b1; i++)
608 values[j++] = i;
609 for (i = a1; i < b0; i++)
610 values[j++] = i;
611 for (i = a0; i < a1; i++)
612 values[j++] = i;
613 for (i = b1; i < n; i++)
614 values[j++] = i;
615 check (j == n);
617 if (r == 0)
618 ll_swap_range (elemp[a0], elemp[a1], elemp[b0], elemp[b1]);
619 else
620 ll_swap_range (elemp[b0], elemp[b1], elemp[a0], elemp[a1]);
621 check_list_contents (&list, values, n);
623 free_elements (n, elems, elemp, values);
627 /* Tests removing ranges of list elements. */
628 static void
629 test_remove_range (void)
631 const int max_elems = 8;
633 int n, r0, r1;
635 for (n = 0; n <= max_elems; n++)
636 for (r0 = 0; r0 <= n; r0++)
637 for (r1 = r0; r1 <= n; r1++)
639 struct ll_list list;
640 struct element **elems;
641 struct ll **elemp;
642 int *values;
644 int i, j;
646 allocate_ascending (n, &list, &elems, &elemp, &values);
647 check_list_contents (&list, values, n);
649 j = 0;
650 for (i = 0; i < r0; i++)
651 values[j++] = i;
652 for (i = r1; i < n; i++)
653 values[j++] = i;
655 ll_remove_range (elemp[r0], elemp[r1]);
656 check_list_contents (&list, values, j);
658 free_elements (n, elems, elemp, values);
662 /* Tests ll_remove_equal. */
663 static void
664 test_remove_equal (void)
666 const int max_elems = 8;
668 int n, r0, r1, eq_pat;
670 for (n = 0; n <= max_elems; n++)
671 for (r0 = 0; r0 <= n; r0++)
672 for (r1 = r0; r1 <= n; r1++)
673 for (eq_pat = 0; eq_pat <= 1 << n; eq_pat++)
675 struct ll_list list;
676 struct element **elems;
677 struct ll **elemp;
678 int *values;
680 struct element to_remove;
681 int remaining;
682 int i;
684 allocate_elements (n, &list, &elems, &elemp, &values);
686 remaining = 0;
687 for (i = 0; i < n; i++)
689 int x = eq_pat & (1 << i) ? -1 : i;
690 bool delete = x == -1 && r0 <= i && i < r1;
691 elems[i]->x = x;
692 if (!delete)
693 values[remaining++] = x;
696 to_remove.x = -1;
697 check ((int) ll_remove_equal (elemp[r0], elemp[r1], &to_remove.ll,
698 compare_elements, &aux_data)
699 == n - remaining);
700 check_list_contents (&list, values, remaining);
702 free_elements (n, elems, elemp, values);
706 /* Tests ll_remove_if. */
707 static void
708 test_remove_if (void)
710 const int max_elems = 8;
712 int n, r0, r1, pattern;
714 for (n = 0; n <= max_elems; n++)
715 for (r0 = 0; r0 <= n; r0++)
716 for (r1 = r0; r1 <= n; r1++)
717 for (pattern = 0; pattern <= 1 << n; pattern++)
719 struct ll_list list;
720 struct element **elems;
721 struct ll **elemp;
722 int *values;
724 int remaining;
725 int i;
727 allocate_elements (n, &list, &elems, &elemp, &values);
729 remaining = 0;
730 for (i = 0; i < n; i++)
732 bool delete = (pattern & (1 << i)) && r0 <= i && i < r1;
733 elems[i]->x = i;
734 if (!delete)
735 values[remaining++] = i;
738 check ((int) ll_remove_if (elemp[r0], elemp[r1],
739 pattern_pred, &pattern)
740 == n - remaining);
741 check_list_contents (&list, values, remaining);
743 free_elements (n, elems, elemp, values);
747 /* Tests ll_moved. */
748 static void
749 test_moved (void)
751 const int max_elems = 8;
753 int n;
755 for (n = 0; n <= max_elems; n++)
757 struct ll_list list;
758 struct element **elems;
759 struct element **new_elems;
760 int *values;
762 int i;
764 allocate_ascending (n, &list, &elems, NULL, &values);
765 allocate_elements (n, NULL, &new_elems, NULL, NULL);
766 check_list_contents (&list, values, n);
768 for (i = 0; i < n; i++)
770 *new_elems[i] = *elems[i];
771 ll_moved (&new_elems[i]->ll);
772 check_list_contents (&list, values, n);
775 free_elements (n, elems, NULL, values);
776 free_elements (n, new_elems, NULL, NULL);
780 /* Tests, via HELPER, a function that looks at list elements
781 equal to some specified element. */
782 static void
783 test_examine_equal_range (void (*helper) (int r0, int r1, int eq_pat,
784 struct ll *to_find,
785 struct ll **elemp))
787 const int max_elems = 8;
789 int n, r0, r1, eq_pat;
791 for (n = 0; n <= max_elems; n++)
792 for (eq_pat = 0; eq_pat <= 1 << n; eq_pat++)
794 struct ll_list list;
795 struct element **elems;
796 struct ll **elemp;
797 int *values;
799 struct element to_find;
801 int i;
803 allocate_ascending (n, &list, &elems, &elemp, &values);
805 for (i = 0; i < n; i++)
806 if (eq_pat & (1 << i))
807 values[i] = elems[i]->x = -1;
809 to_find.x = -1;
810 for (r0 = 0; r0 <= n; r0++)
811 for (r1 = r0; r1 <= n; r1++)
812 helper (r0, r1, eq_pat, &to_find.ll, elemp);
814 check_list_contents (&list, values, n);
816 free_elements (n, elems, elemp, values);
820 /* Tests, via HELPER, a function that looks at list elements for
821 which a given predicate returns true. */
822 static void
823 test_examine_if_range (void (*helper) (int r0, int r1, int eq_pat,
824 struct ll **elemp))
826 const int max_elems = 8;
828 int n, r0, r1, eq_pat;
830 for (n = 0; n <= max_elems; n++)
831 for (eq_pat = 0; eq_pat <= 1 << n; eq_pat++)
833 struct ll_list list;
834 struct element **elems;
835 struct ll **elemp;
836 int *values;
838 allocate_ascending (n, &list, &elems, &elemp, &values);
840 for (r0 = 0; r0 <= n; r0++)
841 for (r1 = r0; r1 <= n; r1++)
842 helper (r0, r1, eq_pat, elemp);
844 check_list_contents (&list, values, n);
846 free_elements (n, elems, elemp, values);
850 /* Helper function for testing ll_find_equal. */
851 static void
852 test_find_equal_helper (int r0, int r1, int eq_pat,
853 struct ll *to_find, struct ll **elemp)
855 struct ll *match;
856 int i;
858 match = ll_find_equal (elemp[r0], elemp[r1], to_find,
859 compare_elements, &aux_data);
860 for (i = r0; i < r1; i++)
861 if (eq_pat & (1 << i))
862 break;
864 check (match == elemp[i]);
867 /* Tests ll_find_equal. */
868 static void
869 test_find_equal (void)
871 test_examine_equal_range (test_find_equal_helper);
874 /* Helper function for testing ll_find_if. */
875 static void
876 test_find_if_helper (int r0, int r1, int eq_pat, struct ll **elemp)
878 struct ll *match = ll_find_if (elemp[r0], elemp[r1],
879 pattern_pred, &eq_pat);
880 int i;
882 for (i = r0; i < r1; i++)
883 if (eq_pat & (1 << i))
884 break;
886 check (match == elemp[i]);
889 /* Tests ll_find_if. */
890 static void
891 test_find_if (void)
893 test_examine_if_range (test_find_if_helper);
896 /* Tests ll_find_adjacent_equal. */
897 static void
898 test_find_adjacent_equal (void)
900 const int max_elems = 8;
902 int n, eq_pat;
904 for (n = 0; n <= max_elems; n++)
905 for (eq_pat = 0; eq_pat <= 1 << n; eq_pat++)
907 struct ll_list list;
908 struct element **elems;
909 struct ll **elemp;
910 int *values;
911 int match;
913 int i;
915 allocate_ascending (n, &list, &elems, &elemp, &values);
917 match = -1;
918 for (i = 0; i < n - 1; i++)
920 elems[i]->y = i;
921 if (eq_pat & (1 << i))
923 values[i] = elems[i]->x = match;
924 values[i + 1] = elems[i + 1]->x = match;
926 else
927 match--;
930 for (i = 0; i <= n; i++)
932 struct ll *ll1 = ll_find_adjacent_equal (elemp[i], ll_null (&list),
933 compare_elements,
934 &aux_data);
935 struct ll *ll2;
936 int j;
938 ll2 = ll_null (&list);
939 for (j = i; j < n - 1; j++)
940 if (eq_pat & (1 << j))
942 ll2 = elemp[j];
943 break;
945 check (ll1 == ll2);
947 check_list_contents (&list, values, n);
949 free_elements (n, elems, elemp, values);
953 /* Helper function for testing ll_count_range. */
954 static void
955 test_count_range_helper (int r0, int r1, int eq_pat UNUSED, struct ll **elemp)
957 check ((int) ll_count_range (elemp[r0], elemp[r1]) == r1 - r0);
960 /* Tests ll_count_range. */
961 static void
962 test_count_range (void)
964 test_examine_if_range (test_count_range_helper);
967 /* Helper function for testing ll_count_equal. */
968 static void
969 test_count_equal_helper (int r0, int r1, int eq_pat,
970 struct ll *to_find, struct ll **elemp)
972 int count1, count2;
973 int i;
975 count1 = ll_count_equal (elemp[r0], elemp[r1], to_find,
976 compare_elements, &aux_data);
977 count2 = 0;
978 for (i = r0; i < r1; i++)
979 if (eq_pat & (1 << i))
980 count2++;
982 check (count1 == count2);
985 /* Tests ll_count_equal. */
986 static void
987 test_count_equal (void)
989 test_examine_equal_range (test_count_equal_helper);
992 /* Helper function for testing ll_count_if. */
993 static void
994 test_count_if_helper (int r0, int r1, int eq_pat, struct ll **elemp)
996 int count1;
997 int count2;
998 int i;
1000 count1 = ll_count_if (elemp[r0], elemp[r1], pattern_pred, &eq_pat);
1002 count2 = 0;
1003 for (i = r0; i < r1; i++)
1004 if (eq_pat & (1 << i))
1005 count2++;
1007 check (count1 == count2);
1010 /* Tests ll_count_if. */
1011 static void
1012 test_count_if (void)
1014 test_examine_if_range (test_count_if_helper);
1017 /* Returns N!. */
1018 static unsigned int
1019 factorial (unsigned int n)
1021 unsigned int value = 1;
1022 while (n > 1)
1023 value *= n--;
1024 return value;
1027 /* Returns the number of permutations of the N values in
1028 VALUES. If VALUES contains duplicates, they must be
1029 adjacent. */
1030 static unsigned int
1031 expected_perms (int *values, size_t n)
1033 size_t i, j;
1034 unsigned int n_perms;
1036 n_perms = factorial (n);
1037 for (i = 0; i < n; i = j)
1039 for (j = i + 1; j < n; j++)
1040 if (values[i] != values[j])
1041 break;
1042 n_perms /= factorial (j - i);
1044 return n_perms;
1047 /* Tests ll_min and ll_max. */
1048 static void
1049 test_min_max (void)
1051 const int max_elems = 6;
1052 int n;
1054 for (n = 0; n <= max_elems; n++)
1056 struct ll_list list;
1057 struct element **elems;
1058 struct ll **elemp;
1059 int *values;
1060 int *new_values = xnmalloc (n, sizeof *values);
1062 size_t n_perms;
1064 allocate_ascending (n, &list, &elems, &elemp, &values);
1066 n_perms = 1;
1067 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1068 compare_elements, &aux_data))
1070 int r0, r1;
1071 struct ll *x;
1072 int i;
1074 for (i = 0, x = ll_head (&list); x != ll_null (&list);
1075 x = ll_next (x), i++)
1077 struct element *e = ll_to_element (x);
1078 elemp[i] = x;
1079 new_values[i] = e->x;
1081 for (r0 = 0; r0 <= n; r0++)
1082 for (r1 = r0; r1 <= n; r1++)
1084 struct ll *min = ll_min (elemp[r0], elemp[r1],
1085 compare_elements, &aux_data);
1086 struct ll *max = ll_max (elemp[r0], elemp[r1],
1087 compare_elements, &aux_data);
1088 if (r0 == r1)
1090 check (min == elemp[r1]);
1091 check (max == elemp[r1]);
1093 else
1095 int min_int, max_int;
1096 int i;
1098 min_int = max_int = new_values[r0];
1099 for (i = r0; i < r1; i++)
1101 int value = new_values[i];
1102 if (value < min_int)
1103 min_int = value;
1104 if (value > max_int)
1105 max_int = value;
1107 check (min != elemp[r1]
1108 && ll_to_element (min)->x == min_int);
1109 check (max != elemp[r1]
1110 && ll_to_element (max)->x == max_int);
1113 n_perms++;
1115 check (n_perms == factorial (n));
1116 check_list_contents (&list, values, n);
1118 free_elements (n, elems, elemp, values);
1119 free (new_values);
1123 /* Tests ll_lexicographical_compare_3way. */
1124 static void
1125 test_lexicographical_compare_3way (void)
1127 const int max_elems = 4;
1129 int n_a, pat_a, n_b, pat_b;
1131 for (n_a = 0; n_a <= max_elems; n_a++)
1132 for (pat_a = 0; pat_a <= 1 << n_a; pat_a++)
1133 for (n_b = 0; n_b <= max_elems; n_b++)
1134 for (pat_b = 0; pat_b <= 1 << n_b; pat_b++)
1136 struct ll_list list_a, list_b;
1137 struct element **elems_a, **elems_b;
1138 struct ll **elemp_a, **elemp_b;
1139 int *values_a, *values_b;
1141 int a0, a1, b0, b1;
1143 allocate_pattern (n_a, pat_a,
1144 &list_a, &elems_a, &elemp_a, &values_a);
1145 allocate_pattern (n_b, pat_b,
1146 &list_b, &elems_b, &elemp_b, &values_b);
1148 for (a0 = 0; a0 <= n_a; a0++)
1149 for (a1 = a0; a1 <= n_a; a1++)
1150 for (b0 = 0; b0 <= n_b; b0++)
1151 for (b1 = b0; b1 <= n_b; b1++)
1153 int a_ordering = lexicographical_compare_3way (
1154 values_a + a0, a1 - a0,
1155 values_b + b0, b1 - b0,
1156 sizeof *values_a,
1157 compare_ints, NULL);
1159 int b_ordering = ll_lexicographical_compare_3way (
1160 elemp_a[a0], elemp_a[a1],
1161 elemp_b[b0], elemp_b[b1],
1162 compare_elements, &aux_data);
1164 check (a_ordering == b_ordering);
1167 free_elements (n_a, elems_a, elemp_a, values_a);
1168 free_elements (n_b, elems_b, elemp_b, values_b);
1172 /* Appends the `x' value in element E to the array pointed to by
1173 NEXT_OUTPUT, and advances NEXT_OUTPUT to the next position. */
1174 static void
1175 apply_func (struct ll *e_, void *next_output_)
1177 struct element *e = ll_to_element (e_);
1178 int **next_output = next_output_;
1180 *(*next_output)++ = e->x;
1183 /* Tests ll_apply. */
1184 static void
1185 test_apply (void)
1187 const int max_elems = 8;
1189 int n, r0, r1;
1191 for (n = 0; n <= max_elems; n++)
1192 for (r0 = 0; r0 <= n; r0++)
1193 for (r1 = r0; r1 <= n; r1++)
1195 struct ll_list list;
1196 struct element **elems;
1197 struct ll **elemp;
1198 int *values;
1200 int *output;
1201 int *next_output;
1203 int i;
1205 allocate_ascending (n, &list, &elems, &elemp, &values);
1206 check_list_contents (&list, values, n);
1208 output = next_output = xnmalloc (n, sizeof *output);
1209 ll_apply (elemp[r0], elemp[r1], apply_func, &next_output);
1210 check_list_contents (&list, values, n);
1212 check (r1 - r0 == next_output - output);
1213 for (i = 0; i < r1 - r0; i++)
1214 check (output[i] == r0 + i);
1216 free_elements (n, elems, elemp, values);
1217 free (output);
1221 /* Tests ll_reverse. */
1222 static void
1223 test_reverse (void)
1225 const int max_elems = 8;
1227 int n, r0, r1;
1229 for (n = 0; n <= max_elems; n++)
1230 for (r0 = 0; r0 <= n; r0++)
1231 for (r1 = r0; r1 <= n; r1++)
1233 struct ll_list list;
1234 struct element **elems;
1235 struct ll **elemp;
1236 int *values;
1238 int i, j;
1240 allocate_ascending (n, &list, &elems, &elemp, &values);
1241 check_list_contents (&list, values, n);
1243 j = 0;
1244 for (i = 0; i < r0; i++)
1245 values[j++] = i;
1246 for (i = r1 - 1; i >= r0; i--)
1247 values[j++] = i;
1248 for (i = r1; i < n; i++)
1249 values[j++] = i;
1251 ll_reverse (elemp[r0], elemp[r1]);
1252 check_list_contents (&list, values, n);
1254 free_elements (n, elems, elemp, values);
1258 /* Tests ll_next_permutation and ll_prev_permutation when the
1259 permuted values have no duplicates. */
1260 static void
1261 test_permutations_no_dups (void)
1263 const int max_elems = 8;
1264 int n;
1266 for (n = 0; n <= max_elems; n++)
1268 struct ll_list list;
1269 struct element **elems;
1270 int *values;
1271 int *old_values = xnmalloc (n, sizeof *values);
1272 int *new_values = xnmalloc (n, sizeof *values);
1274 size_t n_perms;
1276 allocate_ascending (n, &list, &elems, NULL, &values);
1278 n_perms = 1;
1279 extract_values (&list, old_values, n);
1280 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1281 compare_elements, &aux_data))
1283 extract_values (&list, new_values, n);
1284 check (lexicographical_compare_3way (new_values, n,
1285 old_values, n,
1286 sizeof *new_values,
1287 compare_ints, NULL) > 0);
1288 memcpy (old_values, new_values, (n) * sizeof *old_values);
1289 n_perms++;
1291 check (n_perms == factorial (n));
1292 check_list_contents (&list, values, n);
1294 n_perms = 1;
1295 ll_reverse (ll_head (&list), ll_null (&list));
1296 extract_values (&list, old_values, n);
1297 while (ll_prev_permutation (ll_head (&list), ll_null (&list),
1298 compare_elements, &aux_data))
1300 extract_values (&list, new_values, n);
1301 check (lexicographical_compare_3way (new_values, n,
1302 old_values, n,
1303 sizeof *new_values,
1304 compare_ints, NULL) < 0);
1305 memcpy (old_values, new_values, (n) * sizeof *old_values);
1306 n_perms++;
1308 check (n_perms == factorial (n));
1309 ll_reverse (ll_head (&list), ll_null (&list));
1310 check_list_contents (&list, values, n);
1312 free_elements (n, elems, NULL, values);
1313 free (old_values);
1314 free (new_values);
1318 /* Tests ll_next_permutation and ll_prev_permutation when the
1319 permuted values contain duplicates. */
1320 static void
1321 test_permutations_with_dups (void)
1323 const int max_elems = 8;
1324 const int max_dup = 3;
1325 const int repetitions = 1024;
1327 for (int repeat = 0; repeat < repetitions; repeat++)
1328 for (int n_elems = 0; n_elems < max_elems; n_elems++)
1330 struct ll_list list;
1331 struct element **elems;
1332 int *values;
1333 int *old_values = xnmalloc (max_elems, sizeof *values);
1334 int *new_values = xnmalloc (max_elems, sizeof *values);
1336 unsigned int n_permutations;
1337 int left = n_elems;
1338 int value = 0;
1340 allocate_elements (n_elems, &list, &elems, NULL, &values);
1342 value = 0;
1343 while (left > 0)
1345 int max = left < max_dup ? left : max_dup;
1346 int n = rand () % max + 1;
1347 while (n-- > 0)
1349 int idx = n_elems - left--;
1350 values[idx] = elems[idx]->x = value;
1352 value++;
1355 n_permutations = 1;
1356 extract_values (&list, old_values, n_elems);
1357 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1358 compare_elements, &aux_data))
1360 extract_values (&list, new_values, n_elems);
1361 check (lexicographical_compare_3way (new_values, n_elems,
1362 old_values, n_elems,
1363 sizeof *new_values,
1364 compare_ints, NULL) > 0);
1365 memcpy (old_values, new_values, n_elems * sizeof *old_values);
1366 n_permutations++;
1368 check (n_permutations == expected_perms (values, n_elems));
1369 check_list_contents (&list, values, n_elems);
1371 n_permutations = 1;
1372 ll_reverse (ll_head (&list), ll_null (&list));
1373 extract_values (&list, old_values, n_elems);
1374 while (ll_prev_permutation (ll_head (&list), ll_null (&list),
1375 compare_elements, &aux_data))
1377 extract_values (&list, new_values, n_elems);
1378 check (lexicographical_compare_3way (new_values, n_elems,
1379 old_values, n_elems,
1380 sizeof *new_values,
1381 compare_ints, NULL) < 0);
1382 n_permutations++;
1384 ll_reverse (ll_head (&list), ll_null (&list));
1385 check (n_permutations == expected_perms (values, n_elems));
1386 check_list_contents (&list, values, n_elems);
1388 free_elements (n_elems, elems, NULL, values);
1389 free (old_values);
1390 free (new_values);
1394 /* Tests ll_merge when no equal values are to be merged. */
1395 static void
1396 test_merge_no_dups (void)
1398 const int max_elems = 8;
1399 const int max_filler = 3;
1401 int n_merges, pattern, pfx, gap, sfx, order;
1403 for (n_merges = 0; n_merges < max_elems; n_merges++)
1404 for (pattern = 0; pattern <= (1 << n_merges); pattern++)
1405 for (pfx = 0; pfx < max_filler; pfx++)
1406 for (gap = 0; gap < max_filler; gap++)
1407 for (sfx = 0; sfx < max_filler; sfx++)
1408 for (order = 0; order < 2; order++)
1410 struct ll_list list;
1411 struct element **elems;
1412 struct ll **elemp;
1413 int *values;
1415 int n_lists = pfx + n_merges + gap + sfx;
1416 int a0, a1, b0, b1;
1417 int i, j;
1419 allocate_elements (n_lists, &list,
1420 &elems, &elemp, &values);
1422 j = 0;
1423 for (i = 0; i < pfx; i++)
1424 elems[j++]->x = 100 + i;
1425 a0 = j;
1426 for (i = 0; i < n_merges; i++)
1427 if (pattern & (1u << i))
1428 elems[j++]->x = i;
1429 a1 = j;
1430 for (i = 0; i < gap; i++)
1431 elems[j++]->x = 200 + i;
1432 b0 = j;
1433 for (i = 0; i < n_merges; i++)
1434 if (!(pattern & (1u << i)))
1435 elems[j++]->x = i;
1436 b1 = j;
1437 for (i = 0; i < sfx; i++)
1438 elems[j++]->x = 300 + i;
1439 check (n_lists == j);
1441 j = 0;
1442 for (i = 0; i < pfx; i++)
1443 values[j++] = 100 + i;
1444 if (order == 0)
1445 for (i = 0; i < n_merges; i++)
1446 values[j++] = i;
1447 for (i = 0; i < gap; i++)
1448 values[j++] = 200 + i;
1449 if (order == 1)
1450 for (i = 0; i < n_merges; i++)
1451 values[j++] = i;
1452 for (i = 0; i < sfx; i++)
1453 values[j++] = 300 + i;
1454 check (n_lists == j);
1456 if (order == 0)
1457 ll_merge (elemp[a0], elemp[a1], elemp[b0], elemp[b1],
1458 compare_elements, &aux_data);
1459 else
1460 ll_merge (elemp[b0], elemp[b1], elemp[a0], elemp[a1],
1461 compare_elements, &aux_data);
1463 check_list_contents (&list, values, n_lists);
1465 free_elements (n_lists, elems, elemp, values);
1469 /* Tests ll_merge when equal values are to be merged. */
1470 static void
1471 test_merge_with_dups (void)
1473 const int max_elems = 8;
1475 int n, merge_pat, inc_pat, order;
1477 for (n = 0; n <= max_elems; n++)
1478 for (merge_pat = 0; merge_pat <= (1 << n); merge_pat++)
1479 for (inc_pat = 0; inc_pat <= (1 << n); inc_pat++)
1480 for (order = 0; order < 2; order++)
1482 struct ll_list list;
1483 struct element **elems;
1484 struct ll **elemp;
1485 int *values;
1487 int mid;
1488 int i, j, k;
1490 allocate_elements (n, &list, &elems, &elemp, &values);
1492 j = 0;
1493 for (i = k = 0; i < n; i++)
1495 if (merge_pat & (1u << i))
1496 elems[j++]->x = k;
1497 if (inc_pat & (1u << i))
1498 k++;
1500 mid = j;
1501 for (i = k = 0; i < n; i++)
1503 if (!(merge_pat & (1u << i)))
1504 elems[j++]->x = k;
1505 if (inc_pat & (1u << i))
1506 k++;
1508 check (n == j);
1510 if (order == 0)
1512 for (i = 0; i < n; i++)
1513 elems[i]->y = i;
1515 else
1517 for (i = 0; i < mid; i++)
1518 elems[i]->y = 100 + i;
1519 for (i = mid; i < n; i++)
1520 elems[i]->y = i;
1523 j = 0;
1524 for (i = k = 0; i < n; i++)
1526 values[j++] = k;
1527 if (inc_pat & (1u << i))
1528 k++;
1530 check (n == j);
1532 if (order == 0)
1533 ll_merge (elemp[0], elemp[mid], elemp[mid], elemp[n],
1534 compare_elements, &aux_data);
1535 else
1536 ll_merge (elemp[mid], elemp[n], elemp[0], elemp[mid],
1537 compare_elements, &aux_data);
1539 check_list_contents (&list, values, n);
1540 check (ll_is_sorted (ll_head (&list), ll_null (&list),
1541 compare_elements_x_y, &aux_data));
1543 free_elements (n, elems, elemp, values);
1547 /* Tests ll_sort on all permutations up to a maximum number of
1548 elements. */
1549 static void
1550 test_sort_exhaustive (void)
1552 const int max_elems = 8;
1553 int n;
1555 for (n = 0; n <= max_elems; n++)
1557 struct ll_list list;
1558 struct element **elems;
1559 int *values;
1561 struct element **perm_elems;
1562 int *perm_values;
1564 size_t n_perms;
1566 allocate_ascending (n, &list, &elems, NULL, &values);
1567 allocate_elements (n, NULL, &perm_elems, NULL, &perm_values);
1569 n_perms = 1;
1570 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1571 compare_elements, &aux_data))
1573 struct ll_list perm_list;
1574 int j;
1576 extract_values (&list, perm_values, n);
1577 ll_init (&perm_list);
1578 for (j = 0; j < n; j++)
1580 perm_elems[j]->x = perm_values[j];
1581 ll_push_tail (&perm_list, &perm_elems[j]->ll);
1583 ll_sort (ll_head (&perm_list), ll_null (&perm_list),
1584 compare_elements, &aux_data);
1585 check_list_contents (&perm_list, values, n);
1586 check (ll_is_sorted (ll_head (&perm_list), ll_null (&perm_list),
1587 compare_elements, &aux_data));
1588 n_perms++;
1590 check (n_perms == factorial (n));
1592 free_elements (n, elems, NULL, values);
1593 free_elements (n, perm_elems, NULL, perm_values);
1597 /* Tests that ll_sort is stable in the presence of equal
1598 values. */
1599 static void
1600 test_sort_stable (void)
1602 const int max_elems = 6;
1603 int n, inc_pat;
1605 for (n = 0; n <= max_elems; n++)
1606 for (inc_pat = 0; inc_pat <= 1 << n; inc_pat++)
1608 struct ll_list list;
1609 struct element **elems;
1610 int *values;
1612 struct element **perm_elems;
1613 int *perm_values;
1615 size_t n_perms;
1616 int i, j;
1618 allocate_elements (n, &list, &elems, NULL, &values);
1619 allocate_elements (n, NULL, &perm_elems, NULL, &perm_values);
1621 j = 0;
1622 for (i = 0; i < n; i++)
1624 elems[i]->x = values[i] = j;
1625 if (inc_pat & (1 << i))
1626 j++;
1627 elems[i]->y = i;
1630 n_perms = 1;
1631 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1632 compare_elements_y, &aux_data))
1634 struct ll_list perm_list;
1636 extract_values (&list, perm_values, n);
1637 ll_init (&perm_list);
1638 for (i = 0; i < n; i++)
1640 perm_elems[i]->x = perm_values[i];
1641 perm_elems[i]->y = i;
1642 ll_push_tail (&perm_list, &perm_elems[i]->ll);
1644 ll_sort (ll_head (&perm_list), ll_null (&perm_list),
1645 compare_elements, &aux_data);
1646 check_list_contents (&perm_list, values, n);
1647 check (ll_is_sorted (ll_head (&perm_list), ll_null (&perm_list),
1648 compare_elements_x_y, &aux_data));
1649 n_perms++;
1651 check (n_perms == factorial (n));
1653 free_elements (n, elems, NULL, values);
1654 free_elements (n, perm_elems, NULL, perm_values);
1658 /* Tests that ll_sort does not disturb elements outside the
1659 range sorted. */
1660 static void
1661 test_sort_subset (void)
1663 const int max_elems = 8;
1665 int n, r0, r1, repeat;
1667 for (n = 0; n <= max_elems; n++)
1668 for (repeat = 0; repeat < 100; repeat++)
1669 for (r0 = 0; r0 <= n; r0++)
1670 for (r1 = r0; r1 <= n; r1++)
1672 struct ll_list list;
1673 struct element **elems;
1674 struct ll **elemp;
1675 int *values;
1677 allocate_random (n, &list, &elems, &elemp, &values);
1679 qsort (&values[r0], r1 - r0, sizeof *values, compare_ints_noaux);
1680 ll_sort (elemp[r0], elemp[r1], compare_elements, &aux_data);
1681 check_list_contents (&list, values, n);
1683 free_elements (n, elems, elemp, values);
1687 /* Tests that ll_sort works with large lists. */
1688 static void
1689 test_sort_big (void)
1691 const int max_elems = 1024;
1693 int n;
1695 for (n = 0; n < max_elems; n++)
1697 struct ll_list list;
1698 struct element **elems;
1699 int *values;
1701 allocate_random (n, &list, &elems, NULL, &values);
1703 qsort (values, n, sizeof *values, compare_ints_noaux);
1704 ll_sort (ll_head (&list), ll_null (&list), compare_elements, &aux_data);
1705 check_list_contents (&list, values, n);
1707 free_elements (n, elems, NULL, values);
1711 /* Tests ll_unique. */
1712 static void
1713 test_unique (void)
1715 const int max_elems = 10;
1717 int *ascending = xnmalloc (max_elems, sizeof *ascending);
1719 int n, inc_pat, i, j, unique_values;
1721 for (i = 0; i < max_elems; i++)
1722 ascending[i] = i;
1724 for (n = 0; n < max_elems; n++)
1725 for (inc_pat = 0; inc_pat < (1 << n); inc_pat++)
1727 struct ll_list list, dups;
1728 struct element **elems;
1729 int *values;
1731 allocate_elements (n, &list, &elems, NULL, &values);
1733 j = unique_values = 0;
1734 for (i = 0; i < n; i++)
1736 unique_values = j + 1;
1737 elems[i]->x = values[i] = j;
1738 if (inc_pat & (1 << i))
1739 j++;
1741 check_list_contents (&list, values, n);
1743 ll_init (&dups);
1744 check (ll_unique (ll_head (&list), ll_null (&list), ll_null (&dups),
1745 compare_elements, &aux_data)
1746 == (size_t) unique_values);
1747 check_list_contents (&list, ascending, unique_values);
1749 ll_splice (ll_null (&list), ll_head (&dups), ll_null (&dups));
1750 ll_sort (ll_head (&list), ll_null (&list), compare_elements, &aux_data);
1751 check_list_contents (&list, values, n);
1753 free_elements (n, elems, NULL, values);
1756 free (ascending);
1759 /* Tests ll_sort_unique. */
1760 static void
1761 test_sort_unique (void)
1763 const int max_elems = 7;
1764 int n, inc_pat;
1766 for (n = 0; n <= max_elems; n++)
1767 for (inc_pat = 0; inc_pat <= 1 << n; inc_pat++)
1769 struct ll_list list;
1770 struct element **elems;
1771 int *values;
1773 struct element **perm_elems;
1774 int *perm_values;
1776 int n_uniques;
1777 int *unique_values;
1779 size_t n_perms;
1780 int i, j;
1782 allocate_elements (n, &list, &elems, NULL, &values);
1783 allocate_elements (n, NULL, &perm_elems, NULL, &perm_values);
1785 j = n_uniques = 0;
1786 for (i = 0; i < n; i++)
1788 elems[i]->x = values[i] = j;
1789 n_uniques = j + 1;
1790 if (inc_pat & (1 << i))
1791 j++;
1794 unique_values = xnmalloc (n_uniques, sizeof *unique_values);
1795 for (i = 0; i < n_uniques; i++)
1796 unique_values[i] = i;
1798 n_perms = 1;
1799 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1800 compare_elements, &aux_data))
1802 struct ll_list perm_list;
1804 extract_values (&list, perm_values, n);
1805 ll_init (&perm_list);
1806 for (i = 0; i < n; i++)
1808 perm_elems[i]->x = perm_values[i];
1809 perm_elems[i]->y = i;
1810 ll_push_tail (&perm_list, &perm_elems[i]->ll);
1812 ll_sort_unique (ll_head (&perm_list), ll_null (&perm_list), NULL,
1813 compare_elements, &aux_data);
1814 check_list_contents (&perm_list, unique_values, n_uniques);
1815 check (ll_is_sorted (ll_head (&perm_list), ll_null (&perm_list),
1816 compare_elements_x_y, &aux_data));
1817 n_perms++;
1819 check (n_perms == expected_perms (values, n));
1821 free_elements (n, elems, NULL, values);
1822 free_elements (n, perm_elems, NULL, perm_values);
1823 free (unique_values);
1827 /* Tests ll_insert_ordered. */
1828 static void
1829 test_insert_ordered (void)
1831 const int max_elems = 6;
1832 int n, inc_pat;
1834 for (n = 0; n <= max_elems; n++)
1835 for (inc_pat = 0; inc_pat <= 1 << n; inc_pat++)
1837 struct ll_list list;
1838 struct element **elems;
1839 int *values;
1841 struct element **perm_elems;
1842 int *perm_values;
1844 size_t n_perms;
1845 int i, j;
1847 allocate_elements (n, &list, &elems, NULL, &values);
1848 allocate_elements (n, NULL, &perm_elems, NULL, &perm_values);
1850 j = 0;
1851 for (i = 0; i < n; i++)
1853 elems[i]->x = values[i] = j;
1854 if (inc_pat & (1 << i))
1855 j++;
1856 elems[i]->y = i;
1859 n_perms = 1;
1860 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1861 compare_elements_y, &aux_data))
1863 struct ll_list perm_list;
1865 extract_values (&list, perm_values, n);
1866 ll_init (&perm_list);
1867 for (i = 0; i < n; i++)
1869 perm_elems[i]->x = perm_values[i];
1870 perm_elems[i]->y = i;
1871 ll_insert_ordered (ll_head (&perm_list), ll_null (&perm_list),
1872 &perm_elems[i]->ll,
1873 compare_elements, &aux_data);
1875 check (ll_is_sorted (ll_head (&perm_list), ll_null (&perm_list),
1876 compare_elements_x_y, &aux_data));
1877 n_perms++;
1879 check (n_perms == factorial (n));
1881 free_elements (n, elems, NULL, values);
1882 free_elements (n, perm_elems, NULL, perm_values);
1886 /* Tests ll_partition. */
1887 static void
1888 test_partition (void)
1890 const int max_elems = 10;
1892 int n;
1893 unsigned int pbase;
1894 int r0, r1;
1896 for (n = 0; n < max_elems; n++)
1897 for (r0 = 0; r0 <= n; r0++)
1898 for (r1 = r0; r1 <= n; r1++)
1899 for (pbase = 0; pbase <= (1u << (r1 - r0)); pbase++)
1901 struct ll_list list;
1902 struct element **elems;
1903 struct ll **elemp;
1904 int *values;
1906 unsigned int pattern = pbase << r0;
1907 int i, j;
1908 int first_false;
1909 struct ll *part_ll;
1911 allocate_ascending (n, &list, &elems, &elemp, &values);
1913 /* Check that ll_find_partition works okay in every
1914 case. We use it after partitioning, too, but that
1915 only tests cases where it returns non-null. */
1916 for (i = r0; i < r1; i++)
1917 if (!(pattern & (1u << i)))
1918 break;
1919 j = i;
1920 for (; i < r1; i++)
1921 if (pattern & (1u << i))
1922 break;
1923 part_ll = ll_find_partition (elemp[r0], elemp[r1],
1924 pattern_pred,
1925 &pattern);
1926 if (i == r1)
1927 check (part_ll == elemp[j]);
1928 else
1929 check (part_ll == NULL);
1931 /* Figure out expected results. */
1932 j = 0;
1933 first_false = -1;
1934 for (i = 0; i < r0; i++)
1935 values[j++] = i;
1936 for (i = r0; i < r1; i++)
1937 if (pattern & (1u << i))
1938 values[j++] = i;
1939 for (i = r0; i < r1; i++)
1940 if (!(pattern & (1u << i)))
1942 if (first_false == -1)
1943 first_false = i;
1944 values[j++] = i;
1946 if (first_false == -1)
1947 first_false = r1;
1948 for (i = r1; i < n; i++)
1949 values[j++] = i;
1950 check (j == n);
1952 /* Partition and check for expected results. */
1953 check (ll_partition (elemp[r0], elemp[r1],
1954 pattern_pred, &pattern)
1955 == elemp[first_false]);
1956 check (ll_find_partition (elemp[r0], elemp[r1],
1957 pattern_pred, &pattern)
1958 == elemp[first_false]);
1959 check_list_contents (&list, values, n);
1960 check ((int) ll_count (&list) == n);
1962 free_elements (n, elems, elemp, values);
1966 /* Main program. */
1968 struct test
1970 const char *name;
1971 const char *description;
1972 void (*function) (void);
1975 static const struct test tests[] =
1978 "push-pop",
1979 "push/pop",
1980 test_push_pop
1983 "insert-remove",
1984 "insert/remove",
1985 test_insert_remove
1988 "swap",
1989 "swap",
1990 test_swap
1993 "swap-range",
1994 "swap_range",
1995 test_swap_range
1998 "remove-range",
1999 "remove_range",
2000 test_remove_range
2003 "remove-equal",
2004 "remove_equal",
2005 test_remove_equal
2008 "remove-if",
2009 "remove_if",
2010 test_remove_if
2013 "moved",
2014 "moved",
2015 test_moved
2018 "find-equal",
2019 "find_equal",
2020 test_find_equal
2023 "find-if",
2024 "find_if",
2025 test_find_if
2028 "find-adjacent-equal",
2029 "find_adjacent_equal",
2030 test_find_adjacent_equal
2033 "count-range",
2034 "count_range",
2035 test_count_range
2038 "count-equal",
2039 "count_equal",
2040 test_count_equal
2043 "count-if",
2044 "count_if",
2045 test_count_if
2048 "min-max",
2049 "min/max",
2050 test_min_max
2053 "lexicographical-compare-3way",
2054 "lexicographical_compare_3way",
2055 test_lexicographical_compare_3way
2058 "apply",
2059 "apply",
2060 test_apply
2063 "reverse",
2064 "reverse",
2065 test_reverse
2068 "permutations-no-dups",
2069 "permutations (no dups)",
2070 test_permutations_no_dups
2073 "permutations-with-dups",
2074 "permutations (with dups)",
2075 test_permutations_with_dups
2078 "merge-no-dups",
2079 "merge (no dups)",
2080 test_merge_no_dups
2083 "merge-with-dups",
2084 "merge (with dups)",
2085 test_merge_with_dups
2088 "sort-exhaustive",
2089 "sort (exhaustive)",
2090 test_sort_exhaustive
2093 "sort-stable",
2094 "sort (stability)",
2095 test_sort_stable
2098 "sort-subset",
2099 "sort (subset)",
2100 test_sort_subset
2103 "sort-big",
2104 "sort (big)",
2105 test_sort_big
2108 "unique",
2109 "unique",
2110 test_unique
2113 "sort-unique",
2114 "sort_unique",
2115 test_sort_unique
2118 "insert-ordered",
2119 "insert_ordered",
2120 test_insert_ordered
2123 "partition",
2124 "partition",
2125 test_partition
2129 enum { N_TESTS = sizeof tests / sizeof *tests };
2132 main (int argc, char *argv[])
2134 int i;
2136 if (argc != 2)
2138 fprintf (stderr, "exactly one argument required; use --help for help\n");
2139 return EXIT_FAILURE;
2141 else if (!strcmp (argv[1], "--help"))
2143 printf ("%s: test doubly linked list (ll) library\n"
2144 "usage: %s TEST-NAME\n"
2145 "where TEST-NAME is one of the following:\n",
2146 argv[0], argv[0]);
2147 for (i = 0; i < N_TESTS; i++)
2148 printf (" %s\n %s\n", tests[i].name, tests[i].description);
2149 return 0;
2151 else
2153 for (i = 0; i < N_TESTS; i++)
2154 if (!strcmp (argv[1], tests[i].name))
2156 tests[i].function ();
2157 return 0;
2160 fprintf (stderr, "unknown test %s; use --help for help\n", argv[1]);
2161 return EXIT_FAILURE;