--- /dev/null
+/*
+ * crypto-test.h: common test vector processing
+ */
+/*
+ * This file is Free Software. It was originally written for secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This software 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 software; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+
+#ifndef crypto_test_h
+#define crypto_test_h
+
+/* Basic model.
+ *
+ * There is a collection of `registers', each of which can store a value.
+ * Some registers are designated as `input': their values are set while
+ * reading the test vector. Other registers are designated as `output': the
+ * test function is expected to calculate their values, which are then
+ * compared against final values supplied by the test vector. Any
+ * discrepancies are reported.
+ *
+ * While a test suite is running, there is a single vector of registers, and
+ * registers are identified by index, starting from zero. The number of
+ * registers, `nreg', and a threshold `nrout', are defined by the test suite:
+ * registers with index less than `nrout' are for output; other registers up
+ * to, but not including, `nreg' are for input. Finally, the test suite
+ * defines the size of a register. The common test machinery treats
+ * registers as entirely opaque, acting on them only through their defined
+ * types.
+ *
+ * Each kind of test defines a register mapping, which assigns types and
+ * (textual) names to some subset of the registers. A register can be marked
+ * optional; by default, the test vector parser will report an error if a
+ * defined register is not assigned a value.
+ *
+ * The register type is responsible for handling the register on behalf of
+ * the common code. (Test functions can have built-in knowledge of which
+ * registers have which types, and can manipulate registers directly, of
+ * course.)
+ *
+ * Finally, each test defines a test runner, which is responsible for
+ * invoking the test function and checking that the output registers are
+ * correct. There is a generic test runner, but some tests might benefit
+ * from special arrangements.
+ */
+
+union regval {
+ long i; /* signed integer */
+ unsigned long u; /* unsigned integer */
+ struct { void *p; size_t sz; } bytes; /* buffer of bytes */
+#ifdef REG_MEMBERS
+ REG_MEMBERS /* your members here */
+#endif
+};
+
+struct reg {
+ unsigned f; /* flags */
+#define REGF_LIVE 1u /* input register has a value */
+ union regval v; /* register value */
+};
+
+struct regty {
+ void (*init)(union regval *v); /* set up raw memory */
+ void (*parse)(union regval *v, char *p); /* parse text input as value */
+ void (*dump)(FILE *fp, const union regval *v); /* dump value as text */
+ int (*eq)(const union regval *v0, const union regval *v1); /* equal? */
+ void (*release)(union regval *v); /* release any resources */
+};
+
+struct regdef {
+ const char *name; /* register name (for input files) */
+ unsigned i; /* register index */
+ const struct regty *ty; /* register type descriptor */
+ unsigned f; /* flags */
+#define REGF_OPT 1u /* (input) register is optional */
+};
+#define REGLIST_END { 0 }
+
+struct test_state {
+ struct reg *in, *out; /* vectors of registers */
+ unsigned nrout; /* number of output registers */
+ unsigned nreg; /* total number of registers */
+ size_t regsz; /* size of an individual register */
+ int win, lose; /* number of tests passed/failed */
+};
+
+struct test {
+ const char *name; /* name of the test */
+ void (*run)(struct test_state *state, const struct test *test);
+ /* test runner (`run_test') */
+ const struct regdef *regs; /* register definitions */
+ void (*fn)(struct reg *out, const struct reg *in, void *ctx);
+ /* test function */
+};
+
+/* Utility functions. */
+extern NORETURN(bail(const char *msg, ...))
+ FORMAT(printf, 1, 2);
+extern void parse_hex(uint8_t *b, size_t sz, char *p);
+extern void dump_hex(FILE *fp, const uint8_t *b, size_t sz);
+extern void trivial_regty_init(union regval *v);
+extern void trivial_regty_release(union regval *v);
+extern void allocate_bytes(union regval *v, size_t sz);
+
+/* Built-in register types. */
+extern const struct regty
+ regty_int,
+ regty_uint,
+ regty_bytes;
+
+/* Running tests. */
+extern void check_test_output(struct test_state *state,
+ const struct test *test);
+extern void run_test(struct test_state *state, const struct test *test);
+extern int run_test_suite(unsigned nrout, unsigned nreg, size_t regsz,
+ const struct test *tests, FILE *fp);
+
+#endif