1 | /* Copyright (C) 2006 MySQL AB |
2 | |
3 | This program is free software; you can redistribute it and/or modify |
4 | it under the terms of the GNU General Public License as published by |
5 | the Free Software Foundation; version 2 of the License. |
6 | |
7 | This program is distributed in the hope that it will be useful, |
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | GNU General Public License for more details. |
11 | |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software |
14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
15 | MA 02111-1301, USA |
16 | |
17 | Library for providing TAP support for testing C and C++ was written |
18 | by Mats Kindahl <mats@mysql.com>. |
19 | */ |
20 | |
21 | #ifndef TAP_H |
22 | #define TAP_H |
23 | |
24 | #include "ma_global.h" |
25 | |
26 | /* |
27 | @defgroup MyTAP MySQL support for performing unit tests according to |
28 | the Test Anything Protocol (TAP). |
29 | */ |
30 | |
31 | #define NO_PLAN (0) |
32 | |
33 | /** |
34 | Data about test plan. |
35 | |
36 | @ingroup MyTAP_Internal |
37 | |
38 | @internal We are using the "typedef struct X { ... } X" idiom to |
39 | create class/struct X both in C and C++. |
40 | */ |
41 | |
42 | typedef struct TEST_DATA { |
43 | /** |
44 | Number of tests that is planned to execute. |
45 | |
46 | Can be zero (<code>NO_PLAN</code>) meaning that the plan string |
47 | will be printed at the end of test instead. |
48 | */ |
49 | int plan; |
50 | |
51 | /** Number of last test that was done or skipped. */ |
52 | int last; |
53 | |
54 | /** Number of tests that failed. */ |
55 | int failed; |
56 | |
57 | /** Todo reason. */ |
58 | char todo[128]; |
59 | } TEST_DATA; |
60 | |
61 | #ifdef __cplusplus |
62 | extern "C" { |
63 | #endif |
64 | |
65 | /** |
66 | Defines whether "big" tests should be skipped. |
67 | |
68 | This variable is set by plan() function unless MYTAP_CONFIG environment |
69 | variable is set to the string "big". It is supposed to be used as |
70 | |
71 | @code |
72 | if (skip_big_tests) { |
73 | skip(1, "Big test skipped"); |
74 | } else { |
75 | ok(life_universe_and_everything() == 42, "The answer is CORRECT"); |
76 | } |
77 | @endcode |
78 | |
79 | @see SKIP_BIG_TESTS |
80 | */ |
81 | extern int skip_big_tests; |
82 | |
83 | /** |
84 | @defgroup MyTAP_API MyTAP API |
85 | |
86 | MySQL support for performing unit tests according to TAP. |
87 | |
88 | @{ |
89 | */ |
90 | |
91 | /** |
92 | Set number of tests that is planned to execute. |
93 | |
94 | The function also accepts the predefined constant |
95 | <code>NO_PLAN</code>. If the function is not called, it is as if |
96 | it was called with <code>NO_PLAN</code>, i.e., the test plan will |
97 | be printed after all the test lines. |
98 | |
99 | The plan() function will install signal handlers for all signals |
100 | that generate a core, so if you want to override these signals, do |
101 | it <em>after</em> you have called the plan() function. |
102 | |
103 | It will also set skip_big_tests variable if MYTAP_CONFIG environment |
104 | variable is defined. |
105 | |
106 | @see skip_big_tests |
107 | |
108 | @param count The planned number of tests to run. |
109 | */ |
110 | |
111 | void plan(int const count); |
112 | |
113 | |
114 | /** |
115 | Report test result as a TAP line. |
116 | |
117 | Function used to write status of an individual test. Call this |
118 | function in the following manner: |
119 | |
120 | @code |
121 | ok(ducks == paddling, |
122 | "%d ducks did not paddle", ducks - paddling); |
123 | @endcode |
124 | |
125 | @param pass Zero if the test failed, non-zero if it passed. |
126 | @param fmt Format string in printf() format. NULL is allowed, in |
127 | which case nothing is printed. |
128 | */ |
129 | |
130 | void ok(int const pass, char const *fmt, ...) |
131 | __attribute__((format(printf,2,3))); |
132 | |
133 | |
134 | /** |
135 | Skip a determined number of tests. |
136 | |
137 | Function to print that <em>how_many</em> tests have been skipped. |
138 | The reason is printed for each skipped test. Observe that this |
139 | function does not do the actual skipping for you, it just prints |
140 | information that tests have been skipped. This function is not |
141 | usually used, but rather the macro @c SKIP_BLOCK_IF, which does the |
142 | skipping for you. |
143 | |
144 | It shall be used in the following manner: |
145 | |
146 | @code |
147 | if (ducks == 0) { |
148 | skip(2, "No ducks in the pond"); |
149 | } else { |
150 | int i; |
151 | for (i = 0 ; i < 2 ; ++i) |
152 | ok(duck[i] == paddling, "is duck %d paddling?", i); |
153 | } |
154 | @endcode |
155 | |
156 | @see SKIP_BLOCK_IF |
157 | |
158 | @param how_many Number of tests that are to be skipped. |
159 | @param reason A reason for skipping the tests |
160 | */ |
161 | |
162 | void skip(int how_many, char const *const reason, ...) |
163 | __attribute__((format(printf,2,3))); |
164 | |
165 | |
166 | /** |
167 | Helper macro to skip a block of code. The macro can be used to |
168 | simplify conditionally skipping a block of code. It is used in the |
169 | following manner: |
170 | |
171 | @code |
172 | SKIP_BLOCK_IF(ducks == 0, 2, "No ducks in the pond") |
173 | { |
174 | int i; |
175 | for (i = 0 ; i < 2 ; ++i) |
176 | ok(duck[i] == paddling, "is duck %d paddling?", i); |
177 | } |
178 | @endcode |
179 | |
180 | @see skip |
181 | */ |
182 | |
183 | #define SKIP_BLOCK_IF(SKIP_IF_TRUE, COUNT, REASON) \ |
184 | if (SKIP_IF_TRUE) skip((COUNT),(REASON)); else |
185 | |
186 | |
187 | /** |
188 | Helper macro to skip a group of "big" tests. It is used in the following |
189 | manner: |
190 | |
191 | @code |
192 | SKIP_BIG_TESTS(1) |
193 | { |
194 | ok(life_universe_and_everything() == 42, "The answer is CORRECT"); |
195 | } |
196 | @endcode |
197 | |
198 | @see skip_big_tests |
199 | */ |
200 | |
201 | #define SKIP_BIG_TESTS(COUNT) \ |
202 | if (skip_big_tests) skip((COUNT), "big test"); else |
203 | |
204 | |
205 | /** |
206 | Print a diagnostics message. |
207 | |
208 | @param fmt Diagnostics message in printf() format. |
209 | */ |
210 | |
211 | void diag(char const *fmt, ...) |
212 | __attribute__((format(printf,1,2))); |
213 | |
214 | |
215 | /** |
216 | Print a bail out message. |
217 | |
218 | A bail out message can be issued when no further testing can be |
219 | done, e.g., when there are missing dependencies. |
220 | |
221 | The test will exit with status 255. This function does not return. |
222 | |
223 | @code |
224 | BAIL_OUT("Lost connection to server %s", server_name); |
225 | @endcode |
226 | |
227 | @note A bail out message is printed if a signal that generates a |
228 | core is raised. |
229 | |
230 | @param fmt Bail out message in printf() format. |
231 | */ |
232 | |
233 | void BAIL_OUT(char const *fmt, ...) |
234 | __attribute__((noreturn, format(printf,1,2))); |
235 | |
236 | |
237 | /** |
238 | Print summary report and return exit status. |
239 | |
240 | This function will print a summary report of how many tests passed, |
241 | how many were skipped, and how many remains to do. The function |
242 | should be called after all tests are executed in the following |
243 | manner: |
244 | |
245 | @code |
246 | return exit_status(); |
247 | @endcode |
248 | |
249 | @returns @c EXIT_SUCCESS if all tests passed, @c EXIT_FAILURE if |
250 | one or more tests failed. |
251 | */ |
252 | |
253 | int exit_status(void); |
254 | |
255 | |
256 | /** |
257 | Skip entire test suite. |
258 | |
259 | To skip the entire test suite, use this function. It will |
260 | automatically call exit(), so there is no need to have checks |
261 | around it. |
262 | */ |
263 | |
264 | void skip_all(char const *reason, ...) |
265 | __attribute__((noreturn, format(printf, 1, 2))); |
266 | |
267 | |
268 | /** |
269 | Start section of tests that are not yet ready. |
270 | |
271 | To start a section of tests that are not ready and are expected to |
272 | fail, use this function and todo_end() in the following manner: |
273 | |
274 | @code |
275 | todo_start("Not ready yet"); |
276 | ok(is_rocketeering(duck), "Rocket-propelled ducks"); |
277 | ok(is_kamikaze(duck), "Kamikaze ducks"); |
278 | todo_end(); |
279 | @endcode |
280 | |
281 | @see todo_end |
282 | |
283 | @note |
284 | It is not possible to nest todo sections. |
285 | |
286 | @param message Message that will be printed before the todo tests. |
287 | */ |
288 | |
289 | void todo_start(char const *message, ...) |
290 | __attribute__((format(printf, 1, 2))); |
291 | |
292 | |
293 | /** |
294 | End a section of tests that are not yet ready. |
295 | */ |
296 | |
297 | void todo_end(); |
298 | |
299 | /** @} */ |
300 | |
301 | #ifdef __cplusplus |
302 | } |
303 | #endif |
304 | |
305 | #endif /* TAP_H */ |
306 | |