ucx/cx/test.h

changeset 440
7c4b9cba09ca
parent 324
ce13a778654a
equal deleted inserted replaced
439:bf7084544cb1 440:7c4b9cba09ca
33 * 33 *
34 * Usage of this test framework: 34 * Usage of this test framework:
35 * 35 *
36 * **** IN HEADER FILE: **** 36 * **** IN HEADER FILE: ****
37 * 37 *
38 * <pre> 38 * <code>
39 * CX_TEST(function_name); 39 * CX_TEST(function_name);
40 * CX_TEST_SUBROUTINE(subroutine_name, paramlist); // optional 40 * CX_TEST_SUBROUTINE(subroutine_name, paramlist); // optional
41 * </pre> 41 * </code>
42 * 42 *
43 * **** IN SOURCE FILE: **** 43 * **** IN SOURCE FILE: ****
44 * <pre> 44 * <code>
45 * CX_TEST_SUBROUTINE(subroutine_name, paramlist) { 45 * CX_TEST_SUBROUTINE(subroutine_name, paramlist) {
46 * // tests with CX_TEST_ASSERT() 46 * // tests with CX_TEST_ASSERT()
47 * } 47 * }
48 * 48 *
49 * CX_TEST(function_name) { 49 * CX_TEST(function_name) {
52 * // tests with CX_TEST_ASSERT() and/or 52 * // tests with CX_TEST_ASSERT() and/or
53 * // calls with CX_TEST_CALL_SUBROUTINE() here 53 * // calls with CX_TEST_CALL_SUBROUTINE() here
54 * } 54 * }
55 * // cleanup of memory here 55 * // cleanup of memory here
56 * } 56 * }
57 * </pre> 57 * </code>
58 * 58 *
59 * @attention Do not call own functions within a test, that use 59 * @attention Do not call own functions within a test, that use
60 * CX_TEST_ASSERT() macros and are not defined by using CX_TEST_SUBROUTINE(). 60 * CX_TEST_ASSERT() macros and are not defined by using CX_TEST_SUBROUTINE().
61 * 61 *
62 * @author Mike Becker 62 * @author Mike Becker
65 */ 65 */
66 66
67 #ifndef UCX_TEST_H 67 #ifndef UCX_TEST_H
68 #define UCX_TEST_H 68 #define UCX_TEST_H
69 69
70 #include <stdlib.h> 70 #include "common.h"
71
71 #include <stdio.h> 72 #include <stdio.h>
72 #include <string.h> 73 #include <string.h>
73 #include <setjmp.h> 74 #include <setjmp.h>
74 75
75 #ifdef __cplusplus 76 #ifdef __cplusplus
84 * <code>__func__</code>. 85 * <code>__func__</code>.
85 */ 86 */
86 #define __FUNCTION__ __func__ 87 #define __FUNCTION__ __func__
87 #endif 88 #endif
88 89
89 //
90 #if !defined(__clang__) && __GNUC__ > 3 90 #if !defined(__clang__) && __GNUC__ > 3
91 #pragma GCC diagnostic ignored "-Wclobbered" 91 #pragma GCC diagnostic ignored "-Wclobbered"
92 #endif 92 #endif
93
94 #ifndef UCX_COMMON_H
95 /**
96 * Function pointer compatible with fwrite-like functions.
97 */
98 typedef size_t (*cx_write_func)(
99 const void *,
100 size_t,
101 size_t,
102 void *
103 );
104 #endif // UCX_COMMON_H
105 93
106 /** Type for the CxTestSuite. */ 94 /** Type for the CxTestSuite. */
107 typedef struct CxTestSuite CxTestSuite; 95 typedef struct CxTestSuite CxTestSuite;
108 96
109 /** Pointer to a test function. */ 97 /** Pointer to a test function. */
146 /** 134 /**
147 * Creates a new test suite. 135 * Creates a new test suite.
148 * @param name optional name of the suite 136 * @param name optional name of the suite
149 * @return a new test suite 137 * @return a new test suite
150 */ 138 */
139 cx_attr_nonnull
140 cx_attr_nodiscard
141 cx_attr_cstr_arg(1)
142 cx_attr_malloc
151 static inline CxTestSuite* cx_test_suite_new(const char *name) { 143 static inline CxTestSuite* cx_test_suite_new(const char *name) {
152 CxTestSuite* suite = (CxTestSuite*) malloc(sizeof(CxTestSuite)); 144 CxTestSuite* suite = (CxTestSuite*) malloc(sizeof(CxTestSuite));
153 if (suite != NULL) { 145 if (suite != NULL) {
154 suite->name = name; 146 suite->name = name;
155 suite->success = 0; 147 suite->success = 0;
159 151
160 return suite; 152 return suite;
161 } 153 }
162 154
163 /** 155 /**
164 * Destroys a test suite. 156 * Deallocates a test suite.
165 * @param suite the test suite to destroy 157 *
158 * @param suite the test suite to free
166 */ 159 */
167 static inline void cx_test_suite_free(CxTestSuite* suite) { 160 static inline void cx_test_suite_free(CxTestSuite* suite) {
161 if (suite == NULL) return;
168 CxTestSet *l = suite->tests; 162 CxTestSet *l = suite->tests;
169 while (l != NULL) { 163 while (l != NULL) {
170 CxTestSet *e = l; 164 CxTestSet *e = l;
171 l = l->next; 165 l = l->next;
172 free(e); 166 free(e);
177 /** 171 /**
178 * Registers a test function with the specified test suite. 172 * Registers a test function with the specified test suite.
179 * 173 *
180 * @param suite the suite, the test function shall be added to 174 * @param suite the suite, the test function shall be added to
181 * @param test the test function to register 175 * @param test the test function to register
182 * @return zero on success or non-zero on failure 176 * @retval zero success
183 */ 177 * @retval non-zero failure
178 */
179 cx_attr_nonnull
184 static inline int cx_test_register(CxTestSuite* suite, CxTest test) { 180 static inline int cx_test_register(CxTestSuite* suite, CxTest test) {
185 CxTestSet *t = (CxTestSet*) malloc(sizeof(CxTestSet)); 181 CxTestSet *t = (CxTestSet*) malloc(sizeof(CxTestSet));
186 if (t) { 182 if (t) {
187 t->test = test; 183 t->test = test;
188 t->next = NULL; 184 t->next = NULL;
203 199
204 /** 200 /**
205 * Runs a test suite and writes the test log to the specified stream. 201 * Runs a test suite and writes the test log to the specified stream.
206 * @param suite the test suite to run 202 * @param suite the test suite to run
207 * @param out_target the target buffer or file to write the output to 203 * @param out_target the target buffer or file to write the output to
208 * @param out_writer the write function writing to \p out_target 204 * @param out_writer the write function writing to @p out_target
209 */ 205 */
206 cx_attr_nonnull
210 static inline void cx_test_run(CxTestSuite *suite, 207 static inline void cx_test_run(CxTestSuite *suite,
211 void *out_target, cx_write_func out_writer) { 208 void *out_target, cx_write_func out_writer) {
212 if (suite->name == NULL) { 209 if (suite->name == NULL) {
213 out_writer("*** Test Suite ***\n", 1, 19, out_target); 210 out_writer("*** Test Suite ***\n", 1, 19, out_target);
214 } else { 211 } else {
231 out_writer(total, 1, len, out_target); 228 out_writer(total, 1, len, out_target);
232 } 229 }
233 230
234 /** 231 /**
235 * Runs a test suite and writes the test log to the specified FILE stream. 232 * Runs a test suite and writes the test log to the specified FILE stream.
236 * @param suite the test suite to run 233 * @param suite (@c CxTestSuite*) the test suite to run
237 * @param file the target file to write the output to 234 * @param file (@c FILE*) the target file to write the output to
238 */ 235 */
239 #define cx_test_run_f(suite, file) cx_test_run(suite, (void*)file, (cx_write_func)fwrite) 236 #define cx_test_run_f(suite, file) cx_test_run(suite, (void*)file, (cx_write_func)fwrite)
240 237
241 /** 238 /**
242 * Runs a test suite and writes the test log to stdout. 239 * Runs a test suite and writes the test log to stdout.
243 * @param suite the test suite to run 240 * @param suite (@c CxTestSuite*) the test suite to run
244 */ 241 */
245 #define cx_test_run_stdout(suite) cx_test_run_f(suite, stdout) 242 #define cx_test_run_stdout(suite) cx_test_run_f(suite, stdout)
246 243
247 /** 244 /**
248 * Macro for a #CxTest function header. 245 * Macro for a #CxTest function header.
253 */ 250 */
254 #define CX_TEST(name) void name(CxTestSuite* _suite_,void *_output_, cx_write_func _writefnc_) 251 #define CX_TEST(name) void name(CxTestSuite* _suite_,void *_output_, cx_write_func _writefnc_)
255 252
256 /** 253 /**
257 * Defines the scope of a test. 254 * Defines the scope of a test.
255 *
256 * @code
257 * CX_TEST(my_test_name) {
258 * // setup code
259 * CX_TEST_DO {
260 * // your tests go here
261 * }
262 * // tear down code
263 * }
264 * @endcode
265 *
258 * @attention Any CX_TEST_ASSERT() calls must be performed in scope of 266 * @attention Any CX_TEST_ASSERT() calls must be performed in scope of
259 * #CX_TEST_DO. 267 * #CX_TEST_DO.
260 */ 268 */
261 #define CX_TEST_DO _writefnc_("Running ", 1, 8, _output_);\ 269 #define CX_TEST_DO _writefnc_("Running ", 1, 8, _output_);\
262 _writefnc_(__FUNCTION__, 1, strlen(__FUNCTION__), _output_);\ 270 _writefnc_(__FUNCTION__, 1, strlen(__FUNCTION__), _output_);\
270 /** 278 /**
271 * Checks a test assertion. 279 * Checks a test assertion.
272 * If the assertion is correct, the test carries on. If the assertion is not 280 * If the assertion is correct, the test carries on. If the assertion is not
273 * correct, the specified message (terminated by a dot and a line break) is 281 * correct, the specified message (terminated by a dot and a line break) is
274 * written to the test suites output stream. 282 * written to the test suites output stream.
275 * @param condition the condition to check 283 * @param condition (@c bool) the condition to check
276 * @param message the message that shall be printed out on failure 284 * @param message (@c char*) the message that shall be printed out on failure
277 */ 285 */
278 #define CX_TEST_ASSERTM(condition,message) if (!(condition)) { \ 286 #define CX_TEST_ASSERTM(condition,message) if (!(condition)) { \
279 const char *_assert_msg_ = message; \ 287 const char *_assert_msg_ = message; \
280 _writefnc_(_assert_msg_, 1, strlen(_assert_msg_), _output_); \ 288 _writefnc_(_assert_msg_, 1, strlen(_assert_msg_), _output_); \
281 _writefnc_(".\n", 1, 2, _output_); \ 289 _writefnc_(".\n", 1, 2, _output_); \
286 /** 294 /**
287 * Checks a test assertion. 295 * Checks a test assertion.
288 * If the assertion is correct, the test carries on. If the assertion is not 296 * If the assertion is correct, the test carries on. If the assertion is not
289 * correct, the specified message (terminated by a dot and a line break) is 297 * correct, the specified message (terminated by a dot and a line break) is
290 * written to the test suites output stream. 298 * written to the test suites output stream.
291 * @param condition the condition to check 299 * @param condition (@c bool) the condition to check
292 */ 300 */
293 #define CX_TEST_ASSERT(condition) CX_TEST_ASSERTM(condition, #condition " failed") 301 #define CX_TEST_ASSERT(condition) CX_TEST_ASSERTM(condition, #condition " failed")
294 302
295 /** 303 /**
296 * Macro for a test subroutine function header. 304 * Macro for a test subroutine function header.

mercurial