1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/librbd/test_mock_fixture.h"
5 #include "test/librbd/test_support.h"
6 #include "test/librbd/mock/MockExclusiveLock.h"
7 #include "test/librbd/mock/MockImageCtx.h"
8 #include "test/librbd/mock/MockImageState.h"
9 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
10 #include "test/librados_test_stub/MockTestMemRadosClient.h"
11 #include "include/rbd/librbd.hpp"
12 #include "librbd/Utils.h"
13 #include "librbd/trash/MoveRequest.h"
18 struct MockTestImageCtx
: public MockImageCtx
{
19 static MockTestImageCtx
*s_instance
;
20 static MockTestImageCtx
*create(const std::string
&image_name
,
21 const std::string
&image_id
,
22 const char *snap
, librados::IoCtx
& p
,
24 ceph_assert(s_instance
!= nullptr);
25 s_instance
->construct(image_name
, image_id
);
29 MOCK_METHOD2(construct
, void(const std::string
&, const std::string
&));
31 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
32 : librbd::MockImageCtx(image_ctx
) {
37 MockTestImageCtx
*MockTestImageCtx::s_instance
= nullptr;
39 } // anonymous namespace
42 #include "librbd/trash/MoveRequest.cc"
48 using ::testing::InSequence
;
49 using ::testing::Invoke
;
50 using ::testing::Return
;
51 using ::testing::StrEq
;
52 using ::testing::WithArg
;
54 struct TestMockTrashMoveRequest
: public TestMockFixture
{
55 typedef MoveRequest
<librbd::MockTestImageCtx
> MockMoveRequest
;
57 void expect_trash_add(MockTestImageCtx
&mock_image_ctx
,
58 const std::string
& image_id
,
59 cls::rbd::TrashImageSource trash_image_source
,
60 const std::string
& name
,
61 const utime_t
& end_time
,
63 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
64 exec(StrEq("rbd_trash"), _
, StrEq("rbd"), StrEq("trash_add"),
66 .WillOnce(WithArg
<4>(Invoke([=](bufferlist
& in_bl
) {
68 cls::rbd::TrashImageSpec trash_image_spec
;
70 auto bl_it
= in_bl
.cbegin();
72 decode(trash_image_spec
, bl_it
);
74 EXPECT_EQ(id
, image_id
);
75 EXPECT_EQ(trash_image_spec
.source
,
77 EXPECT_EQ(trash_image_spec
.name
, name
);
78 EXPECT_EQ(trash_image_spec
.deferment_end_time
,
84 void expect_aio_remove(MockTestImageCtx
&mock_image_ctx
,
85 const std::string
& oid
, int r
) {
86 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
), remove(oid
, _
))
90 void expect_dir_remove(MockTestImageCtx
& mock_image_ctx
,
91 const std::string
& name
, const std::string
& id
,
97 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
98 exec(StrEq("rbd_directory"), _
, StrEq("rbd"), StrEq("dir_remove_image"),
99 ContentsEqual(in_bl
), _
, _
, _
))
100 .WillOnce(Return(r
));
104 TEST_F(TestMockTrashMoveRequest
, Success
) {
107 librbd::ImageCtx
*ictx
;
108 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
110 MockTestImageCtx
mock_image_ctx(*ictx
);
111 MockExclusiveLock mock_exclusive_lock
;
112 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
113 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
116 expect_op_work_queue(mock_image_ctx
);
119 utime_t delete_time
{ceph_clock_now()};
120 expect_trash_add(mock_image_ctx
, "image id",
121 cls::rbd::TRASH_IMAGE_SOURCE_USER
, "image name", delete_time
,
123 expect_aio_remove(mock_image_ctx
, util::id_obj_name("image name"), 0);
124 expect_dir_remove(mock_image_ctx
, "image name", "image id", 0);
127 cls::rbd::TrashImageSpec trash_image_spec
{
128 cls::rbd::TRASH_IMAGE_SOURCE_USER
, "image name", delete_time
,
130 auto req
= MockMoveRequest::create(mock_image_ctx
.md_ctx
, "image id",
131 trash_image_spec
, &ctx
);
133 ASSERT_EQ(0, ctx
.wait());
136 TEST_F(TestMockTrashMoveRequest
, TrashAddError
) {
139 librbd::ImageCtx
*ictx
;
140 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
142 MockTestImageCtx
mock_image_ctx(*ictx
);
143 MockExclusiveLock mock_exclusive_lock
;
144 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
145 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
148 expect_op_work_queue(mock_image_ctx
);
151 utime_t delete_time
{ceph_clock_now()};
152 expect_trash_add(mock_image_ctx
, "image id",
153 cls::rbd::TRASH_IMAGE_SOURCE_USER
, "image name", delete_time
,
157 cls::rbd::TrashImageSpec trash_image_spec
{
158 cls::rbd::TRASH_IMAGE_SOURCE_USER
, "image name", delete_time
,
160 auto req
= MockMoveRequest::create(mock_image_ctx
.md_ctx
, "image id",
161 trash_image_spec
, &ctx
);
163 ASSERT_EQ(-EPERM
, ctx
.wait());
166 TEST_F(TestMockTrashMoveRequest
, RemoveIdError
) {
169 librbd::ImageCtx
*ictx
;
170 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
172 MockTestImageCtx
mock_image_ctx(*ictx
);
173 MockExclusiveLock mock_exclusive_lock
;
174 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
175 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
178 expect_op_work_queue(mock_image_ctx
);
181 utime_t delete_time
{ceph_clock_now()};
182 expect_trash_add(mock_image_ctx
, "image id",
183 cls::rbd::TRASH_IMAGE_SOURCE_USER
, "image name", delete_time
,
185 expect_aio_remove(mock_image_ctx
, util::id_obj_name("image name"), -EPERM
);
188 cls::rbd::TrashImageSpec trash_image_spec
{
189 cls::rbd::TRASH_IMAGE_SOURCE_USER
, "image name", delete_time
,
191 auto req
= MockMoveRequest::create(mock_image_ctx
.md_ctx
, "image id",
192 trash_image_spec
, &ctx
);
194 ASSERT_EQ(-EPERM
, ctx
.wait());
197 TEST_F(TestMockTrashMoveRequest
, DirectoryRemoveError
) {
200 librbd::ImageCtx
*ictx
;
201 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
203 MockTestImageCtx
mock_image_ctx(*ictx
);
204 MockExclusiveLock mock_exclusive_lock
;
205 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
206 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
209 expect_op_work_queue(mock_image_ctx
);
212 utime_t delete_time
{ceph_clock_now()};
213 expect_trash_add(mock_image_ctx
, "image id",
214 cls::rbd::TRASH_IMAGE_SOURCE_USER
, "image name", delete_time
,
216 expect_aio_remove(mock_image_ctx
, util::id_obj_name("image name"), 0);
217 expect_dir_remove(mock_image_ctx
, "image name", "image id", -EPERM
);
220 cls::rbd::TrashImageSpec trash_image_spec
{
221 cls::rbd::TRASH_IMAGE_SOURCE_USER
, "image name", delete_time
,
223 auto req
= MockMoveRequest::create(mock_image_ctx
.md_ctx
, "image id",
224 trash_image_spec
, &ctx
);
226 ASSERT_EQ(-EPERM
, ctx
.wait());
230 } // namespace librbd