Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

greatest.h 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. /*
  2. * Copyright (c) 2011 Scott Vokes <vokes.s@gmail.com>
  3. *
  4. * Modified 2014 by Thomas Buck <xythobuz@xythobuz.de>
  5. * --> C++ support
  6. * --> Included janoskk color output patch
  7. * --> Modified it so a tty output is detected at runtime (now unix only)
  8. *
  9. * Permission to use, copy, modify, and/or distribute this software for any
  10. * purpose with or without fee is hereby granted, provided that the above
  11. * copyright notice and this permission notice appear in all copies.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  14. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  15. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  16. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  17. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  18. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  19. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  20. */
  21. #ifndef GREATEST_H
  22. #define GREATEST_H
  23. #ifdef __cplusplus
  24. extern "C"
  25. {
  26. #endif
  27. #define GREATEST_VERSION_MAJOR 0
  28. #define GREATEST_VERSION_MINOR 9
  29. #define GREATEST_VERSION_PATCH 3
  30. /* A unit testing system for C, contained in 1 file.
  31. * It doesn't use dynamic allocation or depend on anything
  32. * beyond ANSI C89. */
  33. /*********************************************************************
  34. * Minimal test runner template
  35. *********************************************************************/
  36. #if 0
  37. #include "greatest.h"
  38. TEST foo_should_foo() {
  39. PASS();
  40. }
  41. static void setup_cb(void *data) {
  42. printf("setup callback for each test case\n");
  43. }
  44. static void teardown_cb(void *data) {
  45. printf("teardown callback for each test case\n");
  46. }
  47. SUITE(suite) {
  48. /* Optional setup/teardown callbacks which will be run before/after
  49. * every test case in the suite.
  50. * Cleared when the suite finishes. */
  51. SET_SETUP(setup_cb, voidp_to_callback_data);
  52. SET_TEARDOWN(teardown_cb, voidp_to_callback_data);
  53. RUN_TEST(foo_should_foo);
  54. }
  55. /* Add all the definitions that need to be in the test runner's main file. */
  56. GREATEST_MAIN_DEFS();
  57. int main(int argc, char **argv) {
  58. GREATEST_MAIN_BEGIN(); /* command-line arguments, initialization. */
  59. RUN_SUITE(suite);
  60. GREATEST_MAIN_END(); /* display results */
  61. }
  62. #endif
  63. /*********************************************************************/
  64. #include <stdlib.h>
  65. #include <stdio.h>
  66. #include <string.h>
  67. #include <time.h>
  68. #include <unistd.h>
  69. /***********
  70. * Options *
  71. ***********/
  72. /* Default column width for non-verbose output. */
  73. #ifndef GREATEST_DEFAULT_WIDTH
  74. #define GREATEST_DEFAULT_WIDTH 72
  75. #endif
  76. /* FILE *, for test logging. */
  77. #ifndef GREATEST_STDOUT
  78. #define GREATEST_STDOUT stdout
  79. #endif
  80. /* Remove GREATEST_ prefix from most commonly used symbols? */
  81. #ifndef GREATEST_USE_ABBREVS
  82. #define GREATEST_USE_ABBREVS 1
  83. #endif
  84. /* Colorize the passed/failed results */
  85. #ifndef COLOR_FAIL
  86. #define COLOR_FAIL "\033[22;31;1m"
  87. #endif
  88. #ifndef COLOR_PASS
  89. #define COLOR_PASS "\033[22;32m"
  90. #endif
  91. #define COLOR_RESET "\033[22;0m"
  92. /*********
  93. * Types *
  94. *********/
  95. /* Info for the current running suite. */
  96. typedef struct greatest_suite_info {
  97. unsigned int tests_run;
  98. unsigned int passed;
  99. unsigned int failed;
  100. unsigned int skipped;
  101. /* timers, pre/post running suite and individual tests */
  102. clock_t pre_suite;
  103. clock_t post_suite;
  104. clock_t pre_test;
  105. clock_t post_test;
  106. } greatest_suite_info;
  107. /* Type for a suite function. */
  108. typedef void (greatest_suite_cb)(void);
  109. /* Types for setup/teardown callbacks. If non-NULL, these will be run
  110. * and passed the pointer to their additional data. */
  111. typedef void (greatest_setup_cb)(void *udata);
  112. typedef void (greatest_teardown_cb)(void *udata);
  113. typedef enum {
  114. GREATEST_FLAG_VERBOSE = 0x01,
  115. GREATEST_FLAG_FIRST_FAIL = 0x02,
  116. GREATEST_FLAG_LIST_ONLY = 0x04
  117. } GREATEST_FLAG;
  118. typedef struct greatest_run_info {
  119. unsigned int flags;
  120. unsigned int tests_run; /* total test count */
  121. /* Overall pass/fail/skip counts. */
  122. unsigned int passed;
  123. unsigned int failed;
  124. unsigned int skipped;
  125. /* currently running test suite */
  126. greatest_suite_info suite;
  127. /* info to print about the most recent failure */
  128. const char *fail_file;
  129. unsigned int fail_line;
  130. const char *msg;
  131. /* current setup/teardown hooks and userdata */
  132. greatest_setup_cb *setup;
  133. void *setup_udata;
  134. greatest_teardown_cb *teardown;
  135. void *teardown_udata;
  136. /* formatting info for ".....s...F"-style output */
  137. unsigned int col;
  138. unsigned int width;
  139. /* only run a specific suite or test */
  140. char *suite_filter;
  141. char *test_filter;
  142. /* overall timers */
  143. clock_t begin;
  144. clock_t end;
  145. } greatest_run_info;
  146. /* Global var for the current testing context.
  147. * Initialized by GREATEST_MAIN_DEFS(). */
  148. extern greatest_run_info greatest_info;
  149. /**********************
  150. * Exported functions *
  151. **********************/
  152. void greatest_do_pass(const char *name);
  153. void greatest_do_fail(const char *name);
  154. void greatest_do_skip(const char *name);
  155. int greatest_pre_test(const char *name);
  156. void greatest_post_test(const char *name, int res);
  157. void greatest_usage(const char *name);
  158. void GREATEST_SET_SETUP_CB(greatest_setup_cb *cb, void *udata);
  159. void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata);
  160. /**********
  161. * Macros *
  162. **********/
  163. /* Define a suite. */
  164. #define GREATEST_SUITE(NAME) void NAME(void)
  165. /* Start defining a test function.
  166. * The arguments are not included, to allow parametric testing. */
  167. #define GREATEST_TEST static int
  168. /* Run a suite. */
  169. #define GREATEST_RUN_SUITE(S_NAME) greatest_run_suite(S_NAME, #S_NAME)
  170. /* Run a test in the current suite. */
  171. #define GREATEST_RUN_TEST(TEST) \
  172. do { \
  173. if (greatest_pre_test(#TEST) == 1) { \
  174. int res = TEST(); \
  175. greatest_post_test(#TEST, res); \
  176. } else if (GREATEST_LIST_ONLY()) { \
  177. fprintf(GREATEST_STDOUT, " %s\n", #TEST); \
  178. } \
  179. } while (0)
  180. /* Run a test in the current suite with one void* argument,
  181. * which can be a pointer to a struct with multiple arguments. */
  182. #define GREATEST_RUN_TEST1(TEST, ENV) \
  183. do { \
  184. if (greatest_pre_test(#TEST) == 1) { \
  185. int res = TEST(ENV); \
  186. greatest_post_test(#TEST, res); \
  187. } else if (GREATEST_LIST_ONLY()) { \
  188. fprintf(GREATEST_STDOUT, " %s\n", #TEST); \
  189. } \
  190. } while (0)
  191. /* If __VA_ARGS__ (C99) is supported, allow parametric testing
  192. * without needing to manually manage the argument struct. */
  193. #if defined __cplusplus || (__STDC_VERSION__ >= 19901L)
  194. #define GREATEST_RUN_TESTp(TEST, ...) \
  195. do { \
  196. if (greatest_pre_test(#TEST) == 1) { \
  197. int res = TEST(__VA_ARGS__); \
  198. greatest_post_test(#TEST, res); \
  199. } else if (GREATEST_LIST_ONLY()) { \
  200. fprintf(GREATEST_STDOUT, " %s\n", #TEST); \
  201. } \
  202. } while (0)
  203. #endif
  204. /* Check if the test runner is in verbose mode. */
  205. #define GREATEST_IS_VERBOSE() (greatest_info.flags & GREATEST_FLAG_VERBOSE)
  206. #define GREATEST_LIST_ONLY() (greatest_info.flags & GREATEST_FLAG_LIST_ONLY)
  207. #define GREATEST_FIRST_FAIL() (greatest_info.flags & GREATEST_FLAG_FIRST_FAIL)
  208. #define GREATEST_FAILURE_ABORT() (greatest_info.suite.failed > 0 && GREATEST_FIRST_FAIL())
  209. /* Message-less forms. */
  210. #define GREATEST_PASS() GREATEST_PASSm(NULL)
  211. #define GREATEST_FAIL() GREATEST_FAILm(NULL)
  212. #define GREATEST_SKIP() GREATEST_SKIPm(NULL)
  213. #define GREATEST_ASSERT(COND) GREATEST_ASSERTm(#COND, COND)
  214. #define GREATEST_ASSERT_FALSE(COND) GREATEST_ASSERT_FALSEm(#COND, COND)
  215. #define GREATEST_ASSERT_EQ(EXP, GOT) GREATEST_ASSERT_EQm(#EXP " != " #GOT, EXP, GOT)
  216. #define GREATEST_ASSERT_STR_EQ(EXP, GOT) GREATEST_ASSERT_STR_EQm(#EXP " != " #GOT, EXP, GOT)
  217. /* The following forms take an additional message argument first,
  218. * to be displayed by the test runner. */
  219. /* Fail if a condition is not true, with message. */
  220. #define GREATEST_ASSERTm(MSG, COND) \
  221. do { \
  222. greatest_info.msg = MSG; \
  223. greatest_info.fail_file = __FILE__; \
  224. greatest_info.fail_line = __LINE__; \
  225. if (!(COND)) return -1; \
  226. greatest_info.msg = NULL; \
  227. } while (0)
  228. #define GREATEST_ASSERT_FALSEm(MSG, COND) \
  229. do { \
  230. greatest_info.msg = MSG; \
  231. greatest_info.fail_file = __FILE__; \
  232. greatest_info.fail_line = __LINE__; \
  233. if ((COND)) return -1; \
  234. greatest_info.msg = NULL; \
  235. } while (0)
  236. #define GREATEST_ASSERT_EQm(MSG, EXP, GOT) \
  237. do { \
  238. greatest_info.msg = MSG; \
  239. greatest_info.fail_file = __FILE__; \
  240. greatest_info.fail_line = __LINE__; \
  241. if ((EXP) != (GOT)) return -1; \
  242. greatest_info.msg = NULL; \
  243. } while (0)
  244. #define GREATEST_ASSERT_STR_EQm(MSG, EXP, GOT) \
  245. do { \
  246. const char *exp_s = (EXP); \
  247. const char *got_s = (GOT); \
  248. greatest_info.msg = MSG; \
  249. greatest_info.fail_file = __FILE__; \
  250. greatest_info.fail_line = __LINE__; \
  251. if (0 != strcmp(exp_s, got_s)) { \
  252. fprintf(GREATEST_STDOUT, \
  253. "Expected:\n####\n%s\n####\n", exp_s); \
  254. fprintf(GREATEST_STDOUT, \
  255. "Got:\n####\n%s\n####\n", got_s); \
  256. return -1; \
  257. } \
  258. greatest_info.msg = NULL; \
  259. } while (0)
  260. #define GREATEST_PASSm(MSG) \
  261. do { \
  262. greatest_info.msg = MSG; \
  263. return 0; \
  264. } while (0)
  265. #define GREATEST_FAILm(MSG) \
  266. do { \
  267. greatest_info.fail_file = __FILE__; \
  268. greatest_info.fail_line = __LINE__; \
  269. greatest_info.msg = MSG; \
  270. return -1; \
  271. } while (0)
  272. #define GREATEST_SKIPm(MSG) \
  273. do { \
  274. greatest_info.msg = MSG; \
  275. return 1; \
  276. } while (0)
  277. #define GREATEST_SET_TIME(NAME) \
  278. NAME = clock(); \
  279. if (NAME == (clock_t) -1) { \
  280. fprintf(GREATEST_STDOUT, \
  281. "clock error: %s\n", #NAME); \
  282. exit(EXIT_FAILURE); \
  283. }
  284. #define GREATEST_CLOCK_DIFF(C1, C2) \
  285. fprintf(GREATEST_STDOUT, " (%lu ticks, %.3f sec)", \
  286. (long unsigned int) (C2) - (C1), \
  287. (double)((C2) - (C1)) / (1.0 * (double)CLOCKS_PER_SEC)) \
  288. /* Include several function definitions in the main test file. */
  289. #define GREATEST_MAIN_DEFS() \
  290. \
  291. /* Is FILTER a subset of NAME? */ \
  292. static int greatest_name_match(const char *name, \
  293. const char *filter) { \
  294. size_t offset = 0; \
  295. size_t filter_len = strlen(filter); \
  296. while (name[offset] != '\0') { \
  297. if (name[offset] == filter[0]) { \
  298. if (0 == strncmp(&name[offset], filter, filter_len)) { \
  299. return 1; \
  300. } \
  301. } \
  302. offset++; \
  303. } \
  304. \
  305. return 0; \
  306. } \
  307. \
  308. int greatest_pre_test(const char *name) { \
  309. if (!GREATEST_LIST_ONLY() \
  310. && (!GREATEST_FIRST_FAIL() || greatest_info.suite.failed == 0) \
  311. && (greatest_info.test_filter == NULL || \
  312. greatest_name_match(name, greatest_info.test_filter))) { \
  313. GREATEST_SET_TIME(greatest_info.suite.pre_test); \
  314. if (greatest_info.setup) { \
  315. greatest_info.setup(greatest_info.setup_udata); \
  316. } \
  317. return 1; /* test should be run */ \
  318. } else { \
  319. return 0; /* skipped */ \
  320. } \
  321. } \
  322. \
  323. void greatest_post_test(const char *name, int res) { \
  324. GREATEST_SET_TIME(greatest_info.suite.post_test); \
  325. if (greatest_info.teardown) { \
  326. void *udata = greatest_info.teardown_udata; \
  327. greatest_info.teardown(udata); \
  328. } \
  329. \
  330. if (res < 0) { \
  331. greatest_do_fail(name); \
  332. } else if (res > 0) { \
  333. greatest_do_skip(name); \
  334. } else if (res == 0) { \
  335. greatest_do_pass(name); \
  336. } \
  337. greatest_info.suite.tests_run++; \
  338. greatest_info.col++; \
  339. if (GREATEST_IS_VERBOSE()) { \
  340. GREATEST_CLOCK_DIFF(greatest_info.suite.pre_test, \
  341. greatest_info.suite.post_test); \
  342. fprintf(GREATEST_STDOUT, "\n"); \
  343. } else if (greatest_info.col % greatest_info.width == 0) { \
  344. fprintf(GREATEST_STDOUT, "\n"); \
  345. greatest_info.col = 0; \
  346. } \
  347. if (GREATEST_STDOUT == stdout) fflush(stdout); \
  348. } \
  349. \
  350. static void greatest_run_suite(greatest_suite_cb *suite_cb, \
  351. const char *suite_name) { \
  352. if (greatest_info.suite_filter && \
  353. !greatest_name_match(suite_name, greatest_info.suite_filter)) \
  354. return; \
  355. if (GREATEST_FIRST_FAIL() && greatest_info.failed > 0) return; \
  356. greatest_info.suite.tests_run = 0; \
  357. greatest_info.suite.failed = 0; \
  358. greatest_info.suite.passed = 0; \
  359. greatest_info.suite.skipped = 0; \
  360. greatest_info.suite.pre_suite = 0; \
  361. greatest_info.suite.post_suite = 0; \
  362. greatest_info.suite.pre_test = 0; \
  363. greatest_info.suite.post_test = 0; \
  364. greatest_info.col = 0; \
  365. fprintf(GREATEST_STDOUT, "\n* Suite %s:\n", suite_name); \
  366. GREATEST_SET_TIME(greatest_info.suite.pre_suite); \
  367. suite_cb(); \
  368. GREATEST_SET_TIME(greatest_info.suite.post_suite); \
  369. if (greatest_info.suite.tests_run > 0) { \
  370. fprintf(GREATEST_STDOUT, \
  371. "\n%u tests - %u %spass%s, %u %sfail%s, %u skipped", \
  372. greatest_info.suite.tests_run, \
  373. greatest_info.suite.passed, \
  374. (isatty(fileno(GREATEST_STDOUT))) ? ( \
  375. (!greatest_info.suite.failed) ? COLOR_PASS : COLOR_RESET \
  376. ) : "", \
  377. (isatty(fileno(GREATEST_STDOUT))) ? COLOR_RESET : "", \
  378. greatest_info.suite.failed, \
  379. (isatty(fileno(GREATEST_STDOUT))) ? ( \
  380. (greatest_info.suite.failed) ? COLOR_FAIL : COLOR_RESET \
  381. ) : "", \
  382. (isatty(fileno(GREATEST_STDOUT))) ? COLOR_RESET : "", \
  383. greatest_info.suite.skipped); \
  384. GREATEST_CLOCK_DIFF(greatest_info.suite.pre_suite, \
  385. greatest_info.suite.post_suite); \
  386. fprintf(GREATEST_STDOUT, "\n"); \
  387. } \
  388. greatest_info.setup = NULL; \
  389. greatest_info.setup_udata = NULL; \
  390. greatest_info.teardown = NULL; \
  391. greatest_info.teardown_udata = NULL; \
  392. greatest_info.passed += greatest_info.suite.passed; \
  393. greatest_info.failed += greatest_info.suite.failed; \
  394. greatest_info.skipped += greatest_info.suite.skipped; \
  395. greatest_info.tests_run += greatest_info.suite.tests_run; \
  396. } \
  397. \
  398. void greatest_do_pass(const char *name) { \
  399. if (GREATEST_IS_VERBOSE()) { \
  400. fprintf(GREATEST_STDOUT, \
  401. (isatty(fileno(GREATEST_STDOUT))) ? \
  402. COLOR_PASS "PASS" COLOR_RESET " %s: %s" : \
  403. "PASS %s: %s", \
  404. name, greatest_info.msg ? greatest_info.msg : ""); \
  405. } else { \
  406. fprintf(GREATEST_STDOUT, "."); \
  407. } \
  408. greatest_info.suite.passed++; \
  409. } \
  410. \
  411. void greatest_do_fail(const char *name) { \
  412. if (GREATEST_IS_VERBOSE()) { \
  413. fprintf(GREATEST_STDOUT, \
  414. (isatty(fileno(GREATEST_STDOUT))) ? \
  415. COLOR_FAIL "FAIL" COLOR_RESET " %s: %s (%s:%u)" : \
  416. "FAIL %s: %s (%s:%u)", \
  417. name, greatest_info.msg ? greatest_info.msg : "", \
  418. greatest_info.fail_file, greatest_info.fail_line); \
  419. } else { \
  420. fprintf(GREATEST_STDOUT, "F"); \
  421. /* add linebreak if in line of '.'s */ \
  422. if (greatest_info.col % greatest_info.width != 0) \
  423. fprintf(GREATEST_STDOUT, "\n"); \
  424. greatest_info.col = 0; \
  425. fprintf(GREATEST_STDOUT, \
  426. (isatty(fileno(GREATEST_STDOUT))) ? \
  427. COLOR_FAIL "FAIL" COLOR_RESET " %s: %s (%s:%u)\n" : \
  428. "FAIL %s: %s (%s:%u)\n", \
  429. name, \
  430. greatest_info.msg ? greatest_info.msg : "", \
  431. greatest_info.fail_file, greatest_info.fail_line); \
  432. } \
  433. greatest_info.suite.failed++; \
  434. } \
  435. \
  436. void greatest_do_skip(const char *name) { \
  437. if (GREATEST_IS_VERBOSE()) { \
  438. fprintf(GREATEST_STDOUT, "SKIP %s: %s", \
  439. name, \
  440. greatest_info.msg ? \
  441. greatest_info.msg : "" ); \
  442. } else { \
  443. fprintf(GREATEST_STDOUT, "s"); \
  444. } \
  445. greatest_info.suite.skipped++; \
  446. } \
  447. \
  448. void greatest_usage(const char *name) { \
  449. fprintf(GREATEST_STDOUT, \
  450. "Usage: %s [-hlfv] [-s SUITE] [-t TEST]\n" \
  451. " -h print this Help\n" \
  452. " -l List suites and their tests, then exit\n" \
  453. " -f Stop runner after first failure\n" \
  454. " -v Verbose output\n" \
  455. " -s SUITE only run suite named SUITE\n" \
  456. " -t TEST only run test named TEST\n", \
  457. name); \
  458. } \
  459. \
  460. void GREATEST_SET_SETUP_CB(greatest_setup_cb *cb, void *udata) { \
  461. greatest_info.setup = cb; \
  462. greatest_info.setup_udata = udata; \
  463. } \
  464. \
  465. void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, \
  466. void *udata) { \
  467. greatest_info.teardown = cb; \
  468. greatest_info.teardown_udata = udata; \
  469. } \
  470. \
  471. greatest_run_info greatest_info
  472. /* Handle command-line arguments, etc. */
  473. #define GREATEST_MAIN_BEGIN() \
  474. do { \
  475. int _i = 0; \
  476. memset(&greatest_info, 0, sizeof(greatest_info)); \
  477. if (greatest_info.width == 0) { \
  478. greatest_info.width = GREATEST_DEFAULT_WIDTH; \
  479. } \
  480. for (_i = 1; _i < argc; _i++) { \
  481. if (0 == strcmp("-t", argv[_i])) { \
  482. if (argc <= _i + 1) { \
  483. greatest_usage(argv[0]); \
  484. exit(EXIT_FAILURE); \
  485. } \
  486. greatest_info.test_filter = argv[_i+1]; \
  487. _i++; \
  488. } else if (0 == strcmp("-s", argv[_i])) { \
  489. if (argc <= _i + 1) { \
  490. greatest_usage(argv[0]); \
  491. exit(EXIT_FAILURE); \
  492. } \
  493. greatest_info.suite_filter = argv[_i+1]; \
  494. _i++; \
  495. } else if (0 == strcmp("-f", argv[_i])) { \
  496. greatest_info.flags |= GREATEST_FLAG_FIRST_FAIL; \
  497. } else if (0 == strcmp("-v", argv[_i])) { \
  498. greatest_info.flags |= GREATEST_FLAG_VERBOSE; \
  499. } else if (0 == strcmp("-l", argv[_i])) { \
  500. greatest_info.flags |= GREATEST_FLAG_LIST_ONLY; \
  501. } else if (0 == strcmp("-h", argv[_i])) { \
  502. greatest_usage(argv[0]); \
  503. exit(EXIT_SUCCESS); \
  504. } else { \
  505. fprintf(GREATEST_STDOUT, \
  506. "Unknown argument '%s'\n", argv[_i]); \
  507. greatest_usage(argv[0]); \
  508. exit(EXIT_FAILURE); \
  509. } \
  510. } \
  511. } while (0); \
  512. GREATEST_SET_TIME(greatest_info.begin)
  513. #define GREATEST_MAIN_END() \
  514. do { \
  515. if (!GREATEST_LIST_ONLY()) { \
  516. GREATEST_SET_TIME(greatest_info.end); \
  517. fprintf(GREATEST_STDOUT, \
  518. "\nTotal: %u tests", greatest_info.tests_run); \
  519. GREATEST_CLOCK_DIFF(greatest_info.begin, \
  520. greatest_info.end); \
  521. fprintf(GREATEST_STDOUT, "\n"); \
  522. fprintf(GREATEST_STDOUT, \
  523. "%sPass: %u, fail: %u, " \
  524. "skip: %u.%s\n", \
  525. (isatty(fileno(GREATEST_STDOUT))) ? \
  526. ((greatest_info.failed) ? COLOR_FAIL : COLOR_PASS) : \
  527. "", greatest_info.passed, \
  528. greatest_info.failed, \
  529. greatest_info.skipped, \
  530. (isatty(fileno(GREATEST_STDOUT))) ? COLOR_RESET : ""); \
  531. } \
  532. return (greatest_info.failed > 0 \
  533. ? EXIT_FAILURE : EXIT_SUCCESS); \
  534. } while (0)
  535. /* Make abbreviations without the GREATEST_ prefix for the
  536. * most commonly used symbols. */
  537. #if GREATEST_USE_ABBREVS
  538. #define TEST GREATEST_TEST
  539. #define SUITE GREATEST_SUITE
  540. #define RUN_TEST GREATEST_RUN_TEST
  541. #define RUN_TEST1 GREATEST_RUN_TEST1
  542. #define RUN_SUITE GREATEST_RUN_SUITE
  543. #define ASSERT GREATEST_ASSERT
  544. #define ASSERTm GREATEST_ASSERTm
  545. #define ASSERT_FALSE GREATEST_ASSERT_FALSE
  546. #define ASSERT_EQ GREATEST_ASSERT_EQ
  547. #define ASSERT_STR_EQ GREATEST_ASSERT_STR_EQ
  548. #define ASSERT_FALSEm GREATEST_ASSERT_FALSEm
  549. #define ASSERT_EQm GREATEST_ASSERT_EQm
  550. #define ASSERT_STR_EQm GREATEST_ASSERT_STR_EQm
  551. #define PASS GREATEST_PASS
  552. #define FAIL GREATEST_FAIL
  553. #define SKIP GREATEST_SKIP
  554. #define PASSm GREATEST_PASSm
  555. #define FAILm GREATEST_FAILm
  556. #define SKIPm GREATEST_SKIPm
  557. #define SET_SETUP GREATEST_SET_SETUP_CB
  558. #define SET_TEARDOWN GREATEST_SET_TEARDOWN_CB
  559. #if defined __cplusplus || (__STDC_VERSION__ >= 19901L)
  560. #define RUN_TESTp GREATEST_RUN_TESTp
  561. #endif
  562. #endif /* USE_ABBREVS */
  563. #ifdef __cplusplus
  564. }
  565. #endif
  566. #endif