Cleaned things up a bit for libui's test suite.
This commit is contained in:
parent
b26e0677af
commit
0149639edc
|
@ -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);
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue