forked from xinyu391/zircon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
unittest.h
645 lines (573 loc) · 27.9 KB
/
unittest.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
/*
* Macros for writing unit tests.
*
* Sample usage:
*
* A test case runs a collection of tests like this, with
* BEGIN_TEST_CASE and END_TEST_CASE and the beginning and end of the
* function and RUN_TEST to call each individual test, as follows:
*
* BEGIN_TEST_CASE(foo_tests);
*
* RUN_TEST(test_foo);
* RUN_TEST(test_bar);
* RUN_TEST(test_baz);
*
* END_TEST_CASE(foo_tests);
*
* This creates a static function foo_tests() and registers it with the
* unit test framework. foo_tests() can be executed either by a shell
* command or by a call to run_all_tests(), which runs all registered
* unit tests.
*
* A test looks like this, using the BEGIN_TEST and END_TEST macros at
* the beginning and end of the test and the EXPECT_* macros to
* validate test results, as shown:
*
* static bool test_foo(void)
* {
* BEGIN_TEST;
*
* ...declare variables and do stuff...
* int foo_value = foo_func();
* ...See if the stuff produced the correct value...
* EXPECT_EQ(1, foo_value, "foo_func failed");
* ... there are EXPECT_* macros for many conditions...
* EXPECT_TRUE(foo_condition(), "condition should be true");
* EXPECT_NE(ZX_ERR_TIMED_OUT, foo_event(), "event timed out");
*
* END_TEST;
* }
*/
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/compiler.h>
#ifdef __Fuchsia__
#include <zircon/types.h>
#define UNITTEST_CRASH_HANDLER_SUPPORTED
#endif // __Fuchsia__
#define PRINT_BUFFER_SIZE (512)
// The following helper function makes the "msg" argument optional in
// C++, so that you can write either of the following:
// ASSERT_EQ(x, y, "Check that x equals y");
// ASSERT_EQ(x, y);
// (We could allow the latter in C by making unittest_get_message() a
// var-args function, but that would be less type safe.)
static inline const char* unittest_get_message(const char* arg) {
return arg;
}
#ifdef __cplusplus
static inline const char* unittest_get_message() {
return "<no message>";
}
#endif
// A workaround to help static analyzer identify assertion failures
#if defined(__clang__)
#define ZX_ANALYZER_CREATE_SINK __attribute__((annotate("zx_create_sink")))
#else
#define ZX_ANALYZER_CREATE_SINK //no-op
#endif
// This function will help terminate the static analyzer when it reaches
// an assertion failure site which returns from test case function. The bugs
// discovered by the static analyzer will be suppressed as they are expected
// by the test cases.
static inline void unittest_returns_early(void) ZX_ANALYZER_CREATE_SINK {}
__BEGIN_CDECLS
extern int utest_verbosity_level;
typedef enum test_type {
TEST_SMALL = 0x00000001,
TEST_MEDIUM = 0x00000002,
TEST_LARGE = 0x00000004,
TEST_PERFORMANCE = 0x00000008,
TEST_ALL = 0xFFFFFFFF,
} test_type_t;
#define TEST_ENV_NAME "RUNTESTS_TEST_CLASS"
#define TEST_DEFAULT (TEST_SMALL | TEST_MEDIUM)
extern test_type_t utest_test_type;
/*
* Type for unit test result Output
*/
typedef void (*test_output_func)(const char* line, int len, void* arg);
/*
* Printf dedicated to the unittest library
* the default output is the printf
*/
void unittest_printf_critical(const char* format, ...)
__attribute__((format (printf, 1, 2)));
/*
* Printf dedicated to the unittest library, prints output if
* verbosity of any level is enabled.
*/
#define unittest_printf(format, ...) \
do { \
if (utest_verbosity_level > 0) \
unittest_printf_critical(format, ##__VA_ARGS__); \
} while (0)
/*
* Printf dedicated to the unittest library which output
* depends on the verbosity level.
*/
#define unittest_level_printf(level, format, ...) \
do { \
if (utest_verbosity_level >= (level)) \
unittest_printf_critical(format, ##__VA_ARGS__); \
} while (0)
/*
* Function to set the callback for printing
* the unit test output
*/
void unittest_set_output_function(test_output_func fun, void* arg);
/*
* Function to set the verbosity level. This affects
* the output of unittest_printf().
*/
int unittest_set_verbosity_level(int new_level);
#define UNITTEST_FAIL_TRACEF_FORMAT " [FAILED]\n %s:%d:%s:\n "
/*
* Format the error string
*/
#define UNITTEST_FAIL_TRACEF(str, x...) \
do { \
unittest_printf_critical( \
UNITTEST_FAIL_TRACEF_FORMAT str, \
__FILE__, __LINE__, __PRETTY_FUNCTION__, ##x); \
} while (0)
/*
* Format a tracing message
*/
#define UNITTEST_TRACEF(level, str, x...) \
do { \
if (utest_verbosity_level >= (level)) { \
unittest_printf_critical( \
"%s:%d:%s:\n " str, \
__FILE__, __LINE__, __PRETTY_FUNCTION__, ##x); \
} \
} while (0)
/*
* Internal-only.
* Used by macros to check that the test state is set up correctly.
*/
#define UT_ASSERT_VALID_TEST_STATE \
do { \
if (current_test_info == NULL) { \
unittest_printf_critical( \
"FATAL: %s:%d:%s: Invalid state for EXPECT/ASSERT: " \
"possible missing BEGIN_TEST or BEGIN_HELPER\n", \
__FILE__, __LINE__, __PRETTY_FUNCTION__); \
exit(101); /* Arbitrary, atypical exit status */ \
} \
} while (0)
/*
* BEGIN_TEST_CASE and END_TEST_CASE define a function that calls RUN_TEST. The
* test_name parameter specifies an optional test name to run. If null, all
* tests will be run.
*/
#define BEGIN_TEST_CASE(case_name) \
bool case_name(bool list_only, const char* test_name_matching) { \
bool all_success = true; \
if (list_only) { \
unittest_printf_critical("\nCASE %s\n", #case_name); \
} else { \
unittest_printf_critical("\nCASE %-50s [STARTED] \n", \
#case_name); \
}
#define DEFINE_REGISTER_TEST_CASE(case_name) \
__attribute__((constructor)) static void _register_##case_name(void) { \
unittest_register_test_case(&_##case_name##_element); \
}
#define END_TEST_CASE(case_name) \
if (list_only) { \
unittest_printf_critical("CASE %s\n", #case_name); \
} else if (all_success) { \
unittest_printf_critical("CASE %-50s [PASSED]\n", #case_name); \
} else { \
unittest_printf_critical("CASE %-50s [FAILED]\n", #case_name); \
} \
return all_success; \
} \
static struct test_case_element _##case_name##_element = { \
.next = NULL, \
.failed_next = NULL, \
.name = #case_name, \
.test_case = case_name, \
}; \
DEFINE_REGISTER_TEST_CASE(case_name);
#define RUN_NAMED_TEST_TYPE(name, test, test_type, enable_crash_handler) \
if (!test_name_matching || strcmp(test_name_matching, name) == 0) { \
if (list_only) { \
unittest_printf_critical(" %s\n", name); \
} else { \
unittest_run_named_test(name, test, test_type, ¤t_test_info, \
&all_success, enable_crash_handler); \
} \
}
#define TEST_CASE_ELEMENT(case_name) &_##case_name##_element
/*
* Test classes:
*
* Small: Isolated tests for functions and classes. These must be totally
* synchronous and single-threaded. These tests should be parallelizable;
* there shouldn't be any shared resources between them.
*
* Medium: Single-process integration tests. Ideally these are also synchronous
* and single-threaded but they might run through a large chunk of code in each
* test case, or they might use disk, making them a bit slower.
*
* Large: Multi-process (or particularly incomprehensible single-process)
* integration tests. These tests are often too flaky to run in a CQ, and we
* should try to limit how many we have.
*
* Performance: Tests which are expected to pass, but which are measured
* using other metrics (thresholds, statistical techniques) to identify
* regressions.
*/
#define RUN_TEST_SMALL(test) RUN_NAMED_TEST_TYPE(#test, test, TEST_SMALL, false)
#define RUN_TEST_MEDIUM(test) RUN_NAMED_TEST_TYPE(#test, test, TEST_MEDIUM, false)
#define RUN_TEST_LARGE(test) RUN_NAMED_TEST_TYPE(#test, test, TEST_LARGE, false)
#define RUN_TEST_PERFORMANCE(test) RUN_NAMED_TEST_TYPE(#test, test, TEST_PERFORMANCE, false)
// "RUN_TEST" implies the test is small
#define RUN_TEST(test) RUN_NAMED_TEST_TYPE(#test, test, TEST_SMALL, false)
#define RUN_NAMED_TEST(name, test) RUN_NAMED_TEST_TYPE(name, test, TEST_SMALL, false)
#ifdef UNITTEST_CRASH_HANDLER_SUPPORTED
#define RUN_TEST_ENABLE_CRASH_HANDLER(test) RUN_NAMED_TEST_TYPE(#test, test, TEST_SMALL, true)
/**
* Registers the process or thread as expected to crash. Tests utilizing this
* should be run with RUN_TEST_ENABLE_CRASH_HANDLER. If a crash occurs and
* matches a registered process or thread, it is not bubbled up to the crashlogger
* and the test continues. If any crash was registered but did not occur,
* the test fails.
* Unregistered crashes will also fail the test.
*
* A use case could be as follows:
*
* static bool test_foo_process_expected_crash(void)
* {
* BEGIN_TEST;
*
* ...create a process...
* zx_handle_t process;
* zx_handle_t vmar;
* ASSERT_EQ(zx_process_create(zx_job_default(), fooName, sizeof(fooName),
* 0, &process, &vmar),
* ZX_OK, ""));
* ...register the process as expected to crash...
* REGISTER_CRASH(process);
* ...trigger the crash...
*
* END_TEST;
* }
*/
#define REGISTER_CRASH(handle) \
unittest_register_crash(current_test_info, handle)
#endif // UNITTEST_CRASH_HANDLER_SUPPORTED
/*
* BEGIN_TEST and END_TEST go in a function that is called by RUN_TEST
* and that call the EXPECT_ macros.
*/
#define BEGIN_TEST \
do { \
UT_ASSERT_VALID_TEST_STATE; \
} while (0)
#define END_TEST \
do { \
UT_ASSERT_VALID_TEST_STATE; \
return current_test_info->all_ok; \
} while (0)
/*
* BEGIN_HELPER and END_HELPER let helper threads and files use
* the ASSERT_*,EXPECT_* macros, which require an in-scope, non-NULL
* |test_info* current_test_info|.
*
* This header file defines a static |current_test_info|, which is unlocked and
* should only be touched by the main thread; also, it is not visible to
* functions in other compilation units.
*
* Example usage:
*
* bool my_helper_in_another_file_or_thread() {
* BEGIN_HELPER;
* // Use ASSERT_* or EXPECT_*
* END_HELPER; // Returns false if any EXPECT calls failed.
* }
*/
// Intentionally shadows the global current_test_info to avoid accidentally
// leaking dangling stack pointers.
#define BEGIN_HELPER \
struct test_info _ut_helper_test_info = { .all_ok = true, .crash_list = NULL }; \
struct test_info* current_test_info = &_ut_helper_test_info; \
// By referring to _ut_helper_test_info, we guarantee that
// END_HELPER is matched with BEGIN_HELPER.
#define END_HELPER \
return _ut_helper_test_info.all_ok
#ifdef __cplusplus
#define AUTO_TYPE_VAR(type) auto
#else
#define AUTO_TYPE_VAR(type) __typeof__(type)
#endif
#define RET_FALSE do { unittest_returns_early(); return false; } while (0)
#define DONOT_RET
#define UT_CMP(op, lhs, rhs, lhs_str, rhs_str, ret, ...) \
do { \
UT_ASSERT_VALID_TEST_STATE; \
UNITTEST_TRACEF(2, "%s %s %s\n", lhs_str, #op, rhs_str); \
const AUTO_TYPE_VAR(lhs) _lhs_val = (lhs); \
const AUTO_TYPE_VAR(rhs) _rhs_val = (rhs); \
if (!(_lhs_val op _rhs_val)) { \
UNITTEST_FAIL_TRACEF( \
"%s:\n" \
" Comparison failed: %s %s %s is false\n" \
" Specifically, %lld (0x%llx) %s %lld (0x%llx) is false\n", \
unittest_get_message(__VA_ARGS__), \
lhs_str, #op, rhs_str, (long long int)_lhs_val, \
(unsigned long long)_lhs_val, \
#op, (long long int)_rhs_val, \
(unsigned long long)_rhs_val); \
current_test_info->all_ok = false; \
ret; \
} \
} while (0)
#define UT_TRUE(actual, ret, ...) \
do { \
UT_ASSERT_VALID_TEST_STATE; \
UNITTEST_TRACEF(2, "%s\n", #actual); \
if (!(actual)) { \
UNITTEST_FAIL_TRACEF("%s: %s is false\n", \
unittest_get_message(__VA_ARGS__), \
#actual); \
current_test_info->all_ok = false; \
ret; \
} \
} while (0)
#define UT_FALSE(actual, ret, ...) \
do { \
UT_ASSERT_VALID_TEST_STATE; \
UNITTEST_TRACEF(2, "!(%s)\n", #actual); \
if (actual) { \
UNITTEST_FAIL_TRACEF("%s: %s is true\n", \
unittest_get_message(__VA_ARGS__), \
#actual); \
current_test_info->all_ok = false; \
ret; \
} \
} while (0)
#define UT_NULL(actual, ret, ...) \
do { \
UT_ASSERT_VALID_TEST_STATE; \
UNITTEST_TRACEF(2, "(%s) == NULL\n", #actual); \
if (actual != NULL) { \
UNITTEST_FAIL_TRACEF("%s: %s is non-null!\n", \
unittest_get_message(__VA_ARGS__), \
#actual); \
current_test_info->all_ok = false; \
ret; \
} \
} while (0)
#define UT_NONNULL(actual, ret, ...) \
do { \
UT_ASSERT_VALID_TEST_STATE; \
UNITTEST_TRACEF(2, "(%s) != NULL\n", #actual); \
if (actual == NULL) { \
UNITTEST_FAIL_TRACEF("%s: %s is null!\n", \
unittest_get_message(__VA_ARGS__), \
#actual); \
current_test_info->all_ok = false; \
ret; \
} \
} while (0)
#define UT_BYTES_EQ(expected, actual, length, msg, ret) \
do { \
UT_ASSERT_VALID_TEST_STATE; \
UNITTEST_TRACEF(2, "bytes_eq(%s, %s, %s)\n", \
#expected, #actual, #length); \
if (!unittest_expect_bytes_eq((expected), (actual), (length), msg)) { \
current_test_info->all_ok = false; \
ret; \
} \
} while (0)
#define UT_BYTES_NE(bytes1, bytes2, length, msg, ret) \
do { \
UT_ASSERT_VALID_TEST_STATE; \
UNITTEST_TRACEF(2, "bytes_ne(%s, %s, %s)\n", \
#bytes1, #bytes2, #length); \
size_t _length = (length); \
if (!memcmp(bytes1, bytes2, _length)) { \
UNITTEST_FAIL_TRACEF( \
"%s: %s and %s are the same; " \
"expected different\n", \
msg, #bytes1, #bytes2); \
hexdump8(bytes1, _length); \
current_test_info->all_ok = false; \
ret; \
} \
} while (0)
/* Check that two strings are equal. */
#define UT_STR_EQ(str1, str2, ret, ...) \
do { \
UT_ASSERT_VALID_TEST_STATE; \
UNITTEST_TRACEF(2, "str_eq(%s, %s)\n", #str1, #str2); \
/* Note that we should not do the following here: \
* const char* str1_val = str1; \
* That does not work in C++ if str1 is string.c_str(): the \
* storage for the C string will get deallocated before the \
* string is used. Instead we must use a helper function. */ \
if (!unittest_expect_str_eq((str1), (str2), #str1, #str2, \
unittest_get_message(__VA_ARGS__), \
__FILE__, __LINE__, \
__PRETTY_FUNCTION__)) { \
current_test_info->all_ok = false; \
ret; \
} \
} while (0)
/* Check that two strings are not equal. */
#define UT_STR_NE(str1, str2, ret, ...) \
do { \
UT_ASSERT_VALID_TEST_STATE; \
UNITTEST_TRACEF(2, "str_ne(%s, %s)\n", #str1, #str2); \
if (!unittest_expect_str_ne((str1), (str2), #str1, #str2, \
unittest_get_message(__VA_ARGS__), \
__FILE__, __LINE__, \
__PRETTY_FUNCTION__)) { \
current_test_info->all_ok = false; \
ret; \
} \
} while (0)
#define EXPECT_CMP(op, lhs, rhs, lhs_str, rhs_str, ...) \
UT_CMP(op, lhs, rhs, lhs_str, rhs_str, DONOT_RET, ##__VA_ARGS__)
/*
* Use the EXPECT_* macros to check test results.
*/
#define EXPECT_EQ(lhs, rhs, ...) EXPECT_CMP(==, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define EXPECT_NE(lhs, rhs, ...) EXPECT_CMP(!=, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define EXPECT_LE(lhs, rhs, ...) EXPECT_CMP(<=, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define EXPECT_GE(lhs, rhs, ...) EXPECT_CMP(>=, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define EXPECT_LT(lhs, rhs, ...) EXPECT_CMP(<, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define EXPECT_GT(lhs, rhs, ...) EXPECT_CMP(>, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define EXPECT_TRUE(actual, ...) UT_TRUE(actual, DONOT_RET, ##__VA_ARGS__)
#define EXPECT_FALSE(actual, ...) UT_FALSE(actual, DONOT_RET, ##__VA_ARGS__)
#define EXPECT_NULL(actual, ...) UT_NULL(actual, DONOT_RET, ##__VA_ARGS__)
#define EXPECT_NONNULL(actual, ...) UT_NONNULL(actual, DONOT_RET, ##__VA_ARGS__)
#define EXPECT_BYTES_EQ(expected, actual, length, msg) UT_BYTES_EQ(expected, actual, length, msg, DONOT_RET)
#define EXPECT_BYTES_NE(bytes1, bytes2, length, msg) UT_BYTES_NE(bytes1, bytes2, length, msg, DONOT_RET)
#define EXPECT_STR_EQ(str1, str2, ...) UT_STR_EQ(str1, str2, DONOT_RET, ##__VA_ARGS__)
#define EXPECT_STR_NE(str1, str2, ...) UT_STR_NE(str1, str2, DONOT_RET, ##__VA_ARGS__)
/*
* The ASSERT_* macros are similar to the EXPECT_* macros except that
* they return on failure.
*/
#define ASSERT_NOT_NULL(p) \
do { \
UT_ASSERT_VALID_TEST_STATE; \
if (!p) { \
UNITTEST_FAIL_TRACEF("ERROR: NULL pointer\n"); \
return false; \
} \
} while (0)
#define ASSERT_CMP(op, lhs, rhs, lhs_str, rhs_str, ...) \
UT_CMP(op, lhs, rhs, lhs_str, rhs_str, RET_FALSE, ##__VA_ARGS__)
#define ASSERT_EQ(lhs, rhs, ...) ASSERT_CMP(==, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define ASSERT_NE(lhs, rhs, ...) ASSERT_CMP(!=, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define ASSERT_LE(lhs, rhs, ...) ASSERT_CMP(<=, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define ASSERT_GE(lhs, rhs, ...) ASSERT_CMP(>=, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define ASSERT_LT(lhs, rhs, ...) ASSERT_CMP(<, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define ASSERT_GT(lhs, rhs, ...) ASSERT_CMP(>, lhs, rhs, #lhs, #rhs, ##__VA_ARGS__)
#define ASSERT_TRUE(actual, ...) UT_TRUE(actual, RET_FALSE, ##__VA_ARGS__)
#define ASSERT_FALSE(actual, ...) UT_FALSE(actual, RET_FALSE, ##__VA_ARGS__)
#define ASSERT_NULL(actual, ...) UT_NULL(actual, RET_FALSE, ##__VA_ARGS__)
#define ASSERT_NONNULL(actual, ...) UT_NONNULL(actual, RET_FALSE, ##__VA_ARGS__)
#define ASSERT_BYTES_EQ(expected, actual, length, msg) UT_BYTES_EQ(expected, actual, length, msg, RET_FALSE)
#define ASSERT_BYTES_NE(bytes1, bytes2, length, msg) UT_BYTES_NE(bytes1, bytes2, length, msg, RET_FALSE)
#define ASSERT_STR_EQ(str1, str2, ...) UT_STR_EQ(str1, str2, RET_FALSE, ##__VA_ARGS__)
#define ASSERT_STR_NE(str1, str2, ...) UT_STR_NE(str1, str2, RET_FALSE, ##__VA_ARGS__)
#ifdef UNITTEST_CRASH_HANDLER_SUPPORTED
/**
* Runs the given function in a separate thread, and fails if the function does not crash.
* This is a blocking call.
*
* static void crash(void* arg) {
* ...trigger the crash...
* }
*
* static bool test_crash(void)
* {
* BEGIN_TEST;
*
* ...construct arg...
*
* ASSERT_DEATH(crash, arg, "msg about crash");
*
* END_TEST;
* }
*/
#define ASSERT_DEATH(fn, arg, msg) ASSERT_TRUE(unittest_run_death_fn(fn, arg), msg)
#define ASSERT_NO_DEATH(fn, arg, msg) ASSERT_TRUE(unittest_run_no_death_fn(fn, arg), msg)
#endif // UNITTEST_CRASH_HANDLER_SUPPORTED
/*
* The list of test cases is made up of these elements.
*/
struct test_case_element {
struct test_case_element* next;
struct test_case_element* failed_next;
const char* name;
bool (*test_case)(bool list_only, const char* test_name_matching);
};
/* List of processes or threads which are expected to crash. */
typedef struct crash_list* crash_list_t;
/*
* Struct to store current test case info
*/
struct test_info {
bool all_ok;
crash_list_t crash_list;
};
/*
* Object which stores current test info
*/
__UNUSED static struct test_info* current_test_info;
/*
* Registers a test case with the unit test framework.
*/
void unittest_register_test_case(struct test_case_element* elem);
/*
* Runs all registered test cases.
*/
bool unittest_run_all_tests(int argc, char** argv);
/*
* Runs a single test case.
*/
bool unittest_run_one_test(struct test_case_element* elem, test_type_t type);
/*
* Returns false if expected does not equal actual and prints msg and a hexdump8
* of the input buffers.
*/
bool unittest_expect_bytes_eq(const uint8_t* expected, const uint8_t* actual, size_t len,
const char* msg);
bool unittest_expect_str_eq(const char* str1_value, const char* str2_value,
const char* str1_expr, const char* str2_expr,
const char* msg,
const char* source_filename, int source_line_num,
const char* source_function);
bool unittest_expect_str_ne(const char* str1_value, const char* str2_value,
const char* str1_expr, const char* str2_expr,
const char* msg,
const char* source_filename, int source_line_num,
const char* source_function);
/* Used to implement RUN_TEST() and other variants. */
void unittest_run_named_test(const char* name, bool (*test)(void),
test_type_t test_type,
struct test_info** current_test_info,
bool* all_success, bool enable_crash_handler);
#ifdef UNITTEST_CRASH_HANDLER_SUPPORTED
void unittest_register_crash(struct test_info* current_test_info, zx_handle_t handle);
bool unittest_run_death_fn(void (*fn_to_run)(void*), void* arg);
bool unittest_run_no_death_fn(void (*fn_to_run)(void*), void* arg);
#endif // UNITTEST_CRASH_HANDLER_SUPPORTED
__END_CDECLS