221 lines
5.5 KiB
C
221 lines
5.5 KiB
C
// 10 april 2019
|
|
#include <inttypes.h>
|
|
#include <string.h>
|
|
#include "lib/thread.h"
|
|
#include "test.h"
|
|
|
|
testingSet *beforeTests = NULL;
|
|
|
|
#define errInvalidOptions "options parameter to uiInit() must be NULL"
|
|
#define errAlreadyInitialized "libui already initialized"
|
|
|
|
testingTestInSet(beforeTests, Init)
|
|
{
|
|
uiInitError err;
|
|
int ret;
|
|
|
|
ret = uiInit(NULL, NULL);
|
|
if (ret != 0)
|
|
testingTErrorf(t, "uiInit() with NULL error succeeded with return value %d; expected failure", ret);
|
|
|
|
memset(&err, 0, sizeof (uiInitError));
|
|
|
|
err.Size = 2;
|
|
ret = uiInit(NULL, &err);
|
|
if (ret != 0)
|
|
testingTErrorf(t, "uiInit() with error with invalid size succeeded with return value %d; expected failure", ret);
|
|
|
|
err.Size = sizeof (uiInitError);
|
|
|
|
ret = uiInit(&err, &err);
|
|
if (ret != 0)
|
|
testingTErrorf(t, "uiInit() with non-NULL options succeeded with return value %d; expected failure", err);
|
|
if (strcmp(err.Message, errInvalidOptions) != 0)
|
|
diff(t, "uiInit() with non-NULL options returned bad error message", "%s",
|
|
err.Message, errInvalidOptions);
|
|
}
|
|
|
|
testingTest(InitAfterInitialized)
|
|
{
|
|
uiInitError err;
|
|
int ret;
|
|
|
|
memset(&err, 0, sizeof (uiInitError));
|
|
err.Size = sizeof (uiInitError);
|
|
ret = uiInit(NULL, &err);
|
|
if (ret != 0)
|
|
testingTErrorf(t, "uiInit() after a previous successful call succeeded with return value %d; expected failure", ret);
|
|
if (strcmp(err.Message, errAlreadyInitialized) != 0)
|
|
diff(t, "uiInit() after a previous successful call returned bad error message", "%s",
|
|
err.Message, errAlreadyInitialized);
|
|
}
|
|
|
|
struct testParams {
|
|
uint32_t flag;
|
|
timerSysError 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)
|
|
*/
|
|
static void queued(void *data)
|
|
{
|
|
struct testParams *p = (struct testParams *) data;
|
|
|
|
p->flag = 1;
|
|
uiQuit();
|
|
}
|
|
|
|
testingTest(QueueMain)
|
|
{
|
|
struct testParams p;
|
|
|
|
memset(&p, 0, sizeof (struct testParams));
|
|
p.flag = 0;
|
|
uiQueueMain(queued, &p);
|
|
timeout_uiMain(t, 5 * timerSecond);
|
|
if (p.flag != 1)
|
|
diff(t, "uiQueueMain() didn't set flag properly", "%d",
|
|
p.flag, 1);
|
|
}
|
|
|
|
#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);
|
|
}
|
|
|
|
// TODO somehow funnel the caller's file/line through
|
|
static void checkOrder(testingT *t, uint32_t flag)
|
|
{
|
|
int i;
|
|
|
|
if (flag == orders[0].result)
|
|
return;
|
|
for (i = 1; i < 6; i++)
|
|
if (flag == orders[i].result) {
|
|
diff2(t, "wrong order", "%" PRIu32 " (%s)",
|
|
flag, orders[i].order,
|
|
orders[0].result, orders[0].order);
|
|
return;
|
|
}
|
|
diff2(t, "wrong result", "%" PRIu32 " (%s)",
|
|
flag, "unknown order",
|
|
orders[0].result, orders[0].order);
|
|
}
|
|
|
|
testingTest(QueueMain_Sequence)
|
|
{
|
|
struct testParams p;
|
|
|
|
memset(&p, 0, sizeof (struct testParams));
|
|
queueOrder(&p);
|
|
timeout_uiMain(t, 5 * timerSecond);
|
|
checkOrder(t, p.flag);
|
|
}
|
|
|
|
static void queueThread(void *data)
|
|
{
|
|
struct testParams *p = (struct testParams *) data;
|
|
|
|
p->err = timerSleep(1250 * timerMillisecond);
|
|
uiQueueMain(queued, p);
|
|
}
|
|
|
|
testingTest(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)
|
|
testingTFatalf(t, "error creating thread: " threadSysErrorFmt, threadSysErrorFmtArg(err));
|
|
timeout_uiMain(t, 5 * timerSecond);
|
|
err = threadThreadWaitAndFree(thread);
|
|
if (err != 0)
|
|
testingTFatalf(t, "error waiting for thread to finish: " threadSysErrorFmt, threadSysErrorFmtArg(err));
|
|
if (p.err != 0)
|
|
testingTErrorf(t, "error sleeping in thread to ensure a high likelihood the uiQueueMain() is run after uiMain() starts: " timerSysErrorFmt, timerSysErrorFmtArg(p.err));
|
|
if (p.flag != 1)
|
|
diff(t, "uiQueueMain() didn't set flag properly", "%d",
|
|
p.flag, 1);
|
|
}
|
|
|
|
static void queueOrderThread(void *data)
|
|
{
|
|
struct testParams *p = (struct testParams *) data;
|
|
|
|
p->err = timerSleep(1250 * timerMillisecond);
|
|
queueOrder(p);
|
|
}
|
|
|
|
testingTest(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)
|
|
testingTFatalf(t, "error creating thread: " threadSysErrorFmt, threadSysErrorFmtArg(err));
|
|
timeout_uiMain(t, 5 * timerSecond);
|
|
err = threadThreadWaitAndFree(thread);
|
|
if (err != 0)
|
|
testingTFatalf(t, "error waiting for thread to finish: " threadSysErrorFmt, threadSysErrorFmtArg(err));
|
|
if (p.err != 0)
|
|
testingTErrorf(t, "error sleeping in thread to ensure a high likelihood the uiQueueMain() is run after uiMain() starts: " timerSysErrorFmt, timerSysErrorFmtArg(p.err));
|
|
checkOrder(t, 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
|