Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librbd / object_map / test_mock_SnapshotRemoveRequest.cc
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 "librbd/ImageState.h"
9 #include "librbd/internal.h"
10 #include "librbd/ObjectMap.h"
11 #include "librbd/object_map/SnapshotRemoveRequest.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14
15 namespace librbd {
16 namespace object_map {
17
18 using ::testing::_;
19 using ::testing::DoDefault;
20 using ::testing::Return;
21 using ::testing::StrEq;
22
23 class TestMockObjectMapSnapshotRemoveRequest : public TestMockFixture {
24 public:
25   void expect_load_map(librbd::ImageCtx *ictx, uint64_t snap_id, int r) {
26     std::string snap_oid(ObjectMap<>::object_map_name(ictx->id, snap_id));
27     if (r < 0) {
28       EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
29                   exec(snap_oid, _, StrEq("rbd"), StrEq("object_map_load"), _, _, _))
30                     .WillOnce(Return(r));
31     } else {
32       EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
33                   exec(snap_oid, _, StrEq("rbd"), StrEq("object_map_load"), _, _, _))
34                     .WillOnce(DoDefault());
35     }
36   }
37
38   void expect_remove_snapshot(librbd::ImageCtx *ictx, int r) {
39     std::string oid(ObjectMap<>::object_map_name(ictx->id, CEPH_NOSNAP));
40     if (r < 0) {
41       EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
42                   exec(oid, _, StrEq("lock"), StrEq("assert_locked"), _, _, _))
43                     .WillOnce(Return(r));
44     } else {
45       EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
46                   exec(oid, _, StrEq("lock"), StrEq("assert_locked"), _, _, _))
47                     .WillOnce(DoDefault());
48       EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
49                   exec(oid, _, StrEq("rbd"), StrEq("object_map_snap_remove"), _, _, _))
50                     .WillOnce(DoDefault());
51     }
52   }
53
54   void expect_remove_map(librbd::ImageCtx *ictx, uint64_t snap_id, int r) {
55     std::string snap_oid(ObjectMap<>::object_map_name(ictx->id, snap_id));
56     if (r < 0) {
57       EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx), remove(snap_oid, _))
58                     .WillOnce(Return(r));
59     } else {
60       EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx), remove(snap_oid, _))
61                     .WillOnce(DoDefault());
62     }
63   }
64
65   void expect_invalidate(librbd::ImageCtx *ictx) {
66     EXPECT_CALL(get_mock_io_ctx(ictx->md_ctx),
67                 exec(ictx->header_oid, _, StrEq("rbd"), StrEq("set_flags"), _, _, _))
68                   .WillOnce(DoDefault());
69   }
70 };
71
72 TEST_F(TestMockObjectMapSnapshotRemoveRequest, Success) {
73   REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
74
75   librbd::ImageCtx *ictx;
76   ASSERT_EQ(0, open_image(m_image_name, &ictx));
77   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
78   ASSERT_EQ(0, ictx->state->refresh_if_required());
79
80   uint64_t snap_id = ictx->snap_info.rbegin()->first;
81   if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
82     expect_load_map(ictx, snap_id, 0);
83     expect_remove_snapshot(ictx, 0);
84   }
85   expect_remove_map(ictx, snap_id, 0);
86
87   ceph::BitVector<2> object_map;
88   C_SaferCond cond_ctx;
89   AsyncRequest<> *request = new SnapshotRemoveRequest(
90     *ictx, &object_map, snap_id, &cond_ctx);
91   {
92     RWLock::RLocker owner_locker(ictx->owner_lock);
93     RWLock::WLocker snap_locker(ictx->snap_lock);
94     request->send();
95   }
96   ASSERT_EQ(0, cond_ctx.wait());
97
98   expect_unlock_exclusive_lock(*ictx);
99 }
100
101 TEST_F(TestMockObjectMapSnapshotRemoveRequest, LoadMapMissing) {
102   REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF);
103
104   librbd::ImageCtx *ictx;
105   ASSERT_EQ(0, open_image(m_image_name, &ictx));
106   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
107   ASSERT_EQ(0, ictx->state->refresh_if_required());
108
109   uint64_t snap_id = ictx->snap_info.rbegin()->first;
110   expect_load_map(ictx, snap_id, -ENOENT);
111
112   ceph::BitVector<2> object_map;
113   C_SaferCond cond_ctx;
114   AsyncRequest<> *request = new SnapshotRemoveRequest(
115     *ictx, &object_map, snap_id, &cond_ctx);
116   {
117     RWLock::RLocker owner_locker(ictx->owner_lock);
118     RWLock::WLocker snap_locker(ictx->snap_lock);
119     request->send();
120   }
121   ASSERT_EQ(0, cond_ctx.wait());
122
123   expect_unlock_exclusive_lock(*ictx);
124 }
125
126 TEST_F(TestMockObjectMapSnapshotRemoveRequest, LoadMapError) {
127   REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF);
128
129   librbd::ImageCtx *ictx;
130   ASSERT_EQ(0, open_image(m_image_name, &ictx));
131   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
132   ASSERT_EQ(0, ictx->state->refresh_if_required());
133
134   uint64_t snap_id = ictx->snap_info.rbegin()->first;
135   expect_load_map(ictx, snap_id, -EINVAL);
136   expect_invalidate(ictx);
137   expect_remove_map(ictx, snap_id, 0);
138
139   ceph::BitVector<2> object_map;
140   C_SaferCond cond_ctx;
141   AsyncRequest<> *request = new SnapshotRemoveRequest(
142     *ictx, &object_map, snap_id, &cond_ctx);
143   {
144     RWLock::RLocker owner_locker(ictx->owner_lock);
145     RWLock::WLocker snap_locker(ictx->snap_lock);
146     request->send();
147   }
148   ASSERT_EQ(0, cond_ctx.wait());
149
150   expect_unlock_exclusive_lock(*ictx);
151 }
152
153 TEST_F(TestMockObjectMapSnapshotRemoveRequest, RemoveSnapshotMissing) {
154   REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF);
155
156   librbd::ImageCtx *ictx;
157   ASSERT_EQ(0, open_image(m_image_name, &ictx));
158   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
159   ASSERT_EQ(0, ictx->state->refresh_if_required());
160
161   uint64_t snap_id = ictx->snap_info.rbegin()->first;
162   expect_load_map(ictx, snap_id, 0);
163   expect_remove_snapshot(ictx, -ENOENT);
164   expect_remove_map(ictx, snap_id, 0);
165
166   ceph::BitVector<2> object_map;
167   C_SaferCond cond_ctx;
168   AsyncRequest<> *request = new SnapshotRemoveRequest(
169     *ictx, &object_map, snap_id, &cond_ctx);
170   {
171     RWLock::RLocker owner_locker(ictx->owner_lock);
172     RWLock::WLocker snap_locker(ictx->snap_lock);
173     request->send();
174   }
175   ASSERT_EQ(0, cond_ctx.wait());
176
177   expect_unlock_exclusive_lock(*ictx);
178 }
179
180 TEST_F(TestMockObjectMapSnapshotRemoveRequest, RemoveSnapshotError) {
181   REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF);
182
183   librbd::ImageCtx *ictx;
184   ASSERT_EQ(0, open_image(m_image_name, &ictx));
185   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
186   ASSERT_EQ(0, ictx->state->refresh_if_required());
187
188   uint64_t snap_id = ictx->snap_info.rbegin()->first;
189   expect_load_map(ictx, snap_id, 0);
190   expect_remove_snapshot(ictx, -EINVAL);
191   expect_invalidate(ictx);
192   expect_remove_map(ictx, snap_id, 0);
193
194   ceph::BitVector<2> object_map;
195   C_SaferCond cond_ctx;
196   AsyncRequest<> *request = new SnapshotRemoveRequest(
197     *ictx, &object_map, snap_id, &cond_ctx);
198   {
199     RWLock::RLocker owner_locker(ictx->owner_lock);
200     RWLock::WLocker snap_locker(ictx->snap_lock);
201     request->send();
202   }
203   ASSERT_EQ(0, cond_ctx.wait());
204
205   expect_unlock_exclusive_lock(*ictx);
206 }
207
208 TEST_F(TestMockObjectMapSnapshotRemoveRequest, RemoveMapMissing) {
209   REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
210
211   librbd::ImageCtx *ictx;
212   ASSERT_EQ(0, open_image(m_image_name, &ictx));
213   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
214   ASSERT_EQ(0, ictx->state->refresh_if_required());
215
216   uint64_t snap_id = ictx->snap_info.rbegin()->first;
217   if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
218     expect_load_map(ictx, snap_id, 0);
219     expect_remove_snapshot(ictx, 0);
220   }
221   expect_remove_map(ictx, snap_id, -ENOENT);
222
223   ceph::BitVector<2> object_map;
224   C_SaferCond cond_ctx;
225   AsyncRequest<> *request = new SnapshotRemoveRequest(
226     *ictx, &object_map, snap_id, &cond_ctx);
227   {
228     RWLock::RLocker owner_locker(ictx->owner_lock);
229     RWLock::WLocker snap_locker(ictx->snap_lock);
230     request->send();
231   }
232   ASSERT_EQ(0, cond_ctx.wait());
233
234   expect_unlock_exclusive_lock(*ictx);
235 }
236
237 TEST_F(TestMockObjectMapSnapshotRemoveRequest, RemoveMapError) {
238   REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
239
240   librbd::ImageCtx *ictx;
241   ASSERT_EQ(0, open_image(m_image_name, &ictx));
242   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
243   ASSERT_EQ(0, ictx->state->refresh_if_required());
244
245   uint64_t snap_id = ictx->snap_info.rbegin()->first;
246   if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
247     expect_load_map(ictx, snap_id, 0);
248     expect_remove_snapshot(ictx, 0);
249   }
250   expect_remove_map(ictx, snap_id, -EINVAL);
251
252   ceph::BitVector<2> object_map;
253   C_SaferCond cond_ctx;
254   AsyncRequest<> *request = new SnapshotRemoveRequest(
255     *ictx, &object_map, snap_id, &cond_ctx);
256   {
257     RWLock::RLocker owner_locker(ictx->owner_lock);
258     RWLock::WLocker snap_locker(ictx->snap_lock);
259     request->send();
260   }
261   ASSERT_EQ(-EINVAL, cond_ctx.wait());
262
263   expect_unlock_exclusive_lock(*ictx);
264 }
265
266 TEST_F(TestMockObjectMapSnapshotRemoveRequest, ScrubCleanObjects) {
267   REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF);
268
269   librbd::ImageCtx *ictx;
270   ASSERT_EQ(0, open_image(m_image_name, &ictx));
271   ASSERT_EQ(0, snap_create(*ictx, "snap1"));
272   ASSERT_EQ(0, ictx->state->refresh_if_required());
273
274   uint64_t snap_id = ictx->snap_info.rbegin()->first;
275
276   ceph::BitVector<2> object_map;
277   object_map.resize(1024);
278   for (uint64_t i = 512; i < object_map.size(); ++i) {
279     object_map[i] = i % 2 == 0 ? OBJECT_EXISTS_CLEAN : OBJECT_NONEXISTENT;
280   }
281
282   C_SaferCond cond_ctx;
283   AsyncRequest<> *request = new SnapshotRemoveRequest(
284     *ictx, &object_map, snap_id, &cond_ctx);
285   {
286     RWLock::RLocker owner_locker(ictx->owner_lock);
287     RWLock::WLocker snap_locker(ictx->snap_lock);
288     request->send();
289   }
290   ASSERT_EQ(0, cond_ctx.wait());
291
292   for (uint64_t i = 512; i < object_map.size(); ++i) {
293     ASSERT_EQ(i % 2 == 0 ? OBJECT_EXISTS : OBJECT_NONEXISTENT,
294               object_map[i]);
295   }
296 }
297
298 } // namespace object_map
299 } // namespace librbd