Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / cls_refcount / test_cls_refcount.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 "include/types.h"
5 #include "cls/refcount/cls_refcount_client.h"
6
7 #include "gtest/gtest.h"
8 #include "test/librados/test.h"
9
10 #include <errno.h>
11 #include <string>
12 #include <vector>
13
14 static librados::ObjectWriteOperation *new_op() {
15   return new librados::ObjectWriteOperation();
16 }
17
18 TEST(cls_rgw, test_implicit) /* test refcount using implicit referencing of newly created objects */
19 {
20   librados::Rados rados;
21   librados::IoCtx ioctx;
22   string pool_name = get_temp_pool_name();
23
24   /* create pool */
25   ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
26   ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
27
28   /* add chains */
29   string oid = "obj";
30   string oldtag = "oldtag";
31   string newtag = "newtag";
32
33
34   /* get on a missing object will fail */
35   librados::ObjectWriteOperation *op = new_op();
36   cls_refcount_get(*op, newtag, true);
37   ASSERT_EQ(-ENOENT, ioctx.operate(oid, op));
38   delete op;
39
40   /* create object */
41   ASSERT_EQ(0, ioctx.create(oid, true));
42
43   /* read reference, should return a single wildcard entry */
44
45   list<string> refs;
46
47   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true));
48   ASSERT_EQ(1, (int)refs.size());
49
50   string wildcard_tag;
51   string tag = refs.front();
52
53   ASSERT_EQ(wildcard_tag, tag);
54
55   /* take another reference, verify */
56   op = new_op();
57   cls_refcount_get(*op, newtag, true);
58   ASSERT_EQ(0, ioctx.operate(oid, op));
59
60   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true));
61   ASSERT_EQ(2, (int)refs.size());
62
63   map<string, bool> refs_map;
64   for (list<string>::iterator iter = refs.begin(); iter != refs.end(); ++iter) {
65     refs_map[*iter] = true;
66   }
67
68   ASSERT_EQ(1, (int)refs_map.count(wildcard_tag));
69   ASSERT_EQ(1, (int)refs_map.count(newtag));
70
71   delete op;
72
73   /* drop reference to oldtag */
74
75   op = new_op();
76   cls_refcount_put(*op, oldtag, true);
77   ASSERT_EQ(0, ioctx.operate(oid, op));
78
79   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true));
80   ASSERT_EQ(1, (int)refs.size());
81
82   tag = refs.front();
83   ASSERT_EQ(newtag, tag);
84
85   delete op;
86
87   /* drop oldtag reference again, op should return success, wouldn't do anything */
88
89   op = new_op();
90   cls_refcount_put(*op, oldtag, true);
91   ASSERT_EQ(0, ioctx.operate(oid, op));
92
93   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true));
94   ASSERT_EQ(1, (int)refs.size());
95
96   tag = refs.front();
97   ASSERT_EQ(newtag, tag);
98
99   delete op;
100
101   /* drop newtag reference, make sure object removed */
102   op = new_op();
103   cls_refcount_put(*op, newtag, true);
104   ASSERT_EQ(0, ioctx.operate(oid, op));
105
106   ASSERT_EQ(-ENOENT, ioctx.stat(oid, NULL, NULL));
107
108   delete op;
109
110   /* remove pool */
111   ioctx.close();
112   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
113 }
114
115 /*
116  * similar to test_implicit, just changes the order of the tags removal
117  * see issue #20107
118  */
119 TEST(cls_rgw, test_implicit_idempotent) /* test refcount using implicit referencing of newly created objects */
120 {
121   librados::Rados rados;
122   librados::IoCtx ioctx;
123   string pool_name = get_temp_pool_name();
124
125   /* create pool */
126   ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
127   ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
128
129   /* add chains */
130   string oid = "obj";
131   string oldtag = "oldtag";
132   string newtag = "newtag";
133
134
135   /* get on a missing object will fail */
136   librados::ObjectWriteOperation *op = new_op();
137   cls_refcount_get(*op, newtag, true);
138   ASSERT_EQ(-ENOENT, ioctx.operate(oid, op));
139   delete op;
140
141   /* create object */
142   ASSERT_EQ(0, ioctx.create(oid, true));
143
144   /* read reference, should return a single wildcard entry */
145
146   list<string> refs;
147
148   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true));
149   ASSERT_EQ(1, (int)refs.size());
150
151   string wildcard_tag;
152   string tag = refs.front();
153
154   ASSERT_EQ(wildcard_tag, tag);
155
156   /* take another reference, verify */
157   op = new_op();
158   cls_refcount_get(*op, newtag, true);
159   ASSERT_EQ(0, ioctx.operate(oid, op));
160
161   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true));
162   ASSERT_EQ(2, (int)refs.size());
163
164   map<string, bool> refs_map;
165   for (list<string>::iterator iter = refs.begin(); iter != refs.end(); ++iter) {
166     refs_map[*iter] = true;
167   }
168
169   ASSERT_EQ(1, (int)refs_map.count(wildcard_tag));
170   ASSERT_EQ(1, (int)refs_map.count(newtag));
171
172   delete op;
173
174   /* drop reference to newtag */
175
176   op = new_op();
177   cls_refcount_put(*op, newtag, true);
178   ASSERT_EQ(0, ioctx.operate(oid, op));
179
180   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true));
181   ASSERT_EQ(1, (int)refs.size());
182
183   tag = refs.front();
184   ASSERT_EQ(string(), tag);
185
186   delete op;
187
188   /* drop newtag reference again, op should return success, wouldn't do anything */
189
190   op = new_op();
191   cls_refcount_put(*op, newtag, true);
192   ASSERT_EQ(0, ioctx.operate(oid, op));
193
194   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true));
195   ASSERT_EQ(1, (int)refs.size());
196
197   tag = refs.front();
198   ASSERT_EQ(string(), tag);
199
200   delete op;
201
202   /* drop oldtag reference, make sure object removed */
203   op = new_op();
204   cls_refcount_put(*op, oldtag, true);
205   ASSERT_EQ(0, ioctx.operate(oid, op));
206
207   ASSERT_EQ(-ENOENT, ioctx.stat(oid, NULL, NULL));
208
209   delete op;
210
211   /* remove pool */
212   ioctx.close();
213   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
214 }
215
216
217 TEST(cls_rgw, test_put_snap) {
218   librados::Rados rados;
219   librados::IoCtx ioctx;
220   string pool_name = get_temp_pool_name();
221
222   /* create pool */
223   ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
224   ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
225
226   bufferlist bl;
227   bl.append("hi there");
228   ASSERT_EQ(0, ioctx.write("foo", bl, bl.length(), 0));
229   ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
230   ASSERT_EQ(0, ioctx.remove("foo"));
231
232   sleep(2);
233
234   ASSERT_EQ(0, ioctx.snap_create("snapbar"));
235
236   librados::ObjectWriteOperation *op = new_op();
237   cls_refcount_put(*op, "notag", true);
238   ASSERT_EQ(-ENOENT, ioctx.operate("foo", op));
239
240   EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
241   EXPECT_EQ(0, ioctx.snap_remove("snapbar"));
242
243   delete op;
244
245   /* remove pool */
246   ioctx.close();
247   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
248 }
249
250 TEST(cls_rgw, test_explicit) /* test refcount using implicit referencing of newly created objects */
251 {
252   librados::Rados rados;
253   librados::IoCtx ioctx;
254   string pool_name = get_temp_pool_name();
255
256   /* create pool */
257   ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
258   ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
259
260   /* add chains */
261   string oid = "obj";
262
263
264   /* create object */
265
266   ASSERT_EQ(0, ioctx.create(oid, true));
267
268   /* read reference, should return a single wildcard entry */
269
270   list<string> refs;
271
272   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs));
273   ASSERT_EQ(0, (int)refs.size());
274
275
276   /* take first reference, verify */
277
278   string newtag = "newtag";
279
280   librados::ObjectWriteOperation *op = new_op();
281   cls_refcount_get(*op, newtag);
282   ASSERT_EQ(0, ioctx.operate(oid, op));
283
284   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs));
285   ASSERT_EQ(1, (int)refs.size());
286
287   map<string, bool> refs_map;
288   for (list<string>::iterator iter = refs.begin(); iter != refs.end(); ++iter) {
289     refs_map[*iter] = true;
290   }
291
292   ASSERT_EQ(1, (int)refs_map.count(newtag));
293
294   delete op;
295
296   /* try to drop reference to unexisting tag */
297
298   string nosuchtag = "nosuchtag";
299
300   op = new_op();
301   cls_refcount_put(*op, nosuchtag);
302   ASSERT_EQ(0, ioctx.operate(oid, op));
303
304   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs));
305   ASSERT_EQ(1, (int)refs.size());
306
307   string tag = refs.front();
308   ASSERT_EQ(newtag, tag);
309
310   delete op;
311
312   /* drop newtag reference, make sure object removed */
313   op = new_op();
314   cls_refcount_put(*op, newtag);
315   ASSERT_EQ(0, ioctx.operate(oid, op));
316
317   ASSERT_EQ(-ENOENT, ioctx.stat(oid, NULL, NULL));
318
319   delete op;
320
321   /* remove pool */
322   ioctx.close();
323   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
324 }
325
326 TEST(cls_rgw, set) /* test refcount using implicit referencing of newly created objects */
327 {
328   librados::Rados rados;
329   librados::IoCtx ioctx;
330   string pool_name = get_temp_pool_name();
331
332   /* create pool */
333   ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
334   ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
335
336   /* add chains */
337   string oid = "obj";
338
339
340   /* create object */
341
342   ASSERT_EQ(0, ioctx.create(oid, true));
343
344   /* read reference, should return a single wildcard entry */
345
346   list<string> tag_refs, refs;
347
348 #define TAGS_NUM 5
349   string tags[TAGS_NUM];
350
351   char buf[16];
352   for (int i = 0; i < TAGS_NUM; i++) {
353     snprintf(buf, sizeof(buf), "tag%d", i);
354     tags[i] = buf;
355     tag_refs.push_back(tags[i]);
356   }
357
358   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs));
359   ASSERT_EQ(0, (int)refs.size());
360
361   /* set reference list, verify */
362
363   librados::ObjectWriteOperation *op = new_op();
364   cls_refcount_set(*op, tag_refs);
365   ASSERT_EQ(0, ioctx.operate(oid, op));
366
367   refs.clear();
368   ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs));
369   ASSERT_EQ(TAGS_NUM, (int)refs.size());
370
371   map<string, bool> refs_map;
372   for (list<string>::iterator iter = refs.begin(); iter != refs.end(); ++iter) {
373     refs_map[*iter] = true;
374   }
375
376   for (int i = 0; i < TAGS_NUM; i++) {
377     ASSERT_EQ(1, (int)refs_map.count(tags[i]));
378   }
379
380   delete op;
381
382   /* remove all refs */
383
384   for (int i = 0; i < TAGS_NUM; i++) {
385     op = new_op();
386     cls_refcount_put(*op, tags[i]);
387     ASSERT_EQ(0, ioctx.operate(oid, op));
388     delete op;
389   }
390
391   ASSERT_EQ(-ENOENT, ioctx.stat(oid, NULL, NULL));
392
393   /* remove pool */
394   ioctx.close();
395   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
396 }