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
7 #include "include/err.h"
8 #include "include/rados/librados.h"
9 #include "test/librados/test.h"
10 #include "test/librados/TestCase.h"
12 const char *data
= "testdata";
13 const char *obj
= "testobj";
14 const size_t len
= strlen(data
);
16 class CReadOpsTest
: public RadosTest
{
19 // Create an object and write to it
20 ASSERT_EQ(0, rados_write(ioctx
, obj
, data
, len
, 0));
22 void remove_object() {
23 ASSERT_EQ(0, rados_remove(ioctx
, obj
));
25 int cmp_xattr(const char *xattr
, const char *value
, size_t value_len
,
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
);
35 void fetch_and_verify_omap_vals(char const* const* keys
,
36 char const* const* vals
,
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
);
51 ASSERT_EQ(0, r_vals_by_key
);
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
);
62 void compare_omap_vals(char const* const* keys
,
63 char const* const* vals
,
66 rados_omap_iter_t iter
)
73 ASSERT_EQ(0, rados_omap_get_next(iter
, &key
, &val
, &val_len
));
74 if (val_len
== 0 && key
== NULL
&& val
== NULL
)
77 EXPECT_EQ(std::string(keys
[i
]), std::string(key
));
79 EXPECT_EQ(keys
[i
], key
);
80 ASSERT_EQ(0, memcmp(vals
[i
], val
, val_len
));
81 ASSERT_EQ(lens
[i
], val_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
);
92 void compare_xattrs(char const* const* keys
,
93 char const* const* vals
,
96 rados_xattrs_iter_t iter
)
103 ASSERT_EQ(0, rados_getxattrs_next(iter
, (const char**) &key
,
104 (const char**) &val
, &val_len
));
107 EXPECT_EQ(std::string(keys
[i
]), std::string(key
));
109 EXPECT_EQ(0, memcmp(vals
[i
], val
, val_len
));
111 EXPECT_EQ(lens
[i
], val_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
);
124 TEST_F(CReadOpsTest
, NewDelete
) {
125 rados_read_op_t op
= rados_create_read_op();
127 rados_release_read_op(op
);
130 TEST_F(CReadOpsTest
, SetOpFlags
) {
133 rados_read_op_t op
= rados_create_read_op();
134 size_t bytes_read
= 0;
137 rados_read_op_exec(op
, "rbd", "get_id", NULL
, 0, &out
,
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
);
149 TEST_F(CReadOpsTest
, AssertExists
) {
150 rados_read_op_t op
= rados_create_read_op();
151 rados_read_op_assert_exists(op
);
153 ASSERT_EQ(-ENOENT
, rados_read_op_operate(op
, ioctx
, obj
, 0));
154 rados_release_read_op(op
);
156 op
= rados_create_read_op();
157 rados_read_op_assert_exists(op
);
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
);
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
);
177 TEST_F(CReadOpsTest
, AssertVersion
) {
179 // Write to the object a second time to guarantee that its
180 // version number is greater than 0
182 uint64_t v
= rados_get_last_version(ioctx
);
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
);
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
);
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
);
202 TEST_F(CReadOpsTest
, CmpXattr
) {
206 memset(buf
, 0xcc, sizeof(buf
));
208 const char *xattr
= "test";
209 rados_setxattr(ioctx
, obj
, xattr
, buf
, sizeof(buf
));
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
));
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
));
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
));
236 // check that null bytes are compared correctly
237 rados_setxattr(ioctx
, obj
, xattr
, "\0\0", 2);
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
));
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
));
257 TEST_F(CReadOpsTest
, Read
) {
261 // check that using read_ops returns the same data with
262 // or without bytes_read and rval out params
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
);
272 rados_read_op_t op
= rados_create_read_op();
274 rados_read_op_read(op
, 0, len
, buf
, NULL
, &rval
);
275 ASSERT_EQ(0, rados_read_op_operate(op
, ioctx
, obj
, 0));
277 ASSERT_EQ(0, memcmp(data
, buf
, len
));
278 rados_release_read_op(op
);
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
);
292 rados_read_op_t op
= rados_create_read_op();
293 size_t bytes_read
= 0;
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
);
299 ASSERT_EQ(0, memcmp(data
, buf
, len
));
300 rados_release_read_op(op
);
304 rados_read_op_t op
= rados_create_read_op();
305 size_t bytes_read
= 0;
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
);
312 ASSERT_EQ(0, memcmp(data
, buf
, len
));
313 rados_release_read_op(op
);
319 TEST_F(CReadOpsTest
, Checksum
) {
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
);
333 uint32_t init_value
= -1;
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
),
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
);
350 uint32_t init_value
= -1;
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));
358 rados_release_read_op(op
);
362 uint32_t init_value
= -1;
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]);
380 rados_release_read_op(op
);
386 TEST_F(CReadOpsTest
, RWOrderedRead
) {
390 rados_read_op_t op
= rados_create_read_op();
391 size_t bytes_read
= 0;
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
);
399 ASSERT_EQ(0, memcmp(data
, buf
, len
));
400 rados_release_read_op(op
);
405 TEST_F(CReadOpsTest
, ShortRead
) {
409 // check that using read_ops returns the same data with
410 // or without bytes_read and rval out params
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
);
420 rados_read_op_t op
= rados_create_read_op();
422 rados_read_op_read(op
, 0, len
* 2, buf
, NULL
, &rval
);
423 ASSERT_EQ(0, rados_read_op_operate(op
, ioctx
, obj
, 0));
425 ASSERT_EQ(0, memcmp(data
, buf
, len
));
426 rados_release_read_op(op
);
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
);
440 rados_read_op_t op
= rados_create_read_op();
441 size_t bytes_read
= 0;
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
);
447 ASSERT_EQ(0, memcmp(data
, buf
, len
));
448 rados_release_read_op(op
);
454 TEST_F(CReadOpsTest
, Exec
) {
455 // create object so we don't get -ENOENT
458 rados_read_op_t op
= rados_create_read_op();
460 size_t bytes_read
= 0;
463 rados_read_op_exec(op
, "rbd", "get_all_features", NULL
, 0, &out
,
465 ASSERT_EQ(0, rados_read_op_operate(op
, ioctx
, obj
, 0));
466 rados_release_read_op(op
);
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
);
478 TEST_F(CReadOpsTest
, ExecUserBuf
) {
479 // create object so we don't get -ENOENT
482 rados_read_op_t op
= rados_create_read_op();
483 size_t bytes_read
= 0;
485 char out
[sizeof(features
)];
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
);
492 EXPECT_EQ(sizeof(features
), bytes_read
);
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
);
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
);
514 TEST_F(CReadOpsTest
, Stat
) {
515 rados_read_op_t op
= rados_create_read_op();
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
);
522 rados_release_read_op(op
);
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));
530 EXPECT_EQ(len
, size
);
531 rados_release_read_op(op
);
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
);
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
);
546 TEST_F(CReadOpsTest
, Omap
) {
547 char *keys
[] = {(char*)"bar",
551 char *vals
[] = {(char*)"",
555 size_t lens
[] = {0, 1, 3, 6};
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
);
568 fetch_and_verify_omap_vals(NULL
, NULL
, NULL
, 0);
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
);
576 fetch_and_verify_omap_vals(keys
, vals
, lens
, 4);
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
);
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
);
591 // check omap_cmp finds all expected values
592 rop
= rados_create_read_op();
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
]);
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
);
610 // see http://tracker.ceph.com/issues/19518
611 //ASSERT_EQ(-ECANCELED, r_vals);
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
);
623 fetch_and_verify_omap_vals(&keys
[2], &vals
[2], &lens
[2], 2);
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
);
631 fetch_and_verify_omap_vals(NULL
, NULL
, NULL
, 0);
636 TEST_F(CReadOpsTest
, GetXattrs
) {
639 char *keys
[] = {(char*)"bar",
643 char *vals
[] = {(char*)"",
647 size_t lens
[] = {0, 1, 3, 6};
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));
655 rados_release_read_op(op
);
656 compare_xattrs(keys
, vals
, lens
, 0, it
);
658 for (int i
= 0; i
< 4; ++i
)
659 rados_setxattr(ioctx
, obj
, keys
[i
], vals
[i
], lens
[i
]);
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));
666 rados_release_read_op(op
);
667 compare_xattrs(keys
, vals
, lens
, 4, it
);
672 TEST_F(CReadOpsTest
, CmpExt
) {
674 size_t bytes_read
= 0;
680 // cmpext with match should ensure that the following read is successful
681 rados_read_op_t op
= rados_create_read_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
);
692 // cmpext with mismatch should fail and fill mismatch_buf accordingly
693 memset(buf
, 0, sizeof(buf
));
697 op
= rados_create_read_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
);
705 ASSERT_EQ(-MAX_ERRNO
, cmpext_val
);