internal-check.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /*-*- mode:C; -*- */
  2. /*
  3. * Check: a unit test framework for C
  4. * Copyright (C) 2001, 2002, Arien Malec
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the
  18. * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
  19. * Boston, MA 02110-1301, USA.
  20. */
  21. #ifndef CHECK_H
  22. #define CHECK_H
  23. #include <stddef.h>
  24. #include <string.h>
  25. /* Check: a unit test framework for C
  26. Check is a unit test framework for C. It features a simple
  27. interface for defining unit tests, putting little in the way of the
  28. developer. Tests are run in a separate address space, so Check can
  29. catch both assertion failures and code errors that cause
  30. segmentation faults or other signals. The output from unit tests
  31. can be used within source code editors and IDEs.
  32. Unit tests are created with the START_TEST/END_TEST macro
  33. pair. The fail_unless and fail macros are used for creating
  34. checks within unit tests; the mark_point macro is useful for
  35. trapping the location of signals and/or early exits.
  36. Test cases are created with tcase_create, unit tests are added
  37. with tcase_add_test
  38. Suites are created with suite_create; test cases are added
  39. with suite_add_tcase
  40. Suites are run through an SRunner, which is created with
  41. srunner_create. Additional suites can be added to an SRunner with
  42. srunner_add_suite. An SRunner is freed with srunner_free, which also
  43. frees all suites added to the runner.
  44. Use srunner_run_all to run a suite and print results.
  45. Macros and functions starting with _ (underscore) are internal and
  46. may change without notice. You have been warned!.
  47. */
  48. #ifdef __cplusplus
  49. #define CK_CPPSTART extern "C" {
  50. #define CK_CPPEND }
  51. CK_CPPSTART
  52. #endif
  53. #if defined(__GNUC__) && defined(__GNUC_MINOR__)
  54. #define GCC_VERSION_AT_LEAST(major, minor) \
  55. ((__GNUC__ > (major)) || \
  56. (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
  57. #else
  58. #define GCC_VERSION_AT_LEAST(major, minor) 0
  59. #endif
  60. #if GCC_VERSION_AT_LEAST(2,95)
  61. #define CK_ATTRIBUTE_UNUSED __attribute__ ((unused))
  62. #else
  63. #define CK_ATTRIBUTE_UNUSED
  64. #endif /* GCC 2.95 */
  65. #include <sys/types.h>
  66. /* Used to create the linker script for hiding lib-local symbols. Shall
  67. be put directly in front of the exported symbol. */
  68. #define CK_EXPORT
  69. /* check version numbers */
  70. #define CHECK_MAJOR_VERSION (0)
  71. #define CHECK_MINOR_VERSION (9)
  72. #define CHECK_MICRO_VERSION (8)
  73. extern int CK_EXPORT check_major_version;
  74. extern int CK_EXPORT check_minor_version;
  75. extern int CK_EXPORT check_micro_version;
  76. #ifndef NULL
  77. #define NULL ((void*)0)
  78. #endif
  79. /* opaque type for a test case
  80. A TCase represents a test case. Create with tcase_create, free
  81. with tcase_free. For the moment, test cases can only be run
  82. through a suite
  83. */
  84. typedef struct TCase TCase;
  85. /* type for a test function */
  86. typedef void (*TFun) (int);
  87. /* type for a setup/teardown function */
  88. typedef void (*SFun) (void);
  89. /* Opaque type for a test suite */
  90. typedef struct Suite Suite;
  91. /* Creates a test suite with the given name */
  92. Suite * CK_EXPORT suite_create (const char *name);
  93. /* Add a test case to a suite */
  94. void CK_EXPORT suite_add_tcase (Suite *s, TCase *tc);
  95. /* Create a test case */
  96. TCase * CK_EXPORT tcase_create (const char *name);
  97. /* Add a test function to a test case (macro version) */
  98. #define tcase_add_test(tc,tf) tcase_add_test_raise_signal(tc,tf,0)
  99. /* Add a test function with signal handling to a test case (macro version) */
  100. #define tcase_add_test_raise_signal(tc,tf,signal) \
  101. _tcase_add_test((tc),(tf),"" # tf "",(signal), 0, 0, 1)
  102. /* Add a test function with an expected exit value to a test case (macro version) */
  103. #define tcase_add_exit_test(tc, tf, expected_exit_value) \
  104. _tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),0,1)
  105. /* Add a looping test function to a test case (macro version)
  106. The test will be called in a for(i = s; i < e; i++) loop with each
  107. iteration being executed in a new context. The loop variable 'i' is
  108. available in the test.
  109. */
  110. #define tcase_add_loop_test(tc,tf,s,e) \
  111. _tcase_add_test((tc),(tf),"" # tf "",0,0,(s),(e))
  112. /* Signal version of loop test.
  113. FIXME: add a test case; this is untested as part of Check's tests.
  114. */
  115. #define tcase_add_loop_test_raise_signal(tc,tf,signal,s,e) \
  116. _tcase_add_test((tc),(tf),"" # tf "",(signal),0,(s),(e))
  117. /* allowed exit value version of loop test. */
  118. #define tcase_add_loop_exit_test(tc,tf,expected_exit_value,s,e) \
  119. _tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),(s),(e))
  120. /* Add a test function to a test case
  121. (function version -- use this when the macro won't work
  122. */
  123. void CK_EXPORT _tcase_add_test (TCase *tc, TFun tf, const char *fname, int _signal, int allowed_exit_value, int start, int end);
  124. /* Add unchecked fixture setup/teardown functions to a test case
  125. If unchecked fixture functions are run at the start and end of the
  126. test case, and not before and after unit tests. Note that unchecked
  127. setup/teardown functions are not run in a separate address space,
  128. like test functions, and so must not exit or signal (e.g.,
  129. segfault)
  130. Also, when run in CK_NOFORK mode, unchecked fixture functions may
  131. lead to different unit test behavior IF unit tests change data
  132. setup by the fixture functions.
  133. */
  134. void CK_EXPORT tcase_add_unchecked_fixture (TCase *tc, SFun setup, SFun teardown);
  135. /* Add fixture setup/teardown functions to a test case
  136. Checked fixture functions are run before and after unit
  137. tests. Unlike unchecked fixture functions, checked fixture
  138. functions are run in the same separate address space as the test
  139. program, and thus the test function will survive signals or
  140. unexpected exits in the fixture function. Also, IF the setup
  141. function is idempotent, unit test behavior will be the same in
  142. CK_FORK and CK_NOFORK modes.
  143. However, since fixture functions are run before and after each unit
  144. test, they should not be expensive code.
  145. */
  146. void CK_EXPORT tcase_add_checked_fixture (TCase *tc, SFun setup, SFun teardown);
  147. /* Set the timeout for all tests in a test case. A test that lasts longer
  148. than the timeout (in seconds) will be killed and thus fail with an error.
  149. The timeout can also be set globaly with the environment variable
  150. CK_DEFAULT_TIMEOUT, the specific setting always takes precedence.
  151. */
  152. void CK_EXPORT tcase_set_timeout (TCase *tc, int timeout);
  153. /* Internal function to mark the start of a test function */
  154. void CK_EXPORT tcase_fn_start (const char *fname, const char *file, int line);
  155. /* Start a unit test with START_TEST(unit_name), end with END_TEST
  156. One must use braces within a START_/END_ pair to declare new variables
  157. */
  158. #define START_TEST(__testname)\
  159. static void __testname (int _i CK_ATTRIBUTE_UNUSED)\
  160. {\
  161. tcase_fn_start (""# __testname, __FILE__, __LINE__);
  162. /* End a unit test */
  163. #define END_TEST }
  164. /* Fail the test case unless expr is true */
  165. /* The space before the comma sign before ## is essential to be compatible
  166. with gcc 2.95.3 and earlier.
  167. */
  168. #define fail_unless(expr, ...)\
  169. _fail_unless(expr, __FILE__, __LINE__,\
  170. "Assertion '"#expr"' failed" , ## __VA_ARGS__, NULL)
  171. /* Fail the test case if expr is true */
  172. /* The space before the comma sign before ## is essential to be compatible
  173. with gcc 2.95.3 and earlier.
  174. */
  175. /* FIXME: these macros may conflict with C89 if expr is
  176. FIXME: strcmp (str1, str2) due to excessive string length. */
  177. #define fail_if(expr, ...)\
  178. _fail_unless(!(expr), __FILE__, __LINE__,\
  179. "Failure '"#expr"' occured" , ## __VA_ARGS__, NULL)
  180. /* Always fail */
  181. #define fail(...) _fail_unless(0, __FILE__, __LINE__, "Failed", __VA_ARGS__, NULL)
  182. /* Non macro version of #fail_unless, with more complicated interface */
  183. void CK_EXPORT _fail_unless (int result, const char *file,
  184. int line, const char *expr, ...);
  185. /* New check fail API. */
  186. #define ck_abort() ck_abort_msg(NULL)
  187. #define ck_abort_msg fail
  188. #define ck_assert(C) ck_assert_msg(C, NULL)
  189. #define ck_assert_msg fail_unless
  190. /* Integer comparsion macros with improved output compared to fail_unless(). */
  191. /* O may be any comparion operator. */
  192. #define _ck_assert_int(X, O, Y) ck_assert_msg((X) O (Y), "Assertion '"#X#O#Y"' failed: "#X"==%d, "#Y"==%d", X, Y)
  193. #define ck_assert_int_eq(X, Y) _ck_assert_int(X, ==, Y)
  194. #define ck_assert_int_ne(X, Y) _ck_assert_int(X, !=, Y)
  195. /* String comparsion macros with improved output compared to fail_unless() */
  196. #define _ck_assert_str(C, X, O, Y) ck_assert_msg(C, "Assertion '"#X#O#Y"' failed: "#X"==\"%s\", "#Y"==\"%s\"", X, Y)
  197. #define ck_assert_str_eq(X, Y) _ck_assert_str(!strcmp(X, Y), X, ==, Y)
  198. #define ck_assert_str_ne(X, Y) _ck_assert_str(strcmp(X, Y), X, !=, Y)
  199. /* Mark the last point reached in a unit test
  200. (useful for tracking down where a segfault, etc. occurs)
  201. */
  202. #define mark_point() _mark_point(__FILE__,__LINE__)
  203. /* Non macro version of #mark_point */
  204. void CK_EXPORT _mark_point (const char *file, int line);
  205. /* Result of a test */
  206. enum test_result {
  207. CK_TEST_RESULT_INVALID, /* Default value; should not encounter this */
  208. CK_PASS, /* Test passed*/
  209. CK_FAILURE, /* Test completed but failed */
  210. CK_ERROR /* Test failed to complete
  211. (unexpected signal or non-zero early exit) */
  212. };
  213. /* Specifies the how much output an SRunner should produce */
  214. enum print_output {
  215. CK_SILENT, /* No output */
  216. CK_MINIMAL, /* Only summary output */
  217. CK_NORMAL, /* All failed tests */
  218. CK_VERBOSE, /* All tests */
  219. CK_ENV, /* Look at environment var */
  220. #if 0
  221. CK_SUBUNIT, /* Run as a subunit child process */
  222. #endif
  223. CK_LAST
  224. };
  225. /* Holds state for a running of a test suite */
  226. typedef struct SRunner SRunner;
  227. /* Opaque type for a test failure */
  228. typedef struct TestResult TestResult;
  229. /* accessors for tr fields */
  230. enum ck_result_ctx {
  231. CK_CTX_INVALID, /* Default value; should not encounter this */
  232. CK_CTX_SETUP,
  233. CK_CTX_TEST,
  234. CK_CTX_TEARDOWN
  235. };
  236. /* Type of result */
  237. int CK_EXPORT tr_rtype (TestResult *tr);
  238. /* Context in which the result occurred */
  239. enum ck_result_ctx CK_EXPORT tr_ctx (TestResult *tr);
  240. /* Failure message */
  241. const char * CK_EXPORT tr_msg (TestResult *tr);
  242. /* Line number at which failure occured */
  243. int CK_EXPORT tr_lno (TestResult *tr);
  244. /* File name at which failure occured */
  245. const char * CK_EXPORT tr_lfile (TestResult *tr);
  246. /* Test case in which unit test was run */
  247. const char * CK_EXPORT tr_tcname (TestResult *tr);
  248. /* Creates an SRunner for the given suite */
  249. SRunner * CK_EXPORT srunner_create (Suite *s);
  250. /* Adds a Suite to an SRunner */
  251. void CK_EXPORT srunner_add_suite (SRunner *sr, Suite *s);
  252. /* Frees an SRunner, all suites added to it and all contained test cases */
  253. void CK_EXPORT srunner_free (SRunner *sr);
  254. /* Test running */
  255. /* Runs an SRunner, printing results as specified (see enum print_output) */
  256. void CK_EXPORT srunner_run_all (SRunner *sr, enum print_output print_mode);
  257. /* Next functions are valid only after the suite has been
  258. completely run, of course */
  259. /* Number of failed tests in a run suite. Includes failures + errors */
  260. int CK_EXPORT srunner_ntests_failed (SRunner *sr);
  261. /* Total number of tests run in a run suite */
  262. int CK_EXPORT srunner_ntests_run (SRunner *sr);
  263. /* Return an array of results for all failures
  264. Number of failures is equal to srunner_nfailed_tests. Memory for
  265. the array is malloc'ed and must be freed, but individual TestResults
  266. must not
  267. */
  268. TestResult ** CK_EXPORT srunner_failures (SRunner *sr);
  269. /* Return an array of results for all run tests
  270. Number of results is equal to srunner_ntests_run, and excludes
  271. failures due to setup function failure.
  272. Memory is malloc'ed and must be freed, but individual TestResults
  273. must not
  274. */
  275. TestResult ** CK_EXPORT srunner_results (SRunner *sr);
  276. /* Printing */
  277. /* Print the results contained in an SRunner */
  278. void CK_EXPORT srunner_print (SRunner *sr, enum print_output print_mode);
  279. /* Set a log file to which to write during test running.
  280. Log file setting is an initialize only operation -- it should be
  281. done immediatly after SRunner creation, and the log file can't be
  282. changed after being set.
  283. */
  284. void CK_EXPORT srunner_set_log (SRunner *sr, const char *fname);
  285. /* Does the SRunner have a log file? */
  286. int CK_EXPORT srunner_has_log (SRunner *sr);
  287. /* Return the name of the log file, or NULL if none */
  288. const char * CK_EXPORT srunner_log_fname (SRunner *sr);
  289. /* Set a xml file to which to write during test running.
  290. XML file setting is an initialize only operation -- it should be
  291. done immediatly after SRunner creation, and the XML file can't be
  292. changed after being set.
  293. */
  294. void CK_EXPORT srunner_set_xml (SRunner *sr, const char *fname);
  295. /* Does the SRunner have an XML log file? */
  296. int CK_EXPORT srunner_has_xml (SRunner *sr);
  297. /* Return the name of the XML file, or NULL if none */
  298. const char * CK_EXPORT srunner_xml_fname (SRunner *sr);
  299. /* Control forking */
  300. enum fork_status {
  301. CK_FORK_GETENV, /* look in the environment for CK_FORK */
  302. CK_FORK, /* call fork to run tests */
  303. CK_NOFORK /* don't call fork */
  304. };
  305. /* Get the current fork status */
  306. enum fork_status CK_EXPORT srunner_fork_status (SRunner *sr);
  307. /* Set the current fork status */
  308. void CK_EXPORT srunner_set_fork_status (SRunner *sr, enum fork_status fstat);
  309. /* Fork in a test and make sure messaging and tests work. */
  310. pid_t CK_EXPORT check_fork(void);
  311. /* Wait for the pid and exit. If pid is zero, just exit. */
  312. void CK_EXPORT check_waitpid_and_exit(pid_t pid);
  313. #ifdef __cplusplus
  314. CK_CPPEND
  315. #endif
  316. #endif /* CHECK_H */