]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rbd_mirror/test_mock_ImageSyncThrottler.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / test / rbd_mirror / test_mock_ImageSyncThrottler.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2016 SUSE LINUX GmbH
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include "test/rbd_mirror/test_mock_fixture.h"
16 #include "librbd/journal/TypeTraits.h"
17 #include "test/journal/mock/MockJournaler.h"
18 #include "test/librbd/mock/MockImageCtx.h"
19 #include "librbd/ImageState.h"
20 #include "tools/rbd_mirror/Threads.h"
21 #include "tools/rbd_mirror/ImageSync.h"
22
23 namespace librbd {
24
25 namespace {
26
27 struct MockTestImageCtx : public librbd::MockImageCtx {
28 MockTestImageCtx(librbd::ImageCtx &image_ctx)
29 : librbd::MockImageCtx(image_ctx) {
30 }
31 };
32
33 } // anonymous namespace
34
35 namespace journal {
36
37 template <>
38 struct TypeTraits<librbd::MockTestImageCtx> {
39 typedef ::journal::MockJournaler Journaler;
40 };
41
42 } // namespace journal
43 } // namespace librbd
44
45 namespace rbd {
46 namespace mirror {
47
48 using ::testing::Invoke;
49
50 typedef ImageSync<librbd::MockTestImageCtx> MockImageSync;
51
52 template<>
53 class ImageSync<librbd::MockTestImageCtx> {
54 public:
55 static std::vector<MockImageSync *> instances;
56
57 Context *on_finish;
58 bool syncing = false;
59
60 static ImageSync* create(librbd::MockTestImageCtx *local_image_ctx,
61 librbd::MockTestImageCtx *remote_image_ctx,
62 SafeTimer *timer, Mutex *timer_lock,
63 const std::string &mirror_uuid,
64 journal::MockJournaler *journaler,
65 librbd::journal::MirrorPeerClientMeta *client_meta,
66 ContextWQ *work_queue, Context *on_finish,
67 ProgressContext *progress_ctx = nullptr) {
68 ImageSync *sync = new ImageSync();
69 sync->on_finish = on_finish;
70
71 EXPECT_CALL(*sync, send())
72 .WillRepeatedly(Invoke([sync]() {
73 sync->syncing = true;
74 }));
75
76 return sync;
77 }
78
79 void finish(int r) {
80 on_finish->complete(r);
81 put();
82 }
83
84 void get() {
85 instances.push_back(this);
86 }
87
88 void put() { delete this; }
89
90 MOCK_METHOD0(cancel, void());
91 MOCK_METHOD0(send, void());
92
93 };
94
95
96 std::vector<MockImageSync *> MockImageSync::instances;
97
98 } // namespace mirror
99 } // namespace rbd
100
101
102 // template definitions
103 #include "tools/rbd_mirror/ImageSyncThrottler.cc"
104
105 namespace rbd {
106 namespace mirror {
107
108 class TestMockImageSyncThrottler : public TestMockFixture {
109 public:
110 typedef ImageSyncThrottler<librbd::MockTestImageCtx> MockImageSyncThrottler;
111
112 void SetUp() override {
113 TestMockFixture::SetUp();
114
115 librbd::RBD rbd;
116 ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size));
117 ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
118
119 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
120 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
121
122 mock_sync_throttler = new MockImageSyncThrottler();
123
124 m_mock_local_image_ctx = new librbd::MockTestImageCtx(*m_local_image_ctx);
125 m_mock_remote_image_ctx = new librbd::MockTestImageCtx(*m_remote_image_ctx);
126 m_mock_journaler = new journal::MockJournaler();
127 }
128
129 void TearDown() override {
130 MockImageSync::instances.clear();
131 delete mock_sync_throttler;
132 delete m_mock_local_image_ctx;
133 delete m_mock_remote_image_ctx;
134 delete m_mock_journaler;
135 TestMockFixture::TearDown();
136 }
137
138 void start_sync(const std::string& image_id, Context *ctx) {
139 m_mock_local_image_ctx->id = image_id;
140 mock_sync_throttler->start_sync(m_mock_local_image_ctx,
141 m_mock_remote_image_ctx,
142 m_threads->timer,
143 &m_threads->timer_lock,
144 "mirror_uuid",
145 m_mock_journaler,
146 &m_client_meta,
147 m_threads->work_queue,
148 ctx);
149 }
150
151 void cancel(const std::string& mirror_uuid, MockImageSync *sync,
152 bool running=true) {
153 if (running) {
154 EXPECT_CALL(*sync, cancel())
155 .WillOnce(Invoke([sync]() {
156 sync->finish(-ECANCELED);
157 }));
158 } else {
159 EXPECT_CALL(*sync, cancel()).Times(0);
160 }
161 mock_sync_throttler->cancel_sync(m_local_io_ctx, mirror_uuid);
162 }
163
164 librbd::ImageCtx *m_remote_image_ctx;
165 librbd::ImageCtx *m_local_image_ctx;
166 librbd::MockTestImageCtx *m_mock_local_image_ctx;
167 librbd::MockTestImageCtx *m_mock_remote_image_ctx;
168 journal::MockJournaler *m_mock_journaler;
169 librbd::journal::MirrorPeerClientMeta m_client_meta;
170 MockImageSyncThrottler *mock_sync_throttler;
171 };
172
173 TEST_F(TestMockImageSyncThrottler, Single_Sync) {
174 C_SaferCond ctx;
175 start_sync("image_id", &ctx);
176
177 ASSERT_EQ(1u, MockImageSync::instances.size());
178 MockImageSync *sync = MockImageSync::instances[0];
179 ASSERT_EQ(true, sync->syncing);
180 sync->finish(0);
181 ASSERT_EQ(0, ctx.wait());
182 }
183
184 TEST_F(TestMockImageSyncThrottler, Multiple_Syncs) {
185 mock_sync_throttler->set_max_concurrent_syncs(2);
186
187 C_SaferCond ctx1;
188 start_sync("image_id_1", &ctx1);
189 C_SaferCond ctx2;
190 start_sync("image_id_2", &ctx2);
191 C_SaferCond ctx3;
192 start_sync("image_id_3", &ctx3);
193 C_SaferCond ctx4;
194 start_sync("image_id_4", &ctx4);
195
196 ASSERT_EQ(4u, MockImageSync::instances.size());
197
198 MockImageSync *sync1 = MockImageSync::instances[0];
199 ASSERT_TRUE(sync1->syncing);
200
201 MockImageSync *sync2 = MockImageSync::instances[1];
202 ASSERT_TRUE(sync2->syncing);
203
204 MockImageSync *sync3 = MockImageSync::instances[2];
205 ASSERT_FALSE(sync3->syncing);
206
207 MockImageSync *sync4 = MockImageSync::instances[3];
208 ASSERT_FALSE(sync4->syncing);
209
210 sync1->finish(0);
211 ASSERT_EQ(0, ctx1.wait());
212
213 ASSERT_TRUE(sync3->syncing);
214 sync3->finish(-EINVAL);
215 ASSERT_EQ(-EINVAL, ctx3.wait());
216
217 ASSERT_TRUE(sync4->syncing);
218
219 sync2->finish(0);
220 ASSERT_EQ(0, ctx2.wait());
221
222 sync4->finish(0);
223 ASSERT_EQ(0, ctx4.wait());
224 }
225
226 TEST_F(TestMockImageSyncThrottler, Cancel_Running_Sync) {
227 C_SaferCond ctx1;
228 start_sync("image_id_1", &ctx1);
229 C_SaferCond ctx2;
230 start_sync("image_id_2", &ctx2);
231
232 ASSERT_EQ(2u, MockImageSync::instances.size());
233
234 MockImageSync *sync1 = MockImageSync::instances[0];
235 ASSERT_TRUE(sync1->syncing);
236
237 MockImageSync *sync2 = MockImageSync::instances[1];
238 ASSERT_TRUE(sync2->syncing);
239
240 cancel("image_id_2", sync2);
241 ASSERT_EQ(-ECANCELED, ctx2.wait());
242
243 sync1->finish(0);
244 ASSERT_EQ(0, ctx1.wait());
245 }
246
247 TEST_F(TestMockImageSyncThrottler, Cancel_Waiting_Sync) {
248 mock_sync_throttler->set_max_concurrent_syncs(1);
249
250 C_SaferCond ctx1;
251 start_sync("image_id_1", &ctx1);
252 C_SaferCond ctx2;
253 start_sync("image_id_2", &ctx2);
254
255 ASSERT_EQ(2u, MockImageSync::instances.size());
256
257 MockImageSync *sync1 = MockImageSync::instances[0];
258 ASSERT_TRUE(sync1->syncing);
259
260 MockImageSync *sync2 = MockImageSync::instances[1];
261 ASSERT_FALSE(sync2->syncing);
262
263 cancel("image_id_2", sync2, false);
264 ASSERT_EQ(-ECANCELED, ctx2.wait());
265
266 sync1->finish(0);
267 ASSERT_EQ(0, ctx1.wait());
268 }
269
270 TEST_F(TestMockImageSyncThrottler, Cancel_Running_Sync_Start_Waiting) {
271 mock_sync_throttler->set_max_concurrent_syncs(1);
272
273 C_SaferCond ctx1;
274 start_sync("image_id_1", &ctx1);
275 C_SaferCond ctx2;
276 start_sync("image_id_2", &ctx2);
277
278 ASSERT_EQ(2u, MockImageSync::instances.size());
279
280 MockImageSync *sync1 = MockImageSync::instances[0];
281 ASSERT_TRUE(sync1->syncing);
282
283 MockImageSync *sync2 = MockImageSync::instances[1];
284 ASSERT_FALSE(sync2->syncing);
285
286 cancel("image_id_1", sync1);
287 ASSERT_EQ(-ECANCELED, ctx1.wait());
288
289 ASSERT_TRUE(sync2->syncing);
290 sync2->finish(0);
291 ASSERT_EQ(0, ctx2.wait());
292 }
293
294 TEST_F(TestMockImageSyncThrottler, Increase_Max_Concurrent_Syncs) {
295 mock_sync_throttler->set_max_concurrent_syncs(2);
296
297 C_SaferCond ctx1;
298 start_sync("image_id_1", &ctx1);
299 C_SaferCond ctx2;
300 start_sync("image_id_2", &ctx2);
301 C_SaferCond ctx3;
302 start_sync("image_id_3", &ctx3);
303 C_SaferCond ctx4;
304 start_sync("image_id_4", &ctx4);
305 C_SaferCond ctx5;
306 start_sync("image_id_5", &ctx5);
307
308 ASSERT_EQ(5u, MockImageSync::instances.size());
309
310 MockImageSync *sync1 = MockImageSync::instances[0];
311 ASSERT_TRUE(sync1->syncing);
312
313 MockImageSync *sync2 = MockImageSync::instances[1];
314 ASSERT_TRUE(sync2->syncing);
315
316 MockImageSync *sync3 = MockImageSync::instances[2];
317 ASSERT_FALSE(sync3->syncing);
318
319 MockImageSync *sync4 = MockImageSync::instances[3];
320 ASSERT_FALSE(sync4->syncing);
321
322 MockImageSync *sync5 = MockImageSync::instances[4];
323 ASSERT_FALSE(sync5->syncing);
324
325 mock_sync_throttler->set_max_concurrent_syncs(4);
326
327 ASSERT_TRUE(sync3->syncing);
328 ASSERT_TRUE(sync4->syncing);
329 ASSERT_FALSE(sync5->syncing);
330
331 sync1->finish(0);
332 ASSERT_EQ(0, ctx1.wait());
333
334 ASSERT_TRUE(sync5->syncing);
335 sync5->finish(-EINVAL);
336 ASSERT_EQ(-EINVAL, ctx5.wait());
337
338 sync2->finish(0);
339 ASSERT_EQ(0, ctx2.wait());
340
341 sync3->finish(0);
342 ASSERT_EQ(0, ctx3.wait());
343
344 sync4->finish(0);
345 ASSERT_EQ(0, ctx4.wait());
346 }
347
348 TEST_F(TestMockImageSyncThrottler, Decrease_Max_Concurrent_Syncs) {
349 mock_sync_throttler->set_max_concurrent_syncs(4);
350
351 C_SaferCond ctx1;
352 start_sync("image_id_1", &ctx1);
353 C_SaferCond ctx2;
354 start_sync("image_id_2", &ctx2);
355 C_SaferCond ctx3;
356 start_sync("image_id_3", &ctx3);
357 C_SaferCond ctx4;
358 start_sync("image_id_4", &ctx4);
359 C_SaferCond ctx5;
360 start_sync("image_id_5", &ctx5);
361
362 ASSERT_EQ(5u, MockImageSync::instances.size());
363
364 MockImageSync *sync1 = MockImageSync::instances[0];
365 ASSERT_TRUE(sync1->syncing);
366
367 MockImageSync *sync2 = MockImageSync::instances[1];
368 ASSERT_TRUE(sync2->syncing);
369
370 MockImageSync *sync3 = MockImageSync::instances[2];
371 ASSERT_TRUE(sync3->syncing);
372
373 MockImageSync *sync4 = MockImageSync::instances[3];
374 ASSERT_TRUE(sync4->syncing);
375
376 MockImageSync *sync5 = MockImageSync::instances[4];
377 ASSERT_FALSE(sync5->syncing);
378
379 mock_sync_throttler->set_max_concurrent_syncs(2);
380
381 ASSERT_FALSE(sync5->syncing);
382
383 sync1->finish(0);
384 ASSERT_EQ(0, ctx1.wait());
385
386 ASSERT_FALSE(sync5->syncing);
387
388 sync2->finish(0);
389 ASSERT_EQ(0, ctx2.wait());
390
391 ASSERT_FALSE(sync5->syncing);
392
393 sync3->finish(0);
394 ASSERT_EQ(0, ctx3.wait());
395
396 ASSERT_TRUE(sync5->syncing);
397
398 sync4->finish(0);
399 ASSERT_EQ(0, ctx4.wait());
400
401 sync5->finish(0);
402 ASSERT_EQ(0, ctx5.wait());
403 }
404
405
406 } // namespace mirror
407 } // namespace rbd
408