1 /*
2  * Copyright (c) 2013, Google, Inc. All rights reserved
3  * Copyright 2016 The Fuchsia Authors
4  *
5  * Use of this source code is governed by a MIT-style
6  * license that can be found in the LICENSE file or at
7  * https://opensource.org/licenses/MIT
8  */
9 #pragma once
10 /*
11  * Macros for writing unit tests.
12  *
13  * Sample usage:
14  *
15  * A test case runs a collection of tests like this, with
16  * BEGIN_TEST_CASE and END_TEST_CASE and the beginning and end of the
17  * function and RUN_TEST to call each individual test, as follows:
18  *
19  *  BEGIN_TEST_CASE(foo_tests);
20  *
21  *  RUN_TEST(test_foo);
22  *  RUN_TEST(test_bar);
23  *  RUN_TEST(test_baz);
24  *
25  *  END_TEST_CASE;
26  *
27  * This creates a static function foo_tests() and registers it with the
28  * unit test framework.  foo_tests() can be executed either by a shell
29  * command or by a call to run_all_tests(), which runs all registered
30  * unit tests.
31  *
32  * A test looks like this, using the BEGIN_TEST and END_TEST macros at
33  * the beginning and end of the test and the EXPECT_* macros to
34  * validate test results, as shown:
35  *
36  * static bool test_foo(void)
37  * {
38  *      BEGIN_TEST;
39  *
40  *      ...declare variables and do stuff...
41  *      int foo_value = foo_func();
42  *      ...See if the stuff produced the correct value...
43  *      EXPECT_EQ(1, foo_value, "foo_func failed");
44  *      ... there are EXPECT_* macros for many conditions...
45  *      EXPECT_TRUE(foo_condition(), "condition should be true");
46  *      EXPECT_NEQ(ERR_TIMED_OUT, foo_event(), "event timed out");
47  *
48  *      END_TEST;
49  * }
50  *
51  * To your rules.mk file, add lib/unittest to MODULE_DEPS:
52  *
53  * MODULE_DEPS += \
54  *         lib/unittest   \
55  */
56 #include <printf.h>
57 #include <stdbool.h>
58 #include <stdio.h>
59 #include <stddef.h>
60 #include <stdint.h>
61 #include <string.h>
62 #include <stdarg.h>
63 
64 /*
65  * Printf dedicated to the unittest library
66  * the default output is the printf
67  */
68 void unittest_printf (const char *format, ...) __PRINTFLIKE(1, 2);
69 
70 /*
71  * Function to set the callback for printing
72  * the unit test output
73  */
74 void unittest_set_output_function (_printf_engine_output_func fun, void *arg);
75 
76 /*
77  * Macros to format the error string
78  */
79 #define EXPECTED_STRING "%s\n        expected "
80 #define UNITTEST_FAIL_TRACEF_FORMAT "\n        [FAILED]\n        %s:%d: "
81 #define UNITTEST_FAIL_TRACEF(str, x...)                                                   \
82   do {                                                                                    \
83     unittest_printf(UNITTEST_FAIL_TRACEF_FORMAT str, __PRETTY_FUNCTION__, __LINE__, ##x); \
84   } while (0)
85 
86 /*
87  * BEGIN_TEST_CASE and END_TEST_CASE define a function that calls
88  * RUN_TEST.
89  */
90 #define BEGIN_TEST_CASE(case_name)              \
91     bool case_name(void);                       \
92     bool case_name(void)                        \
93     {                                           \
94     bool all_ok = true;                    \
95     unittest_printf("\nCASE %-49s [STARTED] \n", #case_name);
96 
97 #define DEFINE_REGISTER_TEST_CASE(case_name)                            \
98     static void _register_##case_name(void)                             \
99     {                                                                   \
100         unittest_register_test_case(&_##case_name##_element);           \
101     }                                                                   \
102     void (*_register_##case_name##_ptr)(void) __SECTION(".ctors") =     \
103         _register_##case_name;
104 
105 #define END_TEST_CASE(case_name)                                        \
106     if (all_ok) {                                                  \
107         unittest_printf("CASE %-59s [PASSED]\n", #case_name);           \
108     } else {                                                            \
109         unittest_printf("CASE %-59s [FAILED]\n", #case_name);           \
110     }                                                                   \
111         return all_ok;                                             \
112     }                                                                   \
113     static struct test_case_element _##case_name##_element = {          \
114         .next = NULL,                                                   \
115         .failed_next = NULL,                                            \
116         .name = #case_name,                                             \
117         .test_case = case_name,                                         \
118     };                                                                  \
119     DEFINE_REGISTER_TEST_CASE(case_name);
120 
121 #define RUN_TEST(test)                                  \
122     unittest_printf("    %-50s [RUNNING]",  #test );    \
123     if (! test ()) {                                    \
124          all_ok = false;                           \
125     } else {                                            \
126         unittest_printf(" [PASSED] \n");                \
127     }
128 
129 #define RUN_NAMED_TEST(name, test)                                  \
130     unittest_printf("    %-50s [RUNNING]",  name );    \
131     if (! test ()) {                                    \
132          all_ok = false;                           \
133     } else {                                            \
134         unittest_printf(" [PASSED] \n");                \
135     }
136 
137 
138 /*
139  * BEGIN_TEST and END_TEST go in a function that is called by RUN_TEST
140  * and that call the EXPECT_ macros.
141  */
142 #define BEGIN_TEST bool all_ok = true
143 #define END_TEST return all_ok
144 
145 #ifdef __cplusplus
146 #define AUTO_TYPE_VAR(type) auto&
147 #else
148 #define AUTO_TYPE_VAR(type) __typeof__(type)
149 #endif
150 
151 // The following helper function makes the "msg" argument optional in
152 // C++, so that you can write either of the following:
153 //   ASSERT_EQ(x, y, "Check that x equals y");
154 //   ASSERT_EQ(x, y);
155 // (We could allow the latter in C by making unittest_get_msg() a
156 // var-args function, but that would be less type safe.)
unittest_get_msg(const char * arg)157 static inline const char* unittest_get_msg(const char* arg) {
158     return arg;
159 }
160 #ifdef __cplusplus
unittest_get_msg()161 static inline constexpr const char* unittest_get_msg() {
162     return "<no message>";
163 }
164 #endif
165 
166 /*
167  * UTCHECK_* macros are used to check test results.  Generally, one should
168  * prefer to use either the EXPECT_* (non-terminating) or ASSERT_*
169  * (terminating) forms of the macros.  See below.
170  *
171  * The parameter after |term| is an optional message (const char*) to be printed
172  * if the check fails.
173  */
174 #define UTCHECK_EQ(expected, actual, term, ...)                            \
175     {                                                                      \
176         const AUTO_TYPE_VAR(actual) _e = expected;                                \
177         const AUTO_TYPE_VAR(actual) _a = actual;                                  \
178         if (_e != _a) {                                                    \
179             UNITTEST_FAIL_TRACEF (EXPECTED_STRING "%s (%ld), "             \
180                    "actual %s (%ld)\n",                                    \
181                    unittest_get_msg(__VA_ARGS__), #expected, (long)_e, #actual, (long)_a);           \
182             if (term) {                                                    \
183                 return false;                                              \
184             }                                                              \
185             all_ok = false;                                                \
186         }                                                                  \
187     }
188 
189 #define UTCHECK_NE(expected, actual, term, ...)                            \
190     {                                                                      \
191         const AUTO_TYPE_VAR(expected) _e = expected;                              \
192         const AUTO_TYPE_VAR(actual) _a = actual;                                  \
193         if (_e == _a) {                                                    \
194             UNITTEST_FAIL_TRACEF(EXPECTED_STRING "%s (%ld), %s"            \
195                    " to differ, but they are the same\n",                  \
196                    unittest_get_msg(__VA_ARGS__), #expected, (long)_e, #actual);                     \
197             if (term) {                                                    \
198                 return false;                                              \
199             }                                                              \
200             all_ok = false;                                                \
201         }                                                                  \
202     }
203 
204 #define UTCHECK_LE(expected, actual, term, ...)                            \
205     {                                                                      \
206         const AUTO_TYPE_VAR(actual) _e = expected;                                \
207         const AUTO_TYPE_VAR(actual) _a = actual;                                  \
208         if (_e > _a) {                                                     \
209             UNITTEST_FAIL_TRACEF(EXPECTED_STRING "%s (%ld) to be"          \
210                    " less-than-or-equal-to actual %s (%ld)\n",             \
211                    unittest_get_msg(__VA_ARGS__), #expected, (long)_e, #actual, (long)_a);           \
212             if (term) {                                                    \
213                 return false;                                              \
214             }                                                              \
215             all_ok = false;                                                \
216         }                                                                  \
217     }
218 
219 #define UTCHECK_LT(expected, actual, term, ...)                            \
220     {                                                                      \
221         const AUTO_TYPE_VAR(actual) _e = expected;                                \
222         const AUTO_TYPE_VAR(actual) _a = actual;                                  \
223         if (_e >= _a) {                                                    \
224             UNITTEST_FAIL_TRACEF(EXPECTED_STRING "%s (%ld) to be"          \
225                    " less-than actual %s (%ld)\n",                         \
226                    unittest_get_msg(__VA_ARGS__), #expected, (long)_e, #actual, (long)_a);           \
227             if (term) {                                                    \
228                 return false;                                              \
229             }                                                              \
230             all_ok = false;                                                \
231         }                                                                  \
232     }
233 
234 #define UTCHECK_GE(expected, actual, term, ...)                            \
235     {                                                                      \
236         const AUTO_TYPE_VAR(actual) _e = expected;                                \
237         const AUTO_TYPE_VAR(actual) _a = actual;                                  \
238         if (_e < _a) {                                                     \
239             UNITTEST_FAIL_TRACEF(EXPECTED_STRING "%s (%ld) to be"          \
240                    " greater-than-or-equal-to actual %s (%ld)\n",          \
241                    unittest_get_msg(__VA_ARGS__), #expected, (long)_e, #actual, (long)_a);           \
242             if (term) {                                                    \
243                 return false;                                              \
244             }                                                              \
245             all_ok = false;                                                \
246         }                                                                  \
247     }
248 
249 #define UTCHECK_GT(expected, actual, term, ...)                            \
250     {                                                                      \
251         const AUTO_TYPE_VAR(actual) _e = expected;                                \
252         const AUTO_TYPE_VAR(actual) _a = actual;                                  \
253         if (_e <= _a) {                                                    \
254             UNITTEST_FAIL_TRACEF(EXPECTED_STRING "%s (%ld) to be"          \
255                    " greater-than actual %s (%ld)\n",                      \
256                    unittest_get_msg(__VA_ARGS__), #expected, (long)_e, #actual, (long)_a);           \
257             if (term) {                                                    \
258                 return false;                                              \
259             }                                                              \
260             all_ok = false;                                                \
261         }                                                                  \
262     }
263 
264 #define UTCHECK_TRUE(actual, term, ...)                                    \
265     if (!(actual)) {                                                       \
266         UNITTEST_FAIL_TRACEF("%s: %s is false\n", unittest_get_msg(__VA_ARGS__), #actual);           \
267         if (term) {                                                        \
268             return false;                                                  \
269         }                                                                  \
270         all_ok = false;                                                    \
271     }
272 
273 #define UTCHECK_FALSE(actual, term, ...)                                   \
274     if (actual) {                                                          \
275         UNITTEST_FAIL_TRACEF("%s: %s is true\n", unittest_get_msg(__VA_ARGS__), #actual);            \
276         if (term) {                                                        \
277             return false;                                                  \
278         }                                                                  \
279         all_ok = false;                                                    \
280     }
281 
282 #define UTCHECK_NULL(actual, term, ...)                                    \
283     if (actual != NULL) {                                                  \
284         UNITTEST_FAIL_TRACEF("%s: %s is non-null\n", unittest_get_msg(__VA_ARGS__), #actual);        \
285         if (term) {                                                        \
286             return false;                                                  \
287         }                                                                  \
288         all_ok = false;                                                    \
289     }
290 
291 #define UTCHECK_NONNULL(actual, term, ...)                                 \
292     if (actual == NULL) {                                                  \
293         UNITTEST_FAIL_TRACEF("%s: %s is null\n", unittest_get_msg(__VA_ARGS__), #actual);            \
294         if (term) {                                                        \
295             return false;                                                  \
296         }                                                                  \
297         all_ok = false;                                                    \
298     }
299 
300 
301 #define UTCHECK_BYTES_EQ(expected, actual, length, term, ...)              \
302     if (!expect_bytes_eq(expected, actual, length, unittest_get_msg(__VA_ARGS__))) {                 \
303         if (term) {                                                        \
304             return false;                                                  \
305         }                                                                  \
306         all_ok = false;                                                    \
307     }
308 
309 #define UTCHECK_BYTES_NE(bytes1, bytes2, length, term, ...)                \
310     if (!memcmp(bytes1, bytes2, length)) {                                 \
311         UNITTEST_FAIL_TRACEF("%s and %s are the same; "                    \
312                "expected different\n", #bytes1, #bytes2);                  \
313         hexdump8(bytes1, length);                                          \
314         if (term) {                                                        \
315             return false;                                                  \
316         }                                                                  \
317         all_ok = false;                                                    \
318     }
319 
320 /* For comparing uint64_t, like hw_id_t. */
321 #define UTCHECK_EQ_LL(expected, actual, term, ...)                         \
322     {                                                                      \
323         const AUTO_TYPE_VAR(actual) _e = expected;                                \
324         const AUTO_TYPE_VAR(actual) _a = actual;                                  \
325         if (_e != _a) {                                                    \
326             UNITTEST_FAIL_TRACEF("%s: expected %llu, actual %llu\n",       \
327                    unittest_get_msg(__VA_ARGS__), _e, _a);                                           \
328             if (term) {                                                    \
329                 return false;                                              \
330             }                                                              \
331             all_ok = false;                                                \
332         }                                                                  \
333     }
334 
335 /* EXPECT_* macros check the supplied condition and will print a diagnostic
336  * message and flag the test as having failed if the condition fails.  The test
337  * will continue to run, even if the condition fails.
338  *
339  * The last parameter is an optional const char* message to be included in the
340  * print diagnostic message.
341  */
342 #define EXPECT_EQ(expected, actual, ...) UTCHECK_EQ(expected, actual, false, __VA_ARGS__)
343 #define EXPECT_NE(expected, actual, ...) UTCHECK_NE(expected, actual, false, __VA_ARGS__)
344 #define EXPECT_LE(expected, actual, ...) UTCHECK_LE(expected, actual, false, __VA_ARGS__)
345 #define EXPECT_LT(expected, actual, ...) UTCHECK_LT(expected, actual, false, __VA_ARGS__)
346 #define EXPECT_GE(expected, actual, ...) UTCHECK_GE(expected, actual, false, __VA_ARGS__)
347 #define EXPECT_GT(expected, actual, ...) UTCHECK_GT(expected, actual, false, __VA_ARGS__)
348 #define EXPECT_TRUE(actual, ...) UTCHECK_TRUE(actual, false, __VA_ARGS__)
349 #define EXPECT_FALSE(actual, ...) UTCHECK_FALSE(actual, false, __VA_ARGS__)
350 #define EXPECT_BYTES_EQ(expected, actual, length, ...) \
351   UTCHECK_BYTES_EQ(expected, actual, length, false, __VA_ARGS__)
352 #define EXPECT_BYTES_NE(bytes1, bytes2, length, ...) \
353   UTCHECK_BYTES_NE(bytes1, bytes2, length, false, __VA_ARGS__)
354 #define EXPECT_EQ_LL(expected, actual, ...) UTCHECK_EQ_LL(expected, actual, false, __VA_ARGS__)
355 #define EXPECT_NULL(actual, ...) UTCHECK_NULL(actual, false, __VA_ARGS__)
356 #define EXPECT_NONNULL(actual, ...) UTCHECK_NONNULL(actual, false, __VA_ARGS__)
357 #define EXPECT_OK(actual, ...) UTCHECK_EQ(ZX_OK, actual, false, __VA_ARGS__)
358 
359 /* ASSERT_* macros check the condition and will print a message and immediately
360  * abort a test with a filure status if the condition fails.
361  */
362 #define ASSERT_EQ(expected, actual, ...) UTCHECK_EQ(expected, actual, true, __VA_ARGS__)
363 #define ASSERT_NE(expected, actual, ...) UTCHECK_NE(expected, actual, true, __VA_ARGS__)
364 #define ASSERT_LE(expected, actual, ...) UTCHECK_LE(expected, actual, true, __VA_ARGS__)
365 #define ASSERT_LT(expected, actual, ...) UTCHECK_LT(expected, actual, true, __VA_ARGS__)
366 #define ASSERT_GE(expected, actual, ...) UTCHECK_GE(expected, actual, true, __VA_ARGS__)
367 #define ASSERT_GT(expected, actual, ...) UTCHECK_GT(expected, actual, true, __VA_ARGS__)
368 #define ASSERT_TRUE(actual, ...) UTCHECK_TRUE(actual, true, __VA_ARGS__)
369 #define ASSERT_FALSE(actual, ...) UTCHECK_FALSE(actual, true, __VA_ARGS__)
370 #define ASSERT_BYTES_EQ(expected, actual, length, ...) \
371   UTCHECK_BYTES_EQ(expected, actual, length, true, __VA_ARGS__)
372 #define ASSERT_BYTES_NE(bytes1, bytes2, length, ...) \
373   UTCHECK_BYTES_NE(bytes1, bytes2, length, true, __VA_ARGS__)
374 #define ASSERT_EQ_LL(expected, actual, ...) UTCHECK_EQ_LL(expected, actual, true, __VA_ARGS__)
375 #define ASSERT_NULL(actual, ...) UTCHECK_NULL(actual, true, __VA_ARGS__)
376 #define ASSERT_NONNULL(actual, ...) UTCHECK_NONNULL(actual, true, __VA_ARGS__)
377 #define ASSERT_OK(actual, ...) UTCHECK_EQ(ZX_OK, actual, true, __VA_ARGS__)
378 
379 /*
380  * The list of test cases is made up of these elements.
381  */
382 struct test_case_element {
383     struct test_case_element *next;
384     struct test_case_element *failed_next;
385     const char *name;
386     bool (*test_case)(void);
387 };
388 
389 
390 /*
391  * Registers a test case with the unit test framework.
392  */
393 void unittest_register_test_case(struct test_case_element *elem);
394 
395 /*
396  * Runs all registered test cases.
397  */
398 bool run_all_tests(void);
399 
400 /*
401  * Returns false if expected does not equal actual and prints msg and a hexdump8
402  * of the input buffers.
403  */
404 bool expect_bytes_eq(const uint8_t *expected, const uint8_t *actual, size_t len,
405                      const char *msg);
406