2 * Ceph - scalable distributed file system
4 * Copyright (C) 2015 CERN
6 * Author: Joaquim Rocha <joaquim.rocha@cern.ch>
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.
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"
26 using namespace librados;
28 TEST(ClsNumOps, Add) {
30 std::string pool_name = get_temp_pool_name();
31 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
33 cluster.ioctx_create(pool_name.c_str(), ioctx);
35 // exec numops add method with an empty bufferlist
39 ASSERT_EQ(-EINVAL, ioctx.exec("myobject", "numops", "add", in, out));
41 // add a number to a non-existing key
43 std::string key = "my-key";
44 double value_in = 0.5;
46 std::stringstream stream;
49 ASSERT_EQ(0, rados::cls::numops::add(&ioctx, "myobject", key, value_in));
51 // check that the omap entry was set and the value matches
53 std::set<std::string> keys;
54 std::map<std::string, bufferlist> omap;
57 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
59 std::map<std::string, bufferlist>::iterator it = omap.find(key);
61 ASSERT_NE(omap.end(), it);
63 bufferlist bl = (*it).second;
64 std::string value_out(bl.c_str(), bl.length());
66 EXPECT_EQ(stream.str(), value_out);
68 // add another value to the existing one
70 double new_value_in = 3.001;
72 ASSERT_EQ(0, rados::cls::numops::add(&ioctx, "myobject", key, new_value_in));
74 // check that the omap entry's value matches
78 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
82 ASSERT_NE(omap.end(), it);
85 value_out.assign(bl.c_str(), bl.length());
88 stream << (value_in + new_value_in);
90 EXPECT_EQ(stream.str(), value_out);
92 // set the omap entry with some non-numeric value
96 std::string non_numeric_value("some-non-numeric-text");
97 omap[key].append(non_numeric_value);
99 ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
101 // check that adding a number does not succeed
105 ASSERT_EQ(-EBADMSG, rados::cls::numops::add(&ioctx, "myobject", key, 2.0));
107 // check that the omap entry was not changed
109 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
113 ASSERT_NE(omap.end(), it);
116 value_out.assign(bl.c_str(), bl.length());
118 EXPECT_EQ(non_numeric_value, value_out);
120 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
123 TEST(ClsNumOps, Sub) {
125 std::string pool_name = get_temp_pool_name();
126 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
128 cluster.ioctx_create(pool_name.c_str(), ioctx);
130 // subtract a number from a non-existing key
132 std::string key = "my-key";
133 double value_in = 0.5;
135 std::stringstream stream;
138 ASSERT_EQ(0, rados::cls::numops::sub(&ioctx, "myobject", key, value_in));
140 // check that the omap entry was set and the value matches
142 std::set<std::string> keys;
143 std::map<std::string, bufferlist> omap;
146 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
148 std::map<std::string, bufferlist>::iterator it = omap.find(key);
150 ASSERT_NE(omap.end(), it);
152 bufferlist bl = (*it).second;
153 std::string value_out(bl.c_str(), bl.length());
155 EXPECT_EQ("-" + stream.str(), value_out);
157 // subtract another value to the existing one
159 double new_value_in = 3.001;
161 ASSERT_EQ(0, rados::cls::numops::sub(&ioctx, "myobject", key, new_value_in));
163 // check that the omap entry's value matches
167 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
171 ASSERT_NE(omap.end(), it);
174 value_out.assign(bl.c_str(), bl.length());
177 stream << -(value_in + new_value_in);
179 EXPECT_EQ(stream.str(), value_out);
181 // set the omap entry with some non-numeric value
185 std::string non_numeric_value("some-non-numeric-text");
186 omap[key].append(non_numeric_value);
188 ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
190 // check that subtracting a number does not succeed
194 ASSERT_EQ(-EBADMSG, rados::cls::numops::sub(&ioctx, "myobject", key, 2.0));
196 // check that the omap entry was not changed
198 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
202 ASSERT_NE(omap.end(), it);
205 value_out.assign(bl.c_str(), bl.length());
207 EXPECT_EQ(non_numeric_value, value_out);
209 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
212 TEST(ClsNumOps, Mul) {
214 std::string pool_name = get_temp_pool_name();
215 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
217 cluster.ioctx_create(pool_name.c_str(), ioctx);
219 // exec numops mul method with an empty bufferlist
223 ASSERT_EQ(-EINVAL, ioctx.exec("myobject", "numops", "mul", in, out));
225 // multiply a number to a non-existing key
227 std::string key = "my-key";
228 double value_in = 0.5;
230 std::stringstream stream;
233 ASSERT_EQ(0, rados::cls::numops::mul(&ioctx, "myobject", key, value_in));
235 // check that the omap entry was set and the value is zero
237 std::set<std::string> keys;
238 std::map<std::string, bufferlist> omap;
241 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
243 std::map<std::string, bufferlist>::iterator it = omap.find(key);
245 ASSERT_NE(omap.end(), it);
247 bufferlist bl = (*it).second;
248 std::string value_out(bl.c_str(), bl.length());
250 EXPECT_EQ("0", value_out);
252 // set a non-zero value so we can effectively test multiplications
256 omap[key].append(stream.str());
258 ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
260 // multiply another value to the existing one
262 double new_value_in = 3.001;
264 ASSERT_EQ(0, rados::cls::numops::mul(&ioctx, "myobject", key, new_value_in));
266 // check that the omap entry's value matches
270 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
274 ASSERT_NE(omap.end(), it);
277 value_out.assign(bl.c_str(), bl.length());
280 stream << (value_in * new_value_in);
282 EXPECT_EQ(stream.str(), value_out);
284 // set the omap entry with some non-numeric value
288 std::string non_numeric_value("some-non-numeric-text");
289 omap[key].append(non_numeric_value);
291 ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
293 // check that adding a number does not succeed
295 ASSERT_EQ(-EBADMSG, rados::cls::numops::mul(&ioctx, "myobject", key, 2.0));
297 // check that the omap entry was not changed
301 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
305 ASSERT_NE(omap.end(), it);
308 value_out.assign(bl.c_str(), bl.length());
310 EXPECT_EQ(non_numeric_value, value_out);
312 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
315 TEST(ClsNumOps, Div) {
317 std::string pool_name = get_temp_pool_name();
318 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
320 cluster.ioctx_create(pool_name.c_str(), ioctx);
322 // divide a non-existing key by a number
324 std::string key = "my-key";
325 double value_in = 0.5;
327 std::stringstream stream;
330 ASSERT_EQ(0, rados::cls::numops::div(&ioctx, "myobject", key, value_in));
332 // check that the omap entry was set and the value is zero
334 std::set<std::string> keys;
335 std::map<std::string, bufferlist> omap;
338 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
340 std::map<std::string, bufferlist>::iterator it = omap.find(key);
342 ASSERT_NE(omap.end(), it);
344 bufferlist bl = (*it).second;
345 std::string value_out(bl.c_str(), bl.length());
347 EXPECT_EQ("0", value_out);
349 // check that division by zero is not allowed
351 ASSERT_EQ(-EINVAL, rados::cls::numops::div(&ioctx, "myobject", key, 0));
353 // set a non-zero value so we can effectively test divisions
357 omap[key].append(stream.str());
359 ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
361 // divide another value to the existing one
363 double new_value_in = 3.001;
365 ASSERT_EQ(0, rados::cls::numops::div(&ioctx, "myobject", key, new_value_in));
367 // check that the omap entry's value matches
371 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
375 ASSERT_NE(omap.end(), it);
378 value_out.assign(bl.c_str(), bl.length());
381 stream << (value_in / new_value_in);
383 EXPECT_EQ(stream.str(), value_out);
387 // set the omap entry with some non-numeric value
389 std::string non_numeric_value("some-non-numeric-text");
390 omap[key].append(non_numeric_value);
392 ASSERT_EQ(0, ioctx.omap_set("myobject", omap));
394 // check that adding a number does not succeed
396 ASSERT_EQ(-EBADMSG, rados::cls::numops::div(&ioctx, "myobject", key, 2.0));
398 // check that the omap entry was not changed
402 ASSERT_EQ(0, ioctx.omap_get_vals_by_keys("myobject", keys, &omap));
406 ASSERT_NE(omap.end(), it);
409 value_out.assign(bl.c_str(), bl.length());
411 EXPECT_EQ(non_numeric_value, value_out);
413 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));