Update dgemm_kernel_4x8_haswell.S
[platform/upstream/openblas.git] / utest / ctest.h
1 /* Copyright 2011-2016 Bas van den Berg
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #ifndef CTEST_H
17 #define CTEST_H
18
19 #if defined _WIN32 || defined __CYGWIN__
20 #ifndef WIN32
21 #define WIN32
22 #endif
23 #endif
24
25 #ifndef WIN32
26 #define WEAK __attribute__ ((weak))
27 #else
28 #define WEAK
29 #endif
30
31 #include <inttypes.h> /* intmax_t, uintmax_t, PRI* */
32 #include <stddef.h> /* size_t */
33
34 typedef void (*SetupFunc)(void*);
35 typedef void (*TearDownFunc)(void*);
36 typedef void (*RunWithDataFunc)(void*);
37
38 struct ctest {
39     const char* ssname;  // suite name
40     const char* ttname;  // test name
41     void (*run)();
42     int skip;
43
44     void* data;
45     SetupFunc setup;
46     TearDownFunc teardown;
47
48     struct ctest *next;
49
50     unsigned int magic;
51 };
52
53 #define __FNAME(sname, tname) __ctest_##sname##_##tname##_run
54 #define __TNAME(sname, tname) __ctest_##sname##_##tname
55 #define __PNAME(sname, tname) __ctest_##sname##_##tname##_pointer
56
57 #ifdef __APPLE__
58 #define __CTEST_APPLE
59 #endif
60
61 #ifdef __MINGW32__
62 #undef CTEST_SEGFAULT
63 #endif
64
65 #if defined(_WIN32) && defined(_MSC_VER)
66 #define __CTEST_MSVC
67 #endif
68
69 //config for MSVC compiler
70 #ifdef __CTEST_MSVC
71
72 #define __CTEST_NO_TIME
73 #define CTEST_NO_COLORS
74
75 #ifndef CTEST_ADD_TESTS_MANUALLY
76 #pragma section(".ctest$a")
77 #pragma section(".ctest$u")
78 #pragma section(".ctest$z")
79 #endif
80
81 //clear this flag for msvc
82 #ifdef CTEST_SEGFAULT
83 #undef CTEST_SEGFAULT
84 #endif
85
86 #ifndef __cplusplus
87 #define inline __inline
88 #endif
89 #endif
90
91 #ifdef CTEST_NO_JMP
92 #define __CTEST_NO_JMP
93 #endif
94
95 #define __CTEST_MAGIC (0xdeadbeef)
96
97 #ifdef CTEST_ADD_TESTS_MANUALLY
98 # define __Test_Section
99 #else
100 #ifdef __CTEST_APPLE
101 #define __Test_Section __attribute__ ((used, section ("__DATA, .ctest")))
102 #elif defined (__CTEST_MSVC)
103 #define __Test_Section __declspec( allocate(".ctest$u"))
104 #else
105 #define __Test_Section __attribute__ ((used, section (".ctest")))
106 #endif
107 #endif
108
109 #ifndef __CTEST_MSVC
110 #define __CTEST_STRUCT(sname, tname, _skip, __data, __setup, __teardown) \
111     static struct ctest __TNAME(sname, tname)  = { \
112         .ssname=#sname, \
113         .ttname=#tname, \
114         .run = __FNAME(sname, tname), \
115         .skip = _skip, \
116         .data = __data, \
117         .setup = (SetupFunc)__setup,                                    \
118         .teardown = (TearDownFunc)__teardown,                           \
119         .next =  NULL, \
120         .magic = __CTEST_MAGIC}; \
121     static void * __PNAME(sname, tname)[2] __Test_Section = {(void*)& __TNAME(sname,tname), (void*)__CTEST_MAGIC};
122 #else
123 //for msvc
124 #define __CTEST_STRUCT(sname, tname, _skip, __data, __setup, __teardown) \
125     static struct ctest __TNAME(sname, tname) = { \
126          #sname, \
127          #tname, \
128          __FNAME(sname, tname), \
129          _skip, \
130          __data, \
131          (SetupFunc)__setup, \
132          (TearDownFunc)__teardown, \
133          NULL, \
134          __CTEST_MAGIC}; \
135     __Test_Section static void * __PNAME(sname, tname)[2]= {(void*)& __TNAME(sname,tname), (void *)__CTEST_MAGIC}; 
136 #endif
137
138 #define CTEST_DATA(sname) struct sname##_data
139
140 #define CTEST_SETUP(sname) \
141     void WEAK sname##_setup(struct sname##_data* data)
142
143 #define CTEST_TEARDOWN(sname) \
144     void WEAK sname##_teardown(struct sname##_data* data)
145
146 #define __CTEST_INTERNAL(sname, tname, _skip) \
147     void __FNAME(sname, tname)(); \
148     __CTEST_STRUCT(sname, tname, _skip, NULL, NULL, NULL) \
149     void __FNAME(sname, tname)()
150
151 #ifdef __CTEST_APPLE
152 #define SETUP_FNAME(sname) NULL
153 #define TEARDOWN_FNAME(sname) NULL
154 #else
155 #define SETUP_FNAME(sname) sname##_setup
156 #define TEARDOWN_FNAME(sname) sname##_teardown
157 #endif
158
159 #define __CTEST2_INTERNAL(sname, tname, _skip) \
160     static struct sname##_data  __ctest_##sname##_data; \
161     CTEST_SETUP(sname); \
162     CTEST_TEARDOWN(sname); \
163     void __FNAME(sname, tname)(struct sname##_data* data); \
164     __CTEST_STRUCT(sname, tname, _skip, &__ctest_##sname##_data, SETUP_FNAME(sname), TEARDOWN_FNAME(sname)) \
165     void __FNAME(sname, tname)(struct sname##_data* data)
166
167
168 void CTEST_LOG(const char* fmt, ...);
169 void CTEST_ERR(const char* fmt, ...);  // doesn't return
170
171 #define CTEST(sname, tname) __CTEST_INTERNAL(sname, tname, 0)
172 #define CTEST_SKIP(sname, tname) __CTEST_INTERNAL(sname, tname, 1)
173
174 #define CTEST2(sname, tname) __CTEST2_INTERNAL(sname, tname, 0)
175 #define CTEST2_SKIP(sname, tname) __CTEST2_INTERNAL(sname, tname, 1)
176
177
178 #ifdef CTEST_ADD_TESTS_MANUALLY
179
180 void __ctest_addTest(struct ctest *);
181
182 #define CTEST_ADD(sname, tname) do { \
183     extern struct ctest __TNAME(sname, tname); \
184     __ctest_addTest(&__TNAME(sname, tname)); \
185 } while (0)
186
187 #define CTEST_ADD2(sname, tname) do { \
188     extern struct ctest __TNAME(sname, tname); \
189     __ctest_addTest(&__TNAME(sname, tname)); \
190 } while (0)
191
192 #endif // CTEST_ADD_TESTS_MANUALLY
193
194 void assert_str(const char* exp, const char* real, const char* caller, int line);
195 #define ASSERT_STR(exp, real) assert_str(exp, real, __FILE__, __LINE__)
196
197 void assert_data(const unsigned char* exp, size_t expsize,
198                  const unsigned char* real, size_t realsize,
199                  const char* caller, int line);
200 #define ASSERT_DATA(exp, expsize, real, realsize) \
201     assert_data(exp, expsize, real, realsize, __FILE__, __LINE__)
202
203 void assert_equal(intmax_t exp, intmax_t real, const char* caller, int line);
204 #define ASSERT_EQUAL(exp, real) assert_equal(exp, real, __FILE__, __LINE__)
205
206 void assert_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line);
207 #define ASSERT_EQUAL_U(exp, real) assert_equal_u(exp, real, __FILE__, __LINE__)
208
209 void assert_not_equal(intmax_t exp, intmax_t real, const char* caller, int line);
210 #define ASSERT_NOT_EQUAL(exp, real) assert_not_equal(exp, real, __FILE__, __LINE__)
211
212 void assert_not_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line);
213 #define ASSERT_NOT_EQUAL_U(exp, real) assert_not_equal_u(exp, real, __FILE__, __LINE__)
214
215 void assert_interval(intmax_t exp1, intmax_t exp2, intmax_t real, const char* caller, int line);
216 #define ASSERT_INTERVAL(exp1, exp2, real) assert_interval(exp1, exp2, real, __FILE__, __LINE__)
217
218 void assert_null(void* real, const char* caller, int line);
219 #define ASSERT_NULL(real) assert_null((void*)real, __FILE__, __LINE__)
220
221 void assert_not_null(const void* real, const char* caller, int line);
222 #define ASSERT_NOT_NULL(real) assert_not_null(real, __FILE__, __LINE__)
223
224 void assert_true(int real, const char* caller, int line);
225 #define ASSERT_TRUE(real) assert_true(real, __FILE__, __LINE__)
226
227 void assert_false(int real, const char* caller, int line);
228 #define ASSERT_FALSE(real) assert_false(real, __FILE__, __LINE__)
229
230 void assert_fail(const char* caller, int line);
231 #define ASSERT_FAIL() assert_fail(__FILE__, __LINE__)
232
233 /* If longjmp() is not available, integer flag will be used instead of jmp_buf.
234  *
235  * __CTEST_SETJMP() will clear the flag and return zero, and __CTEST_LONGJMP()
236  * will set the flag to its argument. __CTEST_ERROR_CODE() will return that flag.
237  *
238  * If longjmp() is available, jmp_buf will be used as usual and __CTEST_ERROR_CODE()
239  * will always return zero.
240  *
241  * You can check both __CTEST_SETJMP() and __CTEST_ERROR_CODE() return value
242  * to detect error in a portable way.
243  */
244 #ifdef __CTEST_NO_JMP
245 # define __CTEST_JMPBUF                 int
246 # define __CTEST_ERROR_CODE(_var)       (_var)
247 # define __CTEST_SETJMP(_var)           (_var = 0)
248 # define __CTEST_LONGJMP(_var, _err)    (_var = _err)
249 #else // !__CTEST_NO_JMP
250 # define __CTEST_JMPBUF                 jmp_buf
251 # define __CTEST_ERROR_CODE(_var)       (0)
252 # define __CTEST_SETJMP(_var)           setjmp(_var)
253 # define __CTEST_LONGJMP(_var, _err)    longjmp(_var, _err)
254 #endif // __CTEST_NO_JMP
255
256 void assert_dbl_near(double exp, double real, double tol, const char* caller, int line);
257 #define ASSERT_DBL_NEAR(exp, real) assert_dbl_near(exp, real, 1e-4, __FILE__, __LINE__)
258 #define ASSERT_DBL_NEAR_TOL(exp, real, tol) assert_dbl_near(exp, real, tol, __FILE__, __LINE__)
259
260 void assert_dbl_far(double exp, double real, double tol, const char* caller, int line);
261 #define ASSERT_DBL_FAR(exp, real) assert_dbl_far(exp, real, 1e-4, __FILE__, __LINE__)
262 #define ASSERT_DBL_FAR_TOL(exp, real, tol) assert_dbl_far(exp, real, tol, __FILE__, __LINE__)
263
264 #ifdef CTEST_MAIN
265
266 #ifndef __CTEST_NO_JMP
267 #include <setjmp.h>
268 #endif
269
270 #include <stdarg.h>
271 #include <stdio.h>
272 #include <string.h>
273
274 #ifndef __CTEST_NO_TIME
275 #include <sys/time.h>
276 #endif
277 #include <stdint.h>
278
279 #ifdef __CTEST_MSVC
280 #include <io.h>
281 #else
282 #include <unistd.h>
283 #endif
284
285 #include <stdlib.h>
286
287 #ifdef __CTEST_APPLE
288 #include <dlfcn.h>
289 #endif
290
291 static size_t ctest_errorsize;
292 static char* ctest_errormsg;
293 #define MSG_SIZE 4096
294 static char ctest_errorbuffer[MSG_SIZE];
295 static __CTEST_JMPBUF ctest_err;
296 static int color_output = 1;
297 static const char* suite_name;
298 static const char* test_name;
299
300 typedef int (*filter_func)(struct ctest*);
301
302 #define ANSI_BLACK    "\033[0;30m"
303 #define ANSI_RED      "\033[0;31m"
304 #define ANSI_GREEN    "\033[0;32m"
305 #define ANSI_YELLOW   "\033[0;33m"
306 #define ANSI_BLUE     "\033[0;34m"
307 #define ANSI_MAGENTA  "\033[0;35m"
308 #define ANSI_CYAN     "\033[0;36m"
309 #define ANSI_GREY     "\033[0;37m"
310 #define ANSI_DARKGREY "\033[01;30m"
311 #define ANSI_BRED     "\033[01;31m"
312 #define ANSI_BGREEN   "\033[01;32m"
313 #define ANSI_BYELLOW  "\033[01;33m"
314 #define ANSI_BBLUE    "\033[01;34m"
315 #define ANSI_BMAGENTA "\033[01;35m"
316 #define ANSI_BCYAN    "\033[01;36m"
317 #define ANSI_WHITE    "\033[01;37m"
318 #define ANSI_NORMAL   "\033[0m"
319
320 #ifdef __CTEST_MSVC
321 #ifndef CTEST_ADD_TESTS_MANUALLY
322 __declspec(allocate(".ctest$a")) struct ctest * ctest_win_begin;
323 __declspec(allocate(".ctest$z")) struct ctest * ctest_win_end;
324 #endif
325 #endif
326
327 static CTEST(suite, test) { }
328
329 #define __CTEST_POINTER_NEXT(_test) (struct ctest **)((struct ctest **)(_test) + 2)
330 #define __CTEST_POINTER_PREV(_test) (struct ctest **)((struct ctest **)(_test) - 2)
331
332 /* First element of test list.
333  */
334 static struct ctest * * __ctest_head_p = (struct ctest **)__PNAME(suite, test);
335
336 #ifdef CTEST_ADD_TESTS_MANUALLY
337
338 /* Last element of test list.
339  */
340 static struct ctest *__ctest_tail = &__TNAME(suite, test);
341
342 /* Add test to linked list manually.
343  */
344 void __ctest_addTest(struct ctest *test)
345 {
346     __ctest_tail->next = test;
347     __ctest_tail = test;
348 }
349 #else // !CTEST_ADD_TESTS_MANUALLY
350
351 #ifndef __CTEST_MSVC
352 /* Add all tests to linked list automatically.
353  */
354 static void __ctest_linkTests()
355 {
356     struct ctest ** test;
357     struct ctest ** ctest_begin = (struct ctest **)__PNAME(suite, test);
358     struct ctest ** ctest_end = (struct ctest **)__PNAME(suite, test);
359
360     // find begin and end of section by comparing magics
361     while (1) {
362         struct ctest** t = __CTEST_POINTER_PREV(ctest_begin);
363         if (t[0] == NULL) break;
364         if (t[1] != (struct ctest*)__CTEST_MAGIC) break;
365         ctest_begin = t;
366     }
367     while (1) {
368         struct ctest** t = __CTEST_POINTER_NEXT(ctest_end);
369         if (t[0] == NULL) break;
370         if (t[1] != (struct ctest*)__CTEST_MAGIC) break;
371         ctest_end = t;
372     }
373     ctest_end = __CTEST_POINTER_NEXT(ctest_end); // end after last one
374
375     for (test = ctest_begin; test != ctest_end; test = __CTEST_POINTER_NEXT(test)) {
376         struct ctest ** next_p = __CTEST_POINTER_NEXT(test);
377         struct ctest * next;
378         if (next_p == ctest_end)
379             next = NULL;
380         else
381             next = next_p[0];
382
383         (*test)->next = next;
384     }
385
386     __ctest_head_p = ctest_begin;
387 }
388 #else //for msvc
389 static void __ctest_linkTests()
390 {
391     struct ctest ** ctest_start = __ctest_head_p;
392     struct ctest ** test;
393     struct ctest * cur=ctest_start[0];
394
395     for(test=&ctest_win_begin; test!=&ctest_win_end; test++){
396       //check
397       if(test[1] == (struct ctest*)__CTEST_MAGIC){
398         //skip the start
399         if((test[0]) == ctest_start[0]) continue;
400         
401         cur->next = test[0];
402         cur=cur->next;
403         cur->next=NULL;
404       }
405     }
406 }
407 #endif
408 #endif
409
410 inline static void vprint_errormsg(const char* const fmt, va_list ap) {
411         // (v)snprintf returns the number that would have been written
412     const int ret = vsnprintf(ctest_errormsg, ctest_errorsize, fmt, ap);
413     if (ret < 0) {
414                 ctest_errormsg[0] = 0x00;
415     } else {
416         const size_t size = (size_t) ret;
417         const size_t s = (ctest_errorsize <= size ? size -ctest_errorsize : size);
418         // ctest_errorsize may overflow at this point
419                 ctest_errorsize -= s;
420                 ctest_errormsg += s;
421     }
422 }
423
424 inline static void print_errormsg(const char* const fmt, ...) {
425     va_list argp;
426     va_start(argp, fmt);
427     vprint_errormsg(fmt, argp);
428     va_end(argp);
429 }
430
431 static void msg_start(const char* color, const char* title) {
432     if (color_output) {
433         print_errormsg("%s", color);
434     }
435     print_errormsg("  %s: ", title);
436 }
437
438 static void msg_end() {
439     if (color_output) {
440         print_errormsg(ANSI_NORMAL);
441     }
442     print_errormsg("\n");
443 }
444
445 void CTEST_LOG(const char* fmt, ...)
446 {
447     va_list argp;
448     msg_start(ANSI_BLUE, "LOG");
449
450     va_start(argp, fmt);
451     vprint_errormsg(fmt, argp);
452     va_end(argp);
453
454     msg_end();
455 }
456
457 void CTEST_ERR(const char* fmt, ...)
458 {
459     va_list argp;
460     msg_start(ANSI_YELLOW, "ERR");
461
462     va_start(argp, fmt);
463     vprint_errormsg(fmt, argp);
464     va_end(argp);
465
466     msg_end();
467     __CTEST_LONGJMP(ctest_err, 1);
468 }
469
470 void assert_str(const char* exp, const char*  real, const char* caller, int line) {
471     if ((exp == NULL && real != NULL) ||
472         (exp != NULL && real == NULL) ||
473         (exp && real && strcmp(exp, real) != 0)) {
474         CTEST_ERR("%s:%d  expected '%s', got '%s'", caller, line, exp, real);
475     }
476 }
477
478 void assert_data(const unsigned char* exp, size_t expsize,
479                  const unsigned char* real, size_t realsize,
480                  const char* caller, int line) {
481     size_t i;
482     if (expsize != realsize) {
483         CTEST_ERR("%s:%d  expected %" PRIuMAX " bytes, got %" PRIuMAX, caller, line, (uintmax_t) expsize, (uintmax_t) realsize);
484     }
485     for (i=0; i<expsize; i++) {
486         if (exp[i] != real[i]) {
487             CTEST_ERR("%s:%d expected 0x%02x at offset %" PRIuMAX " got 0x%02x",
488                 caller, line, exp[i], (uintmax_t) i, real[i]);
489         }
490     }
491 }
492
493 void assert_equal(intmax_t exp, intmax_t real, const char* caller, int line) {
494     if (exp != real) {
495         CTEST_ERR("%s:%d  expected %" PRIdMAX ", got %" PRIdMAX, caller, line, exp, real);
496     }
497 }
498
499 void assert_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line) {
500     if (exp != real) {
501         CTEST_ERR("%s:%d  expected %" PRIuMAX ", got %" PRIuMAX, caller, line, exp, real);
502     }
503 }
504
505 void assert_not_equal(intmax_t exp, intmax_t real, const char* caller, int line) {
506     if ((exp) == (real)) {
507         CTEST_ERR("%s:%d  should not be %" PRIdMAX, caller, line, real);
508     }
509 }
510
511 void assert_not_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line) {
512     if ((exp) == (real)) {
513         CTEST_ERR("%s:%d  should not be %" PRIuMAX, caller, line, real);
514     }
515 }
516
517 void assert_interval(intmax_t exp1, intmax_t exp2, intmax_t real, const char* caller, int line) {
518     if (real < exp1 || real > exp2) {
519         CTEST_ERR("%s:%d  expected %" PRIdMAX "-%" PRIdMAX ", got %" PRIdMAX, caller, line, exp1, exp2, real);
520     }
521 }
522
523 void assert_dbl_near(double exp, double real, double tol, const char* caller, int line) {
524     double diff = exp - real;
525     double absdiff = diff;
526     /* avoid using fabs and linking with a math lib */
527     if(diff < 0) {
528       absdiff *= -1;
529     }
530     if (absdiff > tol) {
531         CTEST_ERR("%s:%d  expected %0.3e, got %0.3e (diff %0.3e, tol %0.3e)", caller, line, exp, real, diff, tol);
532     }
533 }
534
535 void assert_dbl_far(double exp, double real, double tol, const char* caller, int line) {
536     double diff = exp - real;
537     double absdiff = diff;
538     /* avoid using fabs and linking with a math lib */
539     if(diff < 0) {
540       absdiff *= -1;
541     }
542     if (absdiff <= tol) {
543         CTEST_ERR("%s:%d  expected %0.3e, got %0.3e (diff %0.3e, tol %0.3e)", caller, line, exp, real, diff, tol);
544     }
545 }
546
547 void assert_null(void* real, const char* caller, int line) {
548     if ((real) != NULL) {
549         CTEST_ERR("%s:%d  should be NULL", caller, line);
550     }
551 }
552
553 void assert_not_null(const void* real, const char* caller, int line) {
554     if (real == NULL) {
555         CTEST_ERR("%s:%d  should not be NULL", caller, line);
556     }
557 }
558
559 void assert_true(int real, const char* caller, int line) {
560     if ((real) == 0) {
561         CTEST_ERR("%s:%d  should be true", caller, line);
562     }
563 }
564
565 void assert_false(int real, const char* caller, int line) {
566     if ((real) != 0) {
567         CTEST_ERR("%s:%d  should be false", caller, line);
568     }
569 }
570
571 void assert_fail(const char* caller, int line) {
572     CTEST_ERR("%s:%d  shouldn't come here", caller, line);
573 }
574
575
576 static int suite_all(struct ctest* t) {
577     (void) t; // fix unused parameter warning
578     return 1;
579 }
580
581 static int suite_filter(struct ctest* t) {
582     return strncmp(suite_name, t->ssname, strlen(suite_name)) == 0;
583 }
584
585 static int suite_test_filter(struct ctest* t) {
586   int suit_match, test_match;
587   suit_match=(strncmp(suite_name, t->ssname, strlen(suite_name)) == 0);
588   test_match=(strncmp(test_name, t->ttname, strlen(test_name)) == 0);
589   return (suit_match & test_match);
590 }
591
592
593 #ifndef __CTEST_NO_TIME
594 static uint64_t getCurrentTime() {
595     struct timeval now;
596     gettimeofday(&now, NULL);
597     uint64_t now64 = (uint64_t) now.tv_sec;
598     now64 *= 1000000;
599     now64 += ((uint64_t) now.tv_usec);
600     return now64;
601 }
602 #endif
603
604 static void color_print(const char* color, const char* text) {
605     if (color_output)
606         printf("%s%s"ANSI_NORMAL"\n", color, text);
607     else
608         printf("%s\n", text);
609 }
610
611 #ifdef __CTEST_APPLE
612 static void *find_symbol(struct ctest *test, const char *fname)
613 {
614     size_t len = strlen(test->ssname) + 1 + strlen(fname);
615     char *symbol_name = (char *) malloc(len + 1);
616     memset(symbol_name, 0, len + 1);
617     snprintf(symbol_name, len + 1, "%s_%s", test->ssname, fname);
618
619     //fprintf(stderr, ">>>> dlsym: loading %s\n", symbol_name);
620     void *symbol = dlsym(RTLD_DEFAULT, symbol_name);
621     if (!symbol) {
622         //fprintf(stderr, ">>>> ERROR: %s\n", dlerror());
623     }
624     // returns NULL on error
625
626     free(symbol_name);
627     return symbol;
628 }
629 #endif
630
631 #ifdef CTEST_SEGFAULT
632 #include <signal.h>
633 static void sighandler(int signum)
634 {
635     char msg[128];
636     snprintf(msg, sizeof(msg), "[SIGNAL %d: %s]", signum, strsignal(signum));
637     color_print(ANSI_BRED, msg);
638     fflush(stdout);
639
640     /* "Unregister" the signal handler and send the signal back to the process
641      * so it can terminate as expected */
642     signal(signum, SIG_DFL);
643     kill(getpid(), signum);
644 }
645 #endif
646
647 int ctest_main(int argc, const char *argv[])
648 {
649     static int total = 0;
650     static int num_ok = 0;
651     static int num_fail = 0;
652     static int num_skip = 0;
653     static int index = 1;
654     static filter_func filter = suite_all;
655
656     const char* color = (num_fail) ? ANSI_BRED : ANSI_GREEN;
657     char results[80];
658     static struct ctest* test;
659
660 #ifdef CTEST_SEGFAULT
661     signal(SIGSEGV, sighandler);
662 #endif
663
664     if (argc == 2) {
665         suite_name = argv[1];
666         filter = suite_filter;
667     }else if (argc == 3) {
668         suite_name = argv[1];
669         test_name = argv[2];
670         filter = suite_test_filter;
671     }
672
673 #ifdef CTEST_NO_COLORS
674     color_output = 0;
675 #else
676     color_output = isatty(1);
677 #endif
678
679 #ifndef __CTEST_NO_TIME
680     uint64_t t1 = getCurrentTime();
681 #endif
682
683 #ifndef CTEST_ADD_TESTS_MANUALLY
684     __ctest_linkTests();
685 #endif
686
687
688     for (test = *(__ctest_head_p); test != NULL; test=test->next) {
689         if (test == &__ctest_suite_test) continue;
690         if (filter(test)) total++;
691     }
692
693     for (test = *(__ctest_head_p); test != NULL; test=test->next) {
694         if (test == &__ctest_suite_test) continue;
695         if (filter(test)) {
696             ctest_errorbuffer[0] = 0;
697             ctest_errorsize = MSG_SIZE-1;
698             ctest_errormsg = ctest_errorbuffer;
699             printf("TEST %d/%d %s:%s ", index, total, test->ssname, test->ttname);
700             fflush(stdout);
701             if (test->skip) {
702                 color_print(ANSI_BYELLOW, "[SKIPPED]");
703                 num_skip++;
704             } else {
705                 int result = __CTEST_SETJMP(ctest_err);
706                 if (result == 0) {
707 #ifdef __CTEST_APPLE
708                     if (!test->setup) {
709                         test->setup = (SetupFunc) find_symbol(test, "setup");
710                     }
711                     if (!test->teardown) {
712                         test->teardown = (TearDownFunc) find_symbol(test, "teardown");
713                     }
714 #endif
715
716                     if (test->setup) test->setup(test->data);
717                     if (test->data)
718                       ((RunWithDataFunc)test->run)(test->data);
719                     else
720                         test->run();
721                     if (test->teardown) test->teardown(test->data);
722                     // if we got here it's ok
723 #ifdef CTEST_COLOR_OK
724                     color_print(ANSI_BGREEN, "[OK]");
725 #else
726                     printf("[OK]\n");
727 #endif
728                     num_ok++;
729                 } else {
730                     color_print(ANSI_BRED, "[FAIL]");
731                     num_fail++;
732                 }
733                 if (ctest_errorsize != MSG_SIZE-1) printf("%s", ctest_errorbuffer);
734             }
735             index++;
736         }
737     }
738 #ifndef __CTEST_NO_TIME
739     uint64_t t2 = getCurrentTime();
740 #endif
741
742 #ifndef __CTEST_NO_TIME
743     sprintf(results, "RESULTS: %d tests (%d ok, %d failed, %d skipped) ran in %"PRIu64" ms", total, num_ok, num_fail, num_skip, (t2 - t1)/1000);
744 #else
745     sprintf(results, "RESULTS: %d tests (%d ok, %d failed, %d skipped)", total, num_ok, num_fail, num_skip);
746 #endif
747     color_print(color, results);
748     return num_fail;
749 }
750
751 #endif
752
753 #endif
754