diff --git a/test/controls.c b/test/controls.c new file mode 100644 index 00000000..8511d113 --- /dev/null +++ b/test/controls.c @@ -0,0 +1,90 @@ +// 8 june 2019 +#include "test.h" + +struct counts { + unsigned int countInit; + unsigned int countFree; +}; + +struct testImplData { + struct counts *counts; +}; + +static struct counts failInit; +static void *testControlFailInit = &failInit; + +// TODO document that impl data is zero-initialized before this is called +// TODO we'll also have to eventually deal with the fact that NULL is not required to be 0... or at least confirm that +static bool testVtableInit(uiControl *c, void *implData, void *initData) +{ + struct testImplData *d = (struct testImplData *) implData; + struct counts *counts = (struct counts *) initData; + + if (initData == testControlFailInit) + return false; + if (initData == NULL) + return true; + if (d->counts == NULL) + d->counts = counts; + d->counts->countInit++; + if (d->counts->countInit > 2) + d->counts->countInit = 2; + return true; +} + +static void testVtableFree(uiControl *c, void *implData) +{ + struct testImplData *d = (struct testImplData *) implData; + + if (d->counts != NULL) { + d->counts->countFree++; + if (d->counts->countFree > 2) + d->counts->countFree = 2; + } +} + +static const uiControlVtable vtable = { + .Size = sizeof (uiControlVtable), + .Init = testVtableInit, + .Free = testVtableFree, +}; + +// TODO explicitly make/document 0 as always invalid +static uint32_t testControlType = 0; + +Test(ControlMethodsCalled) +{ + uiControl *c; + struct counts counts; + + testControlType = uiRegisterControlType("TestControl2", &vtable, testOSVtable(), sizeof (struct testImplData)); + memset(&counts, 0, sizeof (struct counts)); + + c = uiNewControl(testControlType, &counts); + switch (counts.countInit) { + case 0: + TestErrorf("Init() was not called"); + break; + case 1: + // do nothing; this is the expected case + break; + default: + TestErrorf("Init() called more than once"); + } + if (counts.countFree != 0) + TestErrorf("Free() called unexpectedly by uiNewControl()"); + + uiControlFree(c); + switch (counts.countFree) { + case 0: + TestErrorf("Free() was not called"); + break; + case 1: + // do nothing; this is the expected case + break; + default: + TestErrorf("Free() called more than once"); + } + if (counts.countInit != 1) + TestErrorf("Init() called unexpectedly by uiControlFree()"); +} diff --git a/zNEW_test/controls_darwin.m b/test/controls_darwin.m similarity index 100% rename from zNEW_test/controls_darwin.m rename to test/controls_darwin.m diff --git a/test/meson.build b/test/meson.build index 36bdf2e0..28d87f94 100644 --- a/test/meson.build +++ b/test/meson.build @@ -2,12 +2,18 @@ # Using files() is the cleanest way to ensure the python script below gets the right filenames regardless of how meson sandboxes the command it's running. libui_test_sources = files([ + 'controls.c', 'initmain.c', 'noinitwrongthread.c', ]) libui_allcalls_headers = files([ 'allcalls.h', ]) +if libui_OS == 'darwin' + libui_test_sources += files([ + 'controls_darwin.m', + ]) +endif libui_test_sources_without_cases = [ 'errors.c', diff --git a/test/test.h b/test/test.h index 075d3990..fd3c85b4 100644 --- a/test/test.h +++ b/test/test.h @@ -82,6 +82,9 @@ extern void *beginCheckProgrammerError(const char *want); extern void endCheckProgrammerErrorFull(const char *file, long line, void *context); #define endCheckProgrammerError(context) endCheckProgrammerErrorFull(__FILE__, __LINE__, context) +// controls.c +extern const uiControlOSVtable *testOSVtable(void); + #ifdef __cplusplus } #endif diff --git a/zNEW_test/test_darwin.h b/test/test_darwin.h similarity index 100% rename from zNEW_test/test_darwin.h rename to test/test_darwin.h diff --git a/zNEW_test/controls.c b/zNEW_events/test_controls.c similarity index 100% rename from zNEW_test/controls.c rename to zNEW_events/test_controls.c