2020-01-20 19:52:46 -06:00
// 10 april 2019
# include "test.h"
2020-01-21 13:19:52 -06:00
# include "thread.h"
2020-01-20 19:52:46 -06:00
// TODO test the number of calls to queued functions made
# define errInvalidOptions "options parameter to uiInit() must be NULL"
# define errAlreadyInitialized "libui already initialized"
2020-01-21 00:16:47 -06:00
TestNoInit ( Init )
2020-01-20 19:52:46 -06:00
{
uiInitError err ;
if ( uiInit ( NULL , NULL ) )
TestErrorf ( " uiInit() with NULL error succeeded; expected failure " ) ;
memset ( & err , 0 , sizeof ( uiInitError ) ) ;
err . Size = 2 ;
if ( uiInit ( NULL , & err ) )
TestErrorf ( " uiInit() with error with invalid size succeeded; expected failure " ) ;
err . Size = sizeof ( uiInitError ) ;
if ( uiInit ( & err , & err ) )
TestErrorf ( " uiInit() with non-NULL options succeeded; expected failure " ) ;
if ( strcmp ( err . Message , errInvalidOptions ) ! = 0 )
TestErrorf ( " uiInit() with non-NULL options returned bad error message: " diff ( " %s " ) ,
err . Message , errInvalidOptions ) ;
}
2020-01-21 13:19:52 -06:00
Test ( InitAfterInitialized )
2020-01-20 19:52:46 -06:00
{
uiInitError err ;
memset ( & err , 0 , sizeof ( uiInitError ) ) ;
err . Size = sizeof ( uiInitError ) ;
if ( uiInit ( NULL , & err ) )
2020-01-21 13:19:52 -06:00
TestErrorf ( " uiInit() after a previous successful call succeeded; expected failure " ) ;
2020-01-20 19:52:46 -06:00
if ( strcmp ( err . Message , errAlreadyInitialized ) ! = 0 )
2020-01-21 13:19:52 -06:00
TestErrorf ( " uiInit() after a previous successful call returned bad error message: " diff ( " %s " ) ,
2020-01-20 19:52:46 -06:00
err . Message , errAlreadyInitialized ) ;
}
struct testParams {
uint32_t flag ;
} ;
/*
TODO if I remove the uiQuit ( ) from this test on Windows , I will occasionally get
= = = RUN TestQueueMain_DifferentThread
. . / test / initmain . c : 161 : uiMain ( ) timed out ( 5 s )
- - - FAIL : TestQueueMain_DifferentThread ( 4.9989539 s )
*/
static void queued ( void * data )
{
struct testParams * p = ( struct testParams * ) data ;
p - > flag = 1 ;
uiQuit ( ) ;
}
2020-01-21 13:19:52 -06:00
Test ( QueueMain )
2020-01-20 19:52:46 -06:00
{
struct testParams p ;
memset ( & p , 0 , sizeof ( struct testParams ) ) ;
p . flag = 0 ;
uiQueueMain ( queued , & p ) ;
2020-01-21 13:19:52 -06:00
uiMain ( ) ;
2020-01-20 19:52:46 -06:00
if ( p . flag ! = 1 )
2020-01-21 13:19:52 -06:00
TestErrorf ( " uiQueueMain() didn't set flag properly: " diff ( " %d " ) ,
2020-01-20 19:52:46 -06:00
p . flag , 1 ) ;
}
2020-01-21 13:19:52 -06:00
// TODO there has to be a way to do this that absolutely will not possibly go in the wrong order... or produce a false positive
2020-01-20 19:52:46 -06:00
# define queueOp(name, expr) \
static void name ( void * data ) \
{ \
struct testParams * p = ( struct testParams * ) data ; \
p - > flag = p - > flag expr ; \
}
queueOp ( sub2 , - 2 )
queueOp ( div3 , / 3 )
queueOp ( mul8 , * 8 )
static void done ( void * data )
{
uiQuit ( ) ;
}
static const struct {
uint32_t result ;
const char * order ;
} orders [ ] = {
{ 8 , " sub2 -> div3 -> mul8 " } , // the one we want
{ 13 , " sub2 -> mul8 -> div3 " } ,
{ 0 , " div3 -> sub2 -> mul8 " } ,
{ 14 , " div3 -> mul8 -> sub2 " } ,
{ 18 , " mul8 -> sub2 -> div3 " } ,
{ 16 , " mul8 -> div3 -> sub2 " } ,
} ;
static void queueOrder ( struct testParams * p )
{
p - > flag = 7 ;
uiQueueMain ( sub2 , p ) ;
uiQueueMain ( div3 , p ) ;
uiQueueMain ( mul8 , p ) ;
uiQueueMain ( done , NULL ) ;
}
2020-01-21 13:19:52 -06:00
// TODO avoid the need to carry over testingprivRet
// TODO also actually handle file and line again
static void checkOrderFull ( int * testingprivRet , const char * file , long line , uint32_t flag )
2020-01-20 19:52:46 -06:00
{
int i ;
if ( flag = = orders [ 0 ] . result )
return ;
for ( i = 1 ; i < 6 ; i + + )
if ( flag = = orders [ i ] . result ) {
2020-01-21 13:19:52 -06:00
TestErrorf ( " wrong order: " diff ( " % " PRIu32 " (%s) " ) ,
2020-01-20 19:52:46 -06:00
flag , orders [ i ] . order ,
orders [ 0 ] . result , orders [ 0 ] . order ) ;
return ;
}
2020-01-21 13:19:52 -06:00
TestErrorf ( " wrong result: " diff ( " % " PRIu32 " (%s) " ) ,
2020-01-20 19:52:46 -06:00
flag , " unknown order " ,
orders [ 0 ] . result , orders [ 0 ] . order ) ;
}
2020-01-21 13:19:52 -06:00
# define checkOrder(flag) checkOrderFull(testingprivRet, __FILE__, __LINE__, flag)
2020-01-20 19:52:46 -06:00
2020-01-21 13:19:52 -06:00
Test ( QueueMain_Sequence )
2020-01-20 19:52:46 -06:00
{
struct testParams p ;
memset ( & p , 0 , sizeof ( struct testParams ) ) ;
queueOrder ( & p ) ;
2020-01-21 13:19:52 -06:00
uiMain ( ) ;
checkOrder ( p . flag ) ;
2020-01-20 19:52:46 -06:00
}
2020-01-21 13:19:52 -06:00
// TODO make a version of these where the thread is started by a queued function
2020-01-20 19:52:46 -06:00
static void queueThread ( void * data )
{
struct testParams * p = ( struct testParams * ) data ;
2020-01-21 13:19:52 -06:00
// TODO reintegrate the timer somehow
// p->err = timerSleep(1250 * timerMillisecond);
2020-01-20 19:52:46 -06:00
uiQueueMain ( queued , p ) ;
}
2020-01-21 13:19:52 -06:00
Test ( QueueMain_DifferentThread )
2020-01-20 19:52:46 -06:00
{
threadThread * thread ;
threadSysError err ;
struct testParams p ;
memset ( & p , 0 , sizeof ( struct testParams ) ) ;
p . flag = 0 ;
err = threadNewThread ( queueThread , & p , & thread ) ;
if ( err ! = 0 )
2020-01-21 13:19:52 -06:00
TestFatalf ( " error creating thread: " threadSysErrorFmt , threadSysErrorFmtArg ( err ) ) ;
uiMain ( ) ;
2020-01-20 19:52:46 -06:00
err = threadThreadWaitAndFree ( thread ) ;
if ( err ! = 0 )
2020-01-21 13:19:52 -06:00
TestFatalf ( " error waiting for thread to finish: " threadSysErrorFmt , threadSysErrorFmtArg ( err ) ) ;
// if (p.err != 0)
// TestErrorf("error sleeping in thread to ensure a high likelihood the uiQueueMain() is run after uiMain() starts: " timerSysErrorFmt, timerSysErrorFmtArg(p.err));
2020-01-20 19:52:46 -06:00
if ( p . flag ! = 1 )
2020-01-21 13:19:52 -06:00
TestErrorf ( " uiQueueMain() didn't set flag properly: " diff ( " %d " ) ,
2020-01-20 19:52:46 -06:00
p . flag , 1 ) ;
}
static void queueOrderThread ( void * data )
{
struct testParams * p = ( struct testParams * ) data ;
2020-01-21 13:19:52 -06:00
// p->err = timerSleep(1250 * timerMillisecond);
2020-01-20 19:52:46 -06:00
queueOrder ( p ) ;
}
2020-01-21 13:19:52 -06:00
Test ( QueueMain_DifferentThreadSequence )
2020-01-20 19:52:46 -06:00
{
threadThread * thread ;
threadSysError err ;
struct testParams p ;
memset ( & p , 0 , sizeof ( struct testParams ) ) ;
p . flag = 1 ; // make sure it's initialized just in case
err = threadNewThread ( queueOrderThread , & p , & thread ) ;
if ( err ! = 0 )
2020-01-21 13:19:52 -06:00
TestFatalf ( " error creating thread: " threadSysErrorFmt , threadSysErrorFmtArg ( err ) ) ;
uiMain ( ) ;
2020-01-20 19:52:46 -06:00
err = threadThreadWaitAndFree ( thread ) ;
if ( err ! = 0 )
2020-01-21 13:19:52 -06:00
TestFatalf ( " error waiting for thread to finish: " threadSysErrorFmt , threadSysErrorFmtArg ( err ) ) ;
// if (p.err != 0)
// TestErrorf("error sleeping in thread to ensure a high likelihood the uiQueueMain() is run after uiMain() starts: " timerSysErrorFmt, timerSysErrorFmtArg(p.err));
checkOrder ( p . flag ) ;
2020-01-20 19:52:46 -06:00
}
2020-01-21 13:19:52 -06:00
#if 0
2020-01-20 19:52:46 -06:00
static void timer ( void * data )
{
int * n = ( int * ) data ;
// TODO return stop if n == 5, continue otherwise
* n + + ;
}
testingTest ( Timer )
{
}
# endif