And actually did split the new error testing code into its own file. Next is changing both events.c and controls.c to use it (and yes, that means we can finally start continuing work on controls.c).

This commit is contained in:
Pietro Gagliardi 2019-06-09 22:45:44 -04:00
parent b34a427077
commit afbf5f2d59
6 changed files with 85 additions and 103 deletions

75
test/errors.c Normal file
View File

@ -0,0 +1,75 @@
// 28 may 2019
#include "test.h"
struct checkProgrammerErrorParams {
const char *file;
long line;
void (*f)(void *data);
void *data;
bool inThread;
bool caught;
char *msgGot;
const char *msgWant;
};
static void handleProgrammerError(const char *msg, void *data)
{
struct checkProgrammerErrorParams *p = (struct checkProgrammerErrorParams *) data;
p->caught = true;
if (strcmp(msg, p->msgWant) != 0)
p->msgGot = testingUtilStrdup(msg);
}
static void deferResetProgrammerError(testingT *t, void *data)
{
uiprivTestHookReportProgrammerError(NULL, NULL);
}
static void checkProgrammerErrorThreadProc(void *data)
{
struct checkProgrammerErrorParams *p = (struct checkProgrammerErrorParams *) data;
(*(p->f))(p->data);
}
static void checkProgrammerErrorSubtestImpl(testingT *t, void *data)
{
struct checkProgrammerErrorParams *p = (struct checkProgrammerErrorParams *) data;
uiprivTestHookReportProgrammerError(handleProgrammerError, p);
testingTDefer(t, deferResetProgrammerError, NULL);
if (p->inThread) {
threadThread *thread;
threadSysError err;
err = threadNewThread(checkProgrammerErrorThreadProc, p, &thread);
if (err != 0)
testingTFatalfFull(t, p->file, p->line, "error creating thread: " threadSysErrorFmt, threadSysErrorFmtArg(err));
err = threadThreadWaitAndFree(thread);
if (err != 0)
testingTFatalfFull(t, p->file, p->line, "error waiting for thread to finish: " threadSysErrorFmt, threadSysErrorFmtArg(err));
} else
(*(p->f))(p->data);
if (!p->caught)
testingTErrorfFull(t, p->file, p->line, "did not throw a programmer error; should have");
if (p->msgGot != NULL) {
testingTErrorfFull(t, p->file, p->line, "message doesn't match expected string:" diff("%s"),
p->msgGot, p->msgWant);
testingUtilFreeStrdup(p->msgGot);
}
}
void checkProgrammerErrorFull(testingT *t, const char *file, long line, const char *name, void (*f)(void *data), void *data, const char *msgWant, bool inThread)
{
struct checkProgrammerErrorParams p;
memset(&p, 0, sizeof (struct checkProgrammerErrorParams));
p.file = file;
p.line = line;
p.f = f;
p.data = data;
p.inThread = inThread;
p.msgWant = msgWant;
testingTRun(t, name, checkProgrammerErrorSubtestImpl, &p);
}

View File

@ -916,8 +916,9 @@ testingTest(EventInvalidateSender)
runArgsSubtests(t, &p);
}
#if 0
TODOTODO
// TODO table-ize these
// TODO deduplicate this from the one in noinitwrongthread.c?
static void testWhileFiring(void *sender, void *args, void *data)
{
@ -1054,3 +1055,5 @@ testingTest(EventErrors)
"uiEventFree(): can't free event that still has handlers registered");
uiEventFire(firingEvent, NULL, firingEvent);
}
#endif

View File

