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>
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 fprintf (stderr
, "%s:%d: check failed\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 N numbers in VALUES. */
167 print_array (int values
[], size_t n
)
172 for (i
= 0; i
< n
; 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 int *pattern
= pattern_
;
227 return (*pattern
& (1u << element
->x
)) != 0;
230 /* Allocates N elements in *ELEMS.
231 Adds the elements to LIST, if it is nonnull.
232 Puts pointers to the elements' list elements in *ELEMP,
233 followed by a pointer to the list null element, if ELEMP is
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 N values of `x' from LIST into VALUES[]. */
273 extract_values (struct llx_list
*list
, int values
[], size_t n
)
277 check (llx_count (list
) == n
);
278 for (x
= llx_head (list
); x
!= llx_null (list
); x
= llx_next (x
))
280 struct element
*e
= llx_data (x
);
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 N elements in ARRAY, each of which is
327 SIZE bytes in size. */
329 random_shuffle (void *array_
, size_t n
, size_t size
)
331 char *array
= array_
;
332 char *tmp
= xmalloc (size
);
335 for (i
= 0; i
< n
; i
++)
337 size_t j
= rand () % (n
- 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 N values in ELEMENTS. */
409 check_list_contents (struct llx_list
*list
, int elements
[], size_t n
)
414 check ((n
== 0) == llx_is_empty (list
));
416 /* Iterate in forward order. */
417 for (llx
= llx_head (list
), i
= 0; i
< n
; llx
= llx_next (llx
), i
++)
419 struct element
*e
= llx_data (llx
);
420 check (elements
[i
] == e
->x
);
421 check (llx
!= llx_null (list
));
423 check (llx
== llx_null (list
));
425 /* Iterate in reverse order. */
426 for (llx
= llx_tail (list
), i
= 0; i
< n
; llx
= llx_prev (llx
), i
++)
428 struct element
*e
= llx_data (llx
);
429 check (elements
[n
- i
- 1] == e
->x
);
430 check (llx
!= llx_null (list
));
432 check (llx
== llx_null (list
));
434 check (llx_count (list
) == n
);
437 /* Lexicographicallxy compares ARRAY1, which contains COUNT1
438 elements of SIZE bytes each, to ARRAY2, which contains COUNT2
439 elements of SIZE bytes, according to COMPARE. Returns a
440 strcmp-type result. AUX is passed to COMPARE as auxiliary
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 (n
= 0; n
< max_elems
; n
++)
531 struct element
**elems
;
533 int *values
= xnmalloc (n
+ 1, sizeof *values
);
535 struct llx_list list
;
536 struct element extra
;
537 struct llx
*extra_llx
;
540 allocate_ascending (n
, &list
, &elems
, &elemp
, NULL
);
542 for (pos
= 0; pos
<= n
; 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
, n
+ 1);
557 llx_remove (extra_llx
, &llx_malloc_mgr
);
559 check_list_contents (&list
, values
, n
);
561 free_elements (n
, &list
, elems
, elemp
, values
);
565 /* Tests swapping individual elements. */
569 const int max_elems
= 8;
572 for (n
= 0; n
<= max_elems
; n
++)
574 struct llx_list list
;
575 struct element
**elems
;
581 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
582 check_list_contents (&list
, values
, n
);
584 for (i
= 0; i
< n
; i
++)
585 for (j
= 0; j
< n
; j
++)
586 for (k
= 0; k
< 2; k
++)
590 llx_swap (elemp
[i
], elemp
[j
]);
592 values
[i
] = values
[j
];
594 check_list_contents (&list
, values
, n
);
597 free_elements (n
, &list
, elems
, elemp
, values
);
601 /* Tests swapping ranges of list elements. */
603 test_swap_range (void)
605 const int max_elems
= 8;
606 int n
, a0
, a1
, b0
, b1
, r
;
608 for (n
= 0; n
<= max_elems
; n
++)
609 for (a0
= 0; a0
<= n
; a0
++)
610 for (a1
= a0
; a1
<= n
; a1
++)
611 for (b0
= a1
; b0
<= n
; b0
++)
612 for (b1
= b0
; b1
<= n
; b1
++)
613 for (r
= 0; r
< 2; r
++)
615 struct llx_list list
;
616 struct element
**elems
;
622 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
623 check_list_contents (&list
, values
, n
);
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
< n
; 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
, n
);
644 free_elements (n
, &list
, elems
, elemp
, values
);
648 /* Tests removing ranges of list elements. */
650 test_remove_range (void)
652 const int max_elems
= 8;
656 for (n
= 0; n
<= max_elems
; n
++)
657 for (r0
= 0; r0
<= n
; r0
++)
658 for (r1
= r0
; r1
<= n
; r1
++)
660 struct llx_list list
;
661 struct element
**elems
;
667 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
668 check_list_contents (&list
, values
, n
);
671 for (i
= 0; i
< r0
; i
++)
673 for (i
= r1
; i
< n
; i
++)
676 llx_remove_range (elemp
[r0
], elemp
[r1
], &llx_malloc_mgr
);
677 check_list_contents (&list
, values
, j
);
679 free_elements (n
, &list
, elems
, elemp
, values
);
683 /* Tests llx_remove_equal. */
685 test_remove_equal (void)
687 const int max_elems
= 8;
689 int n
, r0
, r1
, eq_pat
;
691 for (n
= 0; n
<= max_elems
; n
++)
692 for (r0
= 0; r0
<= n
; r0
++)
693 for (r1
= r0
; r1
<= n
; r1
++)
694 for (eq_pat
= 0; eq_pat
<= 1 << n
; eq_pat
++)
696 struct llx_list list
;
697 struct element
**elems
;
701 struct element to_remove
;
705 allocate_elements (n
, &list
, &elems
, &elemp
, &values
);
708 for (i
= 0; i
< n
; i
++)
710 int x
= eq_pat
& (1 << i
) ? -1 : i
;
711 bool delete = x
== -1 && r0
<= i
&& i
< r1
;
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 (n
, &list
, elems
, elemp
, values
);
728 /* Tests llx_remove_if. */
730 test_remove_if (void)
732 const int max_elems
= 8;
734 int n
, r0
, r1
, pattern
;
736 for (n
= 0; n
<= max_elems
; n
++)
737 for (r0
= 0; r0
<= n
; r0
++)
738 for (r1
= r0
; r1
<= n
; r1
++)
739 for (pattern
= 0; pattern
<= 1 << n
; pattern
++)
741 struct llx_list list
;
742 struct element
**elems
;
749 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
752 for (i
= 0; i
< n
; 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 (n
, &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 n
, r0
, r1
, eq_pat
;
780 for (n
= 0; n
<= max_elems
; n
++)
781 for (eq_pat
= 0; eq_pat
<= 1 << n
; eq_pat
++)
783 struct llx_list list
;
784 struct element
**elems
;
788 struct element to_find
;
792 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
794 for (i
= 0; i
< n
; i
++)
795 if (eq_pat
& (1 << i
))
796 values
[i
] = elems
[i
]->x
= -1;
799 for (r0
= 0; r0
<= n
; r0
++)
800 for (r1
= r0
; r1
<= n
; r1
++)
801 helper (r0
, r1
, eq_pat
, &to_find
, elemp
);
803 check_list_contents (&list
, values
, n
);
805 free_elements (n
, &list
, elems
, elemp
, values
);
809 /* Tests, via HELPER, a function that looks at list elements for
810 which a given predicate returns true. */
812 test_examine_if_range (void (*helper
) (int r0
, int r1
, int eq_pat
,
815 const int max_elems
= 8;
817 int n
, r0
, r1
, eq_pat
;
819 for (n
= 0; n
<= max_elems
; n
++)
820 for (eq_pat
= 0; eq_pat
<= 1 << n
; eq_pat
++)
822 struct llx_list list
;
823 struct element
**elems
;
827 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
829 for (r0
= 0; r0
<= n
; r0
++)
830 for (r1
= r0
; r1
<= n
; r1
++)
831 helper (r0
, r1
, eq_pat
, elemp
);
833 check_list_contents (&list
, values
, n
);
835 free_elements (n
, &list
, elems
, elemp
, values
);
839 /* Helper function for testing llx_find_equal. */
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 /* Tests llx_find(). */
867 const int max_elems
= 8;
871 for (n
= 0; n
<= max_elems
; n
++)
873 struct llx_list list
;
874 struct element
**elems
;
880 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
882 for (i
= 0; i
< n
; i
++)
883 check (llx_find (llx_head (&list
), llx_null (&list
), elems
[i
])
885 check (llx_find (llx_head (&list
), llx_null (&list
), NULL
) == NULL
);
887 free_elements (n
, &list
, elems
, elemp
, values
);
891 /* Helper function for testing llx_find_if. */
893 test_find_if_helper (int r0
, int r1
, int eq_pat
, struct llx
**elemp
)
895 struct llx
*match
= llx_find_if (elemp
[r0
], elemp
[r1
],
896 pattern_pred
, &eq_pat
);
899 for (i
= r0
; i
< r1
; i
++)
900 if (eq_pat
& (1 << i
))
903 check (match
== elemp
[i
]);
906 /* Tests llx_find_if. */
910 test_examine_if_range (test_find_if_helper
);
913 /* Tests llx_find_adjacent_equal. */
915 test_find_adjacent_equal (void)
917 const int max_elems
= 8;
921 for (n
= 0; n
<= max_elems
; n
++)
922 for (eq_pat
= 0; eq_pat
<= 1 << n
; eq_pat
++)
924 struct llx_list list
;
925 struct element
**elems
;
932 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
935 for (i
= 0; i
< n
- 1; i
++)
938 if (eq_pat
& (1 << i
))
940 values
[i
] = elems
[i
]->x
= match
;
941 values
[i
+ 1] = elems
[i
+ 1]->x
= match
;
947 for (i
= 0; i
<= n
; i
++)
949 struct llx
*llx1
= llx_find_adjacent_equal (elemp
[i
], llx_null (&list
),
955 llx2
= llx_null (&list
);
956 for (j
= i
; j
< n
- 1; j
++)
957 if (eq_pat
& (1 << j
))
962 check (llx1
== llx2
);
964 check_list_contents (&list
, values
, n
);
966 free_elements (n
, &list
, elems
, elemp
, values
);
970 /* Helper function for testing llx_count_range. */
972 test_count_range_helper (int r0
, int r1
, int eq_pat UNUSED
, struct llx
**elemp
)
974 check ((int) llx_count_range (elemp
[r0
], elemp
[r1
]) == r1
- r0
);
977 /* Tests llx_count_range. */
979 test_count_range (void)
981 test_examine_if_range (test_count_range_helper
);
984 /* Helper function for testing llx_count_equal. */
986 test_count_equal_helper (int r0
, int r1
, int eq_pat
,
987 const void *to_find
, struct llx
**elemp
)
992 count1
= llx_count_equal (elemp
[r0
], elemp
[r1
], to_find
,
993 compare_elements
, &aux_data
);
995 for (i
= r0
; i
< r1
; i
++)
996 if (eq_pat
& (1 << i
))
999 check (count1
== count2
);
1002 /* Tests llx_count_equal. */
1004 test_count_equal (void)
1006 test_examine_equal_range (test_count_equal_helper
);
1009 /* Helper function for testing llx_count_if. */
1011 test_count_if_helper (int r0
, int r1
, int eq_pat
, struct llx
**elemp
)
1017 count1
= llx_count_if (elemp
[r0
], elemp
[r1
], pattern_pred
, &eq_pat
);
1020 for (i
= r0
; i
< r1
; i
++)
1021 if (eq_pat
& (1 << i
))
1024 check (count1
== count2
);
1027 /* Tests llx_count_if. */
1029 test_count_if (void)
1031 test_examine_if_range (test_count_if_helper
);
1036 factorial (unsigned int n
)
1038 unsigned int value
= 1;
1044 /* Returns the number of permutations of the N values in
1045 VALUES. If VALUES contains duplicates, they must be
1048 expected_perms (int *values
, size_t n
)
1051 unsigned int n_perms
;
1053 n_perms
= factorial (n
);
1054 for (i
= 0; i
< n
; i
= j
)
1056 for (j
= i
+ 1; j
< n
; j
++)
1057 if (values
[i
] != values
[j
])
1059 n_perms
/= factorial (j
- i
);
1064 /* Tests llx_min and llx_max. */
1068 const int max_elems
= 6;
1071 for (n
= 0; n
<= max_elems
; n
++)
1073 struct llx_list list
;
1074 struct element
**elems
;
1077 int *new_values
= xnmalloc (n
, sizeof *values
);
1081 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
1084 while (llx_next_permutation (llx_head (&list
), llx_null (&list
),
1085 compare_elements
, &aux_data
))
1091 for (i
= 0, x
= llx_head (&list
); x
!= llx_null (&list
);
1092 x
= llx_next (x
), i
++)
1094 struct element
*e
= llx_data (x
);
1096 new_values
[i
] = e
->x
;
1098 for (r0
= 0; r0
<= n
; r0
++)
1099 for (r1
= r0
; r1
<= n
; r1
++)
1101 struct llx
*min
= llx_min (elemp
[r0
], elemp
[r1
],
1102 compare_elements
, &aux_data
);
1103 struct llx
*max
= llx_max (elemp
[r0
], elemp
[r1
],
1104 compare_elements
, &aux_data
);
1107 check (min
== elemp
[r1
]);
1108 check (max
== elemp
[r1
]);
1112 struct element
*min_elem
= llx_data (min
);
1113 struct element
*max_elem
= llx_data (max
);
1114 int min_int
, max_int
;
1117 min_int
= max_int
= new_values
[r0
];
1118 for (i
= r0
; i
< r1
; i
++)
1120 int value
= new_values
[i
];
1121 if (value
< min_int
)
1123 if (value
> max_int
)
1126 check (min
!= elemp
[r1
] && min_elem
->x
== min_int
);
1127 check (max
!= elemp
[r1
] && max_elem
->x
== max_int
);
1132 check (n_perms
== factorial (n
));
1133 check_list_contents (&list
, values
, n
);
1135 free_elements (n
, &list
, elems
, elemp
, values
);
1140 /* Tests llx_lexicographical_compare_3way. */
1142 test_lexicographical_compare_3way (void)
1144 const int max_elems
= 4;
1146 int n_a
, pat_a
, n_b
, pat_b
;
1148 for (n_a
= 0; n_a
<= max_elems
; n_a
++)
1149 for (pat_a
= 0; pat_a
<= 1 << n_a
; pat_a
++)
1150 for (n_b
= 0; n_b
<= max_elems
; n_b
++)
1151 for (pat_b
= 0; pat_b
<= 1 << n_b
; pat_b
++)
1153 struct llx_list list_a
, list_b
;
1154 struct element
**elems_a
, **elems_b
;
1155 struct llx
**elemp_a
, **elemp_b
;
1156 int *values_a
, *values_b
;
1160 allocate_pattern (n_a
, pat_a
,
1161 &list_a
, &elems_a
, &elemp_a
, &values_a
);
1162 allocate_pattern (n_b
, pat_b
,
1163 &list_b
, &elems_b
, &elemp_b
, &values_b
);
1165 for (a0
= 0; a0
<= n_a
; a0
++)
1166 for (a1
= a0
; a1
<= n_a
; a1
++)
1167 for (b0
= 0; b0
<= n_b
; b0
++)
1168 for (b1
= b0
; b1
<= n_b
; b1
++)
1170 int a_ordering
= lexicographical_compare_3way (
1171 values_a
+ a0
, a1
- a0
,
1172 values_b
+ b0
, b1
- b0
,
1174 compare_ints
, NULL
);
1176 int b_ordering
= llx_lexicographical_compare_3way (
1177 elemp_a
[a0
], elemp_a
[a1
],
1178 elemp_b
[b0
], elemp_b
[b1
],
1179 compare_elements
, &aux_data
);
1181 check (a_ordering
== b_ordering
);
1184 free_elements (n_a
, &list_a
, elems_a
, elemp_a
, values_a
);
1185 free_elements (n_b
, &list_b
, elems_b
, elemp_b
, values_b
);
1189 /* Appends the `x' value in element E to the array pointed to by
1190 NEXT_OUTPUT, and advances NEXT_OUTPUT to the next position. */
1192 apply_func (void *e_
, void *next_output_
)
1194 struct element
*e
= e_
;
1195 int **next_output
= next_output_
;
1197 *(*next_output
)++ = e
->x
;
1200 /* Tests llx_apply. */
1204 const int max_elems
= 8;
1208 for (n
= 0; n
<= max_elems
; n
++)
1209 for (r0
= 0; r0
<= n
; r0
++)
1210 for (r1
= r0
; r1
<= n
; r1
++)
1212 struct llx_list list
;
1213 struct element
**elems
;
1221 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
1222 check_list_contents (&list
, values
, n
);
1224 output
= next_output
= xnmalloc (n
, sizeof *output
);
1225 llx_apply (elemp
[r0
], elemp
[r1
], apply_func
, &next_output
);
1226 check_list_contents (&list
, values
, n
);
1227 llx_destroy (&list
, NULL
, NULL
, &llx_malloc_mgr
);
1229 check (r1
- r0
== next_output
- output
);
1230 for (j
= 0; j
< r1
- r0
; j
++)
1231 check (output
[j
] == r0
+ j
);
1233 free_elements (n
, NULL
, elems
, elemp
, values
);
1238 /* Tests llx_destroy. */
1242 const int max_elems
= 8;
1246 for (n
= 0; n
<= max_elems
; n
++)
1248 struct llx_list list
;
1249 struct element
**elems
;
1257 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
1258 check_list_contents (&list
, values
, n
);
1260 output
= next_output
= xnmalloc (n
, sizeof *output
);
1261 llx_destroy (&list
, apply_func
, &next_output
, &llx_malloc_mgr
);
1263 check (n
== next_output
- output
);
1264 for (j
= 0; j
< n
; j
++)
1265 check (output
[j
] == j
);
1267 free_elements (n
, NULL
, elems
, elemp
, values
);
1272 /* Tests llx_reverse. */
1276 const int max_elems
= 8;
1280 for (n
= 0; n
<= max_elems
; n
++)
1281 for (r0
= 0; r0
<= n
; r0
++)
1282 for (r1
= r0
; r1
<= n
; r1
++)
1284 struct llx_list list
;
1285 struct element
**elems
;
1291 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
1292 check_list_contents (&list
, values
, n
);
1295 for (i
= 0; i
< r0
; i
++)
1297 for (i
= r1
- 1; i
>= r0
; i
--)
1299 for (i
= r1
; i
< n
; i
++)
1302 llx_reverse (elemp
[r0
], elemp
[r1
]);
1303 check_list_contents (&list
, values
, n
);
1305 free_elements (n
, &list
, elems
, elemp
, values
);
1309 /* Tests llx_next_permutation and llx_prev_permutation when the
1310 permuted values have no duplicates. */
1312 test_permutations_no_dups (void)
1314 const int max_elems
= 8;
1317 for (n
= 0; n
<= max_elems
; n
++)
1319 struct llx_list list
;
1320 struct element
**elems
;
1322 int *old_values
= xnmalloc (n
, sizeof *values
);
1323 int *new_values
= xnmalloc (n
, sizeof *values
);
1327 allocate_ascending (n
, &list
, &elems
, NULL
, &values
);
1330 extract_values (&list
, old_values
, n
);
1331 while (llx_next_permutation (llx_head (&list
), llx_null (&list
),
1332 compare_elements
, &aux_data
))
1334 extract_values (&list
, new_values
, n
);
1335 check (lexicographical_compare_3way (new_values
, n
,
1338 compare_ints
, NULL
) > 0);
1339 memcpy (old_values
, new_values
, (n
) * sizeof *old_values
);
1342 check (n_perms
== factorial (n
));
1343 check_list_contents (&list
, values
, n
);
1346 llx_reverse (llx_head (&list
), llx_null (&list
));
1347 extract_values (&list
, old_values
, n
);
1348 while (llx_prev_permutation (llx_head (&list
), llx_null (&list
),
1349 compare_elements
, &aux_data
))
1351 extract_values (&list
, new_values
, n
);
1352 check (lexicographical_compare_3way (new_values
, n
,
1355 compare_ints
, NULL
) < 0);
1356 memcpy (old_values
, new_values
, (n
) * sizeof *old_values
);
1359 check (n_perms
== factorial (n
));
1360 llx_reverse (llx_head (&list
), llx_null (&list
));
1361 check_list_contents (&list
, values
, n
);
1363 free_elements (n
, &list
, elems
, NULL
, values
);
1369 /* Tests llx_next_permutation and llx_prev_permutation when the
1370 permuted values contain duplicates. */
1372 test_permutations_with_dups (void)
1374 const int max_elems
= 8;
1375 const int max_dup
= 3;
1376 const int repetitions
= 1024;
1378 for (int repeat
= 0; repeat
< repetitions
; repeat
++)
1379 for (int n_elems
= 0; n_elems
< max_elems
; n_elems
++)
1381 struct llx_list list
;
1382 struct element
**elems
;
1385 int *old_values
= xnmalloc (max_elems
, sizeof *values
);
1386 int *new_values
= xnmalloc (max_elems
, sizeof *values
);
1388 unsigned int n_permutations
;
1392 allocate_elements (n_elems
, &list
, &elems
, &elemp
, &values
);
1397 int max
= left
< max_dup
? left
: max_dup
;
1398 int n
= rand () % max
+ 1;
1401 int idx
= n_elems
- left
--;
1402 values
[idx
] = elems
[idx
]->x
= value
;
1408 extract_values (&list
, old_values
, n_elems
);
1409 while (llx_next_permutation (llx_head (&list
), llx_null (&list
),
1410 compare_elements
, &aux_data
))
1412 extract_values (&list
, new_values
, n_elems
);
1413 check (lexicographical_compare_3way (new_values
, n_elems
,
1414 old_values
, n_elems
,
1416 compare_ints
, NULL
) > 0);
1417 memcpy (old_values
, new_values
, n_elems
* sizeof *old_values
);
1420 check (n_permutations
== expected_perms (values
, n_elems
));
1421 check_list_contents (&list
, values
, n_elems
);
1424 llx_reverse (llx_head (&list
), llx_null (&list
));
1425 extract_values (&list
, old_values
, n_elems
);
1426 while (llx_prev_permutation (llx_head (&list
), llx_null (&list
),
1427 compare_elements
, &aux_data
))
1429 extract_values (&list
, new_values
, n_elems
);
1430 check (lexicographical_compare_3way (new_values
, n_elems
,
1431 old_values
, n_elems
,
1433 compare_ints
, NULL
) < 0);
1436 llx_reverse (llx_head (&list
), llx_null (&list
));
1437 check (n_permutations
== expected_perms (values
, n_elems
));
1438 check_list_contents (&list
, values
, n_elems
);
1440 free_elements (n_elems
, &list
, elems
, elemp
, values
);
1446 /* Tests llx_merge when no equal values are to be merged. */
1448 test_merge_no_dups (void)
1450 const int max_elems
= 8;
1451 const int max_fillxer
= 3;
1453 int n_merges
, pattern
, pfx
, gap
, sfx
, order
;
1455 for (n_merges
= 0; n_merges
< max_elems
; n_merges
++)
1456 for (pattern
= 0; pattern
<= (1 << n_merges
); pattern
++)
1457 for (pfx
= 0; pfx
< max_fillxer
; pfx
++)
1458 for (gap
= 0; gap
< max_fillxer
; gap
++)
1459 for (sfx
= 0; sfx
< max_fillxer
; sfx
++)
1460 for (order
= 0; order
< 2; order
++)
1462 struct llx_list list
;
1463 struct element
**elems
;
1467 int n_lists
= pfx
+ n_merges
+ gap
+ sfx
;
1471 allocate_elements (n_lists
, &list
,
1472 &elems
, &elemp
, &values
);
1475 for (i
= 0; i
< pfx
; i
++)
1476 elems
[j
++]->x
= 100 + i
;
1478 for (i
= 0; i
< n_merges
; i
++)
1479 if (pattern
& (1u << i
))
1482 for (i
= 0; i
< gap
; i
++)
1483 elems
[j
++]->x
= 200 + i
;
1485 for (i
= 0; i
< n_merges
; i
++)
1486 if (!(pattern
& (1u << i
)))
1489 for (i
= 0; i
< sfx
; i
++)
1490 elems
[j
++]->x
= 300 + i
;
1491 check (n_lists
== j
);
1494 for (i
= 0; i
< pfx
; i
++)
1495 values
[j
++] = 100 + i
;
1497 for (i
= 0; i
< n_merges
; i
++)
1499 for (i
= 0; i
< gap
; i
++)
1500 values
[j
++] = 200 + i
;
1502 for (i
= 0; i
< n_merges
; i
++)
1504 for (i
= 0; i
< sfx
; i
++)
1505 values
[j
++] = 300 + i
;
1506 check (n_lists
== j
);
1509 llx_merge (elemp
[a0
], elemp
[a1
], elemp
[b0
], elemp
[b1
],
1510 compare_elements
, &aux_data
);
1512 llx_merge (elemp
[b0
], elemp
[b1
], elemp
[a0
], elemp
[a1
],
1513 compare_elements
, &aux_data
);
1515 check_list_contents (&list
, values
, n_lists
);
1517 free_elements (n_lists
, &list
, elems
, elemp
, values
);
1521 /* Tests llx_merge when equal values are to be merged. */
1523 test_merge_with_dups (void)
1525 const int max_elems
= 8;
1527 int n
, merge_pat
, inc_pat
, order
;
1529 for (n
= 0; n
<= max_elems
; n
++)
1530 for (merge_pat
= 0; merge_pat
<= (1 << n
); merge_pat
++)
1531 for (inc_pat
= 0; inc_pat
<= (1 << n
); inc_pat
++)
1532 for (order
= 0; order
< 2; order
++)
1534 struct llx_list list
;
1535 struct element
**elems
;
1542 allocate_elements (n
, &list
, &elems
, &elemp
, &values
);
1545 for (i
= k
= 0; i
< n
; i
++)
1547 if (merge_pat
& (1u << i
))
1549 if (inc_pat
& (1u << i
))
1553 for (i
= k
= 0; i
< n
; i
++)
1555 if (!(merge_pat
& (1u << i
)))
1557 if (inc_pat
& (1u << i
))
1564 for (i
= 0; i
< n
; i
++)
1569 for (i
= 0; i
< mid
; i
++)
1570 elems
[i
]->y
= 100 + i
;
1571 for (i
= mid
; i
< n
; i
++)
1576 for (i
= k
= 0; i
< n
; i
++)
1579 if (inc_pat
& (1u << i
))
1585 llx_merge (elemp
[0], elemp
[mid
], elemp
[mid
], elemp
[n
],
1586 compare_elements
, &aux_data
);
1588 llx_merge (elemp
[mid
], elemp
[n
], elemp
[0], elemp
[mid
],
1589 compare_elements
, &aux_data
);
1591 check_list_contents (&list
, values
, n
);
1592 check (llx_is_sorted (llx_head (&list
), llx_null (&list
),
1593 compare_elements_x_y
, &aux_data
));
1595 free_elements (n
, &list
, elems
, elemp
, values
);
1599 /* Tests llx_sort on all permutations up to a maximum number of
1602 test_sort_exhaustive (void)
1604 const int max_elems
= 8;
1607 for (n
= 0; n
<= max_elems
; n
++)
1609 struct llx_list list
;
1610 struct element
**elems
;
1613 struct element
**perm_elems
;
1618 allocate_ascending (n
, &list
, &elems
, NULL
, &values
);
1619 allocate_elements (n
, NULL
, &perm_elems
, NULL
, &perm_values
);
1622 while (llx_next_permutation (llx_head (&list
), llx_null (&list
),
1623 compare_elements
, &aux_data
))
1625 struct llx_list perm_list
;
1628 extract_values (&list
, perm_values
, n
);
1629 llx_init (&perm_list
);
1630 for (j
= 0; j
< n
; j
++)
1632 perm_elems
[j
]->x
= perm_values
[j
];
1633 llx_push_tail (&perm_list
, perm_elems
[j
], &llx_malloc_mgr
);
1635 llx_sort (llx_head (&perm_list
), llx_null (&perm_list
),
1636 compare_elements
, &aux_data
);
1637 check_list_contents (&perm_list
, values
, n
);
1638 check (llx_is_sorted (llx_head (&perm_list
), llx_null (&perm_list
),
1639 compare_elements
, &aux_data
));
1640 llx_destroy (&perm_list
, NULL
, NULL
, &llx_malloc_mgr
);
1643 check (n_perms
== factorial (n
));
1645 free_elements (n
, &list
, elems
, NULL
, values
);
1646 free_elements (n
, NULL
, perm_elems
, NULL
, perm_values
);
1650 /* Tests that llx_sort is stable in the presence of equal
1653 test_sort_stable (void)
1655 const int max_elems
= 6;
1658 for (n
= 0; n
<= max_elems
; n
++)
1659 for (inc_pat
= 0; inc_pat
<= 1 << n
; inc_pat
++)
1661 struct llx_list list
;
1662 struct element
**elems
;
1665 struct element
**perm_elems
;
1671 allocate_elements (n
, &list
, &elems
, NULL
, &values
);
1672 allocate_elements (n
, NULL
, &perm_elems
, NULL
, &perm_values
);
1675 for (i
= 0; i
< n
; i
++)
1677 elems
[i
]->x
= values
[i
] = j
;
1678 if (inc_pat
& (1 << i
))
1684 while (llx_next_permutation (llx_head (&list
), llx_null (&list
),
1685 compare_elements_y
, &aux_data
))
1687 struct llx_list perm_list
;
1689 extract_values (&list
, perm_values
, n
);
1690 llx_init (&perm_list
);
1691 for (i
= 0; i
< n
; i
++)
1693 perm_elems
[i
]->x
= perm_values
[i
];
1694 perm_elems
[i
]->y
= i
;
1695 llx_push_tail (&perm_list
, perm_elems
[i
], &llx_malloc_mgr
);
1697 llx_sort (llx_head (&perm_list
), llx_null (&perm_list
),
1698 compare_elements
, &aux_data
);
1699 check_list_contents (&perm_list
, values
, n
);
1700 check (llx_is_sorted (llx_head (&perm_list
), llx_null (&perm_list
),
1701 compare_elements_x_y
, &aux_data
));
1702 llx_destroy (&perm_list
, NULL
, NULL
, &llx_malloc_mgr
);
1705 check (n_perms
== factorial (n
));
1707 free_elements (n
, &list
, elems
, NULL
, values
);
1708 free_elements (n
, NULL
, perm_elems
, NULL
, perm_values
);
1712 /* Tests that llx_sort does not disturb elements outside the
1715 test_sort_subset (void)
1717 const int max_elems
= 8;
1719 int n
, r0
, r1
, repeat
;
1721 for (n
= 0; n
<= max_elems
; n
++)
1722 for (repeat
= 0; repeat
< 100; repeat
++)
1723 for (r0
= 0; r0
<= n
; r0
++)
1724 for (r1
= r0
; r1
<= n
; r1
++)
1726 struct llx_list list
;
1727 struct element
**elems
;
1731 allocate_random (n
, &list
, &elems
, &elemp
, &values
);
1733 qsort (&values
[r0
], r1
- r0
, sizeof *values
, compare_ints_noaux
);
1734 llx_sort (elemp
[r0
], elemp
[r1
], compare_elements
, &aux_data
);
1735 check_list_contents (&list
, values
, n
);
1737 free_elements (n
, &list
, elems
, elemp
, values
);
1741 /* Tests that llx_sort works with large lists. */
1743 test_sort_big (void)
1745 const int max_elems
= 1024;
1749 for (n
= 0; n
< max_elems
; n
++)
1751 struct llx_list list
;
1752 struct element
**elems
;
1755 allocate_random (n
, &list
, &elems
, NULL
, &values
);
1757 qsort (values
, n
, sizeof *values
, compare_ints_noaux
);
1758 llx_sort (llx_head (&list
), llx_null (&list
), compare_elements
, &aux_data
);
1759 check_list_contents (&list
, values
, n
);
1761 free_elements (n
, &list
, elems
, NULL
, values
);
1765 /* Tests llx_unique. */
1769 const int max_elems
= 10;
1771 int *ascending
= xnmalloc (max_elems
, sizeof *ascending
);
1773 int n
, inc_pat
, i
, j
, unique_values
;
1775 for (i
= 0; i
< max_elems
; i
++)
1778 for (n
= 0; n
< max_elems
; n
++)
1779 for (inc_pat
= 0; inc_pat
< (1 << n
); inc_pat
++)
1781 struct llx_list list
, dups
;
1782 struct element
**elems
;
1785 allocate_elements (n
, &list
, &elems
, NULL
, &values
);
1787 j
= unique_values
= 0;
1788 for (i
= 0; i
< n
; i
++)
1790 unique_values
= j
+ 1;
1791 elems
[i
]->x
= values
[i
] = j
;
1792 if (inc_pat
& (1 << i
))
1795 check_list_contents (&list
, values
, n
);
1798 check (llx_unique (llx_head (&list
), llx_null (&list
),
1800 compare_elements
, &aux_data
,
1802 == (size_t) unique_values
);
1803 check_list_contents (&list
, ascending
, unique_values
);
1805 llx_splice (llx_null (&list
), llx_head (&dups
), llx_null (&dups
));
1806 llx_sort (llx_head (&list
), llx_null (&list
), compare_elements
, &aux_data
);
1807 check_list_contents (&list
, values
, n
);
1809 llx_destroy (&dups
, NULL
, NULL
, &llx_malloc_mgr
);
1810 free_elements (n
, &list
, elems
, NULL
, values
);
1816 /* Tests llx_sort_unique. */
1818 test_sort_unique (void)
1820 const int max_elems
= 7;
1823 for (n
= 0; n
<= max_elems
; n
++)
1824 for (inc_pat
= 0; inc_pat
<= 1 << n
; inc_pat
++)
1826 struct llx_list list
;
1827 struct element
**elems
;
1830 struct element
**perm_elems
;
1839 allocate_elements (n
, &list
, &elems
, NULL
, &values
);
1840 allocate_elements (n
, NULL
, &perm_elems
, NULL
, &perm_values
);
1843 for (i
= 0; i
< n
; i
++)
1845 elems
[i
]->x
= values
[i
] = j
;
1847 if (inc_pat
& (1 << i
))
1851 unique_values
= xnmalloc (n_uniques
, sizeof *unique_values
);
1852 for (i
= 0; i
< n_uniques
; i
++)
1853 unique_values
[i
] = i
;
1856 while (llx_next_permutation (llx_head (&list
), llx_null (&list
),
1857 compare_elements
, &aux_data
))
1859 struct llx_list perm_list
;
1861 extract_values (&list
, perm_values
, n
);
1862 llx_init (&perm_list
);
1863 for (i
= 0; i
< n
; i
++)
1865 perm_elems
[i
]->x
= perm_values
[i
];
1866 perm_elems
[i
]->y
= i
;
1867 llx_push_tail (&perm_list
, perm_elems
[i
], &llx_malloc_mgr
);
1869 llx_sort_unique (llx_head (&perm_list
), llx_null (&perm_list
), NULL
,
1870 compare_elements
, &aux_data
,
1872 check_list_contents (&perm_list
, unique_values
, n_uniques
);
1873 check (llx_is_sorted (llx_head (&perm_list
), llx_null (&perm_list
),
1874 compare_elements_x_y
, &aux_data
));
1875 llx_destroy (&perm_list
, NULL
, NULL
, &llx_malloc_mgr
);
1878 check (n_perms
== expected_perms (values
, n
));
1880 free_elements (n
, &list
, elems
, NULL
, values
);
1881 free_elements (n
, NULL
, perm_elems
, NULL
, perm_values
);
1882 free (unique_values
);
1886 /* Tests llx_insert_ordered. */
1888 test_insert_ordered (void)
1890 const int max_elems
= 6;
1893 for (n
= 0; n
<= max_elems
; n
++)
1894 for (inc_pat
= 0; inc_pat
<= 1 << n
; inc_pat
++)
1896 struct llx_list list
;
1897 struct element
**elems
;
1900 struct element
**perm_elems
;
1906 allocate_elements (n
, &list
, &elems
, NULL
, &values
);
1907 allocate_elements (n
, NULL
, &perm_elems
, NULL
, &perm_values
);
1910 for (i
= 0; i
< n
; i
++)
1912 elems
[i
]->x
= values
[i
] = j
;
1913 if (inc_pat
& (1 << i
))
1919 while (llx_next_permutation (llx_head (&list
), llx_null (&list
),
1920 compare_elements_y
, &aux_data
))
1922 struct llx_list perm_list
;
1924 extract_values (&list
, perm_values
, n
);
1925 llx_init (&perm_list
);
1926 for (i
= 0; i
< n
; i
++)
1928 perm_elems
[i
]->x
= perm_values
[i
];
1929 perm_elems
[i
]->y
= i
;
1930 llx_insert_ordered (llx_head (&perm_list
),
1931 llx_null (&perm_list
),
1933 compare_elements
, &aux_data
,
1936 check (llx_is_sorted (llx_head (&perm_list
), llx_null (&perm_list
),
1937 compare_elements_x_y
, &aux_data
));
1938 llx_destroy (&perm_list
, NULL
, NULL
, &llx_malloc_mgr
);
1941 check (n_perms
== factorial (n
));
1943 free_elements (n
, &list
, elems
, NULL
, values
);
1944 free_elements (n
, NULL
, perm_elems
, NULL
, perm_values
);
1948 /* Tests llx_partition. */
1950 test_partition (void)
1952 const int max_elems
= 10;
1958 for (n
= 0; n
< max_elems
; n
++)
1959 for (r0
= 0; r0
<= n
; r0
++)
1960 for (r1
= r0
; r1
<= n
; r1
++)
1961 for (pbase
= 0; pbase
<= (1u << (r1
- r0
)); pbase
++)
1963 struct llx_list list
;
1964 struct element
**elems
;
1968 unsigned int pattern
= pbase
<< r0
;
1971 struct llx
*part_llx
;
1973 allocate_ascending (n
, &list
, &elems
, &elemp
, &values
);
1975 /* Check that llx_find_partition works okay in every
1976 case. We use it after partitioning, too, but that
1977 only tests cases where it returns non-null. */
1978 for (i
= r0
; i
< r1
; i
++)
1979 if (!(pattern
& (1u << i
)))
1983 if (pattern
& (1u << i
))
1985 part_llx
= llx_find_partition (elemp
[r0
], elemp
[r1
],
1989 check (part_llx
== elemp
[j
]);
1991 check (part_llx
== NULL
);
1993 /* Figure out expected results. */
1996 for (i
= 0; i
< r0
; i
++)
1998 for (i
= r0
; i
< r1
; i
++)
1999 if (pattern
& (1u << i
))
2001 for (i
= r0
; i
< r1
; i
++)
2002 if (!(pattern
& (1u << i
)))
2004 if (first_false
== -1)
2008 if (first_false
== -1)
2010 for (i
= r1
; i
< n
; i
++)
2014 /* Partition and check for expected results. */
2015 check (llx_partition (elemp
[r0
], elemp
[r1
],
2016 pattern_pred
, &pattern
)
2017 == elemp
[first_false
]);
2018 check (llx_find_partition (elemp
[r0
], elemp
[r1
],
2019 pattern_pred
, &pattern
)
2020 == elemp
[first_false
]);
2021 check_list_contents (&list
, values
, n
);
2022 check ((int) llx_count (&list
) == n
);
2024 free_elements (n
, &list
, elems
, elemp
, values
);
2028 /* Tests that allocation failure is gracefully handled. */
2030 test_allocation_failure (void)
2032 struct llx_list list
;
2035 check (llx_push_head (&list
, NULL
, &llx_null_mgr
) == NULL
);
2036 check (llx_push_tail (&list
, NULL
, &llx_null_mgr
) == NULL
);
2037 check (llx_insert (llx_null (&list
), NULL
, &llx_null_mgr
) == NULL
);
2038 check_list_contents (&list
, NULL
, 0);
2046 const char *description
;
2047 void (*function
) (void);
2050 static const struct test tests
[] =
2103 "find-adjacent-equal",
2104 "find_adjacent_equal",
2105 test_find_adjacent_equal
2128 "lexicographical-compare-3way",
2129 "lexicographical_compare_3way",
2130 test_lexicographical_compare_3way
2148 "permutations-no-dups",
2149 "permutations (no dups)",
2150 test_permutations_no_dups
2153 "permutations-with-dups",
2154 "permutations (with dups)",
2155 test_permutations_with_dups
2164 "merge (with dups)",
2165 test_merge_with_dups
2169 "sort (exhaustive)",
2170 test_sort_exhaustive
2208 "allocation-failure",
2209 "allocation failure",
2210 test_allocation_failure
2214 enum { N_TESTS
= sizeof tests
/ sizeof *tests
};
2217 main (int argc
, char *argv
[])
2223 fprintf (stderr
, "exactly one argument required; use --help for help\n");
2224 return EXIT_FAILURE
;
2226 else if (!strcmp (argv
[1], "--help"))
2228 printf ("%s: test doubly linked list of pointers (llx) library\n"
2229 "usage: %s TEST-NAME\n"
2230 "where TEST-NAME is one of the following:\n",
2232 for (i
= 0; i
< N_TESTS
; i
++)
2233 printf (" %s\n %s\n", tests
[i
].name
, tests
[i
].description
);
2238 for (i
= 0; i
< N_TESTS
; i
++)
2239 if (!strcmp (argv
[1], tests
[i
].name
))
2241 tests
[i
].function ();
2245 fprintf (stderr
, "unknown test %s; use --help for help\n", argv
[1]);
2246 return EXIT_FAILURE
;