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 786 : register_unit_test( fd_unit_test_t * test ) { 32 786 : if( fd_unit_test_tail ) fd_unit_test_tail->next = test; 33 48 : else fd_unit_test_head = test; 34 786 : fd_unit_test_tail = test; 35 786 : } 36 : 37 : static inline int 38 : match_test_name( char const * test_name, 39 : int argc, 40 786 : char ** argv ) { 41 786 : if( argc<=1 ) return 1; 42 3249 : for( int i=1; i<argc; i++ ) { 43 2724 : if( argv[ i ][ strspn( argv[ i ], " \t\n\r" ) ]=='\0' ) continue; 44 2724 : if( strstr( test_name, argv[ i ] ) ) return 1; 45 2724 : } 46 525 : return 0; 47 540 : } 48 : 49 : #define FD_UNIT_TEST( name ) \ 50 : static void name( void ); \ 51 : static fd_unit_test_t name##_test = { #name, name, NULL }; \ 52 786 : __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 48 : char ** argv ) { 58 834 : for( fd_unit_test_t * tc = fd_unit_test_head; tc; tc = tc->next ) { 59 786 : if( match_test_name( tc->name, argc, argv ) ) { 60 261 : FD_LOG_NOTICE(( "Running %s", tc->name )); 61 261 : tc->fn(); 62 261 : } 63 786 : } 64 48 : }