1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/rbd_mirror/test_mock_fixture.h"
5 #include "include/rbd/librbd.hpp"
6 #include "librbd/journal/Types.h"
7 #include "librbd/journal/TypeTraits.h"
8 #include "test/journal/mock/MockJournaler.h"
9 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
10 #include "test/librbd/mock/MockImageCtx.h"
11 #include "tools/rbd_mirror/image_sync/SyncPointPruneRequest.h"
17 struct MockTestImageCtx : public librbd::MockImageCtx {
18 MockTestImageCtx(librbd::ImageCtx &image_ctx)
19 : librbd::MockImageCtx(image_ctx) {
23 } // anonymous namespace
28 struct TypeTraits<librbd::MockTestImageCtx> {
29 typedef ::journal::MockJournaler Journaler;
32 } // namespace journal
35 // template definitions
36 #include "tools/rbd_mirror/image_sync/SyncPointPruneRequest.cc"
37 template class rbd::mirror::image_sync::SyncPointPruneRequest<librbd::MockTestImageCtx>;
41 namespace image_sync {
44 using ::testing::InSequence;
45 using ::testing::Return;
46 using ::testing::StrEq;
47 using ::testing::WithArg;
49 class TestMockImageSyncSyncPointPruneRequest : public TestMockFixture {
51 typedef SyncPointPruneRequest<librbd::MockTestImageCtx> MockSyncPointPruneRequest;
53 void SetUp() override {
54 TestMockFixture::SetUp();
57 ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size));
58 ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
61 void expect_update_client(journal::MockJournaler &mock_journaler, int r) {
62 EXPECT_CALL(mock_journaler, update_client(_, _))
63 .WillOnce(WithArg<1>(CompleteContext(r)));
66 void expect_get_snap_id(librbd::MockTestImageCtx &mock_remote_image_ctx,
67 const std::string &snap_name, uint64_t snap_id) {
68 EXPECT_CALL(mock_remote_image_ctx, get_snap_id(_, StrEq(snap_name)))
69 .WillOnce(Return(snap_id));
72 void expect_image_refresh(librbd::MockTestImageCtx &mock_remote_image_ctx, int r) {
73 EXPECT_CALL(*mock_remote_image_ctx.state, refresh(_))
74 .WillOnce(CompleteContext(r));
77 void expect_snap_remove(librbd::MockTestImageCtx &mock_remote_image_ctx,
78 const std::string &snap_name, int r) {
79 EXPECT_CALL(*mock_remote_image_ctx.operations, snap_remove(_, StrEq(snap_name), _))
80 .WillOnce(WithArg<2>(CompleteContext(r)));
83 MockSyncPointPruneRequest *create_request(librbd::MockTestImageCtx &mock_remote_image_ctx,
84 journal::MockJournaler &mock_journaler,
85 bool sync_complete, Context *ctx) {
86 return new MockSyncPointPruneRequest(&mock_remote_image_ctx, sync_complete,
87 &mock_journaler, &m_client_meta, ctx);
90 librbd::ImageCtx *m_remote_image_ctx;
91 librbd::journal::MirrorPeerClientMeta m_client_meta;
94 TEST_F(TestMockImageSyncSyncPointPruneRequest, SyncInProgressSuccess) {
95 librbd::journal::MirrorPeerClientMeta client_meta;
96 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
99 m_client_meta = client_meta;
101 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
102 journal::MockJournaler mock_journaler;
105 expect_get_snap_id(mock_remote_image_ctx, "snap1", 123);
106 expect_image_refresh(mock_remote_image_ctx, 0);
107 expect_update_client(mock_journaler, 0);
110 MockSyncPointPruneRequest *req = create_request(mock_remote_image_ctx,
111 mock_journaler, false, &ctx);
113 ASSERT_EQ(0, ctx.wait());
114 ASSERT_EQ(client_meta, m_client_meta);
117 TEST_F(TestMockImageSyncSyncPointPruneRequest, RestartedSyncInProgressSuccess) {
118 librbd::journal::MirrorPeerClientMeta client_meta;
119 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
121 "snap1", boost::none);
122 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
125 m_client_meta = client_meta;
127 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
128 journal::MockJournaler mock_journaler;
131 expect_get_snap_id(mock_remote_image_ctx, "snap1", 123);
132 expect_snap_remove(mock_remote_image_ctx, "snap2", 0);
133 expect_image_refresh(mock_remote_image_ctx, 0);
134 expect_update_client(mock_journaler, 0);
137 MockSyncPointPruneRequest *req = create_request(mock_remote_image_ctx,
138 mock_journaler, false, &ctx);
140 ASSERT_EQ(0, ctx.wait());
142 client_meta.sync_points.pop_back();
143 ASSERT_EQ(client_meta, m_client_meta);
146 TEST_F(TestMockImageSyncSyncPointPruneRequest, SyncInProgressMissingSnapSuccess) {
147 librbd::journal::MirrorPeerClientMeta client_meta;
148 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
152 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
155 m_client_meta = client_meta;
157 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
158 journal::MockJournaler mock_journaler;
161 expect_get_snap_id(mock_remote_image_ctx, "snap1", CEPH_NOSNAP);
162 expect_snap_remove(mock_remote_image_ctx, "snap2", 0);
163 expect_snap_remove(mock_remote_image_ctx, "snap1", 0);
164 expect_image_refresh(mock_remote_image_ctx, 0);
165 expect_update_client(mock_journaler, 0);
168 MockSyncPointPruneRequest *req = create_request(mock_remote_image_ctx,
169 mock_journaler, false, &ctx);
171 ASSERT_EQ(0, ctx.wait());
173 client_meta.sync_points.clear();
174 ASSERT_EQ(client_meta, m_client_meta);
177 TEST_F(TestMockImageSyncSyncPointPruneRequest, SyncInProgressUnexpectedFromSnapSuccess) {
178 librbd::journal::MirrorPeerClientMeta client_meta;
179 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
183 m_client_meta = client_meta;
185 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
186 journal::MockJournaler mock_journaler;
189 expect_get_snap_id(mock_remote_image_ctx, "snap2", 124);
190 expect_snap_remove(mock_remote_image_ctx, "snap2", 0);
191 expect_snap_remove(mock_remote_image_ctx, "snap1", 0);
192 expect_image_refresh(mock_remote_image_ctx, 0);
193 expect_update_client(mock_journaler, 0);
196 MockSyncPointPruneRequest *req = create_request(mock_remote_image_ctx,
197 mock_journaler, false, &ctx);
199 ASSERT_EQ(0, ctx.wait());
201 client_meta.sync_points.clear();
202 ASSERT_EQ(client_meta, m_client_meta);
205 TEST_F(TestMockImageSyncSyncPointPruneRequest, SyncCompleteSuccess) {
206 librbd::journal::MirrorPeerClientMeta client_meta;
207 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
210 m_client_meta = client_meta;
211 ASSERT_EQ(librbd::journal::MIRROR_PEER_STATE_SYNCING, m_client_meta.state);
213 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
214 journal::MockJournaler mock_journaler;
217 expect_snap_remove(mock_remote_image_ctx, "snap1", 0);
218 expect_image_refresh(mock_remote_image_ctx, 0);
219 expect_update_client(mock_journaler, 0);
222 MockSyncPointPruneRequest *req = create_request(mock_remote_image_ctx,
223 mock_journaler, true, &ctx);
225 ASSERT_EQ(0, ctx.wait());
226 ASSERT_TRUE(m_client_meta.sync_points.empty());
227 ASSERT_EQ(librbd::journal::MIRROR_PEER_STATE_REPLAYING, m_client_meta.state);
230 TEST_F(TestMockImageSyncSyncPointPruneRequest, RestartedSyncCompleteSuccess) {
231 librbd::journal::MirrorPeerClientMeta client_meta;
232 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
236 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
239 m_client_meta = client_meta;
241 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
242 journal::MockJournaler mock_journaler;
245 expect_image_refresh(mock_remote_image_ctx, 0);
246 expect_update_client(mock_journaler, 0);
249 MockSyncPointPruneRequest *req = create_request(mock_remote_image_ctx,
250 mock_journaler, true, &ctx);
252 ASSERT_EQ(0, ctx.wait());
253 client_meta.sync_points.pop_front();
254 ASSERT_EQ(client_meta, m_client_meta);
257 TEST_F(TestMockImageSyncSyncPointPruneRequest, RestartedCatchUpSyncCompleteSuccess) {
258 librbd::journal::MirrorPeerClientMeta client_meta;
259 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
263 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
267 m_client_meta = client_meta;
269 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
270 journal::MockJournaler mock_journaler;
273 expect_snap_remove(mock_remote_image_ctx, "snap1", 0);
274 expect_image_refresh(mock_remote_image_ctx, 0);
275 expect_update_client(mock_journaler, 0);
278 MockSyncPointPruneRequest *req = create_request(mock_remote_image_ctx,
279 mock_journaler, true, &ctx);
281 ASSERT_EQ(0, ctx.wait());
282 client_meta.sync_points.pop_front();
283 ASSERT_EQ(client_meta, m_client_meta);
286 TEST_F(TestMockImageSyncSyncPointPruneRequest, SnapshotDNE) {
287 librbd::journal::MirrorPeerClientMeta client_meta;
288 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
291 m_client_meta = client_meta;
293 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
294 journal::MockJournaler mock_journaler;
297 expect_snap_remove(mock_remote_image_ctx, "snap1", -ENOENT);
298 expect_image_refresh(mock_remote_image_ctx, 0);
299 expect_update_client(mock_journaler, 0);
302 MockSyncPointPruneRequest *req = create_request(mock_remote_image_ctx,
303 mock_journaler, true, &ctx);
305 ASSERT_EQ(0, ctx.wait());
306 ASSERT_TRUE(m_client_meta.sync_points.empty());
309 TEST_F(TestMockImageSyncSyncPointPruneRequest, ClientUpdateError) {
310 librbd::journal::MirrorPeerClientMeta client_meta;
311 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
315 client_meta.sync_points.emplace_front(cls::rbd::UserSnapshotNamespace(),
318 m_client_meta = client_meta;
320 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
321 journal::MockJournaler mock_journaler;
324 expect_image_refresh(mock_remote_image_ctx, 0);
325 expect_update_client(mock_journaler, -EINVAL);
328 MockSyncPointPruneRequest *req = create_request(mock_remote_image_ctx,
329 mock_journaler, true, &ctx);
331 ASSERT_EQ(-EINVAL, ctx.wait());
333 ASSERT_EQ(client_meta, m_client_meta);
336 } // namespace image_sync
337 } // namespace mirror