1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2007, 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 routines defined in tower.c.
18 This test program aims to be as comprehensive as possible.
19 With -DNDEBUG, "gcov -b" should report 100% coverage of lines
20 and branches in tower.c routines. (Without -DNDEBUG, branches
21 caused by failed assertions will not be taken.) "valgrind
22 --leak-check=yes --show-reachable=yes" should give a clean
23 report, both with and without -DNDEBUG. */
29 #include <libpspp/tower.h>
38 #include <libpspp/compiler.h>
42 /* Exit with a failure code.
43 (Place a breakpoint on this function while debugging.) */
50 /* If OK is not true, prints a message about failure on the
51 current source file and the given LINE and terminates. */
53 check_func (bool ok, int line)
57 fprintf (stderr, "%s:%d: check failed\n", __FILE__, line);
62 /* Verifies that EXPR evaluates to true.
63 If not, prints a message citing the calling line number and
65 #define check(EXPR) check_func ((EXPR), __LINE__)
67 /* Node type and support routines. */
69 /* Test data block. */
72 struct tower_node node; /* Embedded tower block. */
73 int x; /* Primary value. */
76 /* Returns the `struct block' that NODE is embedded within. */
78 tower_node_to_block (const struct tower_node *node)
80 return tower_data (node, struct block, node);
83 /* Swaps *A and *B. */
92 /* Reverses the order of the CNT integers starting at VALUES. */
94 reverse (int *values, size_t cnt)
100 swap (&values[i++], &values[--j]);
103 /* Arranges the CNT blocks in VALUES into the lexicographically
104 next greater permutation. Returns true if successful.
105 If VALUES is already the lexicographically greatest
106 permutation of its blocks (i.e. ordered from greatest to
107 smallest), arranges them into the lexicographically least
108 permutation (i.e. ordered from smallest to largest) and
111 next_permutation (int *values, size_t cnt)
119 if (values[i] < values[i + 1])
122 for (j = cnt - 1; values[i] >= values[j]; j--)
124 swap (values + i, values + j);
125 reverse (values + (i + 1), cnt - (i + 1));
130 reverse (values, cnt);
138 factorial (unsigned int n)
140 unsigned int value = 1;
141 /* Disallow N values that overflow on 32-bit machines. */
148 /* Returns C(n, k), the number of ways that K choices can be made
149 from N items when order is unimportant. */
151 binomial_cofficient (unsigned int n, unsigned int k)
154 return factorial (n) / factorial (k) / factorial (n - k);
157 /* Tests whether PARTS is a K-part integer composition of N.
158 Returns true if so, false otherwise. */
160 is_k_composition (int n, int k, const int parts[])
166 for (i = 0; i < k; i++)
168 if (parts[i] < 1 || parts[i] > n)
175 /* Advances the K-part integer composition of N stored in PARTS
176 to the next lexicographically greater one.
177 Returns true if successful, false if the composition was
178 already the greatest K-part composition of N (in which case
179 PARTS is unaltered). */
181 next_k_composition (int n UNUSED, int k, int parts[])
185 assert (is_k_composition (n, k, parts));
189 for (i = k - 1; i > 0; i--)
200 assert (is_k_composition (n, k, parts));
204 /* Sets the K integers in PARTS to the lexicographically first
205 K-part composition of N. */
207 first_k_composition (int n, int k, int parts[])
213 for (i = 0; i < k; i++)
215 parts[k - 1] += n - k;
218 /* Advances *K and PARTS to the next integer composition of N.
219 Compositions are ordered from shortest to longest and in
220 lexicographical order within a given length.
221 Before the first call, initialize *K to 0.
222 After each successful call, *K contains the length of the
223 current composition and the *K blocks in PARTS contain its
225 Returns true if successful, false if the set of compositions
226 has been exhausted. */
228 next_composition (int n, int *k, int parts[])
230 if (*k >= 1 && next_k_composition (n, *k, parts))
234 first_k_composition (n, ++*k, parts);
241 /* A block expected to be found in a tower. */
242 struct expected_block
244 int size; /* Expected thickness of block. */
245 int x; /* Expected value for `x' member. */
248 /* Checks that tower T contains the BLOCK_CNT blocks described by
251 check_tower (struct tower *t,
252 struct expected_block blocks[], size_t block_cnt)
255 struct tower_node *node;
258 check (tower_count (t) == block_cnt);
259 check (tower_is_empty (t) == (block_cnt == 0));
262 for (i = 0; i < block_cnt; i++)
264 unsigned long int level;
265 for (level = total_height;
266 level < total_height + blocks[i].size;
269 struct tower_node *found;
270 unsigned long int block_start;
271 found = tower_lookup (t, level, &block_start);
272 check (found != NULL);
273 check (tower_node_to_block (found)->x == blocks[i].x);
274 check (block_start == total_height);
275 check (tower_node_get_level (found) == total_height);
276 check (tower_node_get_index (found) == i);
277 check (tower_get (t, i) == found);
279 total_height += blocks[i].size;
281 check (tower_height (t) == total_height);
283 for (node = tower_first (t), i = 0;
285 node = tower_next (t, node), i++)
287 check (tower_node_get_size (node) == blocks[i].size);
288 check (tower_node_to_block (node)->x == blocks[i].x);
290 check (i == block_cnt);
292 for (node = tower_last (t), i = block_cnt - 1;
294 node = tower_prev (t, node), i--)
296 check (tower_node_get_size (node) == blocks[i].size);
297 check (tower_node_to_block (node)->x == blocks[i].x);
299 check (i == SIZE_MAX);
302 /* Tests inserting all possible sets of block heights into a
303 tower in all possible orders, up to a specified maximum tower
308 const int max_height = 7;
311 for (cnt = 1; cnt <= max_height; cnt++)
313 unsigned int composition_cnt;
314 struct expected_block *expected;
318 struct block *blocks;
320 expected = xnmalloc (cnt, sizeof *expected);
321 sizes = xnmalloc (cnt, sizeof *sizes);
322 order = xnmalloc (cnt, sizeof *order);
323 blocks = xnmalloc (cnt, sizeof *blocks);
327 while (next_composition (cnt, &block_cnt, sizes))
330 unsigned int permutation_cnt;
332 for (i = 0; i < block_cnt; i++)
336 while (permutation_cnt == 0 || next_permutation (order, block_cnt))
340 /* Inserts the block_cnt blocks with the given
341 sizes[] into T in the order given by order[]. */
343 for (i = 0; i < block_cnt; i++)
352 for (j = 0; j < i; j++)
354 && (under == NULL || under->x > order[j]))
355 under = &blocks[order[j]];
357 tower_insert (&t, sizes[idx], &blocks[idx].node,
358 under != NULL ? &under->node : NULL);
361 /* Check that the result is what we expect. */
362 for (i = 0; i < block_cnt; i++)
364 expected[i].size = sizes[i];
367 check_tower (&t, expected, block_cnt);
371 check (permutation_cnt == factorial (block_cnt));
375 check (composition_cnt == 1 << (cnt - 1));
384 /* Tests deleting blocks from towers that initially contain all
385 possible sets of block sizes into a tower in all possible
386 orders, up to a specified maximum tower height. */
390 const int max_height = 7;
393 for (cnt = 1; cnt <= max_height; cnt++)
395 unsigned int composition_cnt;
396 struct expected_block *expected;
400 struct block *blocks;
402 expected = xnmalloc (cnt, sizeof *expected);
403 sizes = xnmalloc (cnt, sizeof *sizes);
404 order = xnmalloc (cnt, sizeof *order);
405 blocks = xnmalloc (cnt, sizeof *blocks);
409 while (next_composition (cnt, &block_cnt, sizes))
412 unsigned int permutation_cnt;
414 for (i = 0; i < block_cnt; i++)
418 while (permutation_cnt == 0 || next_permutation (order, block_cnt))
422 /* Insert blocks into tower in ascending order. */
424 for (i = 0; i < block_cnt; i++)
427 tower_insert (&t, sizes[i], &blocks[i].node, NULL);
429 expected[i].size = sizes[i];
431 check_tower (&t, expected, block_cnt);
433 /* Delete blocks from tower in the order of
435 for (i = 0; i < block_cnt; i++)
439 tower_delete (&t, &blocks[idx].node);
442 assert (j < block_cnt - i);
443 if (expected[j].x == idx)
445 memcpy (&expected[j], &expected[j + 1],
446 sizeof *expected * (block_cnt - i - j - 1));
450 check_tower (&t, expected, block_cnt - i - 1);
455 check (permutation_cnt == factorial (block_cnt));
459 check (composition_cnt == 1 << (cnt - 1));
468 /* Tests towers containing all possible block sizes, resizing
469 the blocks to all possible sizes that conserve the total
470 tower height, up to a maximum total tower height. */
474 const int max_height = 9;
477 for (cnt = 1; cnt <= max_height; cnt++)
479 unsigned int composition_cnt;
480 struct expected_block *expected;
481 int *sizes, *new_sizes;
484 struct block *blocks;
486 expected = xnmalloc (cnt, sizeof *expected);
487 sizes = xnmalloc (cnt, sizeof *sizes);
488 new_sizes = xnmalloc (cnt, sizeof *new_sizes);
489 order = xnmalloc (cnt, sizeof *order);
490 blocks = xnmalloc (cnt, sizeof *blocks);
494 while (next_composition (cnt, &block_cnt, sizes))
497 unsigned int resizes = 0;
499 for (resizes = 0, first_k_composition (cnt, block_cnt, new_sizes);
501 || next_k_composition (cnt, block_cnt, new_sizes));
506 /* Insert blocks into tower in ascending order. */
508 for (i = 0; i < block_cnt; i++)
511 tower_insert (&t, sizes[i], &blocks[i].node, NULL);
513 expected[i].size = sizes[i];
515 check_tower (&t, expected, block_cnt);
517 /* Resize all the blocks. */
518 for (i = 0; i < block_cnt; i++)
520 if (expected[i].size != new_sizes[i] || rand () % 2)
521 tower_resize (&t, &blocks[i].node, new_sizes[i]);
522 expected[i].size = new_sizes[i];
524 check_tower (&t, expected, block_cnt);
526 check (resizes == binomial_cofficient (cnt - 1, block_cnt - 1));
530 check (composition_cnt == 1 << (cnt - 1));
540 /* Tests splicing all possible contiguous sets of blocks out of one
541 tower into a second, initially empty tower. */
543 test_splice_out (void)
545 const int max_height = 9;
548 for (cnt = 1; cnt <= max_height; cnt++)
550 unsigned int composition_cnt;
551 struct expected_block *expected;
552 int *sizes, *new_sizes;
555 struct block *blocks;
557 expected = xnmalloc (cnt, sizeof *expected);
558 sizes = xnmalloc (cnt, sizeof *sizes);
559 new_sizes = xnmalloc (cnt, sizeof *new_sizes);
560 order = xnmalloc (cnt, sizeof *order);
561 blocks = xnmalloc (cnt, sizeof *blocks);
565 while (next_composition (cnt, &block_cnt, sizes))
569 for (i = 0; i < block_cnt; i++)
570 for (j = i; j <= block_cnt; j++)
572 struct tower src, dst;
578 /* Insert blocks into SRC and DST in ascending order. */
579 for (k = 0; k < block_cnt; k++)
582 tower_insert (&src, sizes[k], &blocks[k].node, NULL);
584 expected[k].size = sizes[k];
586 check_tower (&src, expected, block_cnt);
588 /* Splice blocks I...J into DST. */
589 tower_splice (&dst, NULL, &src, &blocks[i].node,
590 j < block_cnt ? &blocks[j].node : NULL);
591 check_tower (&dst, &expected[i], j - i);
592 memmove (&expected[i], &expected[j],
593 sizeof *expected * (block_cnt - j));
594 check_tower (&src, expected, block_cnt - (j - i));
598 check (composition_cnt == 1 << (cnt - 1));
608 /* Tests splicing all of the contents of a tower into all
609 possible positions in a second tower. */
611 test_splice_in (void)
613 const int max_height = 9;
616 for (cnt = 1; cnt <= max_height; cnt++)
618 unsigned int composition_cnt;
619 struct expected_block *expected;
620 int *sizes, *new_sizes;
623 struct block *blocks;
625 expected = xnmalloc (cnt, sizeof *expected);
626 sizes = xnmalloc (cnt, sizeof *sizes);
627 new_sizes = xnmalloc (cnt, sizeof *new_sizes);
628 order = xnmalloc (cnt, sizeof *order);
629 blocks = xnmalloc (cnt, sizeof *blocks);
633 while (next_composition (cnt, &block_cnt, sizes))
637 for (i = 0; i < block_cnt; i++)
638 for (j = i; j <= block_cnt; j++)
640 struct tower src, dst;
646 /* Insert blocks into SRC and DST in ascending order. */
647 for (k = 0; k < block_cnt; k++)
650 tower_insert (k >= i && k < j ? &src : &dst,
651 sizes[k], &blocks[k].node, NULL);
653 expected[k].size = sizes[k];
656 /* Splice SRC into DST. */
657 tower_splice (&dst, j < block_cnt ? &blocks[j].node : NULL,
658 &src, i != j ? &blocks[i].node : NULL, NULL);
659 check_tower (&dst, expected, block_cnt);
663 check (composition_cnt == 1 << (cnt - 1));
679 const char *description;
680 void (*function) (void);
683 static const struct test tests[] =
712 enum { N_TESTS = sizeof tests / sizeof *tests };
715 main (int argc, char *argv[])
721 fprintf (stderr, "exactly one argument required; use --help for help\n");
724 else if (!strcmp (argv[1], "--help"))
726 printf ("%s: test tower library\n"
727 "usage: %s TEST-NAME\n"
728 "where TEST-NAME is one of the following:\n",
730 for (i = 0; i < N_TESTS; i++)
731 printf (" %s\n %s\n", tests[i].name, tests[i].description);
736 for (i = 0; i < N_TESTS; i++)
737 if (!strcmp (argv[1], tests[i].name))
739 tests[i].function ();
743 fprintf (stderr, "unknown test %s; use --help for help\n", argv[1]);