From c241e8676a31c47a7bedd84bd993e70395259e3d Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sat, 30 Jul 2022 18:40:10 -0400 Subject: [PATCH] Restructured the controls tests to allow for more flexibility and implemented that on Windows. Now I can start building ad-hoc controls in tests. --- test/controls.c | 214 +++++++++++++++++++++++----------------- test/controls_windows.c | 47 ++++----- test/test.h | 10 +- windows/controls.cpp | 2 + 4 files changed, 157 insertions(+), 116 deletions(-) diff --git a/test/controls.c b/test/controls.c index a3895f9a..b66aaec9 100644 --- a/test/controls.c +++ b/test/controls.c @@ -1,34 +1,72 @@ // 8 june 2019 #include "test.h" -static bool vtableNopInit(uiControl *c, void *implData, void *initData) +static bool testControlInit(uiControl *c, void *implData, void *initData) +{ + struct testControlImplData *ti = (struct testControlImplData *) implData; + struct testControlImplData *tinit = (struct testControlImplData *) initData; + + if (tinit == NULL) + return true; + *ti = *tinit; + if (ti->realVtable != NULL && ti->realVtable->Init != NULL) + return (*(ti->realVtable->Init))(c, ti->realImplData, initData); + return true; +} + +static void testControlFree(uiControl *c, void *implData) +{ + struct testControlImplData *ti = (struct testControlImplData *) implData; + + if (ti->realVtable != NULL && ti->realVtable->Free != NULL) + (*(ti->realVtable->Free))(c, ti->realImplData); +} + +static void testControlParentChanging(uiControl *c, void *implData, uiControl *oldParent) +{ + struct testControlImplData *ti = (struct testControlImplData *) implData; + + if (ti->realVtable != NULL && ti->realVtable->ParentChanging != NULL) + (*(ti->realVtable->ParentChanging))(c, ti->realImplData, oldParent); +} + +static void testControlParentChanged(uiControl *c, void *implData, uiControl *newParent) +{ + struct testControlImplData *ti = (struct testControlImplData *) implData; + + if (ti->realVtable != NULL && ti->realVtable->ParentChanged != NULL) + (*(ti->realVtable->ParentChanged))(c, ti->realImplData, newParent); +} + +static const uiControlVtable vtable = { + .Size = sizeof (uiControlVtable), + .Init = testControlInit, + .Free = testControlFree, + .ParentChanging = testControlParentChanging, + .ParentChanged = testControlParentChanged, +}; + +const uiControlVtable *testControlVtable(void) +{ + return &vtable; +} + +// the following are kludges for just these first two tests +static bool nopInit(uiControl *c, void *implData, void *initData) { return true; } -static void vtableNopFree(uiControl *c, void *implData) +static void nopFree(uiControl *c, void *implData) { // do nothing } -static void vtableNopParentChanging(uiControl *c, void *implData, uiControl *oldParent) +static void testControlVtableWithNopInitFree(uiControlVtable *vt) { - // do nothing -} - -static void vtableNopParentChanged(uiControl *c, void *implData, uiControl *newParent) -{ - // do nothing -} - -void testControlLoadNopVtable(uiControlVtable *vtable) -{ - memset(vtable, 0, sizeof (uiControlVtable)); - vtable->Size = sizeof (uiControlVtable); - vtable->Init = vtableNopInit; - vtable->Free = vtableNopFree; - vtable->ParentChanging = vtableNopParentChanging; - vtable->ParentChanged = vtableNopParentChanged; + *vt = vtable; + vt->Init = nopInit; + vt->Free = nopFree; } // TODO we'll have to eventually find out for real if memset(0) is sufficient to set pointers to NULL or not; C99 doesn't seem to say @@ -40,8 +78,8 @@ Test(ControlImplDataIsClearedOnNewControl) uiControl *c; char *implData; - testControlLoadNopVtable(&vt); - type = uiRegisterControlType("TestControl", &vt, testOSVtable(), sizeof (memory)); + testControlVtableWithNopInitFree(&vt); + type = uiRegisterControlType("TestControl", &vt, testControlOSVtable(), sizeof (memory)); c = uiNewControl(type, NULL); implData = (char *) uiControlImplData(c); memset(memory, 0, sizeof (memory)); @@ -56,14 +94,32 @@ Test(ZeroSizeImplDataIsNULL) uint32_t type; uiControl *c; - testControlLoadNopVtable(&vt); - type = uiRegisterControlType("TestControl", &vt, testOSVtable(), 0); + testControlVtableWithNopInitFree(&vt); + type = uiRegisterControlType("TestControl", &vt, testControlOSVtable(), 0); c = uiNewControl(type, NULL); if (uiControlImplData(c) != NULL) TestErrorf("control impl data is non-NULL despite being of size 0"); uiControlFree(c); } +uint32_t testControlType(void) +{ + static uint32_t type = 0; + + if (type == 0) + type = uiRegisterControlType("TestControl", testControlVtable(), testControlOSVtable(), sizeof (struct testControlImplData)); + return type; +} + +static uint32_t testControlType2(void) +{ + static uint32_t type = 0; + + if (type == 0) + type = uiRegisterControlType("TestControl2", testControlVtable(), testControlOSVtable(), sizeof (struct testControlImplData)); + return type; +} + struct counts { unsigned int countInit; unsigned int countFree; @@ -73,101 +129,65 @@ struct counts { uiControl *newParent; }; -struct testImplData { - struct counts *counts; -}; - -static struct counts failInit; -static void *testControlFailInit = &failInit; - -static bool testVtableInit(uiControl *c, void *implData, void *initData) +static bool countsInit(uiControl *c, void *implData, void *initData) { - struct testImplData *d = (struct testImplData *) implData; - struct counts *counts = (struct counts *) initData; + struct counts *counts = (struct counts *) implData; - 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; + counts->countInit++; + if (counts->countInit > 2) + counts->countInit = 2; return true; } -static void testVtableFree(uiControl *c, void *implData) +static void countsFree(uiControl *c, void *implData) { - struct testImplData *d = (struct testImplData *) implData; + struct counts *counts = (struct counts *) implData; - if (d->counts != NULL) { - d->counts->countFree++; - if (d->counts->countFree > 2) - d->counts->countFree = 2; - } + counts->countFree++; + if (counts->countFree > 2) + counts->countFree = 2; } -static void testVtableParentChanging(uiControl *c, void *implData, uiControl *oldParent) +static void countsParentChanging(uiControl *c, void *implData, uiControl *oldParent) { - struct testImplData *d = (struct testImplData *) implData; + struct counts *counts = (struct counts *) implData; - if (d->counts != NULL) { - d->counts->oldParent = oldParent; - d->counts->countParentChanging++; - if (d->counts->countParentChanging > 3) - d->counts->countParentChanging = 3; - } + counts->oldParent = oldParent; + counts->countParentChanging++; + if (counts->countParentChanging > 3) + counts->countParentChanging = 3; } -static void testVtableParentChanged(uiControl *c, void *implData, uiControl *newParent) +static void countsParentChanged(uiControl *c, void *implData, uiControl *newParent) { - struct testImplData *d = (struct testImplData *) implData; + struct counts *counts = (struct counts *) implData; - if (d->counts != NULL) { - d->counts->newParent = newParent; - d->counts->countParentChanged++; - if (d->counts->countParentChanged > 3) - d->counts->countParentChanged = 3; - } + counts->newParent = newParent; + counts->countParentChanged++; + if (counts->countParentChanged > 3) + counts->countParentChanged = 3; } - -static const uiControlVtable vtable = { - .Size = sizeof (uiControlVtable), - .Init = testVtableInit, - .Free = testVtableFree, - .ParentChanging = testVtableParentChanging, - .ParentChanged = testVtableParentChanged, +static const uiControlVtable countsVtable = { + .Init = countsInit, + .Free = countsFree, + .ParentChanging = countsParentChanging, + .ParentChanged = countsParentChanged, }; -static uint32_t testControlType(void) -{ - static uint32_t type = 0; - - if (type == 0) - type = uiRegisterControlType("TestControl", &vtable, testOSVtable(), sizeof (struct testImplData)); - return type; -} - -static uint32_t testControlType2(void) -{ - static uint32_t type = 0; - - if (type == 0) - type = uiRegisterControlType("TestControl2", &vtable, testOSVtable(), sizeof (struct testImplData)); - return type; -} - // TODO do this but for the OS-specific methods Test(ControlMethodsCalled) { uiControl *c, *d; + struct testControlImplData initData; struct counts counts; memset(&counts, 0, sizeof (struct counts)); - c = uiNewControl(testControlType(), &counts); + initData.realVtable = &countsVtable; + initData.realOSVtable = NULL; + initData.realImplData = &counts; + c = uiNewControl(testControlType(), &initData); switch (counts.countInit) { case 0: TestErrorf("Init() was not called"); @@ -458,14 +478,24 @@ Test(NewControlOfUnknownTypeIsProgrammerError) endCheckProgrammerError(ctx); } +static bool alwaysFailInit(uiControl *c, void *implData, void *initData) +{ + return false; +} + Test(NewControlWithInvalidInitDataIsProgrammerError) { uint32_t ctrlType; + struct testControlImplData initData; + uiControlVtable vtable; void *ctx; ctrlType = testControlType(); ctx = beginCheckProgrammerError("uiNewControl(): invalid init data for TestControl"); - uiNewControl(ctrlType, testControlFailInit); + memset(&vtable, 0, sizeof (uiControlVtable)); + vtable.Init = alwaysFailInit; + initData.realVtable = &vtable; + uiNewControl(ctrlType, &initData); endCheckProgrammerError(ctx); } diff --git a/test/controls_windows.c b/test/controls_windows.c index 4a0390a1..d2283527 100644 --- a/test/controls_windows.c +++ b/test/controls_windows.c @@ -1,86 +1,90 @@ // 10 june 2019 #include "test_windows.h" -static HWND osVtableNopHandle(uiControl *c, void *implData) +static HWND testControlHandle(uiControl *c, void *implData) { + struct testControlImplData *ti = (struct testControlImplData *) implData; + + if (ti->realOSVtable != NULL && ti->realOSVtable->Handle != NULL) + return (*(ti->realOSVtable->Handle))(c, ti->realImplData); return NULL; } -static HWND osVtableNopParentHandleForChild(uiControl *c, void *implData, uiControl *child) +static HWND testControlParentHandleForChild(uiControl *c, void *implData, uiControl *child) { + struct testControlImplData *ti = (struct testControlImplData *) implData; + + if (ti->realOSVtable != NULL && ti->realOSVtable->ParentHandleForChild != NULL) + return (*(ti->realOSVtable->ParentHandleForChild))(c, ti->realImplData, child); return NULL; } -HRESULT osVtableNopSetControlPos(uiControl *c, void *implData, const RECT *r) +static HRESULT testControlSetControlPos(uiControl *c, void *implData, const RECT *r) { + struct testControlImplData *ti = (struct testControlImplData *) implData; + + if (ti->realOSVtable != NULL && ti->realOSVtable->SetControlPos != NULL) + return (*(ti->realOSVtable->SetControlPos))(c, ti->realImplData, r); return S_OK; } static const uiControlOSVtable osVtable = { .Size = sizeof (uiControlOSVtable), - .Handle = osVtableNopHandle, - .ParentHandleForChild = osVtableNopParentHandleForChild, - .SetControlPos = osVtableNopSetControlPos, + .Handle = testControlHandle, + .ParentHandleForChild = testControlParentHandleForChild, + .SetControlPos = testControlSetControlPos, }; -const uiControlOSVtable *testOSVtable(void) +const uiControlOSVtable *testControlOSVtable(void) { return &osVtable; } Test(WrongControlOSVtableSizeIsProgrammerError) { - uiControlVtable vtable; uiControlOSVtable osvt; void *ctx; - testControlLoadNopVtable(&vtable); ctx = beginCheckProgrammerError("uiRegisterControlType(): wrong size 1 for uiControlOSVtable"); memset(&osvt, 0, sizeof (uiControlOSVtable)); osvt.Size = 1; - uiRegisterControlType("name", &vtable, &osvt, 0); + uiRegisterControlType("name", testControlVtable(), &osvt, 0); endCheckProgrammerError(ctx); } Test(ControlOSVtableWithMissingHandleMethodIsProgrammerError) { - uiControlVtable vtable; uiControlOSVtable osvt; void *ctx; - testControlLoadNopVtable(&vtable); ctx = beginCheckProgrammerError("uiRegisterControlType(): required uiControlOSVtable method Handle() missing for uiControl type name"); osvt = osVtable; osvt.Handle = NULL; - uiRegisterControlType("name", &vtable, &osvt, 0); + uiRegisterControlType("name", testControlVtable(), &osvt, 0); endCheckProgrammerError(ctx); } Test(ControlOSVtableWithMissingParentHandleForChildMethodIsProgrammerError) { - uiControlVtable vtable; uiControlOSVtable osvt; void *ctx; - testControlLoadNopVtable(&vtable); ctx = beginCheckProgrammerError("uiRegisterControlType(): required uiControlOSVtable method ParentHandleForChild() missing for uiControl type name"); osvt = osVtable; osvt.ParentHandleForChild = NULL; - uiRegisterControlType("name", &vtable, &osvt, 0); + uiRegisterControlType("name", testControlVtable(), &osvt, 0); endCheckProgrammerError(ctx); } Test(ControlOSVtableWithMissingSetControlPosMethodIsProgrammerError) { - uiControlVtable vtable; uiControlOSVtable osvt; void *ctx; - testControlLoadNopVtable(&vtable); ctx = beginCheckProgrammerError("uiRegisterControlType(): required uiControlOSVtable method SetControlPos() missing for uiControl type name"); osvt = osVtable; osvt.SetControlPos = NULL; - uiRegisterControlType("name", &vtable, &osvt, 0); + uiRegisterControlType("name", testControlVtable(), &osvt, 0); endCheckProgrammerError(ctx); } @@ -113,15 +117,14 @@ Test(SettingWindowsControlPosOfNullControlIsProgrammerError) Test(SettingWindowsControlPosToNullRectIsProgrammerError) { -#if 0 - // TODO uiControl *c; void *ctx; + c = uiNewControl(testControlType(), NULL); ctx = beginCheckProgrammerError("uiWindowsControlSetControlPos(): invalid null pointer for RECT"); uiWindowsControlSetControlPos(c, NULL); endCheckProgrammerError(ctx); -#endif + uiControlFree(c); } // TODO uiWindowsSetControlHandlePos errors diff --git a/test/test.h b/test/test.h index 8e54daae..cf78f7fe 100644 --- a/test/test.h +++ b/test/test.h @@ -84,8 +84,14 @@ extern void endCheckProgrammerErrorFull(const char *file, long line, void *conte #define endCheckProgrammerError(context) endCheckProgrammerErrorFull(__FILE__, __LINE__, context) // controls.c -extern void testControlLoadNopVtable(uiControlVtable *vtable); -extern const uiControlOSVtable *testOSVtable(void); +struct testControlImplData { + const uiControlVtable *realVtable; + const uiControlOSVtable *realOSVtable; + void *realImplData; +}; +extern const uiControlVtable *testControlVtable(void); +extern const uiControlOSVtable *testControlOSVtable(void); +extern uint32_t testControlType(void); // utf8.c extern const char testUTF8Empty[]; diff --git a/windows/controls.cpp b/windows/controls.cpp index 4db51bfc..85d991de 100644 --- a/windows/controls.cpp +++ b/windows/controls.cpp @@ -81,6 +81,8 @@ HRESULT uiWindowsControlSetControlPos(uiControl *c, const RECT *r) HRESULT uiWindowsSetControlHandlePos(HWND hwnd, const RECT *r) { + if (!uiprivCheckInitializedAndThread()) + return E_FAIL; // TODO return S_OK; }