Started adding more flexible test set functionality.

This commit is contained in:
Pietro Gagliardi 2019-05-09 22:54:14 -04:00
parent f97383f66c
commit 7f986ef073
2 changed files with 32 additions and 53 deletions

View File

@ -223,18 +223,21 @@ static void initTest(testingT *t, const char *name, void (*f)(testingT *), const
#define nGrow 32 #define nGrow 32
struct testset { struct testingSet {
testingT *tests; testingT *tests;
size_t len; size_t len;
size_t cap; size_t cap;
}; };
static struct testset tests = { NULL, 0, 0 }; static testingSet mainTests = { NULL, 0, 0 };
static struct testset testsBefore = { NULL, 0, 0 };
static struct testset testsAfter = { NULL, 0, 0 };
static void testsetAdd(struct testset *set, const char *name, void (*f)(testingT *), const char *file, long line) void testingprivSetRegisterTest(testingSet **pset, const char *name, void (*f)(testingT *), const char *file, long line)
{ {
testingSet *set;
set = &mainTests;
if (pset != NULL)
set = *pset;
if (set->len == set->cap) { if (set->len == set->cap) {
size_t prevcap; size_t prevcap;
@ -246,21 +249,6 @@ static void testsetAdd(struct testset *set, const char *name, void (*f)(testingT
set->len++; set->len++;
} }
void testingprivRegisterTest(const char *name, void (*f)(testingT *), const char *file, long line)
{
testsetAdd(&tests, name, f, file, line);
}
void testingprivRegisterTestBefore(const char *name, void (*f)(testingT *), const char *file, long line)
{
testsetAdd(&testsBefore, name, f, file, line);
}
void testingprivRegisterTestAfter(const char *name, void (*f)(testingT *), const char *file, long line)
{
testsetAdd(&testsAfter, name, f, file, line);
}
static int testcmp(const void *a, const void *b) static int testcmp(const void *a, const void *b)
{ {
const testingT *ta = (const testingT *) a; const testingT *ta = (const testingT *) a;
@ -277,11 +265,6 @@ static int testcmp(const void *a, const void *b)
return 0; return 0;
} }
static void testsetSort(struct testset *set)
{
qsort(set->tests, set->len, sizeof (testingT), testcmp);
}
static void runDefers(testingT *t) static void runDefers(testingT *t)
{ {
struct defer *d; struct defer *d;
@ -297,7 +280,7 @@ static testingOptions opts = {
.Verbose = 0, .Verbose = 0,
}; };
static void testsetRun(struct testset *set, int indent, int *anyFailed) static int testsetprivRun(testingSet *set, int indent)
{ {
size_t i; size_t i;
testingT *t; testingT *t;
@ -305,7 +288,9 @@ static void testsetRun(struct testset *set, int indent, int *anyFailed)
timerTime start, end; timerTime start, end;
char timerstr[timerDurationStringLen]; char timerstr[timerDurationStringLen];
int printStatus; int printStatus;
int anyFailed = 0;
qsort(set->tests, set->len, sizeof (testingT), testcmp);
t = set->tests; t = set->tests;
for (i = 0; i < set->len; i++) { for (i = 0; i < set->len; i++) {
if (opts.Verbose) if (opts.Verbose)
@ -323,7 +308,7 @@ static void testsetRun(struct testset *set, int indent, int *anyFailed)
if (t->failed) { if (t->failed) {
status = "FAIL"; status = "FAIL";
printStatus = 1; // always print status on failure printStatus = 1; // always print status on failure
*anyFailed = 1; anyFailed = 1;
} else if (t->skipped) } else if (t->skipped)
// note that failed overrides skipped // note that failed overrides skipped
status = "SKIP"; status = "SKIP";
@ -334,28 +319,25 @@ static void testsetRun(struct testset *set, int indent, int *anyFailed)
} }
t++; t++;
} }
return anyFailed;
} }
int testingMain(const struct testingOptions *options) int testingMain(testingSet *set, const struct testingOptions *options)
{ {
int anyFailed; int anyFailed;
if (options != NULL) if (set == NULL)
opts = *options; set = &mainTests;
// TODO see if this should run if all tests are skipped // TODO see if this should run if all tests are skipped
if ((testsBefore.len + tests.len + testsAfter.len) == 0) { if (set->len == 0) {
fprintf(stderr, "warning: no tests to run\n"); $$TODOTODO fprintf(stderr, "warning: no tests to run\n");
// imitate Go here (TODO confirm this) // imitate Go here (TODO confirm this)
return 0; return 0;
} }
testsetSort(&testsBefore); return testingprivRun(set, 0);
testsetSort(&tests); }$$TODOTODO{
testsetSort(&testsAfter);
anyFailed = 0;
testsetRun(&testsBefore, 0, &anyFailed);
// TODO print a warning that we skip the next stages if a prior stage failed? // TODO print a warning that we skip the next stages if a prior stage failed?
if (!anyFailed) if (!anyFailed)
testsetRun(&tests, 0, &anyFailed); testsetRun(&tests, 0, &anyFailed);

View File

@ -16,37 +16,36 @@
#define testingprivCtorName(basename) testingprivCtor ## basename #define testingprivCtorName(basename) testingprivCtor ## basename
#define testingprivCtorPtrName(basename) testingprivCtorPtr ## basename #define testingprivCtorPtrName(basename) testingprivCtorPtr ## basename
#if defined(__GNUC__) #if defined(__GNUC__)
#define testingprivMkCtor(basename, regfunc) \ #define testingprivMkCtor(basename, pset) \
__attribute__((constructor)) static void testingprivCtorName(basename)(void) { regfunc(#basename, testingprivScaffoldName(basename), __FILE__, __LINE__); } __attribute__((constructor)) static void testingprivCtorName(basename)(void) { testingprivSetRegisterTest(pset, #basename, testingprivScaffoldName(basename), __FILE__, __LINE__); }
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
#define testingprivMkCtor(basename, regfunc) \ #define testingprivMkCtor(basename, pset) \
static int testingprivCtorName(basename)(void) { regfunc(#basename, testingprivScaffoldName(basename), __FILE__, __LINE__); return 0; } \ static int testingprivCtorName(basename)(void) { testingprivSetRegisterTest(pset, #basename, testingprivScaffoldName(basename), __FILE__, __LINE__); return 0; } \
__pragma(section(".CRT$XCU",read)) \ __pragma(section(".CRT$XCU",read)) \
__declspec(allocate(".CRT$XCU")) static int (*testingprivCtorPtrName(basename))(void) = testingprivCtorName(basename); __declspec(allocate(".CRT$XCU")) static int (*testingprivCtorPtrName(basename))(void) = testingprivCtorName(basename);
#else #else
#error unknown compiler for making constructors in C; cannot continue #error unknown compiler for making constructors in C; cannot continue
#endif #endif
#define testingprivMk(basename, argtype, argname, regfunc) \ #define testingprivMk(basename, argtype, argname, pset) \
void testingprivImplName(basename)(argtype *argname); \ void testingprivImplName(basename)(argtype *argname); \
testingprivMkScaffold(basename, argtype, argname) \ testingprivMkScaffold(basename, argtype, argname) \
testingprivMkCtor(basename, regfunc) \ testingprivMkCtor(basename, pset) \
void testingprivImplName(basename)(argtype *argname) void testingprivImplName(basename)(argtype *argname)
#define testingTest(Name) \ #define testingTest(Name) \
testingprivMk(Test ## Name, testingT, t, testingprivRegisterTest) testingprivMk(Test ## Name, testingT, t, NULL)
#define testingTestBefore(Name) \ #define testingTestInSet(Set, Name) \
testingprivMk(Test ## Name, testingT, t, testingprivRegisterTestBefore) testingprivMk(Test ## Name, testingT, t, &Set)
#define testingTestAfter(Name) \
testingprivMk(Test ## Name, testingT, t, testingprivRegisterTestAfter)
typedef struct testingSet testingSet;
typedef struct testingOptions testingOptions; typedef struct testingOptions testingOptions;
struct testingOptions { struct testingOptions {
int Verbose; int Verbose;
}; };
extern int testingMain(const struct testingOptions *options); extern int testingSetRun(testingSet *set, const struct testingOptions *options);
typedef struct testingT testingT; typedef struct testingT testingT;
#define testingTLogf(t, ...) \ #define testingTLogf(t, ...) \
@ -70,9 +69,7 @@ extern void testingTFailNow(testingT *t);
extern void testingTSkipNow(testingT *t); extern void testingTSkipNow(testingT *t);
extern void testingTDefer(testingT *t, void (*f)(testingT *t, void *data), void *data); extern void testingTDefer(testingT *t, void (*f)(testingT *t, void *data), void *data);
extern void testingprivRegisterTest(const char *, void (*)(testingT *), const char *, long); extern void testingprivSetRegisterTest(testingSet **pset, const char *, void (*)(testingT *), const char *, long);
extern void testingprivRegisterTestBefore(const char *, void (*)(testingT *), const char *, long);
extern void testingprivRegisterTestAfter(const char *, void (*)(testingT *), const char *, long);
// see https://stackoverflow.com/questions/32399191/va-args-expansion-using-msvc // see https://stackoverflow.com/questions/32399191/va-args-expansion-using-msvc
#define testingprivExpand(x) x #define testingprivExpand(x) x
#define testingprivTLogfThen(then, t, ...) ((testingprivTLogfFull(t, __FILE__, __LINE__, __VA_ARGS__)), (then(t))) #define testingprivTLogfThen(then, t, ...) ((testingprivTLogfFull(t, __FILE__, __LINE__, __VA_ARGS__)), (then(t)))