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