Filled in the missing uiControl tests and demoted the non-uiControl requirements to TODOs as I'm not sure how sensible those requirements are. I'll probably bring them back shortly =P Now to implement cycle checking.

This commit is contained in:
Pietro Gagliardi 2020-05-11 10:32:17 -04:00
parent dfd045b3cc
commit 1cf4a3df21
2 changed files with 82 additions and 2 deletions

View File

@ -69,6 +69,8 @@ This function is intended to be used to implement a macro that converts an arbit
#define uiButton(c) ((uiButton *) uiCheckControlType((c), uiButtonType())) #define uiButton(c) ((uiButton *) uiCheckControlType((c), uiButtonType()))
``` ```
(TODO document passing uiControlType() to this, or even make doing so unnecessary)
### `uiNewControl()` ### `uiNewControl()`
```c ```c
@ -109,7 +111,7 @@ This function is used by the implementation of a container control to actually e
This function can only be used to set the parent of an unparented control or to remove its parent. It may not be used to change the parent of an already parented control. It is a programmer error to set the parent of a control that already has a parent to something other than `NULL` (even if to the same parent), or to set the parent of a control with no parent to `NULL`. (The idea here is to reinforce the concept of container implementations being responsible for setting their children properly, not the user.) This function can only be used to set the parent of an unparented control or to remove its parent. It may not be used to change the parent of an already parented control. It is a programmer error to set the parent of a control that already has a parent to something other than `NULL` (even if to the same parent), or to set the parent of a control with no parent to `NULL`. (The idea here is to reinforce the concept of container implementations being responsible for setting their children properly, not the user.)
It is a programmer error to pass `NULL` or a non-control for `c`. It is a programmer error to pass `NULL` for `c`. (TODO non-uiControl for either c or parent?)
It is a programmer error to introduce a cycle when changing the parent of a control. By extension, it is a programmer error to make a control its own parent. It is a programmer error to introduce a cycle when changing the parent of a control. By extension, it is a programmer error to make a control its own parent.
@ -130,4 +132,4 @@ void *uiControlImplData(uiControl *c);
This function is meant to be used by control implementations only. There is in general no guarantee as to the size or format of this pointer. Normal users should not call `uiControlImplData()`. This function is meant to be used by control implementations only. There is in general no guarantee as to the size or format of this pointer. Normal users should not call `uiControlImplData()`.
It is a programmer error to pass `NULL` or a non-`uiControl` for `c`. It is a programmer error to pass `NULL` for `c`. (TODO non-uiControl?)

View File

@ -21,6 +21,7 @@ Test(ControlImplDataIsClearedOnNewControl)
uiControl *c; uiControl *c;
char *implData; char *implData;
memset(&vt, 0, sizeof (uiControlVtable));
vt.Size = sizeof (uiControlVtable); vt.Size = sizeof (uiControlVtable);
vt.Init = vtableNopInit; vt.Init = vtableNopInit;
vt.Free = vtableNopFree; vt.Free = vtableNopFree;
@ -33,6 +34,23 @@ Test(ControlImplDataIsClearedOnNewControl)
uiControlFree(c); uiControlFree(c);
} }
Test(ZeroSizeImplDataIsNULL)
{
uiControlVtable vt;
uint32_t type;
uiControl *c;
memset(&vt, 0, sizeof (uiControlVtable));
vt.Size = sizeof (uiControlVtable);
vt.Init = vtableNopInit;
vt.Free = vtableNopFree;
type = uiRegisterControlType("TestControl", &vt, testOSVtable(), 0);
c = uiNewControl(type, NULL);
if (uiControlImplData(c) != NULL)
TestErrorf("control impl data is non-NULL despite being of size 0");
uiControlFree(c);
}
struct counts { struct counts {
unsigned int countInit; unsigned int countInit;
unsigned int countFree; unsigned int countFree;
@ -399,6 +417,66 @@ Test(ReparentingAlreadyParentedControlToSameParentIsProgrammerError)
endCheckProgrammerError(ctx); endCheckProgrammerError(ctx);
} }
Test(ControlParentCyclesDisallowed_TwoControls)
{
uiControl *c, *d;
void *ctx;
ctx = beginCheckProgrammerError("TODO");
c = uiNewControl(testControlType(), NULL);
d = uiNewControl(testControlType(), NULL);
// this should fail
uiControlSetParent(c, d);
uiControlSetParent(d, c);
// this should not (cleanup)
uiControlSetParent(c, NULL);
uiControlFree(d);
uiControlFree(c);
endCheckProgrammerError(ctx);
}
Test(ControlParentCyclesDisallowed_ThreeControls)
{
uiControl *c, *d, *e;
void *ctx;
ctx = beginCheckProgrammerError("TODO");
c = uiNewControl(testControlType(), NULL);
d = uiNewControl(testControlType(), NULL);
e = uiNewControl(testControlType(), NULL);
// this should fail
uiControlSetParent(c, d);
uiControlSetParent(d, e);
uiControlSetParent(e, c);
// this should not (cleanup)
uiControlSetParent(d, NULL);
uiControlSetParent(c, NULL);
uiControlFree(e);
uiControlFree(d);
uiControlFree(c);
endCheckProgrammerError(ctx);
}
Test(ControlCannotBeItsOwnParent)
{
uiControl *c;
void *ctx;
ctx = beginCheckProgrammerError("TODO");
c = uiNewControl(testControlType(), NULL);
uiControlSetParent(c, c);
uiControlFree(c);
endCheckProgrammerError(ctx);
}
Test(GettingImplDataOfNullControlIsProgrammerError) Test(GettingImplDataOfNullControlIsProgrammerError)
{ {
void *ctx; void *ctx;