*/
#include "common/fault_injector.h"
+#include "common/common_init.h"
+#include "common/ceph_argparse.h"
#include <gtest/gtest.h>
-static const DoutPrefixProvider* dpp() {
- static NoDoutPrefix d{g_ceph_context, ceph_subsys_context};
- return &d;
-}
-
TEST(FaultInjectorDeathTest, InjectAbort)
{
constexpr FaultInjector f{false, InjectAbort{}};
EXPECT_DEATH([[maybe_unused]] int r = f.check(false), "FaultInjector");
}
+// death tests have to run in single-threaded mode, so we can't initialize a
+// CephContext until after those have run (gtest automatically runs them first)
+class Fixture : public testing::Test {
+ boost::intrusive_ptr<CephContext> cct;
+ std::optional<NoDoutPrefix> prefix;
+ protected:
+ void SetUp() override {
+ CephInitParameters params(CEPH_ENTITY_TYPE_CLIENT);
+ cct = common_preinit(params, CODE_ENVIRONMENT_UTILITY,
+ CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
+ prefix.emplace(cct.get(), ceph_subsys_context);
+ }
+ void TearDown() override {
+ prefix.reset();
+ cct.reset();
+ }
+ const DoutPrefixProvider* dpp() { return &*prefix; }
+};
+
// test int as a Key type
-TEST(FaultInjectorInt, Default)
+using FaultInjectorInt = Fixture;
+
+TEST_F(FaultInjectorInt, Default)
{
constexpr FaultInjector<int> f;
EXPECT_EQ(f.check(0), 0);
EXPECT_EQ(f.check(3), 0);
}
-TEST(FaultInjectorInt, InjectError)
+TEST_F(FaultInjectorInt, InjectError)
{
constexpr FaultInjector f{2, InjectError{-EINVAL}};
EXPECT_EQ(f.check(0), 0);
EXPECT_EQ(f.check(3), 0);
}
-TEST(FaultInjectorInt, InjectErrorMessage)
+TEST_F(FaultInjectorInt, InjectErrorMessage)
{
FaultInjector f{2, InjectError{-EINVAL, dpp()}};
EXPECT_EQ(f.check(0), 0);
EXPECT_EQ(f.check(3), 0);
}
-TEST(FaultInjectorInt, AssignError)
+TEST_F(FaultInjectorInt, AssignError)
{
FaultInjector<int> f;
ASSERT_EQ(f.check(0), 0);
EXPECT_EQ(f.check(0), -EINVAL);
}
-TEST(FaultInjectorInt, AssignErrorMessage)
+TEST_F(FaultInjectorInt, AssignErrorMessage)
{
FaultInjector<int> f;
ASSERT_EQ(f.check(0), 0);
}
// test std::string_view as a Key type
-TEST(FaultInjectorString, Default)
+using FaultInjectorString = Fixture;
+
+TEST_F(FaultInjectorString, Default)
{
constexpr FaultInjector<std::string_view> f;
EXPECT_EQ(f.check("Red"), 0);
EXPECT_EQ(f.check("Blue"), 0);
}
-TEST(FaultInjectorString, InjectError)
+TEST_F(FaultInjectorString, InjectError)
{
FaultInjector<std::string_view> f{"Red", InjectError{-EIO}};
EXPECT_EQ(f.check("Red"), -EIO);
EXPECT_EQ(f.check("Blue"), 0);
}
-TEST(FaultInjectorString, InjectErrorMessage)
+TEST_F(FaultInjectorString, InjectErrorMessage)
{
FaultInjector<std::string_view> f{"Red", InjectError{-EIO, dpp()}};
EXPECT_EQ(f.check("Red"), -EIO);
EXPECT_EQ(f.check("Blue"), 0);
}
-TEST(FaultInjectorString, AssignError)
+TEST_F(FaultInjectorString, AssignError)
{
FaultInjector<std::string_view> f;
ASSERT_EQ(f.check("Red"), 0);
EXPECT_EQ(f.check("Red"), -EINVAL);
}
-TEST(FaultInjectorString, AssignErrorMessage)
+TEST_F(FaultInjectorString, AssignErrorMessage)
{
FaultInjector<std::string_view> f;
ASSERT_EQ(f.check("Red"), 0);
}
// test enum class as a Key type
+using FaultInjectorEnum = Fixture;
+
enum class Color { Red, Green, Blue };
static std::ostream& operator<<(std::ostream& out, const Color& c) {
return out;
}
-TEST(FaultInjectorEnum, Default)
+TEST_F(FaultInjectorEnum, Default)
{
constexpr FaultInjector<Color> f;
EXPECT_EQ(f.check(Color::Red), 0);
EXPECT_EQ(f.check(Color::Blue), 0);
}
-TEST(FaultInjectorEnum, InjectError)
+TEST_F(FaultInjectorEnum, InjectError)
{
FaultInjector f{Color::Red, InjectError{-EIO}};
EXPECT_EQ(f.check(Color::Red), -EIO);
EXPECT_EQ(f.check(Color::Blue), 0);
}
-TEST(FaultInjectorEnum, InjectErrorMessage)
+TEST_F(FaultInjectorEnum, InjectErrorMessage)
{
FaultInjector f{Color::Red, InjectError{-EIO, dpp()}};
EXPECT_EQ(f.check(Color::Red), -EIO);
EXPECT_EQ(f.check(Color::Blue), 0);
}
-TEST(FaultInjectorEnum, AssignError)
+TEST_F(FaultInjectorEnum, AssignError)
{
FaultInjector<Color> f;
ASSERT_EQ(f.check(Color::Red), 0);
EXPECT_EQ(f.check(Color::Red), -EINVAL);
}
-TEST(FaultInjectorEnum, AssignErrorMessage)
+TEST_F(FaultInjectorEnum, AssignErrorMessage)
{
FaultInjector<Color> f;
ASSERT_EQ(f.check(Color::Red), 0);
}
// test custom move-only Key type
+using FaultInjectorMoveOnly = Fixture;
+
struct MoveOnlyKey {
MoveOnlyKey() = default;
MoveOnlyKey(const MoveOnlyKey&) = delete;
return out;
}
-TEST(FaultInjectorMoveOnly, Default)
+TEST_F(FaultInjectorMoveOnly, Default)
{
constexpr FaultInjector<MoveOnlyKey> f;
EXPECT_EQ(f.check(MoveOnlyKey{}), 0);
}
-TEST(FaultInjectorMoveOnly, InjectError)
+TEST_F(FaultInjectorMoveOnly, InjectError)
{
FaultInjector f{MoveOnlyKey{}, InjectError{-EIO}};
EXPECT_EQ(f.check(MoveOnlyKey{}), -EIO);
}
-TEST(FaultInjectorMoveOnly, InjectErrorMessage)
+TEST_F(FaultInjectorMoveOnly, InjectErrorMessage)
{
FaultInjector f{MoveOnlyKey{}, InjectError{-EIO, dpp()}};
EXPECT_EQ(f.check(MoveOnlyKey{}), -EIO);
}
-TEST(FaultInjectorMoveOnly, AssignError)
+TEST_F(FaultInjectorMoveOnly, AssignError)
{
FaultInjector<MoveOnlyKey> f;
ASSERT_EQ(f.check({}), 0);
EXPECT_EQ(f.check({}), -EINVAL);
}
-TEST(FaultInjectorMoveOnly, AssignErrorMessage)
+TEST_F(FaultInjectorMoveOnly, AssignErrorMessage)
{
FaultInjector<MoveOnlyKey> f;
ASSERT_EQ(f.check({}), 0);