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 explicit 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 ceph_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
;
95 encode(tag_data
, tag_data_bl
);
97 EXPECT_CALL(mock_journaler
, allocate_tag(456, ContentsEqual(tag_data_bl
),
99 .WillOnce(WithArg
<3>(CompleteContext(r
, static_cast<ContextWQ
*>(NULL
))));
102 void expect_append_journaler(::journal::MockJournaler
&mock_journaler
) {
103 EXPECT_CALL(mock_journaler
, append(_
, _
))
104 .WillOnce(Return(::journal::MockFutureProxy()));
107 void expect_future_flush(::journal::MockFuture
&mock_future
, int r
) {
108 EXPECT_CALL(mock_future
, flush(_
))
109 .WillOnce(CompleteContext(r
, static_cast<ContextWQ
*>(NULL
)));
112 void expect_future_committed(::journal::MockJournaler
&mock_journaler
) {
113 EXPECT_CALL(mock_journaler
, committed(A
<const ::journal::MockFutureProxy
&>()));
116 void expect_flush_commit_position(::journal::MockJournaler
&mock_journaler
,
118 EXPECT_CALL(mock_journaler
, flush_commit_position(_
))
119 .WillOnce(CompleteContext(r
, static_cast<ContextWQ
*>(NULL
)));
122 void expect_start_append(::journal::MockJournaler
&mock_journaler
) {
123 EXPECT_CALL(mock_journaler
, start_append(_
));
126 void expect_stop_append(::journal::MockJournaler
&mock_journaler
, int r
) {
127 EXPECT_CALL(mock_journaler
, stop_append(_
))
128 .WillOnce(CompleteContext(r
, static_cast<ContextWQ
*>(NULL
)));
131 void expect_shut_down_journaler(::journal::MockJournaler
&mock_journaler
,
133 EXPECT_CALL(mock_journaler
, shut_down(_
))
134 .WillOnce(CompleteContext(r
, static_cast<ContextWQ
*>(NULL
)));
139 TEST_F(TestMockJournalPromoteRequest
, SuccessOrderly
) {
140 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
142 librbd::ImageCtx
*ictx
;
143 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
145 MockTestImageCtx
mock_image_ctx(*ictx
);
146 ::journal::MockJournaler mock_journaler
;
147 MockOpenRequest mock_open_request
;
149 expect_op_work_queue(mock_image_ctx
);
152 expect_construct_journaler(mock_journaler
);
153 expect_open_journaler(mock_image_ctx
, mock_open_request
, 0);
154 expect_allocate_tag(mock_journaler
,
155 {Journal
<>::ORPHAN_MIRROR_UUID
, true, 567, 1}, 0);
157 ::journal::MockFuture mock_future
;
158 expect_start_append(mock_journaler
);
159 expect_append_journaler(mock_journaler
);
160 expect_future_flush(mock_future
, 0);
161 expect_future_committed(mock_journaler
);
162 expect_flush_commit_position(mock_journaler
, 0);
163 expect_stop_append(mock_journaler
, 0);
165 expect_shut_down_journaler(mock_journaler
, 0);
168 auto req
= MockPromoteRequest::create(&mock_image_ctx
, false, &ctx
);
170 ASSERT_EQ(0, ctx
.wait());
173 TEST_F(TestMockJournalPromoteRequest
, SuccessForced
) {
174 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
176 librbd::ImageCtx
*ictx
;
177 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
179 MockTestImageCtx
mock_image_ctx(*ictx
);
180 ::journal::MockJournaler mock_journaler
;
181 MockOpenRequest mock_open_request
;
183 expect_op_work_queue(mock_image_ctx
);
186 expect_construct_journaler(mock_journaler
);
187 expect_open_journaler(mock_image_ctx
, mock_open_request
, 0);
188 expect_allocate_tag(mock_journaler
,
189 {Journal
<>::LOCAL_MIRROR_UUID
, true, 567, 0}, 0);
191 ::journal::MockFuture mock_future
;
192 expect_start_append(mock_journaler
);
193 expect_append_journaler(mock_journaler
);
194 expect_future_flush(mock_future
, 0);
195 expect_future_committed(mock_journaler
);
196 expect_flush_commit_position(mock_journaler
, 0);
197 expect_stop_append(mock_journaler
, 0);
199 expect_shut_down_journaler(mock_journaler
, 0);
202 auto req
= MockPromoteRequest::create(&mock_image_ctx
, true, &ctx
);
204 ASSERT_EQ(0, ctx
.wait());
207 TEST_F(TestMockJournalPromoteRequest
, OpenError
) {
208 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
210 librbd::ImageCtx
*ictx
;
211 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
213 MockTestImageCtx
mock_image_ctx(*ictx
);
214 ::journal::MockJournaler mock_journaler
;
215 MockOpenRequest mock_open_request
;
217 expect_op_work_queue(mock_image_ctx
);
220 expect_construct_journaler(mock_journaler
);
221 expect_open_journaler(mock_image_ctx
, mock_open_request
, -ENOENT
);
222 expect_shut_down_journaler(mock_journaler
, -EINVAL
);
225 auto req
= MockPromoteRequest::create(&mock_image_ctx
, false, &ctx
);
227 ASSERT_EQ(-ENOENT
, ctx
.wait());
230 TEST_F(TestMockJournalPromoteRequest
, AllocateTagError
) {
231 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
233 librbd::ImageCtx
*ictx
;
234 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
236 MockTestImageCtx
mock_image_ctx(*ictx
);
237 ::journal::MockJournaler mock_journaler
;
238 MockOpenRequest mock_open_request
;
240 expect_op_work_queue(mock_image_ctx
);
243 expect_construct_journaler(mock_journaler
);
244 expect_open_journaler(mock_image_ctx
, mock_open_request
, 0);
245 expect_allocate_tag(mock_journaler
,
246 {Journal
<>::LOCAL_MIRROR_UUID
, true, 567, 0}, -EBADMSG
);
247 expect_shut_down_journaler(mock_journaler
, -EINVAL
);
250 auto req
= MockPromoteRequest::create(&mock_image_ctx
, true, &ctx
);
252 ASSERT_EQ(-EBADMSG
, ctx
.wait());
255 TEST_F(TestMockJournalPromoteRequest
, AppendEventError
) {
256 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
258 librbd::ImageCtx
*ictx
;
259 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
261 MockTestImageCtx
mock_image_ctx(*ictx
);
262 ::journal::MockJournaler mock_journaler
;
263 MockOpenRequest mock_open_request
;
265 expect_op_work_queue(mock_image_ctx
);
268 expect_construct_journaler(mock_journaler
);
269 expect_open_journaler(mock_image_ctx
, mock_open_request
, 0);
270 expect_allocate_tag(mock_journaler
,
271 {Journal
<>::ORPHAN_MIRROR_UUID
, true, 567, 1}, 0);
273 ::journal::MockFuture mock_future
;
274 expect_start_append(mock_journaler
);
275 expect_append_journaler(mock_journaler
);
276 expect_future_flush(mock_future
, -EPERM
);
277 expect_stop_append(mock_journaler
, 0);
279 expect_shut_down_journaler(mock_journaler
, 0);
282 auto req
= MockPromoteRequest::create(&mock_image_ctx
, false, &ctx
);
284 ASSERT_EQ(-EPERM
, ctx
.wait());
287 TEST_F(TestMockJournalPromoteRequest
, CommitEventError
) {
288 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
290 librbd::ImageCtx
*ictx
;
291 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
293 MockTestImageCtx
mock_image_ctx(*ictx
);
294 ::journal::MockJournaler mock_journaler
;
295 MockOpenRequest mock_open_request
;
297 expect_op_work_queue(mock_image_ctx
);
300 expect_construct_journaler(mock_journaler
);
301 expect_open_journaler(mock_image_ctx
, mock_open_request
, 0);
302 expect_allocate_tag(mock_journaler
,
303 {Journal
<>::ORPHAN_MIRROR_UUID
, true, 567, 1}, 0);
305 ::journal::MockFuture mock_future
;
306 expect_start_append(mock_journaler
);
307 expect_append_journaler(mock_journaler
);
308 expect_future_flush(mock_future
, 0);
309 expect_future_committed(mock_journaler
);
310 expect_flush_commit_position(mock_journaler
, -EINVAL
);
311 expect_stop_append(mock_journaler
, 0);
313 expect_shut_down_journaler(mock_journaler
, 0);
316 auto req
= MockPromoteRequest::create(&mock_image_ctx
, false, &ctx
);
318 ASSERT_EQ(-EINVAL
, ctx
.wait());
321 TEST_F(TestMockJournalPromoteRequest
, ShutDownError
) {
322 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
324 librbd::ImageCtx
*ictx
;
325 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
327 MockTestImageCtx
mock_image_ctx(*ictx
);
328 ::journal::MockJournaler mock_journaler
;
329 MockOpenRequest mock_open_request
;
331 expect_op_work_queue(mock_image_ctx
);
334 expect_construct_journaler(mock_journaler
);
335 expect_open_journaler(mock_image_ctx
, mock_open_request
, 0);
336 expect_allocate_tag(mock_journaler
,
337 {Journal
<>::LOCAL_MIRROR_UUID
, true, 567, 0}, 0);
339 ::journal::MockFuture mock_future
;
340 expect_start_append(mock_journaler
);
341 expect_append_journaler(mock_journaler
);
342 expect_future_flush(mock_future
, 0);
343 expect_future_committed(mock_journaler
);
344 expect_flush_commit_position(mock_journaler
, 0);
345 expect_stop_append(mock_journaler
, 0);
347 expect_shut_down_journaler(mock_journaler
, -EINVAL
);
350 auto req
= MockPromoteRequest::create(&mock_image_ctx
, true, &ctx
);
352 ASSERT_EQ(-EINVAL
, ctx
.wait());
355 } // namespace journal
356 } // namespace librbd