-\f
-#include <stdarg.h>
-#include "command.h"
-#include "random.h"
-#include "lexer.h"
-
-static void test_casefile (int pattern, size_t case_size, size_t case_cnt);
-static struct ccase *get_random_case (size_t case_size, size_t case_idx);
-static void write_random_case (struct casefile *cf, size_t case_idx);
-static void read_and_verify_random_case (struct casefile *cf,
- struct casereader *reader,
- size_t case_idx);
-static void fail_test (const char *message, ...);
-
-int
-cmd_debug_casefile (void)
-{
- static const size_t sizes[] =
- {
- 1, 2, 3, 4, 5, 6, 7, 14, 15, 16, 17, 31, 55, 73,
- 100, 137, 257, 521, 1031, 2053
- };
- int size_max;
- int case_max;
- int pattern;
-
- size_max = sizeof sizes / sizeof *sizes;
- if (lex_match_id ("SMALL"))
- {
- size_max -= 4;
- case_max = 511;
- }
- else
- case_max = 4095;
- if (token != '.')
- return lex_end_of_command ();
-
- for (pattern = 0; pattern < 5; pattern++)
- {
- const size_t *size;
-
- for (size = sizes; size < sizes + size_max; size++)
- {
- size_t case_cnt;
-
- for (case_cnt = 0; case_cnt <= case_max;
- case_cnt = (case_cnt * 2) + 1)
- test_casefile (pattern, *size * sizeof (union value), case_cnt);
- }
- }
- printf ("Casefile tests succeeded.\n");
- return CMD_SUCCESS;
-}
-
-static void
-test_casefile (int pattern, size_t case_size, size_t case_cnt)
-{
- int zero = 0;
- struct casefile *cf;
- struct casereader *r1, *r2;
- const struct ccase *c;
- struct rng *rng;
- size_t i, j;
-
- rng = rng_create ();
- rng_seed (rng, &zero, sizeof zero);
- cf = casefile_create (case_size);
- for (i = 0; i < case_cnt; i++)
- write_random_case (cf, i);
- r1 = casefile_get_reader (cf);
- r2 = casefile_get_reader (cf);
- switch (pattern)
- {
- case 0:
- for (i = 0; i < case_cnt; i++)
- {
- read_and_verify_random_case (cf, r1, i);
- read_and_verify_random_case (cf, r2, i);
- }
- break;
- case 1:
- for (i = 0; i < case_cnt; i++)
- read_and_verify_random_case (cf, r1, i);
- for (i = 0; i < case_cnt; i++)
- read_and_verify_random_case (cf, r2, i);
- break;
- case 2:
- case 3:
- case 4:
- for (i = j = 0; i < case_cnt; i++)
- {
- read_and_verify_random_case (cf, r1, i);
- if (rng_get_int (rng) % pattern == 0)
- read_and_verify_random_case (cf, r2, j++);
- if (i == case_cnt / 2)
- casefile_to_disk (cf);
- }
- for (; j < case_cnt; j++)
- read_and_verify_random_case (cf, r2, j);
- break;
- }
- if (casereader_read (r1, &c))
- fail_test ("Casereader 1 not at end of file.");
- if (casereader_read (r2, &c))
- fail_test ("Casereader 2 not at end of file.");
- if (pattern != 1)
- casereader_destroy (r1);
- if (pattern != 2)
- casereader_destroy (r2);
- casefile_destroy (cf);
- rng_destroy (rng);
-}
-
-static struct ccase *
-get_random_case (size_t case_size, size_t case_idx)
-{
- struct ccase *c = xmalloc (case_size);
- memset (c, case_idx % 257, case_size);
- return c;
-}
-
-static void
-write_random_case (struct casefile *cf, size_t case_idx)
-{
- struct ccase *c = get_random_case (casefile_get_case_size (cf), case_idx);
- casefile_append (cf, c);
- free (c);
-}
-
-static void
-read_and_verify_random_case (struct casefile *cf,
- struct casereader *reader, size_t case_idx)
-{
- const struct ccase *read_case;
- struct ccase *expected_case;
- size_t case_size;
-
- case_size = casefile_get_case_size (cf);
- expected_case = get_random_case (case_size, case_idx);
- if (!casereader_read (reader, &read_case))
- fail_test ("Premature end of casefile.");
- if (memcmp (read_case, expected_case, case_size))
- fail_test ("Case %lu fails comparison.", (unsigned long) case_idx);
- free (expected_case);
-}
-
-static void
-fail_test (const char *message, ...)
-{
- va_list args;
-
- va_start (args, message);
- vprintf (message, args);
- putchar ('\n');
- va_end (args);
-
- exit (1);
-}