exip  Alpha 0.5.4
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
check.h
Go to the documentation of this file.
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., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 #ifndef CHECK_H
23 #define CHECK_H
24 
25 #include <stddef.h>
26 #include <string.h>
27 
28 /* Check: a unit test framework for C
29 
30  Check is a unit test framework for C. It features a simple
31  interface for defining unit tests, putting little in the way of the
32  developer. Tests are run in a separate address space, so Check can
33  catch both assertion failures and code errors that cause
34  segmentation faults or other signals. The output from unit tests
35  can be used within source code editors and IDEs.
36 
37  Unit tests are created with the START_TEST/END_TEST macro
38  pair. The fail_unless and fail macros are used for creating
39  checks within unit tests; the mark_point macro is useful for
40  trapping the location of signals and/or early exits.
41 
42 
43  Test cases are created with tcase_create, unit tests are added
44  with tcase_add_test
45 
46 
47  Suites are created with suite_create; test cases are added
48  with suite_add_tcase
49 
50  Suites are run through an SRunner, which is created with
51  srunner_create. Additional suites can be added to an SRunner with
52  srunner_add_suite. An SRunner is freed with srunner_free, which also
53  frees all suites added to the runner.
54 
55  Use srunner_run_all to run a suite and print results.
56 
57  Macros and functions starting with _ (underscore) are internal and
58  may change without notice. You have been warned!.
59 
60 */
61 
62 
63 #ifdef __cplusplus
64 #define CK_CPPSTART extern "C" {
65 #define CK_CPPEND }
66 CK_CPPSTART
67 #endif
68 
69 #if defined(__GNUC__) && defined(__GNUC_MINOR__)
70 #define GCC_VERSION_AT_LEAST(major, minor) \
71 ((__GNUC__ > (major)) || \
72  (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
73 #else
74 #define GCC_VERSION_AT_LEAST(major, minor) 0
75 #endif
76 
77 #if GCC_VERSION_AT_LEAST(2,95)
78 #define CK_ATTRIBUTE_UNUSED __attribute__ ((unused))
79 #else
80 #define CK_ATTRIBUTE_UNUSED
81 #endif /* GCC 2.95 */
82 
83 #ifdef HAVE_SYS_TYPES_H
84 #include <sys/types.h>
85 #endif
86 
87 /* Used to create the linker script for hiding lib-local symbols. Shall
88  be put directly in front of the exported symbol. */
89 #define CK_EXPORT
90 
91 /* Used for MSVC to create the export attribute */
92 /* CK_DLL_EXP is defined during the compilation of the library */
93 /* on the command line */
94 #ifndef CK_DLL_EXP
95 #define CK_DLL_EXP
96 #endif
97 
98 /* check version numbers */
99 
100 #define CHECK_MAJOR_VERSION (0)
101 #define CHECK_MINOR_VERSION (9)
102 #define CHECK_MICRO_VERSION (6)
103 
107 
108 #ifndef NULL
109 #define NULL ((void*)0)
110 #endif
111 
112 /* opaque type for a test case
113 
114  A TCase represents a test case. Create with tcase_create, free
115  with tcase_free. For the moment, test cases can only be run
116  through a suite
117 */
118 typedef struct TCase TCase;
119 
120 /* type for a test function */
121 typedef void (*TFun) (int);
122 
123 /* type for a setup/teardown function */
124 typedef void (*SFun) (void);
125 
126 /* Opaque type for a test suite */
127 typedef struct Suite Suite;
128 
129 /* Creates a test suite with the given name */
130 CK_DLL_EXP Suite * CK_EXPORT suite_create (const char *name);
131 
132 /* Determines whether a given test suite contains a case named after a
133  given string. */
134 int suite_tcase (Suite *s, const char *tcname);
135 
136 /* Add a test case to a suite */
138 
139 /* Create a test case */
140 CK_DLL_EXP TCase * CK_EXPORT tcase_create (const char *name);
141 
142 /* Add a test function to a test case (macro version) */
143 #define tcase_add_test(tc,tf) tcase_add_test_raise_signal(tc,tf,0)
144 
145 /* Add a test function with signal handling to a test case (macro version) */
146 #define tcase_add_test_raise_signal(tc,tf,signal) \
147  _tcase_add_test((tc),(tf),"" # tf "",(signal), 0, 0, 1)
148 
149 /* Add a test function with an expected exit value to a test case (macro version) */
150 #define tcase_add_exit_test(tc, tf, expected_exit_value) \
151  _tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),0,1)
152 
153 /* Add a looping test function to a test case (macro version)
154 
155  The test will be called in a for(i = s; i < e; i++) loop with each
156  iteration being executed in a new context. The loop variable 'i' is
157  available in the test.
158  */
159 #define tcase_add_loop_test(tc,tf,s,e) \
160  _tcase_add_test((tc),(tf),"" # tf "",0,0,(s),(e))
161 
162 /* Signal version of loop test.
163  FIXME: add a test case; this is untested as part of Check's tests.
164  */
165 #define tcase_add_loop_test_raise_signal(tc,tf,signal,s,e) \
166  _tcase_add_test((tc),(tf),"" # tf "",(signal),0,(s),(e))
167 
168 /* allowed exit value version of loop test. */
169 #define tcase_add_loop_exit_test(tc,tf,expected_exit_value,s,e) \
170  _tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),(s),(e))
171 
172 /* Add a test function to a test case
173  (function version -- use this when the macro won't work
174 */
175 CK_DLL_EXP void CK_EXPORT _tcase_add_test (TCase *tc, TFun tf, const char *fname, int _signal, int allowed_exit_value, int start, int end);
176 
177 /* Add unchecked fixture setup/teardown functions to a test case
178 
179  If unchecked fixture functions are run at the start and end of the
180  test case, and not before and after unit tests. Note that unchecked
181  setup/teardown functions are not run in a separate address space,
182  like test functions, and so must not exit or signal (e.g.,
183  segfault)
184 
185  Also, when run in CK_NOFORK mode, unchecked fixture functions may
186  lead to different unit test behavior IF unit tests change data
187  setup by the fixture functions.
188 */
189 CK_DLL_EXP void CK_EXPORT tcase_add_unchecked_fixture (TCase *tc, SFun setup, SFun teardown);
190 
191 /* Add fixture setup/teardown functions to a test case
192 
193  Checked fixture functions are run before and after unit
194  tests. Unlike unchecked fixture functions, checked fixture
195  functions are run in the same separate address space as the test
196  program, and thus the test function will survive signals or
197  unexpected exits in the fixture function. Also, IF the setup
198  function is idempotent, unit test behavior will be the same in
199  CK_FORK and CK_NOFORK modes.
200 
201  However, since fixture functions are run before and after each unit
202  test, they should not be expensive code.
203 
204 */
205 CK_DLL_EXP void CK_EXPORT tcase_add_checked_fixture (TCase *tc, SFun setup, SFun teardown);
206 
207 /* Set the timeout for all tests in a test case. A test that lasts longer
208  than the timeout (in seconds) will be killed and thus fail with an error.
209  The timeout can also be set globaly with the environment variable
210  CK_DEFAULT_TIMEOUT, the specific setting always takes precedence.
211 */
212 CK_DLL_EXP void CK_EXPORT tcase_set_timeout (TCase *tc, int timeout);
213 
214 /* Internal function to mark the start of a test function */
215 CK_DLL_EXP void CK_EXPORT tcase_fn_start (const char *fname, const char *file, int line);
216 
217 /* Start a unit test with START_TEST(unit_name), end with END_TEST
218  One must use braces within a START_/END_ pair to declare new variables
219 */
220 #define START_TEST(__testname)\
221 static void __testname (int _i CK_ATTRIBUTE_UNUSED)\
222 {\
223  tcase_fn_start (""# __testname, __FILE__, __LINE__);
224 
225 /* End a unit test */
226 #define END_TEST }
227 
228 /* Fail the test case unless expr is true */
229 /* The space before the comma sign before ## is essential to be compatible
230  with gcc 2.95.3 and earlier.
231 */
232 #define fail_unless(expr, ...)\
233  _fail_unless(expr, __FILE__, __LINE__,\
234  "Assertion '"#expr"' failed" , ## __VA_ARGS__, NULL)
235 
236 /* Fail the test case if expr is true */
237 /* The space before the comma sign before ## is essential to be compatible
238  with gcc 2.95.3 and earlier.
239 */
240 
241 /* FIXME: these macros may conflict with C89 if expr is
242  FIXME: strcmp (str1, str2) due to excessive string length. */
243 #define fail_if(expr, ...)\
244  _fail_unless(!(expr), __FILE__, __LINE__,\
245  "Failure '"#expr"' occured" , ## __VA_ARGS__, NULL)
246 
247 /* Always fail */
248 #define fail(...) _fail_unless(0, __FILE__, __LINE__, "Failed" , ## __VA_ARGS__, NULL)
249 
250 /* Non macro version of #fail_unless, with more complicated interface */
251 CK_DLL_EXP void CK_EXPORT _fail_unless (int result, const char *file,
252  int line, const char *expr, ...);
253 
254 /* New check fail API. */
255 #define ck_abort() ck_abort_msg(NULL)
256 #define ck_abort_msg fail
257 #define ck_assert(C) ck_assert_msg(C, NULL)
258 #define ck_assert_msg fail_unless
259 
260 /* Integer comparsion macros with improved output compared to fail_unless(). */
261 /* OP may be any comparion operator. */
262 #define _ck_assert_int(X, OP, Y) do { \
263  int _ck_x = (X); \
264  int _ck_y = (Y); \
265  ck_assert_msg(_ck_x OP _ck_y, "Assertion '"#X#OP#Y"' failed: "#X"==%d, "#Y"==%d", _ck_x, _ck_y); \
266 } while (0)
267 #define ck_assert_int_eq(X, Y) _ck_assert_int(X, ==, Y)
268 #define ck_assert_int_ne(X, Y) _ck_assert_int(X, !=, Y)
269 #define ck_assert_int_lt(X, Y) _ck_assert_int(X, <, Y)
270 #define ck_assert_int_le(X, Y) _ck_assert_int(X, <=, Y)
271 #define ck_assert_int_gt(X, Y) _ck_assert_int(X, >, Y)
272 #define ck_assert_int_ge(X, Y) _ck_assert_int(X, >=, Y)
273 
274 /* String comparsion macros with improved output compared to fail_unless() */
275 /* OP might be any operator that can be used in '0 OP strcmp(X,Y)' comparison */
276 /* The x and y parameter swap in strcmp() is needed to handle >, >=, <, <= operators */
277 #define _ck_assert_str(X, OP, Y) do { \
278  const char* _ck_x = (X); \
279  const char* _ck_y = (Y); \
280  ck_assert_msg(0 OP strcmp(_ck_y, _ck_x), \
281  "Assertion '"#X#OP#Y"' failed: "#X"==\"%s\", "#Y"==\"%s\"", _ck_x, _ck_y); \
282 } while (0)
283 #define ck_assert_str_eq(X, Y) _ck_assert_str(X, ==, Y)
284 #define ck_assert_str_ne(X, Y) _ck_assert_str(X, !=, Y)
285 #define ck_assert_str_lt(X, Y) _ck_assert_str(X, <, Y)
286 #define ck_assert_str_le(X, Y) _ck_assert_str(X, <=, Y)
287 #define ck_assert_str_gt(X, Y) _ck_assert_str(X, >, Y)
288 #define ck_assert_str_ge(X, Y) _ck_assert_str(X, >=, Y)
289 
290 
291 /* Mark the last point reached in a unit test
292  (useful for tracking down where a segfault, etc. occurs)
293 */
294 #define mark_point() _mark_point(__FILE__,__LINE__)
295 
296 /* Non macro version of #mark_point */
297 CK_DLL_EXP void CK_EXPORT _mark_point (const char *file, int line);
298 
299 /* Result of a test */
301  CK_TEST_RESULT_INVALID, /* Default value; should not encounter this */
302  CK_PASS, /* Test passed*/
303  CK_FAILURE, /* Test completed but failed */
304  CK_ERROR /* Test failed to complete
305  (unexpected signal or non-zero early exit) */
306 };
307 
308 /* Specifies the how much output an SRunner should produce */
310  CK_SILENT, /* No output */
311  CK_MINIMAL, /* Only summary output */
312  CK_NORMAL, /* All failed tests */
313  CK_VERBOSE, /* All tests */
314  CK_ENV, /* Look at environment var */
315 #if 0
316  CK_SUBUNIT, /* Run as a subunit child process */
317 #endif
319 };
320 
321 /* Holds state for a running of a test suite */
322 typedef struct SRunner SRunner;
323 
324 /* Opaque type for a test failure */
325 typedef struct TestResult TestResult;
326 
327 /* accessors for tr fields */
329  CK_CTX_INVALID, /* Default value; should not encounter this */
333 };
334 
335 /* Type of result */
337 /* Context in which the result occurred */
339 /* Failure message */
340 CK_DLL_EXP const char * CK_EXPORT tr_msg (TestResult *tr);
341 /* Line number at which failure occured */
343 /* File name at which failure occured */
344 CK_DLL_EXP const char * CK_EXPORT tr_lfile (TestResult *tr);
345 /* Test case in which unit test was run */
346 CK_DLL_EXP const char * CK_EXPORT tr_tcname (TestResult *tr);
347 
348 /* Creates an SRunner for the given suite */
350 
351 /* Adds a Suite to an SRunner */
353 
354 /* Frees an SRunner, all suites added to it and all contained test cases */
356 
357 
358 /* Test running */
359 
360 /* Runs an SRunner, printing results as specified (see enum print_output) */
361 CK_DLL_EXP void CK_EXPORT srunner_run_all (SRunner *sr, enum print_output print_mode);
362 
363 /* Runs an SRunner specifying test suite and test case by name,
364  printing results as specified (see enum print_output). A NULL
365  value means "any test suite" or "any test case". */
366 CK_DLL_EXP void CK_EXPORT srunner_run (SRunner *sr, const char *sname, const char *tcname, enum print_output print_mode);
367 
368 
369 /* Next functions are valid only after the suite has been
370  completely run, of course */
371 
372 /* Number of failed tests in a run suite. Includes failures + errors */
374 
375 /* Total number of tests run in a run suite */
377 
378 /* Return an array of results for all failures
379 
380  Number of failures is equal to srunner_nfailed_tests. Memory for
381  the array is malloc'ed and must be freed, but individual TestResults
382  must not
383 */
385 
386 /* Return an array of results for all run tests
387 
388  Number of results is equal to srunner_ntests_run, and excludes
389  failures due to setup function failure.
390 
391  Memory is malloc'ed and must be freed, but individual TestResults
392  must not
393 */
395 
396 
397 /* Printing */
398 
399 /* Print the results contained in an SRunner */
400 CK_DLL_EXP void CK_EXPORT srunner_print (SRunner *sr, enum print_output print_mode);
401 
402 
403 /* Set a log file to which to write during test running.
404 
405  Log file setting is an initialize only operation -- it should be
406  done immediatly after SRunner creation, and the log file can't be
407  changed after being set.
408 */
409 CK_DLL_EXP void CK_EXPORT srunner_set_log (SRunner *sr, const char *fname);
410 
411 /* Does the SRunner have a log file? */
413 
414 /* Return the name of the log file, or NULL if none */
415 CK_DLL_EXP const char * CK_EXPORT srunner_log_fname (SRunner *sr);
416 
417 /* Set a xml file to which to write during test running.
418 
419  XML file setting is an initialize only operation -- it should be
420  done immediatly after SRunner creation, and the XML file can't be
421  changed after being set.
422 */
423 CK_DLL_EXP void CK_EXPORT srunner_set_xml (SRunner *sr, const char *fname);
424 
425 /* Does the SRunner have an XML log file? */
427 
428 /* Return the name of the XML file, or NULL if none */
429 CK_DLL_EXP const char * CK_EXPORT srunner_xml_fname (SRunner *sr);
430 
431 
432 /* Control forking */
434  CK_FORK_GETENV, /* look in the environment for CK_FORK */
435  CK_FORK, /* call fork to run tests */
436  CK_NOFORK /* don't call fork */
437 };
438 
439 /* Get the current fork status */
441 
442 /* Set the current fork status */
444 
445 /* Fork in a test and make sure messaging and tests work. */
446 #ifndef _MSC_VER
447 CK_DLL_EXP pid_t CK_EXPORT check_fork(void);
448 
449 /* Wait for the pid and exit. If pid is zero, just exit. */
451 #endif /* _MSC_VER */
452 
453 #ifdef __cplusplus
454 CK_CPPEND
455 #endif
456 
457 #endif /* CHECK_H */