]> git.llucax.com Git - software/mutest.git/blob - mutest.h
c84eb1562c49b924ca763ef5424ae9175694c23b
[software/mutest.git] / mutest.h
1 /*
2  * This file is part of mutest, a simple micro unit testing framework for C.
3  *
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/
7  *
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).
13  *
14  * Please, read the README file for more details.
15  */
16
17 #include <stdio.h> /* fprintf() */
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23 /* verbosity level (each level shows all the previous levels too) */
24 enum {
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 */
31 };
32
33 /* print a message according to the verbosity level */
34 #define mu_print(level, ...) \
35         do { \
36                 if (mutest_verbose_level >= level) { \
37                         if (mutest_verbose_level == MU_ERROR) \
38                                 fprintf(stderr, __VA_ARGS__); \
39                         else \
40                                 fprintf(stdout, __VA_ARGS__); \
41                 } \
42         } while (0)
43
44 /* check that an expression evaluates to true, continue if the check fails */
45 #define mu_check(exp) \
46         do { \
47                 mu_print(MU_CHECK, "\t\t* Checking mu_check(%s)...\n", #exp); \
48                 if (exp) ++mutest_passed_checks; \
49                 else { \
50                         ++mutest_failed_checks; \
51                         mutest_case_failed = 1; \
52                         mu_print(MU_ERROR, "%s:%d: mu_check(%s) failed, " \
53                                         "resuming test case\n", __FILE__, \
54                                         __LINE__, #exp); \
55                 } \
56         } while (0)
57
58 /*
59  * ensure that an expression evaluates to true, abort the current test
60  * case if the check fails
61  */
62 #define mu_ensure(exp) \
63         do { \
64                 mu_print(MU_CHECK, "\t\t* Checking mu_ensure(%s)...\n", #exp);\
65                 if (exp) ++mutest_passed_checks; \
66                 else { \
67                         ++mutest_failed_checks; \
68                         mutest_case_failed = 1; \
69                         mu_print(MU_ERROR, "%s:%d: mu_ensure(%s) failed, " \
70                                         "aborting test case\n", __FILE__, \
71                                         __LINE__, #exp); \
72                         return; \
73                 } \
74         } while (0)
75
76 #ifndef MUTEST_PY /* we are using the C implementation */
77
78 /*
79  * this function implements the test suites execution, you should generate
80  * a module with this function using mkmutest, or take a look to that script
81  * if you want to implement your own customized version */
82 void mu_run_suites();
83
84 /* macro for running a single initialization function */
85 #ifndef mu_run_init
86 #define mu_run_init(name) \
87         { \
88                 int name(); \
89                 int r; \
90                 mu_print(MU_CASE, "\t+ Executing initialization function " \
91                                 "'" #name "'...\n"); \
92                 if ((r = name())) { \
93                         mu_print(MU_ERROR, "%s:" #name ": initialization " \
94                                         "function failed (returned %d), " \
95                                         "skipping test suite...\n", \
96                                         mutest_suite_name, r); \
97                         ++mutest_skipped_suites; \
98                         break; \
99                 } \
100         } do { } while (0)
101 #endif /* mu_run_init */
102
103 /* macro for running a single test case */
104 #ifndef mu_run_case
105 #define mu_run_case(name) \
106         do { \
107                 mu_print(MU_CASE, "\t* Executing test case '" #name "'...\n");\
108                 mutest_case_name = #name; \
109                 void name(); \
110                 name(); \
111                 if (mutest_case_failed) { \
112                         ++mutest_failed_cases; \
113                         mutest_suite_failed = 1; \
114                 } else ++mutest_passed_cases; \
115                 mutest_case_failed = 0; \
116         } while (0)
117 #endif /* mu_run_case */
118
119 /* macro for running a single termination function */
120 #ifndef mu_run_term
121 #define mu_run_term(name) \
122         do { \
123                 mu_print(MU_CASE, "\t- Executing termination function '" \
124                                 #name "'...\n"); \
125                 void name(); \
126                 name(); \
127         } while (0)
128 #endif /* mu_run_term */
129
130 /*
131  * mutest exported variables for internal use, do not use directly unless you
132  *  know what you're doing.
133  */
134 extern const char* mutest_suite_name;
135 extern int mutest_failed_suites;
136 extern int mutest_passed_suites;
137 extern int mutest_skipped_suites;
138 extern int mutest_suite_failed;
139 /* test cases */
140 extern const char* mutest_case_name;
141 extern int mutest_failed_cases;
142 extern int mutest_passed_cases;
143 extern int mutest_case_failed;
144 /* checks */
145 extern int mutest_failed_checks;
146 extern int mutest_passed_checks;
147 /* verbosity */
148 extern int mutest_verbose_level;
149
150 #else /* MUTEST_PY is defined, using the Python implementation */
151
152 /* this increments when the "API" changes, it's just for sanity check */
153 int mutest_api_version = 1;
154
155 int mutest_case_failed; /* unused, for C implementation compatibility */
156
157 int mutest_passed_checks;
158 int mutest_failed_checks;
159 void mutest_reset_counters() {
160         mutest_passed_checks = 0;
161         mutest_failed_checks = 0;
162 }
163
164 int mutest_verbose_level = MU_ERROR;
165 void mutest_set_verbose_level(int val) {
166         mutest_verbose_level = val;
167 }
168
169 #endif /* MUTEST_PY */
170
171 #ifdef __cplusplus
172 }
173 #endif
174