1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file
4 
5 #pragma once
6 
7 #include <fbl/function.h>
8 #include <fs-test-utils/fixture.h>
9 #include <unittest/unittest.h>
10 #include <zircon/errors.h>
11 
12 // This library provides equivalent macros from unittest to generate tests that
13 // will use a fixture. Also provides an alternative, that provides the running
14 // test a pointer to the Fixture. Interaction with the underlying devices,
15 // such as mount/remount, etc should always be done through the Fixture class.
16 //
17 // This set of macros are compatible with RUN_TEST_* the fixture will not be passed, nor
18 // will SetUp/TearDown be called for those, but it is required to use BEGIN_FS_TEST_CASE*
19 // if at least one test of the test case requires a fixture.
20 //
21 // SetUpTestCase/TearDownTestCase will run ONCE per TestCase.
22 // SetUp/TearDown will run ONCE per Test run with RUN_FS_TEST_F
23 namespace fs_test_utils {
24 
25 #define ASSERT_OK(status) ASSERT_EQ(status, ZX_OK)
26 #define EXPECT_OK(status) EXPECT_EQ(status, ZX_OK)
27 
28 #define BEGIN_FS_TEST_CASE(name, options_fn)              \
29     BEGIN_TEST_CASE(name##_##options_fn)                  \
30     fs_test_utils::FixtureOptions options = options_fn(); \
31     fs_test_utils::Fixture fixture(options);              \
32     zx_status_t result = fixture.SetUpTestCase();
33 
34 #define RUN_FS_TEST_F_TYPE(test_fn, size)                                                 \
35     if (result == ZX_OK) {                                                                \
36         fbl::Function<bool()> test_wrapper = [&fixture]() {                               \
37             return test_fn(&fixture);                                                     \
38         };                                                                                \
39         fs_test_utils::fs_test_utils_internal::current_test_wrapper = &test_wrapper;      \
40                                                                                           \
41         result = fixture.SetUp();                                                         \
42         if (result == ZX_OK) {                                                            \
43             RUN_NAMED_TEST_TYPE(#test_fn,                                                 \
44                                 fs_test_utils::fs_test_utils_internal::RunTestWrapper,    \
45                                 size, false)                                              \
46         } else {                                                                          \
47             LOG_ERROR(result, "SetUp had errors.\n");                                     \
48             RUN_NAMED_TEST_TYPE(#test_fn,                                                 \
49                                 fs_test_utils::fs_test_utils_internal::Fail, size, false) \
50         }                                                                                 \
51         result = fixture.TearDown();                                                      \
52         if (result != ZX_OK) {                                                            \
53             LOG_ERROR(result, "TearDown had errors.\n");                                  \
54             all_success = false;                                                          \
55         }                                                                                 \
56     } else {                                                                              \
57         LOG_ERROR(result, "SetUpTestCase had errors.\n");                                 \
58         RUN_NAMED_TEST_TYPE(#test_fn,                                                     \
59                             fs_test_utils::fs_test_utils_internal::Fail, size, false)     \
60     }
61 
62 #define END_FS_TEST_CASE(name, options_fn)                \
63     result = fixture.TearDownTestCase();                  \
64     if (result != ZX_OK) {                                \
65         LOG_ERROR(result, "TestCaseSetUp had errors.\n"); \
66         all_success = false;                              \
67     }                                                     \
68     END_TEST_CASE(name##_##options_fn)
69 
70 #define RUN_FS_TEST_F(test_fn) RUN_FS_TEST_F_TYPE(test_fn, TEST_MEDIUM)
71 
72 namespace fs_test_utils_internal {
73 
74 // Pointer to current functor that will be run when RunTestWrapper is called.
75 static fbl::Function<bool()>* current_test_wrapper = nullptr;
76 
77 // Provides a function pointer wrapper over a Callable, to allow
RunTestWrapper()78 inline bool RunTestWrapper() {
79     return (*current_test_wrapper)();
80 }
81 
82 // Function used to make the underlying framework think the test failed,
83 // when setup fails, so test will not run, and will get the test listed.
Fail()84 inline bool Fail() {
85     BEGIN_TEST;
86     ASSERT_TRUE(false);
87     END_TEST;
88 }
89 
90 }; // namespace fs_test_utils_internal
91 
92 } // namespace fs_test_utils
93