]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/image/test_mock_AttachChildRequest.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / librbd / image / test_mock_AttachChildRequest.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/librbd/mock/MockContextWQ.h"
8 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
9 #include "librbd/ImageState.h"
10 #include "librbd/Operations.h"
11 #include "librbd/image/AttachChildRequest.h"
12 #include "librbd/image/RefreshRequest.h"
13 #include "gmock/gmock.h"
14 #include "gtest/gtest.h"
15
16 namespace librbd {
17 namespace {
18
19 struct MockTestImageCtx : public MockImageCtx {
20 MockTestImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
21 }
22 };
23
24 } // anonymous namespace
25
26 namespace image {
27
28 template <>
29 struct RefreshRequest<MockTestImageCtx> {
30 Context* on_finish = nullptr;
31 static RefreshRequest* s_instance;
32 static RefreshRequest* create(MockTestImageCtx &image_ctx,
33 bool acquiring_lock, bool skip_open_parent,
34 Context *on_finish) {
35 ceph_assert(s_instance != nullptr);
36 s_instance->on_finish = on_finish;
37 return s_instance;
38 }
39
40 MOCK_METHOD0(send, void());
41
42 RefreshRequest() {
43 s_instance = this;
44 }
45 };
46
47 RefreshRequest<MockTestImageCtx>* RefreshRequest<MockTestImageCtx>::s_instance = nullptr;
48
49 } // namespace image
50
51 } // namespace librbd
52
53 // template definitions
54 #include "librbd/image/AttachChildRequest.cc"
55
56 namespace librbd {
57 namespace image {
58
59 using ::testing::_;
60 using ::testing::InSequence;
61 using ::testing::Invoke;
62 using ::testing::Return;
63 using ::testing::StrEq;
64 using ::testing::WithArg;
65
66 class TestMockImageAttachChildRequest : public TestMockFixture {
67 public:
68 typedef AttachChildRequest<MockTestImageCtx> MockAttachChildRequest;
69 typedef RefreshRequest<MockTestImageCtx> MockRefreshRequest;
70
71 void SetUp() override {
72 TestMockFixture::SetUp();
73
74 ASSERT_EQ(0, open_image(m_image_name, &image_ctx));
75 ASSERT_EQ(0, image_ctx->operations->snap_create(
76 cls::rbd::UserSnapshotNamespace{}, "snap"));
77 if (is_feature_enabled(RBD_FEATURE_LAYERING)) {
78 ASSERT_EQ(0, image_ctx->operations->snap_protect(
79 cls::rbd::UserSnapshotNamespace{}, "snap"));
80
81 uint64_t snap_id = image_ctx->snap_ids[
82 {cls::rbd::UserSnapshotNamespace{}, "snap"}];
83 ASSERT_NE(CEPH_NOSNAP, snap_id);
84
85 C_SaferCond ctx;
86 image_ctx->state->snap_set(snap_id, &ctx);
87 ASSERT_EQ(0, ctx.wait());
88 }
89 }
90
91 void expect_add_child(MockImageCtx &mock_image_ctx, int r) {
92 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
93 exec(RBD_CHILDREN, _, StrEq("rbd"), StrEq("add_child"), _, _, _))
94 .WillOnce(Return(r));
95 }
96
97 void expect_refresh(MockRefreshRequest& mock_refresh_request, int r) {
98 EXPECT_CALL(mock_refresh_request, send())
99 .WillOnce(Invoke([this, &mock_refresh_request, r]() {
100 image_ctx->op_work_queue->queue(mock_refresh_request.on_finish, r);
101 }));
102 }
103
104 void expect_is_snap_protected(MockImageCtx &mock_image_ctx, bool is_protected,
105 int r) {
106 EXPECT_CALL(mock_image_ctx, is_snap_protected(_, _))
107 .WillOnce(WithArg<1>(Invoke([is_protected, r](bool* is_prot) {
108 *is_prot = is_protected;
109 return r;
110 })));
111 }
112
113 void expect_op_features_set(MockImageCtx &mock_image_ctx, int r) {
114 bufferlist bl;
115 encode(static_cast<uint64_t>(RBD_OPERATION_FEATURE_CLONE_CHILD), bl);
116 encode(static_cast<uint64_t>(RBD_OPERATION_FEATURE_CLONE_CHILD), bl);
117
118 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
119 exec(util::header_name(mock_image_ctx.id), _, StrEq("rbd"),
120 StrEq("op_features_set"), ContentsEqual(bl), _, _))
121 .WillOnce(Return(r));
122 }
123
124 void expect_child_attach(MockImageCtx &mock_image_ctx, int r) {
125 bufferlist bl;
126 encode(mock_image_ctx.snap_id, bl);
127 encode(cls::rbd::ChildImageSpec{m_ioctx.get_id(), "", mock_image_ctx.id},
128 bl);
129
130 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
131 exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
132 StrEq("child_attach"), ContentsEqual(bl), _, _))
133 .WillOnce(Return(r));
134 }
135
136 librbd::ImageCtx *image_ctx;
137 };
138
139 TEST_F(TestMockImageAttachChildRequest, SuccessV1) {
140 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
141
142 MockTestImageCtx mock_image_ctx(*image_ctx);
143
144 InSequence seq;
145
146 expect_add_child(mock_image_ctx, 0);
147
148 MockRefreshRequest mock_refresh_request;
149 expect_refresh(mock_refresh_request, 0);
150 expect_is_snap_protected(mock_image_ctx, true, 0);
151
152 C_SaferCond ctx;
153 auto req = MockAttachChildRequest::create(&mock_image_ctx, &mock_image_ctx,
154 image_ctx->snap_id, nullptr, 0, 1,
155 &ctx);
156 req->send();
157 ASSERT_EQ(0, ctx.wait());
158 }
159
160 TEST_F(TestMockImageAttachChildRequest, SuccessV2) {
161 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
162
163 MockTestImageCtx mock_image_ctx(*image_ctx);
164
165 InSequence seq;
166
167 expect_op_features_set(mock_image_ctx, 0);
168 expect_child_attach(mock_image_ctx, 0);
169
170 C_SaferCond ctx;
171 auto req = MockAttachChildRequest::create(&mock_image_ctx, &mock_image_ctx,
172 image_ctx->snap_id, nullptr, 0, 2,
173 &ctx);
174 req->send();
175 ASSERT_EQ(0, ctx.wait());
176 }
177
178 TEST_F(TestMockImageAttachChildRequest, AddChildError) {
179 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
180
181 MockTestImageCtx mock_image_ctx(*image_ctx);
182
183 InSequence seq;
184
185 expect_add_child(mock_image_ctx, -EINVAL);
186
187 C_SaferCond ctx;
188 auto req = MockAttachChildRequest::create(&mock_image_ctx, &mock_image_ctx,
189 image_ctx->snap_id, nullptr, 0, 1,
190 &ctx);
191 req->send();
192 ASSERT_EQ(-EINVAL, ctx.wait());
193 }
194
195 TEST_F(TestMockImageAttachChildRequest, RefreshError) {
196 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
197
198 MockTestImageCtx mock_image_ctx(*image_ctx);
199
200 InSequence seq;
201
202 expect_add_child(mock_image_ctx, 0);
203
204 MockRefreshRequest mock_refresh_request;
205 expect_refresh(mock_refresh_request, -EINVAL);
206
207 C_SaferCond ctx;
208 auto req = MockAttachChildRequest::create(&mock_image_ctx, &mock_image_ctx,
209 image_ctx->snap_id, nullptr, 0, 1,
210 &ctx);
211 req->send();
212 ASSERT_EQ(-EINVAL, ctx.wait());
213 }
214
215 TEST_F(TestMockImageAttachChildRequest, ValidateProtectedFailed) {
216 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
217
218 MockTestImageCtx mock_image_ctx(*image_ctx);
219
220 InSequence seq;
221
222 expect_add_child(mock_image_ctx, 0);
223
224 MockRefreshRequest mock_refresh_request;
225 expect_refresh(mock_refresh_request, 0);
226 expect_is_snap_protected(mock_image_ctx, false, 0);
227
228 C_SaferCond ctx;
229 auto req = MockAttachChildRequest::create(&mock_image_ctx, &mock_image_ctx,
230 image_ctx->snap_id, nullptr, 0, 1,
231 &ctx);
232 req->send();
233 ASSERT_EQ(-EINVAL, ctx.wait());
234 }
235
236 TEST_F(TestMockImageAttachChildRequest, SetCloneError) {
237 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
238
239 MockTestImageCtx mock_image_ctx(*image_ctx);
240
241 InSequence seq;
242
243 expect_op_features_set(mock_image_ctx, -EINVAL);
244
245 C_SaferCond ctx;
246 auto req = MockAttachChildRequest::create(&mock_image_ctx, &mock_image_ctx,
247 image_ctx->snap_id, nullptr, 0, 2,
248 &ctx);
249 req->send();
250 ASSERT_EQ(-EINVAL, ctx.wait());
251 }
252
253 TEST_F(TestMockImageAttachChildRequest, AttachChildError) {
254 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
255
256 MockTestImageCtx mock_image_ctx(*image_ctx);
257
258 InSequence seq;
259
260 expect_op_features_set(mock_image_ctx, 0);
261 expect_child_attach(mock_image_ctx, -EINVAL);
262
263 C_SaferCond ctx;
264 auto req = MockAttachChildRequest::create(&mock_image_ctx, &mock_image_ctx,
265 image_ctx->snap_id, nullptr, 0, 2,
266 &ctx);
267 req->send();
268 ASSERT_EQ(-EINVAL, ctx.wait());
269 }
270
271 } // namespace image
272 } // namespace librbd