Added skipping and fatal to testing.h.
This commit is contained in:
parent
d0db6f9594
commit
b5570040b0
|
@ -29,12 +29,14 @@ extern "C" {
|
||||||
#define testingprivMkScaffold(name) \
|
#define testingprivMkScaffold(name) \
|
||||||
static inline void testingprivScaffold ## name(testingT *t) \
|
static inline void testingprivScaffold ## name(testingT *t) \
|
||||||
{ \
|
{ \
|
||||||
bool failedNow = false; \
|
bool failedNow = false, skippedNow = false; \
|
||||||
try { name(t); } \
|
try { name(t); } \
|
||||||
catch (testingprivFailNowException e) { failedNow = true; } \
|
catch (testingprivFailNowException e) { failedNow = true; } \
|
||||||
|
catch (testingprivSkipNowException e) { skippedNow = true; } \
|
||||||
/* TODO see if we should catch other exceptions too */ \
|
/* TODO see if we should catch other exceptions too */ \
|
||||||
/* don't call this in the catch block as it calls longjmp() */ \
|
/* don't call these in the catch blocks as they call longjmp() */ \
|
||||||
if (failedNow) testingprivTDoFailNow(t); \
|
if (failedNow) testingprivTDoFailNow(t); \
|
||||||
|
if (skippedNow) testingprivTDoSkipNow(t); \
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define testingprivMkScaffold(name) \
|
#define testingprivMkScaffold(name) \
|
||||||
|
@ -68,24 +70,34 @@ extern "C" {
|
||||||
extern int testingMain(void);
|
extern int testingMain(void);
|
||||||
|
|
||||||
typedef struct testingT testingT;
|
typedef struct testingT testingT;
|
||||||
#define testingTErrorf(t, ...) testingprivTErrorfFull(t, __FILE__, __LINE__, __VA_ARGS__)
|
#define testingTLogf(t, ...) (testingprivTLogfFull(t, __FILE__, __LINE__, __VA_ARGS__))
|
||||||
#define testingTErrorvf(t, format, ap) testingprivTErrorvfFull(t, __FILE__, __LINE__, format, ap)
|
#define testingTLogvf(t, format, ap) (testingprivTLogvfFull(t, __FILE__, __LINE__, format, ap))
|
||||||
|
#define testingTErrorf(t, ...) (testingprivTErrorfFull(t, __FILE__, __LINE__, __VA_ARGS__))
|
||||||
|
#define testingTErrorvf(t, format, ap) (testingprivTErrorvfFull(t, __FILE__, __LINE__, format, ap))
|
||||||
|
#define testingTFatalf(t, ...) ((testingprivTErrorfFull(t, __FILE__, __LINE__, __VA_ARGS__)), (testingTFailNow(t)))
|
||||||
|
#define testingTFatalvf(t, format, ap) ((testingprivTErrorvfFull(t, __FILE__, __LINE__, format, ap)), (testingTFailNow(t)))
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define testingTFailNow(t) (throw testingprivFailNowException())
|
#define testingTFailNow(t) (throw testingprivFailNowException())
|
||||||
|
#define testingTSkipNow(t) (throw testingprivSkipNowException())
|
||||||
#else
|
#else
|
||||||
#define testingTFailNow(t) testingprivTDoFailNow(t)
|
#define testingTFailNow(t) (testingprivTDoFailNow(t))
|
||||||
|
#define testingTSkipNow(t) (testingprivTDoSkipNow(t))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO should __LINE__ arguments use intmax_t or uintmax_t instead of int?
|
// TODO should __LINE__ arguments use intmax_t or uintmax_t instead of int?
|
||||||
extern void testingprivRegisterTest(const char *, void (*)(testingT *));
|
extern void testingprivRegisterTest(const char *, void (*)(testingT *));
|
||||||
|
extern void testingprivTLogfFull(testingT *, const char *, int, const char *, ...);
|
||||||
|
extern void testingprivTLogvfFull(testingT *, const char *, int, const char *, va_list);
|
||||||
extern void testingprivTErrorfFull(testingT *, const char *, int, const char *, ...);
|
extern void testingprivTErrorfFull(testingT *, const char *, int, const char *, ...);
|
||||||
extern void testingprivTErrorvfFull(testingT *, const char *, int, const char *, va_list);
|
extern void testingprivTErrorvfFull(testingT *, const char *, int, const char *, va_list);
|
||||||
extern void testingprivTDoFailNow(testingT *);
|
extern void testingprivTDoFailNow(testingT *);
|
||||||
|
extern void testingprivTDoSkipNow(testingT *);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
namespace {
|
namespace {
|
||||||
class testingprivFailNowException {};
|
class testingprivFailNowException {};
|
||||||
|
class testingprivSkipNowException {};
|
||||||
class testingprivRegisterTestClass {
|
class testingprivRegisterTestClass {
|
||||||
public:
|
public:
|
||||||
testingprivRegisterTestClass(const char *name, void (*f)(testingT *)) { testingprivRegisterTest(name, f); }
|
testingprivRegisterTestClass(const char *name, void (*f)(testingT *)) { testingprivRegisterTest(name, f); }
|
||||||
|
|
|
@ -10,7 +10,8 @@ struct testingT {
|
||||||
const char *name;
|
const char *name;
|
||||||
void (*f)(testingT *);
|
void (*f)(testingT *);
|
||||||
int failed;
|
int failed;
|
||||||
jmp_buf failNowBuf;
|
int skipped;
|
||||||
|
jmp_buf returnNowBuf;
|
||||||
testingT *next;
|
testingT *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ int testingMain(void)
|
||||||
int anyFailed;
|
int anyFailed;
|
||||||
const char *status;
|
const char *status;
|
||||||
|
|
||||||
|
// TODO see if this should run if all tests are skipped
|
||||||
if (tests == NULL) {
|
if (tests == NULL) {
|
||||||
fprintf(stderr, "warning: no tests to run\n");
|
fprintf(stderr, "warning: no tests to run\n");
|
||||||
// imitate Go here (TODO confirm this)
|
// imitate Go here (TODO confirm this)
|
||||||
|
@ -43,13 +45,15 @@ int testingMain(void)
|
||||||
anyFailed = 0;
|
anyFailed = 0;
|
||||||
for (t = tests; t != NULL; t = t->next) {
|
for (t = tests; t != NULL; t = t->next) {
|
||||||
printf("=== RUN %s\n", t->name);
|
printf("=== RUN %s\n", t->name);
|
||||||
if (setjmp(t->failNowBuf) == 0)
|
if (setjmp(t->returnNowBuf) == 0)
|
||||||
(*(t->f))(t);
|
(*(t->f))(t);
|
||||||
status = "PASS";
|
status = "PASS";
|
||||||
if (t->failed) {
|
if (t->failed) {
|
||||||
status = "FAIL";
|
status = "FAIL";
|
||||||
anyFailed = 1;
|
anyFailed = 1;
|
||||||
}
|
} else if (t->skipped)
|
||||||
|
// note that failed overrides skipped
|
||||||
|
status = "SKIP";
|
||||||
printf("--- %s: %s (%s)\n", status, t->name, "TODO");
|
printf("--- %s: %s (%s)\n", status, t->name, "TODO");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +65,16 @@ int testingMain(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void testingprivTDoLog(testingT *t, const char *file, int line, const char *format, va_list ap)
|
void testingprivTLogfFull(testingT *t, const char *file, int line, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
testingprivTLogvfFull(t, file, line, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testingprivTLogvfFull(testingT *t, const char *file, int line, const char *format, va_list ap)
|
||||||
{
|
{
|
||||||
// TODO extract filename from file
|
// TODO extract filename from file
|
||||||
printf("\t%s:%d: ", file, line);
|
printf("\t%s:%d: ", file, line);
|
||||||
|
@ -81,12 +94,18 @@ void testingprivTErrorfFull(testingT *t, const char *file, int line, const char
|
||||||
|
|
||||||
void testingprivTErrorvfFull(testingT *t, const char *file, int line, const char *format, va_list ap)
|
void testingprivTErrorvfFull(testingT *t, const char *file, int line, const char *format, va_list ap)
|
||||||
{
|
{
|
||||||
testingprivTDoLog(t, file, line, format, ap);
|
testingprivTLogvfFull(t, file, line, format, ap);
|
||||||
t->failed = 1;
|
t->failed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void testingprivTDoFailNow(testingT *t)
|
void testingprivTDoFailNow(testingT *t)
|
||||||
{
|
{
|
||||||
t->failed = 1;
|
t->failed = 1;
|
||||||
longjmp(t->failNowBuf, 1);
|
longjmp(t->returnNowBuf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testingprivTDoSkipNow(testingT *t)
|
||||||
|
{
|
||||||
|
t->skipped = 1;
|
||||||
|
longjmp(t->returnNowBuf, 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue