1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
9 #include "gtest/gtest.h"
11 #include "include/err.h"
12 #include "include/buffer.h"
13 #include "include/rbd_types.h"
14 #include "include/rados.h"
15 #include "include/rados/librados.hpp"
16 #include "include/scope_guard.h"
17 #include "include/stringify.h"
18 #include "common/Checksummer.h"
19 #include "mds/mdstypes.h"
20 #include "global/global_context.h"
21 #include "test/librados/testcase_cxx.h"
22 #include "test/librados/test_cxx.h"
24 #include "crimson_utils.h"
27 using namespace librados
;
29 typedef RadosTestPP LibRadosMiscPP
;
30 typedef RadosTestECPP LibRadosMiscECPP
;
32 TEST(LibRadosMiscVersion
, VersionPP
) {
33 int major
, minor
, extra
;
34 Rados::version(&major
, &minor
, &extra
);
37 TEST_F(LibRadosMiscPP
, WaitOSDMapPP
) {
38 ASSERT_EQ(0, cluster
.wait_for_latest_osdmap());
41 TEST_F(LibRadosMiscPP
, LongNamePP
) {
44 int maxlen
= g_conf()->osd_max_object_name_len
;
45 ASSERT_EQ(0, ioctx
.write(string(maxlen
/2, 'a').c_str(), bl
, bl
.length(), 0));
46 ASSERT_EQ(0, ioctx
.write(string(maxlen
-1, 'a').c_str(), bl
, bl
.length(), 0));
47 ASSERT_EQ(0, ioctx
.write(string(maxlen
, 'a').c_str(), bl
, bl
.length(), 0));
48 ASSERT_EQ(-ENAMETOOLONG
, ioctx
.write(string(maxlen
+1, 'a').c_str(), bl
, bl
.length(), 0));
49 ASSERT_EQ(-ENAMETOOLONG
, ioctx
.write(string(maxlen
*2, 'a').c_str(), bl
, bl
.length(), 0));
52 TEST_F(LibRadosMiscPP
, LongLocatorPP
) {
55 int maxlen
= g_conf()->osd_max_object_name_len
;
56 ioctx
.locator_set_key(
57 string((maxlen
/2), 'a'));
63 ioctx
.locator_set_key(
64 string(maxlen
- 1, 'a'));
70 ioctx
.locator_set_key(
77 ioctx
.locator_set_key(
78 string(maxlen
+1, 'a'));
84 ioctx
.locator_set_key(
85 string((maxlen
*2), 'a'));
93 TEST_F(LibRadosMiscPP
, LongNSpacePP
) {
96 int maxlen
= g_conf()->osd_max_object_namespace_len
;
98 string((maxlen
/2), 'a'));
103 bl
, bl
.length(), 0));
105 string(maxlen
- 1, 'a'));
110 bl
, bl
.length(), 0));
112 string(maxlen
, 'a'));
117 bl
, bl
.length(), 0));
119 string(maxlen
+1, 'a'));
124 bl
, bl
.length(), 0));
126 string((maxlen
*2), 'a'));
131 bl
, bl
.length(), 0));
134 TEST_F(LibRadosMiscPP
, LongAttrNamePP
) {
136 bl
.append("content");
137 int maxlen
= g_conf()->osd_max_attr_name_len
;
138 ASSERT_EQ(0, ioctx
.setxattr("bigattrobj", string(maxlen
/2, 'a').c_str(), bl
));
139 ASSERT_EQ(0, ioctx
.setxattr("bigattrobj", string(maxlen
-1, 'a').c_str(), bl
));
140 ASSERT_EQ(0, ioctx
.setxattr("bigattrobj", string(maxlen
, 'a').c_str(), bl
));
141 ASSERT_EQ(-ENAMETOOLONG
, ioctx
.setxattr("bigattrobj", string(maxlen
+1, 'a').c_str(), bl
));
142 ASSERT_EQ(-ENAMETOOLONG
, ioctx
.setxattr("bigattrobj", string(maxlen
*2, 'a').c_str(), bl
));
145 TEST_F(LibRadosMiscPP
, ExecPP
) {
147 ASSERT_EQ(0, ioctx
.write("foo", bl
, 0, 0));
149 int r
= ioctx
.exec("foo", "rbd", "get_all_features", bl2
, out
);
151 auto iter
= out
.cbegin();
152 uint64_t all_features
;
153 decode(all_features
, iter
);
154 // make sure *some* features are specified; don't care which ones
155 ASSERT_NE(all_features
, (unsigned)0);
158 void set_completion_complete(rados_completion_t cb
, void *arg
)
160 bool *my_aio_complete
= (bool*)arg
;
161 *my_aio_complete
= true;
164 TEST_F(LibRadosMiscPP
, BadFlagsPP
) {
165 unsigned badflags
= CEPH_OSD_FLAG_PARALLELEXEC
;
169 ASSERT_EQ(0, ioctx
.write("badfoo", bl
, bl
.length(), 0));
172 ASSERT_EQ(-EINVAL
, ioctx
.remove("badfoo", badflags
));
176 TEST_F(LibRadosMiscPP
, Operate1PP
) {
177 ObjectWriteOperation o
;
182 std::string
val1("val1");
185 bl
.append(val1
.c_str(), val1
.size() + 1);
186 o
.setxattr("key1", bl
);
187 o
.omap_clear(); // shouldn't affect attrs!
189 ASSERT_EQ(0, ioctx
.operate("foo", &o
));
191 ObjectWriteOperation empty
;
192 ASSERT_EQ(0, ioctx
.operate("foo", &empty
));
196 ASSERT_GT(ioctx
.getxattr("foo", "key1", bl
), 0);
197 ASSERT_EQ(0, strcmp(bl
.c_str(), val1
.c_str()));
199 ObjectWriteOperation o2
;
203 o2
.cmpxattr("key1", CEPH_OSD_CMPXATTR_OP_EQ
, bl
);
206 ASSERT_EQ(-ECANCELED
, ioctx
.operate("foo", &o2
));
207 ObjectWriteOperation o3
;
211 o3
.cmpxattr("key1", CEPH_OSD_CMPXATTR_OP_EQ
, bl
);
213 ASSERT_EQ(-ECANCELED
, ioctx
.operate("foo", &o3
));
216 TEST_F(LibRadosMiscPP
, Operate2PP
) {
217 ObjectWriteOperation o
;
220 bl
.append("abcdefg");
223 std::string
val1("val1");
226 bl
.append(val1
.c_str(), val1
.size() + 1);
227 o
.setxattr("key1", bl
);
230 ASSERT_EQ(0, ioctx
.operate("foo", &o
));
233 ASSERT_EQ(0, ioctx
.stat("foo", &size
, &mtime
));
237 TEST_F(LibRadosMiscPP
, BigObjectPP
) {
239 bl
.append("abcdefg");
240 ASSERT_EQ(0, ioctx
.write("foo", bl
, bl
.length(), 0));
243 ObjectWriteOperation o
;
244 o
.truncate(500000000000ull);
245 ASSERT_EQ(-EFBIG
, ioctx
.operate("foo", &o
));
248 ObjectWriteOperation o
;
249 o
.zero(500000000000ull, 1);
250 ASSERT_EQ(-EFBIG
, ioctx
.operate("foo", &o
));
253 ObjectWriteOperation o
;
254 o
.zero(1, 500000000000ull);
255 ASSERT_EQ(-EFBIG
, ioctx
.operate("foo", &o
));
258 ObjectWriteOperation o
;
259 o
.zero(500000000000ull, 500000000000ull);
260 ASSERT_EQ(-EFBIG
, ioctx
.operate("foo", &o
));
264 // this test only works on 64-bit platforms
265 ASSERT_EQ(-EFBIG
, ioctx
.write("foo", bl
, bl
.length(), 500000000000ull));
269 TEST_F(LibRadosMiscPP
, AioOperatePP
) {
270 bool my_aio_complete
= false;
271 AioCompletion
*my_completion
= cluster
.aio_create_completion(
272 (void*)&my_aio_complete
, set_completion_complete
);
273 AioCompletion
*my_completion_null
= NULL
;
274 ASSERT_NE(my_completion
, my_completion_null
);
276 ObjectWriteOperation o
;
281 std::string
val1("val1");
284 bl
.append(val1
.c_str(), val1
.size() + 1);
285 o
.setxattr("key1", bl
);
288 memset(buf2
, 0xdd, sizeof(buf2
));
289 bl2
.append(buf2
, sizeof(buf2
));
292 ASSERT_EQ(0, ioctx
.aio_operate("foo", my_completion
, &o
));
293 ASSERT_EQ(0, my_completion
->wait_for_complete_and_cb());
294 ASSERT_EQ(my_aio_complete
, true);
295 my_completion
->release();
299 ASSERT_EQ(0, ioctx
.stat("foo", &size
, &mtime
));
300 ASSERT_EQ(1024U, size
);
303 TEST_F(LibRadosMiscPP
, AssertExistsPP
) {
305 memset(buf
, 0xcc, sizeof(buf
));
307 bl
.append(buf
, sizeof(buf
));
309 ObjectWriteOperation op
;
312 ASSERT_EQ(-ENOENT
, ioctx
.operate("asdffoo", &op
));
313 ASSERT_EQ(0, ioctx
.create("asdffoo", true));
314 ASSERT_EQ(0, ioctx
.operate("asdffoo", &op
));
315 ASSERT_EQ(-EEXIST
, ioctx
.create("asdffoo", true));
318 TEST_F(LibRadosMiscPP
, AssertVersionPP
) {
320 memset(buf
, 0xcc, sizeof(buf
));
322 bl
.append(buf
, sizeof(buf
));
324 // Create test object...
325 ASSERT_EQ(0, ioctx
.create("asdfbar", true));
326 // ...then write it again to guarantee that the
327 // (unsigned) version must be at least 1 (not 0)
328 // since we want to decrement it by 1 later.
329 ASSERT_EQ(0, ioctx
.write_full("asdfbar", bl
));
331 uint64_t v
= ioctx
.get_last_version();
332 ObjectWriteOperation op1
;
333 op1
.assert_version(v
+1);
335 ASSERT_EQ(-EOVERFLOW
, ioctx
.operate("asdfbar", &op1
));
336 ObjectWriteOperation op2
;
337 op2
.assert_version(v
-1);
339 ASSERT_EQ(-ERANGE
, ioctx
.operate("asdfbar", &op2
));
340 ObjectWriteOperation op3
;
341 op3
.assert_version(v
);
343 ASSERT_EQ(0, ioctx
.operate("asdfbar", &op3
));
346 TEST_F(LibRadosMiscPP
, BigAttrPP
) {
348 memset(buf
, 0xcc, sizeof(buf
));
350 bl
.append(buf
, sizeof(buf
));
352 ASSERT_EQ(0, ioctx
.create("foo", true));
356 cout
<< "osd_max_attr_size = " << g_conf()->osd_max_attr_size
<< std::endl
;
357 if (g_conf()->osd_max_attr_size
) {
360 bl
.append(buffer::create(g_conf()->osd_max_attr_size
));
361 ASSERT_EQ(0, ioctx
.setxattr("foo", "one", bl
));
362 ASSERT_EQ((int)bl
.length(), ioctx
.getxattr("foo", "one", got
));
363 ASSERT_TRUE(bl
.contents_equal(got
));
366 bl
.append(buffer::create(g_conf()->osd_max_attr_size
+1));
367 ASSERT_EQ(-EFBIG
, ioctx
.setxattr("foo", "one", bl
));
369 cout
<< "osd_max_attr_size == 0; skipping test" << std::endl
;
372 for (int i
=0; i
<1000; i
++) {
375 bl
.append(buffer::create(std::min
<uint64_t>(g_conf()->osd_max_attr_size
,
378 snprintf(n
, sizeof(n
), "a%d", i
);
379 ASSERT_EQ(0, ioctx
.setxattr("foo", n
, bl
));
380 ASSERT_EQ((int)bl
.length(), ioctx
.getxattr("foo", n
, got
));
381 ASSERT_TRUE(bl
.contents_equal(got
));
385 TEST_F(LibRadosMiscPP
, CopyPP
) {
388 bl
.append("hi there");
394 ASSERT_EQ(0, ioctx
.write_full("foo", blc
));
395 ASSERT_EQ(0, ioctx
.setxattr("foo", "myattr", xc
));
397 version_t uv
= ioctx
.get_last_version();
399 // pass future version
400 ObjectWriteOperation op
;
401 op
.copy_from("foo", ioctx
, uv
+ 1, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
402 ASSERT_EQ(-EOVERFLOW
, ioctx
.operate("foo.copy", &op
));
406 ObjectWriteOperation op
;
407 op
.copy_from("foo", ioctx
, uv
- 1, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
408 ASSERT_EQ(-ERANGE
, ioctx
.operate("foo.copy", &op
));
411 ObjectWriteOperation op
;
412 op
.copy_from("foo", ioctx
, uv
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
413 ASSERT_EQ(0, ioctx
.operate("foo.copy", &op
));
416 ASSERT_EQ((int)bl
.length(), ioctx
.read("foo.copy", bl2
, 10000, 0));
417 ASSERT_TRUE(bl
.contents_equal(bl2
));
418 ASSERT_EQ((int)x
.length(), ioctx
.getxattr("foo.copy", "myattr", x2
));
419 ASSERT_TRUE(x
.contents_equal(x2
));
422 // small object without a version
424 ObjectWriteOperation op
;
425 op
.copy_from("foo", ioctx
, 0, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
426 ASSERT_EQ(0, ioctx
.operate("foo.copy2", &op
));
429 ASSERT_EQ((int)bl
.length(), ioctx
.read("foo.copy2", bl2
, 10000, 0));
430 ASSERT_TRUE(bl
.contents_equal(bl2
));
431 ASSERT_EQ((int)x
.length(), ioctx
.getxattr("foo.copy2", "myattr", x2
));
432 ASSERT_TRUE(x
.contents_equal(x2
));
436 bl
.append(buffer::create(g_conf()->osd_copyfrom_max_chunk
* 3));
441 ASSERT_EQ(0, ioctx
.write_full("big", blc
));
442 ASSERT_EQ(0, ioctx
.setxattr("big", "myattr", xc
));
445 ObjectWriteOperation op
;
446 op
.copy_from("big", ioctx
, ioctx
.get_last_version(), LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
447 ASSERT_EQ(0, ioctx
.operate("big.copy", &op
));
450 ASSERT_EQ((int)bl
.length(), ioctx
.read("big.copy", bl2
, bl
.length(), 0));
451 ASSERT_TRUE(bl
.contents_equal(bl2
));
452 ASSERT_EQ((int)x
.length(), ioctx
.getxattr("foo.copy", "myattr", x2
));
453 ASSERT_TRUE(x
.contents_equal(x2
));
457 ObjectWriteOperation op
;
458 op
.copy_from("big", ioctx
, 0, LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
459 ASSERT_EQ(0, ioctx
.operate("big.copy2", &op
));
462 ASSERT_EQ((int)bl
.length(), ioctx
.read("big.copy2", bl2
, bl
.length(), 0));
463 ASSERT_TRUE(bl
.contents_equal(bl2
));
464 ASSERT_EQ((int)x
.length(), ioctx
.getxattr("foo.copy2", "myattr", x2
));
465 ASSERT_TRUE(x
.contents_equal(x2
));
469 class LibRadosTwoPoolsECPP
: public RadosTestECPP
472 LibRadosTwoPoolsECPP() {};
473 ~LibRadosTwoPoolsECPP() override
{};
475 static void SetUpTestCase() {
477 pool_name
= get_temp_pool_name();
478 ASSERT_EQ("", create_one_ec_pool_pp(pool_name
, s_cluster
));
479 src_pool_name
= get_temp_pool_name();
480 ASSERT_EQ(0, s_cluster
.pool_create(src_pool_name
.c_str()));
482 librados::IoCtx ioctx
;
483 ASSERT_EQ(0, s_cluster
.ioctx_create(pool_name
.c_str(), ioctx
));
484 ioctx
.application_enable("rados", true);
486 librados::IoCtx src_ioctx
;
487 ASSERT_EQ(0, s_cluster
.ioctx_create(src_pool_name
.c_str(), src_ioctx
));
488 src_ioctx
.application_enable("rados", true);
490 static void TearDownTestCase() {
492 ASSERT_EQ(0, s_cluster
.pool_delete(src_pool_name
.c_str()));
493 ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name
, s_cluster
));
495 static std::string src_pool_name
;
497 void SetUp() override
{
499 RadosTestECPP::SetUp();
500 ASSERT_EQ(0, cluster
.ioctx_create(src_pool_name
.c_str(), src_ioctx
));
501 src_ioctx
.set_namespace(nspace
);
503 void TearDown() override
{
505 // wait for maps to settle before next test
506 cluster
.wait_for_latest_osdmap();
508 RadosTestECPP::TearDown();
510 cleanup_default_namespace(src_ioctx
);
511 cleanup_namespace(src_ioctx
, nspace
);
516 librados::IoCtx src_ioctx
;
518 std::string
LibRadosTwoPoolsECPP::src_pool_name
;
520 //copy_from between ecpool and no-ecpool.
521 TEST_F(LibRadosTwoPoolsECPP
, CopyFrom
) {
524 z
.append_zero(4194304*2);
526 b
.append("copyfrom");
528 // create big object w/ omapheader
530 ASSERT_EQ(0, src_ioctx
.write_full("foo", z
));
531 ASSERT_EQ(0, src_ioctx
.omap_set_header("foo", b
));
532 version_t uv
= src_ioctx
.get_last_version();
533 ObjectWriteOperation op
;
534 op
.copy_from("foo", src_ioctx
, uv
, 0);
535 ASSERT_EQ(-EOPNOTSUPP
, ioctx
.operate("foo.copy", &op
));
538 // same with small object
540 ASSERT_EQ(0, src_ioctx
.omap_set_header("bar", b
));
541 version_t uv
= src_ioctx
.get_last_version();
542 ObjectWriteOperation op
;
543 op
.copy_from("bar", src_ioctx
, uv
, 0);
544 ASSERT_EQ(-EOPNOTSUPP
, ioctx
.operate("bar.copy", &op
));
548 TEST_F(LibRadosMiscPP
, CopyScrubPP
) {
550 bufferlist inbl
, bl
, x
;
551 for (int i
=0; i
<100; ++i
)
552 x
.append("barrrrrrrrrrrrrrrrrrrrrrrrrr");
553 bl
.append(buffer::create(g_conf()->osd_copyfrom_max_chunk
* 3));
558 map
<string
, bufferlist
> to_set
;
559 for (int i
=0; i
<1000; ++i
)
560 to_set
[string("foo") + stringify(i
)] = x
;
564 ASSERT_EQ(0, ioctx
.write_full("small", cbl
));
565 ASSERT_EQ(0, ioctx
.setxattr("small", "myattr", x
));
569 ASSERT_EQ(0, ioctx
.write_full("big", cbl
));
573 ASSERT_EQ(0, ioctx
.write_full("big2", cbl
));
574 ASSERT_EQ(0, ioctx
.setxattr("big2", "myattr", x
));
575 ASSERT_EQ(0, ioctx
.setxattr("big2", "myattr2", x
));
576 ASSERT_EQ(0, ioctx
.omap_set("big2", to_set
));
580 ASSERT_EQ(0, ioctx
.write_full("big3", cbl
));
581 ASSERT_EQ(0, ioctx
.omap_set_header("big3", x
));
582 ASSERT_EQ(0, ioctx
.omap_set("big3", to_set
));
584 // deep scrub to ensure digests are in place
586 for (int i
=0; i
<10; ++i
) {
588 ss
<< "{\"prefix\": \"pg deep-scrub\", \"pgid\": \""
589 << ioctx
.get_id() << "." << i
591 cluster
.mon_command(ss
.str(), inbl
, NULL
, NULL
);
594 // give it a few seconds to go. this is sloppy but is usually enough time
595 cout
<< "waiting for initial deep scrubs..." << std::endl
;
597 cout
<< "done waiting, doing copies" << std::endl
;
601 ObjectWriteOperation op
;
602 op
.copy_from("small", ioctx
, 0, 0);
603 ASSERT_EQ(0, ioctx
.operate("small.copy", &op
));
607 ObjectWriteOperation op
;
608 op
.copy_from("big", ioctx
, 0, 0);
609 ASSERT_EQ(0, ioctx
.operate("big.copy", &op
));
613 ObjectWriteOperation op
;
614 op
.copy_from("big2", ioctx
, 0, 0);
615 ASSERT_EQ(0, ioctx
.operate("big2.copy", &op
));
619 ObjectWriteOperation op
;
620 op
.copy_from("big3", ioctx
, 0, 0);
621 ASSERT_EQ(0, ioctx
.operate("big3.copy", &op
));
624 // deep scrub to ensure digests are correct
626 for (int i
=0; i
<10; ++i
) {
628 ss
<< "{\"prefix\": \"pg deep-scrub\", \"pgid\": \""
629 << ioctx
.get_id() << "." << i
631 cluster
.mon_command(ss
.str(), inbl
, NULL
, NULL
);
634 // give it a few seconds to go. this is sloppy but is usually enough time
635 cout
<< "waiting for final deep scrubs..." << std::endl
;
637 cout
<< "done waiting" << std::endl
;
641 TEST_F(LibRadosMiscPP
, WriteSamePP
) {
648 /* zero the full range before using writesame */
649 memset(full
, 0, sizeof(full
));
650 fl
.append(full
, sizeof(full
));
651 ASSERT_EQ(0, ioctx
.write("ws", fl
, fl
.length(), 0));
653 memset(buf
, 0xcc, sizeof(buf
));
655 bl
.append(buf
, sizeof(buf
));
656 /* write the same buf four times */
657 ASSERT_EQ(0, ioctx
.writesame("ws", bl
, sizeof(full
), 0));
659 /* read back the full buffer and confirm that it matches */
661 fl
.append(full
, sizeof(full
));
662 ASSERT_EQ((int)fl
.length(), ioctx
.read("ws", fl
, fl
.length(), 0));
664 for (cmp
= fl
.c_str(); cmp
< fl
.c_str() + fl
.length(); cmp
+= sizeof(buf
)) {
665 ASSERT_EQ(0, memcmp(cmp
, buf
, sizeof(buf
)));
668 /* write_len not a multiple of data_len should throw error */
670 bl
.append(buf
, sizeof(buf
));
671 ASSERT_EQ(-EINVAL
, ioctx
.writesame("ws", bl
, (sizeof(buf
) * 4) - 1, 0));
673 ioctx
.writesame("ws", bl
, bl
.length() / 2, 0));
674 /* write_len = data_len, i.e. same as write() */
675 ASSERT_EQ(0, ioctx
.writesame("ws", bl
, sizeof(buf
), 0));
678 ioctx
.writesame("ws", bl
, sizeof(buf
), 0));
681 template <typename T
>
682 class LibRadosChecksum
: public LibRadosMiscPP
{
684 typedef typename
T::alg_t alg_t
;
685 typedef typename
T::value_t value_t
;
686 typedef typename
alg_t::init_value_t init_value_t
;
688 static const rados_checksum_type_t type
= T::type
;
690 bufferlist content_bl
;
692 using LibRadosMiscPP::SetUpTestCase
;
693 using LibRadosMiscPP::TearDownTestCase
;
695 void SetUp() override
{
696 LibRadosMiscPP::SetUp();
698 std::string
content(4096, '\0');
699 for (size_t i
= 0; i
< content
.length(); ++i
) {
700 content
[i
] = static_cast<char>(rand() % (126 - 33) + 33);
702 content_bl
.append(content
);
703 ASSERT_EQ(0, ioctx
.write("foo", content_bl
, content_bl
.length(), 0));
707 template <rados_checksum_type_t _type
, typename AlgT
, typename ValueT
>
708 class LibRadosChecksumParams
{
711 typedef ValueT value_t
;
712 static const rados_checksum_type_t type
= _type
;
715 typedef ::testing::Types
<
716 LibRadosChecksumParams
<LIBRADOS_CHECKSUM_TYPE_XXHASH32
,
717 Checksummer::xxhash32
, ceph_le32
>,
718 LibRadosChecksumParams
<LIBRADOS_CHECKSUM_TYPE_XXHASH64
,
719 Checksummer::xxhash64
, ceph_le64
>,
720 LibRadosChecksumParams
<LIBRADOS_CHECKSUM_TYPE_CRC32C
,
721 Checksummer::crc32c
, ceph_le32
>
722 > LibRadosChecksumTypes
;
724 TYPED_TEST_SUITE(LibRadosChecksum
, LibRadosChecksumTypes
);
726 TYPED_TEST(LibRadosChecksum
, Subset
) {
727 uint32_t chunk_size
= 1024;
728 uint32_t csum_count
= this->content_bl
.length() / chunk_size
;
730 typename
TestFixture::init_value_t init_value
= -1;
731 bufferlist init_value_bl
;
732 encode(init_value
, init_value_bl
);
734 std::vector
<bufferlist
> checksum_bls(csum_count
);
735 std::vector
<int> checksum_rvals(csum_count
);
737 // individual checksum ops for each chunk
738 ObjectReadOperation op
;
739 for (uint32_t i
= 0; i
< csum_count
; ++i
) {
740 op
.checksum(TestFixture::type
, init_value_bl
, i
* chunk_size
, chunk_size
,
741 0, &checksum_bls
[i
], &checksum_rvals
[i
]);
743 ASSERT_EQ(0, this->ioctx
.operate("foo", &op
, NULL
));
745 for (uint32_t i
= 0; i
< csum_count
; ++i
) {
746 ASSERT_EQ(0, checksum_rvals
[i
]);
748 auto bl_it
= checksum_bls
[i
].cbegin();
750 decode(count
, bl_it
);
751 ASSERT_EQ(1U, count
);
753 typename
TestFixture::value_t value
;
754 decode(value
, bl_it
);
756 bufferlist content_sub_bl
;
757 content_sub_bl
.substr_of(this->content_bl
, i
* chunk_size
, chunk_size
);
759 typename
TestFixture::value_t expected_value
;
760 bufferptr expected_value_bp
= buffer::create_static(
761 sizeof(expected_value
), reinterpret_cast<char*>(&expected_value
));
762 Checksummer::template calculate
<typename
TestFixture::alg_t
>(
763 init_value
, chunk_size
, 0, chunk_size
, content_sub_bl
,
765 ASSERT_EQ(expected_value
, value
);
769 TYPED_TEST(LibRadosChecksum
, Chunked
) {
770 uint32_t chunk_size
= 1024;
771 uint32_t csum_count
= this->content_bl
.length() / chunk_size
;
773 typename
TestFixture::init_value_t init_value
= -1;
774 bufferlist init_value_bl
;
775 encode(init_value
, init_value_bl
);
777 bufferlist checksum_bl
;
780 // single op with chunked checksum results
781 ObjectReadOperation op
;
782 op
.checksum(TestFixture::type
, init_value_bl
, 0, this->content_bl
.length(),
783 chunk_size
, &checksum_bl
, &checksum_rval
);
784 ASSERT_EQ(0, this->ioctx
.operate("foo", &op
, NULL
));
785 ASSERT_EQ(0, checksum_rval
);
787 auto bl_it
= checksum_bl
.cbegin();
789 decode(count
, bl_it
);
790 ASSERT_EQ(csum_count
, count
);
792 std::vector
<typename
TestFixture::value_t
> expected_values(csum_count
);
793 bufferptr expected_values_bp
= buffer::create_static(
794 csum_count
* sizeof(typename
TestFixture::value_t
),
795 reinterpret_cast<char*>(&expected_values
[0]));
797 Checksummer::template calculate
<typename
TestFixture::alg_t
>(
798 init_value
, chunk_size
, 0, this->content_bl
.length(), this->content_bl
,
799 &expected_values_bp
);
801 for (uint32_t i
= 0; i
< csum_count
; ++i
) {
802 typename
TestFixture::value_t value
;
803 decode(value
, bl_it
);
804 ASSERT_EQ(expected_values
[i
], value
);
808 TEST_F(LibRadosMiscPP
, CmpExtPP
) {
809 bufferlist cmp_bl
, bad_cmp_bl
, write_bl
;
810 char stored_str
[] = "1234567891";
811 char mismatch_str
[] = "1234577777";
813 write_bl
.append(stored_str
);
814 ioctx
.write("cmpextpp", write_bl
, write_bl
.length(), 0);
815 cmp_bl
.append(stored_str
);
816 ASSERT_EQ(0, ioctx
.cmpext("cmpextpp", 0, cmp_bl
));
818 bad_cmp_bl
.append(mismatch_str
);
819 ASSERT_EQ(-MAX_ERRNO
- 5, ioctx
.cmpext("cmpextpp", 0, bad_cmp_bl
));
822 TEST_F(LibRadosMiscPP
, Applications
) {
823 bufferlist inbl
, outbl
;
825 ASSERT_EQ(0, cluster
.mon_command("{\"prefix\": \"osd dump\"}",
826 inbl
, &outbl
, &outs
));
827 ASSERT_LT(0u, outbl
.length());
828 ASSERT_LE(0u, outs
.length());
829 if (!std::regex_search(outbl
.to_str(),
830 std::regex("require_osd_release [l-z]"))) {
831 std::cout
<< "SKIPPING";
835 std::set
<std::string
> expected_apps
= {"rados"};
836 std::set
<std::string
> apps
;
837 ASSERT_EQ(0, ioctx
.application_list(&apps
));
838 ASSERT_EQ(expected_apps
, apps
);
840 ASSERT_EQ(0, ioctx
.application_enable("app1", true));
841 ASSERT_EQ(-EPERM
, ioctx
.application_enable("app2", false));
842 ASSERT_EQ(0, ioctx
.application_enable("app2", true));
844 expected_apps
= {"app1", "app2", "rados"};
845 ASSERT_EQ(0, ioctx
.application_list(&apps
));
846 ASSERT_EQ(expected_apps
, apps
);
848 std::map
<std::string
, std::string
> expected_meta
;
849 std::map
<std::string
, std::string
> meta
;
850 ASSERT_EQ(-ENOENT
, ioctx
.application_metadata_list("dne", &meta
));
851 ASSERT_EQ(0, ioctx
.application_metadata_list("app1", &meta
));
852 ASSERT_EQ(expected_meta
, meta
);
854 ASSERT_EQ(-ENOENT
, ioctx
.application_metadata_set("dne", "key1", "value1"));
855 ASSERT_EQ(0, ioctx
.application_metadata_set("app1", "key1", "value1"));
856 ASSERT_EQ(0, ioctx
.application_metadata_set("app1", "key2", "value2"));
858 expected_meta
= {{"key1", "value1"}, {"key2", "value2"}};
859 ASSERT_EQ(0, ioctx
.application_metadata_list("app1", &meta
));
860 ASSERT_EQ(expected_meta
, meta
);
862 ASSERT_EQ(0, ioctx
.application_metadata_remove("app1", "key1"));
864 expected_meta
= {{"key2", "value2"}};
865 ASSERT_EQ(0, ioctx
.application_metadata_list("app1", &meta
));
866 ASSERT_EQ(expected_meta
, meta
);
869 TEST_F(LibRadosMiscECPP
, CompareExtentRange
) {
873 ObjectWriteOperation write
;
875 ASSERT_EQ(0, ioctx
.operate("foo", &write
));
879 bl2
.append(std::string(2, '\0'));
880 ObjectReadOperation read1
;
881 read1
.cmpext(2, bl2
, nullptr);
882 ASSERT_EQ(0, ioctx
.operate("foo", &read1
, nullptr));
885 bl3
.append(std::string(4, '\0'));
886 ObjectReadOperation read2
;
887 read2
.cmpext(2097152, bl3
, nullptr);
888 ASSERT_EQ(0, ioctx
.operate("foo", &read2
, nullptr));
891 TEST_F(LibRadosMiscPP
, MinCompatOSD
) {
892 int8_t require_osd_release
;
893 ASSERT_EQ(0, cluster
.get_min_compatible_osd(&require_osd_release
));
894 ASSERT_LE(-1, require_osd_release
);
895 ASSERT_GT(CEPH_RELEASE_MAX
, require_osd_release
);
898 TEST_F(LibRadosMiscPP
, MinCompatClient
) {
899 int8_t min_compat_client
;
900 int8_t require_min_compat_client
;
901 ASSERT_EQ(0, cluster
.get_min_compatible_client(&min_compat_client
,
902 &require_min_compat_client
));
903 ASSERT_LE(-1, min_compat_client
);
904 ASSERT_GT(CEPH_RELEASE_MAX
, min_compat_client
);
906 ASSERT_LE(-1, require_min_compat_client
);
907 ASSERT_GT(CEPH_RELEASE_MAX
, require_min_compat_client
);
910 TEST_F(LibRadosMiscPP
, Conf
) {
911 const char* const option
= "bluestore_throttle_bytes";
912 size_t new_size
= 1 << 20;
913 std::string original
;
914 ASSERT_EQ(0, cluster
.conf_get(option
, original
));
915 auto restore_setting
= make_scope_guard([&] {
916 cluster
.conf_set(option
, original
.c_str());
918 std::string expected
= std::to_string(new_size
);
919 ASSERT_EQ(0, cluster
.conf_set(option
, expected
.c_str()));
921 ASSERT_EQ(0, cluster
.conf_get(option
, actual
));
922 ASSERT_EQ(expected
, actual
);