Project Ne10
An Open Optimized Software Library Project for the ARM Architecture
Loading...
Searching...
No Matches
seatest.c
1#include "seatest.h"
2#include <string.h>
3#ifdef WIN32
4#include "windows.h"
5int seatest_is_string_equal_i(const char* s1, const char* s2)
6{
7 #pragma warning(disable: 4996)
8 return stricmp(s1, s2) == 0;
9}
10
11#else
12#include <sys/time.h>
13
14long int GetTickCount()
15{
16//#ifndef __MACH__
17// struct timespec tv;
18// clock_gettime(CLOCK_MONOTONIC, &tv);
19// return tv.tv_sec*1000000 + tv.tv_nsec/1000;
20//
21//#else
22 struct timeval tv;
23 gettimeofday(&tv, NULL);
24 return tv.tv_sec*1000000 + tv.tv_usec;
25//#endif
26}
27void _getch( void ) { }
28int seatest_is_string_equal_i(const char* s1, const char* s2)
29{
30 return strcasecmp(s1, s2) == 0;
31}
32#endif
33
34#ifdef SEATEST_INTERNAL_TESTS
35static int sea_test_last_passed = 0;
36#endif
37
38typedef enum
39{
40 SEATEST_DISPLAY_TESTS,
41 SEATEST_RUN_TESTS,
42 SEATEST_DO_NOTHING,
43 SEATEST_DO_ABORT
44} seatest_action_t;
45
46typedef struct
47{
48 int argc;
49 char** argv;
50 seatest_action_t action;
52static int seatest_screen_width = 70;
53static int sea_tests_run = 0;
54static int sea_tests_passed = 0;
55static int sea_tests_failed = 0;
56static int seatest_display_only = 0;
57static int seatest_verbose = 0;
58static int seatest_machine_readable = 0;
59static char* seatest_current_fixture;
60static char* seatest_current_fixture_path;
61static char seatest_magic_marker[20] = "";
62
63static seatest_void_void seatest_suite_setup_func = 0;
64static seatest_void_void seatest_suite_teardown_func = 0;
65static seatest_void_void seatest_fixture_setup = 0;
66static seatest_void_void seatest_fixture_teardown = 0;
67
68void (*seatest_simple_test_result)(int passed, char* reason, const char* function, unsigned int line) = seatest_simple_test_result_log;
69
70void suite_setup(seatest_void_void setup)
71{
72 seatest_suite_setup_func = setup;
73}
74void suite_teardown(seatest_void_void teardown)
75{
76 seatest_suite_teardown_func = teardown;
77}
78
79int seatest_is_display_only()
80{
81 return seatest_display_only;
82}
83
84void seatest_suite_setup( void )
85{
86 if(seatest_suite_setup_func != 0) seatest_suite_setup_func();
87}
88
89void seatest_suite_teardown( void )
90{
91 if(seatest_suite_teardown_func != 0) seatest_suite_teardown_func();
92}
93
94void fixture_setup(void (*setup)( void ))
95{
96 seatest_fixture_setup = setup;
97}
98void fixture_teardown(void (*teardown)( void ))
99{
100 seatest_fixture_teardown = teardown;
101}
102
103void seatest_setup( void )
104{
105 if(seatest_fixture_setup != 0) seatest_fixture_setup();
106}
107
108void seatest_teardown( void )
109{
110 if(seatest_fixture_teardown != 0) seatest_fixture_teardown();
111}
112
113char* test_file_name(char* path)
114{
115 char* file = path + strlen(path);
116 while(file != path && *file!= '\\' ) file--;
117 if(*file == '\\') file++;
118 return file;
119}
120
121static int seatest_fixture_tests_run;
122static int seatest_fixture_tests_failed;
123
124void seatest_simple_test_result_log(int passed, char* reason, const char* function, unsigned int line)
125{
126 if (!passed)
127 {
128
129 if(seatest_machine_readable)
130 {
131 printf("%s%s,%s,%u,%s\r\n", seatest_magic_marker, seatest_current_fixture_path, function, line, reason );
132 }
133 else
134 {
135 printf("%-30s Line %-5d %s\r\n", function, line, reason );
136 }
137 sea_tests_failed++;
138 }
139 else
140 {
141 if(seatest_verbose)
142 {
143 if(seatest_machine_readable)
144 {
145 printf("%s%s,%s,%u,Passed\r\n", seatest_magic_marker, seatest_current_fixture_path, function, line );
146 }
147 else
148 {
149 printf("%-30s Line %-5d Passed\r\n", function, line);
150 }
151 }
152 sea_tests_passed++;
153 }
154}
155
156void seatest_assert_true(int test, const char* function, unsigned int line)
157{
158 seatest_simple_test_result(test, "Should have been true", function, line);
159
160}
161
162void seatest_assert_false(int test, const char* function, unsigned int line)
163{
164 seatest_simple_test_result(!test, "Should have been false", function, line);
165}
166
167
168void seatest_assert_int_equal(int expected, int actual, const char* function, unsigned int line)
169{
170 char s[SEATEST_PRINT_BUFFER_SIZE];
171 sprintf(s, "Expected %d but was %d", expected, actual);
172 seatest_simple_test_result(expected==actual, s, function, line);
173}
174
175void seatest_assert_ulong_equal(unsigned long expected, unsigned long actual, const char* function, unsigned int line)
176{
177 char s[SEATEST_PRINT_BUFFER_SIZE];
178 sprintf(s, "Expected %lu but was %lu", expected, actual);
179 seatest_simple_test_result(expected==actual, s, function, line);
180}
181
182void seatest_assert_float_vec_equal( float expected, float actual, unsigned int delta, unsigned int seatest_vec, const char* function, unsigned int line )
183{
184 char s[SEATEST_PRINT_BUFFER_SIZE];
185 if (!EQUALS_FLOAT(expected, actual, delta))
186 {
187 sprintf(s, "Expected %e (0x%04X) but was %e (0x%04X) at vector->%d ",
188 expected, *(unsigned int*)&expected, actual, *(unsigned int*)&actual, seatest_vec);
189 seatest_simple_test_result( 0, s, function, line);
190 }
191}
192
193void seatest_assert_float_equal( float expected, float actual, unsigned int delta, unsigned int loop_round, const char* function, unsigned int line )
194{
195 char s[SEATEST_PRINT_BUFFER_SIZE];
196 if (!EQUALS_FLOAT(expected, actual, delta))
197 {
198 sprintf(s, "Expected %e (0x%04X) but was %e (0x%04X) in loop round %d",
199 expected, *(unsigned int*)&expected, actual, *(unsigned int*)&actual, loop_round);
200 seatest_simple_test_result( 0, s, function, line);
201 }
202}
203
204void seatest_assert_double_equal( double expected, double actual, double delta, const char* function, unsigned int line )
205{
206 char s[SEATEST_PRINT_BUFFER_SIZE];
207 double result = expected-actual;
208 sprintf(s, "Expected %f but was %f", expected, actual);
209 if(result < 0.0) result = 0.0 - result;
210 seatest_simple_test_result( result <= delta, s, function, line);
211}
212
213void seatest_assert_string_equal(char* expected, char* actual, const char* function, unsigned int line)
214{
215 int comparison;
216 char s[SEATEST_PRINT_BUFFER_SIZE];
217
218 if ((expected == (char *)0) && (actual == (char *)0))
219 {
220 sprintf(s, "Expected <NULL> but was <NULL>");
221 comparison = 1;
222 }
223 else if ((expected == (char *)0))
224 {
225 sprintf(s, "Expected <NULL> but was %s", actual);
226 comparison = 0;
227 }
228 else if ((actual == (char *)0))
229 {
230 sprintf(s, "Expected %s but was <NULL>", expected);
231 comparison = 0;
232 }
233 else
234 {
235 comparison = strcmp(expected, actual) == 0;
236 sprintf(s, "Expected %s but was %s", expected, actual);
237 }
238
239 seatest_simple_test_result(comparison, s, function, line);
240}
241
242void seatest_assert_string_ends_with(char* expected, char* actual, const char* function, unsigned int line)
243{
244 char s[SEATEST_PRINT_BUFFER_SIZE];
245 sprintf(s, "Expected %s to end with %s", actual, expected);
246 seatest_simple_test_result(strcmp(expected, actual+(strlen(actual)-strlen(expected)))==0, s, function, line);
247}
248
249void seatest_assert_string_starts_with(char* expected, char* actual, const char* function, unsigned int line)
250{
251 char s[SEATEST_PRINT_BUFFER_SIZE];
252 sprintf(s, "Expected %s to start with %s", actual, expected);
253 seatest_simple_test_result(strncmp(expected, actual, strlen(expected))==0, s, function, line);
254}
255
256void seatest_assert_string_contains(char* expected, char* actual, const char* function, unsigned int line)
257{
258 char s[SEATEST_PRINT_BUFFER_SIZE];
259 sprintf(s, "Expected %s to be in %s", expected, actual);
260 seatest_simple_test_result(strstr(actual, expected)!=0, s, function, line);
261}
262
263void seatest_assert_string_doesnt_contain(char* expected, char* actual, const char* function, unsigned int line)
264{
265 char s[SEATEST_PRINT_BUFFER_SIZE];
266 sprintf(s, "Expected %s not to have %s in it", actual, expected);
267 seatest_simple_test_result(strstr(actual, expected)==0, s, function, line);
268}
269
270void seatest_run_test(char* fixture, char* test)
271{
272 sea_tests_run++;
273}
274
275void seatest_header_printer(char* s, int length, char f)
276{
277 int l = strlen(s);
278 int d = (length- (l + 2)) / 2;
279 int i;
280 if(seatest_is_display_only() || seatest_machine_readable) return;
281 for(i = 0; i<d; i++) printf("%c",f);
282 if(l==0) printf("%c%c", f, f);
283 else printf(" %s ", s);
284 for(i = (d+l+2); i<length; i++) printf("%c",f);
285 printf("\r\n");
286}
287
288
289void seatest_test_fixture_start(char* filepath)
290{
291 seatest_current_fixture_path = filepath;
292 seatest_current_fixture = test_file_name(filepath);
293 seatest_header_printer(seatest_current_fixture, seatest_screen_width, '-');
294 seatest_fixture_tests_failed = sea_tests_failed;
295 seatest_fixture_tests_run = sea_tests_run;
296 seatest_fixture_teardown = 0;
297 seatest_fixture_setup = 0;
298}
299
300void seatest_test_fixture_end()
301{
302 char s[SEATEST_PRINT_BUFFER_SIZE];
303 sprintf(s, "%d run %d failed", sea_tests_run-seatest_fixture_tests_run, sea_tests_failed-seatest_fixture_tests_failed);
304 seatest_header_printer(s, seatest_screen_width, ' ');
305 printf("\r\n");
306}
307
308static char* seatest_fixture_filter = 0;
309static char* seatest_test_filter = 0;
310
311void fixture_filter(char* filter)
312{
313 seatest_fixture_filter = filter;
314}
315
316
317void test_filter(char* filter)
318{
319 seatest_test_filter = filter;
320}
321
322void set_magic_marker(char* marker)
323{
324 if(marker == NULL) return;
325 strcpy(seatest_magic_marker, marker);
326}
327
328void seatest_display_test(char* fixture_name, char* test_name)
329{
330 if(test_name == NULL) return;
331 printf("%s,%s\r\n", fixture_name, test_name);
332}
333
334int seatest_should_run( char* fixture, char* test)
335{
336 int run = 1;
337 if(seatest_fixture_filter)
338 {
339 if(strncmp(seatest_fixture_filter, fixture, strlen(seatest_fixture_filter)) != 0) run = 0;
340 }
341 if(seatest_test_filter && test != NULL)
342 {
343 if(strncmp(seatest_test_filter, test, strlen(seatest_test_filter)) != 0) run = 0;
344 }
345
346 if(run && seatest_display_only)
347 {
348 seatest_display_test(fixture, test);
349 run = 0;
350 }
351 return run;
352}
353
354int run_tests(seatest_void_void tests)
355{
356 unsigned long long end;
357 unsigned long long start = GetTickCount();
358 char version[40];
359 char s[40];
360 tests();
361 end = GetTickCount();
362
363 if(seatest_is_display_only() || seatest_machine_readable) return 1;
364 sprintf(version, "SEATEST v%s", SEATEST_VERSION);
365 printf("\r\n\r\n");
366 seatest_header_printer(version, seatest_screen_width, '=');
367 printf("\r\n");
368 if (sea_tests_failed > 0) {
369 seatest_header_printer("Failed", seatest_screen_width, ' ');
370 }
371 else {
372 seatest_header_printer("ALL TESTS PASSED", seatest_screen_width, ' ');
373 }
374 sprintf(s,"%d tests run", sea_tests_run);
375 seatest_header_printer(s, seatest_screen_width, ' ');
376 sprintf(s,"in %llu micro-s",end - start);
377 seatest_header_printer(s, seatest_screen_width, ' ');
378 printf("\r\n");
379 seatest_header_printer("", seatest_screen_width, '=');
380
381 return sea_tests_failed == 0;
382}
383
384
385void seatest_show_help( void )
386{
387 printf("Usage: [-t <testname>] [-f <fixturename>] [-d] [help] [-v] [-m] [-k <marker>\r\n");
388 printf("Flags:\r\n");
389 printf("\thelp:\twill display this help\r\n");
390 printf("\t-t:\twill only run tests that match <testname>\r\n");
391 printf("\t-f:\twill only run fixtures that match <fixturename>\r\n");
392 printf("\t-d:\twill just display test names and fixtures without\r\n");
393 printf("\t-d:\trunning the test\r\n");
394 printf("\t-v:\twill print a more verbose version of the test run\r\n");
395 printf("\t-m:\twill print a machine readable format of the test run, ie :- \r\n");
396 printf("\t \t<textfixture>,<testname>,<linenumber>,<testresult><EOL>\r\n");
397 printf("\t-k:\twill prepend <marker> before machine readable output \r\n");
398 printf("\t \t<marker> cannot start with a '-'\r\n");
399}
400
401
402int seatest_commandline_has_value_after(seatest_testrunner_t* runner, int arg)
403{
404 if(!((arg+1) < runner->argc)) return 0;
405 if(runner->argv[arg+1][0]=='-') return 0;
406 return 1;
407}
408
409int seatest_parse_commandline_option_with_value(seatest_testrunner_t* runner, int arg, char* option, seatest_void_string setter)
410{
411 if(seatest_is_string_equal_i(runner->argv[arg], option))
412 {
413 if(!seatest_commandline_has_value_after(runner, arg))
414 {
415 printf("Error: The %s option expects to be followed by a value\r\n", option);
416 runner->action = SEATEST_DO_ABORT;
417 return 0;
418 }
419 setter(runner->argv[arg+1]);
420 return 1;
421 }
422 return 0;
423}
424
425void seatest_interpret_commandline(seatest_testrunner_t* runner)
426{
427 int arg;
428 for(arg=0; (arg < runner->argc) && (runner->action != SEATEST_DO_ABORT); arg++)
429 {
430 if(seatest_is_string_equal_i(runner->argv[arg], "help"))
431 {
432 seatest_show_help();
433 runner->action = SEATEST_DO_NOTHING;
434 return;
435 }
436 if(seatest_is_string_equal_i(runner->argv[arg], "-d")) runner->action = SEATEST_DISPLAY_TESTS;
437 if(seatest_is_string_equal_i(runner->argv[arg], "-v")) seatest_verbose = 1;
438 if(seatest_is_string_equal_i(runner->argv[arg], "-m")) seatest_machine_readable = 1;
439 if(seatest_parse_commandline_option_with_value(runner,arg,"-t", test_filter)) arg++;
440 if(seatest_parse_commandline_option_with_value(runner,arg,"-f", fixture_filter)) arg++;
441 if(seatest_parse_commandline_option_with_value(runner,arg,"-k", set_magic_marker)) arg++;
442 }
443}
444
445void seatest_testrunner_create(seatest_testrunner_t* runner, int argc, char** argv )
446{
447 runner->action = SEATEST_RUN_TESTS;
448 runner->argc = argc;
449 runner->argv = argv;
450 seatest_interpret_commandline(runner);
451}
452
453int seatest_testrunner(int argc, char** argv, seatest_void_void tests, seatest_void_void setup, seatest_void_void teardown)
454{
456 seatest_testrunner_create(&runner, argc, argv);
457 switch(runner.action)
458 {
459 case SEATEST_DISPLAY_TESTS:
460 {
461 seatest_display_only = 1;
462 run_tests(tests);
463 break;
464 }
465 case SEATEST_RUN_TESTS:
466 {
467 suite_setup(setup);
468 suite_teardown(teardown);
469 return run_tests(tests);
470 }
471 case SEATEST_DO_NOTHING:
472 case SEATEST_DO_ABORT:
473 default:
474 {
475 /* nothing to do, probably because there was an error which should of been already printed out. */
476 }
477 }
478 return 1;
479}
480
481#ifdef SEATEST_INTERNAL_TESTS
482void seatest_simple_test_result_nolog(int passed, char* reason, const char* function, unsigned int line)
483{
484 sea_test_last_passed = passed;
485}
486
487void seatest_assert_last_passed()
488{
489 assert_int_equal(1, sea_test_last_passed);
490}
491
492void seatest_assert_last_failed()
493{
494 assert_int_equal(0, sea_test_last_passed);
495}
496
497void seatest_disable_logging()
498{
499 seatest_simple_test_result = seatest_simple_test_result_nolog;
500}
501
502void seatest_enable_logging()
503{
504 seatest_simple_test_result = seatest_simple_test_result_log;
505}
506#endif