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
26 See llx-test.c for a similar program for the llx_*
33 #include <libpspp/ll.h>
39 /* Support preliminaries. */
40 #if __GNUC__ >= 2 && !defined UNUSED
41 #define UNUSED __attribute__ ((unused))
46 /* Exit with a failure code.
47 (Place a breakpoint on this function while debugging.) */
54 /* If OK is not true, prints a message about failure on the
55 current source file and the given LINE and terminates. */
57 check_func (bool ok, int line)
61 fprintf (stderr, "%s:%d: check failed\n", __FILE__, line);
66 /* Verifies that EXPR evaluates to true.
67 If not, prints a message citing the calling line number and
69 #define check(EXPR) check_func ((EXPR), __LINE__)
71 /* Prints a message about memory exhaustion and exits with a
76 printf ("virtual memory exhausted\n");
80 /* Allocates and returns N bytes of memory. */
96 /* Allocates and returns N * M bytes of memory. */
98 xnmalloc (size_t n, size_t m)
100 if ((size_t) -1 / m <= n)
102 return xmalloc (n * m);
105 /* List type and support routines. */
107 /* Test data element. */
110 struct ll ll; /* Embedded list element. */
111 int x; /* Primary value. */
112 int y; /* Secondary value. */
117 /* Returns the `struct element' that LL is embedded within. */
118 static struct element *
119 ll_to_element (const struct ll *ll)
121 return ll_data (ll, struct element, ll);
124 /* Prints the elements in LIST. */
126 print_list (struct ll_list *list)
131 for (x = ll_head (list); x != ll_null (list); x = ll_next (x))
133 struct element *e = ll_to_element (x);
134 printf (" %d", e->x);
139 /* Prints the value returned by PREDICATE given auxiliary data
140 AUX for each element in LIST. */
142 print_pred (struct ll_list *list,
143 ll_predicate_func *predicate, void *aux UNUSED)
148 for (x = ll_head (list); x != ll_null (list); x = ll_next (x))
149 printf (" %d", predicate (x, aux));
153 /* Prints the CNT numbers in VALUES. */
155 print_array (int values[], size_t cnt)
160 for (i = 0; i < cnt; i++)
161 printf (" %d", values[i]);
165 /* Compares the `x' values in A and B and returns a strcmp-type
166 return value. Verifies that AUX points to aux_data. */
168 compare_elements (const struct ll *a_, const struct ll *b_, void *aux)
170 const struct element *a = ll_to_element (a_);
171 const struct element *b = ll_to_element (b_);
173 check (aux == &aux_data);
174 return a->x < b->x ? -1 : a->x > b->x;
177 /* Compares the `x' and `y' values in A and B and returns a
178 strcmp-type return value. Verifies that AUX points to
181 compare_elements_x_y (const struct ll *a_, const struct ll *b_, void *aux)
183 const struct element *a = ll_to_element (a_);
184 const struct element *b = ll_to_element (b_);
186 check (aux == &aux_data);
188 return a->x < b->x ? -1 : 1;
189 else if (a->y != b->y)
190 return a->y < b->y ? -1 : 1;
195 /* Compares the `y' values in A and B and returns a strcmp-type
196 return value. Verifies that AUX points to aux_data. */
198 compare_elements_y (const struct ll *a_, const struct ll *b_, void *aux)
200 const struct element *a = ll_to_element (a_);
201 const struct element *b = ll_to_element (b_);
203 check (aux == &aux_data);
204 return a->y < b->y ? -1 : a->y > b->y;
207 /* Returns true if the bit in *PATTERN indicated by `x in
208 *ELEMENT is set, false otherwise. */
210 pattern_pred (const struct ll *element_, void *pattern_)
212 const struct element *element = ll_to_element (element_);
213 unsigned int *pattern = pattern_;
215 return (*pattern & (1u << element->x)) != 0;
218 /* Allocates N elements in *ELEMS.
219 Adds the elements to LIST, if it is nonnull.
220 Puts pointers to the elements' list elements in *ELEMP,
221 followed by a pointer to the list null element, if ELEMP is
223 Allocates space for N values in *VALUES, if VALUES is
226 allocate_elements (size_t n,
227 struct ll_list *list,
228 struct element ***elems,
237 *elems = xnmalloc (n, sizeof **elems);
238 for (i = 0; i < n; i++)
240 (*elems)[i] = xmalloc (sizeof ***elems);
242 ll_push_tail (list, &(*elems)[i]->ll);
247 *elemp = xnmalloc (n + 1, sizeof *elemp);
248 for (i = 0; i < n; i++)
249 (*elemp)[i] = &(*elems)[i]->ll;
250 (*elemp)[n] = ll_null (list);
254 *values = xnmalloc (n, sizeof *values);
257 /* Copies the CNT values of `x' from LIST into VALUES[]. */
259 extract_values (struct ll_list *list, int values[], size_t cnt)
263 check (ll_count (list) == cnt);
264 for (x = ll_head (list); x != ll_null (list); x = ll_next (x))
266 struct element *e = ll_to_element (x);
271 /* As allocate_elements, but sets ascending values, starting
272 from 0, in `x' values in *ELEMS and in *VALUES (if
275 allocate_ascending (size_t n,
276 struct ll_list *list,
277 struct element ***elems,
283 allocate_elements (n, list, elems, elemp, values);
285 for (i = 0; i < n; i++)
288 extract_values (list, *values, n);
291 /* As allocate_elements, but sets binary values extracted from
292 successive bits in PATTERN in `x' values in *ELEMS and in
293 *VALUES (if nonnull). */
295 allocate_pattern (size_t n,
297 struct ll_list *list,
298 struct element ***elems,
304 allocate_elements (n, list, elems, elemp, values);
306 for (i = 0; i < n; i++)
307 (*elems)[i]->x = (pattern & (1 << i)) != 0;
309 extract_values (list, *values, n);
312 /* Randomly shuffles the CNT elements in ARRAY, each of which is
313 SIZE bytes in size. */
315 random_shuffle (void *array_, size_t cnt, size_t size)
317 char *array = array_;
318 char *tmp = xmalloc (size);
321 for (i = 0; i < cnt; i++)
323 size_t j = rand () % (cnt - i) + i;
326 memcpy (tmp, array + j * size, size);
327 memcpy (array + j * size, array + i * size, size);
328 memcpy (array + i * size, tmp, size);
335 /* As allocate_ascending, but orders the values randomly. */
337 allocate_random (size_t n,
338 struct ll_list *list,
339 struct element ***elems,
345 allocate_elements (n, list, elems, elemp, values);
347 for (i = 0; i < n; i++)
349 random_shuffle (*elems, n, sizeof **elems);
351 extract_values (list, *values, n);
354 /* Frees the N elements of ELEMS, ELEMP, and VALUES. */
356 free_elements (size_t n,
357 struct element **elems,
363 for (i = 0; i < n; i++)
370 /* Compares A and B and returns a strcmp-type return value. */
372 compare_ints (const void *a_, const void *b_, void *aux UNUSED)
377 return *a < *b ? -1 : *a > *b;
380 /* Compares A and B and returns a strcmp-type return value. */
382 compare_ints_noaux (const void *a_, const void *b_)
387 return *a < *b ? -1 : *a > *b;
390 /* Checks that LIST contains the CNT values in ELEMENTS. */
392 check_list_contents (struct ll_list *list, int elements[], size_t cnt)
397 check ((cnt == 0) == ll_is_empty (list));
399 /* Iterate in forward order. */
400 for (ll = ll_head (list), i = 0; i < cnt; ll = ll_next (ll), i++)
402 struct element *e = ll_to_element (ll);
403 check (elements[i] == e->x);
404 check (ll != ll_null (list));
406 check (ll == ll_null (list));
408 /* Iterate in reverse order. */
409 for (ll = ll_tail (list), i = 0; i < cnt; ll = ll_prev (ll), i++)
411 struct element *e = ll_to_element (ll);
412 check (elements[cnt - i - 1] == e->x);
413 check (ll != ll_null (list));
415 check (ll == ll_null (list));
417 check (ll_count (list) == cnt);
420 /* Lexicographically compares ARRAY1, which contains COUNT1
421 elements of SIZE bytes each, to ARRAY2, which contains COUNT2
422 elements of SIZE bytes, according to COMPARE. Returns a
423 strcmp-type result. AUX is passed to COMPARE as auxiliary
426 lexicographical_compare_3way (const void *array1, size_t count1,
427 const void *array2, size_t count2,
429 int (*compare) (const void *, const void *,
433 const char *first1 = array1;
434 const char *first2 = array2;
435 size_t min_count = count1 < count2 ? count1 : count2;
437 while (min_count > 0)
439 int cmp = compare (first1, first2, aux);
448 return count1 < count2 ? -1 : count1 > count2;
453 /* Tests list push and pop operations. */
457 const int max_elems = 1024;
460 struct element **elems;
465 allocate_elements (max_elems, NULL, &elems, NULL, &values);
469 check_list_contents (&list, NULL, 0);
470 for (i = 0; i < max_elems; i++)
472 values[i] = elems[i]->x = i;
473 ll_push_tail (&list, &elems[i]->ll);
474 check_list_contents (&list, values, i + 1);
477 /* Remove from tail. */
478 for (i = 0; i < max_elems; i++)
480 struct element *e = ll_to_element (ll_pop_tail (&list));
481 check (e->x == max_elems - i - 1);
482 check_list_contents (&list, values, max_elems - i - 1);
486 check_list_contents (&list, NULL, 0);
487 for (i = 0; i < max_elems; i++)
489 values[max_elems - i - 1] = elems[i]->x = max_elems - i - 1;
490 ll_push_head (&list, &elems[i]->ll);
491 check_list_contents (&list, &values[max_elems - i - 1], i + 1);
494 /* Remove from start. */
495 for (i = 0; i < max_elems; i++)
497 struct element *e = ll_to_element (ll_pop_head (&list));
498 check (e->x == (int) i);
499 check_list_contents (&list, &values[i + 1], max_elems - i - 1);
502 free_elements (max_elems, elems, NULL, values);
505 /* Tests insertion and removal at arbitrary positions. */
507 test_insert_remove (void)
509 const int max_elems = 16;
512 for (cnt = 0; cnt < max_elems; cnt++)
514 struct element **elems;
516 int *values = xnmalloc (cnt + 1, sizeof *values);
519 struct element extra;
522 allocate_ascending (cnt, &list, &elems, &elemp, NULL);
524 for (pos = 0; pos <= cnt; pos++)
528 ll_insert (elemp[pos], &extra.ll);
531 for (i = 0; i < pos; i++)
536 check_list_contents (&list, values, cnt + 1);
538 ll_remove (&extra.ll);
540 check_list_contents (&list, values, cnt);
542 free_elements (cnt, elems, elemp, values);
546 /* Tests swapping individual elements. */
550 const int max_elems = 8;
553 for (cnt = 0; cnt <= max_elems; cnt++)
556 struct element **elems;
561 allocate_ascending (cnt, &list, &elems, NULL, &values);
562 check_list_contents (&list, values, cnt);
564 for (i = 0; i < cnt; i++)
565 for (j = 0; j < cnt; j++)
566 for (k = 0; k < 2; k++)
570 ll_swap (&elems[i]->ll, &elems[j]->ll);
572 values[i] = values[j];
574 check_list_contents (&list, values, cnt);
577 free_elements (cnt, elems, NULL, values);
581 /* Tests swapping ranges of list elements. */
583 test_swap_range (void)
585 const int max_elems = 8;
586 int cnt, a0, a1, b0, b1, r;
588 for (cnt = 0; cnt <= max_elems; cnt++)
589 for (a0 = 0; a0 <= cnt; a0++)
590 for (a1 = a0; a1 <= cnt; a1++)
591 for (b0 = a1; b0 <= cnt; b0++)
592 for (b1 = b0; b1 <= cnt; b1++)
593 for (r = 0; r < 2; r++)
596 struct element **elems;
602 allocate_ascending (cnt, &list, &elems, &elemp, &values);
603 check_list_contents (&list, values, cnt);
606 for (i = 0; i < a0; i++)
608 for (i = b0; i < b1; i++)
610 for (i = a1; i < b0; i++)
612 for (i = a0; i < a1; i++)
614 for (i = b1; i < cnt; i++)
619 ll_swap_range (elemp[a0], elemp[a1], elemp[b0], elemp[b1]);
621 ll_swap_range (elemp[b0], elemp[b1], elemp[a0], elemp[a1]);
622 check_list_contents (&list, values, cnt);
624 free_elements (cnt, elems, elemp, values);
628 /* Tests removing ranges of list elements. */
630 test_remove_range (void)
632 const int max_elems = 8;
636 for (cnt = 0; cnt <= max_elems; cnt++)
637 for (r0 = 0; r0 <= cnt; r0++)
638 for (r1 = r0; r1 <= cnt; r1++)
641 struct element **elems;
647 allocate_ascending (cnt, &list, &elems, &elemp, &values);
648 check_list_contents (&list, values, cnt);
651 for (i = 0; i < r0; i++)
653 for (i = r1; i < cnt; i++)
656 ll_remove_range (elemp[r0], elemp[r1]);
657 check_list_contents (&list, values, j);
659 free_elements (cnt, elems, elemp, values);
663 /* Tests ll_remove_equal. */
665 test_remove_equal (void)
667 const int max_elems = 8;
669 int cnt, r0, r1, eq_pat;
671 for (cnt = 0; cnt <= max_elems; cnt++)
672 for (r0 = 0; r0 <= cnt; r0++)
673 for (r1 = r0; r1 <= cnt; r1++)
674 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
677 struct element **elems;
681 struct element to_remove;
685 allocate_elements (cnt, &list, &elems, &elemp, &values);
688 for (i = 0; i < cnt; i++)
690 int x = eq_pat & (1 << i) ? -1 : i;
691 bool delete = x == -1 && r0 <= i && i < r1;
694 values[remaining++] = x;
698 check ((int) ll_remove_equal (elemp[r0], elemp[r1], &to_remove.ll,
699 compare_elements, &aux_data)
701 check_list_contents (&list, values, remaining);
703 free_elements (cnt, elems, elemp, values);
707 /* Tests ll_remove_if. */
709 test_remove_if (void)
711 const int max_elems = 8;
713 int cnt, r0, r1, pattern;
715 for (cnt = 0; cnt <= max_elems; cnt++)
716 for (r0 = 0; r0 <= cnt; r0++)
717 for (r1 = r0; r1 <= cnt; r1++)
718 for (pattern = 0; pattern <= 1 << cnt; pattern++)
721 struct element **elems;
728 allocate_elements (cnt, &list, &elems, &elemp, &values);
731 for (i = 0; i < cnt; i++)
733 bool delete = (pattern & (1 << i)) && r0 <= i && i < r1;
736 values[remaining++] = i;
739 check ((int) ll_remove_if (elemp[r0], elemp[r1],
740 pattern_pred, &pattern)
742 check_list_contents (&list, values, remaining);
744 free_elements (cnt, elems, elemp, values);
748 /* Tests ll_moved. */
752 const int max_elems = 8;
756 for (cnt = 0; cnt <= max_elems; cnt++)
759 struct element **elems;
760 struct element **new_elems;
765 allocate_ascending (cnt, &list, &elems, NULL, &values);
766 allocate_elements (cnt, NULL, &new_elems, NULL, NULL);
767 check_list_contents (&list, values, cnt);
769 for (i = 0; i < cnt; i++)
771 *new_elems[i] = *elems[i];
772 ll_moved (&new_elems[i]->ll);
773 check_list_contents (&list, values, cnt);
776 free_elements (cnt, elems, NULL, values);
777 free_elements (cnt, new_elems, NULL, NULL);
781 /* Tests, via HELPER, a function that looks at list elements
782 equal to some specified element. */
784 test_examine_equal_range (void (*helper) (int r0, int r1, int eq_pat,
788 const int max_elems = 8;
790 int cnt, r0, r1, eq_pat;
792 for (cnt = 0; cnt <= max_elems; cnt++)
793 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
796 struct element **elems;
800 struct element to_find;
804 allocate_ascending (cnt, &list, &elems, &elemp, &values);
806 for (i = 0; i < cnt; i++)
807 if (eq_pat & (1 << i))
808 values[i] = elems[i]->x = -1;
811 for (r0 = 0; r0 <= cnt; r0++)
812 for (r1 = r0; r1 <= cnt; r1++)
813 helper (r0, r1, eq_pat, &to_find.ll, elemp);
815 check_list_contents (&list, values, cnt);
817 free_elements (cnt, elems, elemp, values);
821 /* Tests, via HELPER, a function that looks at list elements for
822 which a given predicate returns true. */
824 test_examine_if_range (void (*helper) (int r0, int r1, int eq_pat,
827 const int max_elems = 8;
829 int cnt, r0, r1, eq_pat;
831 for (cnt = 0; cnt <= max_elems; cnt++)
832 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
835 struct element **elems;
839 allocate_ascending (cnt, &list, &elems, &elemp, &values);
841 for (r0 = 0; r0 <= cnt; r0++)
842 for (r1 = r0; r1 <= cnt; r1++)
843 helper (r0, r1, eq_pat, elemp);
845 check_list_contents (&list, values, cnt);
847 free_elements (cnt, elems, elemp, values);
851 /* Helper function for testing ll_find_equal. */
853 test_find_equal_helper (int r0, int r1, int eq_pat,
854 struct ll *to_find, struct ll **elemp)
859 match = ll_find_equal (elemp[r0], elemp[r1], to_find,
860 compare_elements, &aux_data);
861 for (i = r0; i < r1; i++)
862 if (eq_pat & (1 << i))
865 check (match == elemp[i]);
868 /* Tests ll_find_equal. */
870 test_find_equal (void)
872 test_examine_equal_range (test_find_equal_helper);
875 /* Helper function for testing ll_find_if. */
877 test_find_if_helper (int r0, int r1, int eq_pat, struct ll **elemp)
879 struct ll *match = ll_find_if (elemp[r0], elemp[r1],
880 pattern_pred, &eq_pat);
883 for (i = r0; i < r1; i++)
884 if (eq_pat & (1 << i))
887 check (match == elemp[i]);
890 /* Tests ll_find_if. */
894 test_examine_if_range (test_find_if_helper);
897 /* Tests ll_find_adjacent_equal. */
899 test_find_adjacent_equal (void)
901 const int max_elems = 8;
905 for (cnt = 0; cnt <= max_elems; cnt++)
906 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
909 struct element **elems;
916 allocate_ascending (cnt, &list, &elems, &elemp, &values);
919 for (i = 0; i < cnt - 1; i++)
922 if (eq_pat & (1 << i))
924 values[i] = elems[i]->x = match;
925 values[i + 1] = elems[i + 1]->x = match;
931 for (i = 0; i <= cnt; i++)
933 struct ll *ll1 = ll_find_adjacent_equal (elemp[i], ll_null (&list),
939 ll2 = ll_null (&list);
940 for (j = i; j < cnt - 1; j++)
941 if (eq_pat & (1 << j))
948 check_list_contents (&list, values, cnt);
950 free_elements (cnt, elems, elemp, values);
954 /* Helper function for testing ll_count_range. */
956 test_count_range_helper (int r0, int r1, int eq_pat UNUSED, struct ll **elemp)
958 check ((int) ll_count_range (elemp[r0], elemp[r1]) == r1 - r0);
961 /* Tests ll_count_range. */
963 test_count_range (void)
965 test_examine_if_range (test_count_range_helper);
968 /* Helper function for testing ll_count_equal. */
970 test_count_equal_helper (int r0, int r1, int eq_pat,
971 struct ll *to_find, struct ll **elemp)
976 count1 = ll_count_equal (elemp[r0], elemp[r1], to_find,
977 compare_elements, &aux_data);
979 for (i = r0; i < r1; i++)
980 if (eq_pat & (1 << i))
983 check (count1 == count2);
986 /* Tests ll_count_equal. */
988 test_count_equal (void)
990 test_examine_equal_range (test_count_equal_helper);
993 /* Helper function for testing ll_count_if. */
995 test_count_if_helper (int r0, int r1, int eq_pat, struct ll **elemp)
1001 count1 = ll_count_if (elemp[r0], elemp[r1], pattern_pred, &eq_pat);
1004 for (i = r0; i < r1; i++)
1005 if (eq_pat & (1 << i))
1008 check (count1 == count2);
1011 /* Tests ll_count_if. */
1013 test_count_if (void)
1015 test_examine_if_range (test_count_if_helper);
1020 factorial (unsigned int n)
1022 unsigned int value = 1;
1028 /* Returns the number of permutations of the CNT values in
1029 VALUES. If VALUES contains duplicates, they must be
1032 expected_perms (int *values, size_t cnt)
1035 unsigned int perm_cnt;
1037 perm_cnt = factorial (cnt);
1038 for (i = 0; i < cnt; i = j)
1040 for (j = i + 1; j < cnt; j++)
1041 if (values[i] != values[j])
1043 perm_cnt /= factorial (j - i);
1048 /* Tests ll_min and ll_max. */
1052 const int max_elems = 6;
1055 for (cnt = 0; cnt <= max_elems; cnt++)
1057 struct ll_list list;
1058 struct element **elems;
1061 int *new_values = xnmalloc (cnt, sizeof *values);
1065 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1068 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1069 compare_elements, &aux_data))
1075 for (i = 0, x = ll_head (&list); x != ll_null (&list);
1076 x = ll_next (x), i++)
1078 struct element *e = ll_to_element (x);
1080 new_values[i] = e->x;
1082 for (r0 = 0; r0 <= cnt; r0++)
1083 for (r1 = r0; r1 <= cnt; r1++)
1085 struct ll *min = ll_min (elemp[r0], elemp[r1],
1086 compare_elements, &aux_data);
1087 struct ll *max = ll_max (elemp[r0], elemp[r1],
1088 compare_elements, &aux_data);
1091 check (min == elemp[r1]);
1092 check (max == elemp[r1]);
1096 int min_int, max_int;
1099 min_int = max_int = new_values[r0];
1100 for (i = r0; i < r1; i++)
1102 int value = new_values[i];
1103 if (value < min_int)
1105 if (value > max_int)
1108 check (min != elemp[r1]
1109 && ll_to_element (min)->x == min_int);
1110 check (max != elemp[r1]
1111 && ll_to_element (max)->x == max_int);
1116 check (perm_cnt == factorial (cnt));
1117 check_list_contents (&list, values, cnt);
1119 free_elements (cnt, elems, elemp, values);
1124 /* Tests ll_lexicographical_compare_3way. */
1126 test_lexicographical_compare_3way (void)
1128 const int max_elems = 4;
1130 int cnt_a, pat_a, cnt_b, pat_b;
1132 for (cnt_a = 0; cnt_a <= max_elems; cnt_a++)
1133 for (pat_a = 0; pat_a <= 1 << cnt_a; pat_a++)
1134 for (cnt_b = 0; cnt_b <= max_elems; cnt_b++)
1135 for (pat_b = 0; pat_b <= 1 << cnt_b; pat_b++)
1137 struct ll_list list_a, list_b;
1138 struct element **elems_a, **elems_b;
1139 struct ll **elemp_a, **elemp_b;
1140 int *values_a, *values_b;
1144 allocate_pattern (cnt_a, pat_a,
1145 &list_a, &elems_a, &elemp_a, &values_a);
1146 allocate_pattern (cnt_b, pat_b,
1147 &list_b, &elems_b, &elemp_b, &values_b);
1149 for (a0 = 0; a0 <= cnt_a; a0++)
1150 for (a1 = a0; a1 <= cnt_a; a1++)
1151 for (b0 = 0; b0 <= cnt_b; b0++)
1152 for (b1 = b0; b1 <= cnt_b; b1++)
1154 int a_ordering = lexicographical_compare_3way (
1155 values_a + a0, a1 - a0,
1156 values_b + b0, b1 - b0,
1158 compare_ints, NULL);
1160 int b_ordering = ll_lexicographical_compare_3way (
1161 elemp_a[a0], elemp_a[a1],
1162 elemp_b[b0], elemp_b[b1],
1163 compare_elements, &aux_data);
1165 check (a_ordering == b_ordering);
1168 free_elements (cnt_a, elems_a, elemp_a, values_a);
1169 free_elements (cnt_b, elems_b, elemp_b, values_b);
1173 /* Appends the `x' value in element E to the array pointed to by
1174 NEXT_OUTPUT, and advances NEXT_OUTPUT to the next position. */
1176 apply_func (struct ll *e_, void *next_output_)
1178 struct element *e = ll_to_element (e_);
1179 int **next_output = next_output_;
1181 *(*next_output)++ = e->x;
1184 /* Tests ll_apply. */
1188 const int max_elems = 8;
1192 for (cnt = 0; cnt <= max_elems; cnt++)
1193 for (r0 = 0; r0 <= cnt; r0++)
1194 for (r1 = r0; r1 <= cnt; r1++)
1196 struct ll_list list;
1197 struct element **elems;
1206 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1207 check_list_contents (&list, values, cnt);
1209 output = next_output = xnmalloc (cnt, sizeof *output);
1210 ll_apply (elemp[r0], elemp[r1], apply_func, &next_output);
1211 check_list_contents (&list, values, cnt);
1213 check (r1 - r0 == next_output - output);
1214 for (i = 0; i < r1 - r0; i++)
1215 check (output[i] == r0 + i);
1217 free_elements (cnt, elems, elemp, values);
1222 /* Tests ll_reverse. */
1226 const int max_elems = 8;
1230 for (cnt = 0; cnt <= max_elems; cnt++)
1231 for (r0 = 0; r0 <= cnt; r0++)
1232 for (r1 = r0; r1 <= cnt; r1++)
1234 struct ll_list list;
1235 struct element **elems;
1241 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1242 check_list_contents (&list, values, cnt);
1245 for (i = 0; i < r0; i++)
1247 for (i = r1 - 1; i >= r0; i--)
1249 for (i = r1; i < cnt; i++)
1252 ll_reverse (elemp[r0], elemp[r1]);
1253 check_list_contents (&list, values, cnt);
1255 free_elements (cnt, elems, elemp, values);
1259 /* Tests ll_next_permutation and ll_prev_permutation when the
1260 permuted values have no duplicates. */
1262 test_permutations_no_dups (void)
1264 const int max_elems = 8;
1267 for (cnt = 0; cnt <= max_elems; cnt++)
1269 struct ll_list list;
1270 struct element **elems;
1272 int *old_values = xnmalloc (cnt, sizeof *values);
1273 int *new_values = xnmalloc (cnt, sizeof *values);
1277 allocate_ascending (cnt, &list, &elems, NULL, &values);
1280 extract_values (&list, old_values, cnt);
1281 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1282 compare_elements, &aux_data))
1284 extract_values (&list, new_values, cnt);
1285 check (lexicographical_compare_3way (new_values, cnt,
1288 compare_ints, NULL) > 0);
1289 memcpy (old_values, new_values, (cnt) * sizeof *old_values);
1292 check (perm_cnt == factorial (cnt));
1293 check_list_contents (&list, values, cnt);
1296 ll_reverse (ll_head (&list), ll_null (&list));
1297 extract_values (&list, old_values, cnt);
1298 while (ll_prev_permutation (ll_head (&list), ll_null (&list),
1299 compare_elements, &aux_data))
1301 extract_values (&list, new_values, cnt);
1302 check (lexicographical_compare_3way (new_values, cnt,
1305 compare_ints, NULL) < 0);
1306 memcpy (old_values, new_values, (cnt) * sizeof *old_values);
1309 check (perm_cnt == factorial (cnt));
1310 ll_reverse (ll_head (&list), ll_null (&list));
1311 check_list_contents (&list, values, cnt);
1313 free_elements (cnt, elems, NULL, values);
1319 /* Tests ll_next_permutation and ll_prev_permutation when the
1320 permuted values contain duplicates. */
1322 test_permutations_with_dups (void)
1324 const int max_elems = 8;
1325 const int max_dup = 3;
1326 const int repetitions = 1024;
1330 for (repeat = 0; repeat < repetitions; repeat++)
1331 for (cnt = 0; cnt < max_elems; cnt++)
1333 struct ll_list list;
1334 struct element **elems;
1336 int *old_values = xnmalloc (max_elems, sizeof *values);
1337 int *new_values = xnmalloc (max_elems, sizeof *values);
1339 unsigned int permutation_cnt;
1343 allocate_elements (cnt, &list, &elems, NULL, &values);
1348 int max = left < max_dup ? left : max_dup;
1349 int n = rand () % max + 1;
1352 int idx = cnt - left--;
1353 values[idx] = elems[idx]->x = value;
1358 permutation_cnt = 1;
1359 extract_values (&list, old_values, cnt);
1360 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1361 compare_elements, &aux_data))
1363 extract_values (&list, new_values, cnt);
1364 check (lexicographical_compare_3way (new_values, cnt,
1367 compare_ints, NULL) > 0);
1368 memcpy (old_values, new_values, cnt * sizeof *old_values);
1371 check (permutation_cnt == expected_perms (values, cnt));
1372 check_list_contents (&list, values, cnt);
1374 permutation_cnt = 1;
1375 ll_reverse (ll_head (&list), ll_null (&list));
1376 extract_values (&list, old_values, cnt);
1377 while (ll_prev_permutation (ll_head (&list), ll_null (&list),
1378 compare_elements, &aux_data))
1380 extract_values (&list, new_values, cnt);
1381 check (lexicographical_compare_3way (new_values, cnt,
1384 compare_ints, NULL) < 0);
1387 ll_reverse (ll_head (&list), ll_null (&list));
1388 check (permutation_cnt == expected_perms (values, cnt));
1389 check_list_contents (&list, values, cnt);
1391 free_elements (cnt, elems, NULL, values);
1397 /* Tests ll_merge when no equal values are to be merged. */
1399 test_merge_no_dups (void)
1401 const int max_elems = 8;
1402 const int max_filler = 3;
1404 int merge_cnt, pattern, pfx, gap, sfx, order;
1406 for (merge_cnt = 0; merge_cnt < max_elems; merge_cnt++)
1407 for (pattern = 0; pattern <= (1 << merge_cnt); pattern++)
1408 for (pfx = 0; pfx < max_filler; pfx++)
1409 for (gap = 0; gap < max_filler; gap++)
1410 for (sfx = 0; sfx < max_filler; sfx++)
1411 for (order = 0; order < 2; order++)
1413 struct ll_list list;
1414 struct element **elems;
1418 int list_cnt = pfx + merge_cnt + gap + sfx;
1422 allocate_elements (list_cnt, &list,
1423 &elems, &elemp, &values);
1426 for (i = 0; i < pfx; i++)
1427 elems[j++]->x = 100 + i;
1429 for (i = 0; i < merge_cnt; i++)
1430 if (pattern & (1u << i))
1433 for (i = 0; i < gap; i++)
1434 elems[j++]->x = 200 + i;
1436 for (i = 0; i < merge_cnt; i++)
1437 if (!(pattern & (1u << i)))
1440 for (i = 0; i < sfx; i++)
1441 elems[j++]->x = 300 + i;
1442 check (list_cnt == j);
1445 for (i = 0; i < pfx; i++)
1446 values[j++] = 100 + i;
1448 for (i = 0; i < merge_cnt; i++)
1450 for (i = 0; i < gap; i++)
1451 values[j++] = 200 + i;
1453 for (i = 0; i < merge_cnt; i++)
1455 for (i = 0; i < sfx; i++)
1456 values[j++] = 300 + i;
1457 check (list_cnt == j);
1460 ll_merge (elemp[a0], elemp[a1], elemp[b0], elemp[b1],
1461 compare_elements, &aux_data);
1463 ll_merge (elemp[b0], elemp[b1], elemp[a0], elemp[a1],
1464 compare_elements, &aux_data);
1466 check_list_contents (&list, values, list_cnt);
1468 free_elements (list_cnt, elems, elemp, values);
1472 /* Tests ll_merge when equal values are to be merged. */
1474 test_merge_with_dups (void)
1476 const int max_elems = 8;
1478 int cnt, merge_pat, inc_pat, order;
1480 for (cnt = 0; cnt <= max_elems; cnt++)
1481 for (merge_pat = 0; merge_pat <= (1 << cnt); merge_pat++)
1482 for (inc_pat = 0; inc_pat <= (1 << cnt); inc_pat++)
1483 for (order = 0; order < 2; order++)
1485 struct ll_list list;
1486 struct element **elems;
1493 allocate_elements (cnt, &list, &elems, &elemp, &values);
1496 for (i = k = 0; i < cnt; i++)
1498 if (merge_pat & (1u << i))
1500 if (inc_pat & (1u << i))
1504 for (i = k = 0; i < cnt; i++)
1506 if (!(merge_pat & (1u << i)))
1508 if (inc_pat & (1u << i))
1515 for (i = 0; i < cnt; i++)
1520 for (i = 0; i < mid; i++)
1521 elems[i]->y = 100 + i;
1522 for (i = mid; i < cnt; i++)
1527 for (i = k = 0; i < cnt; i++)
1530 if (inc_pat & (1u << i))
1536 ll_merge (elemp[0], elemp[mid], elemp[mid], elemp[cnt],
1537 compare_elements, &aux_data);
1539 ll_merge (elemp[mid], elemp[cnt], elemp[0], elemp[mid],
1540 compare_elements, &aux_data);
1542 check_list_contents (&list, values, cnt);
1543 check (ll_is_sorted (ll_head (&list), ll_null (&list),
1544 compare_elements_x_y, &aux_data));
1546 free_elements (cnt, elems, elemp, values);
1550 /* Tests ll_sort on all permutations up to a maximum number of
1553 test_sort_exhaustive (void)
1555 const int max_elems = 8;
1558 for (cnt = 0; cnt <= max_elems; cnt++)
1560 struct ll_list list;
1561 struct element **elems;
1564 struct element **perm_elems;
1569 allocate_ascending (cnt, &list, &elems, NULL, &values);
1570 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1573 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1574 compare_elements, &aux_data))
1576 struct ll_list perm_list;
1579 extract_values (&list, perm_values, cnt);
1580 ll_init (&perm_list);
1581 for (j = 0; j < cnt; j++)
1583 perm_elems[j]->x = perm_values[j];
1584 ll_push_tail (&perm_list, &perm_elems[j]->ll);
1586 ll_sort (ll_head (&perm_list), ll_null (&perm_list),
1587 compare_elements, &aux_data);
1588 check_list_contents (&perm_list, values, cnt);
1589 check (ll_is_sorted (ll_head (&perm_list), ll_null (&perm_list),
1590 compare_elements, &aux_data));
1593 check (perm_cnt == factorial (cnt));
1595 free_elements (cnt, elems, NULL, values);
1596 free_elements (cnt, perm_elems, NULL, perm_values);
1600 /* Tests that ll_sort is stable in the presence of equal
1603 test_sort_stable (void)
1605 const int max_elems = 6;
1608 for (cnt = 0; cnt <= max_elems; cnt++)
1609 for (inc_pat = 0; inc_pat <= 1 << cnt; inc_pat++)
1611 struct ll_list list;
1612 struct element **elems;
1615 struct element **perm_elems;
1621 allocate_elements (cnt, &list, &elems, NULL, &values);
1622 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1625 for (i = 0; i < cnt; i++)
1627 elems[i]->x = values[i] = j;
1628 if (inc_pat & (1 << i))
1634 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1635 compare_elements_y, &aux_data))
1637 struct ll_list perm_list;
1639 extract_values (&list, perm_values, cnt);
1640 ll_init (&perm_list);
1641 for (i = 0; i < cnt; i++)
1643 perm_elems[i]->x = perm_values[i];
1644 perm_elems[i]->y = i;
1645 ll_push_tail (&perm_list, &perm_elems[i]->ll);
1647 ll_sort (ll_head (&perm_list), ll_null (&perm_list),
1648 compare_elements, &aux_data);
1649 check_list_contents (&perm_list, values, cnt);
1650 check (ll_is_sorted (ll_head (&perm_list), ll_null (&perm_list),
1651 compare_elements_x_y, &aux_data));
1654 check (perm_cnt == factorial (cnt));
1656 free_elements (cnt, elems, NULL, values);
1657 free_elements (cnt, perm_elems, NULL, perm_values);
1661 /* Tests that ll_sort does not disturb elements outside the
1664 test_sort_subset (void)
1666 const int max_elems = 8;
1668 int cnt, r0, r1, repeat;
1670 for (cnt = 0; cnt <= max_elems; cnt++)
1671 for (repeat = 0; repeat < 100; repeat++)
1672 for (r0 = 0; r0 <= cnt; r0++)
1673 for (r1 = r0; r1 <= cnt; r1++)
1675 struct ll_list list;
1676 struct element **elems;
1680 allocate_random (cnt, &list, &elems, &elemp, &values);
1682 qsort (&values[r0], r1 - r0, sizeof *values, compare_ints_noaux);
1683 ll_sort (elemp[r0], elemp[r1], compare_elements, &aux_data);
1684 check_list_contents (&list, values, cnt);
1686 free_elements (cnt, elems, elemp, values);
1690 /* Tests that ll_sort works with large lists. */
1692 test_sort_big (void)
1694 const int max_elems = 1024;
1698 for (cnt = 0; cnt < max_elems; cnt++)
1700 struct ll_list list;
1701 struct element **elems;
1704 allocate_random (cnt, &list, &elems, NULL, &values);
1706 qsort (values, cnt, sizeof *values, compare_ints_noaux);
1707 ll_sort (ll_head (&list), ll_null (&list), compare_elements, &aux_data);
1708 check_list_contents (&list, values, cnt);
1710 free_elements (cnt, elems, NULL, values);
1714 /* Tests ll_unique. */
1718 const int max_elems = 10;
1720 int *ascending = xnmalloc (max_elems, sizeof *ascending);
1722 int cnt, inc_pat, i, j, unique_values;
1724 for (i = 0; i < max_elems; i++)
1727 for (cnt = 0; cnt < max_elems; cnt++)
1728 for (inc_pat = 0; inc_pat < (1 << cnt); inc_pat++)
1730 struct ll_list list, dups;
1731 struct element **elems;
1734 allocate_elements (cnt, &list, &elems, NULL, &values);
1736 j = unique_values = 0;
1737 for (i = 0; i < cnt; i++)
1739 unique_values = j + 1;
1740 elems[i]->x = values[i] = j;
1741 if (inc_pat & (1 << i))
1744 check_list_contents (&list, values, cnt);
1747 check (ll_unique (ll_head (&list), ll_null (&list), ll_null (&dups),
1748 compare_elements, &aux_data)
1749 == (size_t) unique_values);
1750 check_list_contents (&list, ascending, unique_values);
1752 ll_splice (ll_null (&list), ll_head (&dups), ll_null (&dups));
1753 ll_sort (ll_head (&list), ll_null (&list), compare_elements, &aux_data);
1754 check_list_contents (&list, values, cnt);
1756 free_elements (cnt, elems, NULL, values);
1762 /* Tests ll_sort_unique. */
1764 test_sort_unique (void)
1766 const int max_elems = 7;
1769 for (cnt = 0; cnt <= max_elems; cnt++)
1770 for (inc_pat = 0; inc_pat <= 1 << cnt; inc_pat++)
1772 struct ll_list list;
1773 struct element **elems;
1776 struct element **perm_elems;
1785 allocate_elements (cnt, &list, &elems, NULL, &values);
1786 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1789 for (i = 0; i < cnt; i++)
1791 elems[i]->x = values[i] = j;
1793 if (inc_pat & (1 << i))
1797 unique_values = xnmalloc (unique_cnt, sizeof *unique_values);
1798 for (i = 0; i < unique_cnt; i++)
1799 unique_values[i] = i;
1802 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1803 compare_elements, &aux_data))
1805 struct ll_list perm_list;
1807 extract_values (&list, perm_values, cnt);
1808 ll_init (&perm_list);
1809 for (i = 0; i < cnt; i++)
1811 perm_elems[i]->x = perm_values[i];
1812 perm_elems[i]->y = i;
1813 ll_push_tail (&perm_list, &perm_elems[i]->ll);
1815 ll_sort_unique (ll_head (&perm_list), ll_null (&perm_list), NULL,
1816 compare_elements, &aux_data);
1817 check_list_contents (&perm_list, unique_values, unique_cnt);
1818 check (ll_is_sorted (ll_head (&perm_list), ll_null (&perm_list),
1819 compare_elements_x_y, &aux_data));
1822 check (perm_cnt == expected_perms (values, cnt));
1824 free_elements (cnt, elems, NULL, values);
1825 free_elements (cnt, perm_elems, NULL, perm_values);
1826 free (unique_values);
1830 /* Tests ll_insert_ordered. */
1832 test_insert_ordered (void)
1834 const int max_elems = 6;
1837 for (cnt = 0; cnt <= max_elems; cnt++)
1838 for (inc_pat = 0; inc_pat <= 1 << cnt; inc_pat++)
1840 struct ll_list list;
1841 struct element **elems;
1844 struct element **perm_elems;
1850 allocate_elements (cnt, &list, &elems, NULL, &values);
1851 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1854 for (i = 0; i < cnt; i++)
1856 elems[i]->x = values[i] = j;
1857 if (inc_pat & (1 << i))
1863 while (ll_next_permutation (ll_head (&list), ll_null (&list),
1864 compare_elements_y, &aux_data))
1866 struct ll_list perm_list;
1868 extract_values (&list, perm_values, cnt);
1869 ll_init (&perm_list);
1870 for (i = 0; i < cnt; i++)
1872 perm_elems[i]->x = perm_values[i];
1873 perm_elems[i]->y = i;
1874 ll_insert_ordered (ll_head (&perm_list), ll_null (&perm_list),
1876 compare_elements, &aux_data);
1878 check (ll_is_sorted (ll_head (&perm_list), ll_null (&perm_list),
1879 compare_elements_x_y, &aux_data));
1882 check (perm_cnt == factorial (cnt));
1884 free_elements (cnt, elems, NULL, values);
1885 free_elements (cnt, perm_elems, NULL, perm_values);
1889 /* Tests ll_partition. */
1891 test_partition (void)
1893 const int max_elems = 10;
1899 for (cnt = 0; cnt < max_elems; cnt++)
1900 for (r0 = 0; r0 <= cnt; r0++)
1901 for (r1 = r0; r1 <= cnt; r1++)
1902 for (pbase = 0; pbase <= (1u << (r1 - r0)); pbase++)
1904 struct ll_list list;
1905 struct element **elems;
1909 unsigned int pattern = pbase << r0;
1914 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1916 /* Check that ll_find_partition works okay in every
1917 case. We use it after partitioning, too, but that
1918 only tests cases where it returns non-null. */
1919 for (i = r0; i < r1; i++)
1920 if (!(pattern & (1u << i)))
1924 if (pattern & (1u << i))
1926 part_ll = ll_find_partition (elemp[r0], elemp[r1],
1930 check (part_ll == elemp[j]);
1932 check (part_ll == NULL);
1934 /* Figure out expected results. */
1937 for (i = 0; i < r0; i++)
1939 for (i = r0; i < r1; i++)
1940 if (pattern & (1u << i))
1942 for (i = r0; i < r1; i++)
1943 if (!(pattern & (1u << i)))
1945 if (first_false == -1)
1949 if (first_false == -1)
1951 for (i = r1; i < cnt; i++)
1955 /* Partition and check for expected results. */
1956 check (ll_partition (elemp[r0], elemp[r1],
1957 pattern_pred, &pattern)
1958 == elemp[first_false]);
1959 check (ll_find_partition (elemp[r0], elemp[r1],
1960 pattern_pred, &pattern)
1961 == elemp[first_false]);
1962 check_list_contents (&list, values, cnt);
1963 check ((int) ll_count (&list) == cnt);
1965 free_elements (cnt, elems, elemp, values);
1974 const char *description;
1975 void (*function) (void);
1978 static const struct test tests[] =
2031 "find-adjacent-equal",
2032 "find_adjacent_equal",
2033 test_find_adjacent_equal
2056 "lexicographical-compare-3way",
2057 "lexicographical_compare_3way",
2058 test_lexicographical_compare_3way
2071 "permutations-no-dups",
2072 "permutations (no dups)",
2073 test_permutations_no_dups
2076 "permutations-with-dups",
2077 "permutations (with dups)",
2078 test_permutations_with_dups
2087 "merge (with dups)",
2088 test_merge_with_dups
2092 "sort (exhaustive)",
2093 test_sort_exhaustive
2132 enum { N_TESTS = sizeof tests / sizeof *tests };
2135 main (int argc, char *argv[])
2141 fprintf (stderr, "exactly one argument required; use --help for help\n");
2142 return EXIT_FAILURE;
2144 else if (!strcmp (argv[1], "--help"))
2146 printf ("%s: test doubly linked list (ll) library\n"
2147 "usage: %s TEST-NAME\n"
2148 "where TEST-NAME is one of the following:\n",
2150 for (i = 0; i < N_TESTS; i++)
2151 printf (" %s\n %s\n", tests[i].name, tests[i].description);
2156 for (i = 0; i < N_TESTS; i++)
2157 if (!strcmp (argv[1], tests[i].name))
2159 tests[i].function ();
2163 fprintf (stderr, "unknown test %s; use --help for help\n", argv[1]);
2164 return EXIT_FAILURE;