]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rbd_mirror/test_mock_InstanceReplayer.cc
6e2d58c0aa0e234e60f2dbf8afebc3a429c16744
[ceph.git] / ceph / src / test / rbd_mirror / test_mock_InstanceReplayer.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/mock/MockImageCtx.h"
5 #include "test/rbd_mirror/test_mock_fixture.h"
6 #include "tools/rbd_mirror/ImageDeleter.h"
7 #include "tools/rbd_mirror/ImageReplayer.h"
8 #include "tools/rbd_mirror/InstanceWatcher.h"
9 #include "tools/rbd_mirror/InstanceReplayer.h"
10 #include "tools/rbd_mirror/ServiceDaemon.h"
11 #include "tools/rbd_mirror/Threads.h"
12 #include "tools/rbd_mirror/image_replayer/Types.h"
13
14 namespace librbd {
15
16 namespace {
17
18 struct MockTestImageCtx : public MockImageCtx {
19 MockTestImageCtx(librbd::ImageCtx &image_ctx)
20 : librbd::MockImageCtx(image_ctx) {
21 }
22 };
23
24 } // anonymous namespace
25
26 } // namespace librbd
27
28 namespace rbd {
29 namespace mirror {
30
31 template <>
32 struct Threads<librbd::MockTestImageCtx> {
33 Mutex &timer_lock;
34 SafeTimer *timer;
35 ContextWQ *work_queue;
36
37 Threads(Threads<librbd::ImageCtx> *threads)
38 : timer_lock(threads->timer_lock), timer(threads->timer),
39 work_queue(threads->work_queue) {
40 }
41 };
42
43 template <>
44 struct ImageDeleter<librbd::MockTestImageCtx> {
45 MOCK_METHOD4(schedule_image_delete, void(RadosRef, int64_t,
46 const std::string&, bool));
47 MOCK_METHOD4(wait_for_scheduled_deletion,
48 void(int64_t, const std::string&, Context*, bool));
49 };
50
51 template<>
52 struct ServiceDaemon<librbd::MockTestImageCtx> {
53 MOCK_METHOD3(add_or_update_attribute,
54 void(int64_t, const std::string&,
55 const service_daemon::AttributeValue&));
56 };
57
58 template<>
59 struct InstanceWatcher<librbd::MockTestImageCtx> {
60 };
61
62 template<>
63 struct ImageReplayer<librbd::MockTestImageCtx> {
64 static ImageReplayer* s_instance;
65 std::string global_image_id;
66
67 static ImageReplayer *create(
68 Threads<librbd::MockTestImageCtx> *threads,
69 ImageDeleter<librbd::MockTestImageCtx>* image_deleter,
70 InstanceWatcher<librbd::MockTestImageCtx> *instance_watcher,
71 RadosRef local, const std::string &local_mirror_uuid, int64_t local_pool_id,
72 const std::string &global_image_id) {
73 assert(s_instance != nullptr);
74 s_instance->global_image_id = global_image_id;
75 return s_instance;
76 }
77
78 ImageReplayer() {
79 assert(s_instance == nullptr);
80 s_instance = this;
81 }
82
83 virtual ~ImageReplayer() {
84 assert(s_instance == this);
85 s_instance = nullptr;
86 }
87
88 MOCK_METHOD0(destroy, void());
89 MOCK_METHOD2(start, void(Context *, bool));
90 MOCK_METHOD2(stop, void(Context *, bool));
91 MOCK_METHOD0(restart, void());
92 MOCK_METHOD0(flush, void());
93 MOCK_METHOD2(print_status, void(Formatter *, stringstream *));
94 MOCK_METHOD3(add_remote_image, void(const std::string &,
95 const std::string &,
96 librados::IoCtx &));
97 MOCK_METHOD3(remove_remote_image, void(const std::string &,
98 const std::string &,
99 bool));
100 MOCK_METHOD0(remote_images_empty, bool());
101 MOCK_METHOD0(get_global_image_id, const std::string &());
102 MOCK_METHOD0(get_local_image_id, const std::string &());
103 MOCK_METHOD0(is_running, bool());
104 MOCK_METHOD0(is_stopped, bool());
105 MOCK_METHOD0(is_blacklisted, bool());
106
107 MOCK_CONST_METHOD0(get_health_state, image_replayer::HealthState());
108 };
109
110 ImageReplayer<librbd::MockTestImageCtx>* ImageReplayer<librbd::MockTestImageCtx>::s_instance = nullptr;
111
112 } // namespace mirror
113 } // namespace rbd
114
115 // template definitions
116 #include "tools/rbd_mirror/InstanceReplayer.cc"
117
118 namespace rbd {
119 namespace mirror {
120
121 using ::testing::_;
122 using ::testing::InSequence;
123 using ::testing::Invoke;
124 using ::testing::Return;
125 using ::testing::ReturnRef;
126 using ::testing::WithArg;
127
128 class TestMockInstanceReplayer : public TestMockFixture {
129 public:
130 typedef ImageDeleter<librbd::MockTestImageCtx> MockImageDeleter;
131 typedef ImageReplayer<librbd::MockTestImageCtx> MockImageReplayer;
132 typedef InstanceReplayer<librbd::MockTestImageCtx> MockInstanceReplayer;
133 typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
134 typedef ServiceDaemon<librbd::MockTestImageCtx> MockServiceDaemon;
135 typedef Threads<librbd::MockTestImageCtx> MockThreads;
136
137 void SetUp() override {
138 TestMockFixture::SetUp();
139
140 m_mock_threads = new MockThreads(m_threads);
141 }
142
143 void TearDown() override {
144 delete m_mock_threads;
145 TestMockFixture::TearDown();
146 }
147
148 void expect_wait_for_scheduled_deletion(MockImageDeleter& mock_image_deleter,
149 const std::string& global_image_id,
150 int r) {
151 EXPECT_CALL(mock_image_deleter,
152 wait_for_scheduled_deletion(_, global_image_id, _, false))
153 .WillOnce(WithArg<2>(Invoke([this, r](Context *ctx) {
154 m_threads->work_queue->queue(ctx, r);
155 })));
156 }
157
158 MockThreads *m_mock_threads;
159 };
160
161 TEST_F(TestMockInstanceReplayer, AcquireReleaseImage) {
162 MockServiceDaemon mock_service_daemon;
163 MockImageDeleter mock_image_deleter;
164 MockInstanceWatcher mock_instance_watcher;
165 MockImageReplayer mock_image_replayer;
166 MockInstanceReplayer instance_replayer(
167 m_mock_threads, &mock_service_daemon, &mock_image_deleter,
168 rbd::mirror::RadosRef(new librados::Rados(m_local_io_ctx)),
169 "local_mirror_uuid", m_local_io_ctx.get_id());
170
171 std::string global_image_id("global_image_id");
172
173 EXPECT_CALL(mock_image_replayer, get_global_image_id())
174 .WillRepeatedly(ReturnRef(global_image_id));
175 EXPECT_CALL(mock_image_replayer, is_blacklisted())
176 .WillRepeatedly(Return(false));
177
178 expect_wait_for_scheduled_deletion(mock_image_deleter, "global_image_id", 0);
179
180 InSequence seq;
181
182 instance_replayer.init();
183 instance_replayer.add_peer("remote_mirror_uuid", m_remote_io_ctx);
184
185 // Acquire
186
187 C_SaferCond on_acquire;
188
189 EXPECT_CALL(mock_image_replayer, add_remote_image("remote_mirror_uuid",
190 "remote_image_id", _));
191 EXPECT_CALL(mock_image_replayer, is_stopped())
192 .WillOnce(Return(true));
193 EXPECT_CALL(mock_image_replayer, start(nullptr, false));
194
195 instance_replayer.acquire_image(&mock_instance_watcher, global_image_id,
196 "remote_mirror_uuid", "remote_image_id",
197 &on_acquire);
198 ASSERT_EQ(0, on_acquire.wait());
199
200 // Release
201
202 C_SaferCond on_release;
203
204 EXPECT_CALL(mock_image_replayer,
205 remove_remote_image("remote_mirror_uuid", "remote_image_id",
206 false));
207 EXPECT_CALL(mock_image_replayer, remote_images_empty())
208 .WillOnce(Return(true));
209 EXPECT_CALL(mock_image_replayer, is_stopped())
210 .WillOnce(Return(false));
211 EXPECT_CALL(mock_image_replayer, is_running())
212 .WillOnce(Return(false));
213 EXPECT_CALL(mock_image_replayer, is_stopped())
214 .WillOnce(Return(false));
215 EXPECT_CALL(mock_image_replayer, is_running())
216 .WillOnce(Return(true));
217 EXPECT_CALL(mock_image_replayer, stop(_, false))
218 .WillOnce(CompleteContext(0));
219 EXPECT_CALL(mock_image_replayer, is_stopped())
220 .WillOnce(Return(true));
221 EXPECT_CALL(mock_image_replayer, destroy());
222
223 instance_replayer.release_image("global_image_id", "remote_mirror_uuid",
224 "remote_image_id", false, &on_release);
225 ASSERT_EQ(0, on_release.wait());
226
227 instance_replayer.shut_down();
228 }
229
230 } // namespace mirror
231 } // namespace rbd