1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "include/stringify.h"
5 #include "test/librbd/test_mock_fixture.h"
6 #include "test/librbd/test_support.h"
7 #include "test/librbd/mock/MockImageCtx.h"
8 #include "test/librbd/mock/MockOperations.h"
9 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
10 #include "test/librados_test_stub/MockTestMemRadosClient.h"
11 #include "librbd/mirror/snapshot/CreatePrimaryRequest.h"
12 #include "librbd/mirror/snapshot/UnlinkPeerRequest.h"
13 #include "librbd/mirror/snapshot/Utils.h"
19 struct MockTestImageCtx
: public MockImageCtx
{
20 explicit MockTestImageCtx(librbd::ImageCtx
& image_ctx
) : MockImageCtx(image_ctx
) {
24 } // anonymous namespace
27 // template definitions
28 #include "librbd/mirror/snapshot/Utils.cc"
29 template bool librbd::mirror::snapshot::util::can_create_primary_snapshot(
30 librbd::MockTestImageCtx
*image_ctx
, bool demoted
, bool force
,
31 bool* requires_orphan
, uint64_t *rollback_snap_id
);
32 template bool librbd::mirror::snapshot::util::can_create_non_primary_snapshot(
33 librbd::MockTestImageCtx
*image_ctx
);
40 using ::testing::DoAll
;
41 using ::testing::InSequence
;
42 using ::testing::Invoke
;
43 using ::testing::Return
;
44 using ::testing::StrEq
;
45 using ::testing::WithArg
;
47 class TestMockMirrorSnapshotUtils
: public TestMockFixture
{
49 uint64_t m_snap_seq
= 0;
51 uint64_t snap_create(MockTestImageCtx
&mock_image_ctx
,
52 const cls::rbd::SnapshotNamespace
&ns
,
53 const std::string
& snap_name
) {
54 EXPECT_TRUE(mock_image_ctx
.snap_info
.insert(
56 SnapInfo
{snap_name
, ns
, 0, {}, 0, 0, {}}}).second
);
61 TEST_F(TestMockMirrorSnapshotUtils
, CanCreatePrimarySnapshot
) {
64 librbd::ImageCtx
*ictx
;
65 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
67 MockTestImageCtx
mock_image_ctx(*ictx
);
69 // no previous mirror snapshots found
71 uint64_t rollback_snap_id
;
72 ASSERT_TRUE(util::can_create_primary_snapshot(&mock_image_ctx
, false, false,
75 ASSERT_FALSE(requires_orphan
);
76 ASSERT_EQ(rollback_snap_id
, CEPH_NOSNAP
);
78 cls::rbd::MirrorSnapshotNamespace nns
{
79 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "mirror_uuid", 123};
81 auto copied_snap_id
= snap_create(mock_image_ctx
, nns
, "NPS1");
83 // without force, previous snapshot is non-primary
84 ASSERT_FALSE(util::can_create_primary_snapshot(&mock_image_ctx
, false, false,
87 // demoted, previous snapshot is non-primary
88 ASSERT_FALSE(util::can_create_primary_snapshot(&mock_image_ctx
, true, true,
91 // previous non-primary snapshot is copied
92 ASSERT_TRUE(util::can_create_primary_snapshot(&mock_image_ctx
, false, true,
95 ASSERT_TRUE(requires_orphan
);
96 ASSERT_EQ(rollback_snap_id
, CEPH_NOSNAP
);
99 snap_create(mock_image_ctx
, nns
, "NPS2");
101 // previous non-primary snapshot is not copied yet
102 ASSERT_FALSE(util::can_create_primary_snapshot(&mock_image_ctx
, false, true,
106 ASSERT_TRUE(util::can_create_primary_snapshot(&mock_image_ctx
, false, true,
107 nullptr, &rollback_snap_id
));
108 ASSERT_EQ(rollback_snap_id
, copied_snap_id
);
110 nns
.state
= cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED
;
111 snap_create(mock_image_ctx
, nns
, "NPS3");
113 // previous non-primary snapshot is orphan
114 ASSERT_TRUE(util::can_create_primary_snapshot(&mock_image_ctx
, false, true,
117 cls::rbd::MirrorSnapshotNamespace pns
{
118 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {"uuid"}, "", CEPH_NOSNAP
};
119 snap_create(mock_image_ctx
, pns
, "PS1");
121 // previous primary snapshot is demoted, no force
122 ASSERT_FALSE(util::can_create_primary_snapshot(&mock_image_ctx
, false, false,
125 // previous primary snapshot is demoted, force
126 ASSERT_TRUE(util::can_create_primary_snapshot(&mock_image_ctx
, false, true,
129 pns
.state
= cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
;
130 snap_create(mock_image_ctx
, pns
, "PS2");
132 // previous snapshot is not demoted primary
133 ASSERT_TRUE(util::can_create_primary_snapshot(&mock_image_ctx
, false, false,
137 TEST_F(TestMockMirrorSnapshotUtils
, CanCreateNonPrimarySnapshot
) {
140 librbd::ImageCtx
*ictx
;
141 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
143 MockTestImageCtx
mock_image_ctx(*ictx
);
145 // no previous mirror snapshots found
146 ASSERT_TRUE(util::can_create_non_primary_snapshot(&mock_image_ctx
));
148 cls::rbd::MirrorSnapshotNamespace nns
{
149 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "mirror_uuid", 123};
150 snap_create(mock_image_ctx
, nns
, "NPS1");
152 // previous non-primary snapshot is not copied yet
153 ASSERT_FALSE(util::can_create_non_primary_snapshot(&mock_image_ctx
));
156 snap_create(mock_image_ctx
, nns
, "NPS2");
158 // previous non-primary snapshot is copied
159 ASSERT_TRUE(util::can_create_non_primary_snapshot(&mock_image_ctx
));
161 cls::rbd::MirrorSnapshotNamespace pns
{
162 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"uuid"}, "", CEPH_NOSNAP
};
163 snap_create(mock_image_ctx
, pns
, "PS1");
165 // previous primary snapshot is not in demoted state
166 ASSERT_FALSE(util::can_create_non_primary_snapshot(&mock_image_ctx
));
168 pns
.state
= cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED
;
169 snap_create(mock_image_ctx
, pns
, "PS2");
171 // previous primary snapshot is in demoted state
172 ASSERT_TRUE(util::can_create_non_primary_snapshot(&mock_image_ctx
));
175 } // namespace snapshot
176 } // namespace mirror
177 } // namespace librbd