/* -*-c-*-
*
- * $Id: testrig.c,v 1.9 2000/06/17 10:35:07 mdw Exp $
+ * $Id: testrig.c,v 1.10 2004/04/08 01:36:13 mdw Exp $
*
* Generic test driver
*
* (c) 1998 Straylight/Edgeware
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
* This file is part of the mLib utilities library.
*
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
- *
+ *
* mLib 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 Library General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Library General Public
* License along with mLib; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: testrig.c,v $
- * Revision 1.9 2000/06/17 10:35:07 mdw
- * Initialize the token buffer properly.
- *
- * Revision 1.8 1999/12/10 23:41:37 mdw
- * Support for different sizes and types of integers.
- *
- * Revision 1.7 1999/11/21 13:01:39 mdw
- * Allow more characters to start words in test vector files.
- *
- * Revision 1.6 1999/11/16 15:03:23 mdw
- * Mark test types as constant.
- *
- * Revision 1.5 1999/05/21 22:14:30 mdw
- * Take advantage of the new dynamic string macros.
- *
- * Revision 1.4 1999/05/19 19:02:17 mdw
- * Aesthetic changes: fix spelling of `initialize'; use uppercase token
- * constants; abandon old double-underscore convention for internal
- * functions and variables.
- *
- * Revision 1.3 1999/05/06 19:51:35 mdw
- * Reformatted the LGPL notice a little bit.
- *
- * Revision 1.2 1999/05/05 18:50:31 mdw
- * Change licensing conditions to LGPL.
- *
- * Revision 1.1.1.1 1998/06/17 23:44:42 mdw
- * Initial version of mLib
- *
- */
-
/*----- Header files ------------------------------------------------------*/
#include <ctype.h>
goto again;
/* --- End of file --- */
-
+
case EOF:
return (TOK_EOF);
const test_type type_uint32 = { cvt_uint32, dump_uint32 };
-/* --- @test_run@ --- *
+/* --- @test_do@ --- *
*
- * Arguments: @int argc@ = number of command line arguments
- * @char *argv[]@ = pointer to command line arguments
- * @const test_chunk chunk[]@ = pointer to chunk definitions
- * @const char *vec@ = name of default test vector file
+ * Arguments: @const test_suite suites[]@ = pointer to suite definitions
+ * @FILE *fp@ = test vector file, ready opened
+ * @test_results *results@ = where to put results
*
- * Returns: Doesn't.
+ * Returns: Negative if something bad happened, or the number of
+ * failures.
*
- * Use: Runs a set of test vectors to ensure that a component is
- * working properly.
+ * Use: Runs a collection of tests against a file of test vectors and
+ * reports the results.
*/
-void test_run(int argc, char *argv[],
- const test_chunk chunk[],
- const char *vec)
+int test_do(const test_suite suites[], FILE *fp, test_results *results)
{
- FILE *fp;
- int i;
- const test_chunk *cch;
+ test_results dummy;
dstr dv[TEST_FIELDMAX];
- int fail = 0, ok = 1;
- int sofar = 0;
-
- /* --- Silly bits of initialization --- */
-
- ego(argv[0]);
+ const test_suite *ss;
+ const test_chunk *chunks = suites[0].chunks;
+ const test_chunk *cch;
+ int rc = -1;
+ int ok;
+ int i;
for (i = 0; i < TEST_FIELDMAX; i++)
DCREATE(&dv[i]);
- /* --- Parse command line arguments --- */
-
- {
- const char *p = 0;
-
- i = 0;
- for (;;) {
- if (!p || !*p) {
- if (i >= argc - 1)
- break;
- p = argv[++i];
- if (strcmp(p, "--") == 0) {
- i++;
- break;
- }
- if (p[0] != '-' || p[1] == 0)
- break;
- p++;
- }
- switch (*p++) {
- case 'h':
- printf("%s test driver\n"
- "Usage: %s [-f FILENAME]\n", QUIS, QUIS);
- exit(0);
- case 'f':
- if (!*p) {
- if (i >= argc - 1)
- die(1, "option `-f' expects an argument");
- p = argv[++i];
- }
- vec = p;
- p = 0;
- break;
- default:
- die(1, "option `-%c' unknown", p[-1]);
- break;
- }
- }
- }
-
- /* --- Start parsing from the file --- */
-
- if ((fp = fopen(vec, "r")) == 0)
- die(1, "couldn't open test vector file `%s': %s", vec, strerror(errno));
+ if (!results)
+ results = &dummy;
+ results->tests = 0;
+ results->failed = 0;
for (;;) {
int t = gettok(fp);
/* --- Pick out the chunk name --- */
- if (t != TOK_WORD)
- die(1, "expected <word>; found `%s'", decode(t));
+ if (t != TOK_WORD) {
+ moan("expected <word>; found `%s'", decode(t));
+ goto done;
+ }
+
+ if (strcmp(tok.buf, "SUITE") == 0) {
+ t = gettok(fp);
+ if (t != TOK_WORD) {
+ moan("expected <word>; found `%s'", decode(t));
+ goto done;
+ }
+ for (ss = suites; ; ss++) {
+ if (!ss->name) {
+ chunks = 0;
+ break;
+ }
+ if (strcmp(tok.buf, ss->name) == 0) {
+ chunks = ss->chunks;
+ break;
+ }
+ }
+ continue;
+ }
/* --- Find the right chunk block --- */
- for (cch = chunk; ; cch++) {
+ if (!chunks)
+ goto skip_chunk;
+ for (cch = chunks; ; cch++) {
if (!cch->name)
goto skip_chunk;
if (strcmp(tok.buf, cch->name) == 0)
/* --- Past the open brace to the first chunk --- */
- if ((t = gettok(fp)) != '{')
- die(1, "expected `{'; found `%s'", decode(t));
+ if ((t = gettok(fp)) != '{') {
+ moan("expected `{'; found `%s'", decode(t));
+ goto done;
+ }
/* --- Start on the test data now --- */
printf("%s: ", cch->name);
fflush(stdout);
- sofar = 0;
ok = 1;
for (;;) {
for (i = 0; cch->f[i]; i++) {
DRESET(&dv[i]);
- if (t != TOK_WORD)
- die(1, "expected <word>; found `%s'", decode(t));
+ if (t != TOK_WORD) {
+ moan("expected <word>; found `%s'", decode(t));
+ goto done;
+ }
cch->f[i]->cvt(tok.buf, &dv[i]);
t = gettok(fp);
}
/* --- And a terminating semicolon --- */
- if (t != ';')
- die(1, "expected `;'; found `%s'", decode(t));
+ if (t != ';') {
+ moan("expected `;'; found `%s'", decode(t));
+ goto done;
+ }
/* --- Run the test code --- */
if (!cch->test(dv)) {
+ ok = 0;
printf("%s: ", cch->name);
- for (i = 0; i < sofar; i++) putchar('.');
- fail = 1; ok = 0;
+ for (i = 0; i < results->tests; i++) putchar('.');
+ results->failed++;
}
- sofar++;
putchar('.');
+ results->tests++;
fflush(stdout);
}
continue;
skip_chunk:
- if ((t = gettok(fp)) != '{')
- die(1, "expected '{'; found `%s'", decode(t));
+ if ((t = gettok(fp)) != '{') {
+ moan("expected '{'; found `%s'", decode(t));
+ goto done;
+ }
for (;;) {
t = gettok(fp);
if (t == '}')
break;
while (t == TOK_WORD)
t = gettok(fp);
- if (t != ';')
- die(1, "expected `;'; found `%s'", decode(t));
- }
+ if (t != ';') {
+ moan("expected `;'; found `%s'", decode(t));
+ goto done;
+ }
+ }
+ }
+ rc = results->failed;
+
+ /* --- All done --- */
+
+done:
+ for (i = 0; i < TEST_FIELDMAX; i++)
+ dstr_destroy(&dv[i]);
+ return (rc);
+}
+
+/* --- @test_run@ --- *
+ *
+ * Arguments: @int argc@ = number of command line arguments
+ * @char *argv[]@ = pointer to command line arguments
+ * @const test_chunk chunk[]@ = pointer to chunk definitions
+ * @const char *vec@ = name of default test vector file
+ *
+ * Returns: Doesn't.
+ *
+ * Use: Runs a set of test vectors to ensure that a component is
+ * working properly.
+ */
+
+void test_run(int argc, char *argv[],
+ const test_chunk chunk[],
+ const char *vec)
+{
+ FILE *fp;
+ test_results res;
+ int rc;
+ test_suite suite[2];
+
+ /* --- Silly bits of initialization --- */
+
+ ego(argv[0]);
+
+ /* --- Parse command line arguments --- */
+
+ {
+ const char *p = 0;
+ int i = 0;
+
+ for (;;) {
+ if (!p || !*p) {
+ if (i >= argc - 1)
+ break;
+ p = argv[++i];
+ if (strcmp(p, "--") == 0) {
+ i++;
+ break;
+ }
+ if (p[0] != '-' || p[1] == 0)
+ break;
+ p++;
+ }
+ switch (*p++) {
+ case 'h':
+ printf("%s test driver\n"
+ "Usage: %s [-f FILENAME]\n", QUIS, QUIS);
+ exit(0);
+ case 'f':
+ if (!*p) {
+ if (i >= argc - 1)
+ die(1, "option `-f' expects an argument");
+ p = argv[++i];
+ }
+ vec = p;
+ p = 0;
+ break;
+ default:
+ die(1, "option `-%c' unknown", p[-1]);
+ break;
+ }
+ }
}
- exit(fail);
+ /* --- Start parsing from the file --- */
+
+ if ((fp = fopen(vec, "r")) == 0)
+ die(1, "couldn't open test vector file `%s': %s", vec, strerror(errno));
+ suite[0].name = "simple";
+ suite[0].chunks = chunk;
+ suite[1].name = 0;
+ rc = test_do(suite, fp, &res);
+ if (rc < 0)
+ exit(127);
+ if (res.failed) {
+ fprintf(stderr, "FAILED %u of %u test%s\n",
+ res.failed, res.tests, res.tests == 1 ? "" : "s");
+ } else {
+ fprintf(stderr, "PASSED all %u test%s\n",
+ res.tests, res.tests == 1 ? "" : "s");
+ }
+ exit(!!res.failed);
}
/*----- That's all, folks -------------------------------------------------*/