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/MockImageCtx.h"
7 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
8 #include "common/bit_vector.hpp"
9 #include "librbd/ImageState.h"
10 #include "librbd/internal.h"
11 #include "librbd/operation/SnapshotProtectRequest.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
15 // template definitions
16 #include "librbd/operation/SnapshotProtectRequest.cc"
22 using ::testing::DoAll;
23 using ::testing::DoDefault;
24 using ::testing::Return;
25 using ::testing::SetArgPointee;
26 using ::testing::StrEq;
27 using ::testing::WithArg;
29 class TestMockOperationSnapshotProtectRequest : public TestMockFixture {
31 typedef SnapshotProtectRequest<MockImageCtx> MockSnapshotProtectRequest;
33 void expect_get_snap_id(MockImageCtx &mock_image_ctx, uint64_t snap_id) {
34 EXPECT_CALL(mock_image_ctx, get_snap_id(_, _))
35 .WillOnce(Return(snap_id));
38 void expect_is_snap_protected(MockImageCtx &mock_image_ctx, bool is_protected,
40 auto &expect = EXPECT_CALL(mock_image_ctx, is_snap_protected(_, _));
42 expect.WillOnce(Return(r));
44 expect.WillOnce(DoAll(SetArgPointee<1>(is_protected), Return(0)));
48 void expect_set_protection_status(MockImageCtx &mock_image_ctx, int r) {
49 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
50 exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
51 StrEq("set_protection_status"), _, _, _));
53 expect.WillOnce(Return(r));
55 expect.WillOnce(DoDefault());
60 TEST_F(TestMockOperationSnapshotProtectRequest, Success) {
61 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
63 librbd::ImageCtx *ictx;
64 ASSERT_EQ(0, open_image(m_image_name, &ictx));
65 ASSERT_EQ(0, snap_create(*ictx, "snap1"));
66 ASSERT_EQ(0, ictx->state->refresh_if_required());
68 MockImageCtx mock_image_ctx(*ictx);
70 expect_op_work_queue(mock_image_ctx);
72 ::testing::InSequence seq;
73 expect_get_snap_id(mock_image_ctx, ictx->snap_info.rbegin()->first);
74 expect_is_snap_protected(mock_image_ctx, false, 0);
75 expect_set_protection_status(mock_image_ctx, 0);
78 MockSnapshotProtectRequest *req = new MockSnapshotProtectRequest(
79 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
81 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
84 ASSERT_EQ(0, cond_ctx.wait());
87 TEST_F(TestMockOperationSnapshotProtectRequest, GetSnapIdMissing) {
88 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
90 librbd::ImageCtx *ictx;
91 ASSERT_EQ(0, open_image(m_image_name, &ictx));
92 ASSERT_EQ(0, snap_create(*ictx, "snap1"));
93 ASSERT_EQ(0, ictx->state->refresh_if_required());
95 MockImageCtx mock_image_ctx(*ictx);
97 expect_op_work_queue(mock_image_ctx);
99 ::testing::InSequence seq;
100 expect_get_snap_id(mock_image_ctx, CEPH_NOSNAP);
102 C_SaferCond cond_ctx;
103 MockSnapshotProtectRequest *req = new MockSnapshotProtectRequest(
104 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
106 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
109 ASSERT_EQ(-ENOENT, cond_ctx.wait());
112 TEST_F(TestMockOperationSnapshotProtectRequest, IsSnapProtectedError) {
113 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
115 librbd::ImageCtx *ictx;
116 ASSERT_EQ(0, open_image(m_image_name, &ictx));
117 ASSERT_EQ(0, snap_create(*ictx, "snap1"));
118 ASSERT_EQ(0, ictx->state->refresh_if_required());
120 MockImageCtx mock_image_ctx(*ictx);
122 expect_op_work_queue(mock_image_ctx);
124 ::testing::InSequence seq;
125 expect_get_snap_id(mock_image_ctx, ictx->snap_info.rbegin()->first);
126 expect_is_snap_protected(mock_image_ctx, false, -EINVAL);
128 C_SaferCond cond_ctx;
129 MockSnapshotProtectRequest *req = new MockSnapshotProtectRequest(
130 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
132 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
135 ASSERT_EQ(-EINVAL, cond_ctx.wait());
138 TEST_F(TestMockOperationSnapshotProtectRequest, SnapAlreadyProtected) {
139 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
141 librbd::ImageCtx *ictx;
142 ASSERT_EQ(0, open_image(m_image_name, &ictx));
143 ASSERT_EQ(0, snap_create(*ictx, "snap1"));
144 ASSERT_EQ(0, ictx->state->refresh_if_required());
146 MockImageCtx mock_image_ctx(*ictx);
148 expect_op_work_queue(mock_image_ctx);
150 ::testing::InSequence seq;
151 expect_get_snap_id(mock_image_ctx, ictx->snap_info.rbegin()->first);
152 expect_is_snap_protected(mock_image_ctx, true, 0);
154 C_SaferCond cond_ctx;
155 MockSnapshotProtectRequest *req = new MockSnapshotProtectRequest(
156 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
158 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
161 ASSERT_EQ(-EBUSY, cond_ctx.wait());
164 TEST_F(TestMockOperationSnapshotProtectRequest, SetProtectionStateError) {
165 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
167 librbd::ImageCtx *ictx;
168 ASSERT_EQ(0, open_image(m_image_name, &ictx));
169 ASSERT_EQ(0, snap_create(*ictx, "snap1"));
170 ASSERT_EQ(0, ictx->state->refresh_if_required());
172 MockImageCtx mock_image_ctx(*ictx);
174 expect_op_work_queue(mock_image_ctx);
176 ::testing::InSequence seq;
177 expect_get_snap_id(mock_image_ctx, ictx->snap_info.rbegin()->first);
178 expect_is_snap_protected(mock_image_ctx, false, 0);
179 expect_set_protection_status(mock_image_ctx, -EINVAL);
181 C_SaferCond cond_ctx;
182 MockSnapshotProtectRequest *req = new MockSnapshotProtectRequest(
183 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
185 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
188 ASSERT_EQ(-EINVAL, cond_ctx.wait());
191 } // namespace operation
192 } // namespace librbd