1 // Copyright 2016 The Fuchsia Authors
2 // Copyright (c) 2013, Google, Inc. All rights reserved
3 //
4 // Use of this source code is governed by a MIT-style
5 // license that can be found in the LICENSE file or at
6 // https://opensource.org/licenses/MIT
7 
8 #pragma once
9 /*
10  * Macros for writing unit tests.
11  *
12  * Sample usage:
13  *
14  * A test case runs a collection of unittests, with
15  * UNITTEST_START_TESTCASE and UNITTEST_END_TESTCASE
16  * BEGIN_TEST_CASE and END_TEST_CASE at the beginning and end of the list of
17  * unitests, and UNITTEST for each individual test, as follows:
18  *
19  *  UNITTEST_START_TESTCASE(foo_tests)
20  *
21  *  UNITTEST(test_foo);
22  *  UNITTEST(test_bar);
23  *  UNITTEST(test_baz);
24  *
25  *  UNITTEST_END_TESTCASE(foo_tests,
26  *                        "footest",
27  *                        "Test to be sure that your foos have proper bars");
28  *
29  * This creates an entry in the global unittest table and registers it with the
30  * unit test framework.
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()
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_NE(ZX_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 <stdarg.h>
57 #include <stdbool.h>
58 #include <stddef.h>
59 #include <stdint.h>
60 #include <stdio.h>
61 #include <string.h>
62 
63 #include <zircon/compiler.h>
64 #include <zircon/types.h>
65 #include <trace.h>
66 
67 __BEGIN_CDECLS
68 
69 /*
70  * Printf dedicated to the unittest library
71  * the default output is the printf
72  */
73 int unittest_printf(const char* format, ...) __PRINTFLIKE(1, 2);
74 
75 /*
76  * Macros to format the error string
77  */
78 #define EXPECTED_STRING "%s:\n        expected "
79 #define UNITTEST_FAIL_TRACEF_FORMAT "\n        [FAILED]\n        %s:%d:\n        "
80 #define UNITTEST_FAIL_TRACEF(str, x...)                                        \
81     do {                                                                       \
82         unittest_printf(UNITTEST_FAIL_TRACEF_FORMAT str,                       \
83                         __PRETTY_FUNCTION__, __LINE__, ##x);                   \
84     } while (0)
85 
86 /*
87  * BEGIN_TEST and END_TEST go in a function that is called by RUN_TEST
88  * and that call the EXPECT_ macros.
89  */
90 
91 #define BEGIN_TEST bool all_ok = true
92 #define END_TEST return all_ok
93 
94 #ifdef __cplusplus
95 #define AUTO_TYPE_VAR(type) auto&
96 #else
97 #define AUTO_TYPE_VAR(type) __typeof__(type)
98 #endif
99 
100 /*
101  * UTCHECK_* macros are used to check test results.  Generally, one should
102  * prefer to use either the EXPECT_* (non-terminating) or ASSERT_*
103  * (terminating) forms of the macros.  See below.
104  */
105 #define UTCHECK_EQ(expected, actual, msg, term)                                \
106     do {                                                                       \
107         const AUTO_TYPE_VAR(expected) _e = (expected);                         \
108         const AUTO_TYPE_VAR(actual) _a = (actual);                             \
109         if (_e != _a) {                                                        \
110             UNITTEST_FAIL_TRACEF(EXPECTED_STRING                               \
111                             "%s (%ld), "                                       \
112                             "actual %s (%ld)\n",                               \
113                             msg, #expected, (long)_e, #actual, (long)_a);      \
114             if (term) return false; else all_ok = false;                       \
115         }                                                                      \
116     } while (0)
117 
118 #define UTCHECK_NE(expected, actual, msg, term)                                \
119     do {                                                                       \
120         const AUTO_TYPE_VAR(expected) _e = (expected);                         \
121         const AUTO_TYPE_VAR(actual) _a = (actual);                             \
122         if (_e == (_a)) {                                                      \
123             UNITTEST_FAIL_TRACEF(EXPECTED_STRING                               \
124                             "%s (%ld), %s"                                     \
125                             " to differ, but they are the same %ld\n",         \
126                             msg, #expected, (long)_e, #actual, (long)_a);      \
127             if (term) return false; else all_ok = false;                       \
128         }                                                                      \
129     } while (0)
130 
131 #define UTCHECK_LE(expected, actual, msg, term)                                \
132     do {                                                                       \
133         const AUTO_TYPE_VAR(expected) _e = (expected);                         \
134         const AUTO_TYPE_VAR(actual) _a = (actual);                             \
135         if (_e > _a) {                                                         \
136             UNITTEST_FAIL_TRACEF(EXPECTED_STRING                               \
137                             "%s (%ld) to be"                                   \
138                             " less-than-or-equal-to actual %s (%ld)\n",        \
139                             msg, #expected, (long)_e, #actual, (long)_a);      \
140             if (term) return false; else all_ok = false;                       \
141         }                                                                      \
142     } while (0)
143 
144 #define UTCHECK_LT(expected, actual, msg, term)                                \
145     do {                                                                       \
146         const AUTO_TYPE_VAR(expected) _e = (expected);                         \
147         const AUTO_TYPE_VAR(actual) _a = (actual);                             \
148         if (_e >= _a) {                                                        \
149             UNITTEST_FAIL_TRACEF(EXPECTED_STRING                               \
150                             "%s (%ld) to be"                                   \
151                             " less-than actual %s (%ld)\n",                    \
152                             msg, #expected, (long)_e, #actual, (long)_a);      \
153             if (term) return false; else all_ok = false;                       \
154         }                                                                      \
155     } while (0)
156 
157 #define UTCHECK_GE(expected, actual, msg, term)                                \
158     do {                                                                       \
159         const AUTO_TYPE_VAR(expected) _e = (expected);                         \
160         const AUTO_TYPE_VAR(actual) _a = (actual);                             \
161         if (_e < _a) {                                                         \
162             UNITTEST_FAIL_TRACEF(EXPECTED_STRING                               \
163                             "%s (%ld) to be"                                   \
164                             " greater-than-or-equal-to actual %s (%ld)\n",     \
165                             msg, #expected, (long)_e, #actual, (long)_a);      \
166             if (term) return false; else all_ok = false;                       \
167         }                                                                      \
168     } while (0)
169 
170 #define UTCHECK_GT(expected, actual, msg, term)                                \
171     do {                                                                       \
172         const AUTO_TYPE_VAR(expected) _e = (expected);                         \
173         const AUTO_TYPE_VAR(actual) _a = (actual);                             \
174         if (_e <= _a) {                                                        \
175             UNITTEST_FAIL_TRACEF(EXPECTED_STRING                               \
176                             "%s (%ld) to be"                                   \
177                             " greater-than actual %s (%ld)\n",                 \
178                             msg, #expected, (long)_e, #actual, (long)_a);      \
179             if (term) return false; else all_ok = false;                       \
180         }                                                                      \
181     } while (0)
182 
183 #define UTCHECK_TRUE(actual, msg, term)                                        \
184     if (!(actual)) {                                                           \
185         UNITTEST_FAIL_TRACEF("%s: %s is false\n", msg, #actual);               \
186         if (term) return false; else all_ok = false;                           \
187     }
188 
189 #define UTCHECK_FALSE(actual, msg, term)                                       \
190     if (actual) {                                                              \
191         UNITTEST_FAIL_TRACEF("%s: %s is true\n", msg, #actual);                \
192         if (term) return false; else all_ok = false;                           \
193     }
194 
195 #define UTCHECK_NULL(actual, msg, term)                                        \
196     if (actual != NULL) {                                                      \
197         UNITTEST_FAIL_TRACEF("%s: %s is non-null!\n", msg, #actual);           \
198         if (term) return false; else all_ok = false;                           \
199     }
200 
201 #define UTCHECK_NONNULL(actual, msg, term)                                     \
202     if (actual == NULL) {                                                      \
203         UNITTEST_FAIL_TRACEF("%s: %s is null!\n", msg, #actual);               \
204         if (term) return false; else all_ok = false;                           \
205     }
206 
207 #define UTCHECK_BYTES_EQ(expected, actual, length, msg, term)                  \
208     if (!unittest_expect_bytes((expected), #expected,                          \
209                                (actual), #actual,                              \
210                                (length), msg, __PRETTY_FUNCTION__, __LINE__,   \
211                                true)) {                                        \
212         if (term) return false; else all_ok = false;                           \
213     }
214 
215 #define UTCHECK_BYTES_NE(expected, actual, length, msg, term)                  \
216     if (!unittest_expect_bytes((expected), #expected,                          \
217                                (actual), #actual,                              \
218                                (length), msg, __PRETTY_FUNCTION__, __LINE__,   \
219                                false)) {                                       \
220         if (term) return false; else all_ok = false;                           \
221     }
222 
223 /* EXPECT_* macros check the supplied condition and will print a message and flag the test
224  * as having failed if the condition fails.  The test will continue to run, even
225  * if the condition fails.
226  */
227 #define EXPECT_EQ(expected, actual, msg)               UTCHECK_EQ(expected, actual, msg, false)
228 #define EXPECT_NE(expected, actual, msg)               UTCHECK_NE(expected, actual, msg, false)
229 #define EXPECT_LE(expected, actual, msg)               UTCHECK_LE(expected, actual, msg, false)
230 #define EXPECT_LT(expected, actual, msg)               UTCHECK_LT(expected, actual, msg, false)
231 #define EXPECT_GE(expected, actual, msg)               UTCHECK_GE(expected, actual, msg, false)
232 #define EXPECT_GT(expected, actual, msg)               UTCHECK_GT(expected, actual, msg, false)
233 #define EXPECT_TRUE(actual, msg)                       UTCHECK_TRUE(actual, msg, false)
234 #define EXPECT_FALSE(actual, msg)                      UTCHECK_FALSE(actual, msg, false)
235 #define EXPECT_BYTES_EQ(expected, actual, length, msg) UTCHECK_BYTES_EQ(expected, actual, length, msg, false)
236 #define EXPECT_BYTES_NE(bytes1, bytes2, length, msg)   UTCHECK_BYTES_NE(bytes1, bytes2, length, msg, false)
237 #define EXPECT_EQ_LL(expected, actual, msg)            UTCHECK_EQ_LL(expected, actual, msg, false)
238 #define EXPECT_EQ_LL(expected, actual, msg)            UTCHECK_EQ_LL(expected, actual, msg, false)
239 #define EXPECT_NULL(actual, msg)                       UTCHECK_NULL(actual, msg, false)
240 #define EXPECT_NONNULL(actual, msg)                    UTCHECK_NONNULL(actual, msg, false)
241 
242 /* ASSERT_* macros check the condition and will print a message and immediately
243  * abort a test with a filure status if the condition fails.
244  */
245 #define ASSERT_EQ(expected, actual, msg)               UTCHECK_EQ(expected, actual, msg, true)
246 #define ASSERT_NE(expected, actual, msg)               UTCHECK_NE(expected, actual, msg, true)
247 #define ASSERT_LE(expected, actual, msg)               UTCHECK_LE(expected, actual, msg, true)
248 #define ASSERT_LT(expected, actual, msg)               UTCHECK_LT(expected, actual, msg, true)
249 #define ASSERT_GE(expected, actual, msg)               UTCHECK_GE(expected, actual, msg, true)
250 #define ASSERT_GT(expected, actual, msg)               UTCHECK_GT(expected, actual, msg, true)
251 #define ASSERT_TRUE(actual, msg)                       UTCHECK_TRUE(actual, msg, true)
252 #define ASSERT_FALSE(actual, msg)                      UTCHECK_FALSE(actual, msg, true)
253 #define ASSERT_BYTES_EQ(expected, actual, length, msg) UTCHECK_BYTES_EQ(expected, actual, length, msg, true)
254 #define ASSERT_BYTES_NE(bytes1, bytes2, length, msg)   UTCHECK_BYTES_NE(bytes1, bytes2, length, msg, true)
255 #define ASSERT_EQ_LL(expected, actual, msg)            UTCHECK_EQ_LL(expected, actual, msg, true)
256 #define ASSERT_EQ_LL(expected, actual, msg)            UTCHECK_EQ_LL(expected, actual, msg, true)
257 #define ASSERT_NULL(actual, msg)                       UTCHECK_NULL(actual, msg, true)
258 #define ASSERT_NONNULL(actual, msg)                    UTCHECK_NONNULL(actual, msg, true)
259 
260 /*
261  * The list of test cases is made up of these elements.
262  */
263 struct test_case_element {
264     struct test_case_element* next;
265     struct test_case_element* failed_next;
266     const char* name;
267     bool (*test_case)(void);
268 };
269 
270 /*
271  * Registers a test case with the unit test framework.
272  */
273 void unittest_register_test_case(struct test_case_element* elem);
274 
275 /*
276  * Runs all registered test cases.
277  */
278 bool run_all_tests(void);
279 
280 /*
281  * Returns false if expected does or does not equal actual (based on expect_eq).
282  * Will print msg and a hexdump8 of the input buffers if the check fails.
283  */
284 bool unittest_expect_bytes(const uint8_t* expected,
285                            const char* expected_name,
286                            const uint8_t* actual,
287                            const char* actual_name,
288                            size_t len,
289                            const char *msg,
290                            const char* func,
291                            int line,
292                            bool expect_eq);
293 
294 typedef bool        (*unitest_fn_t)(void);
295 
296 typedef struct unitest_registration {
297     const char*  name;
298     unitest_fn_t fn;
299 } unittest_registration_t;
300 
301 typedef struct unitest_testcase_registration {
302     const char*                     name;
303     const char*                     desc;
304     const unittest_registration_t*  tests;
305     size_t                          test_cnt;
306 } unittest_testcase_registration_t;
307 
308 #define UNITTEST_START_TESTCASE(_global_id)  \
309     static const unittest_registration_t __unittest_table_##_global_id[] = {
310 
311 #define UNITTEST(_name, _fn) \
312     { .name = _name, .fn = _fn },
313 
314 #define UNITTEST_END_TESTCASE(_global_id, _name, _desc)                 \
315     };  /* __unittest_table_##_global_id */                             \
316     __ALIGNED(sizeof(void *)) __USED __SECTION(".data.rel.ro.unittest_testcases") \
317     static const unittest_testcase_registration_t __unittest_case_##_global_id = \
318     {                                                                   \
319         .name = _name,                                                  \
320         .desc = _desc,                                                  \
321         .tests = __unittest_table_##_global_id,                         \
322         .test_cnt = countof(__unittest_table_##_global_id),             \
323     }
324 
325 __END_CDECLS
326