Restructured the controls tests to allow for more flexibility and implemented that on Windows. Now I can start building ad-hoc controls in tests.

This commit is contained in:
Pietro Gagliardi 2022-07-30 18:40:10 -04:00
parent 79d8eb534e
commit c241e8676a
4 changed files with 157 additions and 116 deletions

View File

@ -1,34 +1,72 @@
// 8 june 2019 // 8 june 2019
#include "test.h" #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; return true;
} }
static void vtableNopFree(uiControl *c, void *implData) static void nopFree(uiControl *c, void *implData)
{ {
// do nothing // do nothing
} }
static void vtableNopParentChanging(uiControl *c, void *implData, uiControl *oldParent) static void testControlVtableWithNopInitFree(uiControlVtable *vt)
{ {
// do nothing *vt = vtable;
} vt->Init = nopInit;
vt->Free = nopFree;
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;
} }
// 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 // 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; uiControl *c;
char *implData; char *implData;
testControlLoadNopVtable(&vt); testControlVtableWithNopInitFree(&vt);
type = uiRegisterControlType("TestControl", &vt, testOSVtable(), sizeof (memory)); type = uiRegisterControlType("TestControl", &vt, testControlOSVtable(), sizeof (memory));
c = uiNewControl(type, NULL); c = uiNewControl(type, NULL);
implData = (char *) uiControlImplData(c); implData = (char *) uiControlImplData(c);
memset(memory, 0, sizeof (memory)); memset(memory, 0, sizeof (memory));
@ -56,14 +94,32 @@ Test(ZeroSizeImplDataIsNULL)
uint32_t type; uint32_t type;
uiControl *c; uiControl *c;
testControlLoadNopVtable(&vt); testControlVtableWithNopInitFree(&vt);
type = uiRegisterControlType("TestControl", &vt, testOSVtable(), 0); type = uiRegisterControlType("TestControl", &vt, testControlOSVtable(), 0);
c = uiNewControl(type, NULL); c = uiNewControl(type, NULL);
if (uiControlImplData(c) != NULL) if (uiControlImplData(c) != NULL)
TestErrorf("control impl data is non-NULL despite being of size 0"); TestErrorf("control impl data is non-NULL despite being of size 0");
uiControlFree(c); 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 { struct counts {
unsigned int countInit; unsigned int countInit;
unsigned int countFree; unsigned int countFree;
@ -73,101 +129,65 @@ struct counts {
uiControl *newParent; uiControl *newParent;
}; };
struct testImplData { static bool countsInit(uiControl *c, void *implData, void *initData)
struct counts *counts;
};
static struct counts failInit;
static void *testControlFailInit = &failInit;
static bool testVtableInit(uiControl *c, void *implData, void *initData)
{ {
struct testImplData *d = (struct testImplData *) implData; struct counts *counts = (struct counts *) implData;
struct counts *counts = (struct counts *) initData;
if (initData == testControlFailInit) counts->countInit++;
return false; if (counts->countInit > 2)
if (initData == NULL) counts->countInit = 2;
return true;
if (d->counts == NULL)
d->counts = counts;
d->counts->countInit++;
if (d->counts->countInit > 2)
d->counts->countInit = 2;
return true; 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) { counts->countFree++;
d->counts->countFree++; if (counts->countFree > 2)
if (d->counts->countFree > 2) counts->countFree = 2;
d->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) { counts->oldParent = oldParent;
d->counts->oldParent = oldParent; counts->countParentChanging++;
d->counts->countParentChanging++; if (counts->countParentChanging > 3)
if (d->counts->countParentChanging > 3) counts->countParentChanging = 3;
d->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) { counts->newParent = newParent;
d->counts->newParent = newParent; counts->countParentChanged++;
d->counts->countParentChanged++; if (counts->countParentChanged > 3)
if (d->counts->countParentChanged > 3) counts->countParentChanged = 3;
d->counts->countParentChanged = 3;
}
} }
static const uiControlVtable countsVtable = {
static const uiControlVtable vtable = { .Init = countsInit,
.Size = sizeof (uiControlVtable), .Free = countsFree,
.Init = testVtableInit, .ParentChanging = countsParentChanging,
.Free = testVtableFree, .ParentChanged = countsParentChanged,
.ParentChanging = testVtableParentChanging,
.ParentChanged = testVtableParentChanged,
}; };
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 // TODO do this but for the OS-specific methods
Test(ControlMethodsCalled) Test(ControlMethodsCalled)
{ {
uiControl *c, *d; uiControl *c, *d;
struct testControlImplData initData;
struct counts counts; struct counts counts;
memset(&counts, 0, sizeof (struct 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) { switch (counts.countInit) {
case 0: case 0:
TestErrorf("Init() was not called"); TestErrorf("Init() was not called");
@ -458,14 +478,24 @@ Test(NewControlOfUnknownTypeIsProgrammerError)
endCheckProgrammerError(ctx); endCheckProgrammerError(ctx);
} }
static bool alwaysFailInit(uiControl *c, void *implData, void *initData)
{
return false;
}
Test(NewControlWithInvalidInitDataIsProgrammerError) Test(NewControlWithInvalidInitDataIsProgrammerError)
{ {
uint32_t ctrlType; uint32_t ctrlType;
struct testControlImplData initData;
uiControlVtable vtable;
void *ctx; void *ctx;
ctrlType = testControlType(); ctrlType = testControlType();
ctx = beginCheckProgrammerError("uiNewControl(): invalid init data for TestControl"); 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); endCheckProgrammerError(ctx);
} }

View File

@ -1,86 +1,90 @@
// 10 june 2019 // 10 june 2019
#include "test_windows.h" #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; 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; 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; return S_OK;
} }
static const uiControlOSVtable osVtable = { static const uiControlOSVtable osVtable = {
.Size = sizeof (uiControlOSVtable), .Size = sizeof (uiControlOSVtable),
.Handle = osVtableNopHandle, .Handle = testControlHandle,
.ParentHandleForChild = osVtableNopParentHandleForChild, .ParentHandleForChild = testControlParentHandleForChild,
.SetControlPos = osVtableNopSetControlPos, .SetControlPos = testControlSetControlPos,
}; };
const uiControlOSVtable *testOSVtable(void) const uiControlOSVtable *testControlOSVtable(void)
{ {
return &osVtable; return &osVtable;
} }
Test(WrongControlOSVtableSizeIsProgrammerError) Test(WrongControlOSVtableSizeIsProgrammerError)
{ {
uiControlVtable vtable;
uiControlOSVtable osvt; uiControlOSVtable osvt;
void *ctx; void *ctx;
testControlLoadNopVtable(&vtable);
ctx = beginCheckProgrammerError("uiRegisterControlType(): wrong size 1 for uiControlOSVtable"); ctx = beginCheckProgrammerError("uiRegisterControlType(): wrong size 1 for uiControlOSVtable");
memset(&osvt, 0, sizeof (uiControlOSVtable)); memset(&osvt, 0, sizeof (uiControlOSVtable));
osvt.Size = 1; osvt.Size = 1;
uiRegisterControlType("name", &vtable, &osvt, 0); uiRegisterControlType("name", testControlVtable(), &osvt, 0);
endCheckProgrammerError(ctx); endCheckProgrammerError(ctx);
} }
Test(ControlOSVtableWithMissingHandleMethodIsProgrammerError) Test(ControlOSVtableWithMissingHandleMethodIsProgrammerError)
{ {
uiControlVtable vtable;
uiControlOSVtable osvt; uiControlOSVtable osvt;
void *ctx; void *ctx;
testControlLoadNopVtable(&vtable);
ctx = beginCheckProgrammerError("uiRegisterControlType(): required uiControlOSVtable method Handle() missing for uiControl type name"); ctx = beginCheckProgrammerError("uiRegisterControlType(): required uiControlOSVtable method Handle() missing for uiControl type name");
osvt = osVtable; osvt = osVtable;
osvt.Handle = NULL; osvt.Handle = NULL;
uiRegisterControlType("name", &vtable, &osvt, 0); uiRegisterControlType("name", testControlVtable(), &osvt, 0);
endCheckProgrammerError(ctx); endCheckProgrammerError(ctx);
} }
Test(ControlOSVtableWithMissingParentHandleForChildMethodIsProgrammerError) Test(ControlOSVtableWithMissingParentHandleForChildMethodIsProgrammerError)
{ {
uiControlVtable vtable;
uiControlOSVtable osvt; uiControlOSVtable osvt;
void *ctx; void *ctx;
testControlLoadNopVtable(&vtable);
ctx = beginCheckProgrammerError("uiRegisterControlType(): required uiControlOSVtable method ParentHandleForChild() missing for uiControl type name"); ctx = beginCheckProgrammerError("uiRegisterControlType(): required uiControlOSVtable method ParentHandleForChild() missing for uiControl type name");
osvt = osVtable; osvt = osVtable;
osvt.ParentHandleForChild = NULL; osvt.ParentHandleForChild = NULL;
uiRegisterControlType("name", &vtable, &osvt, 0); uiRegisterControlType("name", testControlVtable(), &osvt, 0);
endCheckProgrammerError(ctx); endCheckProgrammerError(ctx);
} }
Test(ControlOSVtableWithMissingSetControlPosMethodIsProgrammerError) Test(ControlOSVtableWithMissingSetControlPosMethodIsProgrammerError)
{ {
uiControlVtable vtable;
uiControlOSVtable osvt; uiControlOSVtable osvt;
void *ctx; void *ctx;
testControlLoadNopVtable(&vtable);
ctx = beginCheckProgrammerError("uiRegisterControlType(): required uiControlOSVtable method SetControlPos() missing for uiControl type name"); ctx = beginCheckProgrammerError("uiRegisterControlType(): required uiControlOSVtable method SetControlPos() missing for uiControl type name");
osvt = osVtable; osvt = osVtable;
osvt.SetControlPos = NULL; osvt.SetControlPos = NULL;
uiRegisterControlType("name", &vtable, &osvt, 0); uiRegisterControlType("name", testControlVtable(), &osvt, 0);
endCheckProgrammerError(ctx); endCheckProgrammerError(ctx);
} }
@ -113,15 +117,14 @@ Test(SettingWindowsControlPosOfNullControlIsProgrammerError)
Test(SettingWindowsControlPosToNullRectIsProgrammerError) Test(SettingWindowsControlPosToNullRectIsProgrammerError)
{ {
#if 0
// TODO
uiControl *c; uiControl *c;
void *ctx; void *ctx;
c = uiNewControl(testControlType(), NULL);
ctx = beginCheckProgrammerError("uiWindowsControlSetControlPos(): invalid null pointer for RECT"); ctx = beginCheckProgrammerError("uiWindowsControlSetControlPos(): invalid null pointer for RECT");
uiWindowsControlSetControlPos(c, NULL); uiWindowsControlSetControlPos(c, NULL);
endCheckProgrammerError(ctx); endCheckProgrammerError(ctx);
#endif uiControlFree(c);
} }
// TODO uiWindowsSetControlHandlePos errors // TODO uiWindowsSetControlHandlePos errors

View File

@ -84,8 +84,14 @@ extern void endCheckProgrammerErrorFull(const char *file, long line, void *conte
#define endCheckProgrammerError(context) endCheckProgrammerErrorFull(__FILE__, __LINE__, context) #define endCheckProgrammerError(context) endCheckProgrammerErrorFull(__FILE__, __LINE__, context)
// controls.c // controls.c
extern void testControlLoadNopVtable(uiControlVtable *vtable); struct testControlImplData {
extern const uiControlOSVtable *testOSVtable(void); 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 // utf8.c
extern const char testUTF8Empty[]; extern const char testUTF8Empty[];

View File

@ -81,6 +81,8 @@ HRESULT uiWindowsControlSetControlPos(uiControl *c, const RECT *r)
HRESULT uiWindowsSetControlHandlePos(HWND hwnd, const RECT *r) HRESULT uiWindowsSetControlHandlePos(HWND hwnd, const RECT *r)
{ {
if (!uiprivCheckInitializedAndThread())
return E_FAIL;
// TODO // TODO
return S_OK; return S_OK;
} }