Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / cls_numops / test_cls_numops.cc
1 /*
2  * Ceph - scalable distributed file system
3  *
4  * Copyright (C) 2015 CERN
5  *
6  * Author: Joaquim Rocha <joaquim.rocha@cern.ch>
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2.1 of the License, or (at your option) any later version.
12  *
13  */
14
15 #include <iostream>
16 #include <errno.h>
17 #include <set>
18 #include <sstream>
19 #include <string>
20
21 #include "cls/numops/cls_numops_client.h"
22 #include "gtest/gtest.h"
23 #include "include/rados/librados.hpp"
24 #include "test/librados/test.h"
25
26 using namespace librados;
27
28 TEST(ClsNumOps, Add) {
29   Rados cluster;
30   std::string pool_name = get_temp_pool_name();
31   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
32   IoCtx ioctx;
33   cluster.ioctx_create(pool_name.c_str(), ioctx);
34
35   // exec numops add method with an empty bufferlist
36
37   bufferlist in, out;
38
39   ASSERT_EQ(-EINVAL, ioctx.exec("myobject", "numops", "add", in, out));
40
41   // add a number to a non-existing key
42
43   std::string key = "my-key";
44   double value_in = 0.5;
45
46   std::stringstream stream;
47   stream << value_in;
48
49   ASSERT_EQ(0, rados::cls::numops::add(&ioctx, "myobject", key, value_in));
50
51   // check that the omap entry was set and the value matches
52
53   std::set<std::string> keys;
54   std::map<std::string, bufferlist> omap;
55   keys.insert(key);
56
57   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
58
59   std::map<std::string, bufferlist>::iterator it = omap.find(key);
60
61   ASSERT_NE(omap.end(), it);
62
63   bufferlist bl = (*it).second;
64   std::string value_out(bl.c_str(), bl.length());
65
66   EXPECT_EQ(stream.str(), value_out);
67
68   // add another value to the existing one
69
70   double new_value_in = 3.001;
71
72   ASSERT_EQ(0, rados::cls::numops::add(&ioctx, "myobject", key, new_value_in));
73
74   // check that the omap entry's value matches
75
76   omap.clear();
77
78   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
79
80   it = omap.find(key);
81
82   ASSERT_NE(omap.end(), it);
83
84   bl = (*it).second;
85   value_out.assign(bl.c_str(), bl.length());
86
87   stream.str("");
88   stream << (value_in + new_value_in);
89
90   EXPECT_EQ(stream.str(), value_out);
91
92   // set the omap entry with some non-numeric value
93
94   omap.clear();
95
96   std::string non_numeric_value("some-non-numeric-text");
97   omap[key].append(non_numeric_value);
98
99   ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
100
101   // check that adding a number does not succeed
102
103   omap.clear();
104
105   ASSERT_EQ(-EBADMSG, rados::cls::numops::add(&ioctx, "myobject", key, 2.0));
106
107   // check that the omap entry was not changed
108
109   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
110
111   it = omap.find(key);
112
113   ASSERT_NE(omap.end(), it);
114
115   bl = (*it).second;
116   value_out.assign(bl.c_str(), bl.length());
117
118   EXPECT_EQ(non_numeric_value, value_out);
119
120   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
121 }
122
123 TEST(ClsNumOps, Sub) {
124   Rados cluster;
125   std::string pool_name = get_temp_pool_name();
126   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
127   IoCtx ioctx;
128   cluster.ioctx_create(pool_name.c_str(), ioctx);
129
130   // subtract a number from a non-existing key
131
132   std::string key = "my-key";
133   double value_in = 0.5;
134
135   std::stringstream stream;
136   stream << value_in;
137
138   ASSERT_EQ(0, rados::cls::numops::sub(&ioctx, "myobject", key, value_in));
139
140   // check that the omap entry was set and the value matches
141
142   std::set<std::string> keys;
143   std::map<std::string, bufferlist> omap;
144   keys.insert(key);
145
146   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
147
148   std::map<std::string, bufferlist>::iterator it = omap.find(key);
149
150   ASSERT_NE(omap.end(), it);
151
152   bufferlist bl = (*it).second;
153   std::string value_out(bl.c_str(), bl.length());
154
155   EXPECT_EQ("-" + stream.str(), value_out);
156
157   // subtract another value to the existing one
158
159   double new_value_in = 3.001;
160
161   ASSERT_EQ(0, rados::cls::numops::sub(&ioctx, "myobject", key, new_value_in));
162
163   // check that the omap entry's value matches
164
165   omap.clear();
166
167   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
168
169   it = omap.find(key);
170
171   ASSERT_NE(omap.end(), it);
172
173   bl = (*it).second;
174   value_out.assign(bl.c_str(), bl.length());
175
176   stream.str("");
177   stream << -(value_in + new_value_in);
178
179   EXPECT_EQ(stream.str(), value_out);
180
181   // set the omap entry with some non-numeric value
182
183   omap.clear();
184
185   std::string non_numeric_value("some-non-numeric-text");
186   omap[key].append(non_numeric_value);
187
188   ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
189
190   // check that subtracting a number does not succeed
191
192   omap.clear();
193
194   ASSERT_EQ(-EBADMSG, rados::cls::numops::sub(&ioctx, "myobject", key, 2.0));
195
196   // check that the omap entry was not changed
197
198   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
199
200   it = omap.find(key);
201
202   ASSERT_NE(omap.end(), it);
203
204   bl = (*it).second;
205   value_out.assign(bl.c_str(), bl.length());
206
207   EXPECT_EQ(non_numeric_value, value_out);
208
209   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
210 }
211
212 TEST(ClsNumOps, Mul) {
213   Rados cluster;
214   std::string pool_name = get_temp_pool_name();
215   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
216   IoCtx ioctx;
217   cluster.ioctx_create(pool_name.c_str(), ioctx);
218
219   // exec numops mul method with an empty bufferlist
220
221   bufferlist in, out;
222
223   ASSERT_EQ(-EINVAL, ioctx.exec("myobject", "numops", "mul", in, out));
224
225   // multiply a number to a non-existing key
226
227   std::string key = "my-key";
228   double value_in = 0.5;
229
230   std::stringstream stream;
231   stream << value_in;
232
233   ASSERT_EQ(0, rados::cls::numops::mul(&ioctx, "myobject", key, value_in));
234
235   // check that the omap entry was set and the value is zero
236
237   std::set<std::string> keys;
238   std::map<std::string, bufferlist> omap;
239   keys.insert(key);
240
241   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
242
243   std::map<std::string, bufferlist>::iterator it = omap.find(key);
244
245   ASSERT_NE(omap.end(), it);
246
247   bufferlist bl = (*it).second;
248   std::string value_out(bl.c_str(), bl.length());
249
250   EXPECT_EQ("0", value_out);
251
252   // set a non-zero value so we can effectively test multiplications
253
254   omap.clear();
255
256   omap[key].append(stream.str());
257
258   ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
259
260   // multiply another value to the existing one
261
262   double new_value_in = 3.001;
263
264   ASSERT_EQ(0, rados::cls::numops::mul(&ioctx, "myobject", key, new_value_in));
265
266   // check that the omap entry's value matches
267
268   omap.clear();
269
270   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
271
272   it = omap.find(key);
273
274   ASSERT_NE(omap.end(), it);
275
276   bl = (*it).second;
277   value_out.assign(bl.c_str(), bl.length());
278
279   stream.str("");
280   stream << (value_in * new_value_in);
281
282   EXPECT_EQ(stream.str(), value_out);
283
284   // set the omap entry with some non-numeric value
285
286   omap.clear();
287
288   std::string non_numeric_value("some-non-numeric-text");
289   omap[key].append(non_numeric_value);
290
291   ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
292
293   // check that adding a number does not succeed
294
295   ASSERT_EQ(-EBADMSG, rados::cls::numops::mul(&ioctx, "myobject", key, 2.0));
296
297   // check that the omap entry was not changed
298
299   omap.clear();
300
301   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
302
303   it = omap.find(key);
304
305   ASSERT_NE(omap.end(), it);
306
307   bl = (*it).second;
308   value_out.assign(bl.c_str(), bl.length());
309
310   EXPECT_EQ(non_numeric_value, value_out);
311
312   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
313 }
314
315 TEST(ClsNumOps, Div) {
316   Rados cluster;
317   std::string pool_name = get_temp_pool_name();
318   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
319   IoCtx ioctx;
320   cluster.ioctx_create(pool_name.c_str(), ioctx);
321
322   // divide a non-existing key by a number
323
324   std::string key = "my-key";
325   double value_in = 0.5;
326
327   std::stringstream stream;
328   stream << value_in;
329
330   ASSERT_EQ(0, rados::cls::numops::div(&ioctx, "myobject", key, value_in));
331
332   // check that the omap entry was set and the value is zero
333
334   std::set<std::string> keys;
335   std::map<std::string, bufferlist> omap;
336   keys.insert(key);
337
338   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
339
340   std::map<std::string, bufferlist>::iterator it = omap.find(key);
341
342   ASSERT_NE(omap.end(), it);
343
344   bufferlist bl = (*it).second;
345   std::string value_out(bl.c_str(), bl.length());
346
347   EXPECT_EQ("0", value_out);
348
349   // check that division by zero is not allowed
350
351   ASSERT_EQ(-EINVAL, rados::cls::numops::div(&ioctx, "myobject", key, 0));
352
353   // set a non-zero value so we can effectively test divisions
354
355   omap.clear();
356
357   omap[key].append(stream.str());
358
359   ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
360
361   // divide another value to the existing one
362
363   double new_value_in = 3.001;
364
365   ASSERT_EQ(0, rados::cls::numops::div(&ioctx, "myobject", key, new_value_in));
366
367   // check that the omap entry's value matches
368
369   omap.clear();
370
371   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
372
373   it = omap.find(key);
374
375   ASSERT_NE(omap.end(), it);
376
377   bl = (*it).second;
378   value_out.assign(bl.c_str(), bl.length());
379
380   stream.str("");
381   stream << (value_in / new_value_in);
382
383   EXPECT_EQ(stream.str(), value_out);
384
385   omap.clear();
386
387   // set the omap entry with some non-numeric value
388
389   std::string non_numeric_value("some-non-numeric-text");
390   omap[key].append(non_numeric_value);
391
392   ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
393
394   // check that adding a number does not succeed
395
396   ASSERT_EQ(-EBADMSG, rados::cls::numops::div(&ioctx, "myobject", key, 2.0));
397
398   // check that the omap entry was not changed
399
400   omap.clear();
401
402   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
403
404   it = omap.find(key);
405
406   ASSERT_NE(omap.end(), it);
407
408   bl = (*it).second;
409   value_out.assign(bl.c_str(), bl.length());
410
411   EXPECT_EQ(non_numeric_value, value_out);
412
413   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
414 }