ctest.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /* Copyright 2011-2018 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. #ifndef CTEST_H
  16. #define CTEST_H
  17. #ifdef __GNUC__
  18. #define CTEST_IMPL_FORMAT_PRINTF(a, b) __attribute__ ((format(printf, a, b)))
  19. #else
  20. #define CTEST_IMPL_FORMAT_PRINTF(a, b)
  21. #endif
  22. #include <inttypes.h> /* intmax_t, uintmax_t, PRI* */
  23. #include <stddef.h> /* size_t */
  24. void ctest_delay(uint32_t ms);
  25. typedef void (*ctest_setup_func)(void*);
  26. typedef void (*ctest_teardown_func)(void*);
  27. #define CTEST_IMPL_PRAGMA(x) _Pragma (#x)
  28. #if defined(__GNUC__)
  29. #if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
  30. /* the GCC argument will work for both gcc and clang */
  31. #define CTEST_IMPL_DIAG_PUSH_IGNORED(w) \
  32. CTEST_IMPL_PRAGMA(GCC diagnostic push) \
  33. CTEST_IMPL_PRAGMA(GCC diagnostic ignored "-W" #w)
  34. #define CTEST_IMPL_DIAG_POP() \
  35. CTEST_IMPL_PRAGMA(GCC diagnostic pop)
  36. #else
  37. /* the push/pop functionality wasn't in gcc until 4.6, fallback to "ignored" */
  38. #define CTEST_IMPL_DIAG_PUSH_IGNORED(w) \
  39. CTEST_IMPL_PRAGMA(GCC diagnostic ignored "-W" #w)
  40. #define CTEST_IMPL_DIAG_POP()
  41. #endif
  42. #else
  43. /* leave them out entirely for non-GNUC compilers */
  44. #define CTEST_IMPL_DIAG_PUSH_IGNORED(w)
  45. #define CTEST_IMPL_DIAG_POP()
  46. #endif
  47. CTEST_IMPL_DIAG_PUSH_IGNORED(strict-prototypes)
  48. struct ctest {
  49. const char* ssname; // suite name
  50. const char* ttname; // test name
  51. void (*run)();
  52. void* data;
  53. ctest_setup_func* setup;
  54. ctest_teardown_func* teardown;
  55. int skip;
  56. unsigned int magic;
  57. };
  58. CTEST_IMPL_DIAG_POP()
  59. #define CTEST_IMPL_NAME(name) ctest_##name
  60. #define CTEST_IMPL_FNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_run)
  61. #define CTEST_IMPL_TNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname)
  62. #define CTEST_IMPL_DATA_SNAME(sname) CTEST_IMPL_NAME(sname##_data)
  63. #define CTEST_IMPL_DATA_TNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_data)
  64. #define CTEST_IMPL_SETUP_FNAME(sname) CTEST_IMPL_NAME(sname##_setup)
  65. #define CTEST_IMPL_SETUP_FPNAME(sname) CTEST_IMPL_NAME(sname##_setup_ptr)
  66. #define CTEST_IMPL_TEARDOWN_FNAME(sname) CTEST_IMPL_NAME(sname##_teardown)
  67. #define CTEST_IMPL_TEARDOWN_FPNAME(sname) CTEST_IMPL_NAME(sname##_teardown_ptr)
  68. #define CTEST_IMPL_MAGIC (0xdeadbeef)
  69. #ifdef __APPLE__
  70. #define CTEST_IMPL_SECTION __attribute__ ((used, section ("__DATA, .ctest"), aligned(1)))
  71. #else
  72. #define CTEST_IMPL_SECTION __attribute__ ((used, section (".data.ctest"), aligned(1)))
  73. #endif
  74. #define CTEST_IMPL_STRUCT(sname, tname, tskip, tdata, tsetup, tteardown) \
  75. static struct ctest CTEST_IMPL_TNAME(sname, tname) CTEST_IMPL_SECTION = { \
  76. .ssname=#sname, \
  77. .ttname=#tname, \
  78. .run = CTEST_IMPL_FNAME(sname, tname), \
  79. .data = tdata, \
  80. .setup = (ctest_setup_func*) tsetup, \
  81. .teardown = (ctest_teardown_func*) tteardown, \
  82. .skip = tskip, \
  83. .magic = CTEST_IMPL_MAGIC }
  84. #define CTEST_SETUP(sname) \
  85. static void CTEST_IMPL_SETUP_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* data); \
  86. static void (*CTEST_IMPL_SETUP_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_SETUP_FNAME(sname); \
  87. static void CTEST_IMPL_SETUP_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* data)
  88. #define CTEST_TEARDOWN(sname) \
  89. static void CTEST_IMPL_TEARDOWN_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* data); \
  90. static void (*CTEST_IMPL_TEARDOWN_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_TEARDOWN_FNAME(sname); \
  91. static void CTEST_IMPL_TEARDOWN_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* data)
  92. #define CTEST_DATA(sname) \
  93. struct CTEST_IMPL_DATA_SNAME(sname); \
  94. static void (*CTEST_IMPL_SETUP_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*); \
  95. static void (*CTEST_IMPL_TEARDOWN_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*); \
  96. struct CTEST_IMPL_DATA_SNAME(sname)
  97. #define CTEST_IMPL_CTEST(sname, tname, tskip) \
  98. static void CTEST_IMPL_FNAME(sname, tname)(void); \
  99. CTEST_IMPL_STRUCT(sname, tname, tskip, NULL, NULL, NULL); \
  100. static void CTEST_IMPL_FNAME(sname, tname)(void)
  101. #define CTEST_IMPL_CTEST2(sname, tname, tskip) \
  102. static struct CTEST_IMPL_DATA_SNAME(sname) CTEST_IMPL_DATA_TNAME(sname, tname); \
  103. static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* data); \
  104. CTEST_IMPL_STRUCT(sname, tname, tskip, &CTEST_IMPL_DATA_TNAME(sname, tname), &CTEST_IMPL_SETUP_FPNAME(sname), &CTEST_IMPL_TEARDOWN_FPNAME(sname)); \
  105. static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* data)
  106. void CTEST_LOG(const char* fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2);
  107. void CTEST_ERR(const char* fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2); // doesn't return
  108. #define CTEST(sname, tname) CTEST_IMPL_CTEST(sname, tname, 0)
  109. #define CTEST_SKIP(sname, tname) CTEST_IMPL_CTEST(sname, tname, 1)
  110. #define CTEST2(sname, tname) CTEST_IMPL_CTEST2(sname, tname, 0)
  111. #define CTEST2_SKIP(sname, tname) CTEST_IMPL_CTEST2(sname, tname, 1)
  112. void assert_str(const char* exp, const char* real, const char* caller, int line);
  113. #define ASSERT_STR(exp, real) assert_str(exp, real, __FILE__, __LINE__)
  114. void assert_wstr(const wchar_t *exp, const wchar_t *real, const char* caller, int line);
  115. #define ASSERT_WSTR(exp, real) assert_wstr(exp, real, __FILE__, __LINE__)
  116. void assert_data(const unsigned char* exp, size_t expsize,
  117. const unsigned char* real, size_t realsize,
  118. const char* caller, int line);
  119. #define ASSERT_DATA(exp, expsize, real, realsize) \
  120. assert_data(exp, expsize, real, realsize, __FILE__, __LINE__)
  121. void assert_equal(intmax_t exp, intmax_t real, const char* caller, int line);
  122. #define ASSERT_EQUAL(exp, real) assert_equal(exp, real, __FILE__, __LINE__)
  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. void assert_not_equal(intmax_t exp, intmax_t real, const char* caller, int line);
  126. #define ASSERT_NOT_EQUAL(exp, real) assert_not_equal(exp, real, __FILE__, __LINE__)
  127. void assert_not_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line);
  128. #define ASSERT_NOT_EQUAL_U(exp, real) assert_not_equal_u(exp, real, __FILE__, __LINE__)
  129. void assert_interval(intmax_t exp1, intmax_t exp2, intmax_t real, const char* caller, int line);
  130. #define ASSERT_INTERVAL(exp1, exp2, real) assert_interval(exp1, exp2, real, __FILE__, __LINE__)
  131. void assert_null(void* real, const char* caller, int line);
  132. #define ASSERT_NULL(real) assert_null((void*)real, __FILE__, __LINE__)
  133. void assert_not_null(const void* real, const char* caller, int line);
  134. #define ASSERT_NOT_NULL(real) assert_not_null(real, __FILE__, __LINE__)
  135. void assert_true(int real, const char* caller, int line);
  136. #define ASSERT_TRUE(real) assert_true(real, __FILE__, __LINE__)
  137. void assert_false(int real, const char* caller, int line);
  138. #define ASSERT_FALSE(real) assert_false(real, __FILE__, __LINE__)
  139. void assert_fail(const char* caller, int line);
  140. #define ASSERT_FAIL() assert_fail(__FILE__, __LINE__)
  141. void assert_dbl_near(double exp, double real, double tol, const char* caller, int line);
  142. #define ASSERT_DBL_NEAR(exp, real) assert_dbl_near(exp, real, 1e-4, __FILE__, __LINE__)
  143. #define ASSERT_DBL_NEAR_TOL(exp, real, tol) assert_dbl_near(exp, real, tol, __FILE__, __LINE__)
  144. void assert_dbl_far(double exp, double real, double tol, const char* caller, int line);
  145. #define ASSERT_DBL_FAR(exp, real) assert_dbl_far(exp, real, 1e-4, __FILE__, __LINE__)
  146. #define ASSERT_DBL_FAR_TOL(exp, real, tol) assert_dbl_far(exp, real, tol, __FILE__, __LINE__)
  147. #ifdef CTEST_MAIN
  148. #include <setjmp.h>
  149. #include <stdarg.h>
  150. #include <stdio.h>
  151. #include <string.h>
  152. #include <sys/time.h>
  153. #include <unistd.h>
  154. #include <stdint.h>
  155. #include <stdlib.h>
  156. #include <wchar.h>
  157. #ifdef PRIuMAX
  158. #undef PRIuMAX
  159. #define PRIuMAX PRIu32
  160. #endif
  161. #ifdef PRIdMAX
  162. #undef PRIdMAX
  163. #define PRIdMAX PRId32
  164. #endif
  165. #ifdef PRIu64
  166. #undef PRIu64
  167. #define PRIu64 PRIu32
  168. #endif
  169. static size_t ctest_errorsize;
  170. static char* ctest_errormsg;
  171. #define MSG_SIZE 4096
  172. static char ctest_errorbuffer[MSG_SIZE];
  173. static jmp_buf ctest_err;
  174. static int color_output = 1;
  175. static const char* suite_name;
  176. typedef int (*ctest_filter_func)(struct ctest*);
  177. #define ANSI_BLACK "\033[0;30m"
  178. #define ANSI_RED "\033[0;31m"
  179. #define ANSI_GREEN "\033[0;32m"
  180. #define ANSI_YELLOW "\033[0;33m"
  181. #define ANSI_BLUE "\033[0;34m"
  182. #define ANSI_MAGENTA "\033[0;35m"
  183. #define ANSI_CYAN "\033[0;36m"
  184. #define ANSI_GREY "\033[0;37m"
  185. #define ANSI_DARKGREY "\033[01;30m"
  186. #define ANSI_BRED "\033[01;31m"
  187. #define ANSI_BGREEN "\033[01;32m"
  188. #define ANSI_BYELLOW "\033[01;33m"
  189. #define ANSI_BBLUE "\033[01;34m"
  190. #define ANSI_BMAGENTA "\033[01;35m"
  191. #define ANSI_BCYAN "\033[01;36m"
  192. #define ANSI_WHITE "\033[01;37m"
  193. #define ANSI_NORMAL "\033[0m"
  194. CTEST(suite, test) { }
  195. static void vprint_errormsg(const char* const fmt, va_list ap) CTEST_IMPL_FORMAT_PRINTF(1, 0);
  196. static void print_errormsg(const char* const fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2);
  197. static void vprint_errormsg(const char* const fmt, va_list ap) {
  198. // (v)snprintf returns the number that would have been written
  199. const int ret = vsnprintf(ctest_errormsg, ctest_errorsize, fmt, ap);
  200. if (ret < 0) {
  201. ctest_errormsg[0] = 0x00;
  202. } else {
  203. const size_t size = (size_t) ret;
  204. const size_t s = (ctest_errorsize <= size ? size -ctest_errorsize : size);
  205. // ctest_errorsize may overflow at this point
  206. ctest_errorsize -= s;
  207. ctest_errormsg += s;
  208. }
  209. }
  210. static void print_errormsg(const char* const fmt, ...) {
  211. va_list argp;
  212. va_start(argp, fmt);
  213. vprint_errormsg(fmt, argp);
  214. va_end(argp);
  215. }
  216. static void msg_start(const char* color, const char* title) {
  217. if (color_output) {
  218. print_errormsg("%s", color);
  219. }
  220. print_errormsg(" %s: ", title);
  221. }
  222. static void msg_end(void) {
  223. if (color_output) {
  224. print_errormsg(ANSI_NORMAL);
  225. }
  226. print_errormsg("\n");
  227. }
  228. void CTEST_LOG(const char* fmt, ...)
  229. {
  230. va_list argp;
  231. msg_start(ANSI_BLUE, "LOG");
  232. va_start(argp, fmt);
  233. vprint_errormsg(fmt, argp);
  234. va_end(argp);
  235. msg_end();
  236. }
  237. CTEST_IMPL_DIAG_PUSH_IGNORED(missing-noreturn)
  238. void CTEST_ERR(const char* fmt, ...)
  239. {
  240. va_list argp;
  241. msg_start(ANSI_YELLOW, "ERR");
  242. va_start(argp, fmt);
  243. vprint_errormsg(fmt, argp);
  244. va_end(argp);
  245. msg_end();
  246. longjmp(ctest_err, 1);
  247. }
  248. CTEST_IMPL_DIAG_POP()
  249. void assert_str(const char* exp, const char* real, const char* caller, int line) {
  250. if ((exp == NULL && real != NULL) ||
  251. (exp != NULL && real == NULL) ||
  252. (exp && real && strcmp(exp, real) != 0)) {
  253. CTEST_ERR("%s:%d expected '%s', got '%s'", caller, line, exp, real);
  254. }
  255. }
  256. void assert_wstr(const wchar_t *exp, const wchar_t *real, const char* caller, int line) {
  257. if ((exp == NULL && real != NULL) ||
  258. (exp != NULL && real == NULL) ||
  259. (exp && real && wcscmp(exp, real) != 0)) {
  260. CTEST_ERR("%s:%d expected '%ls', got '%ls'", caller, line, exp, real);
  261. }
  262. }
  263. void assert_data(const unsigned char* exp, size_t expsize,
  264. const unsigned char* real, size_t realsize,
  265. const char* caller, int line) {
  266. size_t i;
  267. if (expsize != realsize) {
  268. CTEST_ERR("%s:%d expected %" PRIuMAX " bytes, got %" PRIuMAX, caller, line, (uintmax_t) expsize, (uintmax_t) realsize);
  269. }
  270. for (i=0; i<expsize; i++) {
  271. if (exp[i] != real[i]) {
  272. CTEST_ERR("%s:%d expected 0x%02x at offset %" PRIuMAX " got 0x%02x",
  273. caller, line, exp[i], (uintmax_t) i, real[i]);
  274. }
  275. }
  276. }
  277. void assert_equal(intmax_t exp, intmax_t real, const char* caller, int line) {
  278. if (exp != real) {
  279. CTEST_ERR("%s:%d expected %" PRIdMAX ", got %" PRIdMAX, caller, line, exp, real);
  280. }
  281. }
  282. void assert_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line) {
  283. if (exp != real) {
  284. CTEST_ERR("%s:%d expected %" PRIuMAX ", got %" PRIuMAX, caller, line, exp, real);
  285. }
  286. }
  287. void assert_not_equal(intmax_t exp, intmax_t real, const char* caller, int line) {
  288. if ((exp) == (real)) {
  289. CTEST_ERR("%s:%d should not be %" PRIdMAX, caller, line, real);
  290. }
  291. }
  292. void assert_not_equal_u(uintmax_t exp, uintmax_t real, const char* caller, int line) {
  293. if ((exp) == (real)) {
  294. CTEST_ERR("%s:%d should not be %" PRIuMAX, caller, line, real);
  295. }
  296. }
  297. void assert_interval(intmax_t exp1, intmax_t exp2, intmax_t real, const char* caller, int line) {
  298. if (real < exp1 || real > exp2) {
  299. CTEST_ERR("%s:%d expected %" PRIdMAX "-%" PRIdMAX ", got %" PRIdMAX, caller, line, exp1, exp2, real);
  300. }
  301. }
  302. void assert_dbl_near(double exp, double real, double tol, const char* caller, int line) {
  303. double diff = exp - real;
  304. double absdiff = diff;
  305. /* avoid using fabs and linking with a math lib */
  306. if(diff < 0) {
  307. absdiff *= -1;
  308. }
  309. if (absdiff > tol) {
  310. CTEST_ERR("%s:%d expected %0.3e, got %0.3e (diff %0.3e, tol %0.3e)", caller, line, exp, real, diff, tol);
  311. }
  312. }
  313. void assert_dbl_far(double exp, double real, double tol, const char* caller, int line) {
  314. double diff = exp - real;
  315. double absdiff = diff;
  316. /* avoid using fabs and linking with a math lib */
  317. if(diff < 0) {
  318. absdiff *= -1;
  319. }
  320. if (absdiff <= tol) {
  321. CTEST_ERR("%s:%d expected %0.3e, got %0.3e (diff %0.3e, tol %0.3e)", caller, line, exp, real, diff, tol);
  322. }
  323. }
  324. void assert_null(void* real, const char* caller, int line) {
  325. if ((real) != NULL) {
  326. CTEST_ERR("%s:%d should be NULL", caller, line);
  327. }
  328. }
  329. void assert_not_null(const void* real, const char* caller, int line) {
  330. if (real == NULL) {
  331. CTEST_ERR("%s:%d should not be NULL", caller, line);
  332. }
  333. }
  334. void assert_true(int real, const char* caller, int line) {
  335. if ((real) == 0) {
  336. CTEST_ERR("%s:%d should be true", caller, line);
  337. }
  338. }
  339. void assert_false(int real, const char* caller, int line) {
  340. if ((real) != 0) {
  341. CTEST_ERR("%s:%d should be false", caller, line);
  342. }
  343. }
  344. void assert_fail(const char* caller, int line) {
  345. CTEST_ERR("%s:%d shouldn't come here", caller, line);
  346. }
  347. static int suite_all(struct ctest* t) {
  348. (void) t; // fix unused parameter warning
  349. return 1;
  350. }
  351. static int suite_filter(struct ctest* t) {
  352. return strncmp(suite_name, t->ssname, strlen(suite_name)) == 0;
  353. }
  354. static uint64_t getCurrentTime(void) {
  355. struct timeval now;
  356. gettimeofday(&now, NULL);
  357. uint64_t now64 = (uint64_t) now.tv_sec;
  358. now64 *= 1000000;
  359. now64 += ((uint64_t) now.tv_usec);
  360. return now64;
  361. }
  362. static void color_print(const char* color, const char* text) {
  363. if (color_output)
  364. printf("%s%s"ANSI_NORMAL"\n", color, text);
  365. else
  366. printf("%s\n", text);
  367. }
  368. #ifdef CTEST_SEGFAULT
  369. #include <signal.h>
  370. static void sighandler(int signum)
  371. {
  372. char msg[128];
  373. snprintf(msg, sizeof(msg), "[SIGNAL %d: %s]", signum, sys_siglist[signum]);
  374. color_print(ANSI_BRED, msg);
  375. fflush(stdout);
  376. /* "Unregister" the signal handler and send the signal back to the process
  377. * so it can terminate as expected */
  378. signal(signum, SIG_DFL);
  379. kill(getpid(), signum);
  380. }
  381. #endif
  382. int ctest_main(int argc, const char *argv[]);
  383. __attribute__((no_sanitize_address)) int ctest_main(int argc, const char *argv[])
  384. {
  385. static int total = 0;
  386. static int num_ok = 0;
  387. static int num_fail = 0;
  388. static int num_skip = 0;
  389. static int idx = 1;
  390. static ctest_filter_func filter = suite_all;
  391. #ifdef CTEST_SEGFAULT
  392. signal(SIGSEGV, sighandler);
  393. #endif
  394. if (argc == 2) {
  395. suite_name = argv[1];
  396. filter = suite_filter;
  397. }
  398. #ifdef CTEST_NO_COLORS
  399. color_output = 0;
  400. #else
  401. color_output = isatty(1);
  402. #endif
  403. uint64_t t1 = getCurrentTime();
  404. struct ctest* ctest_begin = &CTEST_IMPL_TNAME(suite, test);
  405. struct ctest* ctest_end = &CTEST_IMPL_TNAME(suite, test);
  406. // find begin and end of section by comparing magics
  407. // Comment the following while(1) loop to avoid invalid address access which cause load exception
  408. // while (1) {
  409. // struct ctest* t = ctest_begin-1;
  410. // if (t->magic != CTEST_IMPL_MAGIC) break;
  411. // ctest_begin--;
  412. // }
  413. while (1) {
  414. struct ctest* t = ctest_end+1;
  415. if (t->magic != CTEST_IMPL_MAGIC) break;
  416. ctest_end++;
  417. }
  418. ctest_end++; // end after last one
  419. static struct ctest* test;
  420. for (test = ctest_begin; test != ctest_end; test++) {
  421. if (test == &CTEST_IMPL_TNAME(suite, test)) continue;
  422. if (filter(test)) total++;
  423. }
  424. for (test = ctest_begin; test != ctest_end; test++) {
  425. if (test == &CTEST_IMPL_TNAME(suite, test)) continue;
  426. if (filter(test)) {
  427. ctest_errorbuffer[0] = 0;
  428. ctest_errorsize = MSG_SIZE-1;
  429. ctest_errormsg = ctest_errorbuffer;
  430. printf("TEST %d/%d %s:%s ", idx, total, test->ssname, test->ttname);
  431. fflush(stdout);
  432. if (test->skip) {
  433. color_print(ANSI_BYELLOW, "[SKIPPED]");
  434. num_skip++;
  435. } else {
  436. int result = setjmp(ctest_err);
  437. if (result == 0) {
  438. if (test->setup && *test->setup) (*test->setup)(test->data);
  439. if (test->data)
  440. test->run(test->data);
  441. else
  442. test->run();
  443. if (test->teardown && *test->teardown) (*test->teardown)(test->data);
  444. // if we got here it's ok
  445. #ifdef CTEST_COLOR_OK
  446. color_print(ANSI_BGREEN, "[OK]");
  447. #else
  448. printf("[OK]\n");
  449. #endif
  450. num_ok++;
  451. } else {
  452. color_print(ANSI_BRED, "[FAIL]");
  453. num_fail++;
  454. }
  455. if (ctest_errorsize != MSG_SIZE-1) printf("%s", ctest_errorbuffer);
  456. }
  457. idx++;
  458. }
  459. }
  460. uint64_t t2 = getCurrentTime();
  461. const char* color = (num_fail) ? ANSI_BRED : ANSI_GREEN;
  462. char results[80];
  463. snprintf(results, sizeof(results), "RESULTS: %d tests (%d ok, %d failed, %d skipped) ran in %" PRIu64 " ms", total, num_ok, num_fail, num_skip, (uint32_t)((t2 - t1)/1000));
  464. color_print(color, results);
  465. return num_fail;
  466. }
  467. #endif
  468. #endif