1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2020 Red Hat, Inc.
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.
15 #include "common/fault_injector.h"
16 #include "common/common_init.h"
17 #include "common/ceph_argparse.h"
18 #include <gtest/gtest.h>
20 TEST(FaultInjectorDeathTest
, InjectAbort
)
22 constexpr FaultInjector f
{false, InjectAbort
{}};
23 EXPECT_EQ(f
.check(true), 0);
24 EXPECT_DEATH([[maybe_unused
]] int r
= f
.check(false), "FaultInjector");
27 TEST(FaultInjectorDeathTest
, AssignAbort
)
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");
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
;
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
);
47 void TearDown() override
{
51 const DoutPrefixProvider
* dpp() { return &*prefix
; }
54 // test int as a Key type
55 using FaultInjectorInt
= Fixture
;
57 TEST_F(FaultInjectorInt
, Default
)
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);
66 TEST_F(FaultInjectorInt
, InjectError
)
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);
75 TEST_F(FaultInjectorInt
, InjectErrorMessage
)
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);
84 TEST_F(FaultInjectorInt
, AssignError
)
87 ASSERT_EQ(f
.check(0), 0);
88 f
.inject(0, InjectError
{-EINVAL
});
89 EXPECT_EQ(f
.check(0), -EINVAL
);
92 TEST_F(FaultInjectorInt
, AssignErrorMessage
)
95 ASSERT_EQ(f
.check(0), 0);
96 f
.inject(0, InjectError
{-EINVAL
, dpp()});
97 EXPECT_EQ(f
.check(0), -EINVAL
);
100 // test std::string_view as a Key type
101 using FaultInjectorString
= Fixture
;
103 TEST_F(FaultInjectorString
, Default
)
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);
111 TEST_F(FaultInjectorString
, InjectError
)
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);
119 TEST_F(FaultInjectorString
, InjectErrorMessage
)
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);
127 TEST_F(FaultInjectorString
, AssignError
)
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
);
135 TEST_F(FaultInjectorString
, AssignErrorMessage
)
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
);
143 // test enum class as a Key type
144 using FaultInjectorEnum
= Fixture
;
146 enum class Color
{ Red
, Green
, Blue
};
148 static std::ostream
& operator<<(std::ostream
& out
, const Color
& c
) {
150 case Color::Red
: return out
<< "Red";
151 case Color::Green
: return out
<< "Green";
152 case Color::Blue
: return out
<< "Blue";
157 TEST_F(FaultInjectorEnum
, Default
)
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);
165 TEST_F(FaultInjectorEnum
, InjectError
)
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);
173 TEST_F(FaultInjectorEnum
, InjectErrorMessage
)
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);
181 TEST_F(FaultInjectorEnum
, AssignError
)
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
);
189 TEST_F(FaultInjectorEnum
, AssignErrorMessage
)
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
);
197 // test custom move-only Key type
198 using FaultInjectorMoveOnly
= Fixture
;
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;
209 static bool operator==(const MoveOnlyKey
&, const MoveOnlyKey
&) {
210 return true; // all keys are equal
212 static std::ostream
& operator<<(std::ostream
& out
, const MoveOnlyKey
&) {
216 TEST_F(FaultInjectorMoveOnly
, Default
)
218 constexpr FaultInjector
<MoveOnlyKey
> f
;
219 EXPECT_EQ(f
.check(MoveOnlyKey
{}), 0);
222 TEST_F(FaultInjectorMoveOnly
, InjectError
)
224 FaultInjector f
{MoveOnlyKey
{}, InjectError
{-EIO
}};
225 EXPECT_EQ(f
.check(MoveOnlyKey
{}), -EIO
);
228 TEST_F(FaultInjectorMoveOnly
, InjectErrorMessage
)
230 FaultInjector f
{MoveOnlyKey
{}, InjectError
{-EIO
, dpp()}};
231 EXPECT_EQ(f
.check(MoveOnlyKey
{}), -EIO
);
234 TEST_F(FaultInjectorMoveOnly
, AssignError
)
236 FaultInjector
<MoveOnlyKey
> f
;
237 ASSERT_EQ(f
.check({}), 0);
238 f
.inject({}, InjectError
{-EINVAL
});
239 EXPECT_EQ(f
.check({}), -EINVAL
);
242 TEST_F(FaultInjectorMoveOnly
, AssignErrorMessage
)
244 FaultInjector
<MoveOnlyKey
> f
;
245 ASSERT_EQ(f
.check({}), 0);
246 f
.inject({}, InjectError
{-EINVAL
, dpp()});
247 EXPECT_EQ(f
.check({}), -EINVAL
);