diff --git a/common/opentype_test.c b/common/opentype_test.c index 3fe00079..589353e8 100644 --- a/common/opentype_test.c +++ b/common/opentype_test.c @@ -3,52 +3,7 @@ #error TODO this is where libui itself goes #endif #include - -#include - -#undef testingprivBadLanguageVersion -#ifdef __cplusplus -// TODO https://stackoverflow.com/questions/2324658/how-to-determine-the-version-of-the-c-standard-used-by-the-compiler implies this won't do with C++0x-era compilers, and https://wiki.apache.org/stdcxx/C++0xCompilerSupport doesn't talk about va_copy() so a simple version check for the C99 preprocessor may be wrong... -// TODO what if __cplusplus is blank (maybe only in that case, since IIRC C++98 requires __cplusplus to have a value)? -#if __cplusplus < 201103L -#define testingprivBadLanguageVersion -#endif -#elif !defined(__STDC_VERSION__) -#define testingprivBadLanguageVersion -#elif __STDC_VERSION__ < 199901L -#define testingprivBadLanguageVersion -#endif -#ifdef testingprivBadLanguageVersion -#error sorry, TODO requires either C99 or C++11; cannot continue -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(__GNUC__) -#define testingTest(Name) \ - void Test ## Name(testingT *t); \ - __attribute__((constructor)) static inline void testingprivCtorRegisterTest ## Name(void) { testingprivRegisterTest("Test" #Name, Test ## Name); } \ - void Test ## Name(testingT *t) -#else -#error unknown compiler; cannot continue -#endif - -extern int testingMain(void); - -typedef struct testingT testingT; -#define testingTErrorf(t, ...) testingprivTErrorfFull(t, __FILE__, __LINE__, __VA_ARGS__) -#define testingTErrorvf(t, format, ap) testingprivTErrorvfFull(t, __FILE__, __LINE__, format, ap) - -// TODO should __LINE__ arguments use intmax_t or uintmax_t instead of int? -extern void testingprivRegisterTest(const char *, void (*)(testingT *)); -extern void testingprivTErrorfFull(testingT *, const char *, int, const char *, ...); -extern void testingprivTErrorvfFull(testingT *, const char *, int, const char *, va_list); - -#ifdef __cplusplus -} -#endif +#include "testing.h" #include #include @@ -89,85 +44,3 @@ int main(void) { return testingMain(); } - -#include -#include - -#define testingprivNew(T) ((T *) malloc(sizeof (T))) - -struct testingT { - const char *name; - void (*f)(testingT *); - int failed; - testingT *next; -}; - -static testingT *tests = NULL; - -void testingprivRegisterTest(const char *name, void (*f)(testingT *)) -{ - testingT *t; - - t = testingprivNew(testingT); - t->name = name; - t->f = f; - t->failed = 0; - t->next = tests; - tests = t; -} - -int testingMain(void) -{ - testingT *t; - int anyFailed; - const char *status; - - if (tests == NULL) { - fprintf(stderr, "warning: no tests to run\n"); - // imitate Go here (TODO confirm this) - return 0; - } - - anyFailed = 0; - for (t = tests; t != NULL; t = t->next) { - printf("=== RUN %s\n", t->name); - (*(t->f))(t); - status = "PASS"; - if (t->failed) { - status = "FAIL"; - anyFailed = 1; - } - printf("--- %s: %s (%s)\n", status, t->name, "TODO"); - } - - if (anyFailed) { - printf("FAIL\n"); - return 1; - } - printf("PASS\n"); - return 0; -} - -static void testingprivTDoLog(testingT *t, const char *file, int line, const char *format, va_list ap) -{ - // TODO extract filename from file - printf("\t%s:%d: ", file, line); - // TODO split into lines separated by \n\t\t and trimming trailing empty lines - vprintf(format, ap); - printf("\n"); -} - -void testingprivTErrorfFull(testingT *t, const char *file, int line, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - testingprivTErrorvfFull(t, file, line, format, ap); - va_end(ap); -} - -void testingprivTErrorvfFull(testingT *t, const char *file, int line, const char *format, va_list ap) -{ - testingprivTDoLog(t, file, line, format, ap); - t->failed = 1; -} diff --git a/common/testing.h b/common/testing.h new file mode 100644 index 00000000..9d8c8006 --- /dev/null +++ b/common/testing.h @@ -0,0 +1,63 @@ +// 27 february 2018 + +#ifndef testingprivIncludeGuard_testing_h +#define testingprivIncludeGuard_testing_h + +#include + +#undef testingprivBadLanguageVersion +#ifdef __cplusplus +// TODO https://stackoverflow.com/questions/2324658/how-to-determine-the-version-of-the-c-standard-used-by-the-compiler implies this won't do with C++0x-era compilers, and https://wiki.apache.org/stdcxx/C++0xCompilerSupport doesn't talk about va_copy() so a simple version check for the C99 preprocessor may be wrong... +// TODO what if __cplusplus is blank (maybe only in that case, since IIRC C++98 requires __cplusplus to have a value)? +#if __cplusplus < 201103L +#define testingprivBadLanguageVersion +#endif +#elif !defined(__STDC_VERSION__) +#define testingprivBadLanguageVersion +#elif __STDC_VERSION__ < 199901L +#define testingprivBadLanguageVersion +#endif +#ifdef testingprivBadLanguageVersion +#error sorry, TODO requires either C99 or C++11; cannot continue +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__GNUC__) +#define testingprivMkCtor(name, reg) \ + __attribute__((constructor)) static void testingprivCtor ## name(void) { reg(#name, name); } +#elif defined(_MSC_VER) +#define testingprivMkCtorPrototype(name, reg) \ + static int name(void) testingprivCtor ## name(void) { reg(#name, name); 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, name); } +#else +#error unknown compiler; cannot continue +#endif + +#define testingTest(Name) \ + void Test ## Name(testingT *t); \ + testingprivMkCtor(Test ## Name, testingprivRegisterTest) \ + void Test ## Name(testingT *t) + +extern int testingMain(void); + +typedef struct testingT testingT; +#define testingTErrorf(t, ...) testingprivTErrorfFull(t, __FILE__, __LINE__, __VA_ARGS__) +#define testingTErrorvf(t, format, ap) testingprivTErrorvfFull(t, __FILE__, __LINE__, format, ap) + +// TODO should __LINE__ arguments use intmax_t or uintmax_t instead of int? +extern void testingprivRegisterTest(const char *, void (*)(testingT *)); +extern void testingprivTErrorfFull(testingT *, const char *, int, const char *, ...); +extern void testingprivTErrorvfFull(testingT *, const char *, int, const char *, va_list); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/common/testing_testing.c b/common/testing_testing.c new file mode 100644 index 00000000..c8d0d986 --- /dev/null +++ b/common/testing_testing.c @@ -0,0 +1,83 @@ +// 27 february 2018 +#include +#include +#include "testing.h" + +#define testingprivNew(T) ((T *) malloc(sizeof (T))) + +struct testingT { + const char *name; + void (*f)(testingT *); + int failed; + testingT *next; +}; + +static testingT *tests = NULL; + +void testingprivRegisterTest(const char *name, void (*f)(testingT *)) +{ + testingT *t; + + t = testingprivNew(testingT); + t->name = name; + t->f = f; + t->failed = 0; + t->next = tests; + tests = t; +} + +int testingMain(void) +{ + testingT *t; + int anyFailed; + const char *status; + + if (tests == NULL) { + fprintf(stderr, "warning: no tests to run\n"); + // imitate Go here (TODO confirm this) + return 0; + } + + anyFailed = 0; + for (t = tests; t != NULL; t = t->next) { + printf("=== RUN %s\n", t->name); + (*(t->f))(t); + status = "PASS"; + if (t->failed) { + status = "FAIL"; + anyFailed = 1; + } + printf("--- %s: %s (%s)\n", status, t->name, "TODO"); + } + + if (anyFailed) { + printf("FAIL\n"); + return 1; + } + printf("PASS\n"); + return 0; +} + +static void testingprivTDoLog(testingT *t, const char *file, int line, const char *format, va_list ap) +{ + // TODO extract filename from file + printf("\t%s:%d: ", file, line); + // TODO split into lines separated by \n\t\t and trimming trailing empty lines + vprintf(format, ap); + printf("\n"); +} + +void testingprivTErrorfFull(testingT *t, const char *file, int line, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + testingprivTErrorvfFull(t, file, line, format, ap); + va_end(ap); +} + +void testingprivTErrorvfFull(testingT *t, const char *file, int line, const char *format, va_list ap) +{ + testingprivTDoLog(t, file, line, format, ap); + t->failed = 1; +}