Cleaned things up a bit for libui's test suite.

This commit is contained in:
Pietro Gagliardi 2019-04-10 14:19:17 -04:00
parent b26e0677af
commit 0149639edc
2 changed files with 63 additions and 41 deletions

View File

@ -24,8 +24,9 @@ struct testingT {
};
static testingT *tests = NULL;
static testingT *testsTail = NULL;
void testingprivRegisterTest(const char *name, void (*f)(testingT *))
static void testingprivNewTest(const char *name, void (*f)(testingT *), testingT *prev)
{
testingT *t;
@ -36,9 +37,18 @@ void testingprivRegisterTest(const char *name, void (*f)(testingT *))
t->skipped = 0;
t->defers = NULL;
t->defersRun = 0;
// TODO add in the order called
t->next = tests;
tests = t;
t->next = testsTail;
return t;
}
void testingprivRegisterTest(const char *name, void (*f)(testingT *))
{
testingT *t;
t = testingprivNewTest(name, f, testsTail);
testsTail = t;
if (tests == NULL)
tests = t;
}
static void runDefers(testingT *t)
@ -52,11 +62,30 @@ static void runDefers(testingT *t)
(*(d->f))(d->data);
}
static void runTestSet(testingT *t, int *anyFailed)
{
const char *status;
for (; t != NULL; t = t->next) {
printf("=== RUN %s\n", t->name);
if (setjmp(t->returnNowBuf) == 0)
(*(t->f))(t);
runDefers(t);
status = "PASS";
if (t->failed) {
status = "FAIL";
*anyFailed = 1;
} else if (t->skipped)
// note that failed overrides skipped
status = "SKIP";
printf("--- %s: %s (%s)\n", status, t->name, "TODO");
}
}
int testingMain(void)
{
testingT *t;
int anyFailed;
const char *status;
// TODO see if this should run if all tests are skipped
if (tests == NULL) {
@ -66,21 +95,7 @@ int testingMain(void)
}
anyFailed = 0;
for (t = tests; t != NULL; t = t->next) {
printf("=== RUN %s\n", t->name);
if (setjmp(t->returnNowBuf) == 0)
(*(t->f))(t);
runDefers(t);
status = "PASS";
if (t->failed) {
status = "FAIL";
anyFailed = 1;
} else if (t->skipped)
// note that failed overrides skipped
status = "SKIP";
printf("--- %s: %s (%s)\n", status, t->name, "TODO");
}
runTestSet(tests, &anyFailed);
if (anyFailed) {
printf("FAIL\n");
return 1;
@ -89,7 +104,7 @@ int testingMain(void)
return 0;
}
void testingprivTLogfFull(testingT *t, const char *file, int line, const char *format, ...)
void testingprivTLogfFull(testingT *t, const char *file, long line, const char *format, ...)
{
va_list ap;
@ -98,7 +113,7 @@ void testingprivTLogfFull(testingT *t, const char *file, int line, const char *f
va_end(ap);
}
void testingprivTLogvfFull(testingT *t, const char *file, int line, const char *format, va_list ap)
void testingprivTLogvfFull(testingT *t, const char *file, long line, const char *format, va_list ap)
{
// TODO extract filename from file
printf("\t%s:%d: ", file, line);
@ -119,13 +134,13 @@ static void returnNow(testingT *t)
longjmp(t->returnNowBuf, 1);
}
void testingprivTDoFailNow(testingT *t)
void testingprivTFailNow(testingT *t)
{
testingTFail(t);
returnNow(t);
}
void testingprivTDoSkipNow(testingT *t)
void testingprivTSkipNow(testingT *t)
{
t->skipped = 1;
returnNow(t);

View File

@ -6,33 +6,38 @@
#include <stdarg.h>
#define testingprivMkScaffold(name) \
static inline void testingprivScaffold ## name(testingT *t) { name(t); }
#define testingprivFullName(basename) testingprivImpl ## basename
#define testingprivScaffoldName(basename) testingprivScaffold ## basename
#define testingprivMkScaffold(basename, argtype, argname) \
static inline void testingprivScaffoldName(basename)(argtype *argname) { testingprivFullName(basename)(argname); }
// references:
// - https://gitlab.gnome.org/GNOME/glib/blob/master/glib/gconstructor.h
// - https://gitlab.gnome.org/GNOME/glib/blob/master/gio/glib-compile-resources.c
// - https://msdn.microsoft.com/en-us/library/bb918180.aspx
#define testingprivCtorName(basename) testingprivCtor ## basename
#define testingprivCtorPtrName(basename) testingprivCtorPtr ## basename
#if defined(__GNUC__)
#define testingprivMkCtor(name, reg) \
__attribute__((constructor)) static void testingprivCtor ## name(void) { reg(#name, testingprivScaffold ## name); }
#define testingprivMkCtor(basename, regfunc) \
__attribute__((constructor)) static void testingprivCtorName(basename)(void) { regfunc(#basename, testingprivScaffoldName(basename)); }
#elif defined(_MSC_VER)
#define testingprivMkCtorPrototype(name, reg) \
static int name(void) testingprivCtor ## name(void) { reg(#name, testingprivScaffold ## name); return 0; } \
#define testingprivMkCtor(basename, reg) \
static int testingprivCtorName(basename)(void) { regfunc(#basename, testingprivScaffoldName(basename)); return 0; } \
__pragma(section(".CRT$XCU",read)) \
__declspec(allocate(".CRT$XCU")) static int (*testingprivCtorPtr ## name)(void) = testingprivCtor ## name;
#elif defined(__SUNPRO_C)
#define testingprivMkCtor(name, reg) \
_Pragma("init(testingprivCtor" #name ")") static void testingprivCtor ## name(void) { reg(#name, testingprivScaffold ## name); }
__declspec(allocate(".CRT$XCU")) static int (*testingprivCtorPtrName(basename))(void) = testingprivCtorName(basename);
#else
#error unknown compiler for making constructors in C; cannot continue
#endif
#define testingprivMk(basename, argtype, argname, regfunc) \
void testingprivImplName(basename)(argtype *argname); \
testingprivMkScaffold(basename, argtype, argname) \
testingprivMkCtor(basename, regfunc) \
void testingprivImplName(basename)(argtype *argname)
#define testingTest(Name) \
void Test ## Name(testingT *t); \
testingprivMkScaffold(Test ## Name) \
testingprivMkCtor(Test ## Name, testingprivRegisterTest) \
void Test ## Name(testingT *t)
testingprivMk(Test ## Name, testingT, t, testingprivRegisterTest)
extern int testingMain(void);
@ -56,12 +61,14 @@ typedef struct testingT testingT;
extern void testingTFail(testingT *t);
extern void testingTFailNow(testingT *t);
extern void testingTSkipNow(testingT *t);
// TODO should the defered function also have t passed to it?
extern void testingTDefer(testingT *t, void (*f)(void *data), void *data);
// TODO should __LINE__ arguments use intmax_t or uintmax_t instead of int?
extern void testingprivRegisterTest(const char *, void (*)(testingT *));
extern void testingprivRegisterManualTest(const char *, void (*)(testingT *));
// see https://stackoverflow.com/questions/32399191/va-args-expansion-using-msvc
#define testingprivExpand(x) x
#define testingprivTLogfThen(then, t, ...) ((testingprivTLogfFull(t, __FILE__, __LINE__, __VA_ARGS__)), (then(t)))
#define testingprivTLogvfThen(then, t, format, ap) ((testingprivTLogvfFull(t, __FILE__, __LINE__, format, ap)), (then(t)))
extern void testingprivTLogfFull(testingT *, const char *, int, const char *, ...);
extern void testingprivTLogvfFull(testingT *, const char *, int, const char *, va_list);
extern void testingprivTLogfFull(testingT *, const char *, long, const char *, ...);
extern void testingprivTLogvfFull(testingT *, const char *, long, const char *, va_list);