From 0149639edc837d97288764e80ac336d1a9691fe7 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Wed, 10 Apr 2019 14:19:17 -0400 Subject: [PATCH] Cleaned things up a bit for libui's test suite. --- test/{testing_testing.c => testing.c} | 63 +++++++++++++++++---------- test/testing.h | 41 +++++++++-------- 2 files changed, 63 insertions(+), 41 deletions(-) rename test/{testing_testing.c => testing.c} (77%) diff --git a/test/testing_testing.c b/test/testing.c similarity index 77% rename from test/testing_testing.c rename to test/testing.c index eb334648..ddd423ba 100644 --- a/test/testing_testing.c +++ b/test/testing.c @@ -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); diff --git a/test/testing.h b/test/testing.h index c3a28316..87659809 100644 --- a/test/testing.h +++ b/test/testing.h @@ -6,33 +6,38 @@ #include -#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);