2
0

cutest.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /*
  2. * CUTest -- C/C++ Unit Test facility
  3. * <http://github.com/mity/cutest>
  4. *
  5. * Copyright (c) 2013-2017 Martin Mitas
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  23. * IN THE SOFTWARE.
  24. */
  25. #ifndef CUTEST_H__
  26. #define CUTEST_H__
  27. /************************
  28. *** Public interface ***
  29. ************************/
  30. /* By default, <cutest.h> provides the main program entry point (function
  31. * main()). However, if the test suite is composed of multiple source files
  32. * which include <cutest.h>, then this causes a problem of multiple main()
  33. * definitions. To avoid this problem, #define macro TEST_NO_MAIN in all
  34. * compilation units but one.
  35. */
  36. /* Macro to specify list of unit tests in the suite.
  37. * The unit test implementation MUST provide list of unit tests it implements
  38. * with this macro:
  39. *
  40. * TEST_LIST = {
  41. * { "test1_name", test1_func_ptr },
  42. * { "test2_name", test2_func_ptr },
  43. * ...
  44. * { 0 }
  45. * };
  46. *
  47. * The list specifies names of each test (must be unique) and pointer to
  48. * a function implementing it. The function does not take any arguments
  49. * and has no return values, i.e. every test function has tp be compatible
  50. * with this prototype:
  51. *
  52. * void test_func(void);
  53. */
  54. #define TEST_LIST const struct test__ test_list__[]
  55. /* Macros for testing whether an unit test succeeds or fails. These macros
  56. * can be used arbitrarily in functions implementing the unit tests.
  57. *
  58. * If any condition fails throughout execution of a test, the test fails.
  59. *
  60. * TEST_CHECK takes only one argument (the condition), TEST_CHECK_ allows
  61. * also to specify an error message to print out if the condition fails.
  62. * (It expects printf-like format string and its parameters). The macros
  63. * return non-zero (condition passes) or 0 (condition fails).
  64. *
  65. * That can be useful when more conditions should be checked only if some
  66. * preceding condition passes, as illustrated in this code snippet:
  67. *
  68. * SomeStruct* ptr = allocate_some_struct();
  69. * if(TEST_CHECK(ptr != NULL)) {
  70. * TEST_CHECK(ptr->member1 < 100);
  71. * TEST_CHECK(ptr->member2 > 200);
  72. * }
  73. */
  74. #define TEST_CHECK_(cond, ...) \
  75. test_check__((cond), __FILE__, __LINE__, __VA_ARGS__)
  76. #define TEST_CHECK(cond) test_check__((cond), __FILE__, __LINE__, "%s", #cond)
  77. /**********************
  78. *** Implementation ***
  79. **********************/
  80. /* The unit test files should not rely on anything below. */
  81. #include <stdarg.h>
  82. #include <stdio.h>
  83. #include <stdlib.h>
  84. #include <string.h>
  85. #if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__)
  86. #define CUTEST_UNIX__ 1
  87. #include <errno.h>
  88. #include <unistd.h>
  89. #include <sys/types.h>
  90. #include <sys/wait.h>
  91. #include <signal.h>
  92. #endif
  93. #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
  94. #define CUTEST_WIN__ 1
  95. #include <windows.h>
  96. #include <io.h>
  97. #endif
  98. #ifdef __cplusplus
  99. #include <exception>
  100. #endif
  101. /* Note our global private identifiers end with '__' to mitigate risk of clash
  102. * with the unit tests implementation. */
  103. #ifdef __cplusplus
  104. extern "C" {
  105. #endif
  106. struct test__ {
  107. const char *name;
  108. void (*func)(void);
  109. };
  110. extern const struct test__ test_list__[];
  111. int test_check__(int cond, const char *file, int line, const char *fmt, ...);
  112. #ifndef TEST_NO_MAIN
  113. static char *test_argv0__ = NULL;
  114. static int test_count__ = 0;
  115. static int test_no_exec__ = 0;
  116. static int test_no_summary__ = 0;
  117. static int test_skip_mode__ = 0;
  118. static int test_stat_failed_units__ = 0;
  119. static int test_stat_run_units__ = 0;
  120. static const struct test__ *test_current_unit__ = NULL;
  121. static int test_current_already_logged__ = 0;
  122. static int test_verbose_level__ = 2;
  123. static int test_current_failures__ = 0;
  124. static int test_colorize__ = 0;
  125. #define CUTEST_COLOR_DEFAULT__ 0
  126. #define CUTEST_COLOR_GREEN__ 1
  127. #define CUTEST_COLOR_RED__ 2
  128. #define CUTEST_COLOR_DEFAULT_INTENSIVE__ 3
  129. #define CUTEST_COLOR_GREEN_INTENSIVE__ 4
  130. #define CUTEST_COLOR_RED_INTENSIVE__ 5
  131. static size_t test_print_in_color__(int color, const char *fmt, ...)
  132. {
  133. va_list args;
  134. char buffer[256];
  135. size_t n;
  136. va_start(args, fmt);
  137. vsnprintf(buffer, sizeof(buffer), fmt, args);
  138. va_end(args);
  139. buffer[sizeof(buffer) - 1] = '\0';
  140. if (!test_colorize__) {
  141. return printf("%s", buffer);
  142. }
  143. #if defined CUTEST_UNIX__
  144. {
  145. const char *col_str;
  146. switch (color) {
  147. case CUTEST_COLOR_GREEN__:
  148. col_str = "\033[0;32m";
  149. break;
  150. case CUTEST_COLOR_RED__:
  151. col_str = "\033[0;31m";
  152. break;
  153. case CUTEST_COLOR_GREEN_INTENSIVE__:
  154. col_str = "\033[1;32m";
  155. break;
  156. case CUTEST_COLOR_RED_INTENSIVE__:
  157. col_str = "\033[1;30m";
  158. break;
  159. case CUTEST_COLOR_DEFAULT_INTENSIVE__:
  160. col_str = "\033[1m";
  161. break;
  162. default:
  163. col_str = "\033[0m";
  164. break;
  165. }
  166. printf("%s", col_str);
  167. n = printf("%s", buffer);
  168. printf("\033[0m");
  169. return n;
  170. }
  171. #elif defined CUTEST_WIN__
  172. {
  173. HANDLE h;
  174. CONSOLE_SCREEN_BUFFER_INFO info;
  175. WORD attr;
  176. h = GetStdHandle(STD_OUTPUT_HANDLE);
  177. GetConsoleScreenBufferInfo(h, &info);
  178. switch (color) {
  179. case CUTEST_COLOR_GREEN__:
  180. attr = FOREGROUND_GREEN;
  181. break;
  182. case CUTEST_COLOR_RED__:
  183. attr = FOREGROUND_RED;
  184. break;
  185. case CUTEST_COLOR_GREEN_INTENSIVE__:
  186. attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
  187. break;
  188. case CUTEST_COLOR_RED_INTENSIVE__:
  189. attr = FOREGROUND_RED | FOREGROUND_INTENSITY;
  190. break;
  191. case CUTEST_COLOR_DEFAULT_INTENSIVE__:
  192. attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED |
  193. FOREGROUND_INTENSITY;
  194. break;
  195. default:
  196. attr = 0;
  197. break;
  198. }
  199. if (attr != 0)
  200. SetConsoleTextAttribute(h, attr);
  201. n = printf("%s", buffer);
  202. SetConsoleTextAttribute(h, info.wAttributes);
  203. return n;
  204. }
  205. #else
  206. n = printf("%s", buffer);
  207. return n;
  208. #endif
  209. }
  210. int test_check__(int cond, const char *file, int line, const char *fmt, ...)
  211. {
  212. const char *result_str;
  213. int result_color;
  214. int verbose_level;
  215. if (cond) {
  216. result_str = "ok";
  217. result_color = CUTEST_COLOR_GREEN__;
  218. verbose_level = 3;
  219. } else {
  220. if (!test_current_already_logged__ && test_current_unit__ != NULL) {
  221. printf("[ ");
  222. test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__, "FAILED");
  223. printf(" ]\n");
  224. }
  225. result_str = "failed";
  226. result_color = CUTEST_COLOR_RED__;
  227. verbose_level = 2;
  228. test_current_failures__++;
  229. test_current_already_logged__++;
  230. }
  231. if (test_verbose_level__ >= verbose_level) {
  232. size_t n = 0;
  233. va_list args;
  234. printf(" ");
  235. if (file != NULL)
  236. n += printf("%s:%d: Check ", file, line);
  237. va_start(args, fmt);
  238. n += vprintf(fmt, args);
  239. va_end(args);
  240. printf("... ");
  241. test_print_in_color__(result_color, result_str);
  242. printf("\n");
  243. test_current_already_logged__++;
  244. }
  245. return (cond != 0);
  246. }
  247. static void test_list_names__(void)
  248. {
  249. const struct test__ *test;
  250. printf("Unit tests:\n");
  251. for (test = &test_list__[0]; test->func != NULL; test++)
  252. printf(" %s\n", test->name);
  253. }
  254. static const struct test__ *test_by_name__(const char *name)
  255. {
  256. const struct test__ *test;
  257. for (test = &test_list__[0]; test->func != NULL; test++) {
  258. if (strcmp(test->name, name) == 0)
  259. return test;
  260. }
  261. return NULL;
  262. }
  263. /* Call directly the given test unit function. */
  264. static int test_do_run__(const struct test__ *test)
  265. {
  266. test_current_unit__ = test;
  267. test_current_failures__ = 0;
  268. test_current_already_logged__ = 0;
  269. if (test_verbose_level__ >= 3) {
  270. test_print_in_color__(CUTEST_COLOR_DEFAULT_INTENSIVE__, "Test %s:\n",
  271. test->name);
  272. test_current_already_logged__++;
  273. } else if (test_verbose_level__ >= 1) {
  274. size_t n;
  275. char spaces[32];
  276. n = test_print_in_color__(CUTEST_COLOR_DEFAULT_INTENSIVE__,
  277. "Test %s... ", test->name);
  278. memset(spaces, ' ', sizeof(spaces));
  279. if (n < sizeof(spaces))
  280. printf("%.*s", (int)(sizeof(spaces) - n), spaces);
  281. } else {
  282. test_current_already_logged__ = 1;
  283. }
  284. #ifdef __cplusplus
  285. try {
  286. #endif
  287. /* This is good to do for case the test unit e.g. crashes. */
  288. fflush(stdout);
  289. fflush(stderr);
  290. test->func();
  291. #ifdef __cplusplus
  292. } catch (std::exception &e) {
  293. const char *what = e.what();
  294. if (what != NULL)
  295. test_check__(0, NULL, 0, "Threw std::exception: %s", what);
  296. else
  297. test_check__(0, NULL, 0, "Threw std::exception");
  298. } catch (...) {
  299. test_check__(0, NULL, 0, "Threw an exception");
  300. }
  301. #endif
  302. if (test_verbose_level__ >= 3) {
  303. switch (test_current_failures__) {
  304. case 0:
  305. test_print_in_color__(CUTEST_COLOR_GREEN_INTENSIVE__,
  306. " All conditions have passed.\n\n");
  307. break;
  308. case 1:
  309. test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__,
  310. " One condition has FAILED.\n\n");
  311. break;
  312. default:
  313. test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__,
  314. " %d conditions have FAILED.\n\n",
  315. test_current_failures__);
  316. break;
  317. }
  318. } else if (test_verbose_level__ >= 1 && test_current_failures__ == 0) {
  319. printf("[ ");
  320. test_print_in_color__(CUTEST_COLOR_GREEN_INTENSIVE__, "OK");
  321. printf(" ]\n");
  322. }
  323. test_current_unit__ = NULL;
  324. return (test_current_failures__ == 0) ? 0 : -1;
  325. }
  326. #if defined(CUTEST_UNIX__) || defined(CUTEST_WIN__)
  327. /* Called if anything goes bad in cutest, or if the unit test ends in other
  328. * way then by normal returning from its function (e.g. exception or some
  329. * abnormal child process termination). */
  330. static void test_error__(const char *fmt, ...)
  331. {
  332. va_list args;
  333. if (test_verbose_level__ == 0)
  334. return;
  335. if (test_verbose_level__ <= 2 && !test_current_already_logged__ &&
  336. test_current_unit__ != NULL) {
  337. printf("[ ");
  338. test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__, "FAILED");
  339. printf(" ]\n");
  340. }
  341. if (test_verbose_level__ >= 2) {
  342. test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__, " Error: ");
  343. va_start(args, fmt);
  344. vprintf(fmt, args);
  345. va_end(args);
  346. printf("\n");
  347. }
  348. }
  349. #endif
  350. /* Trigger the unit test. If possible (and not suppressed) it starts a child
  351. * process who calls test_do_run__(), otherwise it calls test_do_run__()
  352. * directly. */
  353. static void test_run__(const struct test__ *test)
  354. {
  355. int failed = 1;
  356. test_current_unit__ = test;
  357. test_current_already_logged__ = 0;
  358. if (!test_no_exec__) {
  359. #if defined(CUTEST_UNIX__)
  360. pid_t pid;
  361. int exit_code;
  362. pid = fork();
  363. if (pid == (pid_t)-1) {
  364. test_error__("Cannot fork. %s [%d]", strerror(errno), errno);
  365. failed = 1;
  366. } else if (pid == 0) {
  367. /* Child: Do the test. */
  368. failed = (test_do_run__(test) != 0);
  369. exit(failed ? 1 : 0);
  370. } else {
  371. /* Parent: Wait until child terminates and analyze its exit code. */
  372. waitpid(pid, &exit_code, 0);
  373. if (WIFEXITED(exit_code)) {
  374. switch (WEXITSTATUS(exit_code)) {
  375. case 0:
  376. failed = 0;
  377. break; /* test has passed. */
  378. case 1: /* noop */
  379. break; /* "normal" failure. */
  380. default:
  381. test_error__("Unexpected exit code [%d]",
  382. WEXITSTATUS(exit_code));
  383. }
  384. } else if (WIFSIGNALED(exit_code)) {
  385. char tmp[32];
  386. const char *signame;
  387. switch (WTERMSIG(exit_code)) {
  388. case SIGINT:
  389. signame = "SIGINT";
  390. break;
  391. case SIGHUP:
  392. signame = "SIGHUP";
  393. break;
  394. case SIGQUIT:
  395. signame = "SIGQUIT";
  396. break;
  397. case SIGABRT:
  398. signame = "SIGABRT";
  399. break;
  400. case SIGKILL:
  401. signame = "SIGKILL";
  402. break;
  403. case SIGSEGV:
  404. signame = "SIGSEGV";
  405. break;
  406. case SIGILL:
  407. signame = "SIGILL";
  408. break;
  409. case SIGTERM:
  410. signame = "SIGTERM";
  411. break;
  412. default:
  413. sprintf(tmp, "signal %d", WTERMSIG(exit_code));
  414. signame = tmp;
  415. break;
  416. }
  417. test_error__("Test interrupted by %s", signame);
  418. } else {
  419. test_error__("Test ended in an unexpected way [%d]", exit_code);
  420. }
  421. }
  422. #elif defined(CUTEST_WIN__)
  423. char buffer[512] = { 0 };
  424. STARTUPINFOA startupInfo = { 0 };
  425. PROCESS_INFORMATION processInfo;
  426. DWORD exitCode;
  427. /* Windows has no fork(). So we propagate all info into the child
  428. * through a command line arguments. */
  429. _snprintf(buffer, sizeof(buffer) - 1,
  430. "%s --no-exec --no-summary --verbose=%d --color=%s -- \"%s\"",
  431. test_argv0__, test_verbose_level__,
  432. test_colorize__ ? "always" : "never", test->name);
  433. startupInfo.cb = sizeof(STARTUPINFO);
  434. if (CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL,
  435. &startupInfo, &processInfo)) {
  436. WaitForSingleObject(processInfo.hProcess, INFINITE);
  437. GetExitCodeProcess(processInfo.hProcess, &exitCode);
  438. CloseHandle(processInfo.hThread);
  439. CloseHandle(processInfo.hProcess);
  440. failed = (exitCode != 0);
  441. } else {
  442. test_error__("Cannot create unit test subprocess [%ld].",
  443. GetLastError());
  444. failed = 1;
  445. }
  446. #else
  447. /* A platform where we don't know how to run child process. */
  448. failed = (test_do_run__(test) != 0);
  449. #endif
  450. } else {
  451. /* Child processes suppressed through --no-exec. */
  452. failed = (test_do_run__(test) != 0);
  453. }
  454. test_current_unit__ = NULL;
  455. test_stat_run_units__++;
  456. if (failed)
  457. test_stat_failed_units__++;
  458. }
  459. #if defined(CUTEST_WIN__)
  460. /* Callback for SEH events. */
  461. static LONG CALLBACK test_exception_filter__(EXCEPTION_POINTERS *ptrs)
  462. {
  463. test_error__("Unhandled SEH exception %08lx at %p.",
  464. ptrs->ExceptionRecord->ExceptionCode,
  465. ptrs->ExceptionRecord->ExceptionAddress);
  466. fflush(stdout);
  467. fflush(stderr);
  468. return EXCEPTION_EXECUTE_HANDLER;
  469. }
  470. #endif
  471. static void test_help__(void)
  472. {
  473. printf("Usage: %s [options] [test...]\n", test_argv0__);
  474. printf("Run the specified unit tests; or if the option '--skip' is used, "
  475. "run all\n");
  476. printf("tests in the suite but those listed. By default, if no tests are "
  477. "specified\n");
  478. printf("on the command line, all unit tests in the suite are run.\n");
  479. printf("\n");
  480. printf("Options:\n");
  481. printf(
  482. " -s, --skip Execute all unit tests but the listed ones\n");
  483. printf(" --no-exec Do not execute unit tests as child "
  484. "processes\n");
  485. printf(
  486. " --no-summary Suppress printing of test results summary\n");
  487. printf(" -l, --list List unit tests in the suite and exit\n");
  488. printf(" -v, --verbose Enable more verbose output\n");
  489. printf(" --verbose=LEVEL Set verbose level to LEVEL:\n");
  490. printf(" 0 ... Be silent\n");
  491. printf(" 1 ... Output one line per test (and "
  492. "summary)\n");
  493. printf(" 2 ... As 1 and failed conditions (this "
  494. "is default)\n");
  495. printf(" 3 ... As 1 and all conditions (and "
  496. "extended summary)\n");
  497. printf(" --color=WHEN Enable colorized output (WHEN is one of "
  498. "'auto', 'always', 'never')\n");
  499. printf(" -h, --help Display this help and exit\n");
  500. printf("\n");
  501. test_list_names__();
  502. }
  503. int main(int argc, char **argv)
  504. {
  505. const struct test__ **tests = NULL;
  506. int i, j, n = 0;
  507. int seen_double_dash = 0;
  508. test_argv0__ = argv[0];
  509. #if defined CUTEST_UNIX__
  510. test_colorize__ = isatty(STDOUT_FILENO);
  511. #elif defined CUTEST_WIN__
  512. test_colorize__ = _isatty(_fileno(stdout));
  513. #else
  514. test_colorize__ = 0;
  515. #endif
  516. /* Parse options */
  517. for (i = 1; i < argc; i++) {
  518. if (seen_double_dash || argv[i][0] != '-') {
  519. tests = (const struct test__ **)realloc(
  520. (void *)tests, (n + 1) * sizeof(const struct test__ *));
  521. if (tests == NULL) {
  522. fprintf(stderr, "Out of memory.\n");
  523. exit(2);
  524. }
  525. tests[n] = test_by_name__(argv[i]);
  526. if (tests[n] == NULL) {
  527. fprintf(stderr, "%s: Unrecognized unit test '%s'\n", argv[0],
  528. argv[i]);
  529. fprintf(stderr, "Try '%s --list' for list of unit tests.\n",
  530. argv[0]);
  531. exit(2);
  532. }
  533. n++;
  534. } else if (strcmp(argv[i], "--") == 0) {
  535. seen_double_dash = 1;
  536. } else if (strcmp(argv[i], "--help") == 0 ||
  537. strcmp(argv[i], "-h") == 0) {
  538. test_help__();
  539. exit(0);
  540. } else if (strcmp(argv[i], "--verbose") == 0 ||
  541. strcmp(argv[i], "-v") == 0) {
  542. test_verbose_level__++;
  543. } else if (strncmp(argv[i], "--verbose=", 10) == 0) {
  544. test_verbose_level__ = atoi(argv[i] + 10);
  545. } else if (strcmp(argv[i], "--color=auto") == 0) {
  546. /* noop (set from above) */
  547. } else if (strcmp(argv[i], "--color=always") == 0 ||
  548. strcmp(argv[i], "--color") == 0) {
  549. test_colorize__ = 1;
  550. } else if (strcmp(argv[i], "--color=never") == 0) {
  551. test_colorize__ = 0;
  552. } else if (strcmp(argv[i], "--skip") == 0 ||
  553. strcmp(argv[i], "-s") == 0) {
  554. test_skip_mode__ = 1;
  555. } else if (strcmp(argv[i], "--no-exec") == 0) {
  556. test_no_exec__ = 1;
  557. } else if (strcmp(argv[i], "--no-summary") == 0) {
  558. test_no_summary__ = 1;
  559. } else if (strcmp(argv[i], "--list") == 0 ||
  560. strcmp(argv[i], "-l") == 0) {
  561. test_list_names__();
  562. exit(0);
  563. } else {
  564. fprintf(stderr, "%s: Unrecognized option '%s'\n", argv[0], argv[i]);
  565. fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
  566. exit(2);
  567. }
  568. }
  569. #if defined(CUTEST_WIN__)
  570. SetUnhandledExceptionFilter(test_exception_filter__);
  571. #endif
  572. /* Count all test units */
  573. test_count__ = 0;
  574. for (i = 0; test_list__[i].func != NULL; i++)
  575. test_count__++;
  576. /* Run the tests */
  577. if (n == 0) {
  578. /* Run all tests */
  579. for (i = 0; test_list__[i].func != NULL; i++)
  580. test_run__(&test_list__[i]);
  581. } else if (!test_skip_mode__) {
  582. /* Run the listed tests */
  583. for (i = 0; i < n; i++)
  584. test_run__(tests[i]);
  585. } else {
  586. /* Run all tests except those listed */
  587. for (i = 0; test_list__[i].func != NULL; i++) {
  588. int want_skip = 0;
  589. for (j = 0; j < n; j++) {
  590. if (tests[j] == &test_list__[i]) {
  591. want_skip = 1;
  592. break;
  593. }
  594. }
  595. if (!want_skip)
  596. test_run__(&test_list__[i]);
  597. }
  598. }
  599. /* Write a summary */
  600. if (!test_no_summary__ && test_verbose_level__ >= 1) {
  601. test_print_in_color__(CUTEST_COLOR_DEFAULT_INTENSIVE__, "\nSummary:\n");
  602. if (test_verbose_level__ >= 3) {
  603. printf(" Count of all unit tests: %4d\n", test_count__);
  604. printf(" Count of run unit tests: %4d\n",
  605. test_stat_run_units__);
  606. printf(" Count of failed unit tests: %4d\n",
  607. test_stat_failed_units__);
  608. printf(" Count of skipped unit tests: %4d\n",
  609. test_count__ - test_stat_run_units__);
  610. }
  611. if (test_stat_failed_units__ == 0) {
  612. test_print_in_color__(CUTEST_COLOR_GREEN_INTENSIVE__,
  613. " SUCCESS: All unit tests have passed.\n");
  614. } else {
  615. test_print_in_color__(
  616. CUTEST_COLOR_RED_INTENSIVE__,
  617. " FAILED: %d of %d unit tests have failed.\n",
  618. test_stat_failed_units__, test_stat_run_units__);
  619. }
  620. }
  621. if (tests != NULL)
  622. free((void *)tests);
  623. return (test_stat_failed_units__ == 0) ? 0 : 1;
  624. }
  625. #endif /* #ifndef TEST_NO_MAIN */
  626. #ifdef __cplusplus
  627. } /* extern "C" */
  628. #endif
  629. #endif /* #ifndef CUTEST_H__ */