1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/rbd_mirror/test_mock_fixture.h"
5 #include "test/librados_test_stub/LibradosTestStub.h"
6 #include "include/rbd/librbd.hpp"
7 #include "librbd/ImageCtx.h"
8 #include "librbd/ImageState.h"
9 #include "librbd/Operations.h"
10 #include "osdc/Striper.h"
11 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
12 #include "test/librbd/mock/MockImageCtx.h"
13 #include "tools/rbd_mirror/image_sync/SnapshotCreateRequest.h"
14 #include "tools/rbd_mirror/Threads.h"
19 struct MockTestImageCtx : public librbd::MockImageCtx {
20 MockTestImageCtx(librbd::ImageCtx &image_ctx)
21 : librbd::MockImageCtx(image_ctx) {
25 } // anonymous namespace
28 // template definitions
29 #include "tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc"
30 template class rbd::mirror::image_sync::SnapshotCreateRequest<librbd::MockTestImageCtx>;
34 namespace image_sync {
37 using ::testing::DoAll;
38 using ::testing::InSequence;
39 using ::testing::Invoke;
40 using ::testing::InvokeWithoutArgs;
41 using ::testing::Return;
42 using ::testing::ReturnNew;
43 using ::testing::StrEq;
44 using ::testing::WithArg;
46 class TestMockImageSyncSnapshotCreateRequest : public TestMockFixture {
48 typedef SnapshotCreateRequest<librbd::MockTestImageCtx> MockSnapshotCreateRequest;
50 void SetUp() override {
51 TestMockFixture::SetUp();
54 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
55 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
58 void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
59 EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
60 ReturnNew<FunctionContext>([](int) {}));
63 void expect_test_features(librbd::MockTestImageCtx &mock_image_ctx,
64 uint64_t features, bool enabled) {
65 EXPECT_CALL(mock_image_ctx, test_features(features))
66 .WillOnce(Return(enabled));
69 void expect_set_size(librbd::MockTestImageCtx &mock_image_ctx, int r) {
70 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
71 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("set_size"), _, _, _))
75 void expect_remove_parent(librbd::MockTestImageCtx &mock_image_ctx, int r) {
76 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
77 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("remove_parent"), _, _, _))
81 void expect_set_parent(librbd::MockTestImageCtx &mock_image_ctx, int r) {
82 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
83 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("set_parent"), _, _, _))
87 void expect_snap_create(librbd::MockTestImageCtx &mock_image_ctx,
88 const std::string &snap_name, uint64_t snap_id, int r) {
89 EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(_, StrEq(snap_name), _, 0, true))
90 .WillOnce(DoAll(InvokeWithoutArgs([&mock_image_ctx, snap_id, snap_name]() {
91 inject_snap(mock_image_ctx, snap_id, snap_name);
93 WithArg<2>(Invoke([this, r](Context *ctx) {
94 m_threads->work_queue->queue(ctx, r);
98 void expect_object_map_resize(librbd::MockTestImageCtx &mock_image_ctx,
99 librados::snap_t snap_id, int r) {
100 std::string oid(librbd::ObjectMap<>::object_map_name(mock_image_ctx.id,
102 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
103 exec(oid, _, StrEq("rbd"), StrEq("object_map_resize"), _, _, _))
104 .WillOnce(Return(r));
107 static void inject_snap(librbd::MockTestImageCtx &mock_image_ctx,
108 uint64_t snap_id, const std::string &snap_name) {
109 mock_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(),
110 snap_name}] = snap_id;
113 MockSnapshotCreateRequest *create_request(librbd::MockTestImageCtx &mock_local_image_ctx,
114 const std::string &snap_name,
115 const cls::rbd::SnapshotNamespace &snap_namespace,
117 const librbd::ParentSpec &spec,
118 uint64_t parent_overlap,
119 Context *on_finish) {
120 return new MockSnapshotCreateRequest(&mock_local_image_ctx, snap_name, snap_namespace, size,
121 spec, parent_overlap, on_finish);
124 librbd::ImageCtx *m_local_image_ctx;
127 TEST_F(TestMockImageSyncSnapshotCreateRequest, Resize) {
128 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
129 librbd::MockExclusiveLock mock_exclusive_lock;
130 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
133 expect_start_op(mock_exclusive_lock);
134 expect_set_size(mock_local_image_ctx, 0);
135 expect_start_op(mock_exclusive_lock);
136 expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
137 expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
140 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
142 cls::rbd::UserSnapshotNamespace(),
146 ASSERT_EQ(0, ctx.wait());
149 TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeError) {
150 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
151 librbd::MockExclusiveLock mock_exclusive_lock;
152 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
155 expect_start_op(mock_exclusive_lock);
156 expect_set_size(mock_local_image_ctx, -EINVAL);
159 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
161 cls::rbd::UserSnapshotNamespace(),
165 ASSERT_EQ(-EINVAL, ctx.wait());
168 TEST_F(TestMockImageSyncSnapshotCreateRequest, RemoveParent) {
169 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
170 librbd::MockExclusiveLock mock_exclusive_lock;
171 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
173 mock_local_image_ctx.parent_md.spec.pool_id = 213;
176 expect_start_op(mock_exclusive_lock);
177 expect_remove_parent(mock_local_image_ctx, 0);
178 expect_start_op(mock_exclusive_lock);
179 expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
180 expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
183 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
185 cls::rbd::UserSnapshotNamespace(),
186 m_local_image_ctx->size,
189 ASSERT_EQ(0, ctx.wait());
192 TEST_F(TestMockImageSyncSnapshotCreateRequest, RemoveParentError) {
193 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
194 librbd::MockExclusiveLock mock_exclusive_lock;
195 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
197 mock_local_image_ctx.parent_md.spec.pool_id = 213;
200 expect_start_op(mock_exclusive_lock);
201 expect_remove_parent(mock_local_image_ctx, -EINVAL);
204 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
206 cls::rbd::UserSnapshotNamespace(),
207 m_local_image_ctx->size,
210 ASSERT_EQ(-EINVAL, ctx.wait());
213 TEST_F(TestMockImageSyncSnapshotCreateRequest, RemoveSetParent) {
214 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
215 librbd::MockExclusiveLock mock_exclusive_lock;
216 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
218 mock_local_image_ctx.parent_md.spec.pool_id = 213;
221 expect_start_op(mock_exclusive_lock);
222 expect_remove_parent(mock_local_image_ctx, 0);
223 expect_start_op(mock_exclusive_lock);
224 expect_set_parent(mock_local_image_ctx, 0);
225 expect_start_op(mock_exclusive_lock);
226 expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
227 expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
230 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
232 cls::rbd::UserSnapshotNamespace(),
233 m_local_image_ctx->size,
237 ASSERT_EQ(0, ctx.wait());
240 TEST_F(TestMockImageSyncSnapshotCreateRequest, SetParentSpec) {
241 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
242 librbd::MockExclusiveLock mock_exclusive_lock;
243 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
246 expect_start_op(mock_exclusive_lock);
247 expect_set_parent(mock_local_image_ctx, 0);
248 expect_start_op(mock_exclusive_lock);
249 expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
250 expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
253 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
255 cls::rbd::UserSnapshotNamespace(),
256 m_local_image_ctx->size,
260 ASSERT_EQ(0, ctx.wait());
263 TEST_F(TestMockImageSyncSnapshotCreateRequest, SetParentOverlap) {
264 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
265 librbd::MockExclusiveLock mock_exclusive_lock;
266 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
268 mock_local_image_ctx.parent_md.spec = {123, "test", 0};
271 expect_start_op(mock_exclusive_lock);
272 expect_set_parent(mock_local_image_ctx, 0);
273 expect_start_op(mock_exclusive_lock);
274 expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
275 expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
278 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
280 cls::rbd::UserSnapshotNamespace(),
281 m_local_image_ctx->size,
282 mock_local_image_ctx.parent_md.spec,
285 ASSERT_EQ(0, ctx.wait());
288 TEST_F(TestMockImageSyncSnapshotCreateRequest, SetParentError) {
289 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
290 librbd::MockExclusiveLock mock_exclusive_lock;
291 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
294 expect_start_op(mock_exclusive_lock);
295 expect_set_parent(mock_local_image_ctx, -ESTALE);
298 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
300 cls::rbd::UserSnapshotNamespace(),
301 m_local_image_ctx->size,
305 ASSERT_EQ(-ESTALE, ctx.wait());
308 TEST_F(TestMockImageSyncSnapshotCreateRequest, SnapCreate) {
309 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
310 librbd::MockExclusiveLock mock_exclusive_lock;
311 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
314 expect_start_op(mock_exclusive_lock);
315 expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
316 expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
319 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
321 cls::rbd::UserSnapshotNamespace(),
322 m_local_image_ctx->size,
325 ASSERT_EQ(0, ctx.wait());
328 TEST_F(TestMockImageSyncSnapshotCreateRequest, SnapCreateError) {
329 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
330 librbd::MockExclusiveLock mock_exclusive_lock;
331 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
334 expect_start_op(mock_exclusive_lock);
335 expect_snap_create(mock_local_image_ctx, "snap1", 10, -EINVAL);
338 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
340 cls::rbd::UserSnapshotNamespace(),
341 m_local_image_ctx->size,
344 ASSERT_EQ(-EINVAL, ctx.wait());
347 TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeObjectMap) {
348 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
349 librbd::MockExclusiveLock mock_exclusive_lock;
350 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
353 expect_start_op(mock_exclusive_lock);
354 expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
355 expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
356 expect_start_op(mock_exclusive_lock);
357 expect_object_map_resize(mock_local_image_ctx, 10, 0);
360 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
362 cls::rbd::UserSnapshotNamespace(),
363 m_local_image_ctx->size,
366 ASSERT_EQ(0, ctx.wait());
369 TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeObjectMapError) {
370 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
371 librbd::MockExclusiveLock mock_exclusive_lock;
372 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
375 expect_start_op(mock_exclusive_lock);
376 expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
377 expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
378 expect_start_op(mock_exclusive_lock);
379 expect_object_map_resize(mock_local_image_ctx, 10, -EINVAL);
382 MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
384 cls::rbd::UserSnapshotNamespace(),
385 m_local_image_ctx->size,
388 ASSERT_EQ(-EINVAL, ctx.wait());
391 } // namespace image_sync
392 } // namespace mirror