]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/common/test_fault_injector.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / common / test_fault_injector.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2020 Red Hat, Inc.
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include "common/fault_injector.h"
16 #include "common/common_init.h"
17 #include "common/ceph_argparse.h"
18 #include <gtest/gtest.h>
19
20 TEST(FaultInjectorDeathTest, InjectAbort)
21 {
22 constexpr FaultInjector f{false, InjectAbort{}};
23 EXPECT_EQ(f.check(true), 0);
24 EXPECT_DEATH([[maybe_unused]] int r = f.check(false), "FaultInjector");
25 }
26
27 TEST(FaultInjectorDeathTest, AssignAbort)
28 {
29 FaultInjector<bool> f;
30 ASSERT_EQ(f.check(false), 0);
31 f.inject(false, InjectAbort{});
32 EXPECT_DEATH([[maybe_unused]] int r = f.check(false), "FaultInjector");
33 }
34
35 // death tests have to run in single-threaded mode, so we can't initialize a
36 // CephContext until after those have run (gtest automatically runs them first)
37 class Fixture : public testing::Test {
38 boost::intrusive_ptr<CephContext> cct;
39 std::optional<NoDoutPrefix> prefix;
40 protected:
41 void SetUp() override {
42 CephInitParameters params(CEPH_ENTITY_TYPE_CLIENT);
43 cct = common_preinit(params, CODE_ENVIRONMENT_UTILITY,
44 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
45 prefix.emplace(cct.get(), ceph_subsys_context);
46 }
47 void TearDown() override {
48 prefix.reset();
49 cct.reset();
50 }
51 const DoutPrefixProvider* dpp() { return &*prefix; }
52 };
53
54 // test int as a Key type
55 using FaultInjectorInt = Fixture;
56
57 TEST_F(FaultInjectorInt, Default)
58 {
59 constexpr FaultInjector<int> f;
60 EXPECT_EQ(f.check(0), 0);
61 EXPECT_EQ(f.check(1), 0);
62 EXPECT_EQ(f.check(2), 0);
63 EXPECT_EQ(f.check(3), 0);
64 }
65
66 TEST_F(FaultInjectorInt, InjectError)
67 {
68 constexpr FaultInjector f{2, InjectError{-EINVAL}};
69 EXPECT_EQ(f.check(0), 0);
70 EXPECT_EQ(f.check(1), 0);
71 EXPECT_EQ(f.check(2), -EINVAL);
72 EXPECT_EQ(f.check(3), 0);
73 }
74
75 TEST_F(FaultInjectorInt, InjectErrorMessage)
76 {
77 FaultInjector f{2, InjectError{-EINVAL, dpp()}};
78 EXPECT_EQ(f.check(0), 0);
79 EXPECT_EQ(f.check(1), 0);
80 EXPECT_EQ(f.check(2), -EINVAL);
81 EXPECT_EQ(f.check(3), 0);
82 }
83
84 TEST_F(FaultInjectorInt, AssignError)
85 {
86 FaultInjector<int> f;
87 ASSERT_EQ(f.check(0), 0);
88 f.inject(0, InjectError{-EINVAL});
89 EXPECT_EQ(f.check(0), -EINVAL);
90 }
91
92 TEST_F(FaultInjectorInt, AssignErrorMessage)
93 {
94 FaultInjector<int> f;
95 ASSERT_EQ(f.check(0), 0);
96 f.inject(0, InjectError{-EINVAL, dpp()});
97 EXPECT_EQ(f.check(0), -EINVAL);
98 }
99
100 // test std::string_view as a Key type
101 using FaultInjectorString = Fixture;
102
103 TEST_F(FaultInjectorString, Default)
104 {
105 constexpr FaultInjector<std::string_view> f;
106 EXPECT_EQ(f.check("Red"), 0);
107 EXPECT_EQ(f.check("Green"), 0);
108 EXPECT_EQ(f.check("Blue"), 0);
109 }
110
111 TEST_F(FaultInjectorString, InjectError)
112 {
113 FaultInjector<std::string_view> f{"Red", InjectError{-EIO}};
114 EXPECT_EQ(f.check("Red"), -EIO);
115 EXPECT_EQ(f.check("Green"), 0);
116 EXPECT_EQ(f.check("Blue"), 0);
117 }
118
119 TEST_F(FaultInjectorString, InjectErrorMessage)
120 {
121 FaultInjector<std::string_view> f{"Red", InjectError{-EIO, dpp()}};
122 EXPECT_EQ(f.check("Red"), -EIO);
123 EXPECT_EQ(f.check("Green"), 0);
124 EXPECT_EQ(f.check("Blue"), 0);
125 }
126
127 TEST_F(FaultInjectorString, AssignError)
128 {
129 FaultInjector<std::string_view> f;
130 ASSERT_EQ(f.check("Red"), 0);
131 f.inject("Red", InjectError{-EINVAL});
132 EXPECT_EQ(f.check("Red"), -EINVAL);
133 }
134
135 TEST_F(FaultInjectorString, AssignErrorMessage)
136 {
137 FaultInjector<std::string_view> f;
138 ASSERT_EQ(f.check("Red"), 0);
139 f.inject("Red", InjectError{-EINVAL, dpp()});
140 EXPECT_EQ(f.check("Red"), -EINVAL);
141 }
142
143 // test enum class as a Key type
144 using FaultInjectorEnum = Fixture;
145
146 enum class Color { Red, Green, Blue };
147
148 static std::ostream& operator<<(std::ostream& out, const Color& c) {
149 switch (c) {
150 case Color::Red: return out << "Red";
151 case Color::Green: return out << "Green";
152 case Color::Blue: return out << "Blue";
153 }
154 return out;
155 }
156
157 TEST_F(FaultInjectorEnum, Default)
158 {
159 constexpr FaultInjector<Color> f;
160 EXPECT_EQ(f.check(Color::Red), 0);
161 EXPECT_EQ(f.check(Color::Green), 0);
162 EXPECT_EQ(f.check(Color::Blue), 0);
163 }
164
165 TEST_F(FaultInjectorEnum, InjectError)
166 {
167 FaultInjector f{Color::Red, InjectError{-EIO}};
168 EXPECT_EQ(f.check(Color::Red), -EIO);
169 EXPECT_EQ(f.check(Color::Green), 0);
170 EXPECT_EQ(f.check(Color::Blue), 0);
171 }
172
173 TEST_F(FaultInjectorEnum, InjectErrorMessage)
174 {
175 FaultInjector f{Color::Red, InjectError{-EIO, dpp()}};
176 EXPECT_EQ(f.check(Color::Red), -EIO);
177 EXPECT_EQ(f.check(Color::Green), 0);
178 EXPECT_EQ(f.check(Color::Blue), 0);
179 }
180
181 TEST_F(FaultInjectorEnum, AssignError)
182 {
183 FaultInjector<Color> f;
184 ASSERT_EQ(f.check(Color::Red), 0);
185 f.inject(Color::Red, InjectError{-EINVAL});
186 EXPECT_EQ(f.check(Color::Red), -EINVAL);
187 }
188
189 TEST_F(FaultInjectorEnum, AssignErrorMessage)
190 {
191 FaultInjector<Color> f;
192 ASSERT_EQ(f.check(Color::Red), 0);
193 f.inject(Color::Red, InjectError{-EINVAL, dpp()});
194 EXPECT_EQ(f.check(Color::Red), -EINVAL);
195 }
196
197 // test custom move-only Key type
198 using FaultInjectorMoveOnly = Fixture;
199
200 struct MoveOnlyKey {
201 MoveOnlyKey() = default;
202 MoveOnlyKey(const MoveOnlyKey&) = delete;
203 MoveOnlyKey& operator=(const MoveOnlyKey&) = delete;
204 MoveOnlyKey(MoveOnlyKey&&) = default;
205 MoveOnlyKey& operator=(MoveOnlyKey&&) = default;
206 ~MoveOnlyKey() = default;
207 };
208
209 static bool operator==(const MoveOnlyKey&, const MoveOnlyKey&) {
210 return true; // all keys are equal
211 }
212 static std::ostream& operator<<(std::ostream& out, const MoveOnlyKey&) {
213 return out;
214 }
215
216 TEST_F(FaultInjectorMoveOnly, Default)
217 {
218 constexpr FaultInjector<MoveOnlyKey> f;
219 EXPECT_EQ(f.check(MoveOnlyKey{}), 0);
220 }
221
222 TEST_F(FaultInjectorMoveOnly, InjectError)
223 {
224 FaultInjector f{MoveOnlyKey{}, InjectError{-EIO}};
225 EXPECT_EQ(f.check(MoveOnlyKey{}), -EIO);
226 }
227
228 TEST_F(FaultInjectorMoveOnly, InjectErrorMessage)
229 {
230 FaultInjector f{MoveOnlyKey{}, InjectError{-EIO, dpp()}};
231 EXPECT_EQ(f.check(MoveOnlyKey{}), -EIO);
232 }
233
234 TEST_F(FaultInjectorMoveOnly, AssignError)
235 {
236 FaultInjector<MoveOnlyKey> f;
237 ASSERT_EQ(f.check({}), 0);
238 f.inject({}, InjectError{-EINVAL});
239 EXPECT_EQ(f.check({}), -EINVAL);
240 }
241
242 TEST_F(FaultInjectorMoveOnly, AssignErrorMessage)
243 {
244 FaultInjector<MoveOnlyKey> f;
245 ASSERT_EQ(f.check({}), 0);
246 f.inject({}, InjectError{-EINVAL, dpp()});
247 EXPECT_EQ(f.check({}), -EINVAL);
248 }