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