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/librbd/mock/MockImageState.h"
8 #include "test/librbd/mock/MockJournal.h"
9 #include "test/librbd/mock/MockJournalPolicy.h"
10 #include "test/librbd/mock/MockObjectMap.h"
11 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
12 #include "test/librados_test_stub/MockTestMemRadosClient.h"
13 #include "librbd/exclusive_lock/PostAcquireRequest.h"
14 #include "librbd/image/RefreshRequest.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
17 #include <arpa/inet.h>
23 struct MockTestImageCtx : public librbd::MockImageCtx {
24 MockTestImageCtx(librbd::ImageCtx &image_ctx)
25 : librbd::MockImageCtx(image_ctx) {
29 inline ImageCtx &get_image_ctx(MockTestImageCtx &image_ctx) {
30 return *(image_ctx.image_ctx);
33 } // anonymous namespace
38 struct RefreshRequest<librbd::MockTestImageCtx> {
39 static RefreshRequest *s_instance;
42 static RefreshRequest *create(librbd::MockTestImageCtx &image_ctx,
43 bool acquire_lock_refresh,
44 bool skip_open_parent, Context *on_finish) {
45 EXPECT_TRUE(acquire_lock_refresh);
46 assert(s_instance != nullptr);
47 s_instance->on_finish = on_finish;
54 MOCK_METHOD0(send, void());
57 RefreshRequest<librbd::MockTestImageCtx> *RefreshRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
62 // template definitions
63 #include "librbd/Journal.cc"
65 #include "librbd/exclusive_lock/PostAcquireRequest.cc"
66 template class librbd::exclusive_lock::PostAcquireRequest<librbd::MockTestImageCtx>;
68 ACTION_P3(FinishRequest2, request, r, mock) {
69 mock->image_ctx->op_work_queue->queue(request->on_finish, r);
74 namespace exclusive_lock {
77 using ::testing::DoAll;
78 using ::testing::InSequence;
79 using ::testing::Invoke;
80 using ::testing::Return;
81 using ::testing::SetArgPointee;
82 using ::testing::StrEq;
83 using ::testing::WithArg;
85 static const std::string TEST_COOKIE("auto 123");
87 class TestMockExclusiveLockPostAcquireRequest : public TestMockFixture {
89 typedef PostAcquireRequest<MockTestImageCtx> MockPostAcquireRequest;
90 typedef librbd::image::RefreshRequest<MockTestImageCtx> MockRefreshRequest;
92 void expect_test_features(MockTestImageCtx &mock_image_ctx, uint64_t features,
94 EXPECT_CALL(mock_image_ctx, test_features(features))
95 .WillOnce(Return(enabled));
98 void expect_test_features(MockTestImageCtx &mock_image_ctx, uint64_t features,
99 RWLock &lock, bool enabled) {
100 EXPECT_CALL(mock_image_ctx, test_features(features, _))
101 .WillOnce(Return(enabled));
104 void expect_is_refresh_required(MockTestImageCtx &mock_image_ctx, bool required) {
105 EXPECT_CALL(*mock_image_ctx.state, is_refresh_required())
106 .WillOnce(Return(required));
109 void expect_refresh(MockTestImageCtx &mock_image_ctx,
110 MockRefreshRequest &mock_refresh_request, int r) {
111 EXPECT_CALL(mock_refresh_request, send())
112 .WillOnce(FinishRequest2(&mock_refresh_request, r,
116 void expect_create_object_map(MockTestImageCtx &mock_image_ctx,
117 MockObjectMap *mock_object_map) {
118 EXPECT_CALL(mock_image_ctx, create_object_map(_))
119 .WillOnce(Return(mock_object_map));
122 void expect_open_object_map(MockTestImageCtx &mock_image_ctx,
123 MockObjectMap &mock_object_map, int r) {
124 EXPECT_CALL(mock_object_map, open(_))
125 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
128 void expect_close_object_map(MockTestImageCtx &mock_image_ctx,
129 MockObjectMap &mock_object_map) {
130 EXPECT_CALL(mock_object_map, close(_))
131 .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
134 void expect_create_journal(MockTestImageCtx &mock_image_ctx,
135 MockJournal *mock_journal) {
136 EXPECT_CALL(mock_image_ctx, create_journal())
137 .WillOnce(Return(mock_journal));
140 void expect_open_journal(MockTestImageCtx &mock_image_ctx,
141 MockJournal &mock_journal, int r) {
142 EXPECT_CALL(mock_journal, open(_))
143 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
146 void expect_close_journal(MockTestImageCtx &mock_image_ctx,
147 MockJournal &mock_journal) {
148 EXPECT_CALL(mock_journal, close(_))
149 .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
152 void expect_get_journal_policy(MockTestImageCtx &mock_image_ctx,
153 MockJournalPolicy &mock_journal_policy) {
154 EXPECT_CALL(mock_image_ctx, get_journal_policy())
155 .WillOnce(Return(&mock_journal_policy));
158 void expect_journal_disabled(MockJournalPolicy &mock_journal_policy,
160 EXPECT_CALL(mock_journal_policy, journal_disabled())
161 .WillOnce(Return(disabled));
164 void expect_allocate_journal_tag(MockTestImageCtx &mock_image_ctx,
165 MockJournalPolicy &mock_journal_policy,
167 EXPECT_CALL(mock_journal_policy, allocate_tag_on_lock(_))
168 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
171 void expect_handle_prepare_lock_complete(MockTestImageCtx &mock_image_ctx) {
172 EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
177 TEST_F(TestMockExclusiveLockPostAcquireRequest, Success) {
178 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
180 librbd::ImageCtx *ictx;
181 ASSERT_EQ(0, open_image(m_image_name, &ictx));
183 MockTestImageCtx mock_image_ctx(*ictx);
184 expect_op_work_queue(mock_image_ctx);
187 expect_is_refresh_required(mock_image_ctx, false);
189 MockObjectMap mock_object_map;
190 expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
191 expect_create_object_map(mock_image_ctx, &mock_object_map);
192 expect_open_object_map(mock_image_ctx, mock_object_map, 0);
194 MockJournal mock_journal;
195 MockJournalPolicy mock_journal_policy;
196 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
197 mock_image_ctx.snap_lock, true);
198 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
199 expect_journal_disabled(mock_journal_policy, false);
200 expect_create_journal(mock_image_ctx, &mock_journal);
201 expect_handle_prepare_lock_complete(mock_image_ctx);
202 expect_open_journal(mock_image_ctx, mock_journal, 0);
203 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
204 expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
206 C_SaferCond acquire_ctx;
208 MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
212 ASSERT_EQ(0, acquire_ctx.wait());
213 ASSERT_EQ(0, ctx.wait());
216 TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessRefresh) {
217 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
219 librbd::ImageCtx *ictx;
220 ASSERT_EQ(0, open_image(m_image_name, &ictx));
222 MockTestImageCtx mock_image_ctx(*ictx);
223 MockRefreshRequest mock_refresh_request;
224 expect_op_work_queue(mock_image_ctx);
227 expect_is_refresh_required(mock_image_ctx, true);
228 expect_refresh(mock_image_ctx, mock_refresh_request, 0);
230 MockObjectMap mock_object_map;
231 expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
232 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
233 mock_image_ctx.snap_lock, false);
234 expect_handle_prepare_lock_complete(mock_image_ctx);
236 C_SaferCond acquire_ctx;
238 MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
242 ASSERT_EQ(0, acquire_ctx.wait());
243 ASSERT_EQ(0, ctx.wait());
246 TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessJournalDisabled) {
247 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
249 librbd::ImageCtx *ictx;
250 ASSERT_EQ(0, open_image(m_image_name, &ictx));
252 MockTestImageCtx mock_image_ctx(*ictx);
253 expect_op_work_queue(mock_image_ctx);
256 expect_is_refresh_required(mock_image_ctx, false);
258 MockObjectMap mock_object_map;
259 expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
260 expect_create_object_map(mock_image_ctx, &mock_object_map);
261 expect_open_object_map(mock_image_ctx, mock_object_map, 0);
263 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
264 mock_image_ctx.snap_lock, false);
265 expect_handle_prepare_lock_complete(mock_image_ctx);
267 C_SaferCond acquire_ctx;
269 MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
273 ASSERT_EQ(0, acquire_ctx.wait());
274 ASSERT_EQ(0, ctx.wait());
277 TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessObjectMapDisabled) {
278 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
280 librbd::ImageCtx *ictx;
281 ASSERT_EQ(0, open_image(m_image_name, &ictx));
283 MockTestImageCtx mock_image_ctx(*ictx);
284 expect_op_work_queue(mock_image_ctx);
287 expect_is_refresh_required(mock_image_ctx, false);
289 expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
291 MockJournal mock_journal;
292 MockJournalPolicy mock_journal_policy;
293 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
294 mock_image_ctx.snap_lock, true);
295 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
296 expect_journal_disabled(mock_journal_policy, false);
297 expect_create_journal(mock_image_ctx, &mock_journal);
298 expect_handle_prepare_lock_complete(mock_image_ctx);
299 expect_open_journal(mock_image_ctx, mock_journal, 0);
300 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
301 expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
303 C_SaferCond acquire_ctx;
305 MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
309 ASSERT_EQ(0, acquire_ctx.wait());
310 ASSERT_EQ(0, ctx.wait());
313 TEST_F(TestMockExclusiveLockPostAcquireRequest, RefreshError) {
314 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
316 librbd::ImageCtx *ictx;
317 ASSERT_EQ(0, open_image(m_image_name, &ictx));
319 MockTestImageCtx mock_image_ctx(*ictx);
320 MockRefreshRequest mock_refresh_request;
321 expect_op_work_queue(mock_image_ctx);
324 expect_is_refresh_required(mock_image_ctx, true);
325 expect_refresh(mock_image_ctx, mock_refresh_request, -EINVAL);
326 expect_handle_prepare_lock_complete(mock_image_ctx);
328 C_SaferCond *acquire_ctx = new C_SaferCond();
330 MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
334 ASSERT_EQ(-EINVAL, ctx.wait());
337 TEST_F(TestMockExclusiveLockPostAcquireRequest, RefreshLockDisabled) {
338 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
340 librbd::ImageCtx *ictx;
341 ASSERT_EQ(0, open_image(m_image_name, &ictx));
343 MockTestImageCtx mock_image_ctx(*ictx);
344 MockRefreshRequest mock_refresh_request;
345 expect_op_work_queue(mock_image_ctx);
348 expect_is_refresh_required(mock_image_ctx, true);
349 expect_refresh(mock_image_ctx, mock_refresh_request, -ERESTART);
351 MockObjectMap mock_object_map;
352 expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
353 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
354 mock_image_ctx.snap_lock, false);
355 expect_handle_prepare_lock_complete(mock_image_ctx);
357 C_SaferCond acquire_ctx;
359 MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
363 ASSERT_EQ(0, acquire_ctx.wait());
364 ASSERT_EQ(0, ctx.wait());
367 TEST_F(TestMockExclusiveLockPostAcquireRequest, JournalError) {
368 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
370 librbd::ImageCtx *ictx;
371 ASSERT_EQ(0, open_image(m_image_name, &ictx));
373 MockTestImageCtx mock_image_ctx(*ictx);
374 expect_op_work_queue(mock_image_ctx);
377 expect_is_refresh_required(mock_image_ctx, false);
379 MockObjectMap *mock_object_map = new MockObjectMap();
380 expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
381 expect_create_object_map(mock_image_ctx, mock_object_map);
382 expect_open_object_map(mock_image_ctx, *mock_object_map, 0);
384 MockJournal *mock_journal = new MockJournal();
385 MockJournalPolicy mock_journal_policy;
386 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
387 mock_image_ctx.snap_lock, true);
388 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
389 expect_journal_disabled(mock_journal_policy, false);
390 expect_create_journal(mock_image_ctx, mock_journal);
391 expect_handle_prepare_lock_complete(mock_image_ctx);
392 expect_open_journal(mock_image_ctx, *mock_journal, -EINVAL);
393 expect_close_journal(mock_image_ctx, *mock_journal);
394 expect_close_object_map(mock_image_ctx, *mock_object_map);
396 C_SaferCond acquire_ctx;
398 MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
402 ASSERT_EQ(-EINVAL, ctx.wait());
405 TEST_F(TestMockExclusiveLockPostAcquireRequest, AllocateJournalTagError) {
406 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
408 librbd::ImageCtx *ictx;
409 ASSERT_EQ(0, open_image(m_image_name, &ictx));
411 MockTestImageCtx mock_image_ctx(*ictx);
412 expect_op_work_queue(mock_image_ctx);
415 expect_is_refresh_required(mock_image_ctx, false);
417 MockObjectMap *mock_object_map = new MockObjectMap();
418 expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
419 expect_create_object_map(mock_image_ctx, mock_object_map);
420 expect_open_object_map(mock_image_ctx, *mock_object_map, 0);
422 MockJournal *mock_journal = new MockJournal();
423 MockJournalPolicy mock_journal_policy;
424 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
425 mock_image_ctx.snap_lock, true);
426 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
427 expect_journal_disabled(mock_journal_policy, false);
428 expect_create_journal(mock_image_ctx, mock_journal);
429 expect_handle_prepare_lock_complete(mock_image_ctx);
430 expect_open_journal(mock_image_ctx, *mock_journal, 0);
431 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
432 expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, -EPERM);
433 expect_close_journal(mock_image_ctx, *mock_journal);
434 expect_close_object_map(mock_image_ctx, *mock_object_map);
436 C_SaferCond acquire_ctx;
438 MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
442 ASSERT_EQ(-EPERM, ctx.wait());
445 TEST_F(TestMockExclusiveLockPostAcquireRequest, OpenObjectMapError) {
446 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
448 librbd::ImageCtx *ictx;
449 ASSERT_EQ(0, open_image(m_image_name, &ictx));
451 MockTestImageCtx mock_image_ctx(*ictx);
452 expect_op_work_queue(mock_image_ctx);
455 expect_is_refresh_required(mock_image_ctx, false);
457 MockObjectMap *mock_object_map = new MockObjectMap();
458 expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
459 expect_create_object_map(mock_image_ctx, mock_object_map);
460 expect_open_object_map(mock_image_ctx, *mock_object_map, -EFBIG);
462 MockJournal mock_journal;
463 MockJournalPolicy mock_journal_policy;
464 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
465 mock_image_ctx.snap_lock, true);
466 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
467 expect_journal_disabled(mock_journal_policy, false);
468 expect_create_journal(mock_image_ctx, &mock_journal);
469 expect_handle_prepare_lock_complete(mock_image_ctx);
470 expect_open_journal(mock_image_ctx, mock_journal, 0);
471 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
472 expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
474 C_SaferCond acquire_ctx;
476 MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
480 ASSERT_EQ(0, acquire_ctx.wait());
481 ASSERT_EQ(0, ctx.wait());
482 ASSERT_EQ(nullptr, mock_image_ctx.object_map);
485 } // namespace exclusive_lock
486 } // namespace librbd