]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/object_map/test_mock_SnapshotCreateRequest.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / librbd / object_map / test_mock_SnapshotCreateRequest.cc
CommitLineData
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/test_mock_fixture.h"
5#include "test/librbd/test_support.h"
6#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
7#include "common/bit_vector.hpp"
8#include "cls/rbd/cls_rbd_types.h"
9#include "librbd/internal.h"
10#include "librbd/ObjectMap.h"
11#include "librbd/object_map/SnapshotCreateRequest.h"
12#include "gmock/gmock.h"
13#include "gtest/gtest.h"
14
15namespace librbd {
16namespace object_map {
17
18using ::testing::_;
19using ::testing::DoDefault;
20using ::testing::Return;
21using ::testing::StrEq;
22
23class TestMockObjectMapSnapshotCreateRequest : public TestMockFixture {
24public:
25 void inject_snap_info(librbd::ImageCtx *ictx, uint64_t snap_id) {
9f95a23c 26 std::unique_lock image_locker{ictx->image_lock};
7c673cae
FG
27 ictx->add_snap(cls::rbd::UserSnapshotNamespace(), "snap name", snap_id,
28 ictx->size, ictx->parent_md,
29 RBD_PROTECTION_STATUS_UNPROTECTED, 0, utime_t());
30 }
31
32 void expect_read_map(librbd::ImageCtx *ictx, int r) {
33 if (r < 0) {
34 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
35 read(ObjectMap<>::object_map_name(ictx->id, CEPH_NOSNAP),
f67539c2 36 0, 0, _, _, _)).WillOnce(Return(r));
7c673cae
FG
37 } else {
38 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
39 read(ObjectMap<>::object_map_name(ictx->id, CEPH_NOSNAP),
f67539c2 40 0, 0, _, _, _)).WillOnce(DoDefault());
7c673cae
FG
41 }
42 }
43
44 void expect_write_map(librbd::ImageCtx *ictx, uint64_t snap_id, int r) {
45 if (r < 0) {
46 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
47 write_full(
48 ObjectMap<>::object_map_name(ictx->id, snap_id), _, _))
49 .WillOnce(Return(r));
50 } else {
51 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
52 write_full(
53 ObjectMap<>::object_map_name(ictx->id, snap_id), _, _))
54 .WillOnce(DoDefault());
55 }
56 }
57
58 void expect_add_snapshot(librbd::ImageCtx *ictx, int r) {
59 std::string oid(ObjectMap<>::object_map_name(ictx->id, CEPH_NOSNAP));
60 if (r < 0) {
61 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
f67539c2
TL
62 exec(oid, _, StrEq("lock"), StrEq("assert_locked"), _, _, _,
63 _))
7c673cae
FG
64 .WillOnce(Return(r));
65 } else {
66 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
f67539c2
TL
67 exec(oid, _, StrEq("lock"), StrEq("assert_locked"), _, _, _,
68 _))
7c673cae
FG
69 .WillOnce(DoDefault());
70 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
f67539c2
TL
71 exec(oid, _, StrEq("rbd"), StrEq("object_map_snap_add"), _, _,
72 _, _))
7c673cae
FG
73 .WillOnce(DoDefault());
74 }
75 }
76
77 void expect_invalidate(librbd::ImageCtx *ictx) {
78 EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
f67539c2
TL
79 exec(ictx->header_oid, _, StrEq("rbd"), StrEq("set_flags"), _,
80 _, _, _))
7c673cae
FG
81 .WillOnce(DoDefault());
82 }
83};
84
85TEST_F(TestMockObjectMapSnapshotCreateRequest, Success) {
86 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
87
88 librbd::ImageCtx *ictx;
89 ASSERT_EQ(0, open_image(m_image_name, &ictx));
90 ASSERT_EQ(0, acquire_exclusive_lock(*ictx));
91
9f95a23c 92 ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock");
7c673cae
FG
93 ceph::BitVector<2> object_map;
94
95 uint64_t snap_id = 1;
96 inject_snap_info(ictx, snap_id);
97 expect_read_map(ictx, 0);
98 expect_write_map(ictx, snap_id, 0);
99 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
100 expect_add_snapshot(ictx, 0);
101 }
102
103 C_SaferCond cond_ctx;
104 AsyncRequest<> *request = new SnapshotCreateRequest(
9f95a23c 105 *ictx, &object_map_lock, &object_map, snap_id, &cond_ctx);
7c673cae 106 {
9f95a23c 107 std::shared_lock image_locker{ictx->image_lock};
7c673cae
FG
108 request->send();
109 }
110 ASSERT_EQ(0, cond_ctx.wait());
111
112 expect_unlock_exclusive_lock(*ictx);
113}
114
115TEST_F(TestMockObjectMapSnapshotCreateRequest, ReadMapError) {
116 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
117
118 librbd::ImageCtx *ictx;
119 ASSERT_EQ(0, open_image(m_image_name, &ictx));
120 ASSERT_EQ(0, acquire_exclusive_lock(*ictx));
121
9f95a23c 122 ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock");
7c673cae
FG
123 ceph::BitVector<2> object_map;
124
125 uint64_t snap_id = 1;
126 inject_snap_info(ictx, snap_id);
127 expect_read_map(ictx, -ENOENT);
128 expect_invalidate(ictx);
129
130 C_SaferCond cond_ctx;
131 AsyncRequest<> *request = new SnapshotCreateRequest(
9f95a23c 132 *ictx, &object_map_lock, &object_map, snap_id, &cond_ctx);
7c673cae 133 {
9f95a23c 134 std::shared_lock image_locker{ictx->image_lock};
7c673cae
FG
135 request->send();
136 }
f67539c2 137 ASSERT_EQ(-ENOENT, cond_ctx.wait());
7c673cae
FG
138
139 expect_unlock_exclusive_lock(*ictx);
140}
141
142TEST_F(TestMockObjectMapSnapshotCreateRequest, WriteMapError) {
143 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
144
145 librbd::ImageCtx *ictx;
146 ASSERT_EQ(0, open_image(m_image_name, &ictx));
147 ASSERT_EQ(0, acquire_exclusive_lock(*ictx));
148
9f95a23c 149 ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock");
7c673cae
FG
150 ceph::BitVector<2> object_map;
151
152 uint64_t snap_id = 1;
153 inject_snap_info(ictx, snap_id);
154 expect_read_map(ictx, 0);
155 expect_write_map(ictx, snap_id, -EINVAL);
156 expect_invalidate(ictx);
157
158 C_SaferCond cond_ctx;
159 AsyncRequest<> *request = new SnapshotCreateRequest(
9f95a23c 160 *ictx, &object_map_lock, &object_map, snap_id, &cond_ctx);
7c673cae 161 {
9f95a23c 162 std::shared_lock image_locker{ictx->image_lock};
7c673cae
FG
163 request->send();
164 }
f67539c2 165 ASSERT_EQ(-ENOENT, cond_ctx.wait());
7c673cae
FG
166
167 expect_unlock_exclusive_lock(*ictx);
168}
169
170TEST_F(TestMockObjectMapSnapshotCreateRequest, AddSnapshotError) {
171 REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF);
172
173 librbd::ImageCtx *ictx;
174 ASSERT_EQ(0, open_image(m_image_name, &ictx));
175 ASSERT_EQ(0, acquire_exclusive_lock(*ictx));
176
9f95a23c 177 ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock");
7c673cae
FG
178 ceph::BitVector<2> object_map;
179
180 uint64_t snap_id = 1;
181 inject_snap_info(ictx, snap_id);
182 expect_read_map(ictx, 0);
183 expect_write_map(ictx, snap_id, 0);
184 expect_add_snapshot(ictx, -EINVAL);
185 expect_invalidate(ictx);
186
187 C_SaferCond cond_ctx;
188 AsyncRequest<> *request = new SnapshotCreateRequest(
9f95a23c 189 *ictx, &object_map_lock, &object_map, snap_id, &cond_ctx);
7c673cae 190 {
9f95a23c 191 std::shared_lock image_locker{ictx->image_lock};
7c673cae
FG
192 request->send();
193 }
f67539c2 194 ASSERT_EQ(-ENOENT, cond_ctx.wait());
7c673cae
FG
195
196 expect_unlock_exclusive_lock(*ictx);
197}
198
199TEST_F(TestMockObjectMapSnapshotCreateRequest, FlagCleanObjects) {
200 REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF);
201
202 librbd::ImageCtx *ictx;
203 ASSERT_EQ(0, open_image(m_image_name, &ictx));
204 ASSERT_EQ(0, acquire_exclusive_lock(*ictx));
205
9f95a23c 206 ceph::shared_mutex object_map_lock = ceph::make_shared_mutex("lock");
7c673cae
FG
207 ceph::BitVector<2> object_map;
208 object_map.resize(1024);
209 for (uint64_t i = 0; i < object_map.size(); ++i) {
210 object_map[i] = i % 2 == 0 ? OBJECT_EXISTS : OBJECT_NONEXISTENT;
211 }
212
213 uint64_t snap_id = 1;
214 inject_snap_info(ictx, snap_id);
215
216 C_SaferCond cond_ctx;
217 AsyncRequest<> *request = new SnapshotCreateRequest(
9f95a23c 218 *ictx, &object_map_lock, &object_map, snap_id, &cond_ctx);
7c673cae 219 {
9f95a23c 220 std::shared_lock image_locker{ictx->image_lock};
7c673cae
FG
221 request->send();
222 }
223 ASSERT_EQ(0, cond_ctx.wait());
224
225 for (uint64_t i = 0; i < object_map.size(); ++i) {
226 ASSERT_EQ(i % 2 == 0 ? OBJECT_EXISTS_CLEAN : OBJECT_NONEXISTENT,
227 object_map[i]);
228 }
229}
230
231} // namespace object_map
232} // namespace librbd