Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librbd / operation / test_mock_SnapshotUnprotectRequest.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
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 "test/librados_test_stub/MockTestMemRadosClient.h"
9 #include "include/rados/librados.hpp"
10 #include "common/bit_vector.hpp"
11 #include "librbd/ImageState.h"
12 #include "librbd/internal.h"
13 #include "librbd/operation/SnapshotUnprotectRequest.h"
14 #include "gmock/gmock.h"
15 #include "gtest/gtest.h"
16
17 // template definitions
18 #include "librbd/operation/SnapshotUnprotectRequest.cc"
19
20 namespace librbd {
21 namespace operation {
22
23 using ::testing::_;
24 using ::testing::DoAll;
25 using ::testing::DoDefault;
26 using ::testing::Return;
27 using ::testing::SetArgReferee;
28 using ::testing::SetArgPointee;
29 using ::testing::StrEq;
30 using ::testing::WithArg;
31
32 class TestMockOperationSnapshotUnprotectRequest : public TestMockFixture {
33 public:
34   typedef SnapshotUnprotectRequest<MockImageCtx> MockSnapshotUnprotectRequest;
35
36   void expect_get_snap_id(MockImageCtx &mock_image_ctx, uint64_t snap_id) {
37     EXPECT_CALL(mock_image_ctx, get_snap_id(_, _))
38                   .WillOnce(Return(snap_id));
39   }
40
41   void expect_is_snap_unprotected(MockImageCtx &mock_image_ctx,
42                                   bool is_unprotected, int r) {
43     auto &expect = EXPECT_CALL(mock_image_ctx, is_snap_unprotected(_, _));
44     if (r < 0) {
45       expect.WillOnce(Return(r));
46     } else {
47       expect.WillOnce(DoAll(SetArgPointee<1>(is_unprotected), Return(0)));
48     }
49   }
50
51   void expect_set_protection_status(MockImageCtx &mock_image_ctx,
52                                     uint64_t snap_id, uint8_t status, int r) {
53     bufferlist bl;
54     ::encode(snap_id, bl);
55     ::encode(status, bl);
56
57     auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
58                                exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
59                                     StrEq("set_protection_status"), ContentsEqual(bl),
60                                     _, _));
61     if (r < 0) {
62       expect.WillOnce(Return(r));
63     } else {
64       expect.WillOnce(DoDefault());
65     }
66   }
67
68   size_t expect_create_pool_io_contexts(MockImageCtx &mock_image_ctx) {
69     librados::MockTestMemIoCtxImpl &io_ctx_impl =
70       get_mock_io_ctx(mock_image_ctx.md_ctx);
71     librados::MockTestMemRadosClient *rados_client =
72       io_ctx_impl.get_mock_rados_client();
73
74     std::list<std::pair<int64_t, std::string> > pools;
75     int r = rados_client->pool_list(pools);
76     if (r < 0) {
77       ADD_FAILURE() << "failed to list pools";
78       return 0;
79     }
80
81     EXPECT_CALL(*rados_client, create_ioctx(_, _))
82                   .Times(pools.size()).WillRepeatedly(DoAll(
83                     GetReference(&io_ctx_impl), Return(&io_ctx_impl)));
84     return pools.size();
85   }
86
87   void expect_get_children(MockImageCtx &mock_image_ctx, size_t pools, int r) {
88     bufferlist bl;
89     std::set<std::string> children;
90     ::encode(children, bl);
91
92     auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
93                                exec(RBD_CHILDREN, _, StrEq("rbd"), StrEq("get_children"), _,
94                                _, _));
95     if (r < 0) {
96       expect.WillRepeatedly(Return(r));
97     } else {
98       expect.Times(pools).WillRepeatedly(DoAll(
99         SetArgPointee<5>(bl), Return(0)));
100     }
101   }
102 };
103
104 TEST_F(TestMockOperationSnapshotUnprotectRequest, Success) {
105   REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
106
107   librbd::ImageCtx *ictx;
108   ASSERT_EQ(0, open_image(m_image_name, &ictx));
109   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
110   ASSERT_EQ(0, ictx->state->refresh_if_required());
111
112   MockImageCtx mock_image_ctx(*ictx);
113
114   expect_op_work_queue(mock_image_ctx);
115
116   ::testing::InSequence seq;
117   uint64_t snap_id = ictx->snap_info.rbegin()->first;
118   expect_get_snap_id(mock_image_ctx, snap_id);
119   expect_is_snap_unprotected(mock_image_ctx, false, 0);
120   expect_set_protection_status(mock_image_ctx, snap_id,
121                                RBD_PROTECTION_STATUS_UNPROTECTING, 0);
122   size_t pools = expect_create_pool_io_contexts(mock_image_ctx);
123   expect_get_children(mock_image_ctx, pools, -ENOENT);
124   expect_set_protection_status(mock_image_ctx, snap_id,
125                                RBD_PROTECTION_STATUS_UNPROTECTED, 0);
126
127   C_SaferCond cond_ctx;
128   MockSnapshotUnprotectRequest *req = new MockSnapshotUnprotectRequest(
129     mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
130   {
131     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
132     req->send();
133   }
134   ASSERT_EQ(0, cond_ctx.wait());
135 }
136
137 TEST_F(TestMockOperationSnapshotUnprotectRequest, GetSnapIdMissing) {
138   REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
139
140   librbd::ImageCtx *ictx;
141   ASSERT_EQ(0, open_image(m_image_name, &ictx));
142   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
143   ASSERT_EQ(0, ictx->state->refresh_if_required());
144
145   MockImageCtx mock_image_ctx(*ictx);
146
147   expect_op_work_queue(mock_image_ctx);
148
149   ::testing::InSequence seq;
150   expect_get_snap_id(mock_image_ctx, CEPH_NOSNAP);
151
152   C_SaferCond cond_ctx;
153   MockSnapshotUnprotectRequest *req = new MockSnapshotUnprotectRequest(
154     mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
155   {
156     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
157     req->send();
158   }
159   ASSERT_EQ(-ENOENT, cond_ctx.wait());
160 }
161
162 TEST_F(TestMockOperationSnapshotUnprotectRequest, IsSnapUnprotectedError) {
163   REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
164
165   librbd::ImageCtx *ictx;
166   ASSERT_EQ(0, open_image(m_image_name, &ictx));
167   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
168   ASSERT_EQ(0, ictx->state->refresh_if_required());
169
170   MockImageCtx mock_image_ctx(*ictx);
171
172   expect_op_work_queue(mock_image_ctx);
173
174   ::testing::InSequence seq;
175   expect_get_snap_id(mock_image_ctx, ictx->snap_info.rbegin()->first);
176   expect_is_snap_unprotected(mock_image_ctx, false, -EBADMSG);
177
178   C_SaferCond cond_ctx;
179   MockSnapshotUnprotectRequest *req = new MockSnapshotUnprotectRequest(
180     mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
181   {
182     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
183     req->send();
184   }
185   ASSERT_EQ(-EBADMSG, cond_ctx.wait());
186 }
187
188 TEST_F(TestMockOperationSnapshotUnprotectRequest, SnapAlreadyUnprotected) {
189   REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
190
191   librbd::ImageCtx *ictx;
192   ASSERT_EQ(0, open_image(m_image_name, &ictx));
193   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
194   ASSERT_EQ(0, ictx->state->refresh_if_required());
195
196   MockImageCtx mock_image_ctx(*ictx);
197
198   expect_op_work_queue(mock_image_ctx);
199
200   ::testing::InSequence seq;
201   expect_get_snap_id(mock_image_ctx, ictx->snap_info.rbegin()->first);
202   expect_is_snap_unprotected(mock_image_ctx, true, 0);
203
204   C_SaferCond cond_ctx;
205   MockSnapshotUnprotectRequest *req = new MockSnapshotUnprotectRequest(
206     mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
207   {
208     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
209     req->send();
210   }
211   ASSERT_EQ(-EINVAL, cond_ctx.wait());
212 }
213
214 TEST_F(TestMockOperationSnapshotUnprotectRequest, SetProtectionStatusError) {
215   REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
216
217   librbd::ImageCtx *ictx;
218   ASSERT_EQ(0, open_image(m_image_name, &ictx));
219   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
220   ASSERT_EQ(0, ictx->state->refresh_if_required());
221
222   MockImageCtx mock_image_ctx(*ictx);
223
224   expect_op_work_queue(mock_image_ctx);
225
226   ::testing::InSequence seq;
227   uint64_t snap_id = ictx->snap_info.rbegin()->first;
228   expect_get_snap_id(mock_image_ctx, snap_id);
229   expect_is_snap_unprotected(mock_image_ctx, false, 0);
230   expect_set_protection_status(mock_image_ctx, snap_id,
231                                RBD_PROTECTION_STATUS_UNPROTECTING, -EINVAL);
232
233   C_SaferCond cond_ctx;
234   MockSnapshotUnprotectRequest *req = new MockSnapshotUnprotectRequest(
235     mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
236   {
237     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
238     req->send();
239   }
240   ASSERT_EQ(-EINVAL, cond_ctx.wait());
241 }
242
243 TEST_F(TestMockOperationSnapshotUnprotectRequest, ChildrenExist) {
244   REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
245
246   librbd::ImageCtx *ictx;
247   ASSERT_EQ(0, open_image(m_image_name, &ictx));
248   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
249   ASSERT_EQ(0, ictx->state->refresh_if_required());
250
251   MockImageCtx mock_image_ctx(*ictx);
252
253   expect_op_work_queue(mock_image_ctx);
254
255   ::testing::InSequence seq;
256   uint64_t snap_id = ictx->snap_info.rbegin()->first;
257   expect_get_snap_id(mock_image_ctx, snap_id);
258   expect_is_snap_unprotected(mock_image_ctx, false, 0);
259   expect_set_protection_status(mock_image_ctx, snap_id,
260                                RBD_PROTECTION_STATUS_UNPROTECTING, 0);
261   size_t pools = expect_create_pool_io_contexts(mock_image_ctx);
262   expect_get_children(mock_image_ctx, pools, 0);
263   expect_set_protection_status(mock_image_ctx, snap_id,
264                                RBD_PROTECTION_STATUS_PROTECTED, 0);
265
266   C_SaferCond cond_ctx;
267   MockSnapshotUnprotectRequest *req = new MockSnapshotUnprotectRequest(
268     mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), "snap1");
269   {
270     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
271     req->send();
272   }
273   ASSERT_EQ(-EBUSY, cond_ctx.wait());
274 }
275
276 } // namespace operation
277 } // namespace librbd