1 /* PSPP - computes sample statistics.
2 Copyright (C) 2006 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 /* This is a test program for the llx_* routines defined in
21 ll.c. This test program aims to be as comprehensive as
22 possible. "gcov -b" should report 100% coverage of lines and
23 branches in llx.c and llx.h. "valgrind --leak-check=yes
24 --show-reachable=yes" should give a clean report.
26 This test program depends only on ll.c, llx.c, and the
29 See ll-test.c for a similar program for the ll_* routines. */
31 #include <libpspp/llx.h>
37 /* Support preliminaries. */
38 #if __GNUC__ >= 2 && !defined UNUSED
39 #define UNUSED __attribute__ ((unused))
44 /* Exit with a failure code.
45 (Place a breakpoint on this function while debugging.) */
52 /* If OK is not true, prints a message about failure on the
53 current source file and the given LINE and terminates. */
55 check_func (bool ok, int line)
59 printf ("check failed at %s, line %d\n", __FILE__, line);
64 /* Verifies that EXPR evaluates to true.
65 If not, prints a message citing the calling line number and
67 #define check(EXPR) check_func ((EXPR), __LINE__)
69 /* Prints a message about memory exhaustion and exits with a
74 printf ("virtual memory exhausted\n");
78 /* Allocates and returns N bytes of memory. */
94 /* Allocates and returns N * M bytes of memory. */
96 xnmalloc (size_t n, size_t m)
98 if ((size_t) -1 / m <= n)
100 return xmalloc (n * m);
103 /* Always returns a null pointer, failing allocation. */
105 null_allocate_node (void *aux UNUSED)
112 null_release_node (struct llx *llx UNUSED, void *aux UNUSED)
116 /* Memory manager that fails all allocations and does nothing on
118 static const struct llx_manager llx_null_mgr =
125 /* List type and support routines. */
127 /* Test data element. */
130 int x; /* Primary value. */
131 int y; /* Secondary value. */
136 /* Prints the elements in LIST. */
138 print_list (struct llx_list *list)
143 for (x = llx_head (list); x != llx_null (list); x = llx_next (x))
145 const struct element *e = llx_data (x);
146 printf (" %d", e->x);
151 /* Prints the value returned by PREDICATE given auxiliary data
152 AUX for each element in LIST. */
154 print_pred (struct llx_list *list,
155 llx_predicate_func *predicate, void *aux UNUSED)
160 for (x = llx_head (list); x != llx_null (list); x = llx_next (x))
161 printf (" %d", predicate (x, aux));
165 /* Prints the CNT numbers in VALUES. */
167 print_array (int values[], size_t cnt)
172 for (i = 0; i < cnt; i++)
173 printf (" %d", values[i]);
177 /* Compares the `x' values in A and B and returns a strcmp-type
178 return value. Verifies that AUX points to aux_data. */
180 compare_elements (const void *a_, const void *b_, void *aux)
182 const struct element *a = a_;
183 const struct element *b = b_;
185 check (aux == &aux_data);
186 return a->x < b->x ? -1 : a->x > b->x;
189 /* Compares the `x' and `y' values in A and B and returns a
190 strcmp-type return value. Verifies that AUX points to
193 compare_elements_x_y (const void *a_, const void *b_, void *aux)
195 const struct element *a = a_;
196 const struct element *b = b_;
198 check (aux == &aux_data);
200 return a->x < b->x ? -1 : 1;
201 else if (a->y != b->y)
202 return a->y < b->y ? -1 : 1;
207 /* Compares the `y' values in A and B and returns a strcmp-type
208 return value. Verifies that AUX points to aux_data. */
210 compare_elements_y (const void *a_, const void *b_, void *aux)
212 const struct element *a = a_;
213 const struct element *b = b_;
215 check (aux == &aux_data);
216 return a->y < b->y ? -1 : a->y > b->y;
219 /* Returns true if the bit in *PATTERN indicated by `x in
220 *ELEMENT is set, false otherwise. */
222 pattern_pred (const void *element_, void *pattern_)
224 const struct element *element = element_;
225 unsigned *pattern = pattern_;
227 return (*pattern & (1u << element->x)) != 0;
230 /* Allocates N elements in *ELEMS.
231 Adds the elements to LIST, if it is nonnull.
232 Puts pointers to the elements' list elements in *ELEMP,
233 followed by a pointer to the list null element, if ELEMP is
235 Allocates space for N values in *VALUES, if VALUES is
238 allocate_elements (size_t n,
239 struct llx_list *list,
240 struct element ***elems,
249 *elems = xnmalloc (n, sizeof **elems);
252 *elemp = xnmalloc (n + 1, sizeof *elemp);
253 (*elemp)[n] = llx_null (list);
256 for (i = 0; i < n; i++)
258 (*elems)[i] = xmalloc (sizeof ***elems);
261 struct llx *llx = llx_push_tail (list, (*elems)[i], &llx_malloc_mgr);
268 *values = xnmalloc (n, sizeof *values);
271 /* Copies the CNT values of `x' from LIST into VALUES[]. */
273 extract_values (struct llx_list *list, int values[], size_t cnt)
277 check (llx_count (list) == cnt);
278 for (x = llx_head (list); x != llx_null (list); x = llx_next (x))
280 struct element *e = llx_data (x);
285 /* As allocate_elements, but sets ascending values, starting
286 from 0, in `x' values in *ELEMS and in *VALUES (if
289 allocate_ascending (size_t n,
290 struct llx_list *list,
291 struct element ***elems,
297 allocate_elements (n, list, elems, elemp, values);
299 for (i = 0; i < n; i++)
302 extract_values (list, *values, n);
305 /* As allocate_elements, but sets binary values extracted from
306 successive bits in PATTERN in `x' values in *ELEMS and in
307 *VALUES (if nonnull). */
309 allocate_pattern (size_t n,
311 struct llx_list *list,
312 struct element ***elems,
318 allocate_elements (n, list, elems, elemp, values);
320 for (i = 0; i < n; i++)
321 (*elems)[i]->x = (pattern & (1 << i)) != 0;
323 extract_values (list, *values, n);
326 /* Randomly shuffles the CNT elements in ARRAY, each of which is
327 SIZE bytes in size. */
329 random_shuffle (void *array_, size_t cnt, size_t size)
331 char *array = array_;
332 char *tmp = xmalloc (size);
335 for (i = 0; i < cnt; i++)
337 size_t j = rand () % (cnt - i) + i;
340 memcpy (tmp, array + j * size, size);
341 memcpy (array + j * size, array + i * size, size);
342 memcpy (array + i * size, tmp, size);
349 /* As allocate_ascending, but orders the values randomly. */
351 allocate_random (size_t n,
352 struct llx_list *list,
353 struct element ***elems,
359 allocate_elements (n, list, elems, elemp, values);
361 for (i = 0; i < n; i++)
363 random_shuffle (*elems, n, sizeof **elems);
365 extract_values (list, *values, n);
368 /* Frees LIST, the N elements of ELEMS, ELEMP, and VALUES. */
370 free_elements (size_t n,
371 struct llx_list *list,
372 struct element **elems,
379 llx_destroy (list, NULL, NULL, &llx_malloc_mgr);
380 for (i = 0; i < n; i++)
387 /* Compares A and B and returns a strcmp-type return value. */
389 compare_ints (const void *a_, const void *b_, void *aux UNUSED)
394 return *a < *b ? -1 : *a > *b;
397 /* Compares A and B and returns a strcmp-type return value. */
399 compare_ints_noaux (const void *a_, const void *b_)
404 return *a < *b ? -1 : *a > *b;
407 /* Checks that LIST contains the CNT values in ELEMENTS. */
409 check_list_contents (struct llx_list *list, int elements[], size_t cnt)
414 check ((cnt == 0) == llx_is_empty (list));
416 /* Iterate in forward order. */
417 for (llx = llx_head (list), i = 0; i < cnt; llx = llx_next (llx), i++)
419 struct element *e = llx_data (llx);
420 check (elements[i] == e->x);
421 check (llx != llx_null (list));
423 check (llx == llx_null (list));
425 /* Iterate in reverse order. */
426 for (llx = llx_tail (list), i = 0; i < cnt; llx = llx_prev (llx), i++)
428 struct element *e = llx_data (llx);
429 check (elements[cnt - i - 1] == e->x);
430 check (llx != llx_null (list));
432 check (llx == llx_null (list));
434 check (llx_count (list) == cnt);
437 /* Lexicographicallxy compares ARRAY1, which contains COUNT1
438 elements of SIZE bytes each, to ARRAY2, which contains COUNT2
439 elements of SIZE bytes, according to COMPARE. Returns a
440 strcmp-type result. AUX is passed to COMPARE as auxiliary
443 lexicographical_compare_3way (const void *array1, size_t count1,
444 const void *array2, size_t count2,
446 int (*compare) (const void *, const void *,
450 const char *first1 = array1;
451 const char *first2 = array2;
452 size_t min_count = count1 < count2 ? count1 : count2;
454 while (min_count > 0)
456 int cmp = compare (first1, first2, aux);
465 return count1 < count2 ? -1 : count1 > count2;
470 /* Tests list push and pop operations. */
474 const int max_elems = 1024;
476 struct llx_list list;
477 struct element **elems;
482 allocate_elements (max_elems, NULL, &elems, NULL, &values);
486 check_list_contents (&list, NULL, 0);
487 for (i = 0; i < max_elems; i++)
489 values[i] = elems[i]->x = i;
490 llx_push_tail (&list, elems[i], &llx_malloc_mgr);
491 check_list_contents (&list, values, i + 1);
494 /* Remove from tail. */
495 for (i = 0; i < max_elems; i++)
497 struct element *e = llx_pop_tail (&list, &llx_malloc_mgr);
498 check (e->x == max_elems - i - 1);
499 check_list_contents (&list, values, max_elems - i - 1);
503 check_list_contents (&list, NULL, 0);
504 for (i = 0; i < max_elems; i++)
506 values[max_elems - i - 1] = elems[i]->x = max_elems - i - 1;
507 llx_push_head (&list, elems[i], &llx_malloc_mgr);
508 check_list_contents (&list, &values[max_elems - i - 1], i + 1);
511 /* Remove from start. */
512 for (i = 0; i < max_elems; i++)
514 struct element *e = llx_pop_head (&list, &llx_malloc_mgr);
515 check (e->x == (int) i);
516 check_list_contents (&list, &values[i + 1], max_elems - i - 1);
519 free_elements (max_elems, &list, elems, NULL, values);
522 /* Tests insertion and removal at arbitrary positions. */
524 test_insert_remove (void)
526 const int max_elems = 16;
529 for (cnt = 0; cnt < max_elems; cnt++)
531 struct element **elems;
533 int *values = xnmalloc (cnt + 1, sizeof *values);
535 struct llx_list list;
536 struct element extra;
537 struct llx *extra_llx;
540 allocate_ascending (cnt, &list, &elems, &elemp, NULL);
542 for (pos = 0; pos <= cnt; pos++)
546 extra_llx = llx_insert (elemp[pos], &extra, &llx_malloc_mgr);
547 check (extra_llx != NULL);
550 for (i = 0; i < pos; i++)
555 check_list_contents (&list, values, cnt + 1);
557 llx_remove (extra_llx, &llx_malloc_mgr);
559 check_list_contents (&list, values, cnt);
561 free_elements (cnt, &list, elems, elemp, values);
565 /* Tests swapping individual elements. */
569 const int max_elems = 8;
572 for (cnt = 0; cnt <= max_elems; cnt++)
574 struct llx_list list;
575 struct element **elems;
581 allocate_ascending (cnt, &list, &elems, &elemp, &values);
582 check_list_contents (&list, values, cnt);
584 for (i = 0; i < cnt; i++)
585 for (j = 0; j < cnt; j++)
586 for (k = 0; k < 2; k++)
590 llx_swap (elemp[i], elemp[j]);
592 values[i] = values[j];
594 check_list_contents (&list, values, cnt);
597 free_elements (cnt, &list, elems, elemp, values);
601 /* Tests swapping ranges of list elements. */
603 test_swap_range (void)
605 const int max_elems = 8;
606 int cnt, a0, a1, b0, b1, r;
608 for (cnt = 0; cnt <= max_elems; cnt++)
609 for (a0 = 0; a0 <= cnt; a0++)
610 for (a1 = a0; a1 <= cnt; a1++)
611 for (b0 = a1; b0 <= cnt; b0++)
612 for (b1 = b0; b1 <= cnt; b1++)
613 for (r = 0; r < 2; r++)
615 struct llx_list list;
616 struct element **elems;
622 allocate_ascending (cnt, &list, &elems, &elemp, &values);
623 check_list_contents (&list, values, cnt);
626 for (i = 0; i < a0; i++)
628 for (i = b0; i < b1; i++)
630 for (i = a1; i < b0; i++)
632 for (i = a0; i < a1; i++)
634 for (i = b1; i < cnt; i++)
639 llx_swap_range (elemp[a0], elemp[a1], elemp[b0], elemp[b1]);
641 llx_swap_range (elemp[b0], elemp[b1], elemp[a0], elemp[a1]);
642 check_list_contents (&list, values, cnt);
644 free_elements (cnt, &list, elems, elemp, values);
648 /* Tests removing ranges of list elements. */
650 test_remove_range (void)
652 const int max_elems = 8;
656 for (cnt = 0; cnt <= max_elems; cnt++)
657 for (r0 = 0; r0 <= cnt; r0++)
658 for (r1 = r0; r1 <= cnt; r1++)
660 struct llx_list list;
661 struct element **elems;
667 allocate_ascending (cnt, &list, &elems, &elemp, &values);
668 check_list_contents (&list, values, cnt);
671 for (i = 0; i < r0; i++)
673 for (i = r1; i < cnt; i++)
676 llx_remove_range (elemp[r0], elemp[r1], &llx_malloc_mgr);
677 check_list_contents (&list, values, j);
679 free_elements (cnt, &list, elems, elemp, values);
683 /* Tests llx_remove_equal. */
685 test_remove_equal (void)
687 const int max_elems = 8;
689 int cnt, r0, r1, eq_pat;
691 for (cnt = 0; cnt <= max_elems; cnt++)
692 for (r0 = 0; r0 <= cnt; r0++)
693 for (r1 = r0; r1 <= cnt; r1++)
694 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
696 struct llx_list list;
697 struct element **elems;
701 struct element to_remove;
705 allocate_elements (cnt, &list, &elems, &elemp, &values);
708 for (i = 0; i < cnt; i++)
710 int x = eq_pat & (1 << i) ? -1 : i;
711 bool delete = x == -1 && r0 <= i && i < r1;
714 values[remaining++] = x;
718 check ((int) llx_remove_equal (elemp[r0], elemp[r1], &to_remove,
719 compare_elements, &aux_data,
722 check_list_contents (&list, values, remaining);
724 free_elements (cnt, &list, elems, elemp, values);
728 /* Tests llx_remove_if. */
730 test_remove_if (void)
732 const int max_elems = 8;
734 int cnt, r0, r1, pattern;
736 for (cnt = 0; cnt <= max_elems; cnt++)
737 for (r0 = 0; r0 <= cnt; r0++)
738 for (r1 = r0; r1 <= cnt; r1++)
739 for (pattern = 0; pattern <= 1 << cnt; pattern++)
741 struct llx_list list;
742 struct element **elems;
749 allocate_ascending (cnt, &list, &elems, &elemp, &values);
752 for (i = 0; i < cnt; i++)
754 bool delete = (pattern & (1 << i)) && r0 <= i && i < r1;
756 values[remaining++] = i;
759 check ((int) llx_remove_if (elemp[r0], elemp[r1],
760 pattern_pred, &pattern,
763 check_list_contents (&list, values, remaining);
765 free_elements (cnt, &list, elems, elemp, values);
769 /* Tests, via HELPER, a function that looks at list elements
770 equal to some specified element. */
772 test_examine_equal_range (void (*helper) (int r0, int r1, int eq_pat,
776 const int max_elems = 8;
778 int cnt, r0, r1, eq_pat;
780 for (cnt = 0; cnt <= max_elems; cnt++)
781 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
783 struct llx_list list;
784 struct element **elems;
788 struct element to_find;
792 allocate_ascending (cnt, &list, &elems, &elemp, &values);
794 for (i = 0; i < cnt; i++)
795 if (eq_pat & (1 << i))
796 values[i] = elems[i]->x = -1;
799 for (r0 = 0; r0 <= cnt; r0++)
800 for (r1 = r0; r1 <= cnt; r1++)
801 helper (r0, r1, eq_pat, &to_find, elemp);
803 check_list_contents (&list, values, cnt);
805 free_elements (cnt, &list, elems, elemp, values);
809 /* Tests, via HELPER, a function that looks at list elements for
810 which a given predicate returns true. */
812 test_examine_if_range (void (*helper) (int r0, int r1, int eq_pat,
815 const int max_elems = 8;
817 int cnt, r0, r1, eq_pat;
819 for (cnt = 0; cnt <= max_elems; cnt++)
820 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
822 struct llx_list list;
823 struct element **elems;
827 allocate_ascending (cnt, &list, &elems, &elemp, &values);
829 for (r0 = 0; r0 <= cnt; r0++)
830 for (r1 = r0; r1 <= cnt; r1++)
831 helper (r0, r1, eq_pat, elemp);
833 check_list_contents (&list, values, cnt);
835 free_elements (cnt, &list, elems, elemp, values);
839 /* Helper function for testing llx_find_equal. */
841 test_find_equal_helper (int r0, int r1, int eq_pat,
842 const void *to_find, struct llx **elemp)
847 match = llx_find_equal (elemp[r0], elemp[r1], to_find,
848 compare_elements, &aux_data);
849 for (i = r0; i < r1; i++)
850 if (eq_pat & (1 << i))
853 check (match == elemp[i]);
856 /* Tests llx_find_equal. */
858 test_find_equal (void)
860 test_examine_equal_range (test_find_equal_helper);
863 /* Helper function for testing llx_find_if. */
865 test_find_if_helper (int r0, int r1, int eq_pat, struct llx **elemp)
867 struct llx *match = llx_find_if (elemp[r0], elemp[r1],
868 pattern_pred, &eq_pat);
871 for (i = r0; i < r1; i++)
872 if (eq_pat & (1 << i))
875 check (match == elemp[i]);
878 /* Tests llx_find_if. */
882 test_examine_if_range (test_find_if_helper);
885 /* Tests llx_find_adjacent_equal. */
887 test_find_adjacent_equal (void)
889 const int max_elems = 8;
893 for (cnt = 0; cnt <= max_elems; cnt++)
894 for (eq_pat = 0; eq_pat <= 1 << cnt; eq_pat++)
896 struct llx_list list;
897 struct element **elems;
904 allocate_ascending (cnt, &list, &elems, &elemp, &values);
907 for (i = 0; i < cnt - 1; i++)
910 if (eq_pat & (1 << i))
912 values[i] = elems[i]->x = match;
913 values[i + 1] = elems[i + 1]->x = match;
919 for (i = 0; i <= cnt; i++)
921 struct llx *llx1 = llx_find_adjacent_equal (elemp[i], llx_null (&list),
927 llx2 = llx_null (&list);
928 for (j = i; j < cnt - 1; j++)
929 if (eq_pat & (1 << j))
934 check (llx1 == llx2);
936 check_list_contents (&list, values, cnt);
938 free_elements (cnt, &list, elems, elemp, values);
942 /* Helper function for testing llx_count_range. */
944 test_count_range_helper (int r0, int r1, int eq_pat UNUSED, struct llx **elemp)
946 check ((int) llx_count_range (elemp[r0], elemp[r1]) == r1 - r0);
949 /* Tests llx_count_range. */
951 test_count_range (void)
953 test_examine_if_range (test_count_range_helper);
956 /* Helper function for testing llx_count_equal. */
958 test_count_equal_helper (int r0, int r1, int eq_pat,
959 const void *to_find, struct llx **elemp)
964 count1 = llx_count_equal (elemp[r0], elemp[r1], to_find,
965 compare_elements, &aux_data);
967 for (i = r0; i < r1; i++)
968 if (eq_pat & (1 << i))
971 check (count1 == count2);
974 /* Tests llx_count_equal. */
976 test_count_equal (void)
978 test_examine_equal_range (test_count_equal_helper);
981 /* Helper function for testing llx_count_if. */
983 test_count_if_helper (int r0, int r1, int eq_pat, struct llx **elemp)
989 count1 = llx_count_if (elemp[r0], elemp[r1], pattern_pred, &eq_pat);
992 for (i = r0; i < r1; i++)
993 if (eq_pat & (1 << i))
996 check (count1 == count2);
999 /* Tests llx_count_if. */
1001 test_count_if (void)
1003 test_examine_if_range (test_count_if_helper);
1008 factorial (unsigned n)
1016 /* Returns the number of permutations of the CNT values in
1017 VALUES. If VALUES contains duplicates, they must be
1020 expected_perms (int *values, size_t cnt)
1025 perm_cnt = factorial (cnt);
1026 for (i = 0; i < cnt; i = j)
1028 for (j = i + 1; j < cnt; j++)
1029 if (values[i] != values[j])
1031 perm_cnt /= factorial (j - i);
1036 /* Tests llx_min and llx_max. */
1040 const int max_elems = 6;
1043 for (cnt = 0; cnt <= max_elems; cnt++)
1045 struct llx_list list;
1046 struct element **elems;
1049 int *new_values = xnmalloc (cnt, sizeof *values);
1053 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1056 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1057 compare_elements, &aux_data))
1063 for (i = 0, x = llx_head (&list); x != llx_null (&list);
1064 x = llx_next (x), i++)
1066 struct element *e = llx_data (x);
1068 new_values[i] = e->x;
1070 for (r0 = 0; r0 <= cnt; r0++)
1071 for (r1 = r0; r1 <= cnt; r1++)
1073 struct llx *min = llx_min (elemp[r0], elemp[r1],
1074 compare_elements, &aux_data);
1075 struct llx *max = llx_max (elemp[r0], elemp[r1],
1076 compare_elements, &aux_data);
1079 check (min == elemp[r1]);
1080 check (max == elemp[r1]);
1084 struct element *min_elem = llx_data (min);
1085 struct element *max_elem = llx_data (max);
1086 int min_int, max_int;
1089 min_int = max_int = new_values[r0];
1090 for (i = r0; i < r1; i++)
1092 int value = new_values[i];
1093 if (value < min_int)
1095 if (value > max_int)
1098 check (min != elemp[r1] && min_elem->x == min_int);
1099 check (max != elemp[r1] && max_elem->x == max_int);
1104 check (perm_cnt == factorial (cnt));
1105 check_list_contents (&list, values, cnt);
1107 free_elements (cnt, &list, elems, elemp, values);
1112 /* Tests llx_lexicographical_compare_3way. */
1114 test_lexicographical_compare_3way (void)
1116 const int max_elems = 4;
1118 int cnt_a, pat_a, cnt_b, pat_b;
1120 for (cnt_a = 0; cnt_a <= max_elems; cnt_a++)
1121 for (pat_a = 0; pat_a <= 1 << cnt_a; pat_a++)
1122 for (cnt_b = 0; cnt_b <= max_elems; cnt_b++)
1123 for (pat_b = 0; pat_b <= 1 << cnt_b; pat_b++)
1125 struct llx_list list_a, list_b;
1126 struct element **elems_a, **elems_b;
1127 struct llx **elemp_a, **elemp_b;
1128 int *values_a, *values_b;
1132 allocate_pattern (cnt_a, pat_a,
1133 &list_a, &elems_a, &elemp_a, &values_a);
1134 allocate_pattern (cnt_b, pat_b,
1135 &list_b, &elems_b, &elemp_b, &values_b);
1137 for (a0 = 0; a0 <= cnt_a; a0++)
1138 for (a1 = a0; a1 <= cnt_a; a1++)
1139 for (b0 = 0; b0 <= cnt_b; b0++)
1140 for (b1 = b0; b1 <= cnt_b; b1++)
1142 int a_ordering = lexicographical_compare_3way (
1143 values_a + a0, a1 - a0,
1144 values_b + b0, b1 - b0,
1146 compare_ints, NULL);
1148 int b_ordering = llx_lexicographical_compare_3way (
1149 elemp_a[a0], elemp_a[a1],
1150 elemp_b[b0], elemp_b[b1],
1151 compare_elements, &aux_data);
1153 check (a_ordering == b_ordering);
1156 free_elements (cnt_a, &list_a, elems_a, elemp_a, values_a);
1157 free_elements (cnt_b, &list_b, elems_b, elemp_b, values_b);
1161 /* Appends the `x' value in element E to the array pointed to by
1162 NEXT_OUTPUT, and advances NEXT_OUTPUT to the next position. */
1164 apply_func (void *e_, void *next_output_)
1166 struct element *e = e_;
1167 int **next_output = next_output_;
1169 *(*next_output)++ = e->x;
1172 /* Tests llx_apply. */
1176 const int max_elems = 8;
1180 for (cnt = 0; cnt <= max_elems; cnt++)
1181 for (r0 = 0; r0 <= cnt; r0++)
1182 for (r1 = r0; r1 <= cnt; r1++)
1184 struct llx_list list;
1185 struct element **elems;
1193 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1194 check_list_contents (&list, values, cnt);
1196 output = next_output = xnmalloc (cnt, sizeof *output);
1197 llx_apply (elemp[r0], elemp[r1], apply_func, &next_output);
1198 check_list_contents (&list, values, cnt);
1199 llx_destroy (&list, NULL, NULL, &llx_malloc_mgr);
1201 check (r1 - r0 == next_output - output);
1202 for (j = 0; j < r1 - r0; j++)
1203 check (output[j] == r0 + j);
1205 free_elements (cnt, NULL, elems, elemp, values);
1210 /* Tests llx_destroy. */
1214 const int max_elems = 8;
1218 for (cnt = 0; cnt <= max_elems; cnt++)
1220 struct llx_list list;
1221 struct element **elems;
1229 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1230 check_list_contents (&list, values, cnt);
1232 output = next_output = xnmalloc (cnt, sizeof *output);
1233 llx_destroy (&list, apply_func, &next_output, &llx_malloc_mgr);
1235 check (cnt == next_output - output);
1236 for (j = 0; j < cnt; j++)
1237 check (output[j] == j);
1239 free_elements (cnt, NULL, elems, elemp, values);
1244 /* Tests llx_reverse. */
1248 const int max_elems = 8;
1252 for (cnt = 0; cnt <= max_elems; cnt++)
1253 for (r0 = 0; r0 <= cnt; r0++)
1254 for (r1 = r0; r1 <= cnt; r1++)
1256 struct llx_list list;
1257 struct element **elems;
1263 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1264 check_list_contents (&list, values, cnt);
1267 for (i = 0; i < r0; i++)
1269 for (i = r1 - 1; i >= r0; i--)
1271 for (i = r1; i < cnt; i++)
1274 llx_reverse (elemp[r0], elemp[r1]);
1275 check_list_contents (&list, values, cnt);
1277 free_elements (cnt, &list, elems, elemp, values);
1281 /* Tests llx_next_permutation and llx_prev_permutation when the
1282 permuted values have no duplicates. */
1284 test_permutations_no_dups (void)
1286 const int max_elems = 8;
1289 for (cnt = 0; cnt <= max_elems; cnt++)
1291 struct llx_list list;
1292 struct element **elems;
1294 int *old_values = xnmalloc (cnt, sizeof *values);
1295 int *new_values = xnmalloc (cnt, sizeof *values);
1299 allocate_ascending (cnt, &list, &elems, NULL, &values);
1302 extract_values (&list, old_values, cnt);
1303 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1304 compare_elements, &aux_data))
1306 extract_values (&list, new_values, cnt);
1307 check (lexicographical_compare_3way (new_values, cnt,
1310 compare_ints, NULL) > 0);
1311 memcpy (old_values, new_values, (cnt) * sizeof *old_values);
1314 check (perm_cnt == factorial (cnt));
1315 check_list_contents (&list, values, cnt);
1318 llx_reverse (llx_head (&list), llx_null (&list));
1319 extract_values (&list, old_values, cnt);
1320 while (llx_prev_permutation (llx_head (&list), llx_null (&list),
1321 compare_elements, &aux_data))
1323 extract_values (&list, new_values, cnt);
1324 check (lexicographical_compare_3way (new_values, cnt,
1327 compare_ints, NULL) < 0);
1328 memcpy (old_values, new_values, (cnt) * sizeof *old_values);
1331 check (perm_cnt == factorial (cnt));
1332 llx_reverse (llx_head (&list), llx_null (&list));
1333 check_list_contents (&list, values, cnt);
1335 free_elements (cnt, &list, elems, NULL, values);
1341 /* Tests llx_next_permutation and llx_prev_permutation when the
1342 permuted values contain duplicates. */
1344 test_permutations_with_dups (void)
1346 const int max_elems = 8;
1347 const int max_dup = 3;
1348 const int repetitions = 1024;
1352 for (repeat = 0; repeat < repetitions; repeat++)
1353 for (cnt = 0; cnt < max_elems; cnt++)
1355 struct llx_list list;
1356 struct element **elems;
1359 int *old_values = xnmalloc (max_elems, sizeof *values);
1360 int *new_values = xnmalloc (max_elems, sizeof *values);
1362 unsigned permutation_cnt;
1366 allocate_elements (cnt, &list, &elems, &elemp, &values);
1371 int max = left < max_dup ? left : max_dup;
1372 int n = rand () % max + 1;
1375 int idx = cnt - left--;
1376 values[idx] = elems[idx]->x = value;
1381 permutation_cnt = 1;
1382 extract_values (&list, old_values, cnt);
1383 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1384 compare_elements, &aux_data))
1386 extract_values (&list, new_values, cnt);
1387 check (lexicographical_compare_3way (new_values, cnt,
1390 compare_ints, NULL) > 0);
1391 memcpy (old_values, new_values, cnt * sizeof *old_values);
1394 check (permutation_cnt == expected_perms (values, cnt));
1395 check_list_contents (&list, values, cnt);
1397 permutation_cnt = 1;
1398 llx_reverse (llx_head (&list), llx_null (&list));
1399 extract_values (&list, old_values, cnt);
1400 while (llx_prev_permutation (llx_head (&list), llx_null (&list),
1401 compare_elements, &aux_data))
1403 extract_values (&list, new_values, cnt);
1404 check (lexicographical_compare_3way (new_values, cnt,
1407 compare_ints, NULL) < 0);
1410 llx_reverse (llx_head (&list), llx_null (&list));
1411 check (permutation_cnt == expected_perms (values, cnt));
1412 check_list_contents (&list, values, cnt);
1414 free_elements (cnt, &list, elems, elemp, values);
1420 /* Tests llx_merge when no equal values are to be merged. */
1422 test_merge_no_dups (void)
1424 const int max_elems = 8;
1425 const int max_fillxer = 3;
1427 int merge_cnt, pattern, pfx, gap, sfx, order;
1429 for (merge_cnt = 0; merge_cnt < max_elems; merge_cnt++)
1430 for (pattern = 0; pattern <= (1 << merge_cnt); pattern++)
1431 for (pfx = 0; pfx < max_fillxer; pfx++)
1432 for (gap = 0; gap < max_fillxer; gap++)
1433 for (sfx = 0; sfx < max_fillxer; sfx++)
1434 for (order = 0; order < 2; order++)
1436 struct llx_list list;
1437 struct element **elems;
1441 int list_cnt = pfx + merge_cnt + gap + sfx;
1445 allocate_elements (list_cnt, &list,
1446 &elems, &elemp, &values);
1449 for (i = 0; i < pfx; i++)
1450 elems[j++]->x = 100 + i;
1452 for (i = 0; i < merge_cnt; i++)
1453 if (pattern & (1u << i))
1456 for (i = 0; i < gap; i++)
1457 elems[j++]->x = 200 + i;
1459 for (i = 0; i < merge_cnt; i++)
1460 if (!(pattern & (1u << i)))
1463 for (i = 0; i < sfx; i++)
1464 elems[j++]->x = 300 + i;
1465 check (list_cnt == j);
1468 for (i = 0; i < pfx; i++)
1469 values[j++] = 100 + i;
1471 for (i = 0; i < merge_cnt; i++)
1473 for (i = 0; i < gap; i++)
1474 values[j++] = 200 + i;
1476 for (i = 0; i < merge_cnt; i++)
1478 for (i = 0; i < sfx; i++)
1479 values[j++] = 300 + i;
1480 check (list_cnt == j);
1483 llx_merge (elemp[a0], elemp[a1], elemp[b0], elemp[b1],
1484 compare_elements, &aux_data);
1486 llx_merge (elemp[b0], elemp[b1], elemp[a0], elemp[a1],
1487 compare_elements, &aux_data);
1489 check_list_contents (&list, values, list_cnt);
1491 free_elements (list_cnt, &list, elems, elemp, values);
1495 /* Tests llx_merge when equal values are to be merged. */
1497 test_merge_with_dups (void)
1499 const int max_elems = 8;
1501 int cnt, merge_pat, inc_pat, order;
1503 for (cnt = 0; cnt <= max_elems; cnt++)
1504 for (merge_pat = 0; merge_pat <= (1 << cnt); merge_pat++)
1505 for (inc_pat = 0; inc_pat <= (1 << cnt); inc_pat++)
1506 for (order = 0; order < 2; order++)
1508 struct llx_list list;
1509 struct element **elems;
1516 allocate_elements (cnt, &list, &elems, &elemp, &values);
1519 for (i = k = 0; i < cnt; i++)
1521 if (merge_pat & (1u << i))
1523 if (inc_pat & (1u << i))
1527 for (i = k = 0; i < cnt; i++)
1529 if (!(merge_pat & (1u << i)))
1531 if (inc_pat & (1u << i))
1538 for (i = 0; i < cnt; i++)
1543 for (i = 0; i < mid; i++)
1544 elems[i]->y = 100 + i;
1545 for (i = mid; i < cnt; i++)
1550 for (i = k = 0; i < cnt; i++)
1553 if (inc_pat & (1u << i))
1559 llx_merge (elemp[0], elemp[mid], elemp[mid], elemp[cnt],
1560 compare_elements, &aux_data);
1562 llx_merge (elemp[mid], elemp[cnt], elemp[0], elemp[mid],
1563 compare_elements, &aux_data);
1565 check_list_contents (&list, values, cnt);
1566 check (llx_is_sorted (llx_head (&list), llx_null (&list),
1567 compare_elements_x_y, &aux_data));
1569 free_elements (cnt, &list, elems, elemp, values);
1573 /* Tests llx_sort on all permutations up to a maximum number of
1576 test_sort_exhaustive (void)
1578 const int max_elems = 8;
1581 for (cnt = 0; cnt <= max_elems; cnt++)
1583 struct llx_list list;
1584 struct element **elems;
1587 struct element **perm_elems;
1592 allocate_ascending (cnt, &list, &elems, NULL, &values);
1593 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1596 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1597 compare_elements, &aux_data))
1599 struct llx_list perm_list;
1602 extract_values (&list, perm_values, cnt);
1603 llx_init (&perm_list);
1604 for (j = 0; j < cnt; j++)
1606 perm_elems[j]->x = perm_values[j];
1607 llx_push_tail (&perm_list, perm_elems[j], &llx_malloc_mgr);
1609 llx_sort (llx_head (&perm_list), llx_null (&perm_list),
1610 compare_elements, &aux_data);
1611 check_list_contents (&perm_list, values, cnt);
1612 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1613 compare_elements, &aux_data));
1614 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1617 check (perm_cnt == factorial (cnt));
1619 free_elements (cnt, &list, elems, NULL, values);
1620 free_elements (cnt, NULL, perm_elems, NULL, perm_values);
1624 /* Tests that llx_sort is stable in the presence of equal
1627 test_sort_stable (void)
1629 const int max_elems = 6;
1632 for (cnt = 0; cnt <= max_elems; cnt++)
1633 for (inc_pat = 0; inc_pat <= 1 << cnt; inc_pat++)
1635 struct llx_list list;
1636 struct element **elems;
1639 struct element **perm_elems;
1645 allocate_elements (cnt, &list, &elems, NULL, &values);
1646 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1649 for (i = 0; i < cnt; i++)
1651 elems[i]->x = values[i] = j;
1652 if (inc_pat & (1 << i))
1658 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1659 compare_elements_y, &aux_data))
1661 struct llx_list perm_list;
1663 extract_values (&list, perm_values, cnt);
1664 llx_init (&perm_list);
1665 for (i = 0; i < cnt; i++)
1667 perm_elems[i]->x = perm_values[i];
1668 perm_elems[i]->y = i;
1669 llx_push_tail (&perm_list, perm_elems[i], &llx_malloc_mgr);
1671 llx_sort (llx_head (&perm_list), llx_null (&perm_list),
1672 compare_elements, &aux_data);
1673 check_list_contents (&perm_list, values, cnt);
1674 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1675 compare_elements_x_y, &aux_data));
1676 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1679 check (perm_cnt == factorial (cnt));
1681 free_elements (cnt, &list, elems, NULL, values);
1682 free_elements (cnt, NULL, perm_elems, NULL, perm_values);
1686 /* Tests that llx_sort does not disturb elements outside the
1689 test_sort_subset (void)
1691 const int max_elems = 8;
1693 int cnt, r0, r1, repeat;
1695 for (cnt = 0; cnt <= max_elems; cnt++)
1696 for (repeat = 0; repeat < 100; repeat++)
1697 for (r0 = 0; r0 <= cnt; r0++)
1698 for (r1 = r0; r1 <= cnt; r1++)
1700 struct llx_list list;
1701 struct element **elems;
1705 allocate_random (cnt, &list, &elems, &elemp, &values);
1707 qsort (&values[r0], r1 - r0, sizeof *values, compare_ints_noaux);
1708 llx_sort (elemp[r0], elemp[r1], compare_elements, &aux_data);
1709 check_list_contents (&list, values, cnt);
1711 free_elements (cnt, &list, elems, elemp, values);
1715 /* Tests that llx_sort works with large lists. */
1717 test_sort_big (void)
1719 const int max_elems = 1024;
1723 for (cnt = 0; cnt < max_elems; cnt++)
1725 struct llx_list list;
1726 struct element **elems;
1729 allocate_random (cnt, &list, &elems, NULL, &values);
1731 qsort (values, cnt, sizeof *values, compare_ints_noaux);
1732 llx_sort (llx_head (&list), llx_null (&list), compare_elements, &aux_data);
1733 check_list_contents (&list, values, cnt);
1735 free_elements (cnt, &list, elems, NULL, values);
1739 /* Tests llx_unique. */
1743 const int max_elems = 10;
1745 int *ascending = xnmalloc (max_elems, sizeof *ascending);
1747 int cnt, inc_pat, i, j, unique_values;
1749 for (i = 0; i < max_elems; i++)
1752 for (cnt = 0; cnt < max_elems; cnt++)
1753 for (inc_pat = 0; inc_pat < (1 << cnt); inc_pat++)
1755 struct llx_list list, dups;
1756 struct element **elems;
1759 allocate_elements (cnt, &list, &elems, NULL, &values);
1761 j = unique_values = 0;
1762 for (i = 0; i < cnt; i++)
1764 unique_values = j + 1;
1765 elems[i]->x = values[i] = j;
1766 if (inc_pat & (1 << i))
1769 check_list_contents (&list, values, cnt);
1772 check (llx_unique (llx_head (&list), llx_null (&list),
1774 compare_elements, &aux_data,
1776 == (size_t) unique_values);
1777 check_list_contents (&list, ascending, unique_values);
1779 llx_splice (llx_null (&list), llx_head (&dups), llx_null (&dups));
1780 llx_sort (llx_head (&list), llx_null (&list), compare_elements, &aux_data);
1781 check_list_contents (&list, values, cnt);
1783 llx_destroy (&dups, NULL, NULL, &llx_malloc_mgr);
1784 free_elements (cnt, &list, elems, NULL, values);
1790 /* Tests llx_sort_unique. */
1792 test_sort_unique (void)
1794 const int max_elems = 7;
1797 for (cnt = 0; cnt <= max_elems; cnt++)
1798 for (inc_pat = 0; inc_pat <= 1 << cnt; inc_pat++)
1800 struct llx_list list;
1801 struct element **elems;
1804 struct element **perm_elems;
1813 allocate_elements (cnt, &list, &elems, NULL, &values);
1814 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1817 for (i = 0; i < cnt; i++)
1819 elems[i]->x = values[i] = j;
1821 if (inc_pat & (1 << i))
1825 unique_values = xnmalloc (unique_cnt, sizeof *unique_values);
1826 for (i = 0; i < unique_cnt; i++)
1827 unique_values[i] = i;
1830 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1831 compare_elements, &aux_data))
1833 struct llx_list perm_list;
1835 extract_values (&list, perm_values, cnt);
1836 llx_init (&perm_list);
1837 for (i = 0; i < cnt; i++)
1839 perm_elems[i]->x = perm_values[i];
1840 perm_elems[i]->y = i;
1841 llx_push_tail (&perm_list, perm_elems[i], &llx_malloc_mgr);
1843 llx_sort_unique (llx_head (&perm_list), llx_null (&perm_list), NULL,
1844 compare_elements, &aux_data,
1846 check_list_contents (&perm_list, unique_values, unique_cnt);
1847 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1848 compare_elements_x_y, &aux_data));
1849 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1852 check (perm_cnt == expected_perms (values, cnt));
1854 free_elements (cnt, &list, elems, NULL, values);
1855 free_elements (cnt, NULL, perm_elems, NULL, perm_values);
1856 free (unique_values);
1860 /* Tests llx_insert_ordered. */
1862 test_insert_ordered (void)
1864 const int max_elems = 6;
1867 for (cnt = 0; cnt <= max_elems; cnt++)
1868 for (inc_pat = 0; inc_pat <= 1 << cnt; inc_pat++)
1870 struct llx_list list;
1871 struct element **elems;
1874 struct element **perm_elems;
1880 allocate_elements (cnt, &list, &elems, NULL, &values);
1881 allocate_elements (cnt, NULL, &perm_elems, NULL, &perm_values);
1884 for (i = 0; i < cnt; i++)
1886 elems[i]->x = values[i] = j;
1887 if (inc_pat & (1 << i))
1893 while (llx_next_permutation (llx_head (&list), llx_null (&list),
1894 compare_elements_y, &aux_data))
1896 struct llx_list perm_list;
1898 extract_values (&list, perm_values, cnt);
1899 llx_init (&perm_list);
1900 for (i = 0; i < cnt; i++)
1902 perm_elems[i]->x = perm_values[i];
1903 perm_elems[i]->y = i;
1904 llx_insert_ordered (llx_head (&perm_list),
1905 llx_null (&perm_list),
1907 compare_elements, &aux_data,
1910 check (llx_is_sorted (llx_head (&perm_list), llx_null (&perm_list),
1911 compare_elements_x_y, &aux_data));
1912 llx_destroy (&perm_list, NULL, NULL, &llx_malloc_mgr);
1915 check (perm_cnt == factorial (cnt));
1917 free_elements (cnt, &list, elems, NULL, values);
1918 free_elements (cnt, NULL, perm_elems, NULL, perm_values);
1922 /* Tests llx_partition. */
1924 test_partition (void)
1926 const int max_elems = 10;
1932 for (cnt = 0; cnt < max_elems; cnt++)
1933 for (r0 = 0; r0 <= cnt; r0++)
1934 for (r1 = r0; r1 <= cnt; r1++)
1935 for (pbase = 0; pbase <= (1u << (r1 - r0)); pbase++)
1937 struct llx_list list;
1938 struct element **elems;
1942 unsigned pattern = pbase << r0;
1945 struct llx *part_llx;
1947 allocate_ascending (cnt, &list, &elems, &elemp, &values);
1949 /* Check that llx_find_partition works okay in every
1950 case. We use it after partitioning, too, but that
1951 only tests cases where it returns non-null. */
1952 for (i = r0; i < r1; i++)
1953 if (!(pattern & (1u << i)))
1957 if (pattern & (1u << i))
1959 part_llx = llx_find_partition (elemp[r0], elemp[r1],
1963 check (part_llx == elemp[j]);
1965 check (part_llx == NULL);
1967 /* Figure out expected results. */
1970 for (i = 0; i < r0; i++)
1972 for (i = r0; i < r1; i++)
1973 if (pattern & (1u << i))
1975 for (i = r0; i < r1; i++)
1976 if (!(pattern & (1u << i)))
1978 if (first_false == -1)
1982 if (first_false == -1)
1984 for (i = r1; i < cnt; i++)
1988 /* Partition and check for expected results. */
1989 check (llx_partition (elemp[r0], elemp[r1],
1990 pattern_pred, &pattern)
1991 == elemp[first_false]);
1992 check (llx_find_partition (elemp[r0], elemp[r1],
1993 pattern_pred, &pattern)
1994 == elemp[first_false]);
1995 check_list_contents (&list, values, cnt);
1996 check ((int) llx_count (&list) == cnt);
1998 free_elements (cnt, &list, elems, elemp, values);
2002 /* Tests that allocation failure is gracefully handled. */
2004 test_allocation_failure (void)
2006 struct llx_list list;
2009 check (llx_push_head (&list, NULL, &llx_null_mgr) == NULL);
2010 check (llx_push_tail (&list, NULL, &llx_null_mgr) == NULL);
2011 check (llx_insert (llx_null (&list), NULL, &llx_null_mgr) == NULL);
2012 check_list_contents (&list, NULL, 0);
2017 /* Runs TEST_FUNCTION and prints a message about NAME. */
2019 run_test (void (*test_function) (void), const char *name)
2021 printf ("Running %s test... ", name);
2030 run_test (test_push_pop, "push/pop");
2031 run_test (test_insert_remove, "insert/remove");
2032 run_test (test_swap, "swap");
2033 run_test (test_swap_range, "swap_range");
2034 run_test (test_remove_range, "remove_range");
2035 run_test (test_remove_equal, "remove_equal");
2036 run_test (test_remove_if, "remove_if");
2037 run_test (test_find_equal, "find_equal");
2038 run_test (test_find_if, "find_if");
2039 run_test (test_find_adjacent_equal, "find_adjacent_equal");
2040 run_test (test_count_range, "count_range");
2041 run_test (test_count_equal, "count_equal");
2042 run_test (test_count_if, "count_if");
2043 run_test (test_min_max, "min/max");
2044 run_test (test_lexicographical_compare_3way, "lexicographical_compare_3way");
2045 run_test (test_apply, "apply");
2046 run_test (test_destroy, "destroy");
2047 run_test (test_reverse, "reverse");
2048 run_test (test_permutations_no_dups, "permutations (no dups)");
2049 run_test (test_permutations_with_dups, "permutations (with dups)");
2050 run_test (test_merge_no_dups, "merge (no dups)");
2051 run_test (test_merge_with_dups, "merge (with dups)");
2052 run_test (test_sort_exhaustive, "sort (exhaustive)");
2053 run_test (test_sort_stable, "sort (stability)");
2054 run_test (test_sort_subset, "sort (subset)");
2055 run_test (test_sort_big, "sort (big)");
2056 run_test (test_unique, "unique");
2057 run_test (test_sort_unique, "sort_unique");
2058 run_test (test_insert_ordered, "insert_ordered");
2059 run_test (test_partition, "partition");
2060 run_test (test_allocation_failure, "allocation failure");
2067 compile-command: "gcc -Wall -Wstrict-prototypes -Wmissing-prototypes ll.c llx.c llx-test.c -o llx-test -g"