/* vi: set ts=2 shiftwidth=2 expandtab: * * Copyright (C) 2003-2007 Simon Baldwin and Mark J. Tilford * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /* * Module notes: * * o In order to validate all its arguments, this module creates and retains * a copy of every valid game encountered, only freeing them all at the end. * This could make it very memory-hungry when running a large number of * games and scripts. The alternative is to only create games as needed, * and free them once used, but it's nice to fully validate all command line * arguments first, and work afterwards, so for now that's what's done. * * o ...Alternatively, we could validate by creating the game, destroy it, * and then re-parse it later when running the test script. Unfortunately, * parsing an Adrift game can be lengthy (~seconds), so paying this price * twice isn't too attractive either. * * o For now, then, if running lots of test, run in batches of ten or so. */ #include #include #include #include #include #include #include "scare.h" #include "sxprotos.h" /* * main() * * Validate the command line, and each argument as a game to be run. * Execute scripts for each, and return with an error code if any test fails. */ int main (int argc, const char *argv[]) { const sc_char *const program = argv[0]; sc_bool is_verbose = FALSE, is_tracing = FALSE; sx_test_descriptor_t *tests; sc_int count, index_, errors; assert (argc > 0 && argv); /* Get options and validate the command line. */ if (argc > 1 && (strcmp (argv[1], "-v") == 0 || strcmp (argv[1], "-vv") == 0)) { is_verbose = TRUE; is_tracing = (strcmp (argv[1], "-vv") == 0); argc--; argv++; } if (argc < 2) { fprintf (stderr, "Usage: %s [-v | -vv] test [test...]\n", program); return EXIT_FAILURE; } /* * Force test reproducibility. Because game construction may use random * numbers, we also need to remember to reseed this before constructing * each game, and then again before running each. */ sc_set_portable_random (TRUE); /* Set verbosity and tracing for other modules. */ scr_set_verbose (is_verbose); stub_debug_trace (is_tracing); if (getenv ("SC_TRACE_FLAGS")) sc_set_trace_flags (strtoul (getenv ("SC_TRACE_FLAGS"), NULL, 0)); /* Create an array of test descriptors large enough for all tests. */ tests = sx_malloc ((argc - 1) * sizeof (*tests)); /* Validate each test argument by opening a game and script for it. */ count = 0; for (index_ = 1; index_ < argc; index_++) { const sc_char *name; FILE *stream; sx_script script; sc_game game; name = argv[index_]; script = sx_fopen (name, "scr", "r"); if (!script) { fprintf (stderr, "%s: %s.scr: %s\n", program, name, strerror (errno)); continue; } stream = sx_fopen (name, "taf", "rb"); if (!stream) { fprintf (stderr, "%s: %s.taf: %s\n", program, name, strerror (errno)); fclose (script); continue; } sc_reseed_random_sequence (1); game = sc_game_from_stream (stream); fclose (stream); if (!game) { fprintf (stderr, "%s: %s.taf: Unable to decode Adrift game\n", program, name); fclose (script); continue; } tests[count].name = name; tests[count].script = script; tests[count].game = game; count++; } /* Run the available tests and report results. */ if (count > 0) errors = test_run_game_tests (tests, count, is_verbose); else errors = 1; /* Clean up allocations and opened files. */ for (index_ = 0; index_ < count; index_++) { fclose (tests[index_].script); sc_free_game (tests[index_].game); } sx_free (tests); /* Report results overall. */ printf ("%s [%ld test%s, %ld error%s]\n", errors > 0 ? "FAIL" : "PASS", count, count == 1 ? "" : "s", errors, errors == 1 ? "" : "s"); return errors > 0 ? EXIT_FAILURE : EXIT_SUCCESS; }