-/* PSPP - computes sample statistics.
- Copyright (C) 2007 Free Software Foundation, Inc.
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2007, 2010 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* This is a test program for the routines defined in
range-map.c. This test program aims to be as comprehensive as
#include "xalloc.h"
\f
-/* Currently running test. */
-static const char *test_name;
-
/* Exit with a failure code.
(Place a breakpoint on this function while debugging.) */
static void
{
if (!ok)
{
- printf ("Check failed in %s test at %s, line %d\n",
- test_name, __FILE__, line);
+ fprintf (stderr, "%s:%d: check failed\n", __FILE__, line);
check_die ();
}
}
*b = t;
}
-/* Reverses the order of the CNT integers starting at VALUES. */
+/* Reverses the order of the N integers starting at VALUES. */
static void
-reverse (int *values, size_t cnt)
+reverse (int *values, size_t n)
{
size_t i = 0;
- size_t j = cnt;
+ size_t j = n;
while (j > i)
swap (&values[i++], &values[--j]);
}
-/* Arranges the CNT blocks in VALUES into the lexicographically
+/* Arranges the N blocks in VALUES into the lexicographically
next greater permutation. Returns true if successful.
If VALUES is already the lexicographically greatest
permutation of its blocks (i.e. ordered from greatest to
permutation (i.e. ordered from smallest to largest) and
returns false. */
static bool
-next_permutation (int *values, size_t cnt)
+next_permutation (int *values, size_t n)
{
- if (cnt > 0)
+ if (n > 0)
{
- size_t i = cnt - 1;
+ size_t i = n - 1;
while (i != 0)
{
i--;
if (values[i] < values[i + 1])
{
size_t j;
- for (j = cnt - 1; values[i] >= values[j]; j--)
+ for (j = n - 1; values[i] >= values[j]; j--)
continue;
swap (values + i, values + j);
- reverse (values + (i + 1), cnt - (i + 1));
+ reverse (values + (i + 1), n - (i + 1));
return true;
}
}
- reverse (values, cnt);
+ reverse (values, n);
}
return false;
unsigned int value = 1;
/* Disallow N values that overflow on 32-bit machines. */
assert (n <= 12);
- for (; n > 1; )
+ for (; n > 1;)
value *= n--;
return value;
}
return a->start < b->start ? -1 : a->start > b->start;
}
-/* Checks that RM contains the ELEM_CNT elements described by
+/* Checks that RM contains the ELEM_N elements described by
ELEMENTS[]. */
static void
check_range_map (struct range_map *rm,
- struct expected_element elements[], size_t elem_cnt)
+ struct expected_element elements[], size_t n_elems)
{
struct expected_element *sorted;
struct range_map_node *node;
size_t i;
- sorted = xnmalloc (elem_cnt, sizeof *sorted);
- memcpy (sorted, elements, elem_cnt * sizeof *elements);
- qsort (sorted, elem_cnt, sizeof *sorted, compare_expected_element);
+ sorted = xnmalloc (n_elems, sizeof *sorted);
+ memcpy (sorted, elements, n_elems * sizeof *elements);
+ qsort (sorted, n_elems, sizeof *sorted, compare_expected_element);
- check (range_map_is_empty (rm) == (elem_cnt == 0));
+ check (range_map_is_empty (rm) == (n_elems == 0));
- for (i = 0; i < elem_cnt; i++)
+ for (i = 0; i < n_elems; i++)
{
struct expected_element *e = &sorted[i];
unsigned long int position;
range_map_lookup doesn't find any there. */
if (e->start > 0 && (i == 0 || e[-1].end < e->start))
check (range_map_lookup (rm, e->start - 1) == NULL);
- if (i == elem_cnt - 1 || e->end < e[1].start)
+ if (i == n_elems - 1 || e->end < e[1].start)
check (range_map_lookup (rm, e->end) == NULL);
}
struct expected_element *e = &sorted[i];
check (range_map_node_to_element (node)->x == e->x);
}
- check (i == elem_cnt);
+ check (i == n_elems);
free (sorted);
}
test_insert (void)
{
const int max_range = 7;
- int cnt;
+ int n;
- for (cnt = 1; cnt <= max_range; cnt++)
+ for (n = 1; n <= max_range; n++)
{
- unsigned int composition_cnt;
+ unsigned int n_compositions;
struct expected_element *expected;
int *widths;
- int elem_cnt;
+ int n_elems;
int *order;
struct element *elements;
- expected = xnmalloc (cnt, sizeof *expected);
- widths = xnmalloc (cnt, sizeof *widths);
- order = xnmalloc (cnt, sizeof *order);
- elements = xnmalloc (cnt, sizeof *elements);
+ expected = xnmalloc (n, sizeof *expected);
+ widths = xnmalloc (n, sizeof *widths);
+ order = xnmalloc (n, sizeof *order);
+ elements = xnmalloc (n, sizeof *elements);
- elem_cnt = 0;
- composition_cnt = 0;
- while (next_composition (cnt, &elem_cnt, widths))
+ n_elems = 0;
+ n_compositions = 0;
+ while (next_composition (n, &n_elems, widths))
{
int i, j;
- unsigned int permutation_cnt;
+ unsigned int n_permutations;
- for (i = 0; i < elem_cnt; i++)
+ for (i = 0; i < n_elems; i++)
order[i] = i;
- permutation_cnt = 0;
- while (permutation_cnt == 0 || next_permutation (order, elem_cnt))
+ n_permutations = 0;
+ while (n_permutations == 0 || next_permutation (order, n_elems))
{
struct range_map rm;
- /* Inserts the elem_cnt elements with the given
+ /* Inserts the n_elems elements with the given
widths[] into T in the order given by order[]. */
range_map_init (&rm);
- for (i = 0; i < elem_cnt; i++)
+ for (i = 0; i < n_elems; i++)
{
unsigned long int start, end;
int idx;
expected[i].end = end;
check_range_map (&rm, expected, i + 1);
}
- permutation_cnt++;
+ n_permutations++;
}
- check (permutation_cnt == factorial (elem_cnt));
+ check (n_permutations == factorial (n_elems));
- composition_cnt++;
+ n_compositions++;
}
- check (composition_cnt == 1 << (cnt - 1));
+ check (n_compositions == 1 << (n - 1));
free (expected);
free (widths);
test_delete (int gap)
{
const int max_range = 7;
- int cnt;
+ int n;
- for (cnt = 1; cnt <= max_range; cnt++)
+ for (n = 1; n <= max_range; n++)
{
- unsigned int composition_cnt;
+ unsigned int n_compositions;
struct expected_element *expected;
int *widths;
- int elem_cnt;
+ int n_elems;
int *order;
struct element *elements;
- expected = xnmalloc (cnt, sizeof *expected);
- widths = xnmalloc (cnt, sizeof *widths);
- order = xnmalloc (cnt, sizeof *order);
- elements = xnmalloc (cnt, sizeof *elements);
+ expected = xnmalloc (n, sizeof *expected);
+ widths = xnmalloc (n, sizeof *widths);
+ order = xnmalloc (n, sizeof *order);
+ elements = xnmalloc (n, sizeof *elements);
- elem_cnt = 0;
- composition_cnt = 0;
- while (next_composition (cnt, &elem_cnt, widths))
+ n_elems = 0;
+ n_compositions = 0;
+ while (next_composition (n, &n_elems, widths))
{
int i, j;
- unsigned int permutation_cnt;
+ unsigned int n_permutations;
- for (i = 0; i < elem_cnt; i++)
+ for (i = 0; i < n_elems; i++)
order[i] = i;
- permutation_cnt = 0;
- while (permutation_cnt == 0 || next_permutation (order, elem_cnt))
+ n_permutations = 0;
+ while (n_permutations == 0 || next_permutation (order, n_elems))
{
struct range_map rm;
unsigned long int start;
/* Insert all the elements. */
range_map_init (&rm);
start = 0;
- for (i = 0; i < elem_cnt; i++)
+ for (i = 0; i < n_elems; i++)
{
int width = widths[i] > gap ? widths[i] - gap : widths[i];
unsigned long int end = start + width;
for (j = 0; ; j++)
{
- assert (j < elem_cnt);
+ assert (j < n_elems);
if (order[j] == i)
{
expected[j].x = i;
start += widths[i];
}
- check_range_map (&rm, expected, elem_cnt);
+ check_range_map (&rm, expected, n_elems);
/* Delete the elements in the specified order. */
- for (i = 0; i < elem_cnt; i++)
+ for (i = 0; i < n_elems; i++)
{
range_map_delete (&rm, &elements[order[i]].node);
- check_range_map (&rm, expected + i + 1, elem_cnt - i - 1);
+ check_range_map (&rm, expected + i + 1, n_elems - i - 1);
}
- permutation_cnt++;
+ n_permutations++;
}
- check (permutation_cnt == factorial (elem_cnt));
+ check (n_permutations == factorial (n_elems));
- composition_cnt++;
+ n_compositions++;
}
- check (composition_cnt == 1 << (cnt - 1));
+ check (n_compositions == 1 << (n - 1));
free (expected);
free (widths);
\f
/* Main program. */
-/* Runs TEST_FUNCTION and prints a message about NAME. */
-static void
-run_test (void (*test_function) (void), const char *name)
-{
- test_name = name;
- putchar ('.');
- fflush (stdout);
- test_function ();
-}
+struct test
+ {
+ const char *name;
+ const char *description;
+ void (*function) (void);
+ };
+
+static const struct test tests[] =
+ {
+ {
+ "insert",
+ "insert",
+ test_insert
+ },
+ {
+ "delete-contiguous",
+ "delete from contiguous ranges",
+ test_delete_contiguous
+ },
+ {
+ "delete-gaps",
+ "delete from ranges separated by gaps",
+ test_delete_gaps
+ },
+ };
+
+enum { N_TESTS = sizeof tests / sizeof *tests };
int
-main (void)
+main (int argc, char *argv[])
{
- run_test (test_insert, "insert");
- run_test (test_delete_contiguous, "delete from contiguous ranges");
- run_test (test_delete_gaps, "delete from ranges separated by gaps");
- putchar ('\n');
+ int i;
- return 0;
+ if (argc != 2)
+ {
+ fprintf (stderr, "exactly one argument required; use --help for help\n");
+ return EXIT_FAILURE;
+ }
+ else if (!strcmp (argv[1], "--help"))
+ {
+ printf ("%s: test range map library\n"
+ "usage: %s TEST-NAME\n"
+ "where TEST-NAME is one of the following:\n",
+ argv[0], argv[0]);
+ for (i = 0; i < N_TESTS; i++)
+ printf (" %s\n %s\n", tests[i].name, tests[i].description);
+ return 0;
+ }
+ else
+ {
+ for (i = 0; i < N_TESTS; i++)
+ if (!strcmp (argv[1], tests[i].name))
+ {
+ tests[i].function ();
+ return 0;
+ }
+
+ fprintf (stderr, "unknown test %s; use --help for help\n", argv[1]);
+ return EXIT_FAILURE;
+ }
}