Line data Source code
1 : /* fd_unit_test.c helps with writing unit tests. 2 : 3 : Usage: 4 : 5 : FD_UNIT_TEST( foo ) { ... } 6 : FD_UNIT_TEST( bar ) { ... } 7 : 8 : #include "fd_unit_test.c" 9 : 10 : void main() { fd_unit_tests( argc, argv ); } 11 : 12 : Then run: ./my_test bar 13 : (Only runs tests matching the string 'bar') */ 14 : 15 : #include "../log/fd_log.h" 16 : #include <string.h> 17 : 18 : struct fd_unit_test { 19 : char const * name; 20 : void (* fn)( void ); 21 : struct fd_unit_test * next; 22 : }; 23 : 24 : typedef struct fd_unit_test fd_unit_test_t; 25 : 26 : /* Linked list of known unit tests */ 27 : static fd_unit_test_t * fd_unit_test_head = NULL; 28 : static fd_unit_test_t * fd_unit_test_tail = NULL; 29 : 30 : static inline void 31 516 : register_unit_test( fd_unit_test_t * test ) { 32 516 : if( fd_unit_test_tail ) fd_unit_test_tail->next = test; 33 39 : else fd_unit_test_head = test; 34 516 : fd_unit_test_tail = test; 35 516 : } 36 : 37 : static inline int 38 : match_test_name( char const * test_name, 39 : int argc, 40 516 : char ** argv ) { 41 516 : if( argc<=1 ) return 1; 42 1590 : for( int i=1; i<argc; i++ ) { 43 1320 : if( argv[ i ][ strspn( argv[ i ], " \t\n\r" ) ]=='\0' ) continue; 44 1320 : if( strstr( test_name, argv[ i ] ) ) return 1; 45 1320 : } 46 270 : return 0; 47 276 : } 48 : 49 : #define FD_UNIT_TEST( name ) \ 50 : static void name( void ); \ 51 : static fd_unit_test_t name##_test = { #name, name, NULL }; \ 52 516 : __attribute__((constructor)) static void register_##name( void ) { register_unit_test( &name##_test ); } \ 53 : static void name( void ) 54 : 55 : static inline void 56 : fd_unit_tests( int argc, 57 39 : char ** argv ) { 58 555 : for( fd_unit_test_t * tc = fd_unit_test_head; tc; tc = tc->next ) { 59 516 : if( match_test_name( tc->name, argc, argv ) ) { 60 246 : FD_LOG_NOTICE(( "Running %s", tc->name )); 61 246 : tc->fn(); 62 246 : } 63 516 : } 64 39 : }