Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librbd / operation / test_mock_EnableFeaturesRequest.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 "cls/rbd/cls_rbd_client.h"
8 #include "librbd/Operations.h"
9 #include "librbd/internal.h"
10 #include "librbd/image/SetFlagsRequest.h"
11 #include "librbd/io/AioCompletion.h"
12 #include "librbd/mirror/EnableRequest.h"
13 #include "librbd/journal/CreateRequest.h"
14 #include "librbd/journal/Types.h"
15 #include "librbd/object_map/CreateRequest.h"
16 #include "librbd/operation/EnableFeaturesRequest.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19
20 namespace librbd {
21
22 namespace {
23
24 struct MockOperationImageCtx : public MockImageCtx {
25   MockOperationImageCtx(librbd::ImageCtx& image_ctx)
26     : MockImageCtx(image_ctx) {
27   }
28 };
29
30 } // anonymous namespace
31
32 namespace image {
33
34 template<>
35 class SetFlagsRequest<MockOperationImageCtx> {
36 public:
37   static SetFlagsRequest *s_instance;
38   Context *on_finish = nullptr;
39
40   static SetFlagsRequest *create(MockOperationImageCtx *image_ctx, uint64_t flags,
41                                  uint64_t mask, Context *on_finish) {
42     assert(s_instance != nullptr);
43     s_instance->on_finish = on_finish;
44     return s_instance;
45   }
46
47   SetFlagsRequest() {
48     s_instance = this;
49   }
50
51   MOCK_METHOD0(send, void());
52 };
53
54 SetFlagsRequest<MockOperationImageCtx> *SetFlagsRequest<MockOperationImageCtx>::s_instance;
55
56 } // namespace image
57
58 namespace journal {
59
60 template<>
61 class CreateRequest<MockOperationImageCtx> {
62 public:
63   static CreateRequest *s_instance;
64   Context *on_finish = nullptr;
65
66   static CreateRequest *create(IoCtx &ioctx, const std::string &imageid,
67                                uint8_t order, uint8_t splay_width,
68                                const std::string &object_pool,
69                                uint64_t tag_class, TagData &tag_data,
70                                const std::string &client_id,
71                                MockContextWQ *op_work_queue,
72                                Context *on_finish) {
73     assert(s_instance != nullptr);
74     s_instance->on_finish = on_finish;
75     return s_instance;
76   }
77
78   CreateRequest() {
79     s_instance = this;
80   }
81
82   MOCK_METHOD0(send, void());
83 };
84
85 CreateRequest<MockOperationImageCtx> *CreateRequest<MockOperationImageCtx>::s_instance = nullptr;
86
87 } // namespace journal
88
89 namespace mirror {
90
91 template<>
92 class EnableRequest<MockOperationImageCtx> {
93 public:
94   static EnableRequest *s_instance;
95   Context *on_finish = nullptr;
96
97   static EnableRequest *create(MockOperationImageCtx *image_ctx, Context *on_finish) {
98     assert(s_instance != nullptr);
99     s_instance->on_finish = on_finish;
100     return s_instance;
101   }
102
103   EnableRequest() {
104     s_instance = this;
105   }
106
107   MOCK_METHOD0(send, void());
108 };
109
110 EnableRequest<MockOperationImageCtx> *EnableRequest<MockOperationImageCtx>::s_instance = nullptr;
111
112 } // namespace mirror
113
114 namespace object_map {
115
116 template<>
117 class CreateRequest<MockOperationImageCtx> {
118 public:
119   static CreateRequest *s_instance;
120   Context *on_finish = nullptr;
121
122   static CreateRequest *create(MockOperationImageCtx *image_ctx, Context *on_finish) {
123     assert(s_instance != nullptr);
124     s_instance->on_finish = on_finish;
125     return s_instance;
126   }
127
128   CreateRequest() {
129     s_instance = this;
130   }
131
132   MOCK_METHOD0(send, void());
133 };
134
135 CreateRequest<MockOperationImageCtx> *CreateRequest<MockOperationImageCtx>::s_instance = nullptr;
136
137 } // namespace object_map
138
139 template <>
140 struct AsyncRequest<MockOperationImageCtx> : public AsyncRequest<MockImageCtx> {
141   MockOperationImageCtx &m_image_ctx;
142
143   AsyncRequest(MockOperationImageCtx &image_ctx, Context *on_finish)
144     : AsyncRequest<MockImageCtx>(image_ctx, on_finish), m_image_ctx(image_ctx) {
145   }
146 };
147
148 } // namespace librbd
149
150 // template definitions
151 #include "librbd/AsyncRequest.cc"
152 #include "librbd/AsyncObjectThrottle.cc"
153 #include "librbd/operation/Request.cc"
154 #include "librbd/operation/EnableFeaturesRequest.cc"
155
156 namespace librbd {
157 namespace operation {
158
159 using ::testing::Invoke;
160 using ::testing::Return;
161 using ::testing::WithArg;
162 using ::testing::_;
163
164 class TestMockOperationEnableFeaturesRequest : public TestMockFixture {
165 public:
166   typedef librbd::image::SetFlagsRequest<MockOperationImageCtx> MockSetFlagsRequest;
167   typedef librbd::journal::CreateRequest<MockOperationImageCtx> MockCreateJournalRequest;
168   typedef librbd::mirror::EnableRequest<MockOperationImageCtx> MockEnableMirrorRequest;
169   typedef librbd::object_map::CreateRequest<MockOperationImageCtx> MockCreateObjectMapRequest;
170   typedef EnableFeaturesRequest<MockOperationImageCtx> MockEnableFeaturesRequest;
171
172   class PoolMirrorModeEnabler {
173   public:
174     PoolMirrorModeEnabler(librados::IoCtx &ioctx) : m_ioctx(ioctx) {
175       EXPECT_EQ(0, librbd::cls_client::mirror_uuid_set(&m_ioctx, "test-uuid"));
176       EXPECT_EQ(0, librbd::cls_client::mirror_mode_set(
177                   &m_ioctx, cls::rbd::MIRROR_MODE_POOL));
178     }
179
180     ~PoolMirrorModeEnabler() {
181       EXPECT_EQ(0, librbd::cls_client::mirror_mode_set(
182                 &m_ioctx, cls::rbd::MIRROR_MODE_DISABLED));
183     }
184   private:
185     librados::IoCtx &m_ioctx;
186   };
187
188   void ensure_features_disabled(librbd::ImageCtx *ictx,
189                                 uint64_t features_to_disable) {
190     uint64_t features;
191
192     ASSERT_EQ(0, librbd::get_features(ictx, &features));
193     features_to_disable &= features;
194     if (!features_to_disable) {
195       return;
196     }
197     ASSERT_EQ(0, ictx->operations->update_features(features_to_disable, false));
198     ASSERT_EQ(0, librbd::get_features(ictx, &features));
199     ASSERT_EQ(0U, features & features_to_disable);
200   }
201
202   void expect_prepare_lock(MockOperationImageCtx &mock_image_ctx) {
203     EXPECT_CALL(*mock_image_ctx.state, prepare_lock(_))
204       .WillOnce(Invoke([](Context *on_ready) {
205             on_ready->complete(0);
206           }));
207     expect_op_work_queue(mock_image_ctx);
208   }
209
210   void expect_handle_prepare_lock_complete(MockOperationImageCtx &mock_image_ctx) {
211     EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
212   }
213
214   void expect_block_writes(MockOperationImageCtx &mock_image_ctx) {
215     EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
216       .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
217   }
218
219   void expect_unblock_writes(MockOperationImageCtx &mock_image_ctx) {
220     EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes()).Times(1);
221   }
222
223   void expect_verify_lock_ownership(MockOperationImageCtx &mock_image_ctx) {
224     if (mock_image_ctx.exclusive_lock != nullptr) {
225       EXPECT_CALL(*mock_image_ctx.exclusive_lock, is_lock_owner())
226         .WillRepeatedly(Return(true));
227     }
228   }
229
230   void expect_block_requests(MockOperationImageCtx &mock_image_ctx) {
231     if (mock_image_ctx.exclusive_lock != nullptr) {
232       EXPECT_CALL(*mock_image_ctx.exclusive_lock, block_requests(0)).Times(1);
233     }
234   }
235
236   void expect_unblock_requests(MockOperationImageCtx &mock_image_ctx) {
237     if (mock_image_ctx.exclusive_lock != nullptr) {
238       EXPECT_CALL(*mock_image_ctx.exclusive_lock, unblock_requests()).Times(1);
239     }
240   }
241
242   void expect_set_flags_request_send(
243     MockOperationImageCtx &mock_image_ctx,
244     MockSetFlagsRequest &mock_set_flags_request, int r) {
245     EXPECT_CALL(mock_set_flags_request, send())
246       .WillOnce(FinishRequest(&mock_set_flags_request, r,
247                               &mock_image_ctx));
248   }
249
250   void expect_create_journal_request_send(
251     MockOperationImageCtx &mock_image_ctx,
252     MockCreateJournalRequest &mock_create_journal_request, int r) {
253     EXPECT_CALL(mock_create_journal_request, send())
254       .WillOnce(FinishRequest(&mock_create_journal_request, r,
255                               &mock_image_ctx));
256   }
257
258   void expect_enable_mirror_request_send(
259     MockOperationImageCtx &mock_image_ctx,
260     MockEnableMirrorRequest &mock_enable_mirror_request, int r) {
261     EXPECT_CALL(mock_enable_mirror_request, send())
262       .WillOnce(FinishRequest(&mock_enable_mirror_request, r,
263                               &mock_image_ctx));
264   }
265
266   void expect_create_object_map_request_send(
267     MockOperationImageCtx &mock_image_ctx,
268     MockCreateObjectMapRequest &mock_create_object_map_request, int r) {
269     EXPECT_CALL(mock_create_object_map_request, send())
270       .WillOnce(FinishRequest(&mock_create_object_map_request, r,
271                               &mock_image_ctx));
272   }
273
274   void expect_notify_update(MockOperationImageCtx &mock_image_ctx) {
275     EXPECT_CALL(mock_image_ctx, notify_update(_))
276       .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
277   }
278
279 };
280
281 TEST_F(TestMockOperationEnableFeaturesRequest, All) {
282   REQUIRE_FORMAT_V2();
283
284   librbd::ImageCtx *ictx;
285   ASSERT_EQ(0, open_image(m_image_name, &ictx));
286
287   uint64_t features;
288   ASSERT_EQ(0, librbd::get_features(ictx, &features));
289
290   uint64_t features_to_enable = RBD_FEATURES_MUTABLE & features;
291
292   REQUIRE(features_to_enable);
293
294   ensure_features_disabled(ictx, features_to_enable);
295
296   MockOperationImageCtx mock_image_ctx(*ictx);
297
298   MockSetFlagsRequest mock_set_flags_request;
299   MockCreateJournalRequest mock_create_journal_request;
300   MockCreateObjectMapRequest mock_create_object_map_request;
301
302   ::testing::InSequence seq;
303   expect_prepare_lock(mock_image_ctx);
304   expect_block_writes(mock_image_ctx);
305   expect_block_requests(mock_image_ctx);
306   if (features_to_enable & RBD_FEATURE_JOURNALING) {
307     expect_create_journal_request_send(mock_image_ctx,
308                                        mock_create_journal_request, 0);
309   }
310   if (features_to_enable & (RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF)) {
311     expect_set_flags_request_send(mock_image_ctx,
312                                   mock_set_flags_request, 0);
313   }
314   if (features_to_enable & RBD_FEATURE_OBJECT_MAP) {
315     expect_create_object_map_request_send(mock_image_ctx,
316                                           mock_create_object_map_request, 0);
317   }
318   expect_notify_update(mock_image_ctx);
319   expect_unblock_requests(mock_image_ctx);
320   expect_unblock_writes(mock_image_ctx);
321   expect_handle_prepare_lock_complete(mock_image_ctx);
322
323   C_SaferCond cond_ctx;
324   MockEnableFeaturesRequest *req = new MockEnableFeaturesRequest(
325     mock_image_ctx, &cond_ctx, 0, features_to_enable);
326   {
327     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
328     req->send();
329   }
330   ASSERT_EQ(0, cond_ctx.wait());
331 }
332
333 TEST_F(TestMockOperationEnableFeaturesRequest, ObjectMap) {
334   REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
335
336   librbd::ImageCtx *ictx;
337   ASSERT_EQ(0, open_image(m_image_name, &ictx));
338
339   uint64_t features;
340   ASSERT_EQ(0, librbd::get_features(ictx, &features));
341
342   ensure_features_disabled(
343     ictx, RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF);
344
345   MockOperationImageCtx mock_image_ctx(*ictx);
346   MockExclusiveLock mock_exclusive_lock;
347   MockJournal mock_journal;
348   MockObjectMap mock_object_map;
349   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
350                       mock_object_map);
351
352   expect_verify_lock_ownership(mock_image_ctx);
353
354   MockSetFlagsRequest mock_set_flags_request;
355   MockCreateObjectMapRequest mock_create_object_map_request;
356
357   ::testing::InSequence seq;
358   expect_prepare_lock(mock_image_ctx);
359   expect_block_writes(mock_image_ctx);
360   if (mock_image_ctx.journal != nullptr) {
361     expect_is_journal_replaying(*mock_image_ctx.journal);
362   }
363   expect_block_requests(mock_image_ctx);
364   expect_append_op_event(mock_image_ctx, true, 0);
365   expect_set_flags_request_send(mock_image_ctx,
366                                 mock_set_flags_request, 0);
367   expect_create_object_map_request_send(mock_image_ctx,
368                                         mock_create_object_map_request, 0);
369   expect_notify_update(mock_image_ctx);
370   expect_unblock_requests(mock_image_ctx);
371   expect_unblock_writes(mock_image_ctx);
372   expect_handle_prepare_lock_complete(mock_image_ctx);
373   expect_commit_op_event(mock_image_ctx, 0);
374
375   C_SaferCond cond_ctx;
376   MockEnableFeaturesRequest *req = new MockEnableFeaturesRequest(
377     mock_image_ctx, &cond_ctx, 0, RBD_FEATURE_OBJECT_MAP);
378   {
379     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
380     req->send();
381   }
382   ASSERT_EQ(0, cond_ctx.wait());
383 }
384
385 TEST_F(TestMockOperationEnableFeaturesRequest, ObjectMapError) {
386   REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
387
388   librbd::ImageCtx *ictx;
389   ASSERT_EQ(0, open_image(m_image_name, &ictx));
390
391   uint64_t features;
392   ASSERT_EQ(0, librbd::get_features(ictx, &features));
393
394   ensure_features_disabled(
395     ictx, RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF);
396
397   MockOperationImageCtx mock_image_ctx(*ictx);
398   MockExclusiveLock mock_exclusive_lock;
399   MockJournal mock_journal;
400   MockObjectMap mock_object_map;
401   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
402                       mock_object_map);
403
404   expect_verify_lock_ownership(mock_image_ctx);
405
406   MockSetFlagsRequest mock_set_flags_request;
407   MockCreateObjectMapRequest mock_create_object_map_request;
408
409   ::testing::InSequence seq;
410   expect_prepare_lock(mock_image_ctx);
411   expect_block_writes(mock_image_ctx);
412   if (mock_image_ctx.journal != nullptr) {
413     expect_is_journal_replaying(*mock_image_ctx.journal);
414   }
415   expect_block_requests(mock_image_ctx);
416   expect_append_op_event(mock_image_ctx, true, 0);
417   expect_set_flags_request_send(mock_image_ctx,
418                                 mock_set_flags_request, 0);
419   expect_create_object_map_request_send(
420     mock_image_ctx, mock_create_object_map_request, -EINVAL);
421   expect_unblock_requests(mock_image_ctx);
422   expect_unblock_writes(mock_image_ctx);
423   expect_handle_prepare_lock_complete(mock_image_ctx);
424   expect_commit_op_event(mock_image_ctx, -EINVAL);
425
426   C_SaferCond cond_ctx;
427   MockEnableFeaturesRequest *req = new MockEnableFeaturesRequest(
428     mock_image_ctx, &cond_ctx, 0, RBD_FEATURE_OBJECT_MAP);
429   {
430     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
431     req->send();
432   }
433   ASSERT_EQ(-EINVAL, cond_ctx.wait());
434 }
435
436 TEST_F(TestMockOperationEnableFeaturesRequest, SetFlagsError) {
437   REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
438
439   librbd::ImageCtx *ictx;
440   ASSERT_EQ(0, open_image(m_image_name, &ictx));
441
442   uint64_t features;
443   ASSERT_EQ(0, librbd::get_features(ictx, &features));
444
445   ensure_features_disabled(
446     ictx, RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF);
447
448   MockOperationImageCtx mock_image_ctx(*ictx);
449   MockExclusiveLock mock_exclusive_lock;
450   MockJournal mock_journal;
451   MockObjectMap mock_object_map;
452   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
453                       mock_object_map);
454
455   expect_verify_lock_ownership(mock_image_ctx);
456
457   MockSetFlagsRequest mock_set_flags_request;
458   MockCreateObjectMapRequest mock_create_object_map_request;
459
460   ::testing::InSequence seq;
461   expect_prepare_lock(mock_image_ctx);
462   expect_block_writes(mock_image_ctx);
463   if (mock_image_ctx.journal != nullptr) {
464     expect_is_journal_replaying(*mock_image_ctx.journal);
465   }
466   expect_block_requests(mock_image_ctx);
467   expect_append_op_event(mock_image_ctx, true, 0);
468   expect_set_flags_request_send(mock_image_ctx,
469                                 mock_set_flags_request, -EINVAL);
470   expect_unblock_requests(mock_image_ctx);
471   expect_unblock_writes(mock_image_ctx);
472   expect_handle_prepare_lock_complete(mock_image_ctx);
473   expect_commit_op_event(mock_image_ctx, -EINVAL);
474
475   C_SaferCond cond_ctx;
476   MockEnableFeaturesRequest *req = new MockEnableFeaturesRequest(
477     mock_image_ctx, &cond_ctx, 0, RBD_FEATURE_OBJECT_MAP);
478   {
479     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
480     req->send();
481   }
482   ASSERT_EQ(-EINVAL, cond_ctx.wait());
483 }
484
485 TEST_F(TestMockOperationEnableFeaturesRequest, Mirroring) {
486   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
487
488   librbd::ImageCtx *ictx;
489   ASSERT_EQ(0, open_image(m_image_name, &ictx));
490
491   uint64_t features;
492   ASSERT_EQ(0, librbd::get_features(ictx, &features));
493
494   ensure_features_disabled(ictx, RBD_FEATURE_JOURNALING);
495
496   PoolMirrorModeEnabler enabler(m_ioctx);
497
498   MockOperationImageCtx mock_image_ctx(*ictx);
499   MockExclusiveLock mock_exclusive_lock;
500   MockJournal mock_journal;
501   MockObjectMap mock_object_map;
502   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
503                       mock_object_map);
504
505   expect_verify_lock_ownership(mock_image_ctx);
506
507   MockCreateJournalRequest mock_create_journal_request;
508   MockEnableMirrorRequest mock_enable_mirror_request;
509
510   ::testing::InSequence seq;
511   expect_prepare_lock(mock_image_ctx);
512   expect_block_writes(mock_image_ctx);
513   expect_block_requests(mock_image_ctx);
514   expect_create_journal_request_send(mock_image_ctx,
515                                      mock_create_journal_request, 0);
516   expect_enable_mirror_request_send(mock_image_ctx,
517                                     mock_enable_mirror_request, 0);
518   expect_notify_update(mock_image_ctx);
519   expect_unblock_requests(mock_image_ctx);
520   expect_unblock_writes(mock_image_ctx);
521   expect_handle_prepare_lock_complete(mock_image_ctx);
522
523   C_SaferCond cond_ctx;
524   MockEnableFeaturesRequest *req = new MockEnableFeaturesRequest(
525     mock_image_ctx, &cond_ctx, 0, RBD_FEATURE_JOURNALING);
526   {
527     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
528     req->send();
529   }
530   ASSERT_EQ(0, cond_ctx.wait());
531 }
532
533 TEST_F(TestMockOperationEnableFeaturesRequest, JournalingError) {
534   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
535
536   librbd::ImageCtx *ictx;
537   ASSERT_EQ(0, open_image(m_image_name, &ictx));
538
539   uint64_t features;
540   ASSERT_EQ(0, librbd::get_features(ictx, &features));
541
542   ensure_features_disabled(ictx, RBD_FEATURE_JOURNALING);
543
544   PoolMirrorModeEnabler enabler(m_ioctx);
545
546   MockOperationImageCtx mock_image_ctx(*ictx);
547   MockExclusiveLock mock_exclusive_lock;
548   MockJournal mock_journal;
549   MockObjectMap mock_object_map;
550   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
551                       mock_object_map);
552
553   expect_verify_lock_ownership(mock_image_ctx);
554
555   MockCreateJournalRequest mock_create_journal_request;
556   MockEnableMirrorRequest mock_enable_mirror_request;
557
558   ::testing::InSequence seq;
559   expect_prepare_lock(mock_image_ctx);
560   expect_block_writes(mock_image_ctx);
561   expect_block_requests(mock_image_ctx);
562   expect_create_journal_request_send(mock_image_ctx,
563                                      mock_create_journal_request, -EINVAL);
564   expect_unblock_requests(mock_image_ctx);
565   expect_unblock_writes(mock_image_ctx);
566   expect_handle_prepare_lock_complete(mock_image_ctx);
567
568   C_SaferCond cond_ctx;
569   MockEnableFeaturesRequest *req = new MockEnableFeaturesRequest(
570     mock_image_ctx, &cond_ctx, 0, RBD_FEATURE_JOURNALING);
571   {
572     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
573     req->send();
574   }
575   ASSERT_EQ(-EINVAL, cond_ctx.wait());
576 }
577
578 TEST_F(TestMockOperationEnableFeaturesRequest, MirroringError) {
579   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
580
581   librbd::ImageCtx *ictx;
582   ASSERT_EQ(0, open_image(m_image_name, &ictx));
583
584   uint64_t features;
585   ASSERT_EQ(0, librbd::get_features(ictx, &features));
586
587   ensure_features_disabled(ictx, RBD_FEATURE_JOURNALING);
588
589   PoolMirrorModeEnabler enabler(m_ioctx);
590
591   MockOperationImageCtx mock_image_ctx(*ictx);
592   MockExclusiveLock mock_exclusive_lock;
593   MockJournal mock_journal;
594   MockObjectMap mock_object_map;
595   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
596                       mock_object_map);
597
598   expect_verify_lock_ownership(mock_image_ctx);
599
600   MockCreateJournalRequest mock_create_journal_request;
601   MockEnableMirrorRequest mock_enable_mirror_request;
602
603   ::testing::InSequence seq;
604   expect_prepare_lock(mock_image_ctx);
605   expect_block_writes(mock_image_ctx);
606   expect_block_requests(mock_image_ctx);
607   expect_create_journal_request_send(mock_image_ctx,
608                                      mock_create_journal_request, 0);
609   expect_enable_mirror_request_send(mock_image_ctx,
610                                     mock_enable_mirror_request, -EINVAL);
611   expect_notify_update(mock_image_ctx);
612   expect_unblock_requests(mock_image_ctx);
613   expect_unblock_writes(mock_image_ctx);
614   expect_handle_prepare_lock_complete(mock_image_ctx);
615
616   C_SaferCond cond_ctx;
617   MockEnableFeaturesRequest *req = new MockEnableFeaturesRequest(
618     mock_image_ctx, &cond_ctx, 0, RBD_FEATURE_JOURNALING);
619   {
620     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
621     req->send();
622   }
623   ASSERT_EQ(0, cond_ctx.wait());
624 }
625
626 } // namespace operation
627 } // namespace librbd