chiark / gitweb /
Infrastructure: Split the files into subdirectories.
[mLib] / testrig.c
diff --git a/testrig.c b/testrig.c
deleted file mode 100644 (file)
index c85276f..0000000
--- a/testrig.c
+++ /dev/null
@@ -1,531 +0,0 @@
-/* -*-c-*-
- *
- * Generic test driver
- *
- * (c) 1998 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of the mLib utilities library.
- *
- * mLib is free software; you can redistribute it and/or modify
- * 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "dstr.h"
-#include "report.h"
-#include "quis.h"
-#include "testrig.h"
-
-/*----- Static variables --------------------------------------------------*/
-
-static dstr tok = DSTR_INIT;
-
-enum {
-  TOK_EOF = 0x100,
-  TOK_WORD
-};
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @decode@ --- *
- *
- * Arguments:  @int tok@ = token type to decode
- *
- * Returns:    Pointer to a textual representation of the token.
- *
- * Use:                Produces a readable representation of a token.
- */
-
-static const char *decode(int t)
-{
-  static char buf[4];
-
-  switch (t) {
-    case TOK_EOF:
-      return ("<eof>");
-    case TOK_WORD:
-      return (tok.buf);
-    default:
-      buf[0] = t;
-      buf[1] = 0;
-      return (buf);
-  }
-  return ("<buggy-program>");
-}
-
-/* --- @gettok@ --- *
- *
- * Arguments:  @FILE *fp@ = file handle to read from
- *
- * Returns:    Type of token read.
- *
- * Use:                Reads a token from the input stream.
- */
-
-static int gettok(FILE *fp)
-{
-  int ch;
-
-  /* --- Clear the token accumulator --- */
-
-  DRESET(&tok);
-
-  /* --- Prime the lookahead character --- */
-
-again:
-  ch = getc(fp);
-
-  /* --- Skip leading whitespace --- */
-
-  while (isspace((unsigned char)ch))
-    ch = getc(fp);
-
-  /* --- Trap some special characters --- */
-
-  switch (ch) {
-
-    /* --- Comments --- */
-
-    case '#':
-      do ch = getc(fp); while (ch != EOF && ch != '\n');
-      goto again;
-
-    /* --- End of file --- */
-
-    case EOF:
-      return (TOK_EOF);
-
-    /* --- Quote characters --- */
-
-    case '`':
-      ch = '\'';
-    case '\'':
-    case '\"': {
-      int quote = ch;
-
-      for (;;) {
-       ch = getc(fp);
-       if (ch == EOF || ch == quote)
-         break;
-       if (ch == '\\') {
-         ch = getc(fp);
-         if (ch == EOF)
-           ch = '\\';
-       }
-       DPUTC(&tok, ch);
-      }
-      DPUTZ(&tok);
-      return (TOK_WORD);
-    }
-
-    /* --- Self-delimiting things --- */
-
-    case ';':
-    case '{':
-    case '}':
-      return (ch);
-
-    /* --- Anything else is a word --- */
-
-    default:
-      for (;;) {
-       DPUTC(&tok, ch);
-       ch = getc(fp);
-       switch (ch) {
-         case EOF:
-         case ';':
-         case '{':
-         case '}':
-         case '\"':
-         case '\'':
-         case '`':
-           goto done;
-         default:
-           if (isspace((unsigned char)ch))
-             goto done;
-       }
-       if (ch == '\\') {
-         ch = getc(fp);
-         if (ch == EOF)
-           ch = '\\';
-       }
-      }
-    done:
-      ungetc(ch, fp);
-      DPUTZ(&tok);
-      return (TOK_WORD);
-  }
-}
-
-/* --- @type_hex@ --- */
-
-static void cvt_hex(const char *s, dstr *d)
-{
-  while (s[0] && s[1]) {
-    int x = s[0], y = s[1];
-    if ('0' <= x && x <= '9') x -= '0';
-    else if ('A' <= x && x <= 'F') x -= 'A' - 10;
-    else if ('a' <= x && x <= 'f') x -= 'a' - 10;
-    else x = 0;
-    if ('0' <= y && y <= '9') y -= '0';
-    else if ('A' <= y && y <= 'F') y -= 'A' - 10;
-    else if ('a' <= y && y <= 'f') y -= 'a' - 10;
-    else y = 0;
-    DPUTC(d, (x << 4) + y);
-    s += 2;
-  }
-}
-
-static void dump_hex(dstr *d, FILE *fp)
-{
-  const char *p, *q;
-  for (p = d->buf, q = p + d->len; p < q; p++)
-    fprintf(fp, "%02x", *(unsigned char *)p);
-}
-
-const test_type type_hex = { cvt_hex, dump_hex };
-
-/* --- @type_string@ --- */
-
-static void cvt_string(const char *s, dstr *d)
-{
-  DPUTS(d, s);
-}
-
-static void dump_string(dstr *d, FILE *fp)
-{
-  DWRITE(d, fp);
-}
-
-const test_type type_string = { cvt_string, dump_string };
-
-/* --- @type_int@ --- */
-
-static void cvt_int(const char *s, dstr *d)
-{
-  DENSURE(d, sizeof(int));
-  sscanf(s, "%i", (int *)d->buf);
-}
-
-static void dump_int(dstr *d, FILE *fp)
-{
-  fprintf(fp, "%i", *(int *)d->buf);
-}
-
-const test_type type_int = { cvt_int, dump_int };
-
-/* --- @type_long@ --- */
-
-static void cvt_long(const char *s, dstr *d)
-{
-  DENSURE(d, sizeof(long));
-  *(long *)d->buf = strtol(s, 0, 0);
-}
-
-static void dump_long(dstr *d, FILE *fp)
-{
-  fprintf(fp, "%li", *(long *)d->buf);
-}
-
-const test_type type_long = { cvt_long, dump_long };
-
-/* --- @type_ulong@ --- */
-
-static void cvt_ulong(const char *s, dstr *d)
-{
-  DENSURE(d, sizeof(unsigned long));
-  *(unsigned long *)d->buf = strtoul(s, 0, 0);
-}
-
-static void dump_ulong(dstr *d, FILE *fp)
-{
-  fprintf(fp, "%lu", *(unsigned long *)d->buf);
-}
-
-const test_type type_ulong = { cvt_ulong, dump_ulong };
-
-/* --- @type_uint32@ --- */
-
-static void cvt_uint32(const char *buf, dstr *d)
-{
-  DENSURE(d, sizeof(uint32));
-  *(uint32 *)d->buf = strtoul(buf, 0, 0);
-}
-
-static void dump_uint32(dstr *d, FILE *fp)
-{
-  fprintf(fp, "%lu\n", (unsigned long)*(uint32 *)d->buf);
-}
-
-const test_type type_uint32 = { cvt_uint32, dump_uint32 };
-
-/* --- @test_do@ --- *
- *
- * Arguments:  @const test_suite suites[]@ = pointer to suite definitions
- *             @FILE *fp@ = test vector file, ready opened
- *             @test_results *results@ = where to put results
- *
- * Returns:    Negative if something bad happened, or the number of
- *             failures.
- *
- * Use:                Runs a collection of tests against a file of test vectors and
- *             reports the results.
- */
-
-int test_do(const test_suite suites[], FILE *fp, test_results *results)
-{
-  test_results dummy;
-  dstr dv[TEST_FIELDMAX];
-  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]);
-
-  if (!results)
-    results = &dummy;
-  results->tests = 0;
-  results->failed = 0;
-
-  for (;;) {
-    int t = gettok(fp);
-
-    /* --- This is a reasonable place to stop --- */
-
-    if (t == TOK_EOF)
-      break;
-
-    /* --- Pick out the chunk name --- */
-
-    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 --- */
-
-    if (!chunks)
-      goto skip_chunk;
-    for (cch = chunks; ; cch++) {
-      if (!cch->name)
-       goto skip_chunk;
-      if (strcmp(tok.buf, cch->name) == 0)
-       break;
-    }
-
-    /* --- Past the open brace to the first chunk --- */
-
-    if ((t = gettok(fp)) != '{') {
-      moan("expected `{'; found `%s'", decode(t));
-      goto done;
-    }
-
-    /* --- Start on the test data now --- */
-
-    printf("%s: ", cch->name);
-    fflush(stdout);
-    ok = 1;
-
-    for (;;) {
-      t = gettok(fp);
-
-      /* --- Accept a close brace --- */
-
-      if (t == '}')
-       break;
-
-      /* --- Otherwise I expect a list of words --- */
-
-      for (i = 0; cch->f[i]; i++) {
-       DRESET(&dv[i]);
-       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 != ';') {
-       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 < results->tests; i++) putchar('.');
-       results->failed++;
-      }
-      putchar('.');
-      results->tests++;
-      fflush(stdout);
-    }
-
-    puts(ok ? " ok" : " failed");
-    fflush(stdout);
-    continue;
-
-  skip_chunk:
-    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 != ';') {
-       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;
-      }
-    }
-  }
-
-  /* --- 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 -------------------------------------------------*/