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/journal/mock/MockJournaler.h"
8 #include "librbd/journal/OpenRequest.h"
9 #include "librbd/journal/PromoteRequest.h"
15 struct MockTestImageCtx : public MockImageCtx {
16 MockTestImageCtx(librbd::ImageCtx& image_ctx) : MockImageCtx(image_ctx) {
20 } // anonymous namespace
25 struct TypeTraits<MockTestImageCtx> {
26 typedef ::journal::MockJournalerProxy Journaler;
27 typedef ::journal::MockFutureProxy Future;
31 struct OpenRequest<MockTestImageCtx> {
32 Context *on_finish = nullptr;
33 static OpenRequest *s_instance;
34 static OpenRequest *create(MockTestImageCtx *image_ctx,
35 ::journal::MockJournalerProxy *journaler,
36 Mutex *lock, ImageClientMeta *client_meta,
37 uint64_t *tag_tid, journal::TagData *tag_data,
39 assert(s_instance != nullptr);
40 client_meta->tag_class = 456;
41 tag_data->mirror_uuid = Journal<>::ORPHAN_MIRROR_UUID;
43 s_instance->on_finish = on_finish;
51 MOCK_METHOD0(send, void());
54 OpenRequest<MockTestImageCtx> *OpenRequest<MockTestImageCtx>::s_instance = nullptr;
56 } // namespace journal
59 // template definitions
60 #include "librbd/journal/PromoteRequest.cc"
61 template class librbd::journal::PromoteRequest<librbd::MockTestImageCtx>;
68 using ::testing::InSequence;
69 using ::testing::Return;
70 using ::testing::WithArg;
72 class TestMockJournalPromoteRequest : public TestMockFixture {
74 typedef PromoteRequest<MockTestImageCtx> MockPromoteRequest;
75 typedef OpenRequest<MockTestImageCtx> MockOpenRequest;
77 void expect_construct_journaler(::journal::MockJournaler &mock_journaler) {
78 EXPECT_CALL(mock_journaler, construct());
81 void expect_open_journaler(MockTestImageCtx &mock_image_ctx,
82 MockOpenRequest &mock_open_request, int r) {
83 EXPECT_CALL(mock_open_request, send())
84 .WillOnce(FinishRequest(&mock_open_request, r, &mock_image_ctx));
87 void expect_allocate_tag(::journal::MockJournaler &mock_journaler,
88 const journal::TagPredecessor &predecessor, int r) {
90 tag_data.mirror_uuid = Journal<>::LOCAL_MIRROR_UUID;
91 tag_data.predecessor = predecessor;
93 bufferlist tag_data_bl;
94 ::encode(tag_data, tag_data_bl);
96 EXPECT_CALL(mock_journaler, allocate_tag(456, ContentsEqual(tag_data_bl),
98 .WillOnce(WithArg<3>(CompleteContext(r, static_cast<ContextWQ*>(NULL))));
101 void expect_append_journaler(::journal::MockJournaler &mock_journaler) {
102 EXPECT_CALL(mock_journaler, append(_, _))
103 .WillOnce(Return(::journal::MockFutureProxy()));
106 void expect_future_flush(::journal::MockFuture &mock_future, int r) {
107 EXPECT_CALL(mock_future, flush(_))
108 .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL)));
111 void expect_future_committed(::journal::MockJournaler &mock_journaler) {
112 EXPECT_CALL(mock_journaler, committed(A<const ::journal::MockFutureProxy &>()));
115 void expect_flush_commit_position(::journal::MockJournaler &mock_journaler,
117 EXPECT_CALL(mock_journaler, flush_commit_position(_))
118 .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL)));
121 void expect_start_append(::journal::MockJournaler &mock_journaler) {
122 EXPECT_CALL(mock_journaler, start_append(_, _, _));
125 void expect_stop_append(::journal::MockJournaler &mock_journaler, int r) {
126 EXPECT_CALL(mock_journaler, stop_append(_))
127 .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL)));
130 void expect_shut_down_journaler(::journal::MockJournaler &mock_journaler,
132 EXPECT_CALL(mock_journaler, shut_down(_))
133 .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL)));
138 TEST_F(TestMockJournalPromoteRequest, SuccessOrderly) {
139 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
141 librbd::ImageCtx *ictx;
142 ASSERT_EQ(0, open_image(m_image_name, &ictx));
144 MockTestImageCtx mock_image_ctx(*ictx);
145 ::journal::MockJournaler mock_journaler;
146 MockOpenRequest mock_open_request;
148 expect_op_work_queue(mock_image_ctx);
151 expect_construct_journaler(mock_journaler);
152 expect_open_journaler(mock_image_ctx, mock_open_request, 0);
153 expect_allocate_tag(mock_journaler,
154 {Journal<>::ORPHAN_MIRROR_UUID, true, 567, 1}, 0);
156 ::journal::MockFuture mock_future;
157 expect_start_append(mock_journaler);
158 expect_append_journaler(mock_journaler);
159 expect_future_flush(mock_future, 0);
160 expect_future_committed(mock_journaler);
161 expect_flush_commit_position(mock_journaler, 0);
162 expect_stop_append(mock_journaler, 0);
164 expect_shut_down_journaler(mock_journaler, 0);
167 auto req = MockPromoteRequest::create(&mock_image_ctx, false, &ctx);
169 ASSERT_EQ(0, ctx.wait());
172 TEST_F(TestMockJournalPromoteRequest, SuccessForced) {
173 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
175 librbd::ImageCtx *ictx;
176 ASSERT_EQ(0, open_image(m_image_name, &ictx));
178 MockTestImageCtx mock_image_ctx(*ictx);
179 ::journal::MockJournaler mock_journaler;
180 MockOpenRequest mock_open_request;
182 expect_op_work_queue(mock_image_ctx);
185 expect_construct_journaler(mock_journaler);
186 expect_open_journaler(mock_image_ctx, mock_open_request, 0);
187 expect_allocate_tag(mock_journaler,
188 {Journal<>::LOCAL_MIRROR_UUID, true, 567, 0}, 0);
190 ::journal::MockFuture mock_future;
191 expect_start_append(mock_journaler);
192 expect_append_journaler(mock_journaler);
193 expect_future_flush(mock_future, 0);
194 expect_future_committed(mock_journaler);
195 expect_flush_commit_position(mock_journaler, 0);
196 expect_stop_append(mock_journaler, 0);
198 expect_shut_down_journaler(mock_journaler, 0);
201 auto req = MockPromoteRequest::create(&mock_image_ctx, true, &ctx);
203 ASSERT_EQ(0, ctx.wait());
206 TEST_F(TestMockJournalPromoteRequest, OpenError) {
207 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
209 librbd::ImageCtx *ictx;
210 ASSERT_EQ(0, open_image(m_image_name, &ictx));
212 MockTestImageCtx mock_image_ctx(*ictx);
213 ::journal::MockJournaler mock_journaler;
214 MockOpenRequest mock_open_request;
216 expect_op_work_queue(mock_image_ctx);
219 expect_construct_journaler(mock_journaler);
220 expect_open_journaler(mock_image_ctx, mock_open_request, -ENOENT);
221 expect_shut_down_journaler(mock_journaler, -EINVAL);
224 auto req = MockPromoteRequest::create(&mock_image_ctx, false, &ctx);
226 ASSERT_EQ(-ENOENT, ctx.wait());
229 TEST_F(TestMockJournalPromoteRequest, AllocateTagError) {
230 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
232 librbd::ImageCtx *ictx;
233 ASSERT_EQ(0, open_image(m_image_name, &ictx));
235 MockTestImageCtx mock_image_ctx(*ictx);
236 ::journal::MockJournaler mock_journaler;
237 MockOpenRequest mock_open_request;
239 expect_op_work_queue(mock_image_ctx);
242 expect_construct_journaler(mock_journaler);
243 expect_open_journaler(mock_image_ctx, mock_open_request, 0);
244 expect_allocate_tag(mock_journaler,
245 {Journal<>::LOCAL_MIRROR_UUID, true, 567, 0}, -EBADMSG);
246 expect_shut_down_journaler(mock_journaler, -EINVAL);
249 auto req = MockPromoteRequest::create(&mock_image_ctx, true, &ctx);
251 ASSERT_EQ(-EBADMSG, ctx.wait());
254 TEST_F(TestMockJournalPromoteRequest, AppendEventError) {
255 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
257 librbd::ImageCtx *ictx;
258 ASSERT_EQ(0, open_image(m_image_name, &ictx));
260 MockTestImageCtx mock_image_ctx(*ictx);
261 ::journal::MockJournaler mock_journaler;
262 MockOpenRequest mock_open_request;
264 expect_op_work_queue(mock_image_ctx);
267 expect_construct_journaler(mock_journaler);
268 expect_open_journaler(mock_image_ctx, mock_open_request, 0);
269 expect_allocate_tag(mock_journaler,
270 {Journal<>::ORPHAN_MIRROR_UUID, true, 567, 1}, 0);
272 ::journal::MockFuture mock_future;
273 expect_start_append(mock_journaler);
274 expect_append_journaler(mock_journaler);
275 expect_future_flush(mock_future, -EPERM);
276 expect_stop_append(mock_journaler, 0);
278 expect_shut_down_journaler(mock_journaler, 0);
281 auto req = MockPromoteRequest::create(&mock_image_ctx, false, &ctx);
283 ASSERT_EQ(-EPERM, ctx.wait());
286 TEST_F(TestMockJournalPromoteRequest, CommitEventError) {
287 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
289 librbd::ImageCtx *ictx;
290 ASSERT_EQ(0, open_image(m_image_name, &ictx));
292 MockTestImageCtx mock_image_ctx(*ictx);
293 ::journal::MockJournaler mock_journaler;
294 MockOpenRequest mock_open_request;
296 expect_op_work_queue(mock_image_ctx);
299 expect_construct_journaler(mock_journaler);
300 expect_open_journaler(mock_image_ctx, mock_open_request, 0);
301 expect_allocate_tag(mock_journaler,
302 {Journal<>::ORPHAN_MIRROR_UUID, true, 567, 1}, 0);
304 ::journal::MockFuture mock_future;
305 expect_start_append(mock_journaler);
306 expect_append_journaler(mock_journaler);
307 expect_future_flush(mock_future, 0);
308 expect_future_committed(mock_journaler);
309 expect_flush_commit_position(mock_journaler, -EINVAL);
310 expect_stop_append(mock_journaler, 0);
312 expect_shut_down_journaler(mock_journaler, 0);
315 auto req = MockPromoteRequest::create(&mock_image_ctx, false, &ctx);
317 ASSERT_EQ(-EINVAL, ctx.wait());
320 TEST_F(TestMockJournalPromoteRequest, ShutDownError) {
321 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
323 librbd::ImageCtx *ictx;
324 ASSERT_EQ(0, open_image(m_image_name, &ictx));
326 MockTestImageCtx mock_image_ctx(*ictx);
327 ::journal::MockJournaler mock_journaler;
328 MockOpenRequest mock_open_request;
330 expect_op_work_queue(mock_image_ctx);
333 expect_construct_journaler(mock_journaler);
334 expect_open_journaler(mock_image_ctx, mock_open_request, 0);
335 expect_allocate_tag(mock_journaler,
336 {Journal<>::LOCAL_MIRROR_UUID, true, 567, 0}, 0);
338 ::journal::MockFuture mock_future;
339 expect_start_append(mock_journaler);
340 expect_append_journaler(mock_journaler);
341 expect_future_flush(mock_future, 0);
342 expect_future_committed(mock_journaler);
343 expect_flush_commit_position(mock_journaler, 0);
344 expect_stop_append(mock_journaler, 0);
346 expect_shut_down_journaler(mock_journaler, -EINVAL);
349 auto req = MockPromoteRequest::create(&mock_image_ctx, true, &ctx);
351 ASSERT_EQ(-EINVAL, ctx.wait());
354 } // namespace journal
355 } // namespace librbd