Simple XUnit test library / objects in plain C Snapshot
|
00001 /* Copyright (c) Michael Moser (2011) . 3-clause BSD License applies */ 00002 00003 #include "vtest.h" 00004 #include "vtestrunner.h" 00005 #include "vtestcui.h" 00006 #include <stdio.h> 00007 #include <string.h> 00008 #include <stdarg.h> 00009 00010 00011 00012 static PFN_DEBUG_FUNCTION debug_output_hook = 0; 00013 00014 00015 static void MSG( const char * format, ... ) 00016 { 00017 va_list ap; 00018 00019 va_start(ap, format); 00020 if (!debug_output_hook) { 00021 vfprintf( stdout, format, ap ); 00022 } else { 00023 char big_buf[ 32 * 1024 ]; 00024 00025 vsnprintf( big_buf, sizeof( big_buf ), format, ap ); 00026 debug_output_hook( big_buf ); 00027 fputs( big_buf, stdout ); 00028 } 00029 va_end(ap); 00030 00031 } 00032 00033 void VTEST_CUI_set_debug_output_hook( PFN_DEBUG_FUNCTION debug_output_hook_ ) { 00034 debug_output_hook = debug_output_hook_; 00035 } 00036 00037 void CUI_report_suite_start (const char *suite_name) 00038 { 00039 MSG( "Suite %s\n", suite_name ); 00040 } 00041 00042 void CUI_report_test_start (const char *suite_name, const char *test_name, int iteration, int maxiteration) 00043 { 00044 if (maxiteration == 1) { 00045 MSG( " Test: %s/%s started\n", suite_name, test_name); 00046 } else { 00047 MSG( " Test: %s/%s started. iteration #%d out of #%d\n", suite_name, test_name, iteration, maxiteration); 00048 } 00049 } 00050 00051 #ifdef TIME_TEST_GETTIMEOFDAY 00052 00053 static void format_time( char *time_str, size_t time_str_len, struct timeval *duration) 00054 { 00055 if (duration->tv_sec != 0) { 00056 snprintf(time_str, time_str_len," (Duration - %ld sec %ld micro secs)\n", duration->tv_sec, duration->tv_usec); 00057 } else { 00058 snprintf(time_str, time_str_len," (Duration - %ld micro secs)\n", duration->tv_usec); 00059 } 00060 00061 } 00062 #endif 00063 00064 00065 void CUI_report_results( VTEST_STATUS status, 00066 const char *suite_name, const char *test_name, 00067 struct timeval *duration, 00068 const char *fail_cond, const char *fail_file,int fail_line) 00069 { 00070 (void) (test_name); 00071 00072 switch(status) { 00073 case VTEST_TEST_OK: { 00074 #ifdef TIME_TEST_GETTIMEOFDAY 00075 char msg[100]; 00076 char *ptr; 00077 size_t size; 00078 00079 ptr = msg; 00080 size = sizeof(msg); 00081 00082 strcpy(msg, " Status: Ok" ); 00083 00084 size -= strlen(msg); 00085 ptr += strlen(msg); 00086 00087 format_time( ptr, size, duration ); 00088 00089 MSG( msg ); 00090 00091 #else 00092 (void) (duration); 00093 MSG( " Status: Ok\n"); 00094 #endif 00095 } 00096 break; 00097 case VTEST_TEST_FAILED: 00098 MSG( " Status: Failed - %s at %s:%d\n", 00099 fail_cond, fail_file, fail_line); 00100 break; 00101 case VTEST_SUITE_SETUP_FAILED: 00102 MSG( "Suite %s setup failed - %s at %s:%d\n", 00103 suite_name, fail_cond, fail_file, fail_line); 00104 break; 00105 00106 case VTEST_SUITE_TEARDOWN_FAILED: 00107 MSG( "Suite %s teardown failed - %s at %s:%d\n", 00108 suite_name, fail_cond, fail_file, fail_line); 00109 break; 00110 00111 default: { 00112 } 00113 } 00114 } 00115 00116 void CUI_report_wrapup (int suitesinitfailed, int suitesteardownfailed, 00117 int tests_passed, int tests_failed, int testnotrun) 00118 { 00119 MSG( "\nTest summary\n" 00120 " Tests passed: %d\n" 00121 " Tests failed: %d\n" 00122 " Tests not run: %d (due to suite setup failure)\n" 00123 " Suites setup failed: %d\n" 00124 " Suites teardown failed: %d\n", 00125 00126 tests_passed, tests_failed, testnotrun, 00127 suitesinitfailed, suitesteardownfailed); 00128 00129 if (!suitesinitfailed && !suitesteardownfailed && 00130 !tests_failed && !testnotrun) { 00131 00132 MSG( "\nALL TESTS PASSED\n"); 00133 00134 } else { 00135 00136 MSG( "\n***YOU HAVE TESTS TO FIX***\n"); 00137 00138 } 00139 00140 } 00141 00142 int VTEST_CUI_test_runner(VTEST_TEST_SUITE *suite) 00143 { 00144 VTEST_RUNNER_IMPL impl; 00145 00146 impl.suite_start = CUI_report_suite_start; 00147 impl.test_start = CUI_report_test_start; 00148 impl.results = CUI_report_results; 00149 impl.wrapup = CUI_report_wrapup; 00150 00151 return VTEST_test_runner( suite, &impl ); 00152 00153 } 00154 00155 int VTEST_CUI_test_runner_cmdline(VTEST_TEST_SUITE *suite, int argc, char *argv[]) 00156 { 00157 VTEST_RUNNER_IMPL impl; 00158 00159 impl.suite_start = CUI_report_suite_start; 00160 impl.test_start = CUI_report_test_start; 00161 impl.results = CUI_report_results; 00162 impl.wrapup = CUI_report_wrapup; 00163 00164 return VTEST_test_runner_cmdline( suite, &impl, argc, argv); 00165 00166 } 00167 00168 void VTEST_CUI_list_suite(VTEST_TEST_SUITE *suite) 00169 { 00170 for(;suite; suite = suite->next_suite) { 00171 MSG( "%s ",suite->name); 00172 } 00173 } 00174 00175 int VTEST_CUI_list_tests_of_suite(VTEST_TEST_SUITE *suite,const char *suite_name) 00176 { 00177 int ret = 0; 00178 VTEST_TEST *test; 00179 00180 00181 for(;suite; suite = suite->next_suite) { 00182 if (strcmp(suite->name,suite_name) == 0) { 00183 ret = 1; 00184 00185 for(test = suite->test_cases; test->name != 0; test++) { 00186 00187 MSG( "%s ",test->name); 00188 } 00189 } 00190 } 00191 00192 return ret; 00193 } 00194