]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/rbd_mirror/test_mock_fixture.h" | |
5 | #include "librbd/journal/TypeTraits.h" | |
9f95a23c | 6 | #include "tools/rbd_mirror/BaseRequest.h" |
31f18b77 | 7 | #include "tools/rbd_mirror/InstanceWatcher.h" |
7c673cae FG |
8 | #include "tools/rbd_mirror/Threads.h" |
9 | #include "tools/rbd_mirror/image_replayer/BootstrapRequest.h" | |
7c673cae FG |
10 | #include "tools/rbd_mirror/image_replayer/OpenImageRequest.h" |
11 | #include "tools/rbd_mirror/image_replayer/OpenLocalImageRequest.h" | |
9f95a23c TL |
12 | #include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h" |
13 | #include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h" | |
14 | #include "tools/rbd_mirror/image_replayer/StateBuilder.h" | |
7c673cae FG |
15 | #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" |
16 | #include "test/librbd/mock/MockImageCtx.h" | |
9f95a23c TL |
17 | #include "test/rbd_mirror/mock/image_sync/MockSyncPointHandler.h" |
18 | #include "test/rbd_mirror/mock/MockBaseRequest.h" | |
7c673cae FG |
19 | |
20 | namespace librbd { | |
21 | ||
22 | namespace { | |
23 | ||
24 | struct MockTestImageCtx : public librbd::MockImageCtx { | |
25 | MockTestImageCtx(librbd::ImageCtx &image_ctx) | |
26 | : librbd::MockImageCtx(image_ctx) { | |
27 | } | |
28 | }; | |
29 | ||
30 | } // anonymous namespace | |
7c673cae FG |
31 | } // namespace librbd |
32 | ||
33 | namespace rbd { | |
34 | namespace mirror { | |
35 | ||
36 | class ProgressContext; | |
37 | ||
11fdf7f2 TL |
38 | template <> |
39 | struct Threads<librbd::MockTestImageCtx> { | |
9f95a23c | 40 | ceph::mutex &timer_lock; |
11fdf7f2 | 41 | SafeTimer *timer; |
f67539c2 | 42 | librbd::asio::ContextWQ *work_queue; |
11fdf7f2 TL |
43 | |
44 | Threads(Threads<librbd::ImageCtx> *threads) | |
45 | : timer_lock(threads->timer_lock), timer(threads->timer), | |
46 | work_queue(threads->work_queue) { | |
47 | } | |
48 | }; | |
49 | ||
7c673cae | 50 | template<> |
31f18b77 FG |
51 | struct ImageSync<librbd::MockTestImageCtx> { |
52 | static ImageSync* s_instance; | |
53 | Context *on_finish = nullptr; | |
54 | ||
55 | static ImageSync* create( | |
9f95a23c | 56 | Threads<librbd::MockTestImageCtx>* threads, |
31f18b77 FG |
57 | librbd::MockTestImageCtx *local_image_ctx, |
58 | librbd::MockTestImageCtx *remote_image_ctx, | |
9f95a23c TL |
59 | const std::string &local_mirror_uuid, |
60 | image_sync::SyncPointHandler* sync_point_handler, | |
31f18b77 | 61 | InstanceWatcher<librbd::MockTestImageCtx> *instance_watcher, |
9f95a23c | 62 | ProgressContext *progress_ctx, Context *on_finish) { |
11fdf7f2 | 63 | ceph_assert(s_instance != nullptr); |
31f18b77 FG |
64 | s_instance->on_finish = on_finish; |
65 | return s_instance; | |
66 | } | |
67 | ||
68 | ImageSync() { | |
11fdf7f2 | 69 | ceph_assert(s_instance == nullptr); |
31f18b77 FG |
70 | s_instance = this; |
71 | } | |
72 | ~ImageSync() { | |
73 | s_instance = nullptr; | |
74 | } | |
75 | ||
76 | MOCK_METHOD0(get, void()); | |
77 | MOCK_METHOD0(put, void()); | |
78 | MOCK_METHOD0(send, void()); | |
79 | MOCK_METHOD0(cancel, void()); | |
80 | }; | |
81 | ||
82 | ImageSync<librbd::MockTestImageCtx>* | |
83 | ImageSync<librbd::MockTestImageCtx>::s_instance = nullptr; | |
84 | ||
85 | template<> | |
86 | struct InstanceWatcher<librbd::MockTestImageCtx> { | |
7c673cae FG |
87 | }; |
88 | ||
89 | namespace image_replayer { | |
90 | ||
91 | template<> | |
9f95a23c TL |
92 | struct OpenImageRequest<librbd::MockTestImageCtx> { |
93 | static OpenImageRequest* s_instance; | |
7c673cae FG |
94 | librbd::MockTestImageCtx **image_ctx = nullptr; |
95 | Context *on_finish = nullptr; | |
96 | ||
9f95a23c TL |
97 | static OpenImageRequest* create(librados::IoCtx &io_ctx, |
98 | librbd::MockTestImageCtx **image_ctx, | |
99 | const std::string &image_id, | |
100 | bool read_only, Context *on_finish) { | |
11fdf7f2 | 101 | ceph_assert(s_instance != nullptr); |
7c673cae FG |
102 | s_instance->image_ctx = image_ctx; |
103 | s_instance->on_finish = on_finish; | |
9f95a23c | 104 | s_instance->construct(io_ctx, image_id); |
7c673cae FG |
105 | return s_instance; |
106 | } | |
107 | ||
9f95a23c | 108 | OpenImageRequest() { |
11fdf7f2 | 109 | ceph_assert(s_instance == nullptr); |
7c673cae FG |
110 | s_instance = this; |
111 | } | |
9f95a23c | 112 | ~OpenImageRequest() { |
7c673cae FG |
113 | s_instance = nullptr; |
114 | } | |
115 | ||
9f95a23c TL |
116 | MOCK_METHOD2(construct, void(librados::IoCtx &io_ctx, |
117 | const std::string &image_id)); | |
7c673cae FG |
118 | MOCK_METHOD0(send, void()); |
119 | }; | |
120 | ||
121 | template<> | |
9f95a23c TL |
122 | struct OpenLocalImageRequest<librbd::MockTestImageCtx> { |
123 | static OpenLocalImageRequest* s_instance; | |
124 | librbd::MockTestImageCtx **image_ctx = nullptr; | |
7c673cae FG |
125 | Context *on_finish = nullptr; |
126 | ||
9f95a23c TL |
127 | static OpenLocalImageRequest* create(librados::IoCtx &local_io_ctx, |
128 | librbd::MockTestImageCtx **local_image_ctx, | |
129 | const std::string &local_image_id, | |
f67539c2 | 130 | librbd::asio::ContextWQ *work_queue, |
9f95a23c | 131 | Context *on_finish) { |
11fdf7f2 | 132 | ceph_assert(s_instance != nullptr); |
9f95a23c | 133 | s_instance->image_ctx = local_image_ctx; |
7c673cae | 134 | s_instance->on_finish = on_finish; |
9f95a23c | 135 | s_instance->construct(local_io_ctx, local_image_id); |
7c673cae FG |
136 | return s_instance; |
137 | } | |
138 | ||
9f95a23c | 139 | OpenLocalImageRequest() { |
11fdf7f2 | 140 | ceph_assert(s_instance == nullptr); |
7c673cae FG |
141 | s_instance = this; |
142 | } | |
9f95a23c | 143 | ~OpenLocalImageRequest() { |
7c673cae FG |
144 | s_instance = nullptr; |
145 | } | |
146 | ||
9f95a23c TL |
147 | MOCK_METHOD2(construct, void(librados::IoCtx &io_ctx, |
148 | const std::string &image_id)); | |
7c673cae FG |
149 | MOCK_METHOD0(send, void()); |
150 | }; | |
151 | ||
152 | template<> | |
9f95a23c TL |
153 | struct PrepareLocalImageRequest<librbd::MockTestImageCtx> { |
154 | static PrepareLocalImageRequest* s_instance; | |
155 | std::string *local_image_name = nullptr; | |
156 | StateBuilder<librbd::MockTestImageCtx>** state_builder = nullptr; | |
7c673cae FG |
157 | Context *on_finish = nullptr; |
158 | ||
9f95a23c TL |
159 | static PrepareLocalImageRequest* create(librados::IoCtx &, |
160 | const std::string &global_image_id, | |
161 | std::string *local_image_name, | |
162 | StateBuilder<librbd::MockTestImageCtx>** state_builder, | |
f67539c2 | 163 | librbd::asio::ContextWQ *work_queue, |
9f95a23c | 164 | Context *on_finish) { |
11fdf7f2 | 165 | ceph_assert(s_instance != nullptr); |
9f95a23c TL |
166 | s_instance->local_image_name = local_image_name; |
167 | s_instance->state_builder = state_builder; | |
7c673cae FG |
168 | s_instance->on_finish = on_finish; |
169 | return s_instance; | |
170 | } | |
171 | ||
9f95a23c | 172 | PrepareLocalImageRequest() { |
7c673cae FG |
173 | s_instance = this; |
174 | } | |
7c673cae FG |
175 | |
176 | MOCK_METHOD0(send, void()); | |
177 | }; | |
178 | ||
179 | template<> | |
9f95a23c TL |
180 | struct PrepareRemoteImageRequest<librbd::MockTestImageCtx> { |
181 | static PrepareRemoteImageRequest* s_instance; | |
182 | StateBuilder<librbd::MockTestImageCtx>** state_builder = nullptr; | |
7c673cae FG |
183 | Context *on_finish = nullptr; |
184 | ||
9f95a23c TL |
185 | static PrepareRemoteImageRequest* create(Threads<librbd::MockTestImageCtx> *threads, |
186 | librados::IoCtx &, | |
187 | librados::IoCtx &, | |
188 | const std::string &global_image_id, | |
189 | const std::string &local_mirror_uuid, | |
190 | const RemotePoolMeta& remote_pool_meta, | |
191 | ::journal::CacheManagerHandler *cache_manager_handler, | |
192 | StateBuilder<librbd::MockTestImageCtx>** state_builder, | |
193 | Context *on_finish) { | |
11fdf7f2 | 194 | ceph_assert(s_instance != nullptr); |
9f95a23c | 195 | s_instance->state_builder = state_builder; |
7c673cae | 196 | s_instance->on_finish = on_finish; |
7c673cae FG |
197 | return s_instance; |
198 | } | |
199 | ||
9f95a23c | 200 | PrepareRemoteImageRequest() { |
7c673cae FG |
201 | s_instance = this; |
202 | } | |
7c673cae | 203 | |
7c673cae FG |
204 | MOCK_METHOD0(send, void()); |
205 | }; | |
206 | ||
207 | template<> | |
9f95a23c TL |
208 | struct StateBuilder<librbd::MockTestImageCtx> { |
209 | static StateBuilder* s_instance; | |
7c673cae | 210 | |
9f95a23c TL |
211 | image_sync::MockSyncPointHandler mock_sync_point_handler; |
212 | MockBaseRequest mock_base_request; | |
213 | ||
214 | librbd::MockTestImageCtx* local_image_ctx = nullptr; | |
215 | librbd::MockTestImageCtx* remote_image_ctx = nullptr; | |
216 | std::string local_image_id; | |
217 | std::string remote_mirror_uuid; | |
218 | std::string remote_image_id; | |
219 | ||
220 | static StateBuilder* create(const std::string&) { | |
11fdf7f2 | 221 | ceph_assert(s_instance != nullptr); |
7c673cae FG |
222 | return s_instance; |
223 | } | |
224 | ||
9f95a23c TL |
225 | image_sync::MockSyncPointHandler* create_sync_point_handler() { |
226 | return &mock_sync_point_handler; | |
7c673cae | 227 | } |
9f95a23c TL |
228 | |
229 | StateBuilder() { | |
230 | s_instance = this; | |
7c673cae FG |
231 | } |
232 | ||
9f95a23c TL |
233 | MOCK_CONST_METHOD0(is_disconnected, bool()); |
234 | MOCK_CONST_METHOD0(is_local_primary, bool()); | |
2a845540 | 235 | MOCK_CONST_METHOD0(is_remote_primary, bool()); |
9f95a23c TL |
236 | MOCK_CONST_METHOD0(is_linked, bool()); |
237 | ||
238 | MOCK_CONST_METHOD0(replay_requires_remote_image, bool()); | |
239 | MOCK_METHOD1(close_remote_image, void(Context*)); | |
240 | ||
241 | MOCK_METHOD6(create_local_image_request, | |
242 | BaseRequest*(Threads<librbd::MockTestImageCtx>*, | |
243 | librados::IoCtx&, | |
244 | const std::string&, | |
245 | PoolMetaCache*, | |
246 | ProgressContext*, | |
247 | Context*)); | |
248 | MOCK_METHOD5(create_prepare_replay_request, | |
249 | BaseRequest*(const std::string&, | |
250 | ProgressContext*, | |
251 | bool*, bool*, Context*)); | |
252 | ||
253 | void destroy_sync_point_handler() { | |
254 | } | |
255 | void destroy() { | |
256 | } | |
7c673cae FG |
257 | }; |
258 | ||
7c673cae FG |
259 | OpenImageRequest<librbd::MockTestImageCtx>* |
260 | OpenImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
261 | OpenLocalImageRequest<librbd::MockTestImageCtx>* | |
262 | OpenLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
9f95a23c TL |
263 | PrepareLocalImageRequest<librbd::MockTestImageCtx>* |
264 | PrepareLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
265 | PrepareRemoteImageRequest<librbd::MockTestImageCtx>* | |
266 | PrepareRemoteImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
267 | StateBuilder<librbd::MockTestImageCtx>* | |
268 | StateBuilder<librbd::MockTestImageCtx>::s_instance = nullptr; | |
7c673cae FG |
269 | |
270 | } // namespace image_replayer | |
271 | } // namespace mirror | |
272 | } // namespace rbd | |
273 | ||
274 | // template definitions | |
275 | #include "tools/rbd_mirror/image_replayer/BootstrapRequest.cc" | |
7c673cae FG |
276 | |
277 | namespace rbd { | |
278 | namespace mirror { | |
279 | namespace image_replayer { | |
280 | ||
281 | using ::testing::_; | |
282 | using ::testing::DoAll; | |
283 | using ::testing::InSequence; | |
284 | using ::testing::Invoke; | |
285 | using ::testing::Return; | |
286 | using ::testing::SetArgPointee; | |
287 | using ::testing::StrEq; | |
288 | using ::testing::WithArg; | |
9f95a23c | 289 | using ::testing::WithArgs; |
7c673cae FG |
290 | |
291 | MATCHER_P(IsSameIoCtx, io_ctx, "") { | |
292 | return &get_mock_io_ctx(arg) == &get_mock_io_ctx(*io_ctx); | |
293 | } | |
294 | ||
295 | class TestMockImageReplayerBootstrapRequest : public TestMockFixture { | |
296 | public: | |
11fdf7f2 | 297 | typedef Threads<librbd::MockTestImageCtx> MockThreads; |
7c673cae | 298 | typedef BootstrapRequest<librbd::MockTestImageCtx> MockBootstrapRequest; |
31f18b77 FG |
299 | typedef ImageSync<librbd::MockTestImageCtx> MockImageSync; |
300 | typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher; | |
7c673cae FG |
301 | typedef OpenImageRequest<librbd::MockTestImageCtx> MockOpenImageRequest; |
302 | typedef OpenLocalImageRequest<librbd::MockTestImageCtx> MockOpenLocalImageRequest; | |
9f95a23c TL |
303 | typedef PrepareLocalImageRequest<librbd::MockTestImageCtx> MockPrepareLocalImageRequest; |
304 | typedef PrepareRemoteImageRequest<librbd::MockTestImageCtx> MockPrepareRemoteImageRequest; | |
305 | typedef StateBuilder<librbd::MockTestImageCtx> MockStateBuilder; | |
7c673cae FG |
306 | typedef std::list<cls::journal::Tag> Tags; |
307 | ||
308 | void SetUp() override { | |
309 | TestMockFixture::SetUp(); | |
310 | ||
311 | librbd::RBD rbd; | |
312 | ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size)); | |
313 | ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx)); | |
7c673cae | 314 | |
7c673cae FG |
315 | ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); |
316 | ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx)); | |
317 | } | |
318 | ||
9f95a23c TL |
319 | void expect_send(MockPrepareLocalImageRequest &mock_request, |
320 | MockStateBuilder& mock_state_builder, | |
321 | const std::string& local_image_id, | |
322 | const std::string& local_image_name, int r) { | |
323 | EXPECT_CALL(mock_request, send()) | |
324 | .WillOnce(Invoke([&mock_request, &mock_state_builder, local_image_id, | |
325 | local_image_name, r]() { | |
326 | if (r == 0) { | |
327 | *mock_request.state_builder = &mock_state_builder; | |
328 | mock_state_builder.local_image_id = local_image_id; | |
329 | *mock_request.local_image_name = local_image_name; | |
330 | } | |
331 | mock_request.on_finish->complete(r); | |
332 | })); | |
7c673cae FG |
333 | } |
334 | ||
9f95a23c TL |
335 | void expect_send(MockPrepareRemoteImageRequest& mock_request, |
336 | MockStateBuilder& mock_state_builder, | |
337 | const std::string& remote_mirror_uuid, | |
338 | const std::string& remote_image_id, | |
339 | int r) { | |
340 | EXPECT_CALL(mock_request, send()) | |
341 | .WillOnce(Invoke([&mock_request, &mock_state_builder, remote_mirror_uuid, | |
342 | remote_image_id, r]() { | |
343 | if (r >= 0) { | |
344 | *mock_request.state_builder = &mock_state_builder; | |
345 | mock_state_builder.remote_image_id = remote_image_id; | |
346 | } | |
347 | ||
348 | mock_state_builder.remote_mirror_uuid = remote_mirror_uuid; | |
349 | mock_request.on_finish->complete(r); | |
350 | })); | |
7c673cae FG |
351 | } |
352 | ||
9f95a23c TL |
353 | void expect_is_local_primary(MockStateBuilder& mock_state_builder, |
354 | bool is_primary) { | |
355 | EXPECT_CALL(mock_state_builder, is_local_primary()) | |
356 | .WillOnce(Return(is_primary)); | |
7c673cae FG |
357 | } |
358 | ||
2a845540 TL |
359 | void expect_is_remote_primary(MockStateBuilder& mock_state_builder, |
360 | bool is_primary) { | |
361 | EXPECT_CALL(mock_state_builder, is_remote_primary()) | |
362 | .WillOnce(Return(is_primary)); | |
363 | } | |
364 | ||
365 | void expect_is_linked(MockStateBuilder& mock_state_builder, bool is_linked) { | |
366 | EXPECT_CALL(mock_state_builder, is_linked()) | |
367 | .WillOnce(Return(is_linked)); | |
368 | } | |
369 | ||
9f95a23c TL |
370 | void expect_is_disconnected(MockStateBuilder& mock_state_builder, |
371 | bool is_disconnected) { | |
372 | EXPECT_CALL(mock_state_builder, is_disconnected()) | |
373 | .WillOnce(Return(is_disconnected)); | |
d2e6a577 FG |
374 | } |
375 | ||
9f95a23c TL |
376 | void expect_replay_requires_remote_image(MockStateBuilder& mock_state_builder, |
377 | bool requires_image) { | |
378 | EXPECT_CALL(mock_state_builder, replay_requires_remote_image()) | |
379 | .WillOnce(Return(requires_image)); | |
7c673cae FG |
380 | } |
381 | ||
382 | void expect_open_image(MockOpenImageRequest &mock_open_image_request, | |
383 | librados::IoCtx &io_ctx, const std::string &image_id, | |
384 | librbd::MockTestImageCtx &mock_image_ctx, int r) { | |
9f95a23c TL |
385 | EXPECT_CALL(mock_open_image_request, |
386 | construct(IsSameIoCtx(&io_ctx), image_id)); | |
7c673cae FG |
387 | EXPECT_CALL(mock_open_image_request, send()) |
388 | .WillOnce(Invoke([this, &mock_open_image_request, &mock_image_ctx, r]() { | |
389 | *mock_open_image_request.image_ctx = &mock_image_ctx; | |
390 | m_threads->work_queue->queue(mock_open_image_request.on_finish, r); | |
391 | })); | |
392 | } | |
393 | ||
394 | void expect_open_local_image(MockOpenLocalImageRequest &mock_open_local_image_request, | |
395 | librados::IoCtx &io_ctx, const std::string &image_id, | |
396 | librbd::MockTestImageCtx *mock_image_ctx, int r) { | |
397 | EXPECT_CALL(mock_open_local_image_request, | |
398 | construct(IsSameIoCtx(&io_ctx), image_id)); | |
399 | EXPECT_CALL(mock_open_local_image_request, send()) | |
400 | .WillOnce(Invoke([this, &mock_open_local_image_request, mock_image_ctx, r]() { | |
9f95a23c TL |
401 | if (r >= 0) { |
402 | *mock_open_local_image_request.image_ctx = mock_image_ctx; | |
403 | } | |
7c673cae FG |
404 | m_threads->work_queue->queue(mock_open_local_image_request.on_finish, |
405 | r); | |
406 | })); | |
407 | } | |
408 | ||
9f95a23c TL |
409 | void expect_close_remote_image( |
410 | MockStateBuilder& mock_state_builder, int r) { | |
411 | EXPECT_CALL(mock_state_builder, close_remote_image(_)) | |
412 | .WillOnce(Invoke([&mock_state_builder, r] | |
413 | (Context* on_finish) { | |
414 | mock_state_builder.remote_image_ctx = nullptr; | |
415 | on_finish->complete(r); | |
7c673cae FG |
416 | })); |
417 | } | |
418 | ||
9f95a23c TL |
419 | void expect_create_local_image(MockStateBuilder& mock_state_builder, |
420 | const std::string& local_image_id, int r) { | |
421 | EXPECT_CALL(mock_state_builder, | |
422 | create_local_image_request(_, _, _, _, _, _)) | |
423 | .WillOnce(WithArg<5>( | |
424 | Invoke([&mock_state_builder, local_image_id, r](Context* ctx) { | |
425 | if (r >= 0) { | |
426 | mock_state_builder.local_image_id = local_image_id; | |
427 | } | |
428 | mock_state_builder.mock_base_request.on_finish = ctx; | |
429 | return &mock_state_builder.mock_base_request; | |
430 | }))); | |
431 | EXPECT_CALL(mock_state_builder.mock_base_request, send()) | |
432 | .WillOnce(Invoke([this, &mock_state_builder, r]() { | |
433 | m_threads->work_queue->queue( | |
434 | mock_state_builder.mock_base_request.on_finish, r); | |
7c673cae FG |
435 | })); |
436 | } | |
437 | ||
9f95a23c TL |
438 | void expect_prepare_replay(MockStateBuilder& mock_state_builder, |
439 | bool resync_requested, bool syncing, int r) { | |
440 | EXPECT_CALL(mock_state_builder, | |
441 | create_prepare_replay_request(_, _, _, _, _)) | |
442 | .WillOnce(WithArgs<2, 3, 4>( | |
443 | Invoke([&mock_state_builder, resync_requested, syncing, r] | |
444 | (bool* resync, bool* sync, Context* ctx) { | |
445 | if (r >= 0) { | |
446 | *resync = resync_requested; | |
447 | *sync = syncing; | |
448 | } | |
449 | mock_state_builder.mock_base_request.on_finish = ctx; | |
450 | return &mock_state_builder.mock_base_request; | |
451 | }))); | |
452 | EXPECT_CALL(mock_state_builder.mock_base_request, send()) | |
453 | .WillOnce(Invoke([this, &mock_state_builder, r]() { | |
454 | m_threads->work_queue->queue( | |
455 | mock_state_builder.mock_base_request.on_finish, r); | |
7c673cae FG |
456 | })); |
457 | } | |
458 | ||
31f18b77 FG |
459 | void expect_image_sync(MockImageSync &mock_image_sync, int r) { |
460 | EXPECT_CALL(mock_image_sync, get()); | |
461 | EXPECT_CALL(mock_image_sync, send()) | |
462 | .WillOnce(Invoke([this, &mock_image_sync, r]() { | |
463 | m_threads->work_queue->queue(mock_image_sync.on_finish, r); | |
464 | })); | |
465 | EXPECT_CALL(mock_image_sync, put()); | |
7c673cae FG |
466 | } |
467 | ||
11fdf7f2 TL |
468 | MockBootstrapRequest *create_request(MockThreads* mock_threads, |
469 | MockInstanceWatcher *mock_instance_watcher, | |
7c673cae FG |
470 | const std::string &global_image_id, |
471 | const std::string &local_mirror_uuid, | |
7c673cae | 472 | Context *on_finish) { |
9f95a23c TL |
473 | return new MockBootstrapRequest(mock_threads, |
474 | m_local_io_ctx, | |
7c673cae | 475 | m_remote_io_ctx, |
31f18b77 | 476 | mock_instance_watcher, |
7c673cae | 477 | global_image_id, |
7c673cae | 478 | local_mirror_uuid, |
9f95a23c TL |
479 | {"remote mirror uuid", |
480 | "remote mirror peer uuid"}, | |
481 | nullptr, nullptr, nullptr, | |
482 | &m_mock_state_builder, | |
483 | &m_do_resync, on_finish); | |
7c673cae FG |
484 | } |
485 | ||
486 | librbd::ImageCtx *m_remote_image_ctx; | |
487 | librbd::ImageCtx *m_local_image_ctx = nullptr; | |
7c673cae | 488 | |
9f95a23c TL |
489 | MockStateBuilder* m_mock_state_builder = nullptr; |
490 | bool m_do_resync = false; | |
491 | }; | |
7c673cae | 492 | |
9f95a23c | 493 | TEST_F(TestMockImageReplayerBootstrapRequest, Success) { |
7c673cae FG |
494 | InSequence seq; |
495 | ||
9f95a23c TL |
496 | // prepare local image |
497 | MockStateBuilder mock_state_builder; | |
498 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
499 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
500 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
501 | ||
502 | // prepare remote image | |
503 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
504 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
505 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
506 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 TL |
507 | expect_is_remote_primary(mock_state_builder, true); |
508 | ||
509 | // open the remote image | |
510 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); | |
511 | MockOpenImageRequest mock_open_image_request; | |
512 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
513 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
514 | ||
515 | // open the local image | |
516 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); | |
517 | MockOpenLocalImageRequest mock_open_local_image_request; | |
518 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
519 | mock_local_image_ctx.id, &mock_local_image_ctx, 0); | |
520 | ||
521 | // prepare replay | |
522 | expect_prepare_replay(mock_state_builder, false, false, 0); | |
523 | expect_is_disconnected(mock_state_builder, false); | |
524 | ||
525 | // close remote image | |
526 | expect_replay_requires_remote_image(mock_state_builder, false); | |
527 | expect_close_remote_image(mock_state_builder, 0); | |
528 | ||
529 | C_SaferCond ctx; | |
530 | MockThreads mock_threads(m_threads); | |
531 | MockInstanceWatcher mock_instance_watcher; | |
532 | MockBootstrapRequest *request = create_request( | |
533 | &mock_threads, &mock_instance_watcher, "global image id", | |
534 | "local mirror uuid", &ctx); | |
535 | request->send(); | |
536 | ASSERT_EQ(0, ctx.wait()); | |
537 | } | |
538 | ||
539 | TEST_F(TestMockImageReplayerBootstrapRequest, PrepareRemoteImageNotPrimaryLocalDNE) { | |
540 | InSequence seq; | |
541 | ||
542 | // prepare local image | |
543 | MockStateBuilder mock_state_builder; | |
544 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
545 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
546 | m_local_image_ctx->id, m_local_image_ctx->name, -ENOENT); | |
547 | ||
548 | // prepare remote image | |
549 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
550 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
551 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
552 | expect_is_local_primary(mock_state_builder, false); | |
553 | expect_is_remote_primary(mock_state_builder, false); | |
554 | ||
555 | C_SaferCond ctx; | |
556 | MockThreads mock_threads(m_threads); | |
557 | MockInstanceWatcher mock_instance_watcher; | |
558 | MockBootstrapRequest *request = create_request( | |
559 | &mock_threads, &mock_instance_watcher, "global image id", | |
560 | "local mirror uuid", &ctx); | |
561 | request->send(); | |
562 | ASSERT_EQ(-EREMOTEIO, ctx.wait()); | |
563 | } | |
564 | ||
565 | TEST_F(TestMockImageReplayerBootstrapRequest, PrepareRemoteImageNotPrimaryLocalUnlinked) { | |
566 | InSequence seq; | |
567 | ||
568 | // prepare local image | |
569 | MockStateBuilder mock_state_builder; | |
570 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
571 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
572 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
573 | ||
574 | // prepare remote image | |
575 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
576 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
577 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
578 | expect_is_local_primary(mock_state_builder, false); | |
579 | expect_is_remote_primary(mock_state_builder, false); | |
580 | expect_is_linked(mock_state_builder, false); | |
581 | ||
582 | C_SaferCond ctx; | |
583 | MockThreads mock_threads(m_threads); | |
584 | MockInstanceWatcher mock_instance_watcher; | |
585 | MockBootstrapRequest *request = create_request( | |
586 | &mock_threads, &mock_instance_watcher, "global image id", | |
587 | "local mirror uuid", &ctx); | |
588 | request->send(); | |
589 | ASSERT_EQ(-EREMOTEIO, ctx.wait()); | |
590 | } | |
591 | ||
592 | TEST_F(TestMockImageReplayerBootstrapRequest, PrepareRemoteImageNotPrimaryLocalLinked) { | |
593 | InSequence seq; | |
594 | ||
595 | // prepare local image | |
596 | MockStateBuilder mock_state_builder; | |
597 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
598 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
599 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
600 | ||
601 | // prepare remote image | |
602 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
603 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
604 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
605 | expect_is_local_primary(mock_state_builder, false); | |
606 | expect_is_remote_primary(mock_state_builder, false); | |
607 | expect_is_linked(mock_state_builder, true); | |
7c673cae | 608 | |
d2e6a577 | 609 | // open the remote image |
d2e6a577 FG |
610 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); |
611 | MockOpenImageRequest mock_open_image_request; | |
612 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
613 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
614 | ||
9f95a23c | 615 | // open the local image |
b32b8144 | 616 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); |
9f95a23c TL |
617 | MockOpenLocalImageRequest mock_open_local_image_request; |
618 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
619 | mock_local_image_ctx.id, &mock_local_image_ctx, 0); | |
620 | ||
621 | // prepare replay | |
622 | expect_prepare_replay(mock_state_builder, false, false, 0); | |
623 | expect_is_disconnected(mock_state_builder, false); | |
7c673cae | 624 | |
9f95a23c TL |
625 | // close remote image |
626 | expect_replay_requires_remote_image(mock_state_builder, false); | |
627 | expect_close_remote_image(mock_state_builder, 0); | |
7c673cae FG |
628 | |
629 | C_SaferCond ctx; | |
11fdf7f2 | 630 | MockThreads mock_threads(m_threads); |
31f18b77 | 631 | MockInstanceWatcher mock_instance_watcher; |
7c673cae | 632 | MockBootstrapRequest *request = create_request( |
9f95a23c TL |
633 | &mock_threads, &mock_instance_watcher, "global image id", |
634 | "local mirror uuid", &ctx); | |
7c673cae | 635 | request->send(); |
9f95a23c | 636 | ASSERT_EQ(0, ctx.wait()); |
7c673cae FG |
637 | } |
638 | ||
aee94f69 TL |
639 | TEST_F(TestMockImageReplayerBootstrapRequest, PrepareRemoteImageDNELocalLinked) { |
640 | InSequence seq; | |
641 | ||
642 | // prepare local image | |
643 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
644 | MockStateBuilder mock_state_builder; | |
645 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
646 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
647 | ||
648 | // prepare remote image | |
649 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
650 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
651 | "remote mirror uuid", m_remote_image_ctx->id, -ENOENT); | |
652 | expect_is_local_primary(mock_state_builder, false); | |
653 | expect_is_linked(mock_state_builder, true); | |
654 | ||
655 | C_SaferCond ctx; | |
656 | MockThreads mock_threads(m_threads); | |
657 | MockInstanceWatcher mock_instance_watcher; | |
658 | MockBootstrapRequest *request = create_request( | |
659 | &mock_threads, &mock_instance_watcher, "global image id", | |
660 | "local mirror uuid", &ctx); | |
661 | request->send(); | |
662 | ASSERT_EQ(-ENOLINK, ctx.wait()); | |
663 | } | |
664 | ||
665 | TEST_F(TestMockImageReplayerBootstrapRequest, PrepareRemoteImageDNELocalLinkedCanceled) { | |
666 | InSequence seq; | |
667 | ||
668 | // prepare local image | |
669 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
670 | MockStateBuilder mock_state_builder; | |
671 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
672 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
673 | ||
674 | // prepare remote image | |
675 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
676 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
677 | "remote mirror uuid", m_remote_image_ctx->id, -ENOENT); | |
678 | expect_is_local_primary(mock_state_builder, false); | |
679 | expect_is_linked(mock_state_builder, true); | |
680 | ||
681 | C_SaferCond ctx; | |
682 | MockThreads mock_threads(m_threads); | |
683 | MockInstanceWatcher mock_instance_watcher; | |
684 | MockBootstrapRequest *request = create_request( | |
685 | &mock_threads, &mock_instance_watcher, "global image id", | |
686 | "local mirror uuid", &ctx); | |
687 | request->cancel(); | |
688 | request->send(); | |
689 | ASSERT_EQ(-ENOLINK, ctx.wait()); | |
690 | } | |
691 | ||
9f95a23c | 692 | TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImageError) { |
28e407b8 AA |
693 | InSequence seq; |
694 | ||
9f95a23c TL |
695 | // prepare local image |
696 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
697 | MockStateBuilder mock_state_builder; | |
698 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
699 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
700 | ||
701 | // prepare remote image | |
702 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
703 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
704 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
705 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 706 | expect_is_remote_primary(mock_state_builder, true); |
28e407b8 AA |
707 | |
708 | // open the remote image | |
28e407b8 AA |
709 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); |
710 | MockOpenImageRequest mock_open_image_request; | |
711 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
712 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
713 | ||
28e407b8 AA |
714 | // open the local image |
715 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); | |
28e407b8 AA |
716 | MockOpenLocalImageRequest mock_open_local_image_request; |
717 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
9f95a23c TL |
718 | mock_local_image_ctx.id, &mock_local_image_ctx, |
719 | -EINVAL); | |
28e407b8 | 720 | |
9f95a23c TL |
721 | // close remote image |
722 | expect_replay_requires_remote_image(mock_state_builder, false); | |
723 | expect_close_remote_image(mock_state_builder, 0); | |
28e407b8 AA |
724 | |
725 | C_SaferCond ctx; | |
11fdf7f2 | 726 | MockThreads mock_threads(m_threads); |
28e407b8 | 727 | MockInstanceWatcher mock_instance_watcher; |
28e407b8 | 728 | MockBootstrapRequest *request = create_request( |
9f95a23c TL |
729 | &mock_threads, &mock_instance_watcher, "global image id", |
730 | "local mirror uuid", &ctx); | |
28e407b8 | 731 | request->send(); |
9f95a23c | 732 | ASSERT_EQ(-EINVAL, ctx.wait()); |
28e407b8 AA |
733 | } |
734 | ||
9f95a23c | 735 | TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImageDNE) { |
7c673cae FG |
736 | InSequence seq; |
737 | ||
9f95a23c TL |
738 | // prepare local image |
739 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
740 | MockStateBuilder mock_state_builder; | |
741 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
742 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
743 | ||
744 | // prepare remote image | |
745 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
746 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
747 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
748 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 749 | expect_is_remote_primary(mock_state_builder, true); |
7c673cae | 750 | |
d2e6a577 | 751 | // open the remote image |
d2e6a577 FG |
752 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); |
753 | MockOpenImageRequest mock_open_image_request; | |
754 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
755 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
756 | ||
7c673cae | 757 | // open the local image |
b32b8144 | 758 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); |
7c673cae FG |
759 | MockOpenLocalImageRequest mock_open_local_image_request; |
760 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
9f95a23c TL |
761 | mock_local_image_ctx.id, &mock_local_image_ctx, |
762 | -ENOENT); | |
763 | ||
764 | // create local image | |
765 | expect_create_local_image(mock_state_builder, "local image id", 0); | |
766 | ||
767 | // re-open the local image | |
768 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
769 | "local image id", &mock_local_image_ctx, 0); | |
770 | ||
771 | // prepare replay | |
772 | expect_prepare_replay(mock_state_builder, false, false, 0); | |
773 | expect_is_disconnected(mock_state_builder, false); | |
774 | ||
775 | // close remote image | |
776 | expect_replay_requires_remote_image(mock_state_builder, false); | |
777 | expect_close_remote_image(mock_state_builder, 0); | |
7c673cae FG |
778 | |
779 | C_SaferCond ctx; | |
11fdf7f2 | 780 | MockThreads mock_threads(m_threads); |
31f18b77 | 781 | MockInstanceWatcher mock_instance_watcher; |
7c673cae | 782 | MockBootstrapRequest *request = create_request( |
9f95a23c TL |
783 | &mock_threads, &mock_instance_watcher, "global image id", |
784 | "local mirror uuid", &ctx); | |
7c673cae FG |
785 | request->send(); |
786 | ASSERT_EQ(0, ctx.wait()); | |
787 | } | |
788 | ||
9f95a23c | 789 | TEST_F(TestMockImageReplayerBootstrapRequest, OpenLocalImagePrimary) { |
7c673cae FG |
790 | InSequence seq; |
791 | ||
9f95a23c TL |
792 | // prepare local image |
793 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
794 | MockStateBuilder mock_state_builder; | |
795 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
796 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
797 | ||
798 | // prepare remote image | |
799 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
800 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
801 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
802 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 803 | expect_is_remote_primary(mock_state_builder, true); |
7c673cae | 804 | |
d2e6a577 | 805 | // open the remote image |
d2e6a577 FG |
806 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); |
807 | MockOpenImageRequest mock_open_image_request; | |
808 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
809 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
810 | ||
7c673cae | 811 | // open the local image |
b32b8144 | 812 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); |
7c673cae FG |
813 | MockOpenLocalImageRequest mock_open_local_image_request; |
814 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
9f95a23c TL |
815 | mock_local_image_ctx.id, &mock_local_image_ctx, |
816 | -EREMOTEIO); | |
817 | ||
818 | // close remote image | |
819 | expect_replay_requires_remote_image(mock_state_builder, false); | |
820 | expect_close_remote_image(mock_state_builder, 0); | |
7c673cae FG |
821 | |
822 | C_SaferCond ctx; | |
11fdf7f2 | 823 | MockThreads mock_threads(m_threads); |
31f18b77 | 824 | MockInstanceWatcher mock_instance_watcher; |
7c673cae | 825 | MockBootstrapRequest *request = create_request( |
9f95a23c TL |
826 | &mock_threads, &mock_instance_watcher, "global image id", |
827 | "local mirror uuid", &ctx); | |
7c673cae | 828 | request->send(); |
9f95a23c | 829 | ASSERT_EQ(-EREMOTEIO, ctx.wait()); |
7c673cae FG |
830 | } |
831 | ||
9f95a23c | 832 | TEST_F(TestMockImageReplayerBootstrapRequest, CreateLocalImageError) { |
7c673cae FG |
833 | InSequence seq; |
834 | ||
9f95a23c TL |
835 | // prepare local image |
836 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
837 | MockStateBuilder mock_state_builder; | |
838 | expect_send(mock_prepare_local_image_request, mock_state_builder, "", "", | |
839 | -ENOENT); | |
840 | ||
841 | // prepare remote image | |
842 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
843 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
844 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
845 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 846 | expect_is_remote_primary(mock_state_builder, true); |
7c673cae | 847 | |
d2e6a577 | 848 | // open the remote image |
d2e6a577 FG |
849 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); |
850 | MockOpenImageRequest mock_open_image_request; | |
851 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
852 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
853 | ||
9f95a23c TL |
854 | // create local image |
855 | expect_create_local_image(mock_state_builder, "local image id", -EINVAL); | |
7c673cae | 856 | |
9f95a23c TL |
857 | // close remote image |
858 | expect_replay_requires_remote_image(mock_state_builder, false); | |
859 | expect_close_remote_image(mock_state_builder, 0); | |
7c673cae FG |
860 | |
861 | C_SaferCond ctx; | |
11fdf7f2 | 862 | MockThreads mock_threads(m_threads); |
31f18b77 | 863 | MockInstanceWatcher mock_instance_watcher; |
7c673cae | 864 | MockBootstrapRequest *request = create_request( |
9f95a23c TL |
865 | &mock_threads, &mock_instance_watcher, "global image id", |
866 | "local mirror uuid", &ctx); | |
7c673cae | 867 | request->send(); |
9f95a23c | 868 | ASSERT_EQ(-EINVAL, ctx.wait()); |
7c673cae FG |
869 | } |
870 | ||
9f95a23c | 871 | TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayError) { |
7c673cae FG |
872 | InSequence seq; |
873 | ||
9f95a23c TL |
874 | // prepare local image |
875 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
876 | MockStateBuilder mock_state_builder; | |
877 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
878 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
879 | ||
880 | // prepare remote image | |
881 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
882 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
883 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
884 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 885 | expect_is_remote_primary(mock_state_builder, true); |
7c673cae | 886 | |
d2e6a577 | 887 | // open the remote image |
d2e6a577 FG |
888 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); |
889 | MockOpenImageRequest mock_open_image_request; | |
890 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
891 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
892 | ||
7c673cae | 893 | // open the local image |
b32b8144 | 894 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); |
7c673cae FG |
895 | MockOpenLocalImageRequest mock_open_local_image_request; |
896 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
897 | mock_local_image_ctx.id, &mock_local_image_ctx, 0); | |
9f95a23c TL |
898 | |
899 | // prepare replay | |
900 | expect_prepare_replay(mock_state_builder, false, false, -EINVAL); | |
901 | ||
902 | // close remote image | |
903 | expect_replay_requires_remote_image(mock_state_builder, false); | |
904 | expect_close_remote_image(mock_state_builder, 0); | |
7c673cae FG |
905 | |
906 | C_SaferCond ctx; | |
11fdf7f2 | 907 | MockThreads mock_threads(m_threads); |
31f18b77 | 908 | MockInstanceWatcher mock_instance_watcher; |
7c673cae | 909 | MockBootstrapRequest *request = create_request( |
9f95a23c TL |
910 | &mock_threads, &mock_instance_watcher, "global image id", |
911 | "local mirror uuid", &ctx); | |
7c673cae | 912 | request->send(); |
9f95a23c | 913 | ASSERT_EQ(-EINVAL, ctx.wait()); |
7c673cae FG |
914 | } |
915 | ||
9f95a23c | 916 | TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayResyncRequested) { |
7c673cae FG |
917 | InSequence seq; |
918 | ||
9f95a23c TL |
919 | // prepare local image |
920 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
921 | MockStateBuilder mock_state_builder; | |
922 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
923 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
924 | ||
925 | // prepare remote image | |
926 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
927 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
928 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
929 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 930 | expect_is_remote_primary(mock_state_builder, true); |
7c673cae | 931 | |
d2e6a577 | 932 | // open the remote image |
d2e6a577 FG |
933 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); |
934 | MockOpenImageRequest mock_open_image_request; | |
935 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
936 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
937 | ||
7c673cae | 938 | // open the local image |
b32b8144 | 939 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); |
7c673cae FG |
940 | MockOpenLocalImageRequest mock_open_local_image_request; |
941 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
942 | mock_local_image_ctx.id, &mock_local_image_ctx, 0); | |
943 | ||
9f95a23c TL |
944 | // prepare replay |
945 | expect_prepare_replay(mock_state_builder, true, false, 0); | |
7c673cae | 946 | |
9f95a23c TL |
947 | // close remote image |
948 | expect_replay_requires_remote_image(mock_state_builder, false); | |
949 | expect_close_remote_image(mock_state_builder, 0); | |
7c673cae FG |
950 | |
951 | C_SaferCond ctx; | |
11fdf7f2 | 952 | MockThreads mock_threads(m_threads); |
31f18b77 | 953 | MockInstanceWatcher mock_instance_watcher; |
7c673cae | 954 | MockBootstrapRequest *request = create_request( |
9f95a23c TL |
955 | &mock_threads, &mock_instance_watcher, "global image id", |
956 | "local mirror uuid", &ctx); | |
7c673cae FG |
957 | request->send(); |
958 | ASSERT_EQ(0, ctx.wait()); | |
959 | ASSERT_TRUE(m_do_resync); | |
960 | } | |
961 | ||
9f95a23c | 962 | TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplaySyncing) { |
7c673cae FG |
963 | InSequence seq; |
964 | ||
9f95a23c TL |
965 | // prepare local image |
966 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
967 | MockStateBuilder mock_state_builder; | |
968 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
969 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
970 | ||
971 | // prepare remote image | |
972 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
973 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
974 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
975 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 976 | expect_is_remote_primary(mock_state_builder, true); |
7c673cae | 977 | |
d2e6a577 | 978 | // open the remote image |
d2e6a577 FG |
979 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); |
980 | MockOpenImageRequest mock_open_image_request; | |
981 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
982 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
983 | ||
7c673cae | 984 | // open the local image |
9f95a23c | 985 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); |
7c673cae FG |
986 | MockOpenLocalImageRequest mock_open_local_image_request; |
987 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
988 | mock_local_image_ctx.id, &mock_local_image_ctx, 0); | |
7c673cae | 989 | |
9f95a23c TL |
990 | // prepare replay |
991 | expect_prepare_replay(mock_state_builder, false, true, 0); | |
992 | expect_is_disconnected(mock_state_builder, false); | |
28e407b8 | 993 | |
9f95a23c | 994 | // image sync |
31f18b77 FG |
995 | MockImageSync mock_image_sync; |
996 | expect_image_sync(mock_image_sync, 0); | |
7c673cae | 997 | |
9f95a23c TL |
998 | // close remote image |
999 | expect_replay_requires_remote_image(mock_state_builder, false); | |
1000 | expect_close_remote_image(mock_state_builder, 0); | |
7c673cae FG |
1001 | |
1002 | C_SaferCond ctx; | |
11fdf7f2 | 1003 | MockThreads mock_threads(m_threads); |
31f18b77 | 1004 | MockInstanceWatcher mock_instance_watcher; |
7c673cae | 1005 | MockBootstrapRequest *request = create_request( |
9f95a23c TL |
1006 | &mock_threads, &mock_instance_watcher, "global image id", |
1007 | "local mirror uuid", &ctx); | |
7c673cae FG |
1008 | request->send(); |
1009 | ASSERT_EQ(0, ctx.wait()); | |
1010 | } | |
1011 | ||
9f95a23c | 1012 | TEST_F(TestMockImageReplayerBootstrapRequest, PrepareReplayDisconnected) { |
7c673cae FG |
1013 | InSequence seq; |
1014 | ||
9f95a23c TL |
1015 | // prepare local image |
1016 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
1017 | MockStateBuilder mock_state_builder; | |
1018 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
1019 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
1020 | ||
1021 | // prepare remote image | |
1022 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
1023 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
1024 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
1025 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 1026 | expect_is_remote_primary(mock_state_builder, true); |
7c673cae | 1027 | |
d2e6a577 | 1028 | // open the remote image |
d2e6a577 FG |
1029 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); |
1030 | MockOpenImageRequest mock_open_image_request; | |
1031 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
1032 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
1033 | ||
9f95a23c TL |
1034 | // open the local image |
1035 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); | |
7c673cae FG |
1036 | MockOpenLocalImageRequest mock_open_local_image_request; |
1037 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
9f95a23c | 1038 | mock_local_image_ctx.id, &mock_local_image_ctx, 0); |
7c673cae | 1039 | |
9f95a23c TL |
1040 | // prepare replay |
1041 | expect_prepare_replay(mock_state_builder, false, false, 0); | |
2a845540 | 1042 | expect_is_disconnected(mock_state_builder, true); |
d2e6a577 | 1043 | |
9f95a23c TL |
1044 | // close remote image |
1045 | expect_replay_requires_remote_image(mock_state_builder, false); | |
1046 | expect_close_remote_image(mock_state_builder, 0); | |
d2e6a577 | 1047 | |
9f95a23c TL |
1048 | C_SaferCond ctx; |
1049 | MockThreads mock_threads(m_threads); | |
1050 | MockInstanceWatcher mock_instance_watcher; | |
1051 | MockBootstrapRequest *request = create_request( | |
1052 | &mock_threads, &mock_instance_watcher, "global image id", | |
1053 | "local mirror uuid", &ctx); | |
1054 | request->send(); | |
1055 | ASSERT_EQ(0, ctx.wait()); | |
1056 | } | |
1057 | ||
1058 | TEST_F(TestMockImageReplayerBootstrapRequest, ImageSyncError) { | |
1059 | InSequence seq; | |
7c673cae | 1060 | |
9f95a23c TL |
1061 | // prepare local image |
1062 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
1063 | MockStateBuilder mock_state_builder; | |
1064 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
1065 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
d2e6a577 | 1066 | |
9f95a23c TL |
1067 | // prepare remote image |
1068 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
1069 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
1070 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
1071 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 1072 | expect_is_remote_primary(mock_state_builder, true); |
9f95a23c TL |
1073 | |
1074 | // open the remote image | |
1075 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); | |
1076 | MockOpenImageRequest mock_open_image_request; | |
1077 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
1078 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
7c673cae FG |
1079 | |
1080 | // open the local image | |
9f95a23c TL |
1081 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); |
1082 | MockOpenLocalImageRequest mock_open_local_image_request; | |
7c673cae FG |
1083 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, |
1084 | mock_local_image_ctx.id, &mock_local_image_ctx, 0); | |
7c673cae | 1085 | |
9f95a23c TL |
1086 | // prepare replay |
1087 | expect_prepare_replay(mock_state_builder, false, true, 0); | |
1088 | expect_is_disconnected(mock_state_builder, false); | |
28e407b8 | 1089 | |
9f95a23c | 1090 | // image sync |
31f18b77 | 1091 | MockImageSync mock_image_sync; |
9f95a23c | 1092 | expect_image_sync(mock_image_sync, -EINVAL); |
7c673cae | 1093 | |
9f95a23c TL |
1094 | // close remote image |
1095 | expect_replay_requires_remote_image(mock_state_builder, false); | |
1096 | expect_close_remote_image(mock_state_builder, 0); | |
7c673cae FG |
1097 | |
1098 | C_SaferCond ctx; | |
11fdf7f2 | 1099 | MockThreads mock_threads(m_threads); |
31f18b77 | 1100 | MockInstanceWatcher mock_instance_watcher; |
7c673cae | 1101 | MockBootstrapRequest *request = create_request( |
9f95a23c TL |
1102 | &mock_threads, &mock_instance_watcher, "global image id", |
1103 | "local mirror uuid", &ctx); | |
11fdf7f2 | 1104 | request->send(); |
9f95a23c | 1105 | ASSERT_EQ(-EINVAL, ctx.wait()); |
11fdf7f2 TL |
1106 | } |
1107 | ||
9f95a23c | 1108 | TEST_F(TestMockImageReplayerBootstrapRequest, ImageSyncCanceled) { |
11fdf7f2 TL |
1109 | InSequence seq; |
1110 | ||
9f95a23c TL |
1111 | // prepare local image |
1112 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
1113 | MockStateBuilder mock_state_builder; | |
1114 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
1115 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
1116 | ||
1117 | // prepare remote image | |
1118 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
1119 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
1120 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
1121 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 1122 | expect_is_remote_primary(mock_state_builder, true); |
11fdf7f2 TL |
1123 | |
1124 | // open the remote image | |
11fdf7f2 TL |
1125 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); |
1126 | MockOpenImageRequest mock_open_image_request; | |
1127 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
1128 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
1129 | ||
9f95a23c | 1130 | // open the local image |
11fdf7f2 | 1131 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); |
9f95a23c TL |
1132 | MockOpenLocalImageRequest mock_open_local_image_request; |
1133 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
1134 | mock_local_image_ctx.id, &mock_local_image_ctx, 0); | |
11fdf7f2 | 1135 | |
9f95a23c TL |
1136 | // prepare replay |
1137 | expect_prepare_replay(mock_state_builder, false, true, 0); | |
1138 | expect_is_disconnected(mock_state_builder, false); | |
11fdf7f2 | 1139 | |
9f95a23c TL |
1140 | // close remote image |
1141 | expect_replay_requires_remote_image(mock_state_builder, false); | |
1142 | expect_close_remote_image(mock_state_builder, 0); | |
11fdf7f2 | 1143 | |
9f95a23c TL |
1144 | C_SaferCond ctx; |
1145 | MockThreads mock_threads(m_threads); | |
1146 | MockInstanceWatcher mock_instance_watcher; | |
1147 | MockBootstrapRequest *request = create_request( | |
1148 | &mock_threads, &mock_instance_watcher, "global image id", | |
1149 | "local mirror uuid", &ctx); | |
1150 | request->cancel(); | |
1151 | request->send(); | |
1152 | ASSERT_EQ(-ECANCELED, ctx.wait()); | |
1153 | } | |
1154 | ||
1155 | TEST_F(TestMockImageReplayerBootstrapRequest, CloseRemoteImageError) { | |
1156 | InSequence seq; | |
1157 | ||
1158 | // prepare local image | |
1159 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
1160 | MockStateBuilder mock_state_builder; | |
1161 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
1162 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
1163 | ||
1164 | // prepare remote image | |
1165 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
1166 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
1167 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
1168 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 1169 | expect_is_remote_primary(mock_state_builder, true); |
9f95a23c TL |
1170 | |
1171 | // open the remote image | |
1172 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); | |
1173 | MockOpenImageRequest mock_open_image_request; | |
1174 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
1175 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
11fdf7f2 TL |
1176 | |
1177 | // open the local image | |
9f95a23c | 1178 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); |
11fdf7f2 TL |
1179 | MockOpenLocalImageRequest mock_open_local_image_request; |
1180 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
1181 | mock_local_image_ctx.id, &mock_local_image_ctx, 0); | |
11fdf7f2 | 1182 | |
9f95a23c TL |
1183 | // prepare replay |
1184 | expect_prepare_replay(mock_state_builder, false, false, 0); | |
1185 | expect_is_disconnected(mock_state_builder, false); | |
11fdf7f2 | 1186 | |
9f95a23c TL |
1187 | // attempt to close remote image |
1188 | expect_replay_requires_remote_image(mock_state_builder, false); | |
1189 | expect_close_remote_image(mock_state_builder, -EINVAL); | |
1190 | ||
1191 | C_SaferCond ctx; | |
1192 | MockThreads mock_threads(m_threads); | |
1193 | MockInstanceWatcher mock_instance_watcher; | |
1194 | MockBootstrapRequest *request = create_request( | |
1195 | &mock_threads, &mock_instance_watcher, "global image id", | |
1196 | "local mirror uuid", &ctx); | |
1197 | request->send(); | |
1198 | ASSERT_EQ(0, ctx.wait()); | |
1199 | } | |
1200 | ||
1201 | TEST_F(TestMockImageReplayerBootstrapRequest, ReplayRequiresRemoteImage) { | |
1202 | InSequence seq; | |
1203 | ||
1204 | // prepare local image | |
1205 | MockPrepareLocalImageRequest mock_prepare_local_image_request; | |
1206 | MockStateBuilder mock_state_builder; | |
1207 | expect_send(mock_prepare_local_image_request, mock_state_builder, | |
1208 | m_local_image_ctx->id, m_local_image_ctx->name, 0); | |
1209 | ||
1210 | // prepare remote image | |
1211 | MockPrepareRemoteImageRequest mock_prepare_remote_image_request; | |
1212 | expect_send(mock_prepare_remote_image_request, mock_state_builder, | |
1213 | "remote mirror uuid", m_remote_image_ctx->id, 0); | |
1214 | expect_is_local_primary(mock_state_builder, false); | |
2a845540 | 1215 | expect_is_remote_primary(mock_state_builder, true); |
9f95a23c TL |
1216 | |
1217 | // open the remote image | |
1218 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); | |
1219 | MockOpenImageRequest mock_open_image_request; | |
1220 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
1221 | mock_remote_image_ctx.id, mock_remote_image_ctx, 0); | |
1222 | ||
1223 | // open the local image | |
1224 | librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); | |
1225 | MockOpenLocalImageRequest mock_open_local_image_request; | |
1226 | expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, | |
1227 | mock_local_image_ctx.id, &mock_local_image_ctx, 0); | |
1228 | ||
1229 | // prepare replay | |
1230 | expect_prepare_replay(mock_state_builder, false, false, 0); | |
1231 | expect_is_disconnected(mock_state_builder, false); | |
11fdf7f2 | 1232 | |
9f95a23c TL |
1233 | // remote image is left open |
1234 | expect_replay_requires_remote_image(mock_state_builder, true); | |
11fdf7f2 TL |
1235 | |
1236 | C_SaferCond ctx; | |
1237 | MockThreads mock_threads(m_threads); | |
1238 | MockInstanceWatcher mock_instance_watcher; | |
11fdf7f2 | 1239 | MockBootstrapRequest *request = create_request( |
9f95a23c TL |
1240 | &mock_threads, &mock_instance_watcher, "global image id", |
1241 | "local mirror uuid", &ctx); | |
7c673cae FG |
1242 | request->send(); |
1243 | ASSERT_EQ(0, ctx.wait()); | |
1244 | } | |
1245 | ||
1246 | } // namespace image_replayer | |
1247 | } // namespace mirror | |
1248 | } // namespace rbd |