Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librados / c_read_operations.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // Tests for the C API coverage of atomic read operations
3
4 #include <errno.h>
5 #include <string>
6
7 #include "include/err.h"
8 #include "include/rados/librados.h"
9 #include "test/librados/test.h"
10 #include "test/librados/TestCase.h"
11
12 const char *data = "testdata";
13 const char *obj = "testobj";
14 const size_t len = strlen(data);
15
16 class CReadOpsTest : public RadosTest {
17 protected:
18   void write_object() {
19     // Create an object and write to it
20     ASSERT_EQ(0, rados_write(ioctx, obj, data, len, 0));
21   }
22   void remove_object() {
23     ASSERT_EQ(0, rados_remove(ioctx, obj));
24   }
25   int cmp_xattr(const char *xattr, const char *value, size_t value_len,
26                 uint8_t cmp_op)
27   {
28     rados_read_op_t op = rados_create_read_op();
29     rados_read_op_cmpxattr(op, xattr, cmp_op, value, value_len);
30     int r = rados_read_op_operate(op, ioctx, obj, 0);
31     rados_release_read_op(op);
32     return r;
33   }
34
35   void fetch_and_verify_omap_vals(char const* const* keys,
36                                   char const* const* vals,
37                                   const size_t *lens,
38                                   size_t len)
39   {
40     rados_omap_iter_t iter_vals, iter_keys, iter_vals_by_key;
41     int r_vals, r_keys, r_vals_by_key;
42     rados_read_op_t op = rados_create_read_op();
43     rados_read_op_omap_get_vals2(op, NULL, NULL, 100, &iter_vals, NULL, &r_vals);
44     rados_read_op_omap_get_keys2(op, NULL, 100, &iter_keys, NULL, &r_keys);
45     rados_read_op_omap_get_vals_by_keys(op, keys, len,
46                                         &iter_vals_by_key, &r_vals_by_key);
47     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
48     rados_release_read_op(op);
49     ASSERT_EQ(0, r_vals);
50     ASSERT_EQ(0, r_keys);
51     ASSERT_EQ(0, r_vals_by_key);
52
53     const char *zeros[len];
54     size_t zero_lens[len];
55     memset(zeros, 0, sizeof(zeros));
56     memset(zero_lens, 0, sizeof(zero_lens));
57     compare_omap_vals(keys, vals, lens, len, iter_vals);
58     compare_omap_vals(keys, zeros, zero_lens, len, iter_keys);
59     compare_omap_vals(keys, vals, lens, len, iter_vals_by_key);
60   }
61
62   void compare_omap_vals(char const* const* keys,
63                          char const* const* vals,
64                          const size_t *lens,
65                          size_t len,
66                          rados_omap_iter_t iter)
67   {
68     size_t i = 0;
69     char *key = NULL;
70     char *val = NULL;
71     size_t val_len = 0;
72     while (i < len) {
73       ASSERT_EQ(0, rados_omap_get_next(iter, &key, &val, &val_len));
74       if (val_len == 0 && key == NULL && val == NULL)
75         break;
76       if (key)
77         EXPECT_EQ(std::string(keys[i]), std::string(key));
78       else
79         EXPECT_EQ(keys[i], key);
80       ASSERT_EQ(0, memcmp(vals[i], val, val_len));
81       ASSERT_EQ(lens[i], val_len);
82       ++i;
83     }
84     ASSERT_EQ(i, len);
85     ASSERT_EQ(0, rados_omap_get_next(iter, &key, &val, &val_len));
86     ASSERT_EQ((char*)NULL, key);
87     ASSERT_EQ((char*)NULL, val);
88     ASSERT_EQ(0u, val_len);
89     rados_omap_get_end(iter);
90   }
91
92   void compare_xattrs(char const* const* keys,
93                       char const* const* vals,
94                       const size_t *lens,
95                       size_t len,
96                       rados_xattrs_iter_t iter)
97   {
98     size_t i = 0;
99     char *key = NULL;
100     char *val = NULL;
101     size_t val_len = 0;
102     while (i < len) {
103       ASSERT_EQ(0, rados_getxattrs_next(iter, (const char**) &key,
104                                         (const char**) &val, &val_len));
105       if (key == NULL)
106         break;
107       EXPECT_EQ(std::string(keys[i]), std::string(key));
108       if (val != NULL) {
109         EXPECT_EQ(0, memcmp(vals[i], val, val_len));
110       }
111       EXPECT_EQ(lens[i], val_len);
112       ++i;
113     }
114     ASSERT_EQ(i, len);
115     ASSERT_EQ(0, rados_getxattrs_next(iter, (const char**)&key,
116                                       (const char**)&val, &val_len));
117     ASSERT_EQ((char*)NULL, key);
118     ASSERT_EQ((char*)NULL, val);
119     ASSERT_EQ(0u, val_len);
120     rados_getxattrs_end(iter);
121   }
122 };
123
124 TEST_F(CReadOpsTest, NewDelete) {
125   rados_read_op_t op = rados_create_read_op();
126   ASSERT_TRUE(op);
127   rados_release_read_op(op);
128 }
129
130 TEST_F(CReadOpsTest, SetOpFlags) {
131   write_object();
132
133   rados_read_op_t op = rados_create_read_op();
134   size_t bytes_read = 0;
135   char *out = NULL;
136   int rval = 0;
137   rados_read_op_exec(op, "rbd", "get_id", NULL, 0, &out,
138                      &bytes_read, &rval);
139   rados_read_op_set_flags(op, LIBRADOS_OP_FLAG_FAILOK);
140   EXPECT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
141   EXPECT_EQ(-EIO, rval);
142   EXPECT_EQ(0u, bytes_read);
143   EXPECT_EQ((char*)NULL, out);
144   rados_release_read_op(op);
145
146   remove_object();
147 }
148
149 TEST_F(CReadOpsTest, AssertExists) {
150   rados_read_op_t op = rados_create_read_op();
151   rados_read_op_assert_exists(op);
152
153   ASSERT_EQ(-ENOENT, rados_read_op_operate(op, ioctx, obj, 0));
154   rados_release_read_op(op);
155
156   op = rados_create_read_op();
157   rados_read_op_assert_exists(op);
158
159   rados_completion_t completion;
160   ASSERT_EQ(0, rados_aio_create_completion(NULL, NULL, NULL, &completion));
161   ASSERT_EQ(0, rados_aio_read_op_operate(op, ioctx, completion, obj, 0));
162   rados_aio_wait_for_complete(completion);
163   ASSERT_EQ(-ENOENT, rados_aio_get_return_value(completion));
164   rados_aio_release(completion);
165   rados_release_read_op(op);
166
167   write_object();
168
169   op = rados_create_read_op();
170   rados_read_op_assert_exists(op);
171   ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
172   rados_release_read_op(op);
173
174   remove_object();
175 }
176
177 TEST_F(CReadOpsTest, AssertVersion) {
178   write_object();
179   // Write to the object a second time to guarantee that its
180   // version number is greater than 0
181   write_object();
182   uint64_t v = rados_get_last_version(ioctx);
183
184   rados_read_op_t op = rados_create_read_op();
185   rados_read_op_assert_version(op, v+1);
186   ASSERT_EQ(-EOVERFLOW, rados_read_op_operate(op, ioctx, obj, 0));
187   rados_release_read_op(op);
188
189   op = rados_create_read_op();
190   rados_read_op_assert_version(op, v-1);
191   ASSERT_EQ(-ERANGE, rados_read_op_operate(op, ioctx, obj, 0));
192   rados_release_read_op(op);
193
194   op = rados_create_read_op();
195   rados_read_op_assert_version(op, v);
196   ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
197   rados_release_read_op(op);
198
199   remove_object();
200 }
201
202 TEST_F(CReadOpsTest, CmpXattr) {
203   write_object();
204
205   char buf[len];
206   memset(buf, 0xcc, sizeof(buf));
207
208   const char *xattr = "test";
209   rados_setxattr(ioctx, obj, xattr, buf, sizeof(buf));
210
211   // equal value
212   EXPECT_EQ(1, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_EQ));
213   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_NE));
214   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_GT));
215   EXPECT_EQ(1, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_GTE));
216   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_LT));
217   EXPECT_EQ(1, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_LTE));
218
219   // < value
220   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, sizeof(buf) - 1, LIBRADOS_CMPXATTR_OP_EQ));
221   EXPECT_EQ(1, cmp_xattr(xattr, buf, sizeof(buf) - 1, LIBRADOS_CMPXATTR_OP_NE));
222   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, sizeof(buf) - 1, LIBRADOS_CMPXATTR_OP_GT));
223   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, sizeof(buf) - 1, LIBRADOS_CMPXATTR_OP_GTE));
224   EXPECT_EQ(1, cmp_xattr(xattr, buf, sizeof(buf) - 1, LIBRADOS_CMPXATTR_OP_LT));
225   EXPECT_EQ(1, cmp_xattr(xattr, buf, sizeof(buf) - 1, LIBRADOS_CMPXATTR_OP_LTE));
226
227   // > value
228   memset(buf, 0xcd, sizeof(buf));
229   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_EQ));
230   EXPECT_EQ(1, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_NE));
231   EXPECT_EQ(1, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_GT));
232   EXPECT_EQ(1, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_GTE));
233   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_LT));
234   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, sizeof(buf), LIBRADOS_CMPXATTR_OP_LTE));
235
236   // check that null bytes are compared correctly
237   rados_setxattr(ioctx, obj, xattr, "\0\0", 2);
238   buf[0] = '\0';
239   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_EQ));
240   EXPECT_EQ(1, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_NE));
241   EXPECT_EQ(1, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_GT));
242   EXPECT_EQ(1, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_GTE));
243   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_LT));
244   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_LTE));
245
246   buf[1] = '\0';
247   EXPECT_EQ(1, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_EQ));
248   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_NE));
249   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_GT));
250   EXPECT_EQ(1, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_GTE));
251   EXPECT_EQ(-ECANCELED, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_LT));
252   EXPECT_EQ(1, cmp_xattr(xattr, buf, 2, LIBRADOS_CMPXATTR_OP_LTE));
253
254   remove_object();
255 }
256
257 TEST_F(CReadOpsTest, Read) {
258   write_object();
259
260   char buf[len];
261   // check that using read_ops returns the same data with
262   // or without bytes_read and rval out params
263   {
264     rados_read_op_t op = rados_create_read_op();
265     rados_read_op_read(op, 0, len, buf, NULL, NULL);
266     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
267     ASSERT_EQ(0, memcmp(data, buf, len));
268     rados_release_read_op(op);
269   }
270
271   {
272     rados_read_op_t op = rados_create_read_op();
273     int rval;
274     rados_read_op_read(op, 0, len, buf, NULL, &rval);
275     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
276     ASSERT_EQ(0, rval);
277     ASSERT_EQ(0, memcmp(data, buf, len));
278     rados_release_read_op(op);
279   }
280
281   {
282     rados_read_op_t op = rados_create_read_op();
283     size_t bytes_read = 0;
284     rados_read_op_read(op, 0, len, buf, &bytes_read, NULL);
285     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
286     ASSERT_EQ(len, bytes_read);
287     ASSERT_EQ(0, memcmp(data, buf, len));
288     rados_release_read_op(op);
289   }
290
291   {
292     rados_read_op_t op = rados_create_read_op();
293     size_t bytes_read = 0;
294     int rval;
295     rados_read_op_read(op, 0, len, buf, &bytes_read, &rval);
296     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
297     ASSERT_EQ(len, bytes_read);
298     ASSERT_EQ(0, rval);
299     ASSERT_EQ(0, memcmp(data, buf, len));
300     rados_release_read_op(op);
301   }
302
303   {
304     rados_read_op_t op = rados_create_read_op();
305     size_t bytes_read = 0;
306     int rval;
307     rados_read_op_read(op, 0, len, buf, &bytes_read, &rval);
308     rados_read_op_set_flags(op, LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
309     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
310     ASSERT_EQ(len, bytes_read);
311     ASSERT_EQ(0, rval);
312     ASSERT_EQ(0, memcmp(data, buf, len));
313     rados_release_read_op(op);
314   }
315
316   remove_object();
317 }
318
319 TEST_F(CReadOpsTest, Checksum) {
320   write_object();
321
322   {
323     rados_read_op_t op = rados_create_read_op();
324     uint64_t init_value = -1;
325     rados_read_op_checksum(op, LIBRADOS_CHECKSUM_TYPE_XXHASH64,
326                            reinterpret_cast<char *>(&init_value),
327                            sizeof(init_value), 0, len, 0, NULL, 0, NULL);
328     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
329     rados_release_read_op(op);
330   }
331
332   {
333     uint32_t init_value = -1;
334     uint32_t crc[2];
335     rados_read_op_t op = rados_create_read_op();
336     rados_read_op_checksum(op, LIBRADOS_CHECKSUM_TYPE_CRC32C,
337                            reinterpret_cast<char *>(&init_value),
338                            sizeof(init_value), 0, len, 0,
339                            reinterpret_cast<char *>(&crc), sizeof(crc),
340                            nullptr);
341     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
342     ASSERT_EQ(1U, crc[0]);
343     uint32_t expected_crc = ceph_crc32c(
344       -1, reinterpret_cast<const uint8_t*>(data), static_cast<uint32_t>(len));
345     ASSERT_EQ(expected_crc, crc[1]);
346     rados_release_read_op(op);
347   }
348
349   {
350     uint32_t init_value = -1;
351     int rval;
352     rados_read_op_t op = rados_create_read_op();
353     rados_read_op_checksum(op, LIBRADOS_CHECKSUM_TYPE_XXHASH32,
354                            reinterpret_cast<char *>(&init_value),
355                            sizeof(init_value), 0, len, 0, nullptr, 0, &rval);
356     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
357     ASSERT_EQ(0, rval);
358     rados_release_read_op(op);
359   }
360
361   {
362     uint32_t init_value = -1;
363     uint32_t crc[3];
364     int rval;
365     rados_read_op_t op = rados_create_read_op();
366     rados_read_op_checksum(op, LIBRADOS_CHECKSUM_TYPE_CRC32C,
367                            reinterpret_cast<char *>(&init_value),
368                            sizeof(init_value), 0, len, 4,
369                            reinterpret_cast<char *>(&crc), sizeof(crc), &rval);
370     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
371     ASSERT_EQ(2U, crc[0]);
372     uint32_t expected_crc[2];
373     expected_crc[0] = ceph_crc32c(
374       -1, reinterpret_cast<const uint8_t*>(data), 4U);
375     expected_crc[1] = ceph_crc32c(
376       -1, reinterpret_cast<const uint8_t*>(data + 4), 4U);
377     ASSERT_EQ(expected_crc[0], crc[1]);
378     ASSERT_EQ(expected_crc[1], crc[2]);
379     ASSERT_EQ(0, rval);
380     rados_release_read_op(op);
381   }
382
383   remove_object();
384 }
385
386 TEST_F(CReadOpsTest, RWOrderedRead) {
387   write_object();
388
389   char buf[len];
390   rados_read_op_t op = rados_create_read_op();
391   size_t bytes_read = 0;
392   int rval;
393   rados_read_op_read(op, 0, len, buf, &bytes_read, &rval);
394   rados_read_op_set_flags(op, LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
395   ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj,
396                                      LIBRADOS_OPERATION_ORDER_READS_WRITES));
397   ASSERT_EQ(len, bytes_read);
398   ASSERT_EQ(0, rval);
399   ASSERT_EQ(0, memcmp(data, buf, len));
400   rados_release_read_op(op);
401
402   remove_object();
403 }
404
405 TEST_F(CReadOpsTest, ShortRead) {
406   write_object();
407
408   char buf[len * 2];
409   // check that using read_ops returns the same data with
410   // or without bytes_read and rval out params
411   {
412     rados_read_op_t op = rados_create_read_op();
413     rados_read_op_read(op, 0, len * 2, buf, NULL, NULL);
414     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
415     ASSERT_EQ(0, memcmp(data, buf, len));
416     rados_release_read_op(op);
417   }
418
419   {
420     rados_read_op_t op = rados_create_read_op();
421     int rval;
422     rados_read_op_read(op, 0, len * 2, buf, NULL, &rval);
423     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
424     ASSERT_EQ(0, rval);
425     ASSERT_EQ(0, memcmp(data, buf, len));
426     rados_release_read_op(op);
427   }
428
429   {
430     rados_read_op_t op = rados_create_read_op();
431     size_t bytes_read = 0;
432     rados_read_op_read(op, 0, len * 2, buf, &bytes_read, NULL);
433     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
434     ASSERT_EQ(len, bytes_read);
435     ASSERT_EQ(0, memcmp(data, buf, len));
436     rados_release_read_op(op);
437   }
438
439   {
440     rados_read_op_t op = rados_create_read_op();
441     size_t bytes_read = 0;
442     int rval;
443     rados_read_op_read(op, 0, len * 2, buf, &bytes_read, &rval);
444     ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
445     ASSERT_EQ(len, bytes_read);
446     ASSERT_EQ(0, rval);
447     ASSERT_EQ(0, memcmp(data, buf, len));
448     rados_release_read_op(op);
449   }
450
451   remove_object();
452 }
453
454 TEST_F(CReadOpsTest, Exec) {
455   // create object so we don't get -ENOENT
456   write_object();
457
458   rados_read_op_t op = rados_create_read_op();
459   ASSERT_TRUE(op);
460   size_t bytes_read = 0;
461   char *out = NULL;
462   int rval = 0;
463   rados_read_op_exec(op, "rbd", "get_all_features", NULL, 0, &out,
464                      &bytes_read, &rval);
465   ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
466   rados_release_read_op(op);
467   EXPECT_EQ(0, rval);
468   EXPECT_TRUE(out);
469   uint64_t features;
470   EXPECT_EQ(sizeof(features), bytes_read);
471   // make sure buffer is at least as long as it claims
472   ASSERT_TRUE(out[bytes_read-1] == out[bytes_read-1]);
473   rados_buffer_free(out);
474
475   remove_object();
476 }
477
478 TEST_F(CReadOpsTest, ExecUserBuf) {
479   // create object so we don't get -ENOENT
480   write_object();
481
482   rados_read_op_t op = rados_create_read_op();
483   size_t bytes_read = 0;
484   uint64_t features;
485   char out[sizeof(features)];
486   int rval = 0;
487   rados_read_op_exec_user_buf(op, "rbd", "get_all_features", NULL, 0, out,
488                               sizeof(out), &bytes_read, &rval);
489   ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
490   rados_release_read_op(op);
491   EXPECT_EQ(0, rval);
492   EXPECT_EQ(sizeof(features), bytes_read);
493
494   // buffer too short
495   bytes_read = 1024;
496   op = rados_create_read_op();
497   rados_read_op_exec_user_buf(op, "rbd", "get_all_features", NULL, 0, out,
498                               sizeof(features) - 1, &bytes_read, &rval);
499   ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
500   rados_release_read_op(op);
501   EXPECT_EQ(0u, bytes_read);
502   EXPECT_EQ(-ERANGE, rval);
503
504   // input buffer and no rval or bytes_read
505   op = rados_create_read_op();
506   rados_read_op_exec_user_buf(op, "rbd", "get_all_features", out, sizeof(out),
507                               out, sizeof(out), NULL, NULL);
508   ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
509   rados_release_read_op(op);
510
511   remove_object();
512 }
513
514 TEST_F(CReadOpsTest, Stat) {
515   rados_read_op_t op = rados_create_read_op();
516   uint64_t size = 1;
517   int rval;
518   rados_read_op_stat(op, &size, NULL, &rval);
519   EXPECT_EQ(-ENOENT, rados_read_op_operate(op, ioctx, obj, 0));
520   EXPECT_EQ(-EIO, rval);
521   EXPECT_EQ(1u, size);
522   rados_release_read_op(op);
523
524   write_object();
525
526   op = rados_create_read_op();
527   rados_read_op_stat(op, &size, NULL, &rval);
528   EXPECT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
529   EXPECT_EQ(0, rval);
530   EXPECT_EQ(len, size);
531   rados_release_read_op(op);
532
533   op = rados_create_read_op();
534   rados_read_op_stat(op, NULL, NULL, NULL);
535   EXPECT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
536   rados_release_read_op(op);
537
538   remove_object();
539
540   op = rados_create_read_op();
541   rados_read_op_stat(op, NULL, NULL, NULL);
542   EXPECT_EQ(-ENOENT, rados_read_op_operate(op, ioctx, obj, 0));
543   rados_release_read_op(op);
544 }
545
546 TEST_F(CReadOpsTest, Omap) {
547   char *keys[] = {(char*)"bar",
548                   (char*)"foo",
549                   (char*)"test1",
550                   (char*)"test2"};
551   char *vals[] = {(char*)"",
552                   (char*)"\0",
553                   (char*)"abc",
554                   (char*)"va\0lue"};
555   size_t lens[] = {0, 1, 3, 6};
556
557   // check for -ENOENT before the object exists and when it exists
558   // with no omap entries
559   rados_omap_iter_t iter_vals;
560   rados_read_op_t rop = rados_create_read_op();
561   rados_read_op_omap_get_vals2(rop, "", "", 10, &iter_vals, NULL, NULL);
562   ASSERT_EQ(-ENOENT, rados_read_op_operate(rop, ioctx, obj, 0));
563   rados_release_read_op(rop);
564   compare_omap_vals(NULL, NULL, NULL, 0, iter_vals);
565
566   write_object();
567
568   fetch_and_verify_omap_vals(NULL, NULL, NULL, 0);
569
570   // write and check for the k/v pairs
571   rados_write_op_t op = rados_create_write_op();
572   rados_write_op_omap_set(op, keys, vals, lens, 4);
573   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, obj, NULL, 0));
574   rados_release_write_op(op);
575
576   fetch_and_verify_omap_vals(keys, vals, lens, 4);
577
578   rados_omap_iter_t iter_keys;
579   int r_vals = -1, r_keys = -1;
580   rop = rados_create_read_op();
581   rados_read_op_omap_get_vals2(rop, "", "test", 1, &iter_vals, NULL, &r_vals);
582   rados_read_op_omap_get_keys2(rop, "test", 1, &iter_keys, NULL, &r_keys);
583   ASSERT_EQ(0, rados_read_op_operate(rop, ioctx, obj, 0));
584   rados_release_read_op(rop);
585   EXPECT_EQ(0, r_vals);
586   EXPECT_EQ(0, r_keys);
587
588   compare_omap_vals(&keys[2], &vals[2], &lens[2], 1, iter_vals);
589   compare_omap_vals(&keys[2], &vals[0], &lens[0], 1, iter_keys);
590
591   // check omap_cmp finds all expected values
592   rop = rados_create_read_op();
593   int rvals[4];
594   for (int i = 0; i < 4; ++i)
595     rados_read_op_omap_cmp(rop, keys[i], LIBRADOS_CMPXATTR_OP_EQ,
596                            vals[i], lens[i], &rvals[i]);
597   EXPECT_EQ(0, rados_read_op_operate(rop, ioctx, obj, 0));
598   rados_release_read_op(rop);
599   for (int i = 0; i < 4; ++i)
600     EXPECT_EQ(0, rvals[i]);
601
602   // try to remove keys with a guard that should fail
603   op = rados_create_write_op();
604   rados_write_op_omap_cmp(op, keys[2], LIBRADOS_CMPXATTR_OP_LT,
605                           vals[2], lens[2], &r_vals);
606   rados_write_op_omap_rm_keys(op, keys, 2);
607   EXPECT_EQ(-ECANCELED, rados_write_op_operate(op, ioctx, obj, NULL, 0));
608   rados_release_write_op(op);
609
610   // see http://tracker.ceph.com/issues/19518
611   //ASSERT_EQ(-ECANCELED, r_vals);
612
613   // verifying the keys are still there, and then remove them
614   op = rados_create_write_op();
615   rados_write_op_omap_cmp(op, keys[0], LIBRADOS_CMPXATTR_OP_EQ,
616                           vals[0], lens[0], NULL);
617   rados_write_op_omap_cmp(op, keys[1], LIBRADOS_CMPXATTR_OP_EQ,
618                           vals[1], lens[1], NULL);
619   rados_write_op_omap_rm_keys(op, keys, 2);
620   EXPECT_EQ(0, rados_write_op_operate(op, ioctx, obj, NULL, 0));
621   rados_release_write_op(op);
622
623   fetch_and_verify_omap_vals(&keys[2], &vals[2], &lens[2], 2);
624
625   // clear the rest and check there are none left
626   op = rados_create_write_op();
627   rados_write_op_omap_clear(op);
628   EXPECT_EQ(0, rados_write_op_operate(op, ioctx, obj, NULL, 0));
629   rados_release_write_op(op);
630
631   fetch_and_verify_omap_vals(NULL, NULL, NULL, 0);
632
633   remove_object();
634 }
635
636 TEST_F(CReadOpsTest, GetXattrs) {
637   write_object();
638
639   char *keys[] = {(char*)"bar",
640                   (char*)"foo",
641                   (char*)"test1",
642                   (char*)"test2"};
643   char *vals[] = {(char*)"",
644                   (char*)"\0",
645                   (char*)"abc",
646                   (char*)"va\0lue"};
647   size_t lens[] = {0, 1, 3, 6};
648
649   int rval = 1;
650   rados_read_op_t op = rados_create_read_op();
651   rados_xattrs_iter_t it;
652   rados_read_op_getxattrs(op, &it, &rval);
653   EXPECT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
654   EXPECT_EQ(0, rval);
655   rados_release_read_op(op);
656   compare_xattrs(keys, vals, lens, 0, it);
657
658   for (int i = 0; i < 4; ++i)
659     rados_setxattr(ioctx, obj, keys[i], vals[i], lens[i]);
660
661   rval = 1;
662   op = rados_create_read_op();
663   rados_read_op_getxattrs(op, &it, &rval);
664   EXPECT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
665   EXPECT_EQ(0, rval);
666   rados_release_read_op(op);
667   compare_xattrs(keys, vals, lens, 4, it);
668
669   remove_object();
670 }
671
672 TEST_F(CReadOpsTest, CmpExt) {
673   char buf[len];
674   size_t bytes_read = 0;
675   int cmpext_val = 0;
676   int read_val = 0;
677
678   write_object();
679
680   // cmpext with match should ensure that the following read is successful
681   rados_read_op_t op = rados_create_read_op();
682   ASSERT_TRUE(op);
683   // @obj, @data and @len correspond to object initialised by write_object()
684   rados_read_op_cmpext(op, data, len, 0, &cmpext_val);
685   rados_read_op_read(op, 0, len, buf, &bytes_read, &read_val);
686   ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0));
687   ASSERT_EQ(len, bytes_read);
688   ASSERT_EQ(0, memcmp(data, buf, len));
689   ASSERT_EQ(cmpext_val, 0);
690   rados_release_read_op(op);
691
692   // cmpext with mismatch should fail and fill mismatch_buf accordingly
693   memset(buf, 0, sizeof(buf));
694   bytes_read = 0;
695   cmpext_val = 0;
696   read_val = 0;
697   op = rados_create_read_op();
698   ASSERT_TRUE(op);
699   // @obj, @data and @len correspond to object initialised by write_object()
700   rados_read_op_cmpext(op, "mismatch", strlen("mismatch"), 0, &cmpext_val);
701   rados_read_op_read(op, 0, len, buf, &bytes_read, &read_val);
702   ASSERT_EQ(-MAX_ERRNO, rados_read_op_operate(op, ioctx, obj, 0));
703   rados_release_read_op(op);
704
705   ASSERT_EQ(-MAX_ERRNO, cmpext_val);
706
707   remove_object();
708 }