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