2018-02-28 00:21:10 -06:00
// 27 february 2018
2018-02-27 22:44:50 -06:00
# ifndef TODO_TEST
# error TODO this is where libui itself goes
# endif
2018-02-28 18:43:29 -06:00
# include <inttypes.h>
2018-02-27 22:44:50 -06:00
# include <stdarg.h>
2018-02-28 00:21:10 -06:00
# undef testingprivBadLanguageVersion
# ifdef __cplusplus
// TODO https://stackoverflow.com/questions/2324658/how-to-determine-the-version-of-the-c-standard-used-by-the-compiler implies this won't do with C++0x-era compilers, and https://wiki.apache.org/stdcxx/C++0xCompilerSupport doesn't talk about va_copy() so a simple version check for the C99 preprocessor may be wrong...
// TODO what if __cplusplus is blank (maybe only in that case, since IIRC C++98 requires __cplusplus to have a value)?
# if __cplusplus < 201103L
# define testingprivBadLanguageVersion
# endif
# elif !defined(__STDC_VERSION__)
# define testingprivBadLanguageVersion
# elif __STDC_VERSION__ < 199901L
# define testingprivBadLanguageVersion
# endif
# ifdef testingprivBadLanguageVersion
2018-02-28 18:43:29 -06:00
# error sorry, TODO requires either C99 or C++11; cannot continue
2018-02-28 00:21:10 -06:00
# endif
2018-02-27 22:44:50 -06:00
# ifdef __cplusplus
extern " C " {
# endif
# if defined(__GNUC__)
# define testingTest(Name) \
void Test # # Name ( testingT * t ) ; \
__attribute__ ( ( constructor ) ) static inline void testingprivCtorRegisterTest # # Name ( void ) { testingprivRegisterTest ( " Test " # Name , Test # # Name ) ; } \
void Test # # Name ( testingT * t )
# else
# error unknown compiler; cannot continue
# endif
extern int testingMain ( void ) ;
typedef struct testingT testingT ;
2018-02-28 00:21:10 -06:00
# define testingTErrorf(t, ...) testingprivTErrorfFull(t, __FILE__, __LINE__, __VA_ARGS__)
# define testingTErrorvf(t, format, ap) testingprivTErrorvfFull(t, __FILE__, __LINE__, format, ap)
2018-02-27 22:44:50 -06:00
2018-02-28 00:21:10 -06:00
// TODO should __LINE__ arguments use intmax_t or uintmax_t instead of int?
extern void testingprivRegisterTest ( const char * , void ( * ) ( testingT * ) ) ;
extern void testingprivTErrorfFull ( testingT * , const char * , int , const char * , . . . ) ;
extern void testingprivTErrorvfFull ( testingT * , const char * , int , const char * , va_list ) ;
2018-02-27 22:44:50 -06:00
# ifdef __cplusplus
}
# endif
2018-02-28 18:43:29 -06:00
# include <stddef.h>
# include <stdint.h>
# include <stdlib.h>
# include <string.h>
typedef struct uiOpenTypeFeatures uiOpenTypeFeatures ;
typedef int uiForEach ;
enum { uiForEachContinue , uiForEachStop } ;
typedef uiForEach ( * uiOpenTypeFeaturesForEachFunc ) ( const uiOpenTypeFeatures * otf , char a , char b , char c , char d , uint32_t value , void * data ) ;
# define uiprivNew(x) ((x *) malloc(sizeof (x)))
# define uiprivAlloc(x,y) malloc(x)
# define uiprivRealloc(x,y,z) realloc(x,y)
# define uiprivFree free
# include "opentype.c"
testingTest ( OpenTypeFeaturesAddGet )
2018-02-27 22:44:50 -06:00
{
2018-02-28 18:43:29 -06:00
uiOpenTypeFeatures * otf ;
char a , b , c , d ;
uint32_t value ;
otf = uiNewOpenTypeFeatures ( ) ;
uiOpenTypeFeaturesAdd ( otf , ' a ' , ' b ' , ' c ' , ' d ' , 12345 ) ;
if ( ! uiOpenTypeFeaturesGet ( otf , ' a ' , ' b ' , ' c ' , ' d ' , & value ) ) {
testingTErrorf ( t , " uiOpenTypeFeaturesGet() failed to get feature we added " ) ;
goto out ;
}
if ( value ! = 12345 ) {
testingTErrorf ( t , " feature abcd: got % " PRIu32 " , want 12345 " , value ) ;
goto out ;
}
out :
uiFreeOpenTypeFeatures ( otf ) ;
2018-02-27 22:44:50 -06:00
}
int main ( void )
{
return testingMain ( ) ;
}
# include <stdio.h>
# include <stdlib.h>
# define testingprivNew(T) ((T *) malloc(sizeof (T)))
struct testingT {
const char * name ;
void ( * f ) ( testingT * ) ;
int failed ;
2018-02-28 00:22:16 -06:00
testingT * next ;
2018-02-27 22:44:50 -06:00
} ;
static testingT * tests = NULL ;
void testingprivRegisterTest ( const char * name , void ( * f ) ( testingT * ) )
{
testingT * t ;
2018-02-28 00:21:10 -06:00
t = testingprivNew ( testingT ) ;
2018-02-27 22:44:50 -06:00
t - > name = name ;
t - > f = f ;
t - > failed = 0 ;
t - > next = tests ;
tests = t ;
}
int testingMain ( void )
{
testingT * t ;
int anyFailed ;
const char * status ;
if ( tests = = NULL ) {
fprintf ( stderr , " warning: no tests to run \n " ) ;
2018-02-28 00:21:10 -06:00
// imitate Go here (TODO confirm this)
2018-02-27 22:44:50 -06:00
return 0 ;
}
anyFailed = 0 ;
for ( t = tests ; t ! = NULL ; t = t - > next ) {
printf ( " === RUN %s \n " , t - > name ) ;
( * ( t - > f ) ) ( t ) ;
status = " PASS " ;
if ( t - > failed ) {
status = " FAIL " ;
anyFailed = 1 ;
}
printf ( " --- %s: %s (%s) \n " , status , t - > name , " TODO " ) ;
}
if ( anyFailed ) {
printf ( " FAIL \n " ) ;
return 1 ;
}
printf ( " PASS \n " ) ;
return 0 ;
}
2018-02-28 00:21:10 -06:00
static void testingprivTDoLog ( testingT * t , const char * file , int line , const char * format , va_list ap )
{
// TODO extract filename from file
printf ( " \t %s:%d: " , file , line ) ;
// TODO split into lines separated by \n\t\t and trimming trailing empty lines
vprintf ( format , ap ) ;
printf ( " \n " ) ;
}
void testingprivTErrorfFull ( testingT * t , const char * file , int line , const char * format , . . . )
2018-02-27 22:44:50 -06:00
{
va_list ap ;
va_start ( ap , format ) ;
2018-02-28 00:21:10 -06:00
testingprivTErrorvfFull ( t , file , line , format , ap ) ;
2018-02-27 22:44:50 -06:00
va_end ( ap ) ;
}
2018-02-28 00:21:10 -06:00
void testingprivTErrorvfFull ( testingT * t , const char * file , int line , const char * format , va_list ap )
2018-02-27 22:44:50 -06:00
{
2018-02-28 00:21:10 -06:00
testingprivTDoLog ( t , file , line , format , ap ) ;
t - > failed = 1 ;
2018-02-27 22:44:50 -06:00
}