From 19fcec84d8d7d21e796c7624e521b60d28ee21ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:45:59 +0200 Subject: Adding upstream version 16.2.11+ds. Signed-off-by: Daniel Baumann --- src/test/librbd/trash/test_mock_MoveRequest.cc | 230 +++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 src/test/librbd/trash/test_mock_MoveRequest.cc (limited to 'src/test/librbd/trash/test_mock_MoveRequest.cc') diff --git a/src/test/librbd/trash/test_mock_MoveRequest.cc b/src/test/librbd/trash/test_mock_MoveRequest.cc new file mode 100644 index 000000000..1a35c62ae --- /dev/null +++ b/src/test/librbd/trash/test_mock_MoveRequest.cc @@ -0,0 +1,230 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "test/librbd/test_mock_fixture.h" +#include "test/librbd/test_support.h" +#include "test/librbd/mock/MockExclusiveLock.h" +#include "test/librbd/mock/MockImageCtx.h" +#include "test/librbd/mock/MockImageState.h" +#include "test/librados_test_stub/MockTestMemIoCtxImpl.h" +#include "test/librados_test_stub/MockTestMemRadosClient.h" +#include "include/rbd/librbd.hpp" +#include "librbd/Utils.h" +#include "librbd/trash/MoveRequest.h" + +namespace librbd { +namespace { + +struct MockTestImageCtx : public MockImageCtx { + static MockTestImageCtx *s_instance; + static MockTestImageCtx *create(const std::string &image_name, + const std::string &image_id, + const char *snap, librados::IoCtx& p, + bool read_only) { + ceph_assert(s_instance != nullptr); + s_instance->construct(image_name, image_id); + return s_instance; + } + + MOCK_METHOD2(construct, void(const std::string&, const std::string&)); + + MockTestImageCtx(librbd::ImageCtx &image_ctx) + : librbd::MockImageCtx(image_ctx) { + s_instance = this; + } +}; + +MockTestImageCtx *MockTestImageCtx::s_instance = nullptr; + +} // anonymous namespace +} // namespace librbd + +#include "librbd/trash/MoveRequest.cc" + +namespace librbd { +namespace trash { + +using ::testing::_; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::Return; +using ::testing::StrEq; +using ::testing::WithArg; + +struct TestMockTrashMoveRequest : public TestMockFixture { + typedef MoveRequest MockMoveRequest; + + void expect_trash_add(MockTestImageCtx &mock_image_ctx, + const std::string& image_id, + cls::rbd::TrashImageSource trash_image_source, + const std::string& name, + const utime_t& end_time, + int r) { + EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(StrEq("rbd_trash"), _, StrEq("rbd"), StrEq("trash_add"), + _, _, _, _)) + .WillOnce(WithArg<4>(Invoke([=](bufferlist& in_bl) { + std::string id; + cls::rbd::TrashImageSpec trash_image_spec; + + auto bl_it = in_bl.cbegin(); + decode(id, bl_it); + decode(trash_image_spec, bl_it); + + EXPECT_EQ(id, image_id); + EXPECT_EQ(trash_image_spec.source, + trash_image_source); + EXPECT_EQ(trash_image_spec.name, name); + EXPECT_EQ(trash_image_spec.deferment_end_time, + end_time); + return r; + }))); + } + + void expect_aio_remove(MockTestImageCtx &mock_image_ctx, + const std::string& oid, int r) { + EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), remove(oid, _)) + .WillOnce(Return(r)); + } + + void expect_dir_remove(MockTestImageCtx& mock_image_ctx, + const std::string& name, const std::string& id, + int r) { + bufferlist in_bl; + encode(name, in_bl); + encode(id, in_bl); + + EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(StrEq("rbd_directory"), _, StrEq("rbd"), StrEq("dir_remove_image"), + ContentsEqual(in_bl), _, _, _)) + .WillOnce(Return(r)); + } +}; + +TEST_F(TestMockTrashMoveRequest, Success) { + REQUIRE_FORMAT_V2(); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + + expect_op_work_queue(mock_image_ctx); + + InSequence seq; + utime_t delete_time{ceph_clock_now()}; + expect_trash_add(mock_image_ctx, "image id", + cls::rbd::TRASH_IMAGE_SOURCE_USER, "image name", delete_time, + 0); + expect_aio_remove(mock_image_ctx, util::id_obj_name("image name"), 0); + expect_dir_remove(mock_image_ctx, "image name", "image id", 0); + + C_SaferCond ctx; + cls::rbd::TrashImageSpec trash_image_spec{ + cls::rbd::TRASH_IMAGE_SOURCE_USER, "image name", delete_time, + delete_time}; + auto req = MockMoveRequest::create(mock_image_ctx.md_ctx, "image id", + trash_image_spec, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockTrashMoveRequest, TrashAddError) { + REQUIRE_FORMAT_V2(); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + + expect_op_work_queue(mock_image_ctx); + + InSequence seq; + utime_t delete_time{ceph_clock_now()}; + expect_trash_add(mock_image_ctx, "image id", + cls::rbd::TRASH_IMAGE_SOURCE_USER, "image name", delete_time, + -EPERM); + + C_SaferCond ctx; + cls::rbd::TrashImageSpec trash_image_spec{ + cls::rbd::TRASH_IMAGE_SOURCE_USER, "image name", delete_time, + delete_time}; + auto req = MockMoveRequest::create(mock_image_ctx.md_ctx, "image id", + trash_image_spec, &ctx); + req->send(); + ASSERT_EQ(-EPERM, ctx.wait()); +} + +TEST_F(TestMockTrashMoveRequest, RemoveIdError) { + REQUIRE_FORMAT_V2(); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + + expect_op_work_queue(mock_image_ctx); + + InSequence seq; + utime_t delete_time{ceph_clock_now()}; + expect_trash_add(mock_image_ctx, "image id", + cls::rbd::TRASH_IMAGE_SOURCE_USER, "image name", delete_time, + 0); + expect_aio_remove(mock_image_ctx, util::id_obj_name("image name"), -EPERM); + + C_SaferCond ctx; + cls::rbd::TrashImageSpec trash_image_spec{ + cls::rbd::TRASH_IMAGE_SOURCE_USER, "image name", delete_time, + delete_time}; + auto req = MockMoveRequest::create(mock_image_ctx.md_ctx, "image id", + trash_image_spec, &ctx); + req->send(); + ASSERT_EQ(-EPERM, ctx.wait()); +} + +TEST_F(TestMockTrashMoveRequest, DirectoryRemoveError) { + REQUIRE_FORMAT_V2(); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + + expect_op_work_queue(mock_image_ctx); + + InSequence seq; + utime_t delete_time{ceph_clock_now()}; + expect_trash_add(mock_image_ctx, "image id", + cls::rbd::TRASH_IMAGE_SOURCE_USER, "image name", delete_time, + 0); + expect_aio_remove(mock_image_ctx, util::id_obj_name("image name"), 0); + expect_dir_remove(mock_image_ctx, "image name", "image id", -EPERM); + + C_SaferCond ctx; + cls::rbd::TrashImageSpec trash_image_spec{ + cls::rbd::TRASH_IMAGE_SOURCE_USER, "image name", delete_time, + delete_time}; + auto req = MockMoveRequest::create(mock_image_ctx.md_ctx, "image id", + trash_image_spec, &ctx); + req->send(); + ASSERT_EQ(-EPERM, ctx.wait()); +} + +} // namespace trash +} // namespace librbd -- cgit v1.2.3