And added the multithreaded uiQueueMain() tests.
This commit is contained in:
parent
6c41fb712e
commit
df8eadb980
|
@ -63,7 +63,7 @@ testingTest(QueueMain)
|
|||
uiQueueMain(queued, &flag);
|
||||
timeout_uiMain(t, 5 * testingNsecPerSec, 0);
|
||||
if (flag != 1)
|
||||
testingTErrorf(t, "uiQueueMain didn't set flag properly: got %d, want 1", flag);
|
||||
testingTErrorf(t, "uiQueueMain() didn't set flag properly: got %d, want 1", flag);
|
||||
}
|
||||
|
||||
#define queueOp(name, expr) \
|
||||
|
@ -93,30 +93,77 @@ static const struct {
|
|||
{ 16, "mul8 -> div3 -> sub2" },
|
||||
};
|
||||
|
||||
static void queueOrder(uint32_t *flag)
|
||||
{
|
||||
*flag = 7;
|
||||
uiQueueMain(sub2, flag);
|
||||
uiQueueMain(div3, flag);
|
||||
uiQueueMain(mul8, flag);
|
||||
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) {
|
||||
testingTErrorf(t, "got %" PRIu32 " (%s), want %" PRIu32 " (%s)", flag, orders[i].order, orders[0].result, orders[0].order);
|
||||
return;
|
||||
}
|
||||
testingTErrorf(t, "got %" PRIu32 " (unknown order), want %" PRIu32 " (%s)", flag, orders[0].result, orders[0].order);
|
||||
}
|
||||
|
||||
testingTest(QueueMain_Sequence)
|
||||
{
|
||||
uint32_t flag;
|
||||
int i;
|
||||
|
||||
flag = 7;
|
||||
uiQueueMain(sub2, &flag);
|
||||
uiQueueMain(div3, &flag);
|
||||
uiQueueMain(mul8, &flag);
|
||||
uiQueueMain(done, NULL);
|
||||
queueOrder(&flag);
|
||||
timeout_uiMain(t, 5 * testingNsecPerSec, 0);
|
||||
if (flag != orders[0].result) {
|
||||
for (i = 1; i < 6; i++)
|
||||
if (flag == orders[i].result) {
|
||||
testingTErrorf(t, "got %" PRIu32 " (%s), want %" PRIu32 " (%s)", flag, orders[i].order, orders[0].result, orders[0].order);
|
||||
break;
|
||||
}
|
||||
if (i >= 6)
|
||||
testingTErrorf(t, "got %" PRIu32 " (unknown order), want %" PRIu32 " (%s)", flag, orders[0].result, orders[0].order);
|
||||
}
|
||||
checkOrder(t, flag);
|
||||
}
|
||||
|
||||
// TODO testingTest(QueueMain_DifferentThread)
|
||||
// TODO testingTest(QueueMain_DifferentThreadSequence)
|
||||
static void queueThread(void *data)
|
||||
{
|
||||
int *flag = (int *) data;
|
||||
|
||||
testingSleep(1250 * testingNsecPerMsec);
|
||||
uiQueueMain(queued, flag);
|
||||
}
|
||||
|
||||
testingTest(QueueMain_DifferentThread)
|
||||
{
|
||||
testingThread *thread;
|
||||
int flag = 0;
|
||||
|
||||
thread = testingNewThread(queueThread, &flag);
|
||||
timeout_uiMain(t, 5 * testingNsecPerSec, 0);
|
||||
testingThreadWaitAndFree(thread);
|
||||
if (flag != 1)
|
||||
testingTErrorf(t, "uiQueueMain() didn't set flag properly: got %d, want 1", flag);
|
||||
}
|
||||
|
||||
static void queueOrderThread(void *data)
|
||||
{
|
||||
uint32_t *flag = (uint32_t *) data;
|
||||
|
||||
testingSleep(1250 * testingNsecPerMsec);
|
||||
queueOrder(flag);
|
||||
}
|
||||
|
||||
testingTest(QueueMain_DifferentThreadSequence)
|
||||
{
|
||||
testingThread *thread;
|
||||
uint32_t flag;
|
||||
|
||||
thread = testingNewThread(queueOrderThread, &flag);
|
||||
timeout_uiMain(t, 5 * testingNsecPerSec, 0);
|
||||
testingThreadWaitAndFree(thread);
|
||||
checkOrder(t, flag);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void timer(void *data)
|
||||
|
|
|
@ -67,6 +67,7 @@ extern void testingTDefer(testingT *t, void (*f)(testingT *t, void *data), void
|
|||
typedef struct testingTimer testingTimer;
|
||||
|
||||
#define testingNsecPerUsec ((int64_t) 1000)
|
||||
#define testingNsecPerMsec ((int64_t) 1000000)
|
||||
#define testingNsecPerSec ((int64_t) 1000000000)
|
||||
|
||||
extern testingTimer *testingNewTimer(void);
|
||||
|
@ -81,6 +82,13 @@ extern void testingFreeNsecString(char *s);
|
|||
#define testingRunWithTimeout(t, timeout, f, data, comment, failNowOnError) \
|
||||
testingprivRunWithTimeout(t, __FILE__, __LINE__, timeout, f, data, comment, failNowOnError)
|
||||
|
||||
extern void testingSleep(int64_t nsec);
|
||||
|
||||
// TODO I don't like this threading model, but let's use it for now so I can continue working
|
||||
typedef struct testingThread testingThread;
|
||||
extern testingThread *testingNewThread(void (*f)(void *data), void *data);
|
||||
extern void testingThreadWaitAndFree(testingThread *t);
|
||||
|
||||
extern void testingprivRegisterTest(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);
|
||||
|
|
|
@ -259,3 +259,56 @@ out:
|
|||
if (failNowOnError)
|
||||
testingTFailNow(t);
|
||||
}
|
||||
|
||||
void testingSleep(int64_t nsec)
|
||||
{
|
||||
HANDLE timer;
|
||||
LARGE_INTEGER duration;
|
||||
|
||||
// TODO check errors, possibly falling back to Sleep() (although it has lower resolution)
|
||||
// TODO rename all the other durations that are timeout or timer to duration or nsec, both here and in the Unix/Darwin code
|
||||
duration.QuadPart = nsec / 100;
|
||||
duration.QuadPart = -duration.QuadPart;
|
||||
timer = CreateWaitableTimerW(NULL, TRUE, NULL);
|
||||
SetWaitableTimer(timer, &duration, 0, NULL, NULL, FALSE);
|
||||
WaitForSingleObject(timer, INFINITE);
|
||||
CloseHandle(timer);
|
||||
}
|
||||
|
||||
struct testingThread {
|
||||
uintptr_t handle;
|
||||
void (*f)(void *data);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static unsigned __stdcall threadThreadProc(void *data)
|
||||
{
|
||||
testingThread *t = (testingThread *) data;
|
||||
|
||||
(*(t->f))(t->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
testingThread *testingNewThread(void (*f)(void *data), void *data)
|
||||
{
|
||||
testingThread *t;
|
||||
|
||||
t = malloc(sizeof (testingThread));
|
||||
// TODO check error
|
||||
ZeroMemory(t, sizeof (testingThread));
|
||||
t->f = f;
|
||||
t->data = data;
|
||||
|
||||
t->handle = _beginthreadex(NULL, 0, threadThreadProc, t, 0, NULL);
|
||||
// TODO check error
|
||||
return t;
|
||||
}
|
||||
|
||||
void testingThreadWaitAndFree(testingThread *t)
|
||||
{
|
||||
// TODO check errors
|
||||
WaitForSingleObject((HANDLE) (t->handle), INFINITE);
|
||||
// TODO end check errors
|
||||
CloseHandle((HANDLE) (t->handle));
|
||||
free(t);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue