libui/test/initmain.c

218 lines
5.4 KiB
C
Raw Normal View History

// 10 april 2019
#include "test.h"
#include "thread.h"
// TODO test the number of calls to queued functions made
#define errInvalidOptions "options parameter to uiInit() must be NULL"
#define errAlreadyInitialized "libui already initialized"
TestNoInit(Init)
{
uiInitError err;
if (uiInit(NULL, NULL))
TestErrorf("uiInit() with NULL error succeeded; expected failure");
memset(&err, 0, sizeof (uiInitError));
err.Size = 2;
if (uiInit(NULL, &err))
TestErrorf("uiInit() with error with invalid size succeeded; expected failure");
err.Size = sizeof (uiInitError);
if (uiInit(&err, &err))
TestErrorf("uiInit() with non-NULL options succeeded; expected failure");
if (strcmp(err.Message, errInvalidOptions) != 0)
TestErrorf("uiInit() with non-NULL options returned bad error message:" diff("%s"),
err.Message, errInvalidOptions);
}
Test(InitAfterInitialized)
{
uiInitError err;
memset(&err, 0, sizeof (uiInitError));
err.Size = sizeof (uiInitError);
if (uiInit(NULL, &err))
TestErrorf("uiInit() after a previous successful call succeeded; expected failure");
if (strcmp(err.Message, errAlreadyInitialized) != 0)
TestErrorf("uiInit() after a previous successful call returned bad error message:" diff("%s"),
err.Message, errAlreadyInitialized);
}
struct testParams {
uint32_t flag;
threadSysError err;
};
/*
TODO if I remove the uiQuit() from this test on Windows, I will occasionally get
=== RUN TestQueueMain_DifferentThread
../test/initmain.c:161: uiMain() timed out (5s)
--- FAIL: TestQueueMain_DifferentThread (4.9989539s)
TODO see if this is still relevant
*/
static void queued(void *data)
{
struct testParams *p = (struct testParams *) data;
p->flag = 1;
uiQuit();
}
Test(QueueMain)
{
struct testParams p;
memset(&p, 0, sizeof (struct testParams));
p.flag = 0;
uiQueueMain(queued, &p);
uiMain();
if (p.flag != 1)
TestErrorf("uiQueueMain() didn't set flag properly:" diff("%d"),
p.flag, 1);
}
// TODO there has to be a way to do this that absolutely will not possibly go in the wrong order... or produce a false positive
#define queueOp(name, expr) \
static void name(void *data) \
{ \
struct testParams *p = (struct testParams *) data; \
p->flag = p->flag expr; \
}
queueOp(sub2, - 2)
queueOp(div3, / 3)
queueOp(mul8, * 8)
static void done(void *data)
{
uiQuit();
}
static const struct {
uint32_t result;
const char *order;
} orders[] = {
{ 8, "sub2 -> div3 -> mul8" }, // the one we want
{ 13, "sub2 -> mul8 -> div3" },
{ 0, "div3 -> sub2 -> mul8" },
{ 14, "div3 -> mul8 -> sub2" },
{ 18, "mul8 -> sub2 -> div3" },
{ 16, "mul8 -> div3 -> sub2" },
};
static void queueOrder(struct testParams *p)
{
p->flag = 7;
uiQueueMain(sub2, p);
uiQueueMain(div3, p);
uiQueueMain(mul8, p);
uiQueueMain(done, NULL);
}
2020-01-23 20:36:50 -06:00
static void checkOrderFull(const char *file, long line, uint32_t flag)
{
int i;
if (flag == orders[0].result)
return;
for (i = 1; i < 6; i++)
if (flag == orders[i].result) {
TestErrorfFull(file, line, "wrong order:" diff("%" PRIu32 " (%s)"),
flag, orders[i].order,
orders[0].result, orders[0].order);
return;
}
TestErrorfFull(file, line, "wrong result:" diff("%" PRIu32 " (%s)"),
flag, "unknown order",
orders[0].result, orders[0].order);
}
2020-01-23 20:36:50 -06:00
#define checkOrder(flag) checkOrderFull(__FILE__, __LINE__, flag)
Test(QueueMain_Sequence)
{
struct testParams p;
memset(&p, 0, sizeof (struct testParams));
queueOrder(&p);
uiMain();
checkOrder(p.flag);
}
// TODO make a version of these where the thread is started by a queued function
static void queueThread(void *data)
{
struct testParams *p = (struct testParams *) data;
p->err = threadSleep(1250 * threadMillisecond);
uiQueueMain(queued, p);
}
Test(QueueMain_DifferentThread)
{
threadThread *thread;
threadSysError err;
struct testParams p;
memset(&p, 0, sizeof (struct testParams));
p.flag = 0;
err = threadNewThread(queueThread, &p, &thread);
if (err != 0)
TestFatalf("error creating thread: " threadSysErrorFmt, threadSysErrorFmtArg(err));
uiMain();
err = threadThreadWaitAndFree(thread);
if (err != 0)
TestFatalf("error waiting for thread to finish: " threadSysErrorFmt, threadSysErrorFmtArg(err));
if (p.err != 0)
TestErrorf("error sleeping in thread to ensure a high likelihood the uiQueueMain() is run after uiMain() starts: " threadSysErrorFmt, threadSysErrorFmtArg(p.err));
if (p.flag != 1)
TestErrorf("uiQueueMain() didn't set flag properly:" diff("%d"),
p.flag, 1);
}
static void queueOrderThread(void *data)
{
struct testParams *p = (struct testParams *) data;
p->err = threadSleep(1250 * threadMillisecond);
queueOrder(p);
}
Test(QueueMain_DifferentThreadSequence)
{
threadThread *thread;
threadSysError err;
struct testParams p;
memset(&p, 0, sizeof (struct testParams));
p.flag = 1; // make sure it's initialized just in case
err = threadNewThread(queueOrderThread, &p, &thread);
if (err != 0)
TestFatalf("error creating thread: " threadSysErrorFmt, threadSysErrorFmtArg(err));
uiMain();
err = threadThreadWaitAndFree(thread);
if (err != 0)
TestFatalf("error waiting for thread to finish: " threadSysErrorFmt, threadSysErrorFmtArg(err));
if (p.err != 0)
TestErrorf("error sleeping in thread to ensure a high likelihood the uiQueueMain() is run after uiMain() starts: " threadSysErrorFmt, threadSysErrorFmtArg(p.err));
checkOrder(p.flag);
}
#if 0
static void timer(void *data)
{
int *n = (int *) data;
// TODO return stop if n == 5, continue otherwise
*n++;
}
testingTest(Timer)
{
}
#endif