2 * This file is part of mutest, a simple micro unit testing framework for C.
4 * mutest was written by Leandro Lucarella <llucax@gmail.com> and is released
5 * under the BOLA license, please see the LICENSE file or visit:
6 * http://blitiri.com.ar/p/bola/
8 * This header file should be included in the source files that will make up
9 * a test suite. It's used for both C and Python implementation, but when
10 * using the Python implementation you should define the MUTEST_PY macro.
11 * If you implement your mu_run_suites() function yourself, you probably will
12 * need to include this header too (see mkmutest).
14 * Please, read the README file for more details.
17 #include <stdio.h> /* fprintf() */
23 /* verbosity level (each level shows all the previous levels too) */
25 MU_QUIET = 0, /* be completely quiet */
26 MU_ERROR, /* shows errors only */
27 MU_SUMMARY, /* shows a summary */
28 MU_SUITE, /* shows test suites progress */
29 MU_CASE, /* shows test cases progress */
30 MU_CHECK /* shows the current running check */
33 /* print a message according to the verbosity level */
34 #define mu_print(level, ...) \
36 if (mutest_verbose_level >= level) { \
37 if (mutest_verbose_level == MU_ERROR) \
38 fprintf(stderr, __VA_ARGS__); \
40 fprintf(stdout, __VA_ARGS__); \
44 /* print an error message */
45 #define mu_printerr(name, action) \
46 mu_print(MU_ERROR, __FILE__ ":%d: " name " failed, "\
47 action " test case\n", __LINE__);
49 /* modify the internal state so a failure gets counted */
50 #define mutest_count_err ++mutest_failed_checks; mutest_case_failed = 1;
52 /* modify the internal state so a success gets counted */
53 #define mutest_count_suc ++mutest_passed_checks;
59 /* print an error message triggered by a C++ exception */
60 #define mu_printex(name, action, ex) \
61 mu_print(MU_ERROR, __FILE__ ":%d: " name " failed, " \
62 "exception thrown (%s), " action \
63 " test case\n", __LINE__, ex);
65 #define mutest_try try {
66 #define mutest_catch(name, action, final) \
67 } catch (const std::exception& e) { \
69 mu_printex(name, action, e.what()); \
73 mu_printex(name, action, "[unknown]"); \
77 #else /* !__cplusplus */
80 #define mutest_catch(name, action, exp)
82 #endif /* __cplusplus */
84 /* check that an expression evaluates to true, continue if the check fails */
85 #define mu_check_base(exp, name, action, final) \
87 mu_print(MU_CHECK, "\t\t* Checking " name "(" #exp ")...\n"); \
89 if (exp) mutest_count_suc \
92 mu_printerr(name "(" #exp ")", action); \
95 mutest_catch(name, action, final) \
98 /* check that an expression evaluates to true, continue if the check fails */
99 #define mu_check(exp) mu_check_base(exp, "mu_check", "resuming", continue)
102 * ensure that an expression evaluates to true, abort the current test
103 * case if the check fails
105 #define mu_ensure(exp) mu_check_base(exp, "mu_ensure", "aborting", return)
109 #define mu_echeck_base(ex, exp, name, action, final) \
111 mu_print(MU_CHECK, "\t\t* Checking " name "(" #ex ", " #exp \
116 mu_printerr(name "(" #ex ", " #exp ")", \
117 "no exception thrown, " action); \
119 } catch (const ex& e) { \
121 } catch (const std::exception& e) { \
123 mu_printex(name "(" #ex ", " #exp ")", action, \
128 mu_printex(name "(" #ex ", " #exp ")", action, \
135 * check that an expression throws a particular exception, continue if the
138 #define mu_echeck(ex, exp) \
139 mu_echeck_base(ex, exp, "mu_echeck", "resuming", continue)
142 * ensure that an expression throws a particular exception, abort the current
143 * test case if the check fails
145 #define mu_eensure(ex, exp) \
146 mu_echeck_base(ex, exp, "mu_eensure", "aborting", return)
148 #endif /* __cplusplus */
150 #ifndef MUTEST_PY /* we are using the C implementation */
153 * this function implements the test suites execution, you should generate
154 * a module with this function using mkmutest, or take a look to that script
155 * if you want to implement your own customized version */
156 void mu_run_suites();
158 /* macro for running a single initialization function */
160 #define mu_run_init(name) \
164 mu_print(MU_CASE, "\t+ Executing initialization function " \
165 "'" #name "'...\n"); \
166 if ((r = name())) { \
167 mu_print(MU_ERROR, "%s:" #name ": initialization " \
168 "function failed (returned %d), " \
169 "skipping test suite...\n", \
170 mutest_suite_name, r); \
171 ++mutest_skipped_suites; \
175 #endif /* mu_run_init */
177 /* macro for running a single test case */
179 #define mu_run_case(name) \
181 mu_print(MU_CASE, "\t* Executing test case '" #name "'...\n");\
182 mutest_case_name = #name; \
185 if (mutest_case_failed) { \
186 ++mutest_failed_cases; \
187 mutest_suite_failed = 1; \
188 } else ++mutest_passed_cases; \
189 mutest_case_failed = 0; \
191 #endif /* mu_run_case */
193 /* macro for running a single termination function */
195 #define mu_run_term(name) \
197 mu_print(MU_CASE, "\t- Executing termination function '" \
202 #endif /* mu_run_term */
205 * mutest exported variables for internal use, do not use directly unless you
206 * know what you're doing.
208 extern const char* mutest_suite_name;
209 extern int mutest_failed_suites;
210 extern int mutest_passed_suites;
211 extern int mutest_skipped_suites;
212 extern int mutest_suite_failed;
214 extern const char* mutest_case_name;
215 extern int mutest_failed_cases;
216 extern int mutest_passed_cases;
217 extern int mutest_case_failed;
219 extern int mutest_failed_checks;
220 extern int mutest_passed_checks;
222 extern int mutest_verbose_level;
224 #else /* MUTEST_PY is defined, using the Python implementation */
226 /* this increments when the "API" changes, it's just for sanity check */
227 int mutest_api_version = 1;
229 int mutest_case_failed; /* unused, for C implementation compatibility */
231 int mutest_passed_checks;
232 int mutest_failed_checks;
233 void mutest_reset_counters() {
234 mutest_passed_checks = 0;
235 mutest_failed_checks = 0;
238 int mutest_verbose_level = MU_ERROR;
239 void mutest_set_verbose_level(int val) {
240 mutest_verbose_level = val;
243 #endif /* MUTEST_PY */