Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librados / snapshots.cc
1 #include "include/rados/librados.hpp"
2 #include "test/librados/test.h"
3 #include "test/librados/TestCase.h"
4
5 #include <algorithm>
6 #include <errno.h>
7 #include "gtest/gtest.h"
8 #include <string>
9
10 using namespace librados;
11 using std::string;
12
13 typedef RadosTest LibRadosSnapshots;
14 typedef RadosTest LibRadosSnapshotsSelfManaged;
15 typedef RadosTestPP LibRadosSnapshotsPP;
16 typedef RadosTestPP LibRadosSnapshotsSelfManagedPP;
17 typedef RadosTestEC LibRadosSnapshotsEC;
18 typedef RadosTestEC LibRadosSnapshotsSelfManagedEC;
19 typedef RadosTestECPP LibRadosSnapshotsECPP;
20 typedef RadosTestECPP LibRadosSnapshotsSelfManagedECPP;
21
22 const int bufsize = 128;
23
24 TEST_F(LibRadosSnapshots, SnapList) {
25   char buf[bufsize];
26   memset(buf, 0xcc, sizeof(buf));
27   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
28   ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snap1"));
29   rados_snap_t snaps[10];
30   EXPECT_EQ(1, rados_ioctx_snap_list(ioctx, snaps,
31                                      sizeof(snaps) / sizeof(snaps[0])));
32   rados_snap_t rid;
33   EXPECT_EQ(0, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
34   EXPECT_EQ(rid, snaps[0]);
35   EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
36 }
37
38 TEST_F(LibRadosSnapshotsPP, SnapListPP) {
39   char buf[bufsize];
40   memset(buf, 0xcc, sizeof(buf));
41   bufferlist bl1;
42   bl1.append(buf, sizeof(buf));
43   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
44   ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
45   ASSERT_EQ(0, ioctx.snap_create("snap1"));
46   ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
47   std::vector<snap_t> snaps;
48   EXPECT_EQ(0, ioctx.snap_list(&snaps));
49   EXPECT_EQ(1U, snaps.size());
50   snap_t rid;
51   EXPECT_EQ(0, ioctx.snap_lookup("snap1", &rid));
52   EXPECT_EQ(rid, snaps[0]);
53   EXPECT_EQ(0, ioctx.snap_remove("snap1"));
54   ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
55 }
56
57 TEST_F(LibRadosSnapshots, SnapRemove) {
58   char buf[bufsize];
59   memset(buf, 0xcc, sizeof(buf));
60   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
61   ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snap1"));
62   rados_snap_t rid;
63   ASSERT_EQ(0, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
64   ASSERT_EQ(-EEXIST, rados_ioctx_snap_create(ioctx, "snap1"));
65   ASSERT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
66   ASSERT_EQ(-ENOENT, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
67 }
68
69 TEST_F(LibRadosSnapshotsPP, SnapRemovePP) {
70   char buf[bufsize];
71   memset(buf, 0xcc, sizeof(buf));
72   bufferlist bl1;
73   bl1.append(buf, sizeof(buf));
74   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
75   ASSERT_EQ(0, ioctx.snap_create("snap1"));
76   rados_snap_t rid;
77   ASSERT_EQ(0, ioctx.snap_lookup("snap1", &rid));
78   ASSERT_EQ(0, ioctx.snap_remove("snap1"));
79   ASSERT_EQ(-ENOENT, ioctx.snap_lookup("snap1", &rid));
80 }
81
82 TEST_F(LibRadosSnapshots, Rollback) {
83   char buf[bufsize];
84   memset(buf, 0xcc, sizeof(buf));
85   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
86   ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snap1"));
87   char buf2[sizeof(buf)];
88   memset(buf2, 0xdd, sizeof(buf2));
89   EXPECT_EQ(0, rados_write_full(ioctx, "foo", buf2, sizeof(buf2)));
90   EXPECT_EQ(0, rados_ioctx_snap_rollback(ioctx, "foo", "snap1"));
91   char buf3[sizeof(buf)];
92   EXPECT_EQ((int)sizeof(buf3), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
93   EXPECT_EQ(0, memcmp(buf, buf3, sizeof(buf)));
94   EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
95 }
96
97 TEST_F(LibRadosSnapshotsPP, RollbackPP) {
98   char buf[bufsize];
99   memset(buf, 0xcc, sizeof(buf));
100   bufferlist bl1;
101   bl1.append(buf, sizeof(buf));
102   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
103   ASSERT_EQ(0, ioctx.snap_create("snap1"));
104   char buf2[sizeof(buf)];
105   memset(buf2, 0xdd, sizeof(buf2));
106   bufferlist bl2;
107   bl2.append(buf2, sizeof(buf2));
108   EXPECT_EQ(0, ioctx.write_full("foo", bl2));
109   EXPECT_EQ(0, ioctx.snap_rollback("foo", "snap1"));
110   bufferlist bl3;
111   EXPECT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
112   EXPECT_EQ(0, memcmp(buf, bl3.c_str(), sizeof(buf)));
113   EXPECT_EQ(0, ioctx.snap_remove("snap1"));
114 }
115
116 TEST_F(LibRadosSnapshots, SnapGetName) {
117   char buf[bufsize];
118   memset(buf, 0xcc, sizeof(buf));
119   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
120   ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snapfoo"));
121   rados_snap_t rid;
122   EXPECT_EQ(0, rados_ioctx_snap_lookup(ioctx, "snapfoo", &rid));
123   EXPECT_EQ(-ENOENT, rados_ioctx_snap_lookup(ioctx, "snapbar", &rid));
124   char name[128];
125   memset(name, 0, sizeof(name));
126   EXPECT_EQ(0, rados_ioctx_snap_get_name(ioctx, rid, name, sizeof(name)));
127   time_t snaptime;
128   EXPECT_EQ(0, rados_ioctx_snap_get_stamp(ioctx, rid, &snaptime));
129   EXPECT_EQ(0, strcmp(name, "snapfoo"));
130   EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snapfoo"));
131 }
132
133 TEST_F(LibRadosSnapshotsPP, SnapGetNamePP) {
134   char buf[bufsize];
135   memset(buf, 0xcc, sizeof(buf));
136   bufferlist bl;
137   bl.append(buf, sizeof(buf));
138   ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
139   ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
140   rados_snap_t rid;
141   EXPECT_EQ(0, ioctx.snap_lookup("snapfoo", &rid));
142   EXPECT_EQ(-ENOENT, ioctx.snap_lookup("snapbar", &rid));
143   std::string name;
144   EXPECT_EQ(0, ioctx.snap_get_name(rid, &name));
145   time_t snaptime;
146   EXPECT_EQ(0, ioctx.snap_get_stamp(rid, &snaptime));
147   EXPECT_EQ(0, strcmp(name.c_str(), "snapfoo"));
148   EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
149 }
150
151 TEST_F(LibRadosSnapshotsPP, SnapCreateRemovePP) {
152   // reproduces http://tracker.ceph.com/issues/10262
153   bufferlist bl;
154   bl.append("foo");
155   ASSERT_EQ(0, ioctx.write("foo", bl, bl.length(), 0));
156   ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
157   ASSERT_EQ(0, ioctx.remove("foo"));
158   ASSERT_EQ(0, ioctx.snap_create("snapbar"));
159
160   std::unique_ptr<librados::ObjectWriteOperation> op(new librados::ObjectWriteOperation());
161   op->create(false);
162   op->remove();
163   ASSERT_EQ(0, ioctx.operate("foo", op.get()));
164
165   EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
166   EXPECT_EQ(0, ioctx.snap_remove("snapbar"));
167 }
168
169 TEST_F(LibRadosSnapshotsSelfManaged, Snap) {
170   std::vector<uint64_t> my_snaps;
171   my_snaps.push_back(-2);
172   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back()));
173   ::std::reverse(my_snaps.begin(), my_snaps.end());
174   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
175                                         &my_snaps[0], my_snaps.size()));
176   ::std::reverse(my_snaps.begin(), my_snaps.end());
177   char buf[bufsize];
178   memset(buf, 0xcc, sizeof(buf));
179   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
180
181   my_snaps.push_back(-2);
182   rados_completion_t completion;
183   ASSERT_EQ(0, rados_aio_create_completion(nullptr, nullptr, nullptr,
184                                            &completion));
185   rados_aio_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back(), completion);
186   ASSERT_EQ(0, rados_aio_wait_for_complete(completion));
187   rados_aio_release(completion);
188   ::std::reverse(my_snaps.begin(), my_snaps.end());
189   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
190                                         &my_snaps[0], my_snaps.size()));
191   ::std::reverse(my_snaps.begin(), my_snaps.end());
192   char buf2[sizeof(buf)];
193   memset(buf2, 0xdd, sizeof(buf2));
194   ASSERT_EQ(0, rados_write(ioctx, "foo", buf2, sizeof(buf2), 0));
195   rados_ioctx_snap_set_read(ioctx, my_snaps[1]-1);
196   char buf3[sizeof(buf)];
197   ASSERT_EQ(-ENOENT, rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
198
199   rados_ioctx_snap_set_read(ioctx, my_snaps[1]);
200   ASSERT_EQ((int)sizeof(buf3), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
201   ASSERT_EQ(0, memcmp(buf3, buf, sizeof(buf)));
202
203   ASSERT_EQ(0, rados_aio_create_completion(nullptr, nullptr, nullptr,
204                                            &completion));
205   rados_aio_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back(), completion);
206   ASSERT_EQ(0, rados_aio_wait_for_complete(completion));
207   rados_aio_release(completion);
208   my_snaps.pop_back();
209   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back()));
210   my_snaps.pop_back();
211   rados_ioctx_snap_set_read(ioctx, LIBRADOS_SNAP_HEAD);
212   ASSERT_EQ(0, rados_remove(ioctx, "foo"));
213 }
214
215 TEST_F(LibRadosSnapshotsSelfManaged, Rollback) {
216   std::vector<uint64_t> my_snaps;
217   my_snaps.push_back(-2);
218   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back()));
219   ::std::reverse(my_snaps.begin(), my_snaps.end());
220   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
221                                         &my_snaps[0], my_snaps.size()));
222   ::std::reverse(my_snaps.begin(), my_snaps.end());
223   char buf[bufsize];
224   memset(buf, 0xcc, sizeof(buf));
225   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
226
227   my_snaps.push_back(-2);
228   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back()));
229   ::std::reverse(my_snaps.begin(), my_snaps.end());
230   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
231                                         &my_snaps[0], my_snaps.size()));
232   ::std::reverse(my_snaps.begin(), my_snaps.end());
233   char buf2[sizeof(buf)];
234   memset(buf2, 0xdd, sizeof(buf2));
235   ASSERT_EQ(0, rados_write(ioctx, "foo", buf2, sizeof(buf2), 0));
236   rados_ioctx_selfmanaged_snap_rollback(ioctx, "foo", my_snaps[1]);
237   char buf3[sizeof(buf)];
238   ASSERT_EQ((int)sizeof(buf3), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
239   ASSERT_EQ(0, memcmp(buf3, buf, sizeof(buf)));
240
241   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back()));
242   my_snaps.pop_back();
243   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back()));
244   my_snaps.pop_back();
245   ASSERT_EQ(0, rados_remove(ioctx, "foo"));
246 }
247
248 TEST_F(LibRadosSnapshotsSelfManagedPP, SnapPP) {
249   std::vector<uint64_t> my_snaps;
250   my_snaps.push_back(-2);
251   ASSERT_FALSE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
252   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
253   ASSERT_TRUE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
254   ::std::reverse(my_snaps.begin(), my_snaps.end()); 
255   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
256   ::std::reverse(my_snaps.begin(), my_snaps.end());
257   char buf[bufsize];
258   memset(buf, 0xcc, sizeof(buf));
259   bufferlist bl1;
260   bl1.append(buf, sizeof(buf));
261   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
262
263   my_snaps.push_back(-2);
264   librados::AioCompletion *completion = cluster.aio_create_completion();
265   ioctx.aio_selfmanaged_snap_create(&my_snaps.back(), completion);
266   ASSERT_EQ(0, completion->wait_for_complete());
267   completion->release();
268   ::std::reverse(my_snaps.begin(), my_snaps.end());
269   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
270   ::std::reverse(my_snaps.begin(), my_snaps.end());
271   char buf2[sizeof(buf)];
272   memset(buf2, 0xdd, sizeof(buf2));
273   bufferlist bl2;
274   bl2.append(buf2, sizeof(buf2));
275   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), 0));
276
277   ioctx.snap_set_read(my_snaps[1]);
278   bufferlist bl3;
279   ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
280   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
281
282   completion = cluster.aio_create_completion();
283   ioctx.aio_selfmanaged_snap_remove(my_snaps.back(), completion);
284   ASSERT_EQ(0, completion->wait_for_complete());
285   completion->release();
286   my_snaps.pop_back();
287   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
288   my_snaps.pop_back();
289   ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
290   ASSERT_TRUE(cluster.get_pool_is_selfmanaged_snaps_mode(pool_name));
291   ASSERT_EQ(0, ioctx.remove("foo"));
292 }
293
294 TEST_F(LibRadosSnapshotsSelfManagedPP, RollbackPP) {
295   std::vector<uint64_t> my_snaps;
296   IoCtx readioctx;
297   ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), readioctx));
298   readioctx.set_namespace(nspace);
299   readioctx.snap_set_read(LIBRADOS_SNAP_DIR);
300
301   my_snaps.push_back(-2);
302   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
303   ::std::reverse(my_snaps.begin(), my_snaps.end());
304   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
305   ::std::reverse(my_snaps.begin(), my_snaps.end());
306   char buf[bufsize];
307   memset(buf, 0xcc, sizeof(buf));
308   bufferlist bl1;
309   bl1.append(buf, sizeof(buf));
310   //Write 3 consecutive buffers
311   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
312   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize));
313   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*2));
314
315   snap_set_t ss;
316
317   snap_t head = SNAP_HEAD;
318   ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
319   ASSERT_EQ(1u, ss.clones.size());
320   ASSERT_EQ(head, ss.clones[0].cloneid);
321   ASSERT_EQ(0u, ss.clones[0].snaps.size());
322   ASSERT_EQ(0u, ss.clones[0].overlap.size());
323   ASSERT_EQ(384u, ss.clones[0].size);
324
325   my_snaps.push_back(-2);
326   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
327   ::std::reverse(my_snaps.begin(), my_snaps.end());
328   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
329   ::std::reverse(my_snaps.begin(), my_snaps.end());
330   char buf2[sizeof(buf)];
331   memset(buf2, 0xdd, sizeof(buf2));
332   bufferlist bl2;
333   bl2.append(buf2, sizeof(buf2));
334   //Change the middle buffer
335   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize));
336   //Add another after
337   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*3));
338
339   ASSERT_EQ(-EINVAL, ioctx.list_snaps("foo", &ss));
340   ObjectReadOperation o;
341   o.list_snaps(&ss, NULL);
342   ASSERT_EQ(-EINVAL, ioctx.operate("foo", &o, NULL));
343
344   ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
345   ASSERT_EQ(2u, ss.clones.size());
346   ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
347   ASSERT_EQ(1u, ss.clones[0].snaps.size());
348   ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
349   ASSERT_EQ(2u, ss.clones[0].overlap.size());
350   ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
351   ASSERT_EQ(128u, ss.clones[0].overlap[0].second);
352   ASSERT_EQ(256u, ss.clones[0].overlap[1].first);
353   ASSERT_EQ(128u, ss.clones[0].overlap[1].second);
354   ASSERT_EQ(384u, ss.clones[0].size);
355   ASSERT_EQ(head, ss.clones[1].cloneid);
356   ASSERT_EQ(0u, ss.clones[1].snaps.size());
357   ASSERT_EQ(0u, ss.clones[1].overlap.size());
358   ASSERT_EQ(512u, ss.clones[1].size);
359
360   ioctx.selfmanaged_snap_rollback("foo", my_snaps[1]);
361
362   bufferlist bl3;
363   ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
364   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
365   ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), bufsize));
366   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
367   ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), bufsize*2));
368   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
369   ASSERT_EQ((int)0, ioctx.read("foo", bl3, sizeof(buf), bufsize*3));
370
371   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
372   my_snaps.pop_back();
373   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
374   my_snaps.pop_back();
375   readioctx.close();
376 }
377
378 TEST_F(LibRadosSnapshotsSelfManagedPP, SnapOverlapPP) {
379   std::vector<uint64_t> my_snaps;
380   IoCtx readioctx;
381   ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), readioctx));
382   readioctx.set_namespace(nspace);
383   readioctx.snap_set_read(LIBRADOS_SNAP_DIR);
384
385   my_snaps.push_back(-2);
386   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
387   ::std::reverse(my_snaps.begin(), my_snaps.end());
388   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
389   ::std::reverse(my_snaps.begin(), my_snaps.end());
390   char buf[bufsize];
391   memset(buf, 0xcc, sizeof(buf));
392   bufferlist bl1;
393   bl1.append(buf, sizeof(buf));
394   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
395   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*2));
396   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*4));
397   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*6));
398   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), bufsize*8));
399
400   snap_set_t ss;
401   snap_t head = SNAP_HEAD;
402   ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
403   ASSERT_EQ(1u, ss.clones.size());
404   ASSERT_EQ(head, ss.clones[0].cloneid);
405   ASSERT_EQ(0u, ss.clones[0].snaps.size());
406   ASSERT_EQ(0u, ss.clones[0].overlap.size());
407   ASSERT_EQ(1152u, ss.clones[0].size);
408
409   my_snaps.push_back(-2);
410   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
411   ::std::reverse(my_snaps.begin(), my_snaps.end());
412   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
413   ::std::reverse(my_snaps.begin(), my_snaps.end());
414   char buf2[sizeof(buf)];
415   memset(buf2, 0xdd, sizeof(buf2));
416   bufferlist bl2;
417   bl2.append(buf2, sizeof(buf2));
418   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*1));
419   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*3));
420   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*5));
421   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*7));
422   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize*9));
423
424   ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
425   ASSERT_EQ(2u, ss.clones.size());
426   ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
427   ASSERT_EQ(1u, ss.clones[0].snaps.size());
428   ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
429   ASSERT_EQ(5u, ss.clones[0].overlap.size());
430   ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
431   ASSERT_EQ(128u, ss.clones[0].overlap[0].second);
432   ASSERT_EQ(256u, ss.clones[0].overlap[1].first);
433   ASSERT_EQ(128u, ss.clones[0].overlap[1].second);
434   ASSERT_EQ(512u, ss.clones[0].overlap[2].first);
435   ASSERT_EQ(128u, ss.clones[0].overlap[2].second);
436   ASSERT_EQ(768u, ss.clones[0].overlap[3].first);
437   ASSERT_EQ(128u, ss.clones[0].overlap[3].second);
438   ASSERT_EQ(1024u, ss.clones[0].overlap[4].first);
439   ASSERT_EQ(128u, ss.clones[0].overlap[4].second);
440   ASSERT_EQ(1152u, ss.clones[0].size);
441   ASSERT_EQ(head, ss.clones[1].cloneid);
442   ASSERT_EQ(0u, ss.clones[1].snaps.size());
443   ASSERT_EQ(0u, ss.clones[1].overlap.size());
444   ASSERT_EQ(1280u, ss.clones[1].size);
445
446   my_snaps.push_back(-2);
447   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
448   ::std::reverse(my_snaps.begin(), my_snaps.end());
449   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
450   ::std::reverse(my_snaps.begin(), my_snaps.end());
451
452   char buf3[sizeof(buf)];
453   memset(buf3, 0xee, sizeof(buf3));
454   bufferlist bl4;
455   bl4.append(buf3, sizeof(buf3));
456   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*1));
457   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*4));
458   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*5));
459   ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf3), bufsize*8));
460
461   ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
462   ASSERT_EQ(3u, ss.clones.size());
463   ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
464   ASSERT_EQ(1u, ss.clones[0].snaps.size());
465   ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
466   ASSERT_EQ(5u, ss.clones[0].overlap.size());
467   ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
468   ASSERT_EQ(128u, ss.clones[0].overlap[0].second);
469   ASSERT_EQ(256u, ss.clones[0].overlap[1].first);
470   ASSERT_EQ(128u, ss.clones[0].overlap[1].second);
471   ASSERT_EQ(512u, ss.clones[0].overlap[2].first);
472   ASSERT_EQ(128u, ss.clones[0].overlap[2].second);
473   ASSERT_EQ(768u, ss.clones[0].overlap[3].first);
474   ASSERT_EQ(128u, ss.clones[0].overlap[3].second);
475   ASSERT_EQ(1024u, ss.clones[0].overlap[4].first);
476   ASSERT_EQ(128u, ss.clones[0].overlap[4].second);
477   ASSERT_EQ(1152u, ss.clones[0].size);
478
479   ASSERT_EQ(my_snaps[2], ss.clones[1].cloneid);
480   ASSERT_EQ(1u, ss.clones[1].snaps.size());
481   ASSERT_EQ(my_snaps[2], ss.clones[1].snaps[0]);
482   ASSERT_EQ(4u, ss.clones[1].overlap.size());
483   ASSERT_EQ(0u, ss.clones[1].overlap[0].first);
484   ASSERT_EQ(128u, ss.clones[1].overlap[0].second);
485   ASSERT_EQ(256u, ss.clones[1].overlap[1].first);
486   ASSERT_EQ(256u, ss.clones[1].overlap[1].second);
487   ASSERT_EQ(768u, ss.clones[1].overlap[2].first);
488   ASSERT_EQ(256u, ss.clones[1].overlap[2].second);
489   ASSERT_EQ(1152u, ss.clones[1].overlap[3].first);
490   ASSERT_EQ(128u, ss.clones[1].overlap[3].second);
491   ASSERT_EQ(1280u, ss.clones[1].size);
492
493   ASSERT_EQ(head, ss.clones[2].cloneid);
494   ASSERT_EQ(0u, ss.clones[2].snaps.size());
495   ASSERT_EQ(0u, ss.clones[2].overlap.size());
496   ASSERT_EQ(1280u, ss.clones[2].size);
497
498   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
499   my_snaps.pop_back();
500   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
501   my_snaps.pop_back();
502   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
503   my_snaps.pop_back();
504   readioctx.close();
505 }
506
507 TEST_F(LibRadosSnapshotsSelfManagedPP, Bug11677) {
508   std::vector<uint64_t> my_snaps;
509   my_snaps.push_back(-2);
510   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
511   ::std::reverse(my_snaps.begin(), my_snaps.end());
512   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
513   ::std::reverse(my_snaps.begin(), my_snaps.end());
514
515   int bsize = 1<<20;
516   char *buf = (char *)new char[bsize];
517   memset(buf, 0xcc, bsize);
518   bufferlist bl1;
519   bl1.append(buf, bsize);
520   ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
521
522   my_snaps.push_back(-2);
523   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
524   ::std::reverse(my_snaps.begin(), my_snaps.end());
525   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
526   ::std::reverse(my_snaps.begin(), my_snaps.end());
527
528   std::unique_ptr<librados::ObjectWriteOperation> op(new librados::ObjectWriteOperation());
529   op->assert_exists();
530   op->remove();
531   ASSERT_EQ(0, ioctx.operate("foo", op.get()));
532
533   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
534   my_snaps.pop_back();
535   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
536   my_snaps.pop_back();
537   ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
538   delete[] buf;
539 }
540
541 // EC testing
542 TEST_F(LibRadosSnapshotsEC, SnapList) {
543   char buf[bufsize];
544   memset(buf, 0xcc, sizeof(buf));
545   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
546   ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snap1"));
547   rados_snap_t snaps[10];
548   EXPECT_EQ(1, rados_ioctx_snap_list(ioctx, snaps,
549                                      sizeof(snaps) / sizeof(snaps[0])));
550   rados_snap_t rid;
551   EXPECT_EQ(0, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
552   EXPECT_EQ(rid, snaps[0]);
553   EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
554 }
555
556 TEST_F(LibRadosSnapshotsECPP, SnapListPP) {
557   char buf[bufsize];
558   memset(buf, 0xcc, sizeof(buf));
559   bufferlist bl1;
560   bl1.append(buf, sizeof(buf));
561   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
562   ASSERT_EQ(0, ioctx.snap_create("snap1"));
563   std::vector<snap_t> snaps;
564   EXPECT_EQ(0, ioctx.snap_list(&snaps));
565   EXPECT_EQ(1U, snaps.size());
566   snap_t rid;
567   EXPECT_EQ(0, ioctx.snap_lookup("snap1", &rid));
568   EXPECT_EQ(rid, snaps[0]);
569   EXPECT_EQ(0, ioctx.snap_remove("snap1"));
570 }
571
572 TEST_F(LibRadosSnapshotsEC, SnapRemove) {
573   char buf[bufsize];
574   memset(buf, 0xcc, sizeof(buf));
575   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
576   ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snap1"));
577   rados_snap_t rid;
578   ASSERT_EQ(0, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
579   ASSERT_EQ(-EEXIST, rados_ioctx_snap_create(ioctx, "snap1"));
580   ASSERT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
581   ASSERT_EQ(-ENOENT, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
582 }
583
584 TEST_F(LibRadosSnapshotsECPP, SnapRemovePP) {
585   char buf[bufsize];
586   memset(buf, 0xcc, sizeof(buf));
587   bufferlist bl1;
588   bl1.append(buf, sizeof(buf));
589   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
590   ASSERT_EQ(0, ioctx.snap_create("snap1"));
591   rados_snap_t rid;
592   ASSERT_EQ(0, ioctx.snap_lookup("snap1", &rid));
593   ASSERT_EQ(0, ioctx.snap_remove("snap1"));
594   ASSERT_EQ(-ENOENT, ioctx.snap_lookup("snap1", &rid));
595 }
596
597 TEST_F(LibRadosSnapshotsEC, Rollback) {
598   char buf[bufsize];
599   memset(buf, 0xcc, sizeof(buf));
600   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
601   ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snap1"));
602   char buf2[sizeof(buf)];
603   memset(buf2, 0xdd, sizeof(buf2));
604   EXPECT_EQ(0, rados_write_full(ioctx, "foo", buf2, sizeof(buf2)));
605   EXPECT_EQ(0, rados_ioctx_snap_rollback(ioctx, "foo", "snap1"));
606   char buf3[sizeof(buf)];
607   EXPECT_EQ((int)sizeof(buf3), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
608   EXPECT_EQ(0, memcmp(buf, buf3, sizeof(buf)));
609   EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
610 }
611
612 TEST_F(LibRadosSnapshotsECPP, RollbackPP) {
613   char buf[bufsize];
614   memset(buf, 0xcc, sizeof(buf));
615   bufferlist bl1;
616   bl1.append(buf, sizeof(buf));
617   ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
618   ASSERT_EQ(0, ioctx.snap_create("snap1"));
619   char buf2[sizeof(buf)];
620   memset(buf2, 0xdd, sizeof(buf2));
621   bufferlist bl2;
622   bl2.append(buf2, sizeof(buf2));
623   EXPECT_EQ(0, ioctx.write_full("foo", bl2));
624   EXPECT_EQ(0, ioctx.snap_rollback("foo", "snap1"));
625   bufferlist bl3;
626   EXPECT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
627   EXPECT_EQ(0, memcmp(buf, bl3.c_str(), sizeof(buf)));
628   EXPECT_EQ(0, ioctx.snap_remove("snap1"));
629 }
630
631 TEST_F(LibRadosSnapshotsEC, SnapGetName) {
632   char buf[bufsize];
633   memset(buf, 0xcc, sizeof(buf));
634   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
635   ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snapfoo"));
636   rados_snap_t rid;
637   EXPECT_EQ(0, rados_ioctx_snap_lookup(ioctx, "snapfoo", &rid));
638   EXPECT_EQ(-ENOENT, rados_ioctx_snap_lookup(ioctx, "snapbar", &rid));
639   char name[128];
640   memset(name, 0, sizeof(name));
641   EXPECT_EQ(0, rados_ioctx_snap_get_name(ioctx, rid, name, sizeof(name)));
642   time_t snaptime;
643   EXPECT_EQ(0, rados_ioctx_snap_get_stamp(ioctx, rid, &snaptime));
644   EXPECT_EQ(0, strcmp(name, "snapfoo"));
645   EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snapfoo"));
646 }
647
648 TEST_F(LibRadosSnapshotsECPP, SnapGetNamePP) {
649   char buf[bufsize];
650   memset(buf, 0xcc, sizeof(buf));
651   bufferlist bl;
652   bl.append(buf, sizeof(buf));
653   ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
654   ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
655   rados_snap_t rid;
656   EXPECT_EQ(0, ioctx.snap_lookup("snapfoo", &rid));
657   EXPECT_EQ(-ENOENT, ioctx.snap_lookup("snapbar", &rid));
658   std::string name;
659   EXPECT_EQ(0, ioctx.snap_get_name(rid, &name));
660   time_t snaptime;
661   EXPECT_EQ(0, ioctx.snap_get_stamp(rid, &snaptime));
662   EXPECT_EQ(0, strcmp(name.c_str(), "snapfoo"));
663   EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
664 }
665
666 TEST_F(LibRadosSnapshotsSelfManagedEC, Snap) {
667   std::vector<uint64_t> my_snaps;
668   my_snaps.push_back(-2);
669   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back()));
670   ::std::reverse(my_snaps.begin(), my_snaps.end());
671   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
672                                         &my_snaps[0], my_snaps.size()));
673   ::std::reverse(my_snaps.begin(), my_snaps.end());
674   int bsize = alignment;
675   char *buf = (char *)new char[bsize];
676   memset(buf, 0xcc, bsize);
677   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, bsize, 0));
678
679   my_snaps.push_back(-2);
680   rados_completion_t completion;
681   ASSERT_EQ(0, rados_aio_create_completion(nullptr, nullptr, nullptr,
682                                            &completion));
683   rados_aio_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back(), completion);
684   ASSERT_EQ(0, rados_aio_wait_for_complete(completion));
685   rados_aio_release(completion);
686   ::std::reverse(my_snaps.begin(), my_snaps.end());
687   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
688                                         &my_snaps[0], my_snaps.size()));
689   ::std::reverse(my_snaps.begin(), my_snaps.end());
690   char *buf2 = (char *)new char[bsize];
691   memset(buf2, 0xdd, bsize);
692   ASSERT_EQ(0, rados_write(ioctx, "foo", buf2, bsize, bsize));
693   rados_ioctx_snap_set_read(ioctx, my_snaps[1]-1);
694   char *buf3 = (char *)new char[bsize*2];
695   ASSERT_EQ(-ENOENT, rados_read(ioctx, "foo", buf3, bsize*2, 0));
696
697   rados_ioctx_snap_set_read(ioctx, my_snaps[1]);
698   ASSERT_EQ(bsize, rados_read(ioctx, "foo", buf3, bsize*2, 0));
699   ASSERT_EQ(0, memcmp(buf3, buf, bsize));
700
701   ASSERT_EQ(0, rados_aio_create_completion(nullptr, nullptr, nullptr,
702                                            &completion));
703   rados_aio_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back(), completion);
704   ASSERT_EQ(0, rados_aio_wait_for_complete(completion));
705   rados_aio_release(completion);
706   my_snaps.pop_back();
707   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back()));
708   my_snaps.pop_back();
709   rados_ioctx_snap_set_read(ioctx, LIBRADOS_SNAP_HEAD);
710   ASSERT_EQ(0, rados_remove(ioctx, "foo"));
711   delete[] buf;
712   delete[] buf2;
713   delete[] buf3;
714 }
715
716 TEST_F(LibRadosSnapshotsSelfManagedEC, Rollback) {
717   std::vector<uint64_t> my_snaps;
718   my_snaps.push_back(-2);
719   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back()));
720   ::std::reverse(my_snaps.begin(), my_snaps.end());
721   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
722                                         &my_snaps[0], my_snaps.size()));
723   ::std::reverse(my_snaps.begin(), my_snaps.end());
724   int bsize = alignment;
725   char *buf = (char *)new char[bsize];
726   memset(buf, 0xcc, bsize);
727   ASSERT_EQ(0, rados_write(ioctx, "foo", buf, bsize, 0));
728
729   my_snaps.push_back(-2);
730   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back()));
731   ::std::reverse(my_snaps.begin(), my_snaps.end());
732   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
733                                         &my_snaps[0], my_snaps.size()));
734   ::std::reverse(my_snaps.begin(), my_snaps.end());
735   char *buf2 = (char *)new char[bsize];
736   memset(buf2, 0xdd, bsize);
737
738   ASSERT_EQ(0, rados_write(ioctx, "foo", buf2, bsize, bsize));
739   rados_ioctx_selfmanaged_snap_rollback(ioctx, "foo", my_snaps[1]);
740   char *buf3 = (char *)new char[bsize*2];
741   ASSERT_EQ(bsize, rados_read(ioctx, "foo", buf3, bsize*2, 0));
742   ASSERT_EQ(0, memcmp(buf3, buf, bsize));
743
744   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back()));
745   my_snaps.pop_back();
746   ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back()));
747   my_snaps.pop_back();
748   ASSERT_EQ(0, rados_remove(ioctx, "foo"));
749   delete[] buf;
750   delete[] buf2;
751   delete[] buf3;
752 }
753
754 TEST_F(LibRadosSnapshotsSelfManagedECPP, SnapPP) {
755   std::vector<uint64_t> my_snaps;
756   my_snaps.push_back(-2);
757   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
758   ::std::reverse(my_snaps.begin(), my_snaps.end());
759   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
760   ::std::reverse(my_snaps.begin(), my_snaps.end());
761   int bsize = alignment;
762   char *buf = (char *)new char[bsize];
763   memset(buf, 0xcc, bsize);
764   bufferlist bl1;
765   bl1.append(buf, bsize);
766   ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
767
768   my_snaps.push_back(-2);
769   librados::AioCompletion *completion = cluster.aio_create_completion();
770   ioctx.aio_selfmanaged_snap_create(&my_snaps.back(), completion);
771   ASSERT_EQ(0, completion->wait_for_complete());
772   completion->release();
773   ::std::reverse(my_snaps.begin(), my_snaps.end());
774   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
775   ::std::reverse(my_snaps.begin(), my_snaps.end());
776   char *buf2 = (char *)new char[bsize];
777   memset(buf2, 0xdd, bsize);
778   bufferlist bl2;
779   bl2.append(buf2, bsize);
780   // Add another aligned buffer
781   ASSERT_EQ(0, ioctx.write("foo", bl2, bsize, bsize));
782
783   ioctx.snap_set_read(my_snaps[1]);
784   bufferlist bl3;
785   ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize*3, 0));
786   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
787
788   completion = cluster.aio_create_completion();
789   ioctx.aio_selfmanaged_snap_remove(my_snaps.back(), completion);
790   ASSERT_EQ(0, completion->wait_for_complete());
791   completion->release();
792   my_snaps.pop_back();
793   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
794   my_snaps.pop_back();
795   ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
796   ASSERT_EQ(0, ioctx.remove("foo"));
797   delete[] buf;
798   delete[] buf2;
799 }
800
801 TEST_F(LibRadosSnapshotsSelfManagedECPP, RollbackPP) {
802   std::vector<uint64_t> my_snaps;
803   IoCtx readioctx;
804   ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), readioctx));
805   readioctx.set_namespace(nspace);
806   readioctx.snap_set_read(LIBRADOS_SNAP_DIR);
807
808   my_snaps.push_back(-2);
809   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
810   ::std::reverse(my_snaps.begin(), my_snaps.end());
811   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
812   ::std::reverse(my_snaps.begin(), my_snaps.end());
813   int bsize = alignment;
814   char *buf = (char *)new char[bsize];
815   memset(buf, 0xcc, bsize);
816   bufferlist bl1;
817   bl1.append(buf, bsize);
818   //Write 3 consecutive buffers
819   ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
820   ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, bsize));
821   ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, bsize*2));
822
823   snap_set_t ss;
824
825   snap_t head = SNAP_HEAD;
826   ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
827   ASSERT_EQ(1u, ss.clones.size());
828   ASSERT_EQ(head, ss.clones[0].cloneid);
829   ASSERT_EQ(0u, ss.clones[0].snaps.size());
830   ASSERT_EQ(0u, ss.clones[0].overlap.size());
831   ASSERT_EQ((unsigned)(bsize*3), ss.clones[0].size);
832
833   my_snaps.push_back(-2);
834   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
835   ::std::reverse(my_snaps.begin(), my_snaps.end());
836   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
837   ::std::reverse(my_snaps.begin(), my_snaps.end());
838   char *buf2 = (char *)new char[bsize];
839   memset(buf2, 0xdd, bsize);
840   bufferlist bl2;
841   bl2.append(buf2, bsize);
842   //Change the middle buffer
843   //ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), bufsize));
844   //Add another after
845   ASSERT_EQ(0, ioctx.write("foo", bl2, bsize, bsize*3));
846
847   ASSERT_EQ(-EINVAL, ioctx.list_snaps("foo", &ss));
848   ObjectReadOperation o;
849   o.list_snaps(&ss, NULL);
850   ASSERT_EQ(-EINVAL, ioctx.operate("foo", &o, NULL));
851
852   ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
853   ASSERT_EQ(2u, ss.clones.size());
854   ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
855   ASSERT_EQ(1u, ss.clones[0].snaps.size());
856   ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
857   ASSERT_EQ(1u, ss.clones[0].overlap.size());
858   ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
859   ASSERT_EQ((unsigned)bsize*3, ss.clones[0].overlap[0].second);
860   ASSERT_EQ((unsigned)bsize*3, ss.clones[0].size);
861   ASSERT_EQ(head, ss.clones[1].cloneid);
862   ASSERT_EQ(0u, ss.clones[1].snaps.size());
863   ASSERT_EQ(0u, ss.clones[1].overlap.size());
864   ASSERT_EQ((unsigned)bsize*4, ss.clones[1].size);
865
866   ioctx.selfmanaged_snap_rollback("foo", my_snaps[1]);
867
868   bufferlist bl3;
869   ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, 0));
870   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
871   ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, bsize));
872   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
873   ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, bsize*2));
874   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
875   ASSERT_EQ(0, ioctx.read("foo", bl3, bsize, bsize*3));
876
877   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
878   my_snaps.pop_back();
879   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
880   my_snaps.pop_back();
881   readioctx.close();
882
883   delete[] buf;
884   delete[] buf2;
885 }
886
887 TEST_F(LibRadosSnapshotsSelfManagedECPP, Bug11677) {
888   std::vector<uint64_t> my_snaps;
889   my_snaps.push_back(-2);
890   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
891   ::std::reverse(my_snaps.begin(), my_snaps.end());
892   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
893   ::std::reverse(my_snaps.begin(), my_snaps.end());
894
895   int bsize = alignment;
896   char *buf = (char *)new char[bsize];
897   memset(buf, 0xcc, bsize);
898   bufferlist bl1;
899   bl1.append(buf, bsize);
900   ASSERT_EQ(0, ioctx.write("foo", bl1, bsize, 0));
901
902   my_snaps.push_back(-2);
903   ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
904   ::std::reverse(my_snaps.begin(), my_snaps.end());
905   ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
906   ::std::reverse(my_snaps.begin(), my_snaps.end());
907
908   std::unique_ptr<librados::ObjectWriteOperation> op(new librados::ObjectWriteOperation());
909   op->assert_exists();
910   op->remove();
911   ASSERT_EQ(0, ioctx.operate("foo", op.get()));
912
913   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
914   my_snaps.pop_back();
915   ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
916   my_snaps.pop_back();
917   ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
918   delete[] buf;
919 }
920