2023-03-26 19:15:17 +08:00

506 lines
12 KiB
C

#define DEFAULT_NUMBER_OF_PROCESSES 4
static const char *usage =
"usage: tissat [<option> ... ] [ <pattern> ... ]\n"
"\n"
"where '<option>' is one of the following:\n"
"\n"
"-h prints this command line option information\n"
"-v increase verbosity and force sequential testing\n"
#if defined(LOGGING) && !defined(QUIET)
"-l increase logging level for solver instances\n"
"-s non-parallel sequential testing"
"(implied by '-v' and '-l')\n"
"-p print progress "
"(can not be combined with '-v' or '-l')\n"
#else
"-p print progress (can not be combined with '-v')\n"
"-s non-parallel sequential testing (implied by '-v')\n"
#endif
"-j[<processes>] number of processes (infinite '-j', default '-j%d')\n"
"-b thorough big tests and all options\n"
"\n"
"The list of patterns is matched to the function names of the tests.\n"
"If no pattern is given at all then all test cases are executed.\n"
"\n"
"Otherwise only those tests are executed for which at least one\n"
"pattern matches its function name (contains the pattern).\n";
#include "build.h"
#include "../src/allocate.h"
#include "../src/application.h"
#include "../src/check.h"
#include "../src/clause.h"
#include "../src/colors.h"
#include "../src/file.h"
#include "../src/handle.h"
#include "../src/internal.h"
#include "../src/literal.h"
#include "../src/parse.h"
#include "../src/print.h"
#include "../src/resize.h"
#include "../src/resources.h"
#include "../src/stack.h"
#include "../src/utilities.h"
#include "../src/vector.h"
#include <ctype.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <unistd.h>
#include "test.h"
bool tissat_big;
bool tissat_found_test_directory;
bool tissat_sequential;
bool tissat_progress;
int tissat_processes;
#ifndef NPROOFS
bool tissat_found_drabt;
bool tissat_found_drat_trim;
#endif
const char *tissat_root = DIR;
#ifdef _POSIX_C_SOURCE
bool tissat_found_bzip2;
bool tissat_found_gzip;
bool tissat_found_lzma;
bool tissat_found_xz;
bool tissat_found_7z;
#endif
#if defined(LOGGING) && !defined(QUIET)
static int tissat_logging;
#endif
void
tissat_init_solver (kissat * solver)
{
#if !defined(NOPTIONS) && !defined(QUIET)
#ifdef LOGGING
if (tissat_logging)
solver->options.log = tissat_logging;
#endif
if (tissat_verbosity > 1)
solver->options.verbose = tissat_verbosity - 1;
#else
(void) solver;
#endif
solver->watching = true;
}
static bool
find_test_directory (void)
{
struct stat buf;
return !stat ("../test", &buf);
}
static bool
match (const char *str, const char *pattern)
{
for (const char *s = str; *s; s++)
{
const char *p = pattern;
for (const char *q = s; *p && *p == *q; p++, q++)
;
if (!*p)
return true;
}
return false;
}
static int patterns;
static void
schedule (const char *name, void (*scheduler) (void), int argc, char **argv)
{
bool execute = !patterns || argc < 2;
for (int i = 1; !execute && i < argc; i++)
execute = match (name, argv[i]);
if (patterns && !execute)
return;
const unsigned before = tissat_scheduled;
scheduler ();
const unsigned jobs = tissat_scheduled - before;
tissat_message ("Scheduled %u jobs through '%s'.", jobs, name);
}
static int
get_number_of_cores (void)
{
int res = -1;
#ifdef _POSIX_C_SOURCE
res = sysconf (_SC_NPROCESSORS_ONLN);
#endif
return res;
}
static int
default_number_of_processes (void)
{
int res = get_number_of_cores ();
return res <= 0 ? DEFAULT_NUMBER_OF_PROCESSES : res;
}
int
main (int argc, char **argv)
{
const double start = kissat_wall_clock_time ();
const char *sequential_option = 0;
const char *processes_option = 0;
const char *verbose_option = 0;
if (chdir (DIR))
FATAL ("could not change to build director '%s'", DIR);
for (int i = 1; i < argc; i++)
if (!strcmp (argv[i], "-h"))
printf (usage, default_number_of_processes ()), exit (0);
else if (!strcmp (argv[i], "-v"))
{
if (tissat_progress)
tissat_error ("can not combine '-p' and '-v'");
if (processes_option)
tissat_error ("can not combine '%s' and '-v'", processes_option);
if (!verbose_option)
verbose_option = argv[i];
tissat_verbosity++;
}
else if (!strcmp (argv[i], "-s"))
{
if (sequential_option)
tissat_error ("multiple '-s' options");
if (processes_option)
tissat_error ("can not combine '%s' and '-s'", processes_option);
if (!tissat_sequential)
{
tissat_sequential = true;
sequential_option = "-s";
}
}
else if (!strcmp (argv[i], "-p"))
{
if (verbose_option)
tissat_error ("can not combine '%s' and '-p'", verbose_option);
tissat_progress = true;
}
else if (!strcmp (argv[i], "-j"))
{
if (verbose_option)
tissat_error ("can not combine '%s' and '-j'", verbose_option);
if (tissat_sequential)
tissat_error ("can not combine '-s' and '-j'");
if (processes_option)
{
if (!strcmp (processes_option, "-j"))
tissat_error ("multiple '-j' options");
else
tissat_error ("multiple '%s' and '-j'", processes_option);
}
else
assert (!tissat_processes);
processes_option = argv[i];
tissat_processes = -1;
}
else if (argv[i][0] == '-' && argv[i][1] == 'j' && argv[i][2])
{
if (processes_option)
{
if (!strcmp (processes_option, argv[i]))
tissat_error ("multiple '%s' options", argv[i]);
else
tissat_error ("multiple '%s' and '%s'",
processes_option, argv[i]);
}
else
assert (!tissat_processes);
int tmp = 0;
char ch;
for (const char *p = argv[i] + 2; (ch = *p); p++)
{
if (!isdigit (ch))
tissat_error ("expected digit in '%s' (try '-h')", argv[i]);
if (INT_MAX / 10 < tmp)
tissat_error ("number in '%s' way too large (try '-h')",
argv[i]);
tmp *= 10;
int digit = ch - '0';
if (INT_MAX - digit <= tmp)
tissat_error ("number in '%s' too large (try '-h')", argv[i]);
tmp += digit;
}
if (!tmp)
tissat_error ("invalid zero argument in '%s' (try '-h')", argv[i]);
if (verbose_option)
tissat_error ("can not combine '%s' and '%s'",
verbose_option, argv[i]);
if (tissat_sequential)
tissat_error ("can not combine '-s' and '%s'", argv[i]);
processes_option = argv[i];
tissat_processes = tmp;
}
#if defined(LOGGING) && !defined(QUIET)
else if (!strcmp (argv[i], "-l"))
{
if (tissat_progress)
tissat_error ("can not combine '-p' and '-l");
if (processes_option)
tissat_error ("can not combine '%s' and '-v'", processes_option);
if (!verbose_option)
verbose_option = argv[i];
tissat_logging++;
tissat_verbosity = 4;
}
#endif
else if (!strcmp (argv[i], "-b"))
tissat_big = true;
else if (argv[i][0] == '-')
tissat_error ("invalid option '%s' (try '-h')", argv[i]);
else
patterns++;
if (tissat_verbosity && !tissat_sequential)
{
if (!tissat_sequential)
{
tissat_sequential = true;
sequential_option = "-v";
}
}
#if defined(LOGGING)
if (tissat_logging && !tissat_sequential)
{
if (!tissat_sequential)
{
tissat_sequential = true;
sequential_option = "-l";
}
}
#endif
if (!tissat_sequential && !tissat_processes)
tissat_processes = default_number_of_processes ();
#ifndef QUIET
kissat_banner ("", "TISSAT Tester for KISSAT");
tissat_line ();
tissat_message ("Use '-h' to print usage (i.e., how to use patterns).");
#else
tissat_message ("TISSAT Tester for KISSAT");
#endif
tissat_message ("Changed to '%s' directory.", DIR);
if (tissat_sequential)
tissat_message ("Forced sequential non-parallel execution "
"(due to '-s').");
else if (tissat_processes < 0)
{
if (processes_option)
tissat_message ("Parallel execution "
"using an arbitrary number of processes "
"(due to '-j').");
else
{
assert (DEFAULT_NUMBER_OF_PROCESSES < 0);
tissat_message ("Parallel execution "
"using an arbitrary number of processes "
"(by default).");
}
}
else
{
if (processes_option)
tissat_message ("Parallel execution "
"using at most %d processes (due to '%s').",
tissat_processes, processes_option);
else
{
tissat_message ("Parallel execution "
"using at most %d processes (by default).",
tissat_processes);
}
}
if (tissat_progress)
tissat_message ("Job execution progress reporting " "(due to '-p').");
else if (verbose_option)
tissat_message ("Job execution progress reporting disabled "
"(due to '%s').", verbose_option);
else
tissat_message ("Job execution progress reporting disabled "
"(enable with '-p').");
tissat_found_test_directory = find_test_directory ();
if (!tissat_found_test_directory)
{
tissat_line ();
tissat_message ("Could not find '../test/' directory.");
tissat_message ("Skipping test cases that rely on '../test' .");
}
else
{
tissat_line ();
tissat_message ("Found '../test' directory "
"(running test cases that need '../test' too).");
}
#ifndef NPROOFS
bool found_proof_checker = false;
#define FIND(EXECUTABLE,FLAG) \
do { \
if ((tissat_found_ ## FLAG = kissat_find_executable (#EXECUTABLE))) \
{ \
tissat_message ("Found '%s' executable (will check proofs with it).", \
#EXECUTABLE); \
found_proof_checker = true; \
} \
else \
tissat_warning ("Did not find '%s' executable.", #EXECUTABLE); \
} while (0)
// *INDENT-OFF*
FIND (drabt, drabt);
FIND (drat-trim, drat_trim);
// *INDENT-ON*
if (!found_proof_checker)
{
tissat_line ();
tissat_bold_message ("Install either 'drat-trim' or "
"'drabt' to check proofs too!");
tissat_line ();
}
#undef FIND
#endif
#ifdef _POSIX_C_SOURCE
bool found_compression_utility;
#define FIND(EXECUTABLE) \
do { \
if ((tissat_found_ ## EXECUTABLE = kissat_find_executable (#EXECUTABLE))) \
{ \
tissat_message ("Found '%s' executable for testing compression.", \
#EXECUTABLE); \
found_compression_utility = true; \
} \
else \
tissat_warning ("Did not find '%s' executable for testing compression.", \
#EXECUTABLE); \
} while (0)
// *INDENT-OFF*
FIND (bzip2);
FIND (gzip);
FIND (lzma);
FIND (xz);
FIND (7z);
// *INDENT-ON*
if (!found_compression_utility)
tissat_message
("Not testing compression (no compression utility found).");
#else
tissat_message ("No compression tests for non POSIX configuration.");
#endif
tissat_line ();
#define SCHEDULE(NAME) \
do { \
void tissat_schedule_ ## NAME (void); \
schedule ("tissat_schedule_" #NAME, \
tissat_schedule_ ## NAME, argc, argv); \
} while (0)
SCHEDULE (error);
SCHEDULE (endianess);
SCHEDULE (format);
SCHEDULE (references);
SCHEDULE (reluctant);
SCHEDULE (random);
SCHEDULE (queue);
SCHEDULE (allocate);
SCHEDULE (stack);
SCHEDULE (arena);
SCHEDULE (heap);
SCHEDULE (vector);
SCHEDULE (rank);
SCHEDULE (sort);
SCHEDULE (bump);
SCHEDULE (options);
SCHEDULE (init);
SCHEDULE (add);
SCHEDULE (file);
SCHEDULE (parse);
SCHEDULE (usage);
SCHEDULE (main);
SCHEDULE (collect);
SCHEDULE (solve);
SCHEDULE (coverage);
SCHEDULE (terminate);
#ifndef NPROOFS
if (tissat_found_drabt || tissat_found_drat_trim)
SCHEDULE (prove);
#endif
#ifndef NDEBUG
SCHEDULE (dump);
#endif
if (tissat_scheduled)
{
tissat_line ();
if (tissat_sequential)
tissat_run_jobs (0);
else
tissat_run_jobs (tissat_processes);
if (tissat_verbosity)
tissat_section ("Finished");
else
tissat_line ();
tissat_message ("All %u test jobs %ssucceeded%s in %.2f seconds.",
tissat_scheduled,
kissat_bold_green_color_code (1),
kissat_normal_color_code (1),
kissat_wall_clock_time () - start);
tissat_release_jobs ();
}
else
tissat_warning ("No job scheduled.");
return 0;
}