/* test-rx.c - Correctness tests for Rx
*
****************************************************************
* Copyright (C) 2000 Thomas Lord
*
* See the file "COPYING" for further information about
* the copyright and warranty status of this work.
*/
#include "hackerlab/rx-posix/regexps.h"
#include "hackerlab/cmd/main.h"
#include "hackerlab/tests/rx-posix-tests/test-rx.h"
#include "hackerlab/tests/rx-posix-tests/test-decls.h"
static t_uchar * program_name = "test-rx";
static t_uchar * usage = "[options]";
static t_uchar * version_string = "1.0";
#define OPTS(OP, OP2) \
OP (opt_help_msg, "h", "help", 0, \
"Display a help message and exit.") \
OP (opt_version, "V", "version", 0, \
"Display a release identifier string") \
OP2 (opt_version, 0, 0, 0, "and exit.") \
OP (opt_random, "r", "random", 0, \
"Run the tests in random order.") \
OP (opt_iterations, "i", "iterations=n", 1, \
"Iterate N times.") \
OP (opt_repeat, 0, "repeat=n", 1, \
"Repeat each test N times per iteration.") \
OP (opt_number, "n", "number=n", 1, \
"Run only test #N.") \
OP (opt_verbose, "v", "verbose", 0, \
"Run tests verbosely.") \
OP (opt_quiet, "q", "quiet", 0, \
"Produce no (ordinary) output.") \
OP (opt_dfa_cache_threshold, "D", "dfa-cache-threshold=N", 1, \
"Set the DFA cache GC threshold.") \
OP (opt_nfa_cache_threshold, "N", "nfa-cache-threshold=N", 1, \
"Set the NFA cache GC threshold.")
enum options
{
OPTS (OPT_ENUM, OPT_IGN)
};
struct opt_desc opts[] =
{
OPTS (OPT_DESC, OPT_DESC)
{-1, 0, 0, 0, 0}
};
static int exit_status = 0;
static void
test_failed (struct rx_test * test)
{
safe_printfmt (2, "FAILED: %s\n pattern: %s\n string: %s\n", test->name, test->pattern, test->string);
exit_status = 1;
}
static int n_comps = 0;
static int n_execs = 0;
static void
run_a_test (struct rx_test * test)
{
regex_t preg;
int comp_result;
int exec_result;
regmatch_t pmatch[10];
comp_result = regcomp (&preg, test->pattern, test->cflags);
++n_comps;
if (comp_result != test->compile_error)
{
char errbuf[1000];
regerror (comp_result, &preg, errbuf, sizeof (errbuf));
test_failed (test);
safe_printfmt (2, " Expected regcomp to return %d, actually returned %d (%s)\n", test->compile_error, comp_result, errbuf);
if (!comp_result)
regfree (&preg);
return;
}
if (comp_result)
return;
exec_result = regexec (&preg, test->string, test->n_match, pmatch, test->eflags);
++n_execs;
if (!exec_result != test->is_match)
{
test_failed (test);
safe_printfmt (2, " Expected regexec to return %d, actually returned %d\n", !test->is_match, exec_result);
regfree (&preg);
return;
}
{
int x;
for (x = 0; x < test->n_match; ++x)
{
if ( (pmatch[x].rm_so != test->pmatch[x].rm_so)
|| (pmatch[x].rm_eo != test->pmatch[x].rm_eo))
{
test_failed (test);
safe_printfmt (2, " Expected pmatch[%d] to be { rm_so == %d, rm_eo == %d } but got {%d, %d}.\n",
x,
(int)test->pmatch[x].rm_so,
(int)test->pmatch[x].rm_eo,
(int)pmatch[x].rm_so,
(int)pmatch[x].rm_eo);
regfree (&preg);
return;
}
}
}
regfree (&preg);
return;
}
int
main (int argc, char * argv[])
{
int errn;
int x;
int noisy;
int quiet;
int repeats;
int iterations;
int random_order;
int number;
unsigned long cache_size;
int o;
struct opt_parsed * option;
noisy = 0;
quiet = 0;
iterations = 1;
repeats = 1;
random_order = 0;
number = -1;
option = 0;
while (1)
{
o = opt_standard (lim_use_must_malloc, &option, opts, &argc, argv, program_name, usage, version_string, 0, opt_help_msg, opt_none, opt_version);
if (o == opt_none)
break;
switch (o)
{
default:
safe_printfmt (2, "unhandled option `%s'\n", option->opt_string);
panic ("internal error parsing arguments");
usage_error:
opt_usage (2, argv[0], program_name, usage, 1);
panic_exit ();
bogus_arg:
safe_printfmt (2, "ill-formed argument for `%s' (`%s')\n", option->opt_string, option->arg_string);
goto usage_error;
case opt_random:
random_order = 1;
break;
case opt_iterations:
if (cvt_decimal_to_uint (&errn, &iterations, option->arg_string, str_length (option->arg_string)))
goto bogus_arg;
break;
case opt_repeat:
if (cvt_decimal_to_uint (&errn, &repeats, option->arg_string, str_length (option->arg_string)))
goto bogus_arg;
break;
case opt_number:
if (cvt_decimal_to_int (&errn, &number, option->arg_string, str_length (option->arg_string)))
goto bogus_arg;
if (number >= ((sizeof (rx_tests) / sizeof (rx_tests[0])) - 1))
{
safe_printfmt (2, "test number out of range\n");
exit (1);
}
break;
case opt_dfa_cache_threshold:
if (cvt_decimal_to_ulong (&errn, &cache_size, option->arg_string, str_length (option->arg_string)))
goto bogus_arg;
rx_set_dfa_cache_threshold ((size_t)cache_size);
break;
case opt_nfa_cache_threshold:
if (cvt_decimal_to_ulong (&errn, &cache_size, option->arg_string, str_length (option->arg_string)))
goto bogus_arg;
rx_set_nfa_cache_threshold ((size_t)cache_size);
break;
case opt_verbose:
noisy = 1;
break;
case opt_quiet:
quiet = 1;
break;
}
}
if (noisy && quiet)
{
safe_printfmt (2, "Can not be both verbose and quiet\n");
goto usage_error;
}
while (iterations--)
{
int r;
if (number >= 0)
{
if (noisy)
safe_printfmt (1, "%d %s\n", number, rx_tests[number].name);
for (r = 0; r < repeats; ++r)
{
if (noisy && (repeats > 1))
safe_printfmt (1, "...%d", r);
run_a_test (&rx_tests[number]);
}
if (noisy && (repeats > 1))
safe_printfmt (1, "\n");
}
else
{
for (x = 0; rx_tests[x].pattern; ++x)
{
int y;
if (random_order)
y = random () % ((sizeof (rx_tests) / sizeof (rx_tests[0])) - 1);
else
y = x;
if (noisy)
safe_printfmt (1, "%d %s\n", y, rx_tests[y].name);
for (r = 0; r < repeats; ++r)
{
if (noisy && (repeats > 1))
safe_printfmt (1, "...%d", r);
run_a_test (&rx_tests[y]);
}
if (noisy && (repeats > 1))
safe_printfmt (1, "\n");
}
}
}
if (!quiet)
{
size_t threshold;
size_t failure_pt;
size_t in_use;
size_t high_water_mark;
int dfa_hits;
int dfa_misses;
int dfa_total_hits;
int dfa_total_misses;
rx_dfa_cache_statistics (&threshold, &failure_pt, &in_use, &high_water_mark, &dfa_hits, &dfa_misses, &dfa_total_hits, &dfa_total_misses);
safe_printfmt (1, "dfa cache stats:\n threshold %lu; failure_pt %lu\n in_use %lu; high_water_mark %lu\n hits %d; misses %d; total_hits %d; total_misses %d\n",
(unsigned long)threshold,
(unsigned long)failure_pt,
(unsigned long)in_use,
(unsigned long)high_water_mark,
dfa_hits, dfa_misses, dfa_total_hits, dfa_total_misses);
}
if (!quiet)
{
size_t threshold;
size_t failure_pt;
size_t in_use;
size_t high_water_mark;
int nfa_hits;
int nfa_misses;
int nfa_saves;
rx_nfa_cache_statistics (&threshold, &failure_pt, &in_use, &high_water_mark, &nfa_hits, &nfa_misses, &nfa_saves);
safe_printfmt (1, "nfa cache stats:\n threshold %lu; failure_pt %lu\n in_use %lu; high_water_mark %lu\n hits %d; misses %d; saves %d\n",
(unsigned long)threshold,
(unsigned long)failure_pt,
(unsigned long)in_use,
(unsigned long)high_water_mark,
nfa_hits, nfa_misses, nfa_saves);
}
{
size_t dfa_bytes;
size_t nfa_bytes;
dfa_bytes = rx_flush_dfa_cache ();
nfa_bytes = rx_flush_nfa_cache ();
if (!quiet || dfa_bytes || nfa_bytes)
{
safe_printfmt (1, "memory retained by dfa cache: %lu bytes\n", (unsigned long)dfa_bytes);
safe_printfmt (1, "memory retained by nfa cache: %lu bytes\n", (unsigned long)nfa_bytes);
}
if (dfa_bytes || nfa_bytes)
exit_status = 1;
}
if (!quiet)
{
safe_printfmt (1, "%d regcomps, %d regexecs\n", n_comps, n_execs);
safe_printfmt (1, "Posix and Rx extension validation tests %s\n", exit_status ? "failed" : "passed");
}
exit (exit_status);
}
syntax highlighted by Code2HTML, v. 0.9.1