113 lines
2.1 KiB
C
113 lines
2.1 KiB
C
// 19 january 2020
|
|
#include "test.h"
|
|
|
|
// Do not put any test cases in this file; they will not be run.
|
|
|
|
static int testcmp(const void *aa, const void *bb)
|
|
{
|
|
const struct testingprivCase *a = (const struct testingprivCase *) aa;
|
|
const struct testingprivCase *b = (const struct testingprivCase *) bb;
|
|
|
|
return strcmp(a->name, b->name);
|
|
}
|
|
|
|
struct defer {
|
|
void (*f)(void *data);
|
|
void *data;
|
|
struct defer *next;
|
|
};
|
|
|
|
static struct defer *defers = NULL;
|
|
|
|
static void runDefers(void)
|
|
{
|
|
struct defer *d;
|
|
|
|
for (d = defers; d != NULL; d = d->next)
|
|
(*(d->f))(d->data);
|
|
}
|
|
|
|
static int testingprivRet = 0;
|
|
|
|
void TestFail(void)
|
|
{
|
|
testingprivRet = 1;
|
|
}
|
|
|
|
void TestFailNow(void)
|
|
{
|
|
exit(1);
|
|
}
|
|
|
|
void TestSkipNow(void)
|
|
{
|
|
// see https://mesonbuild.com/Unit-tests.html#skipped-tests-and-hard-errors
|
|
exit(77);
|
|
}
|
|
|
|
void TestDefer(void (*f)(void *data), void *data)
|
|
{
|
|
struct defer *d;
|
|
|
|
d = (struct defer *) malloc(sizeof (struct defer));
|
|
if (d == NULL) {
|
|
fprintf(stderr, "** internal error: memory exhausted in TestDefer()\n");
|
|
abort();
|
|
}
|
|
memset(d, 0, sizeof (struct defer));
|
|
d->f = f;
|
|
d->data = data;
|
|
d->next = defers;
|
|
defers = d;
|
|
}
|
|
|
|
static const char *basename(const char *file)
|
|
{
|
|
const char *p;
|
|
|
|
for (;;) {
|
|
p = strpbrk(file, "/\\");
|
|
if (p == NULL)
|
|
break;
|
|
file = p + 1;
|
|
}
|
|
return file;
|
|
}
|
|
|
|
void testingprivLogfFullThen(FILE *f, void (*then)(void), const char *filename, long line, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
fprintf(f, "%s:%ld: ", basename(filename), line);
|
|
vfprintf(f, fmt, ap);
|
|
fprintf(f, "\n");
|
|
va_end(ap);
|
|
if (then != NULL)
|
|
(*then)();
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct testingprivCase *t;
|
|
struct testingprivCase want;
|
|
|
|
if (argc != 2) {
|
|
fprintf(stderr, "usage: %s TestName\n", argv[0]);
|
|
return 1;
|
|
}
|
|
want.name = argv[1];
|
|
t = (struct testingprivCase *) bsearch(&want, testingprivCases, testingprivNumCases, sizeof (struct testingprivCase), testcmp);
|
|
if (t == NULL) {
|
|
fprintf(stderr, "%s: no such test\n", argv[1]);
|
|
return 1;
|
|
}
|
|
testingprivRet = 0;
|
|
if (atexit(runDefers) != 0) {
|
|
fprintf(stderr, "atexit(runDefers) failed (errno %d); can't test\n", errno);
|
|
return 1;
|
|
}
|
|
(*(t->f))();
|
|
return testingprivRet;
|
|
}
|