2020-05-10 16:58:48 -05:00
// 8 june 2019
# include "test.h"
2020-05-10 20:29:03 -05:00
// TODO replace hardcoded control types of 5 with a constant from the test hook system
2020-05-10 16:58:48 -05:00
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() " ) ;
}
2020-05-10 20:29:03 -05:00
Test ( NullControlTypeNameIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiRegisterControlType(): invalid null pointer for name " ) ;
uiRegisterControlType ( NULL , NULL , NULL , 0 ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( NullControlVtableIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiRegisterControlType(): invalid null pointer for uiControlVtable " ) ;
uiRegisterControlType ( " name " , NULL , NULL , 0 ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( WrongControlVtableSizeIsProgrammerError )
{
uiControlVtable vtable ;
void * ctx ;
ctx = beginCheckProgrammerError ( " uiRegisterControlType(): wrong size 1 for uiControlVtable " ) ;
memset ( & vtable , 0 , sizeof ( uiControlVtable ) ) ;
vtable . Size = 1 ;
uiRegisterControlType ( " name " , & vtable , NULL , 0 ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( ControlVtableWithMIssingInitMethodIsProgrammerError )
{
uiControlVtable vt ;
void * ctx ;
ctx = beginCheckProgrammerError ( " uiRegisterControlType(): required uiControlVtable method Init() missing for uiControl type name " ) ;
vt = vtable ;
vt . Init = NULL ;
uiRegisterControlType ( " name " , & vt , NULL , 0 ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( ControlVtableWithMIssingFreeMethodIsProgrammerError )
{
uiControlVtable vt ;
void * ctx ;
ctx = beginCheckProgrammerError ( " uiRegisterControlType(): required uiControlVtable method Free() missing for uiControl type name " ) ;
vt = vtable ;
vt . Free = NULL ;
uiRegisterControlType ( " name " , & vt , NULL , 0 ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( NullControlOSVtableIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiRegisterControlType(): invalid null pointer for uiControlOSVtable " ) ;
uiRegisterControlType ( " name " , & vtable , NULL , 0 ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( CheckingNullControlIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiCheckControlType(): invalid null pointer for uiControl " ) ;
uiCheckControlType ( NULL , uiControlType ( ) ) ;
endCheckProgrammerError ( ctx ) ;
}
// TODO should this test be the same as the following one instead?
Test ( CheckingNonControlIsProgrammerError )
{
// TODO make sure this is fine; if not, just use the following check instead
static char buf [ ] = " this is not a uiControl but is big enough to at the very least not cause a problem with UB hopefully " ;
void * ctx ;
ctx = beginCheckProgrammerError ( " TODO " ) ;
uiCheckControlType ( buf , uiControlType ( ) ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( CheckingControlWithoutControlMarkerIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiCheckControlType(): object passed in not a uiControl " ) ;
uiCheckControlType ( uiprivTestHookControlWithInvalidControlMarker ( ) , uiControlType ( ) ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( CheckingControlWithAnUnknownTypeIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiCheckControlType(): unknown uiControl type 5 found in uiControl (this is likely not a real uiControl or some data is corrupt) " ) ;
uiCheckControlType ( uiprivTestHookControlWithInvalidType ( ) , testControlType ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( CheckingControlWithAnUnknownTypeIsProgrammerErrorEvenIfCheckingAgainstuiControlType )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiCheckControlType(): unknown uiControl type 5 found in uiControl (this is likely not a real uiControl or some data is corrupt) " ) ;
uiCheckControlType ( uiprivTestHookControlWithInvalidType ( ) , uiControlType ( ) ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( CheckingForUnknownControlTypeIsProgrammerError )
{
uiControl * c ;
void * ctx ;
ctx = beginCheckProgrammerError ( " uiCheckControlType(): unknown uiControl type 5 requested " ) ;
c = uiNewControl ( testControlType , NULL ) ;
uiCheckControlType ( c , 5 ) ;
uiControlFree ( c ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( CheckControlTypeFailsCorrectly )
{
uiControl * c ;
void * ctx ;
ctx = beginCheckProgrammerError ( " uiCheckControlType(): wrong uiControl type passed: got TestControl, want TestControl2 " ) ;
c = uiNewControl ( testControlType , NULL ) ;
uiCheckControlType ( c , testControlType2 ) ;
uiControlFree ( c ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( NewControlOfTypeControlIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiNewControl(): uiControlType() passed in when specific control type needed " ) ;
uiNewControl ( uiControlType ( ) , NULL ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( NewControlOfUnknownTypeIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiNewControl(): unknown uiControl type 5 requested " ) ;
uiNewControl ( 5 , NULL ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( NewControlWithInvalidInitDataIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiNewControl(): invalid init data for TestControl " ) ;
uiNewControl ( testControlType , testControlFailInit ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( FreeingNullControlIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiControlFree(): invalid null pointer for uiControl " ) ;
uiControlFree ( NULL ) ;
endCheckProgrammerError ( ctx ) ;
}
// TODO go back through all these tests and make the programmer error check as finely scoped as necessary
Test ( FreeingParentedControlIsProgrammerError )
{
uiControl * c , * d ;
void * ctx ;
ctx = beginCheckProgrammerError ( " uiControlFree(): cannot be called on a control with has a parent " ) ;
c = uiNewControl ( testControlType , NULL ) ;
d = uiNewControl ( testControlType , NULL ) ;
// this should fail
uiControlSetParent ( c , d ) ;
uiControlFree ( c ) ;
// this should not fail; it's normal cleanup
uiControlSetParent ( c , NULL ) ;
uiControlFree ( d ) ;
uiControlFree ( c ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( SetParentWithNullControlIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiControlSetParent(): invalid null pointer for uiControl " ) ;
uiControlSetParent ( NULL , NULL ) ;
endCheckProgrammerError ( ctx ) ;
}
// TODO copy this test but first setting and then removing the parent first, instead of just testing the initial state
Test ( RemovingParentFromParentlessControlIsProgrammerError )
{
uiControl * c ;
void * ctx ;
ctx = beginCheckProgrammerError ( " uiControlSetParent(): cannot set a control with no parent to have no parent " ) ;
c = uiNewControl ( testControlType , NULL ) ;
uiControlSetParent ( c , NULL ) ;
uiControlFree ( c ) ;
endCheckProgrammerError ( ctx ) ;
}
Test ( ReparentingAlreadyParentedControlIsProgrammerError )
{
uiControl * c , * d , * e ;
void * ctx ;
ctx = beginCheckProgrammerError ( " uiControlSetParent(): cannot set a control with a parent to have another parent " ) ;
c = uiNewControl ( testControlType , NULL ) ;
d = uiNewControl ( testControlType , NULL ) ;
e = uiNewControl ( testControlType , NULL ) ;
// this should fail
uiControlSetParent ( c , d ) ;
uiControlSetParent ( c , e ) ;
// this should not (cleanup)
uiControlSetParent ( c , NULL ) ;
uiControlFree ( e ) ;
uiControlFree ( d ) ;
uiControlFree ( c ) ;
endCheckProgrammerError ( ctx ) ;
}
// TODO define and then test the above but for the same parent
Test ( GettingImplDataOfNullControlIsProgrammerError )
{
void * ctx ;
ctx = beginCheckProgrammerError ( " uiControlImplData(): invalid null pointer for uiControl " ) ;
uiControlImplData ( NULL ) ;
endCheckProgrammerError ( ctx ) ;
}