]>
Commit | Line | Data |
---|---|---|
adb31ebb TL |
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 "include/rbd_types.h" | |
8 | #include "common/ceph_mutex.h" | |
9 | #include "librbd/object_map/DiffRequest.h" | |
10 | #include "gtest/gtest.h" | |
11 | #include "gmock/gmock.h" | |
12 | ||
13 | namespace librbd { | |
14 | namespace { | |
15 | ||
16 | struct MockTestImageCtx : public MockImageCtx { | |
17 | MockTestImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) { | |
18 | } | |
19 | }; | |
20 | ||
21 | } // anonymous namespace | |
22 | } // namespace librbd | |
23 | ||
24 | #include "librbd/object_map/DiffRequest.cc" | |
25 | ||
26 | using ::testing::_; | |
27 | using ::testing::Invoke; | |
28 | using ::testing::InSequence; | |
29 | using ::testing::StrEq; | |
30 | using ::testing::WithArg; | |
31 | ||
32 | namespace librbd { | |
33 | namespace object_map { | |
34 | ||
35 | class TestMockObjectMapDiffRequest : public TestMockFixture { | |
36 | public: | |
37 | typedef DiffRequest<MockTestImageCtx> MockDiffRequest; | |
38 | ||
39 | void SetUp() override { | |
40 | TestMockFixture::SetUp(); | |
41 | ||
42 | ASSERT_EQ(0, open_image(m_image_name, &m_image_ctx)); | |
43 | } | |
44 | ||
45 | void expect_get_flags(MockTestImageCtx& mock_image_ctx, uint64_t snap_id, | |
46 | int32_t flags, int r) { | |
47 | EXPECT_CALL(mock_image_ctx, get_flags(snap_id, _)) | |
48 | .WillOnce(WithArg<1>(Invoke([flags, r](uint64_t *out_flags) { | |
49 | *out_flags = flags; | |
50 | return r; | |
51 | }))); | |
52 | } | |
53 | ||
54 | template <typename Lambda> | |
55 | void expect_load_map(MockTestImageCtx& mock_image_ctx, uint64_t snap_id, | |
56 | const BitVector<2>& object_map, int r, | |
57 | Lambda&& lambda) { | |
58 | std::string snap_oid(ObjectMap<>::object_map_name(mock_image_ctx.id, | |
59 | snap_id)); | |
60 | EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), | |
61 | exec(snap_oid, _, StrEq("rbd"), StrEq("object_map_load"), _, | |
f67539c2 | 62 | _, _, _)) |
adb31ebb TL |
63 | .WillOnce(WithArg<5>(Invoke([object_map, r, lambda=std::move(lambda)] |
64 | (bufferlist* out_bl) { | |
65 | lambda(); | |
66 | ||
67 | auto out_object_map{object_map}; | |
68 | out_object_map.set_crc_enabled(false); | |
69 | encode(out_object_map, *out_bl); | |
70 | return r; | |
71 | }))); | |
72 | } | |
73 | ||
74 | void expect_load_map(MockTestImageCtx& mock_image_ctx, uint64_t snap_id, | |
75 | const BitVector<2>& object_map, int r) { | |
76 | expect_load_map(mock_image_ctx, snap_id, object_map, r, [](){}); | |
77 | } | |
78 | ||
79 | librbd::ImageCtx* m_image_ctx = nullptr; | |
80 | BitVector<2> m_object_diff_state; | |
81 | }; | |
82 | ||
83 | TEST_F(TestMockObjectMapDiffRequest, InvalidStartSnap) { | |
84 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
85 | ||
86 | InSequence seq; | |
87 | ||
88 | C_SaferCond ctx; | |
89 | auto req = new MockDiffRequest(&mock_image_ctx, CEPH_NOSNAP, 0, | |
90 | &m_object_diff_state, &ctx); | |
91 | req->send(); | |
92 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
93 | } | |
94 | ||
95 | TEST_F(TestMockObjectMapDiffRequest, StartEndSnapEqual) { | |
96 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
97 | ||
98 | InSequence seq; | |
99 | ||
100 | C_SaferCond ctx; | |
101 | auto req = new MockDiffRequest(&mock_image_ctx, 1, 1, | |
102 | &m_object_diff_state, &ctx); | |
103 | req->send(); | |
104 | ASSERT_EQ(0, ctx.wait()); | |
105 | ASSERT_EQ(0U, m_object_diff_state.size()); | |
106 | } | |
107 | ||
108 | TEST_F(TestMockObjectMapDiffRequest, FastDiffDisabled) { | |
109 | // negative test -- object-map implicitly enables fast-diff | |
110 | REQUIRE(!is_feature_enabled(RBD_FEATURE_OBJECT_MAP)); | |
111 | ||
112 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
113 | ||
114 | InSequence seq; | |
115 | ||
116 | C_SaferCond ctx; | |
117 | auto req = new MockDiffRequest(&mock_image_ctx, 0, CEPH_NOSNAP, | |
118 | &m_object_diff_state, &ctx); | |
119 | req->send(); | |
120 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
121 | } | |
122 | ||
123 | TEST_F(TestMockObjectMapDiffRequest, FastDiffInvalid) { | |
124 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
125 | ||
126 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
127 | mock_image_ctx.snap_info = { | |
128 | {1U, {"snap1", {cls::rbd::UserSnapshotNamespace{}}, {}, {}, {}, {}, {}}} | |
129 | }; | |
130 | ||
131 | InSequence seq; | |
132 | expect_get_flags(mock_image_ctx, 1U, RBD_FLAG_FAST_DIFF_INVALID, 0); | |
133 | ||
134 | C_SaferCond ctx; | |
135 | auto req = new MockDiffRequest(&mock_image_ctx, 0, CEPH_NOSNAP, | |
136 | &m_object_diff_state, &ctx); | |
137 | req->send(); | |
138 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
139 | } | |
140 | ||
141 | TEST_F(TestMockObjectMapDiffRequest, FullDelta) { | |
142 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
143 | ||
144 | uint32_t object_count = 5; | |
145 | m_image_ctx->size = object_count * (1 << m_image_ctx->order); | |
146 | ||
147 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
148 | mock_image_ctx.snap_info = { | |
149 | {1U, {"snap1", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
150 | {}, {}, {}}}, | |
151 | {2U, {"snap2", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
152 | {}, {}, {}}} | |
153 | }; | |
154 | ||
155 | InSequence seq; | |
156 | ||
157 | expect_get_flags(mock_image_ctx, 1U, 0, 0); | |
158 | ||
159 | BitVector<2> object_map_1; | |
160 | object_map_1.resize(object_count); | |
161 | object_map_1[1] = OBJECT_EXISTS_CLEAN; | |
162 | expect_load_map(mock_image_ctx, 1U, object_map_1, 0); | |
163 | ||
164 | expect_get_flags(mock_image_ctx, 2U, 0, 0); | |
165 | ||
166 | BitVector<2> object_map_2; | |
167 | object_map_2.resize(object_count); | |
168 | object_map_2[1] = OBJECT_EXISTS_CLEAN; | |
169 | object_map_2[2] = OBJECT_EXISTS; | |
170 | object_map_2[3] = OBJECT_EXISTS; | |
171 | expect_load_map(mock_image_ctx, 2U, object_map_2, 0); | |
172 | ||
173 | expect_get_flags(mock_image_ctx, CEPH_NOSNAP, 0, 0); | |
174 | ||
175 | BitVector<2> object_map_head; | |
176 | object_map_head.resize(object_count); | |
177 | object_map_head[1] = OBJECT_EXISTS_CLEAN; | |
178 | object_map_head[2] = OBJECT_EXISTS_CLEAN; | |
179 | expect_load_map(mock_image_ctx, CEPH_NOSNAP, object_map_head, 0); | |
180 | ||
181 | C_SaferCond ctx; | |
182 | auto req = new MockDiffRequest(&mock_image_ctx, 0, CEPH_NOSNAP, | |
183 | &m_object_diff_state, &ctx); | |
184 | req->send(); | |
185 | ASSERT_EQ(0, ctx.wait()); | |
186 | ||
187 | BitVector<2> expected_diff_state; | |
188 | expected_diff_state.resize(object_count); | |
cd265ab1 TL |
189 | expected_diff_state[1] = DIFF_STATE_DATA_UPDATED; |
190 | expected_diff_state[2] = DIFF_STATE_DATA_UPDATED; | |
191 | expected_diff_state[3] = DIFF_STATE_HOLE_UPDATED; | |
adb31ebb TL |
192 | ASSERT_EQ(expected_diff_state, m_object_diff_state); |
193 | } | |
194 | ||
195 | TEST_F(TestMockObjectMapDiffRequest, IntermediateDelta) { | |
196 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
197 | ||
198 | uint32_t object_count = 5; | |
199 | m_image_ctx->size = object_count * (1 << m_image_ctx->order); | |
200 | ||
201 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
202 | mock_image_ctx.snap_info = { | |
203 | {1U, {"snap1", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
204 | {}, {}, {}}}, | |
205 | {2U, {"snap2", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
206 | {}, {}, {}}} | |
207 | }; | |
208 | ||
209 | InSequence seq; | |
210 | ||
211 | expect_get_flags(mock_image_ctx, 1U, 0, 0); | |
212 | ||
213 | BitVector<2> object_map_1; | |
214 | object_map_1.resize(object_count); | |
a4b75251 | 215 | object_map_1[1] = OBJECT_EXISTS; |
adb31ebb TL |
216 | object_map_1[2] = OBJECT_EXISTS_CLEAN; |
217 | expect_load_map(mock_image_ctx, 1U, object_map_1, 0); | |
218 | ||
219 | expect_get_flags(mock_image_ctx, 2U, 0, 0); | |
220 | ||
221 | BitVector<2> object_map_2; | |
222 | object_map_2.resize(object_count); | |
223 | object_map_2[1] = OBJECT_EXISTS_CLEAN; | |
224 | object_map_2[2] = OBJECT_EXISTS; | |
225 | object_map_2[3] = OBJECT_EXISTS; | |
226 | expect_load_map(mock_image_ctx, 2U, object_map_2, 0); | |
227 | ||
228 | C_SaferCond ctx; | |
229 | auto req = new MockDiffRequest(&mock_image_ctx, 1, 2, | |
230 | &m_object_diff_state, &ctx); | |
231 | req->send(); | |
232 | ASSERT_EQ(0, ctx.wait()); | |
233 | ||
234 | BitVector<2> expected_diff_state; | |
235 | expected_diff_state.resize(object_count); | |
cd265ab1 TL |
236 | expected_diff_state[1] = DIFF_STATE_DATA; |
237 | expected_diff_state[2] = DIFF_STATE_DATA_UPDATED; | |
238 | expected_diff_state[3] = DIFF_STATE_DATA_UPDATED; | |
adb31ebb TL |
239 | ASSERT_EQ(expected_diff_state, m_object_diff_state); |
240 | } | |
241 | ||
242 | TEST_F(TestMockObjectMapDiffRequest, EndDelta) { | |
243 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
244 | ||
245 | uint32_t object_count = 5; | |
246 | m_image_ctx->size = object_count * (1 << m_image_ctx->order); | |
247 | ||
248 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
249 | mock_image_ctx.snap_info = { | |
250 | {1U, {"snap1", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
251 | {}, {}, {}}}, | |
252 | {2U, {"snap2", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
253 | {}, {}, {}}} | |
254 | }; | |
255 | ||
256 | InSequence seq; | |
257 | ||
258 | expect_get_flags(mock_image_ctx, 2U, 0, 0); | |
259 | ||
260 | BitVector<2> object_map_2; | |
261 | object_map_2.resize(object_count); | |
262 | object_map_2[1] = OBJECT_EXISTS_CLEAN; | |
263 | object_map_2[2] = OBJECT_EXISTS; | |
264 | object_map_2[3] = OBJECT_EXISTS; | |
265 | expect_load_map(mock_image_ctx, 2U, object_map_2, 0); | |
266 | ||
267 | expect_get_flags(mock_image_ctx, CEPH_NOSNAP, 0, 0); | |
268 | ||
269 | BitVector<2> object_map_head; | |
270 | object_map_head.resize(object_count); | |
271 | object_map_head[1] = OBJECT_EXISTS_CLEAN; | |
272 | object_map_head[2] = OBJECT_EXISTS_CLEAN; | |
273 | expect_load_map(mock_image_ctx, CEPH_NOSNAP, object_map_head, 0); | |
274 | ||
275 | C_SaferCond ctx; | |
276 | auto req = new MockDiffRequest(&mock_image_ctx, 2, CEPH_NOSNAP, | |
277 | &m_object_diff_state, &ctx); | |
278 | req->send(); | |
279 | ASSERT_EQ(0, ctx.wait()); | |
280 | ||
281 | BitVector<2> expected_diff_state; | |
282 | expected_diff_state.resize(object_count); | |
cd265ab1 | 283 | expected_diff_state[1] = DIFF_STATE_DATA; |
a4b75251 | 284 | expected_diff_state[2] = DIFF_STATE_DATA; |
cd265ab1 | 285 | expected_diff_state[3] = DIFF_STATE_HOLE_UPDATED; |
adb31ebb TL |
286 | ASSERT_EQ(expected_diff_state, m_object_diff_state); |
287 | } | |
288 | ||
289 | TEST_F(TestMockObjectMapDiffRequest, StartSnapDNE) { | |
290 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
291 | ||
292 | uint32_t object_count = 5; | |
293 | m_image_ctx->size = object_count * (1 << m_image_ctx->order); | |
294 | ||
295 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
296 | mock_image_ctx.snap_info = { | |
297 | {2U, {"snap2", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
298 | {}, {}, {}}} | |
299 | }; | |
300 | ||
301 | InSequence seq; | |
302 | ||
303 | C_SaferCond ctx; | |
304 | auto req = new MockDiffRequest(&mock_image_ctx, 1, CEPH_NOSNAP, | |
305 | &m_object_diff_state, &ctx); | |
306 | req->send(); | |
307 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
308 | } | |
309 | ||
310 | TEST_F(TestMockObjectMapDiffRequest, EndSnapDNE) { | |
311 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
312 | ||
313 | uint32_t object_count = 5; | |
314 | m_image_ctx->size = object_count * (1 << m_image_ctx->order); | |
315 | ||
316 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
317 | mock_image_ctx.snap_info = { | |
318 | {1U, {"snap1", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
319 | {}, {}, {}}} | |
320 | }; | |
321 | ||
322 | InSequence seq; | |
323 | ||
324 | expect_get_flags(mock_image_ctx, 1U, 0, 0); | |
325 | ||
326 | BitVector<2> object_map_1; | |
327 | object_map_1.resize(object_count); | |
328 | expect_load_map(mock_image_ctx, 1U, object_map_1, 0); | |
329 | ||
330 | C_SaferCond ctx; | |
331 | auto req = new MockDiffRequest(&mock_image_ctx, 1, 2, | |
332 | &m_object_diff_state, &ctx); | |
333 | req->send(); | |
334 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
335 | } | |
336 | ||
337 | TEST_F(TestMockObjectMapDiffRequest, IntermediateSnapDNE) { | |
338 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
339 | ||
340 | uint32_t object_count = 5; | |
341 | m_image_ctx->size = object_count * (1 << m_image_ctx->order); | |
342 | ||
343 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
344 | mock_image_ctx.snap_info = { | |
345 | {1U, {"snap1", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
346 | {}, {}, {}}}, | |
347 | {2U, {"snap2", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
348 | {}, {}, {}}} | |
349 | }; | |
350 | ||
351 | InSequence seq; | |
352 | ||
353 | expect_get_flags(mock_image_ctx, 1U, 0, 0); | |
354 | ||
355 | BitVector<2> object_map_1; | |
356 | object_map_1.resize(object_count); | |
357 | object_map_1[1] = OBJECT_EXISTS_CLEAN; | |
358 | expect_load_map(mock_image_ctx, 1U, object_map_1, 0, | |
359 | [&mock_image_ctx]() { mock_image_ctx.snap_info.erase(2); }); | |
360 | ||
361 | expect_get_flags(mock_image_ctx, CEPH_NOSNAP, 0, 0); | |
362 | ||
363 | BitVector<2> object_map_head; | |
364 | object_map_head.resize(object_count); | |
365 | object_map_head[1] = OBJECT_EXISTS_CLEAN; | |
366 | expect_load_map(mock_image_ctx, CEPH_NOSNAP, object_map_head, 0); | |
367 | ||
368 | C_SaferCond ctx; | |
369 | auto req = new MockDiffRequest(&mock_image_ctx, 0, CEPH_NOSNAP, | |
370 | &m_object_diff_state, &ctx); | |
371 | req->send(); | |
372 | ASSERT_EQ(0, ctx.wait()); | |
373 | ||
374 | BitVector<2> expected_diff_state; | |
375 | expected_diff_state.resize(object_count); | |
cd265ab1 | 376 | expected_diff_state[1] = DIFF_STATE_DATA_UPDATED; |
adb31ebb TL |
377 | ASSERT_EQ(expected_diff_state, m_object_diff_state); |
378 | } | |
379 | ||
380 | TEST_F(TestMockObjectMapDiffRequest, LoadObjectMapDNE) { | |
381 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
382 | ||
383 | uint32_t object_count = 5; | |
384 | m_image_ctx->size = object_count * (1 << m_image_ctx->order); | |
385 | ||
386 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
387 | ||
388 | InSequence seq; | |
389 | ||
390 | expect_get_flags(mock_image_ctx, CEPH_NOSNAP, 0, 0); | |
391 | ||
392 | BitVector<2> object_map_head; | |
393 | expect_load_map(mock_image_ctx, CEPH_NOSNAP, object_map_head, -ENOENT); | |
394 | ||
395 | C_SaferCond ctx; | |
396 | auto req = new MockDiffRequest(&mock_image_ctx, 0, CEPH_NOSNAP, | |
397 | &m_object_diff_state, &ctx); | |
398 | req->send(); | |
399 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
400 | } | |
401 | ||
402 | TEST_F(TestMockObjectMapDiffRequest, LoadIntermediateObjectMapDNE) { | |
403 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
404 | ||
405 | uint32_t object_count = 5; | |
406 | m_image_ctx->size = object_count * (1 << m_image_ctx->order); | |
407 | ||
408 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
409 | mock_image_ctx.snap_info = { | |
410 | {1U, {"snap1", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
411 | {}, {}, {}}} | |
412 | }; | |
413 | ||
414 | InSequence seq; | |
415 | ||
416 | expect_get_flags(mock_image_ctx, 1U, 0, 0); | |
417 | ||
418 | BitVector<2> object_map_1; | |
419 | expect_load_map(mock_image_ctx, 1U, object_map_1, -ENOENT); | |
420 | ||
421 | expect_get_flags(mock_image_ctx, CEPH_NOSNAP, 0, 0); | |
422 | ||
423 | BitVector<2> object_map_head; | |
424 | object_map_head.resize(object_count); | |
425 | object_map_head[1] = OBJECT_EXISTS_CLEAN; | |
426 | expect_load_map(mock_image_ctx, CEPH_NOSNAP, object_map_head, 0); | |
427 | ||
428 | C_SaferCond ctx; | |
429 | auto req = new MockDiffRequest(&mock_image_ctx, 0, CEPH_NOSNAP, | |
430 | &m_object_diff_state, &ctx); | |
431 | req->send(); | |
432 | ASSERT_EQ(0, ctx.wait()); | |
433 | ||
434 | BitVector<2> expected_diff_state; | |
435 | expected_diff_state.resize(object_count); | |
cd265ab1 | 436 | expected_diff_state[1] = DIFF_STATE_DATA_UPDATED; |
adb31ebb TL |
437 | ASSERT_EQ(expected_diff_state, m_object_diff_state); |
438 | } | |
439 | ||
440 | TEST_F(TestMockObjectMapDiffRequest, LoadObjectMapError) { | |
441 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
442 | ||
443 | uint32_t object_count = 5; | |
444 | m_image_ctx->size = object_count * (1 << m_image_ctx->order); | |
445 | ||
446 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
447 | mock_image_ctx.snap_info = { | |
448 | {1U, {"snap1", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
449 | {}, {}, {}}} | |
450 | }; | |
451 | ||
452 | InSequence seq; | |
453 | ||
454 | expect_get_flags(mock_image_ctx, 1U, 0, 0); | |
455 | ||
456 | BitVector<2> object_map_1; | |
457 | expect_load_map(mock_image_ctx, 1U, object_map_1, -EPERM); | |
458 | ||
459 | C_SaferCond ctx; | |
460 | auto req = new MockDiffRequest(&mock_image_ctx, 0, CEPH_NOSNAP, | |
461 | &m_object_diff_state, &ctx); | |
462 | req->send(); | |
463 | ASSERT_EQ(-EPERM, ctx.wait()); | |
464 | } | |
465 | ||
466 | TEST_F(TestMockObjectMapDiffRequest, ObjectMapTooSmall) { | |
467 | REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); | |
468 | ||
469 | uint32_t object_count = 5; | |
470 | m_image_ctx->size = object_count * (1 << m_image_ctx->order); | |
471 | ||
472 | MockTestImageCtx mock_image_ctx(*m_image_ctx); | |
473 | mock_image_ctx.snap_info = { | |
474 | {1U, {"snap1", {cls::rbd::UserSnapshotNamespace{}}, mock_image_ctx.size, {}, | |
475 | {}, {}, {}}} | |
476 | }; | |
477 | ||
478 | InSequence seq; | |
479 | ||
480 | expect_get_flags(mock_image_ctx, 1U, 0, 0); | |
481 | ||
482 | BitVector<2> object_map_1; | |
483 | expect_load_map(mock_image_ctx, 1U, object_map_1, 0); | |
484 | ||
485 | C_SaferCond ctx; | |
486 | auto req = new MockDiffRequest(&mock_image_ctx, 0, CEPH_NOSNAP, | |
487 | &m_object_diff_state, &ctx); | |
488 | req->send(); | |
489 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
490 | } | |
491 | ||
492 | } // namespace object_map | |
493 | } // librbd |