CCL: /home/chisarie/Documents/lsst_ccl/CCL/tests/ctest.h Source File

CCL

ctest.h
Go to the documentation of this file.
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
37 struct ctest {
38 const char* ssname; // suite name
39 const char* ttname; // test name
40 void (*run)();
41 int skip;
42
43 void* data;
44 SetupFunc setup;
45 TearDownFunc teardown;
46
47 unsigned int magic;
48 };
49
50 #define __FNAME(sname, tname) __ctest_##sname##_##tname##_run
51 #define __TNAME(sname, tname) __ctest_##sname##_##tname
52
53 #define __CTEST_MAGIC (0xdeadbeef)
54 #ifdef __APPLE__
55 #define __Test_Section __attribute__ ((used, section ("__DATA, .ctest")))
56 #else
57 #define __Test_Section __attribute__ ((used, section (".ctest")))
58 #endif
59
60 #define __CTEST_STRUCT(sname, tname, _skip, __data, __setup, __teardown) \
61 static struct ctest __TNAME(sname, tname) __Test_Section = { \
62 .ssname=#sname, \
63 .ttname=#tname, \
64 .run = __FNAME(sname, tname), \
65 .skip = _skip, \
66 .data = __data, \
67 .setup = (SetupFunc)__setup, \
68 .teardown = (TearDownFunc)__teardown, \
69 .magic = __CTEST_MAGIC };
70
71 #define CTEST_DATA(sname) struct sname##_data
72
73 #define CTEST_SETUP(sname) \
74 void WEAK sname##_setup(struct sname##_data* data)
75
76 #define CTEST_TEARDOWN(sname) \
77 void WEAK sname##_teardown(struct sname##_data* data)
78
79 #define __CTEST_INTERNAL(sname, tname, _skip) \
80 void __FNAME(sname, tname)(); \
81 __CTEST_STRUCT(sname, tname, _skip, NULL, NULL, NULL) \
82 void __FNAME(sname, tname)()
83
84 #ifdef __APPLE__
85 #define SETUP_FNAME(sname) NULL
86 #define TEARDOWN_FNAME(sname) NULL
87 #else
88 #define SETUP_FNAME(sname) sname##_setup
89 #define TEARDOWN_FNAME(sname) sname##_teardown
90 #endif
91
92 #define __CTEST2_INTERNAL(sname, tname, _skip) \
93 static struct sname##_data __ctest_##sname##_data; \
94 CTEST_SETUP(sname); \
95 CTEST_TEARDOWN(sname); \
96 void __FNAME(sname, tname)(struct sname##_data* data); \
97 __CTEST_STRUCT(sname, tname, _skip, &__ctest_##sname##_data, SETUP_FNAME(sname), TEARDOWN_FNAME(sname)) \
98 void __FNAME(sname, tname)(struct sname##_data* data)
99
100
101 void CTEST_LOG(const char* fmt, ...);
102 void CTEST_ERR(const char* fmt, ...); // doesn't return
103
104 #define CTEST(sname, tname) __CTEST_INTERNAL(sname, tname, 0)
105 #define CTEST_SKIP(sname, tname) __CTEST_INTERNAL(sname, tname, 1)
106
107 #define CTEST2(sname, tname) __CTEST2_INTERNAL(sname, tname, 0)
108 #define CTEST2_SKIP(sname, tname) __CTEST2_INTERNAL(sname, tname, 1)
109
110
111 void assert_str(const char* exp, const char* real, const char* caller, int line);
112 #define ASSERT_STR(exp, real) assert_str(exp, real, __FILE__, __LINE__)
113
114 void assert_data(const unsigned char* exp, size_t expsize,
115 const unsigned char* real, size_t realsize,
116 const char* caller, int line);
117 #define ASSERT_DATA(exp, expsize, real, realsize) \
118 assert_data(exp, expsize, real, realsize, __FILE__, __LINE__)
119
120 void assert_equal(intmax_t exp, intmax_t real, const char* caller, int line);
121 #define ASSERT_EQUAL(exp, real) assert_equal(exp, real, __FILE__, __LINE__)
122
123 void assert_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line);
124 #define ASSERT_EQUAL_U(exp, real) assert_equal_u(exp, real, __FILE__, __LINE__)
125
126 void assert_not_equal(intmax_t exp, intmax_t real, const char* caller, int line);
127 #define ASSERT_NOT_EQUAL(exp, real) assert_not_equal(exp, real, __FILE__, __LINE__)
128
129 void assert_not_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line);
130 #define ASSERT_NOT_EQUAL_U(exp, real) assert_not_equal_u(exp, real, __FILE__, __LINE__)
131
132 void assert_interval(intmax_t exp1, intmax_t exp2, intmax_t real, const char* caller, int line);
133 #define ASSERT_INTERVAL(exp1, exp2, real) assert_interval(exp1, exp2, real, __FILE__, __LINE__)
134
135 void assert_null(void* real, const char* caller, int line);
136 #define ASSERT_NULL(real) assert_null((void*)real, __FILE__, __LINE__)
137
138 void assert_not_null(const void* real, const char* caller, int line);
139 #define ASSERT_NOT_NULL(real) assert_not_null(real, __FILE__, __LINE__)
140
141 void assert_true(int real, const char* caller, int line);
142 #define ASSERT_TRUE(real) assert_true(real, __FILE__, __LINE__)
143
144 void assert_false(int real, const char* caller, int line);
145 #define ASSERT_FALSE(real) assert_false(real, __FILE__, __LINE__)
146
147 void assert_fail(const char* caller, int line);
148 #define ASSERT_FAIL() assert_fail(__FILE__, __LINE__)
149
150 void assert_dbl_near(double exp, double real, double tol, const char* caller, int line);
151 #define ASSERT_DBL_NEAR(exp, real) assert_dbl_near(exp, real, 1e-4, __FILE__, __LINE__)
152 #define ASSERT_DBL_NEAR_TOL(exp, real, tol) assert_dbl_near(exp, real, tol, __FILE__, __LINE__)
153
154 void assert_dbl_far(double exp, double real, double tol, const char* caller, int line);
155 #define ASSERT_DBL_FAR(exp, real) assert_dbl_far(exp, real, 1e-4, __FILE__, __LINE__)
156 #define ASSERT_DBL_FAR_TOL(exp, real, tol) assert_dbl_far(exp, real, tol, __FILE__, __LINE__)
157
158 #ifdef CTEST_MAIN
159
160 #include <setjmp.h>
161 #include <stdarg.h>
162 #include <stdio.h>
163 #include <string.h>
164 #include <sys/time.h>
165 #include <unistd.h>
166 #include <stdint.h>
167 #include <stdlib.h>
168
169 #ifdef __APPLE__
170 #include <dlfcn.h>
171 #endif
172
173 static size_t ctest_errorsize;
174 static char* ctest_errormsg;
175 #define MSG_SIZE 4096
176 static char ctest_errorbuffer[MSG_SIZE];
177 static jmp_buf ctest_err;
178 static int color_output = 1;
179 static const char* suite_name;
180
181 typedef int (*filter_func)(struct ctest*);
182
183 #define ANSI_BLACK "\033[0;30m"
184 #define ANSI_RED "\033[0;31m"
185 #define ANSI_GREEN "\033[0;32m"
186 #define ANSI_YELLOW "\033[0;33m"
187 #define ANSI_BLUE "\033[0;34m"
188 #define ANSI_MAGENTA "\033[0;35m"
189 #define ANSI_CYAN "\033[0;36m"
190 #define ANSI_GREY "\033[0;37m"
191 #define ANSI_DARKGREY "\033[01;30m"
192 #define ANSI_BRED "\033[01;31m"
193 #define ANSI_BGREEN "\033[01;32m"
194 #define ANSI_BYELLOW "\033[01;33m"
195 #define ANSI_BBLUE "\033[01;34m"
196 #define ANSI_BMAGENTA "\033[01;35m"
197 #define ANSI_BCYAN "\033[01;36m"
198 #define ANSI_WHITE "\033[01;37m"
199 #define ANSI_NORMAL "\033[0m"
200
201 static CTEST(suite, test) { }
202
203 inline static void vprint_errormsg(const char* const fmt, va_list ap) {
204 // (v)snprintf returns the number that would have been written
205 const int ret = vsnprintf(ctest_errormsg, ctest_errorsize, fmt, ap);
206 if (ret < 0) {
207 ctest_errormsg[0] = 0x00;
208 } else {
209 const size_t size = (size_t) ret;
210 const size_t s = (ctest_errorsize <= size ? size -ctest_errorsize : size);
211 // ctest_errorsize may overflow at this point
212 ctest_errorsize -= s;
213 ctest_errormsg += s;
214 }
215 }
216
217 inline static void print_errormsg(const char* const fmt, ...) {
218 va_list argp;
219 va_start(argp, fmt);
220 vprint_errormsg(fmt, argp);
221 va_end(argp);
222 }
223
224 static void msg_start(const char* color, const char* title) {
225 if (color_output) {
226 print_errormsg("%s", color);
227 }
228 print_errormsg(" %s: ", title);
229 }
230
231 static void msg_end() {
232 if (color_output) {
233 print_errormsg(ANSI_NORMAL);
234 }
235 print_errormsg("\n");
236 }
237
238 void CTEST_LOG(const char* fmt, ...)
239 {
240 va_list argp;
241 msg_start(ANSI_BLUE, "LOG");
242
243 va_start(argp, fmt);
244 vprint_errormsg(fmt, argp);
245 va_end(argp);
246
247 msg_end();
248 }
249
250 void CTEST_ERR(const char* fmt, ...)
251 {
252 va_list argp;
253 msg_start(ANSI_YELLOW, "ERR");
254
255 va_start(argp, fmt);
256 vprint_errormsg(fmt, argp);
257 va_end(argp);
258
259 msg_end();
260 longjmp(ctest_err, 1);
261 }
262
263 void assert_str(const char* exp, const char* real, const char* caller, int line) {
264 if ((exp == NULL && real != NULL) ||
265 (exp != NULL && real == NULL) ||
266 (exp && real && strcmp(exp, real) != 0)) {
267 CTEST_ERR("%s:%d expected '%s', got '%s'", caller, line, exp, real);
268 }
269 }
270
271 void assert_data(const unsigned char* exp, size_t expsize,
272 const unsigned char* real, size_t realsize,
273 const char* caller, int line) {
274 size_t i;
275 if (expsize != realsize) {
276 CTEST_ERR("%s:%d expected %" PRIuMAX " bytes, got %" PRIuMAX, caller, line, (uintmax_t) expsize, (uintmax_t) realsize);
277 }
278 for (i=0; i<expsize; i++) {
279 if (exp[i] != real[i]) {
280 CTEST_ERR("%s:%d expected 0x%02x at offset %" PRIuMAX " got 0x%02x",
281 caller, line, exp[i], (uintmax_t) i, real[i]);
282 }
283 }
284 }
285
286 void assert_equal(intmax_t exp, intmax_t real, const char* caller, int line) {
287 if (exp != real) {
288 CTEST_ERR("%s:%d expected %" PRIdMAX ", got %" PRIdMAX, caller, line, exp, real);
289 }
290 }
291
292 void assert_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line) {
293 if (exp != real) {
294 CTEST_ERR("%s:%d expected %" PRIuMAX ", got %" PRIuMAX, caller, line, exp, real);
295 }
296 }
297
298 void assert_not_equal(intmax_t exp, intmax_t real, const char* caller, int line) {
299 if ((exp) == (real)) {
300 CTEST_ERR("%s:%d should not be %" PRIdMAX, caller, line, real);
301 }
302 }
303
304 void assert_not_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line) {
305 if ((exp) == (real)) {
306 CTEST_ERR("%s:%d should not be %" PRIuMAX, caller, line, real);
307 }
308 }
309
310 void assert_interval(intmax_t exp1, intmax_t exp2, intmax_t real, const char* caller, int line) {
311 if (real < exp1 || real > exp2) {
312 CTEST_ERR("%s:%d expected %" PRIdMAX "-%" PRIdMAX ", got %" PRIdMAX, caller, line, exp1, exp2, real);
313 }
314 }
315
316 void assert_dbl_near(double exp, double real, double tol, const char* caller, int line) {
317 double diff = exp - real;
318 double absdiff = diff;
319 /* avoid using fabs and linking with a math lib */
320 if(diff < 0) {
321 absdiff *= -1;
322 }
323 if (absdiff > tol) {
324 CTEST_ERR("%s:%d expected %0.6e, got %0.6e (diff %0.6e, tol %0.6e)", caller, line, exp, real, diff, tol);
325 }
326 }
327
328 void assert_dbl_far(double exp, double real, double tol, const char* caller, int line) {
329 double diff = exp - real;
330 double absdiff = diff;
331 /* avoid using fabs and linking with a math lib */
332 if(diff < 0) {
333 absdiff *= -1;
334 }
335 if (absdiff <= tol) {
336 CTEST_ERR("%s:%d expected %0.6e, got %0.6e (diff %0.6e, tol %0.6e)", caller, line, exp, real, diff, tol);
337 }
338 }
339
340 void assert_null(void* real, const char* caller, int line) {
341 if ((real) != NULL) {
342 CTEST_ERR("%s:%d should be NULL", caller, line);
343 }
344 }
345
346 void assert_not_null(const void* real, const char* caller, int line) {
347 if (real == NULL) {
348 CTEST_ERR("%s:%d should not be NULL", caller, line);
349 }
350 }
351
352 void assert_true(int real, const char* caller, int line) {
353 if ((real) == 0) {
354 CTEST_ERR("%s:%d should be true", caller, line);
355 }
356 }
357
358 void assert_false(int real, const char* caller, int line) {
359 if ((real) != 0) {
360 CTEST_ERR("%s:%d should be false", caller, line);
361 }
362 }
363
364 void assert_fail(const char* caller, int line) {
365 CTEST_ERR("%s:%d shouldn't come here", caller, line);
366 }
367
368
369 static int suite_all(struct ctest* t) {
370 (void) t; // fix unused parameter warning
371 return 1;
372 }
373
374 static int suite_filter(struct ctest* t) {
375 return strncmp(suite_name, t->ssname, strlen(suite_name)) == 0;
376 }
377
378 static uint64_t getCurrentTime() {
379 struct timeval now;
380 gettimeofday(&now, NULL);
381 uint64_t now64 = (uint64_t) now.tv_sec;
382 now64 *= 1000000;
383 now64 += ((uint64_t) now.tv_usec);
384 return now64;
385 }
386
387 static void color_print(const char* color, const char* text) {
388 if (color_output)
389 printf("%s%s"ANSI_NORMAL"\n", color, text);
390 else
391 printf("%s\n", text);
392 }
393
394 #ifdef __APPLE__
395 static void *find_symbol(struct ctest *test, const char *fname)
396 {
397 size_t len = strlen(test->ssname) + 1 + strlen(fname);
398 char *symbol_name = (char *) malloc(len + 1);
399 memset(symbol_name, 0, len + 1);
400 snprintf(symbol_name, len + 1, "%s_%s", test->ssname, fname);
401
402 //fprintf(stderr, ">>>> dlsym: loading %s\n", symbol_name);
403 void *symbol = dlsym(RTLD_DEFAULT, symbol_name);
404 if (!symbol) {
405 //fprintf(stderr, ">>>> ERROR: %s\n", dlerror());
406 }
407 // returns NULL on error
408
409 free(symbol_name);
410 return symbol;
411 }
412 #endif
413
414 #ifdef CTEST_SEGFAULT
415 #include <signal.h>
416 static void sighandler(int signum)
417 {
418 char msg[128];
419 sprintf(msg, "[SIGNAL %d: %s]", signum, sys_siglist[signum]);
420 color_print(ANSI_BRED, msg);
421 fflush(stdout);
422
423 /* "Unregister" the signal handler and send the signal back to the process
424 * so it can terminate as expected */
425 signal(signum, SIG_DFL);
426 kill(getpid(), signum);
427 }
428 #endif
429
430 int ctest_main(int argc, const char *argv[])
431 {
432 static int total = 0;
433 static int num_ok = 0;
434 static int num_fail = 0;
435 static int num_skip = 0;
436 static int index = 1;
437 static filter_func filter = suite_all;
438
439 #ifdef CTEST_SEGFAULT
440 signal(SIGSEGV, sighandler);
441 #endif
442
443 if (argc == 2) {
444 suite_name = argv[1];
445 filter = suite_filter;
446 }
447 #ifdef CTEST_NO_COLORS
448 color_output = 0;
449 #else
450 color_output = isatty(1);
451 #endif
452 uint64_t t1 = getCurrentTime();
453
454 struct ctest* ctest_begin = &__TNAME(suite, test);
455 struct ctest* ctest_end = &__TNAME(suite, test);
456 // find begin and end of section by comparing magics
457 while (1) {
458 struct ctest* t = ctest_begin-1;
459 if (t->magic != __CTEST_MAGIC) break;
460 ctest_begin--;
461 }
462 while (1) {
463 struct ctest* t = ctest_end+1;
464 if (t->magic != __CTEST_MAGIC) break;
465 ctest_end++;
466 }
467 ctest_end++; // end after last one
468
469 static struct ctest* test;
470 for (test = ctest_begin; test != ctest_end; test++) {
471 if (test == &__TNAME(suite, test)) continue;
472 if (filter(test)) total++;
473 }
474
475 for (test = ctest_begin; test != ctest_end; test++) {
476 if (test == &__TNAME(suite, test)) continue;
477 if (filter(test)) {
478 ctest_errorbuffer[0] = 0;
479 ctest_errorsize = MSG_SIZE-1;
480 ctest_errormsg = ctest_errorbuffer;
481 printf("TEST %d/%d %s:%s ", index, total, test->ssname, test->ttname);
482 fflush(stdout);
483 if (test->skip) {
484 color_print(ANSI_BYELLOW, "[SKIPPED]");
485 num_skip++;
486 } else {
487 int result = setjmp(ctest_err);
488 if (result == 0) {
489 #ifdef __APPLE__
490 if (!test->setup) {
491 test->setup = (SetupFunc) find_symbol(test, "setup");
492 }
493 if (!test->teardown) {
494 test->teardown = (TearDownFunc) find_symbol(test, "teardown");
495 }
496 #endif
497
498 if (test->setup) test->setup(test->data);
499 if (test->data)
500 test->run(test->data);
501 else
502 test->run();
503 if (test->teardown) test->teardown(test->data);
504 // if we got here it's ok
505 #ifdef CTEST_COLOR_OK
506 color_print(ANSI_BGREEN, "[OK]");
507 #else
508 printf("[OK]\n");
509 #endif
510 num_ok++;
511 } else {
512 color_print(ANSI_BRED, "[FAIL]");
513 num_fail++;
514 }
515 if (ctest_errorsize != MSG_SIZE-1) printf("%s", ctest_errorbuffer);
516 }
517 index++;
518 }
519 }
520 uint64_t t2 = getCurrentTime();
521
522 const char* color = (num_fail) ? ANSI_BRED : ANSI_GREEN;
523 char results[80];
524 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);
525 color_print(color, results);
526 return num_fail;
527 }
528
529 #endif
530
531 #endif
532
ctest::run
void(* run)()
Definition: ctest.h:40
assert_equal
void assert_equal(intmax_t exp, intmax_t real, const char *caller, int line)
CTEST
#define CTEST(sname, tname)
Definition: ctest.h:104
assert_dbl_near
void assert_dbl_near(double exp, double real, double tol, const char *caller, int line)
CTEST_LOG
void CTEST_LOG(const char *fmt,...)
assert_data
void assert_data(const unsigned char *exp, size_t expsize, const unsigned char *real, size_t realsize, const char *caller, int line)
assert_not_equal
void assert_not_equal(intmax_t exp, intmax_t real, const char *caller, int line)
assert_null
void assert_null(void *real, const char *caller, int line)
assert_dbl_far
void assert_dbl_far(double exp, double real, double tol, const char *caller, int line)
__TNAME
#define __TNAME(sname, tname)
Definition: ctest.h:51
TearDownFunc
void(* TearDownFunc)(void *)
Definition: ctest.h:35
ctest
Definition: ctest.h:37
assert_interval
void assert_interval(intmax_t exp1, intmax_t exp2, intmax_t real, const char *caller, int line)
ctest::teardown
TearDownFunc teardown
Definition: ctest.h:45
assert_equal_u
void assert_equal_u(uintmax_t exp, uintmax_t real, const char *caller, int line)
ctest::magic
unsigned int magic
Definition: ctest.h:47
assert_str
void assert_str(const char *exp, const char *real, const char *caller, int line)
__CTEST_MAGIC
#define __CTEST_MAGIC
Definition: ctest.h:53
assert_false
void assert_false(int real, const char *caller, int line)
ctest::data
void * data
Definition: ctest.h:43
assert_not_equal_u
void assert_not_equal_u(uintmax_t exp, uintmax_t real, const char *caller, int line)
assert_true
void assert_true(int real, const char *caller, int line)
ctest::setup
SetupFunc setup
Definition: ctest.h:44
ctest::ssname
const char * ssname
Definition: ctest.h:38
ctest::ttname
const char * ttname
Definition: ctest.h:39
assert_fail
void assert_fail(const char *caller, int line)
ctest::skip
int skip
Definition: ctest.h:41
CTEST_ERR
void CTEST_ERR(const char *fmt,...)
assert_not_null
void assert_not_null(const void *real, const char *caller, int line)
SetupFunc
void(* SetupFunc)(void *)
Definition: ctest.h:34