1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/librbd/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"
18 struct MockTestImageCtx
: public MockImageCtx
{
19 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
20 : librbd::MockImageCtx(image_ctx
) {
24 } // anonymous namespace
32 struct Threads
<librbd::MockTestImageCtx
> {
35 ContextWQ
*work_queue
;
37 Threads(Threads
<librbd::ImageCtx
> *threads
)
38 : timer_lock(threads
->timer_lock
), timer(threads
->timer
),
39 work_queue(threads
->work_queue
) {
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));
52 struct ServiceDaemon
<librbd::MockTestImageCtx
> {
53 MOCK_METHOD3(add_or_update_attribute
,
54 void(int64_t, const std::string
&,
55 const service_daemon::AttributeValue
&));
59 struct InstanceWatcher
<librbd::MockTestImageCtx
> {
63 struct ImageReplayer
<librbd::MockTestImageCtx
> {
64 static ImageReplayer
* s_instance
;
65 std::string global_image_id
;
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
;
79 assert(s_instance
== nullptr);
83 virtual ~ImageReplayer() {
84 assert(s_instance
== this);
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
&,
97 MOCK_METHOD3(remove_remote_image
, void(const std::string
&,
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());
107 MOCK_CONST_METHOD0(get_health_state
, image_replayer::HealthState());
110 ImageReplayer
<librbd::MockTestImageCtx
>* ImageReplayer
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
112 } // namespace mirror
115 // template definitions
116 #include "tools/rbd_mirror/InstanceReplayer.cc"
122 using ::testing::InSequence
;
123 using ::testing::Invoke
;
124 using ::testing::Return
;
125 using ::testing::ReturnRef
;
126 using ::testing::WithArg
;
128 class TestMockInstanceReplayer
: public TestMockFixture
{
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
;
137 void SetUp() override
{
138 TestMockFixture::SetUp();
140 m_mock_threads
= new MockThreads(m_threads
);
143 void TearDown() override
{
144 delete m_mock_threads
;
145 TestMockFixture::TearDown();
148 void expect_wait_for_scheduled_deletion(MockImageDeleter
& mock_image_deleter
,
149 const std::string
& global_image_id
,
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
);
158 MockThreads
*m_mock_threads
;
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());
171 std::string
global_image_id("global_image_id");
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));
178 expect_wait_for_scheduled_deletion(mock_image_deleter
, "global_image_id", 0);
182 instance_replayer
.init();
183 instance_replayer
.add_peer("remote_mirror_uuid", m_remote_io_ctx
);
187 C_SaferCond on_acquire
;
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));
195 instance_replayer
.acquire_image(&mock_instance_watcher
, global_image_id
,
196 "remote_mirror_uuid", "remote_image_id",
198 ASSERT_EQ(0, on_acquire
.wait());
202 C_SaferCond on_release
;
204 EXPECT_CALL(mock_image_replayer
,
205 remove_remote_image("remote_mirror_uuid", "remote_image_id",
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());
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());
227 instance_replayer
.shut_down();
230 } // namespace mirror