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
26 See ll-test.c for a similar program for the ll_* routines. */
32 #include <libpspp/llx.h>
38 /* Support preliminaries. */
39 #if __GNUC__ >= 2 && !defined UNUSED
40 #define UNUSED __attribute__ ((unused))
45 /* Exit with a failure code.
46 (Place a breakpoint on this function while debugging.) */
53 /* If OK is not true, prints a message about failure on the
54 current source file and the given LINE and terminates. */
56 check_func (bool ok, int line)
60 fprintf (stderr, "%s:%d: check failed\n", __FILE__, line);
65 /* Verifies that EXPR evaluates to true.
66 If not, prints a message citing the calling line number and
68 #define check(EXPR) check_func ((EXPR), __LINE__)
70 /* Prints a message about memory exhaustion and exits with a
75 printf ("virtual memory exhausted\n");
79 /* Allocates and returns N bytes of memory. */
95 /* Allocates and returns N * M bytes of memory. */
97 xnmalloc (size_t n, size_t m)
99 if ((size_t) -1 / m <= n)
101 return xmalloc (n * m);
104 /* Always returns a null pointer, failing allocation. */
106 null_allocate_node (void *aux UNUSED)
113 null_release_node (struct llx *llx UNUSED, void *aux UNUSED)
117 /* Memory manager that fails all allocations and does nothing on
119 static const struct llx_manager llx_null_mgr =
126 /* List type and support routines. */
128 /* Test data element. */
131 int x; /* Primary value. */
132 int y; /* Secondary value. */
137 /* Prints the elements in LIST. */
139 print_list (struct llx_list *list)
144 for (x = llx_head (list); x != llx_null (list); x = llx_next (x))
146 const struct element *e = llx_data (x);
147 printf (" %d", e->x);
152 /* Prints the value returned by PREDICATE given auxiliary data
153 AUX for each element in LIST. */
155 print_pred (struct llx_list *list,
156 llx_predicate_func *predicate, void *aux UNUSED)
161 for (x = llx_head (list); x != llx_null (list); x = llx_next (x))
162 printf (" %d", predicate (x, aux));
166 /* Prints the CNT numbers in VALUES. */
168 print_array (int values[], size_t cnt)
173 for (i = 0; i < cnt; i++)
174 printf (" %d", values[i]);
178 /* Compares the `x' values in A and B and returns a strcmp-type
179 return value. Verifies that AUX points to aux_data. */
181 compare_elements (const void *a_, const void *b_, void *aux)
183 const struct element *a = a_;
184 const struct element *b = b_;
186 check (aux == &aux_data);
187 return a->x < b->x ? -1 : a->x > b->x;
190 /* Compares the `x' and `y' values in A and B and returns a
191 strcmp-type return value. Verifies that AUX points to
194 compare_elements_x_y (const void *a_, const void *b_, void *aux)
196 const struct element *a = a_;
197 const struct element *b = b_;
199 check (aux == &aux_data);
201 return a->x < b->x ? -1 : 1;
202 else if (a->y != b->y)
203 return a->y < b->y ? -1 : 1;
208 /* Compares the `y' values in A and B and returns a strcmp-type
209 return value. Verifies that AUX points to aux_data. */
211 compare_elements_y (const void *a_, const void *b_, void *aux)
213 const struct element *a = a_;
214 const struct element *b = b_;
216 check (aux == &aux_data);
217 return a->y < b->y ? -1 : a->y > b->y;
220 /* Returns true if the bit in *PATTERN indicated by `x in
221 *ELEMENT is set, false otherwise. */
223 pattern_pred (const void *element_, void *pattern_)
225 const struct element *element = element_;
226 unsigned int *pattern = pattern_;
228 return (*pattern & (1u << element->x)) != 0;
231 /* Allocates N elements in *ELEMS.
232 Adds the elements to LIST, if it is nonnull.
233 Puts pointers to the elements' list elements in *ELEMP,
234 followed by a pointer to the list null element, if ELEMP is
236 Allocates space for N values in *VALUES, if VALUES is
239 allocate_elements (size_t n,
240 struct llx_list *list,
241 struct element ***elems,
250 *elems = xnmalloc (n, sizeof **elems);
253 *elemp = xnmalloc (n + 1, sizeof *elemp);
254 (*elemp)[n] = llx_null (list);
257 for (i = 0; i < n; i++)
259 (*elems)[i] = xmalloc (sizeof ***elems);
262 struct llx *llx = llx_push_tail (list, (*elems)[i], &llx_malloc_mgr);
269 *values = xnmalloc (n, sizeof *values);
272 /* Copies the CNT values of `x' from LIST into VALUES[]. */
274 extract_values (struct llx_list *list, int values[], size_t cnt)
278 check (llx_count (list) == cnt);
279 for (x = llx_head (list); x != llx_null (list); x = llx_next (x))
281 struct element *e = llx_data (x);
286 /* As allocate_elements, but sets ascending values, starting
287 from 0, in `x' values in *ELEMS and in *VALUES (if
290 allocate_ascending (size_t n,
291 struct llx_list *list,
292 struct element ***elems,
298 allocate_elements (n, list, elems, elemp, values);
300 for (i = 0; i < n; i++)
303 extract_values (list, *values, n);
306 /* As allocate_elements, but sets binary values extracted from
307 successive bits in PATTERN in `x' values in *ELEMS and in
308 *VALUES (if nonnull). */
310 allocate_pattern (size_t n,
312 struct llx_list *list,
313 struct element ***elems,
319 allocate_elements (n, list, elems, elemp, values);
321 for (i = 0; i < n; i++)
322 (*elems)[i]->x = (pattern & (1 << i)) != 0;
324 extract_values (list, *values, n);
327 /* Randomly shuffles the CNT elements in ARRAY, each of which is
328 SIZE bytes in size. */
330 random_shuffle (void *array_, size_t cnt, size_t size)
332 char *array = array_;
333 char *tmp = xmalloc (size);
336 for (i = 0; i < cnt; i++)
338 size_t j = rand () % (cnt - i) + i;
341 memcpy (tmp, array + j * size, size);
342 memcpy (array + j * size, array + i * size, size);
343 memcpy (array + i * size, tmp, size);
350 /* As allocate_ascending, but orders the values randomly. */
352 allocate_random (size_t n,
353 struct llx_list *list,
354 struct element ***elems,
360 allocate_elements (n, list, elems, elemp, values);
362 for (i = 0; i < n; i++)
364 random_shuffle (*elems, n, sizeof **elems);
366 extract_values (list, *values, n);
369 /* Frees LIST, the N elements of ELEMS, ELEMP, and VALUES. */
371 free_elements (size_t n,
372 struct llx_list *list,
373 struct element **elems,
380 llx_destroy (list, NULL, NULL, &llx_malloc_mgr);
381 for (i = 0; i < n; i++)
388 /* Compares A and B and returns a strcmp-type return value. */
390 compare_ints (const void *a_, const void *b_, void *aux UNUSED)
395 return *a < *b ? -1 : *a > *b;
398 /* Compares A and B and returns a strcmp-type return value. */
400 compare_ints_noaux (const void *a_, const void *b_)
405 return *a < *b ? -1 : *a > *b;
408 /* Checks that LIST contains the CNT values in ELEMENTS. */
410 check_list_contents (struct llx_list *list, int elements[], size_t cnt)
415 check ((cnt == 0) == llx_is_empty (list));
417 /* Iterate in forward order. */
418 for (llx = llx_head (list), i = 0; i < cnt; llx = llx_next (llx), i++)
420 struct element *e = llx_data (llx);
421 check (elements[i] == e->x);
422 check (llx != llx_null (list));
424 check (llx == llx_null (list));
426 /* Iterate in reverse order. */
427 for (llx = llx_tail (list), i = 0; i < cnt; llx = llx_prev (llx), i++)
429 struct element *e = llx_data (llx);
430 check (elements[cnt - i - 1] == e->x);
431 check (llx != llx_null (list));
433 check (llx == llx_null (list));
435 check (llx_count (list) == cnt);
438 /* Lexicographicallxy compares ARRAY1, which contains COUNT1
439 elements of SIZE bytes each, to ARRAY2, which contains COUNT2
440 elements of SIZE bytes, according to COMPARE. Returns a
441 strcmp-type result. AUX is passed to COMPARE as auxiliary
444 lexicographical_compare_3way (const void *array1, size_t count1,
445 const void *array2, size_t count2,
447 int (*compare) (const void *, const void *,
451 const char *first1 = array1;
452 const char *first2 = array2;
453 size_t min_count = count1 < count2 ? count1 : count2;
455 while (min_count > 0)
457 int cmp = compare (first1, first2, aux);
466 return count1 < count2 ? -1 : count1 > count2;
471 /* Tests list push and pop operations. */
475 const int max_elems = 1024;
477 struct llx_list list;
478 struct element **elems;
483 allocate_elements (max_elems, NULL, &elems, NULL, &values);
487 check_list_contents (&list, NULL, 0);
488 for (i = 0; i < max_elems; i++)
490 values[i] = elems[i]->x = i;
491 llx_push_tail (&list, elems[i], &llx_malloc_mgr);
492 check_list_contents (&list, values, i + 1);
495 /* Remove from tail. */
496 for (i = 0; i < max_elems; i++)
498 struct element *e = llx_pop_tail (&list, &llx_malloc_mgr);
499 check (e->x == max_elems - i - 1);
500 check_list_contents (&list, values, max_elems - i - 1);
504 check_list_contents (&list, NULL, 0);
505 for (i = 0; i < max_elems; i++)
507 values[max_elems - i - 1] = elems[i]->x = max_elems - i - 1;
508 llx_push_head (&list, elems[i], &llx_malloc_mgr);
509 check_list_contents (&list, &values[max_elems - i - 1], i + 1);
512 /* Remove from start. */
513 for (i = 0; i < max_elems; i++)
515 struct element *e = llx_pop_head (&list, &llx_malloc_mgr);
516 check (e->x == (int) i);
517 check_list_contents (&list, &values[i + 1], max_elems - i - 1);
520 free_elements (max_elems, &list, elems, NULL, values);
523 /* Tests insertion and removal at arbitrary positions. */
525 test_insert_remove (void)
527 const int max_elems = 16;
530 for (cnt = 0; cnt < max_elems; cnt++)
532 struct element **elems;
534 int *values = xnmalloc (cnt + 1, sizeof *values);
536 struct llx_list list;
537 struct element extra;
538 struct llx *extra_llx;
541 allocate_ascending (cnt, &list, &elems, &elemp, NULL);
543 for (pos = 0; pos <= cnt; pos++)
547 extra_llx = llx_insert (elemp[pos], &extra, &llx_malloc_mgr);
548 check (extra_llx != NULL);
551 for (i = 0; i < pos; i++)
556 check_list_contents (&list, values, cnt + 1);
558 llx_remove (extra_llx, &llx_malloc_mgr);
560 check_list_contents (&list, values, cnt);
562 free_elements (cnt, &list, elems, elemp, values);
566 /* Tests swapping individual elements. */
570 const int max_elems = 8;
573 for (cnt = 0; cnt <= max_elems; cnt++)
575 struct llx_list list;
576 struct element **elems;
582 allocate_ascending (cnt, &list, &elems, &elemp, &values);
583 check_list_contents (&list, values, cnt);
585 for (i = 0; i < cnt; i++)
586 for (j = 0; j < cnt; j++)
587 for (k = 0; k < 2; k++)
591 llx_swap (elemp[i], elemp[j]);
593 values[i] = values[j];
595 check_list_contents (&list, values, cnt);
598 free_elements (cnt, &list, elems, elemp, values);
602 /* Tests swapping ranges of list elements. */
604 test_swap_range (void)
606 const int max_elems = 8;
607 int cnt, a0, a1, b0, b1, r;
609 for (cnt = 0; cnt <= max_elems; cnt++)
610 for (a0 = 0; a0 <= cnt; a0++)
611 for (a1 = a0; a1 <= cnt; a1++)
612 for (b0 = a1; b0 <= cnt; b0++)
613 for (b1 = b0; b1 <= cnt; b1++)
614 for (r = 0; r < 2; r++)
616 struct llx_list list;
617 struct element **elems;
623 allocate_ascending (cnt, &list, &elems, &elemp, &values);
624 check_list_contents (&list, values, cnt);
627 for (i = 0; i < a0; i++)
629 for (i = b0; i < b1; i++)
631 for (i = a1; i < b0; i++)
633 for (i = a0; i < a1; i++)
635 for (i = b1; i < cnt; i++)
640 llx_swap_range (elemp[a0], elemp[a1], elemp[b0], elemp[b1]);
642 llx_swap_range (elemp[b0], elemp[b1], elemp[a0], elemp[a1]);
643 check_list_contents (&list, values, cnt);
645 free_elements (cnt, &list, elems, elemp, values);
649 /* Tests removing ranges of list elements. */
651 test_remove_range (void)
653 const int max_elems = 8;
657 for (cnt = 0; cnt <= max_elems; cnt++)
658 for (r0 = 0; r0 <= cnt; r0++)
659 for (r1 = r0; r1 <= cnt; r1++)
661 struct llx_list list;
662 struct element **elems;
668 allocate_ascending (cnt, &list, &elems, &elemp, &values);
669 check_list_contents (&list, values, cnt);
672 for (i = 0; i < r0; i++)
674 for (i = r1; i < cnt; i++)
677 llx_remove_range (elemp[r0], elemp[r1], &llx_malloc_mgr);
678 check_list_contents (&list, values, j);
680 free_elements (cnt, &list, elems, elemp, values);
684 /* Tests llx_remove_equal. */
686 test_remove_equal (void)
688 const int max_elems = 8;
690 int cnt, r0, r1, eq_pat;
692 for (cnt = 0; cnt <= max_elems; cnt++)
693 for (r0 = 0; r0 <= cnt; r0++)
694 for (r1 = r0; r1 <= cnt; r1++)
695 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
697 struct llx_list list;
698 struct element **elems;
702 struct element to_remove;
706 allocate_elements (cnt, &list, &elems, &elemp, &values);
709 for (i = 0; i < cnt; i++)
711 int x = eq_pat & (1 << i) ? -1 : i;
712 bool delete = x == -1 && r0 <= i && i < r1;
715 values[remaining++] = x;
719 check ((int) llx_remove_equal (elemp[r0], elemp[r1], &to_remove,
720 compare_elements, &aux_data,
723 check_list_contents (&list, values, remaining);
725 free_elements (cnt, &list, elems, elemp, values);
729 /* Tests llx_remove_if. */
731 test_remove_if (void)
733 const int max_elems = 8;
735 int cnt, r0, r1, pattern;
737 for (cnt = 0; cnt <= max_elems; cnt++)
738 for (r0 = 0; r0 <= cnt; r0++)
739 for (r1 = r0; r1 <= cnt; r1++)
740 for (pattern = 0; pattern <= 1 << cnt; pattern++)
742 struct llx_list list;
743 struct element **elems;
750 allocate_ascending (cnt, &list, &elems, &elemp, &values);
753 for (i = 0; i < cnt; i++)
755 bool delete = (pattern & (1 << i)) && r0 <= i && i < r1;
757 values[remaining++] = i;
760 check ((int) llx_remove_if (elemp[r0], elemp[r1],
761 pattern_pred, &pattern,
764 check_list_contents (&list, values, remaining);
766 free_elements (cnt, &list, elems, elemp, values);
770 /* Tests, via HELPER, a function that looks at list elements
771 equal to some specified element. */
773 test_examine_equal_range (void (*helper) (int r0, int r1, int eq_pat,
777 const int max_elems = 8;
779 int cnt, r0, r1, eq_pat;
781 for (cnt = 0; cnt <= max_elems; cnt++)
782 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
784 struct llx_list list;
785 struct element **elems;
789 struct element to_find;
793 allocate_ascending (cnt, &list, &elems, &elemp, &values);
795 for (i = 0; i < cnt; i++)
796 if (eq_pat & (1 << i))
797 values[i] = elems[i]->x = -1;
800 for (r0 = 0; r0 <= cnt; r0++)
801 for (r1 = r0; r1 <= cnt; r1++)
802 helper (r0, r1, eq_pat, &to_find, elemp);
804 check_list_contents (&list, values, cnt);
806 free_elements (cnt, &list, elems, elemp, values);
810 /* Tests, via HELPER, a function that looks at list elements for
811 which a given predicate returns true. */
813 test_examine_if_range (void (*helper) (int r0, int r1, int eq_pat,
816 const int max_elems = 8;
818 int cnt, r0, r1, eq_pat;
820 for (cnt = 0; cnt <= max_elems; cnt++)
821 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
823 struct llx_list list;
824 struct element **elems;
828 allocate_ascending (cnt, &list, &elems, &elemp, &values);
830 for (r0 = 0; r0 <= cnt; r0++)
831 for (r1 = r0; r1 <= cnt; r1++)
832 helper (r0, r1, eq_pat, elemp);
834 check_list_contents (&list, values, cnt);
836 free_elements (cnt, &list, elems, elemp, values);
840 /* Helper function for testing llx_find_equal. */
842 test_find_equal_helper (int r0, int r1, int eq_pat,
843 const void *to_find, struct llx **elemp)
848 match = llx_find_equal (elemp[r0], elemp[r1], to_find,
849 compare_elements, &aux_data);
850 for (i = r0; i < r1; i++)
851 if (eq_pat & (1 << i))
854 check (match == elemp[i]);
857 /* Tests llx_find_equal. */
859 test_find_equal (void)
861 test_examine_equal_range (test_find_equal_helper);
864 /* Tests llx_find(). */
868 const int max_elems = 8;
872 for (cnt = 0; cnt <= max_elems; cnt++)
874 struct llx_list list;
875 struct element **elems;
881 allocate_ascending (cnt, &list, &elems, &elemp, &values);
883 for (i = 0; i < cnt; i++)
884 check (llx_find (llx_head (&list), llx_null (&list), elems[i])
886 check (llx_find (llx_head (&list), llx_null (&list), NULL) == NULL);
888 free_elements (cnt, &list, elems, elemp, values);
892 /* Helper function for testing llx_find_if. */
894 test_find_if_helper (int r0, int r1, int eq_pat, struct llx **elemp)
896 struct llx *match = llx_find_if (elemp[r0], elemp[r1],
897 pattern_pred, &eq_pat);
900 for (i = r0; i < r1; i++)
901 if (eq_pat & (1 << i))
904 check (match == elemp[i]);
907 /* Tests llx_find_if. */
911 test_examine_if_range (test_find_if_helper);
914 /* Tests llx_find_adjacent_equal. */
916 test_find_adjacent_equal (void)
918 const int max_elems = 8;
922 for (cnt = 0; cnt <= max_elems; cnt++)
923 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
925 struct llx_list list;
926 struct element **elems;
933 allocate_ascending (cnt, &list, &elems, &elemp, &values);
936 for (i = 0; i < cnt - 1; i++)
939 if (eq_pat & (1 << i))
941 values[i] = elems[i]->x = match;
942 values[i + 1] = elems[i + 1]->x = match;
948 for (i = 0; i <= cnt; i++)
950 struct llx *llx1 = llx_find_adjacent_equal (elemp[i], llx_null (&list),
956 llx2 = llx_null (&list);
957 for (j = i; j < cnt - 1; j++)
958 if (eq_pat & (1 << j))
963 check (llx1 == llx2);
965 check_list_contents (&list, values, cnt);
967 free_elements (cnt, &list, elems, elemp, values);
971 /* Helper function for testing llx_count_range. */
973 test_count_range_helper (int r0, int r1, int eq_pat UNUSED, struct llx **elemp)
975 check ((int) llx_count_range (elemp[r0], elemp[r1]) == r1 - r0);
978 /* Tests llx_count_range. */
980 test_count_range (void)
982 test_examine_if_range (test_count_range_helper);
985 /* Helper function for testing llx_count_equal. */
987 test_count_equal_helper (int r0, int r1, int eq_pat,
988 const void *to_find, struct llx **elemp)
993 count1 = llx_count_equal (elemp[r0], elemp[r1], to_find,
994 compare_elements, &aux_data);
996 for (i = r0; i < r1; i++)
997 if (eq_pat & (1 << i))
1000 check (count1 == count2);
1003 /* Tests llx_count_equal. */
1005 test_count_equal (void)
1007 test_examine_equal_range (test_count_equal_helper);
1010 /* Helper function for testing llx_count_if. */
1012 test_count_if_helper (int r0, int r1, int eq_pat, struct llx **elemp)
1018 count1 = llx_count_if (elemp[r0], elemp[r1], pattern_pred, &eq_pat);
1021 for (i = r0; i < r1; i++)
1022 if (eq_pat & (1 << i))
1025 check (count1 == count2);
1028 /* Tests llx_count_if. */
1030 test_count_if (void)
1032 test_examine_if_range (test_count_if_helper);
1037 factorial (unsigned int n)
1039 unsigned int value = 1;
1045 /* Returns the number of permutations of the CNT values in
1046 VALUES. If VALUES contains duplicates, they must be
1049 expected_perms (int *values, size_t cnt)
1052 unsigned int perm_cnt;
1054 perm_cnt = factorial (cnt);
1055 for (i = 0; i < cnt; i = j)
1057 for (j = i + 1; j < cnt; j++)
1058 if (values[i] != values[j])
1060 perm_cnt /= factorial (j - i);
1065 /* Tests llx_min and llx_max. */
1069 const int max_elems = 6;
1072 for (cnt = 0; cnt <= max_elems; cnt++)
1074 struct llx_list list;
1075 struct element **elems;
1078 int *new_values = xnmalloc (cnt, sizeof *values);
1082 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1085 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1086 compare_elements, &aux_data))
1092 for (i = 0, x = llx_head (&list); x != llx_null (&list);
1093 x = llx_next (x), i++)
1095 struct element *e = llx_data (x);
1097 new_values[i] = e->x;
1099 for (r0 = 0; r0 <= cnt; r0++)
1100 for (r1 = r0; r1 <= cnt; r1++)
1102 struct llx *min = llx_min (elemp[r0], elemp[r1],
1103 compare_elements, &aux_data);
1104 struct llx *max = llx_max (elemp[r0], elemp[r1],
1105 compare_elements, &aux_data);
1108 check (min == elemp[r1]);
1109 check (max == elemp[r1]);
1113 struct element *min_elem = llx_data (min);
1114 struct element *max_elem = llx_data (max);
1115 int min_int, max_int;
1118 min_int = max_int = new_values[r0];
1119 for (i = r0; i < r1; i++)
1121 int value = new_values[i];
1122 if (value < min_int)
1124 if (value > max_int)
1127 check (min != elemp[r1] && min_elem->x == min_int);
1128 check (max != elemp[r1] && max_elem->x == max_int);
1133 check (perm_cnt == factorial (cnt));
1134 check_list_contents (&list, values, cnt);
1136 free_elements (cnt, &list, elems, elemp, values);
1141 /* Tests llx_lexicographical_compare_3way. */
1143 test_lexicographical_compare_3way (void)
1145 const int max_elems = 4;
1147 int cnt_a, pat_a, cnt_b, pat_b;
1149 for (cnt_a = 0; cnt_a <= max_elems; cnt_a++)
1150 for (pat_a = 0; pat_a <= 1 << cnt_a; pat_a++)
1151 for (cnt_b = 0; cnt_b <= max_elems; cnt_b++)
1152 for (pat_b = 0; pat_b <= 1 << cnt_b; pat_b++)
1154 struct llx_list list_a, list_b;
1155 struct element **elems_a, **elems_b;
1156 struct llx **elemp_a, **elemp_b;
1157 int *values_a, *values_b;
1161 allocate_pattern (cnt_a, pat_a,
1162 &list_a, &elems_a, &elemp_a, &values_a);
1163 allocate_pattern (cnt_b, pat_b,
1164 &list_b, &elems_b, &elemp_b, &values_b);
1166 for (a0 = 0; a0 <= cnt_a; a0++)
1167 for (a1 = a0; a1 <= cnt_a; a1++)
1168 for (b0 = 0; b0 <= cnt_b; b0++)
1169 for (b1 = b0; b1 <= cnt_b; b1++)
1171 int a_ordering = lexicographical_compare_3way (
1172 values_a + a0, a1 - a0,
1173 values_b + b0, b1 - b0,
1175 compare_ints, NULL);
1177 int b_ordering = llx_lexicographical_compare_3way (
1178 elemp_a[a0], elemp_a[a1],
1179 elemp_b[b0], elemp_b[b1],
1180 compare_elements, &aux_data);
1182 check (a_ordering == b_ordering);
1185 free_elements (cnt_a, &list_a, elems_a, elemp_a, values_a);
1186 free_elements (cnt_b, &list_b, elems_b, elemp_b, values_b);
1190 /* Appends the `x' value in element E to the array pointed to by
1191 NEXT_OUTPUT, and advances NEXT_OUTPUT to the next position. */
1193 apply_func (void *e_, void *next_output_)
1195 struct element *e = e_;
1196 int **next_output = next_output_;
1198 *(*next_output)++ = e->x;
1201 /* Tests llx_apply. */
1205 const int max_elems = 8;
1209 for (cnt = 0; cnt <= max_elems; cnt++)
1210 for (r0 = 0; r0 <= cnt; r0++)
1211 for (r1 = r0; r1 <= cnt; r1++)
1213 struct llx_list list;
1214 struct element **elems;
1222 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1223 check_list_contents (&list, values, cnt);
1225 output = next_output = xnmalloc (cnt, sizeof *output);
1226 llx_apply (elemp[r0], elemp[r1], apply_func, &next_output);
1227 check_list_contents (&list, values, cnt);
1228 llx_destroy (&list, NULL, NULL, &llx_malloc_mgr);
1230 check (r1 - r0 == next_output - output);
1231 for (j = 0; j < r1 - r0; j++)
1232 check (output[j] == r0 + j);
1234 free_elements (cnt, NULL, elems, elemp, values);
1239 /* Tests llx_destroy. */
1243 const int max_elems = 8;
1247 for (cnt = 0; cnt <= max_elems; cnt++)
1249 struct llx_list list;
1250 struct element **elems;
1258 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1259 check_list_contents (&list, values, cnt);
1261 output = next_output = xnmalloc (cnt, sizeof *output);
1262 llx_destroy (&list, apply_func, &next_output, &llx_malloc_mgr);
1264 check (cnt == next_output - output);
1265 for (j = 0; j < cnt; j++)
1266 check (output[j] == j);
1268 free_elements (cnt, NULL, elems, elemp, values);
1273 /* Tests llx_reverse. */
1277 const int max_elems = 8;
1281 for (cnt = 0; cnt <= max_elems; cnt++)
1282 for (r0 = 0; r0 <= cnt; r0++)
1283 for (r1 = r0; r1 <= cnt; r1++)
1285 struct llx_list list;
1286 struct element **elems;
1292 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1293 check_list_contents (&list, values, cnt);
1296 for (i = 0; i < r0; i++)
1298 for (i = r1 - 1; i >= r0; i--)
1300 for (i = r1; i < cnt; i++)
1303 llx_reverse (elemp[r0], elemp[r1]);
1304 check_list_contents (&list, values, cnt);
1306 free_elements (cnt, &list, elems, elemp, values);
1310 /* Tests llx_next_permutation and llx_prev_permutation when the
1311 permuted values have no duplicates. */
1313 test_permutations_no_dups (void)
1315 const int max_elems = 8;
1318 for (cnt = 0; cnt <= max_elems; cnt++)
1320 struct llx_list list;
1321 struct element **elems;
1323 int *old_values = xnmalloc (cnt, sizeof *values);
1324 int *new_values = xnmalloc (cnt, sizeof *values);
1328 allocate_ascending (cnt, &list, &elems, NULL, &values);
1331 extract_values (&list, old_values, cnt);
1332 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1333 compare_elements, &aux_data))
1335 extract_values (&list, new_values, cnt);
1336 check (lexicographical_compare_3way (new_values, cnt,
1339 compare_ints, NULL) > 0);
1340 memcpy (old_values, new_values, (cnt) * sizeof *old_values);
1343 check (perm_cnt == factorial (cnt));
1344 check_list_contents (&list, values, cnt);
1347 llx_reverse (llx_head (&list), llx_null (&list));
1348 extract_values (&list, old_values, cnt);
1349 while (llx_prev_permutation (llx_head (&list), llx_null (&list),
1350 compare_elements, &aux_data))
1352 extract_values (&list, new_values, cnt);
1353 check (lexicographical_compare_3way (new_values, cnt,
1356 compare_ints, NULL) < 0);
1357 memcpy (old_values, new_values, (cnt) * sizeof *old_values);
1360 check (perm_cnt == factorial (cnt));
1361 llx_reverse (llx_head (&list), llx_null (&list));
1362 check_list_contents (&list, values, cnt);
1364 free_elements (cnt, &list, elems, NULL, values);
1370 /* Tests llx_next_permutation and llx_prev_permutation when the
1371 permuted values contain duplicates. */
1373 test_permutations_with_dups (void)
1375 const int max_elems = 8;
1376 const int max_dup = 3;
1377 const int repetitions = 1024;
1381 for (repeat = 0; repeat < repetitions; repeat++)
1382 for (cnt = 0; cnt < max_elems; cnt++)
1384 struct llx_list list;
1385 struct element **elems;
1388 int *old_values = xnmalloc (max_elems, sizeof *values);
1389 int *new_values = xnmalloc (max_elems, sizeof *values);
1391 unsigned int permutation_cnt;
1395 allocate_elements (cnt, &list, &elems, &elemp, &values);
1400 int max = left < max_dup ? left : max_dup;
1401 int n = rand () % max + 1;
1404 int idx = cnt - left--;
1405 values[idx] = elems[idx]->x = value;
1410 permutation_cnt = 1;
1411 extract_values (&list, old_values, cnt);
1412 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1413 compare_elements, &aux_data))
1415 extract_values (&list, new_values, cnt);
1416 check (lexicographical_compare_3way (new_values, cnt,
1419 compare_ints, NULL) > 0);
1420 memcpy (old_values, new_values, cnt * sizeof *old_values);
1423 check (permutation_cnt == expected_perms (values, cnt));
1424 check_list_contents (&list, values, cnt);
1426 permutation_cnt = 1;
1427 llx_reverse (llx_head (&list), llx_null (&list));
1428 extract_values (&list, old_values, cnt);
1429 while (llx_prev_permutation (llx_head (&list), llx_null (&list),
1430 compare_elements, &aux_data))
1432 extract_values (&list, new_values, cnt);
1433 check (lexicographical_compare_3way (new_values, cnt,
1436 compare_ints, NULL) < 0);
1439 llx_reverse (llx_head (&list), llx_null (&list));
1440 check (permutation_cnt == expected_perms (values, cnt));
1441 check_list_contents (&list, values, cnt);
1443 free_elements (cnt, &list, elems, elemp, values);
1449 /* Tests llx_merge when no equal values are to be merged. */
1451 test_merge_no_dups (void)
1453 const int max_elems = 8;
1454 const int max_fillxer = 3;
1456 int merge_cnt, pattern, pfx, gap, sfx, order;
1458 for (merge_cnt = 0; merge_cnt < max_elems; merge_cnt++)
1459 for (pattern = 0; pattern <= (1 << merge_cnt); pattern++)
1460 for (pfx = 0; pfx < max_fillxer; pfx++)
1461 for (gap = 0; gap < max_fillxer; gap++)
1462 for (sfx = 0; sfx < max_fillxer; sfx++)
1463 for (order = 0; order < 2; order++)
1465 struct llx_list list;
1466 struct element **elems;
1470 int list_cnt = pfx + merge_cnt + gap + sfx;
1474 allocate_elements (list_cnt, &list,
1475 &elems, &elemp, &values);
1478 for (i = 0; i < pfx; i++)
1479 elems[j++]->x = 100 + i;
1481 for (i = 0; i < merge_cnt; i++)
1482 if (pattern & (1u << i))
1485 for (i = 0; i < gap; i++)
1486 elems[j++]->x = 200 + i;
1488 for (i = 0; i < merge_cnt; i++)
1489 if (!(pattern & (1u << i)))
1492 for (i = 0; i < sfx; i++)
1493 elems[j++]->x = 300 + i;
1494 check (list_cnt == j);
1497 for (i = 0; i < pfx; i++)
1498 values[j++] = 100 + i;
1500 for (i = 0; i < merge_cnt; i++)
1502 for (i = 0; i < gap; i++)
1503 values[j++] = 200 + i;
1505 for (i = 0; i < merge_cnt; i++)
1507 for (i = 0; i < sfx; i++)
1508 values[j++] = 300 + i;
1509 check (list_cnt == j);
1512 llx_merge (elemp[a0], elemp[a1], elemp[b0], elemp[b1],
1513 compare_elements, &aux_data);
1515 llx_merge (elemp[b0], elemp[b1], elemp[a0], elemp[a1],
1516 compare_elements, &aux_data);
1518 check_list_contents (&list, values, list_cnt);
1520 free_elements (list_cnt, &list, elems, elemp, values);
1524 /* Tests llx_merge when equal values are to be merged. */
1526 test_merge_with_dups (void)
1528 const int max_elems = 8;
1530 int cnt, merge_pat, inc_pat, order;
1532 for (cnt = 0; cnt <= max_elems; cnt++)
1533 for (merge_pat = 0; merge_pat <= (1 << cnt); merge_pat++)
1534 for (inc_pat = 0; inc_pat <= (1 << cnt); inc_pat++)
1535 for (order = 0; order < 2; order++)
1537 struct llx_list list;
1538 struct element **elems;
1545 allocate_elements (cnt, &list, &elems, &elemp, &values);
1548 for (i = k = 0; i < cnt; i++)
1550 if (merge_pat & (1u << i))
1552 if (inc_pat & (1u << i))
1556 for (i = k = 0; i < cnt; i++)
1558 if (!(merge_pat & (1u << i)))
1560 if (inc_pat & (1u << i))
1567 for (i = 0; i < cnt; i++)
1572 for (i = 0; i < mid; i++)
1573 elems[i]->y = 100 + i;
1574 for (i = mid; i < cnt; i++)
1579 for (i = k = 0; i < cnt; i++)
1582 if (inc_pat & (1u << i))
1588 llx_merge (elemp[0], elemp[mid], elemp[mid], elemp[cnt],
1589 compare_elements, &aux_data);
1591 llx_merge (elemp[mid], elemp[cnt], elemp[0], elemp[mid],
1592 compare_elements, &aux_data);
1594 check_list_contents (&list, values, cnt);
1595 check (llx_is_sorted (llx_head (&list), llx_null (&list),
1596 compare_elements_x_y, &aux_data));
1598 free_elements (cnt, &list, elems, elemp, values);
1602 /* Tests llx_sort on all permutations up to a maximum number of
1605 test_sort_exhaustive (void)
1607 const int max_elems = 8;
1610 for (cnt = 0; cnt <= max_elems; cnt++)
1612 struct llx_list list;
1613 struct element **elems;
1616 struct element **perm_elems;
1621 allocate_ascending (cnt, &list, &elems, NULL, &values);
1622 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1625 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1626 compare_elements, &aux_data))
1628 struct llx_list perm_list;
1631 extract_values (&list, perm_values, cnt);
1632 llx_init (&perm_list);
1633 for (j = 0; j < cnt; j++)
1635 perm_elems[j]->x = perm_values[j];
1636 llx_push_tail (&perm_list, perm_elems[j], &llx_malloc_mgr);
1638 llx_sort (llx_head (&perm_list), llx_null (&perm_list),
1639 compare_elements, &aux_data);
1640 check_list_contents (&perm_list, values, cnt);
1641 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1642 compare_elements, &aux_data));
1643 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1646 check (perm_cnt == factorial (cnt));
1648 free_elements (cnt, &list, elems, NULL, values);
1649 free_elements (cnt, NULL, perm_elems, NULL, perm_values);
1653 /* Tests that llx_sort is stable in the presence of equal
1656 test_sort_stable (void)
1658 const int max_elems = 6;
1661 for (cnt = 0; cnt <= max_elems; cnt++)
1662 for (inc_pat = 0; inc_pat <= 1 << cnt; inc_pat++)
1664 struct llx_list list;
1665 struct element **elems;
1668 struct element **perm_elems;
1674 allocate_elements (cnt, &list, &elems, NULL, &values);
1675 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1678 for (i = 0; i < cnt; i++)
1680 elems[i]->x = values[i] = j;
1681 if (inc_pat & (1 << i))
1687 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1688 compare_elements_y, &aux_data))
1690 struct llx_list perm_list;
1692 extract_values (&list, perm_values, cnt);
1693 llx_init (&perm_list);
1694 for (i = 0; i < cnt; i++)
1696 perm_elems[i]->x = perm_values[i];
1697 perm_elems[i]->y = i;
1698 llx_push_tail (&perm_list, perm_elems[i], &llx_malloc_mgr);
1700 llx_sort (llx_head (&perm_list), llx_null (&perm_list),
1701 compare_elements, &aux_data);
1702 check_list_contents (&perm_list, values, cnt);
1703 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1704 compare_elements_x_y, &aux_data));
1705 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1708 check (perm_cnt == factorial (cnt));
1710 free_elements (cnt, &list, elems, NULL, values);
1711 free_elements (cnt, NULL, perm_elems, NULL, perm_values);
1715 /* Tests that llx_sort does not disturb elements outside the
1718 test_sort_subset (void)
1720 const int max_elems = 8;
1722 int cnt, r0, r1, repeat;
1724 for (cnt = 0; cnt <= max_elems; cnt++)
1725 for (repeat = 0; repeat < 100; repeat++)
1726 for (r0 = 0; r0 <= cnt; r0++)
1727 for (r1 = r0; r1 <= cnt; r1++)
1729 struct llx_list list;
1730 struct element **elems;
1734 allocate_random (cnt, &list, &elems, &elemp, &values);
1736 qsort (&values[r0], r1 - r0, sizeof *values, compare_ints_noaux);
1737 llx_sort (elemp[r0], elemp[r1], compare_elements, &aux_data);
1738 check_list_contents (&list, values, cnt);
1740 free_elements (cnt, &list, elems, elemp, values);
1744 /* Tests that llx_sort works with large lists. */
1746 test_sort_big (void)
1748 const int max_elems = 1024;
1752 for (cnt = 0; cnt < max_elems; cnt++)
1754 struct llx_list list;
1755 struct element **elems;
1758 allocate_random (cnt, &list, &elems, NULL, &values);
1760 qsort (values, cnt, sizeof *values, compare_ints_noaux);
1761 llx_sort (llx_head (&list), llx_null (&list), compare_elements, &aux_data);
1762 check_list_contents (&list, values, cnt);
1764 free_elements (cnt, &list, elems, NULL, values);
1768 /* Tests llx_unique. */
1772 const int max_elems = 10;
1774 int *ascending = xnmalloc (max_elems, sizeof *ascending);
1776 int cnt, inc_pat, i, j, unique_values;
1778 for (i = 0; i < max_elems; i++)
1781 for (cnt = 0; cnt < max_elems; cnt++)
1782 for (inc_pat = 0; inc_pat < (1 << cnt); inc_pat++)
1784 struct llx_list list, dups;
1785 struct element **elems;
1788 allocate_elements (cnt, &list, &elems, NULL, &values);
1790 j = unique_values = 0;
1791 for (i = 0; i < cnt; i++)
1793 unique_values = j + 1;
1794 elems[i]->x = values[i] = j;
1795 if (inc_pat & (1 << i))
1798 check_list_contents (&list, values, cnt);
1801 check (llx_unique (llx_head (&list), llx_null (&list),
1803 compare_elements, &aux_data,
1805 == (size_t) unique_values);
1806 check_list_contents (&list, ascending, unique_values);
1808 llx_splice (llx_null (&list), llx_head (&dups), llx_null (&dups));
1809 llx_sort (llx_head (&list), llx_null (&list), compare_elements, &aux_data);
1810 check_list_contents (&list, values, cnt);
1812 llx_destroy (&dups, NULL, NULL, &llx_malloc_mgr);
1813 free_elements (cnt, &list, elems, NULL, values);
1819 /* Tests llx_sort_unique. */
1821 test_sort_unique (void)
1823 const int max_elems = 7;
1826 for (cnt = 0; cnt <= max_elems; cnt++)
1827 for (inc_pat = 0; inc_pat <= 1 << cnt; inc_pat++)
1829 struct llx_list list;
1830 struct element **elems;
1833 struct element **perm_elems;
1842 allocate_elements (cnt, &list, &elems, NULL, &values);
1843 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1846 for (i = 0; i < cnt; i++)
1848 elems[i]->x = values[i] = j;
1850 if (inc_pat & (1 << i))
1854 unique_values = xnmalloc (unique_cnt, sizeof *unique_values);
1855 for (i = 0; i < unique_cnt; i++)
1856 unique_values[i] = i;
1859 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1860 compare_elements, &aux_data))
1862 struct llx_list perm_list;
1864 extract_values (&list, perm_values, cnt);
1865 llx_init (&perm_list);
1866 for (i = 0; i < cnt; i++)
1868 perm_elems[i]->x = perm_values[i];
1869 perm_elems[i]->y = i;
1870 llx_push_tail (&perm_list, perm_elems[i], &llx_malloc_mgr);
1872 llx_sort_unique (llx_head (&perm_list), llx_null (&perm_list), NULL,
1873 compare_elements, &aux_data,
1875 check_list_contents (&perm_list, unique_values, unique_cnt);
1876 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1877 compare_elements_x_y, &aux_data));
1878 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1881 check (perm_cnt == expected_perms (values, cnt));
1883 free_elements (cnt, &list, elems, NULL, values);
1884 free_elements (cnt, NULL, perm_elems, NULL, perm_values);
1885 free (unique_values);
1889 /* Tests llx_insert_ordered. */
1891 test_insert_ordered (void)
1893 const int max_elems = 6;
1896 for (cnt = 0; cnt <= max_elems; cnt++)
1897 for (inc_pat = 0; inc_pat <= 1 << cnt; inc_pat++)
1899 struct llx_list list;
1900 struct element **elems;
1903 struct element **perm_elems;
1909 allocate_elements (cnt, &list, &elems, NULL, &values);
1910 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1913 for (i = 0; i < cnt; i++)
1915 elems[i]->x = values[i] = j;
1916 if (inc_pat & (1 << i))
1922 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1923 compare_elements_y, &aux_data))
1925 struct llx_list perm_list;
1927 extract_values (&list, perm_values, cnt);
1928 llx_init (&perm_list);
1929 for (i = 0; i < cnt; i++)
1931 perm_elems[i]->x = perm_values[i];
1932 perm_elems[i]->y = i;
1933 llx_insert_ordered (llx_head (&perm_list),
1934 llx_null (&perm_list),
1936 compare_elements, &aux_data,
1939 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1940 compare_elements_x_y, &aux_data));
1941 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1944 check (perm_cnt == factorial (cnt));
1946 free_elements (cnt, &list, elems, NULL, values);
1947 free_elements (cnt, NULL, perm_elems, NULL, perm_values);
1951 /* Tests llx_partition. */
1953 test_partition (void)
1955 const int max_elems = 10;
1961 for (cnt = 0; cnt < max_elems; cnt++)
1962 for (r0 = 0; r0 <= cnt; r0++)
1963 for (r1 = r0; r1 <= cnt; r1++)
1964 for (pbase = 0; pbase <= (1u << (r1 - r0)); pbase++)
1966 struct llx_list list;
1967 struct element **elems;
1971 unsigned int pattern = pbase << r0;
1974 struct llx *part_llx;
1976 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1978 /* Check that llx_find_partition works okay in every
1979 case. We use it after partitioning, too, but that
1980 only tests cases where it returns non-null. */
1981 for (i = r0; i < r1; i++)
1982 if (!(pattern & (1u << i)))
1986 if (pattern & (1u << i))
1988 part_llx = llx_find_partition (elemp[r0], elemp[r1],
1992 check (part_llx == elemp[j]);
1994 check (part_llx == NULL);
1996 /* Figure out expected results. */
1999 for (i = 0; i < r0; i++)
2001 for (i = r0; i < r1; i++)
2002 if (pattern & (1u << i))
2004 for (i = r0; i < r1; i++)
2005 if (!(pattern & (1u << i)))
2007 if (first_false == -1)
2011 if (first_false == -1)
2013 for (i = r1; i < cnt; i++)
2017 /* Partition and check for expected results. */
2018 check (llx_partition (elemp[r0], elemp[r1],
2019 pattern_pred, &pattern)
2020 == elemp[first_false]);
2021 check (llx_find_partition (elemp[r0], elemp[r1],
2022 pattern_pred, &pattern)
2023 == elemp[first_false]);
2024 check_list_contents (&list, values, cnt);
2025 check ((int) llx_count (&list) == cnt);
2027 free_elements (cnt, &list, elems, elemp, values);
2031 /* Tests that allocation failure is gracefully handled. */
2033 test_allocation_failure (void)
2035 struct llx_list list;
2038 check (llx_push_head (&list, NULL, &llx_null_mgr) == NULL);
2039 check (llx_push_tail (&list, NULL, &llx_null_mgr) == NULL);
2040 check (llx_insert (llx_null (&list), NULL, &llx_null_mgr) == NULL);
2041 check_list_contents (&list, NULL, 0);
2049 const char *description;
2050 void (*function) (void);
2053 static const struct test tests[] =
2106 "find-adjacent-equal",
2107 "find_adjacent_equal",
2108 test_find_adjacent_equal
2131 "lexicographical-compare-3way",
2132 "lexicographical_compare_3way",
2133 test_lexicographical_compare_3way
2151 "permutations-no-dups",
2152 "permutations (no dups)",
2153 test_permutations_no_dups
2156 "permutations-with-dups",
2157 "permutations (with dups)",
2158 test_permutations_with_dups
2167 "merge (with dups)",
2168 test_merge_with_dups
2172 "sort (exhaustive)",
2173 test_sort_exhaustive
2211 "allocation-failure",
2212 "allocation failure",
2213 test_allocation_failure
2217 enum { N_TESTS = sizeof tests / sizeof *tests };
2220 main (int argc, char *argv[])
2226 fprintf (stderr, "exactly one argument required; use --help for help\n");
2227 return EXIT_FAILURE;
2229 else if (!strcmp (argv[1], "--help"))
2231 printf ("%s: test doubly linked list of pointers (llx) library\n"
2232 "usage: %s TEST-NAME\n"
2233 "where TEST-NAME is one of the following:\n",
2235 for (i = 0; i < N_TESTS; i++)
2236 printf (" %s\n %s\n", tests[i].name, tests[i].description);
2241 for (i = 0; i < N_TESTS; i++)
2242 if (!strcmp (argv[1], tests[i].name))
2244 tests[i].function ();
2248 fprintf (stderr, "unknown test %s; use --help for help\n", argv[1]);
2249 return EXIT_FAILURE;