@ -6,16 +6,6 @@ void timeoutMain(void *data)
uiMain();
}
void catchProgrammerError(const char *msg, void *data)
{
struct errorParams *errorParams = (struct errorParams *) data;
errorParams->caught = true;
if (strcmp(msg, errorParams->msgWant) != 0)
testingTErrorfFull(errorParams->t, errorParams->file, errorParams->line, "%s: message doesn't match expected string:" diff("%s"),
errorParams->exprstr, msg, errorParams->msgWant);
}
static void runSetORingResults(testingSet *set, const struct testingOptions *options, bool *anyRun, bool *anyFailed)
{
bool ar, af;

View File

@ -2,6 +2,7 @@
libui_test_sources = [
'controls.c',
'errors.c',
'events.c',
'initmain.c',
'main.c',

View File

@ -1,82 +1,6 @@
// 28 may 2019
#include "test.h"
struct checkProgrammerErrorParams {
const char *file;
long line;
void (*f)(void *data);
void *data;
bool inThread;
bool caught;
char *msgGot;
const char *msgWant;
};
static void handleProgrammerError(const char *msg, void *data)
{
struct checkProgrammerErrorParams *p = (struct checkProgrammerErrorParams *) data;
p->caught = true;
if (strcmp(msg, p->msgWant) != 0)
p->msgGot = testingUtilStrdup(msg);
}
static void deferResetProgrammerError(testingT *t, void *data)
{
uiprivTestHookReportProgrammerError(NULL, NULL);
}
static void checkProgrammerErrorThreadProc(void *data)
{
struct checkProgrammerErrorParams *p = (struct checkProgrammerErrorParams *) data;
(*(p->f))(p->data);
}
static void checkProgrammerErrorSubtestImpl(testingT *t, void *data)
{
struct checkProgrammerErrorParams *p = (struct checkProgrammerErrorParams *) data;
uiprivTestHookReportProgrammerError(handleProgrammerError, p);
testingTDefer(t, deferResetProgrammerError, NULL);
if (p->inThread) {
threadThread *thread;
threadSysError err;
err = threadNewThread(checkProgrammerErrorThreadProc, p, &thread);
if (err != 0)
testingTFatalfFull(t, p->file, p->line, "error creating thread: " threadSysErrorFmt, threadSysErrorFmtArg(err));
err = threadThreadWaitAndFree(thread);
if (err != 0)
testingTFatalfFull(t, p->file, p->line, "error waiting for thread to finish: " threadSysErrorFmt, threadSysErrorFmtArg(err));
} else
(*(p->f))(p->data);
if (!p->caught)
testingTErrorfFull(t, p->file, p->line, "did not throw a programmer error; should have");
if (p->msgGot != NULL) {
testingTErrorfFull(t, p->file, p->line, "message doesn't match expected string:" diff("%s"),
p->msgGot, p->msgWant);
testingUtilFreeStrdup(p->msgGot);
}
}
void checkProgrammerErrorFull(testingT *t, const char *file, long line, const char *name, void (*f)(void *data), void *data, const char *msgWant, bool inThread)
{
struct checkProgrammerErrorParams p;
memset(&p, 0, sizeof (struct checkProgrammerErrorParams));
p.file = file;
p.line = line;
p.f = f;
p.data = data;
p.inThread = inThread;
p.msgWant = msgWant;
testingTRun(t, name, checkProgrammerErrorSubtestImpl, &p);
}
#define checkProgrammerError(t, name, f, data, msgWant) checkProgrammerErrorFull(t, __FILE__, __LINE__, name, f, data, msgWant, false)
#define checkProgrammerErrorInThread(t, name, f, data, msgWant) checkProgrammerErrorFull(t, __FILE__, __LINE__, name, f, data, msgWant, true)
#define allcallsCase(f, ...) \
void doCase ## f(void *data) \
{ \

View File

@ -34,22 +34,11 @@ struct errorParams {
const char *msgWant;
bool caught;
};
extern void catchProgrammerError(const char *msg, void *data);
#define testProgrammerError(tt, expr, mw) { \
struct errorParams errorParams; \
testingTLogf(t, "*** %s", #expr); \
uiprivTestHookReportProgrammerError(catchProgrammerError, &errorParams); \
errorParams.t = tt; \
errorParams.file = __FILE__; \
errorParams.line = __LINE__; \
errorParams.exprstr = #expr; \
errorParams.msgWant = mw; \
errorParams.caught = false; \
expr; \
if (!errorParams.caught) \
testingTErrorfFull(t, errorParams.file, errorParams.line, "%s did not throw a programmer error; should have", #expr); \
uiprivTestHookReportProgrammerError(NULL, NULL); \
}
// init.c
extern testingSet *beforeTests;
// errors.c
extern void checkProgrammerErrorFull(testingT *t, const char *file, long line, const char *name, void (*f)(void *data), void *data, const char *msgWant, bool inThread);
#define checkProgrammerError(t, name, f, data, msgWant) checkProgrammerErrorFull(t, __FILE__, __LINE__, name, f, data, msgWant, false)
#define checkProgrammerErrorInThread(t, name, f, data, msgWant) checkProgrammerErrorFull(t, __FILE__, __LINE__, name, f, data, msgWant, true)