summaryrefslogtreecommitdiffstats
path: root/src/test/libradosstriper
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/test/libradosstriper
parentInitial commit. (diff)
downloadceph-upstream.tar.xz
ceph-upstream.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/test/libradosstriper/CMakeLists.txt34
-rw-r--r--src/test/libradosstriper/TestCase.cc80
-rw-r--r--src/test/libradosstriper/TestCase.h82
-rw-r--r--src/test/libradosstriper/aio.cc617
-rw-r--r--src/test/libradosstriper/io.cc406
-rw-r--r--src/test/libradosstriper/striping.cc329
6 files changed, 1548 insertions, 0 deletions
diff --git a/src/test/libradosstriper/CMakeLists.txt b/src/test/libradosstriper/CMakeLists.txt
new file mode 100644
index 00000000..8e53a300
--- /dev/null
+++ b/src/test/libradosstriper/CMakeLists.txt
@@ -0,0 +1,34 @@
+#
+# Note: only compiled if WITH_LIBRADOSSTRIPER is defined.
+#
+add_library(rados_striper_test STATIC TestCase.cc)
+target_link_libraries(rados_striper_test
+ radostest
+ radostest-cxx
+ GTest::GTest)
+
+add_executable(ceph_test_rados_striper_api_striping
+ striping.cc
+ )
+target_link_libraries(ceph_test_rados_striper_api_striping
+ ${UNITTEST_LIBS} rados_striper_test
+ radosstriper
+ librados)
+install(TARGETS ceph_test_rados_striper_api_striping
+ DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+add_executable(ceph_test_rados_striper_api_io
+ io.cc)
+target_link_libraries(ceph_test_rados_striper_api_io
+ ${UNITTEST_LIBS} rados_striper_test
+ radosstriper
+ librados)
+install(TARGETS ceph_test_rados_striper_api_io
+ DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+add_executable(ceph_test_rados_striper_api_aio
+ aio.cc)
+target_link_libraries(ceph_test_rados_striper_api_aio librados radosstriper
+ ${UNITTEST_LIBS} rados_striper_test)
+install(TARGETS ceph_test_rados_striper_api_aio
+ DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/test/libradosstriper/TestCase.cc b/src/test/libradosstriper/TestCase.cc
new file mode 100644
index 00000000..98e81f49
--- /dev/null
+++ b/src/test/libradosstriper/TestCase.cc
@@ -0,0 +1,80 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <errno.h>
+#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
+#include "test/libradosstriper/TestCase.h"
+
+using namespace libradosstriper;
+
+std::string StriperTest::pool_name;
+rados_t StriperTest::s_cluster = NULL;
+
+void StriperTest::SetUpTestCase()
+{
+ pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool(pool_name, &s_cluster));
+}
+
+void StriperTest::TearDownTestCase()
+{
+ ASSERT_EQ(0, destroy_one_pool(pool_name, &s_cluster));
+}
+
+void StriperTest::SetUp()
+{
+ cluster = StriperTest::s_cluster;
+ ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
+ ASSERT_EQ(0, rados_striper_create(ioctx, &striper));
+}
+
+void StriperTest::TearDown()
+{
+ rados_striper_destroy(striper);
+ rados_ioctx_destroy(ioctx);
+}
+
+std::string StriperTestPP::pool_name;
+librados::Rados StriperTestPP::s_cluster;
+
+void StriperTestPP::SetUpTestCase()
+{
+ pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, s_cluster));
+}
+
+void StriperTestPP::TearDownTestCase()
+{
+ ASSERT_EQ(0, destroy_one_pool_pp(pool_name, s_cluster));
+}
+
+void StriperTestPP::SetUp()
+{
+ ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
+ ASSERT_EQ(0, RadosStriper::striper_create(ioctx, &striper));
+}
+
+// this is pure copy and paste from previous class
+// but for the inheritance from TestWithParam
+// with gtest >= 1.6, we couldd avoid this by using
+// inheritance from WithParamInterface
+std::string StriperTestParam::pool_name;
+librados::Rados StriperTestParam::s_cluster;
+
+void StriperTestParam::SetUpTestCase()
+{
+ pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, s_cluster));
+}
+
+void StriperTestParam::TearDownTestCase()
+{
+ ASSERT_EQ(0, destroy_one_pool_pp(pool_name, s_cluster));
+}
+
+void StriperTestParam::SetUp()
+{
+ ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
+ ASSERT_EQ(0, RadosStriper::striper_create(ioctx, &striper));
+}
diff --git a/src/test/libradosstriper/TestCase.h b/src/test/libradosstriper/TestCase.h
new file mode 100644
index 00000000..c316b3bf
--- /dev/null
+++ b/src/test/libradosstriper/TestCase.h
@@ -0,0 +1,82 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_TEST_RADOS_TESTCASE_H
+#define CEPH_TEST_RADOS_TESTCASE_H
+
+#include "include/rados/librados.h"
+#include "include/rados/librados.hpp"
+#include "include/radosstriper/libradosstriper.h"
+#include "include/radosstriper/libradosstriper.hpp"
+#include "gtest/gtest.h"
+
+#include <string>
+
+/**
+ * These test cases create a temporary pool that lives as long as the
+ * test case. Each test within a test case gets a new ioctx and striper
+ * set to a unique namespace within the pool.
+ *
+ * Since pool creation and deletion is slow, this allows many tests to
+ * run faster.
+ */
+class StriperTest : public ::testing::Test {
+public:
+ StriperTest() {}
+ ~StriperTest() override {}
+protected:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+ static rados_t s_cluster;
+ static std::string pool_name;
+
+ void SetUp() override;
+ void TearDown() override;
+ rados_t cluster = NULL;
+ rados_ioctx_t ioctx = NULL;
+ rados_striper_t striper = NULL;
+};
+
+class StriperTestPP : public ::testing::Test {
+public:
+ StriperTestPP() : cluster(s_cluster) {}
+ ~StriperTestPP() override {}
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+protected:
+ static librados::Rados s_cluster;
+ static std::string pool_name;
+
+ void SetUp() override;
+ librados::Rados &cluster;
+ librados::IoCtx ioctx;
+ libradosstriper::RadosStriper striper;
+};
+
+struct TestData {
+ uint32_t stripe_unit;
+ uint32_t stripe_count;
+ uint32_t object_size;
+ size_t size;
+};
+// this is pure copy and paste from previous class
+// but for the inheritance from TestWithParam
+// with gtest >= 1.6, we couldd avoid this by using
+// inheritance from WithParamInterface
+class StriperTestParam : public ::testing::TestWithParam<TestData> {
+public:
+ StriperTestParam() : cluster(s_cluster) {}
+ ~StriperTestParam() override {}
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+protected:
+ static librados::Rados s_cluster;
+ static std::string pool_name;
+
+ void SetUp() override;
+ librados::Rados &cluster;
+ librados::IoCtx ioctx;
+ libradosstriper::RadosStriper striper;
+};
+
+#endif
diff --git a/src/test/libradosstriper/aio.cc b/src/test/libradosstriper/aio.cc
new file mode 100644
index 00000000..6c3d612c
--- /dev/null
+++ b/src/test/libradosstriper/aio.cc
@@ -0,0 +1,617 @@
+#include "include/rados/librados.h"
+#include "include/rados/librados.hpp"
+#include "include/radosstriper/libradosstriper.h"
+#include "include/radosstriper/libradosstriper.hpp"
+#include "test/librados/test.h"
+#include "test/libradosstriper/TestCase.h"
+
+#include <boost/scoped_ptr.hpp>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <errno.h>
+
+using namespace librados;
+using namespace libradosstriper;
+using std::pair;
+
+class AioTestData
+{
+public:
+ AioTestData() : m_complete(false), m_safe(false) {
+ m_sem = sem_open("test_libradosstriper_aio_sem", O_CREAT, 0644, 0);
+ }
+
+ ~AioTestData() {
+ sem_unlink("test_libradosstriper_aio_sem");
+ sem_close(m_sem);
+ }
+
+ sem_t *m_sem;
+ bool m_complete;
+ bool m_safe;
+};
+
+void set_completion_complete(rados_completion_t cb, void *arg)
+{
+ AioTestData *test = static_cast<AioTestData*>(arg);
+ test->m_complete = true;
+ sem_post(test->m_sem);
+}
+
+void set_completion_safe(rados_completion_t cb, void *arg)
+{
+ AioTestData *test = static_cast<AioTestData*>(arg);
+ test->m_safe = true;
+ sem_post(test->m_sem);
+}
+
+TEST_F(StriperTest, SimpleWrite) {
+ AioTestData test_data;
+ rados_completion_t my_completion;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion));
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_aio_write(striper, "StriperTest", my_completion, buf, sizeof(buf), 0));
+ TestAlarm alarm;
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ rados_aio_release(my_completion);
+}
+
+TEST_F(StriperTestPP, SimpleWritePP) {
+ AioTestData test_data;
+ AioCompletion *my_completion = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.aio_write("SimpleWritePP", my_completion, bl1, sizeof(buf), 0));
+ TestAlarm alarm;
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ my_completion->release();
+}
+
+TEST_F(StriperTest, WaitForSafe) {
+ AioTestData test_data;
+ rados_completion_t my_completion;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion));
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_aio_write(striper, "WaitForSafe", my_completion, buf, sizeof(buf), 0));
+ TestAlarm alarm;
+ rados_aio_wait_for_safe(my_completion);
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ rados_aio_release(my_completion);
+}
+
+TEST_F(StriperTestPP, WaitForSafePP) {
+ AioTestData test_data;
+ AioCompletion *my_completion = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.aio_write("WaitForSafePP", my_completion, bl1, sizeof(buf), 0));
+ TestAlarm alarm;
+ my_completion->wait_for_safe();
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ my_completion->release();
+}
+
+TEST_F(StriperTest, RoundTrip) {
+ AioTestData test_data;
+ rados_completion_t my_completion;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion));
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_aio_write(striper, "RoundTrip", my_completion, buf, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ }
+ char buf2[128];
+ memset(buf2, 0, sizeof(buf2));
+ rados_completion_t my_completion2;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion2));
+ ASSERT_EQ(0, rados_striper_aio_read(striper, "RoundTrip", my_completion2, buf2, sizeof(buf2), 0));
+ {
+ TestAlarm alarm;
+ rados_aio_wait_for_complete(my_completion2);
+ }
+ ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ rados_aio_release(my_completion);
+ rados_aio_release(my_completion2);
+}
+
+TEST_F(StriperTest, RoundTrip2) {
+ AioTestData test_data;
+ rados_completion_t my_completion;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion));
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_aio_write(striper, "RoundTrip2", my_completion, buf, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ }
+ char buf2[128];
+ memset(buf2, 0, sizeof(buf2));
+ rados_completion_t my_completion2;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion2));
+ ASSERT_EQ(0, rados_striper_aio_read(striper, "RoundTrip2", my_completion2, buf2, sizeof(buf2), 0));
+ {
+ TestAlarm alarm;
+ rados_aio_wait_for_safe(my_completion2);
+ }
+ ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ rados_aio_release(my_completion);
+ rados_aio_release(my_completion2);
+}
+
+TEST_F(StriperTestPP, RoundTripPP) {
+ AioTestData test_data;
+ AioCompletion *my_completion = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.aio_write("RoundTripPP", my_completion, bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ }
+ bufferlist bl2;
+ AioCompletion *my_completion2 = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ ASSERT_EQ(0, striper.aio_read("RoundTripPP", my_completion2, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ my_completion2->wait_for_complete();
+ }
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ my_completion->release();
+ my_completion2->release();
+}
+
+TEST_F(StriperTestPP, RoundTripPP2) {
+ AioTestData test_data;
+ AioCompletion *my_completion = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.aio_write("RoundTripPP2", my_completion, bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ }
+ bufferlist bl2;
+ AioCompletion *my_completion2 = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ ASSERT_EQ(0, striper.aio_read("RoundTripPP2", my_completion2, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ my_completion2->wait_for_safe();
+ }
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ my_completion->release();
+ my_completion2->release();
+}
+
+TEST_F(StriperTest, IsComplete) {
+ AioTestData test_data;
+ rados_completion_t my_completion;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion));
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_aio_write(striper, "IsComplete", my_completion, buf, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ }
+ char buf2[128];
+ memset(buf2, 0, sizeof(buf2));
+ rados_completion_t my_completion2;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion2));
+ ASSERT_EQ(0, rados_striper_aio_read(striper, "IsComplete", my_completion2, buf2, sizeof(buf2), 0));
+ {
+ TestAlarm alarm;
+ // Busy-wait until the AIO completes.
+ // Normally we wouldn't do this, but we want to test rados_aio_is_complete.
+ while (true) {
+ int is_complete = rados_aio_is_complete(my_completion2);
+ if (is_complete)
+ break;
+ }
+ }
+ ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ rados_aio_release(my_completion);
+ rados_aio_release(my_completion2);
+}
+
+TEST_F(StriperTestPP, IsCompletePP) {
+ AioTestData test_data;
+ AioCompletion *my_completion = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.aio_write("IsCompletePP", my_completion, bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ }
+ bufferlist bl2;
+ AioCompletion *my_completion2 = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ ASSERT_EQ(0, striper.aio_read("IsCompletePP", my_completion2, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ // Busy-wait until the AIO completes.
+ // Normally we wouldn't do this, but we want to test rados_aio_is_complete.
+ while (true) {
+ int is_complete = my_completion2->is_complete();
+ if (is_complete)
+ break;
+ }
+ }
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ my_completion->release();
+ my_completion2->release();
+}
+
+TEST_F(StriperTest, IsSafe) {
+ AioTestData test_data;
+ rados_completion_t my_completion;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion));
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_aio_write(striper, "IsSafe", my_completion, buf, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ // Busy-wait until the AIO completes.
+ // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
+ while (true) {
+ int is_safe = rados_aio_is_safe(my_completion);
+ if (is_safe)
+ break;
+ }
+ }
+ char buf2[128];
+ memset(buf2, 0, sizeof(buf2));
+ rados_completion_t my_completion2;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion2));
+ ASSERT_EQ(0, rados_striper_aio_read(striper, "IsSafe", my_completion2, buf2, sizeof(buf2), 0));
+ {
+ TestAlarm alarm;
+ rados_aio_wait_for_complete(my_completion2);
+ }
+ ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ rados_aio_release(my_completion);
+ rados_aio_release(my_completion2);
+}
+
+TEST_F(StriperTestPP, IsSafePP) {
+ AioTestData test_data;
+ AioCompletion *my_completion = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.aio_write("IsSafePP", my_completion, bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ // Busy-wait until the AIO completes.
+ // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
+ while (true) {
+ int is_safe = my_completion->is_safe();
+ if (is_safe)
+ break;
+ }
+ }
+ bufferlist bl2;
+ AioCompletion *my_completion2 = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ ASSERT_EQ(0, striper.aio_read("IsSafePP", my_completion2, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ my_completion2->wait_for_complete();
+ }
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ my_completion->release();
+ my_completion2->release();
+}
+
+TEST_F(StriperTest, RoundTripAppend) {
+ AioTestData test_data;
+ rados_completion_t my_completion, my_completion2, my_completion3;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion));
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_aio_append(striper, "RoundTripAppend", my_completion, buf, sizeof(buf)));
+ {
+ TestAlarm alarm;
+ rados_aio_wait_for_complete(my_completion);
+ }
+ char buf2[128];
+ memset(buf2, 0xdd, sizeof(buf2));
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion2));
+ ASSERT_EQ(0, rados_striper_aio_append(striper, "RoundTripAppend", my_completion2, buf2, sizeof(buf)));
+ {
+ TestAlarm alarm;
+ rados_aio_wait_for_complete(my_completion2);
+ }
+ char buf3[sizeof(buf) + sizeof(buf2)];
+ memset(buf3, 0, sizeof(buf3));
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion3));
+ ASSERT_EQ(0, rados_striper_aio_read(striper, "RoundTripAppend", my_completion3, buf3, sizeof(buf3), 0));
+ {
+ TestAlarm alarm;
+ rados_aio_wait_for_complete(my_completion3);
+ }
+ ASSERT_EQ((int)(sizeof(buf) + sizeof(buf2)), rados_aio_get_return_value(my_completion3));
+ ASSERT_EQ(0, memcmp(buf3, buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(buf3 + sizeof(buf), buf2, sizeof(buf2)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ rados_aio_release(my_completion);
+ rados_aio_release(my_completion2);
+ rados_aio_release(my_completion3);
+}
+
+TEST_F(StriperTestPP, RoundTripAppendPP) {
+ AioTestData test_data;
+ AioCompletion *my_completion = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.aio_append("RoundTripAppendPP", my_completion, bl1, sizeof(buf)));
+ {
+ TestAlarm alarm;
+ my_completion->wait_for_complete();
+ }
+ char buf2[128];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ AioCompletion *my_completion2 = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ ASSERT_EQ(0, striper.aio_append("RoundTripAppendPP", my_completion2, bl2, sizeof(buf2)));
+ {
+ TestAlarm alarm;
+ my_completion2->wait_for_complete();
+ }
+ bufferlist bl3;
+ AioCompletion *my_completion3 = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ ASSERT_EQ(0, striper.aio_read("RoundTripAppendPP", my_completion3, &bl3, 2 * sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ my_completion3->wait_for_complete();
+ }
+ ASSERT_EQ(sizeof(buf) + sizeof(buf2), (unsigned)my_completion3->get_return_value());
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf), buf2, sizeof(buf2)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ my_completion->release();
+ my_completion2->release();
+ my_completion3->release();
+}
+
+TEST_F(StriperTest, Flush) {
+ AioTestData test_data;
+ rados_completion_t my_completion;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion));
+ char buf[128];
+ memset(buf, 0xee, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_aio_write(striper, "Flush", my_completion, buf, sizeof(buf), 0));
+ rados_striper_aio_flush(striper);
+ char buf2[128];
+ memset(buf2, 0, sizeof(buf2));
+ rados_completion_t my_completion2;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion2));
+ ASSERT_EQ(0, rados_striper_aio_read(striper, "Flush", my_completion2, buf2, sizeof(buf2), 0));
+ {
+ TestAlarm alarm;
+ rados_aio_wait_for_complete(my_completion2);
+ }
+ ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ rados_aio_release(my_completion);
+ rados_aio_release(my_completion2);
+}
+
+TEST_F(StriperTestPP, FlushPP) {
+ AioTestData test_data;
+ AioCompletion *my_completion = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ char buf[128];
+ memset(buf, 0xee, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.aio_write("FlushPP", my_completion, bl1, sizeof(buf), 0));
+ striper.aio_flush();
+ bufferlist bl2;
+ AioCompletion *my_completion2 = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ ASSERT_EQ(0, striper.aio_read("FlushPP", my_completion2, &bl2, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ my_completion2->wait_for_complete();
+ }
+ ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ my_completion->release();
+ my_completion2->release();
+}
+
+TEST_F(StriperTest, RoundTripWriteFull) {
+ AioTestData test_data;
+ rados_completion_t my_completion, my_completion2, my_completion3;
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion));
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_aio_write(striper, "RoundTripWriteFull", my_completion, buf, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ rados_aio_wait_for_complete(my_completion);
+ }
+ char buf2[64];
+ memset(buf2, 0xdd, sizeof(buf2));
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion2));
+ ASSERT_EQ(0, rados_striper_aio_write_full(striper, "RoundTripWriteFull", my_completion2, buf2, sizeof(buf2)));
+ {
+ TestAlarm alarm;
+ rados_aio_wait_for_complete(my_completion2);
+ }
+ char buf3[sizeof(buf) + sizeof(buf2)];
+ memset(buf3, 0, sizeof(buf3));
+ ASSERT_EQ(0, rados_aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe, &my_completion3));
+ ASSERT_EQ(0, rados_striper_aio_read(striper, "RoundTripWriteFull", my_completion3, buf3, sizeof(buf3), 0));
+ {
+ TestAlarm alarm;
+ rados_aio_wait_for_complete(my_completion3);
+ }
+ ASSERT_EQ(sizeof(buf2), (unsigned)rados_aio_get_return_value(my_completion3));
+ ASSERT_EQ(0, memcmp(buf3, buf2, sizeof(buf2)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ rados_aio_release(my_completion);
+ rados_aio_release(my_completion2);
+ rados_aio_release(my_completion3);
+}
+
+TEST_F(StriperTestPP, RoundTripWriteFullPP) {
+ AioTestData test_data;
+ AioCompletion *my_completion = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.aio_write("RoundTripWriteFullPP", my_completion, bl1, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ my_completion->wait_for_complete();
+ }
+ char buf2[64];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ AioCompletion *my_completion2 = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ ASSERT_EQ(0, striper.aio_write_full("RoundTripWriteFullPP", my_completion2, bl2));
+ {
+ TestAlarm alarm;
+ my_completion2->wait_for_complete();
+ }
+ bufferlist bl3;
+ AioCompletion *my_completion3 = librados::Rados::aio_create_completion
+ ((void*)&test_data, set_completion_complete, set_completion_safe);
+ ASSERT_EQ(0, striper.aio_read("RoundTripWriteFullPP", my_completion3, &bl3, sizeof(buf), 0));
+ {
+ TestAlarm alarm;
+ my_completion3->wait_for_complete();
+ }
+ ASSERT_EQ(sizeof(buf2), (unsigned)my_completion3->get_return_value());
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
+ sem_wait(test_data.m_sem);
+ sem_wait(test_data.m_sem);
+ my_completion->release();
+ my_completion2->release();
+ my_completion3->release();
+}
+
+TEST_F(StriperTest, RemoveTest) {
+ char buf[128];
+ char buf2[sizeof(buf)];
+ // create oabject
+ memset(buf, 0xaa, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "RemoveTest", buf, sizeof(buf), 0));
+ // async remove it
+ AioTestData test_data;
+ rados_completion_t my_completion;
+ ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
+ set_completion_complete, set_completion_safe, &my_completion));
+ ASSERT_EQ(0, rados_striper_aio_remove(striper, "RemoveTest", my_completion));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
+ }
+ ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
+ rados_aio_release(my_completion);
+ // check we get ENOENT on reading
+ ASSERT_EQ(-ENOENT, rados_striper_read(striper, "RemoveTest", buf2, sizeof(buf2), 0));
+}
+
+TEST_F(StriperTestPP, RemoveTestPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("RemoveTestPP", bl, sizeof(buf), 0));
+ AioCompletion *my_completion = cluster.aio_create_completion(0, 0, 0);
+ ASSERT_EQ(0, striper.aio_remove("RemoveTestPP", my_completion));
+ {
+ TestAlarm alarm;
+ ASSERT_EQ(0, my_completion->wait_for_complete());
+ }
+ ASSERT_EQ(0, my_completion->get_return_value());
+ bufferlist bl2;
+ ASSERT_EQ(-ENOENT, striper.read("RemoveTestPP", &bl2, sizeof(buf), 0));
+ my_completion->release();
+}
diff --git a/src/test/libradosstriper/io.cc b/src/test/libradosstriper/io.cc
new file mode 100644
index 00000000..2f931e5e
--- /dev/null
+++ b/src/test/libradosstriper/io.cc
@@ -0,0 +1,406 @@
+#include "include/rados/librados.h"
+#include "include/rados/librados.hpp"
+#include "include/radosstriper/libradosstriper.h"
+#include "include/radosstriper/libradosstriper.hpp"
+#include "test/librados/test.h"
+#include "test/libradosstriper/TestCase.h"
+
+#include <fcntl.h>
+#include <errno.h>
+#include "gtest/gtest.h"
+
+using namespace librados;
+using namespace libradosstriper;
+using std::string;
+
+TEST_F(StriperTest, SimpleWrite) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "SimpleWrite", buf, sizeof(buf), 0));
+}
+
+TEST_F(StriperTestPP, SimpleWritePP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("SimpleWritePP", bl, sizeof(buf), 0));
+}
+
+TEST_F(StriperTest, SimpleWriteFull) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write_full(striper, "SimpleWrite", buf, sizeof(buf)));
+}
+
+TEST_F(StriperTestPP, SimpleWriteFullPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write_full("SimpleWritePP", bl));
+}
+
+TEST_F(StriperTest, Stat) {
+ uint64_t psize;
+ time_t pmtime;
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "Stat", buf, sizeof(buf), 0));
+ ASSERT_EQ(0, rados_striper_stat(striper, "Stat", &psize, &pmtime));
+ ASSERT_EQ(psize, sizeof(buf));
+ ASSERT_EQ(-ENOENT, rados_striper_stat(striper, "nonexistent", &psize, &pmtime));
+}
+
+TEST_F(StriperTestPP, StatPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("Statpp", bl, sizeof(buf), 0));
+ uint64_t psize;
+ time_t pmtime;
+ ASSERT_EQ(0, striper.stat("Statpp", &psize, &pmtime));
+ ASSERT_EQ(psize, sizeof(buf));
+ ASSERT_EQ(-ENOENT, striper.stat("nonexistent", &psize, &pmtime));
+}
+
+TEST_F(StriperTest, RoundTrip) {
+ char buf[128];
+ char buf2[sizeof(buf)];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "RoundTrip", buf, sizeof(buf), 0));
+ memset(buf2, 0, sizeof(buf2));
+ ASSERT_EQ((int)sizeof(buf2), rados_striper_read(striper, "RoundTrip", buf2, sizeof(buf2), 0));
+ ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+}
+
+TEST_F(StriperTestPP, RoundTripPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("RoundTripPP", bl, sizeof(buf), 0));
+ bufferlist cl;
+ ASSERT_EQ((int)sizeof(buf), striper.read("RoundTripPP", &cl, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(buf, cl.c_str(), sizeof(buf)));
+}
+
+TEST_F(StriperTest, OverlappingWriteRoundTrip) {
+ char buf[128];
+ char buf2[64];
+ char buf3[sizeof(buf)];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "OverlappingWriteRoundTrip", buf, sizeof(buf), 0));
+ memset(buf2, 0xdd, sizeof(buf2));
+ ASSERT_EQ(0, rados_striper_write(striper, "OverlappingWriteRoundTrip", buf2, sizeof(buf2), 0));
+ memset(buf3, 0, sizeof(buf3));
+ ASSERT_EQ((int)sizeof(buf3), rados_striper_read(striper, "OverlappingWriteRoundTrip", buf3, sizeof(buf3), 0));
+ ASSERT_EQ(0, memcmp(buf3, buf2, sizeof(buf2)));
+ ASSERT_EQ(0, memcmp(buf3 + sizeof(buf2), buf, sizeof(buf) - sizeof(buf2)));
+}
+
+TEST_F(StriperTestPP, OverlappingWriteRoundTripPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("OverlappingWriteRoundTripPP", bl1, sizeof(buf), 0));
+ char buf2[64];
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ASSERT_EQ(0, striper.write("OverlappingWriteRoundTripPP", bl2, sizeof(buf2), 0));
+ bufferlist bl3;
+ ASSERT_EQ((int)sizeof(buf), striper.read("OverlappingWriteRoundTripPP", &bl3, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
+ ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf2), buf, sizeof(buf) - sizeof(buf2)));
+}
+
+TEST_F(StriperTest, SparseWriteRoundTrip) {
+ char buf[128];
+ char buf2[2*sizeof(buf)];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "SparseWriteRoundTrip", buf, sizeof(buf), 0));
+ ASSERT_EQ(0, rados_striper_write(striper, "SparseWriteRoundTrip", buf, sizeof(buf), 1000000000));
+ memset(buf2, 0xaa, sizeof(buf2));
+ ASSERT_EQ((int)sizeof(buf2), rados_striper_read(striper, "SparseWriteRoundTrip", buf2, sizeof(buf2), 0));
+ ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+ memset(buf, 0, sizeof(buf));
+ ASSERT_EQ(0, memcmp(buf, buf2+sizeof(buf), sizeof(buf)));
+ memset(buf2, 0xaa, sizeof(buf2));
+ ASSERT_EQ((int)sizeof(buf), rados_striper_read(striper, "SparseWriteRoundTrip", buf2, sizeof(buf), 500000000));
+ ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+}
+
+TEST_F(StriperTestPP, SparseWriteRoundTripPP) {
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("SparseWriteRoundTripPP", bl1, sizeof(buf), 0));
+ ASSERT_EQ(0, striper.write("SparseWriteRoundTripPP", bl1, sizeof(buf), 1000000000));
+ bufferlist bl2;
+ ASSERT_EQ((int)(2*sizeof(buf)), striper.read("SparseWriteRoundTripPP", &bl2, 2*sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)));
+ memset(buf, 0, sizeof(buf));
+ ASSERT_EQ(0, memcmp(bl2.c_str()+sizeof(buf), buf, sizeof(buf)));
+ ASSERT_EQ((int)sizeof(buf), striper.read("SparseWriteRoundTripPP", &bl2, sizeof(buf), 500000000));
+ ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)));
+}
+
+TEST_F(StriperTest, WriteFullRoundTrip) {
+ char buf[128];
+ char buf2[64];
+ char buf3[128];
+ memset(buf, 0xcc, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "WriteFullRoundTrip", buf, sizeof(buf), 0));
+ memset(buf2, 0xdd, sizeof(buf2));
+ ASSERT_EQ(0, rados_striper_write_full(striper, "WriteFullRoundTrip", buf2, sizeof(buf2)));
+ memset(buf3, 0x00, sizeof(buf3));
+ ASSERT_EQ((int)sizeof(buf2), rados_striper_read(striper, "WriteFullRoundTrip", buf3, sizeof(buf3), 0));
+ ASSERT_EQ(0, memcmp(buf2, buf3, sizeof(buf2)));
+}
+
+TEST_F(StriperTestPP, WriteFullRoundTripPP) {
+ char buf[128];
+ char buf2[64];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("WriteFullRoundTripPP", bl1, sizeof(buf), 0));
+ memset(buf2, 0xdd, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ASSERT_EQ(0, striper.write_full("WriteFullRoundTripPP", bl2));
+ bufferlist bl3;
+ ASSERT_EQ((int)sizeof(buf2), striper.read("WriteFullRoundTripPP", &bl3, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
+}
+
+TEST_F(StriperTest, AppendRoundTrip) {
+ char buf[64];
+ char buf2[64];
+ char buf3[sizeof(buf) + sizeof(buf2)];
+ memset(buf, 0xde, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_append(striper, "AppendRoundTrip", buf, sizeof(buf)));
+ memset(buf2, 0xad, sizeof(buf2));
+ ASSERT_EQ(0, rados_striper_append(striper, "AppendRoundTrip", buf2, sizeof(buf2)));
+ memset(buf3, 0, sizeof(buf3));
+ ASSERT_EQ((int)sizeof(buf3), rados_striper_read(striper, "AppendRoundTrip", buf3, sizeof(buf3), 0));
+ ASSERT_EQ(0, memcmp(buf3, buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(buf3 + sizeof(buf), buf2, sizeof(buf2)));
+}
+
+TEST_F(StriperTestPP, AppendRoundTripPP) {
+ char buf[64];
+ char buf2[64];
+ memset(buf, 0xde, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.append("AppendRoundTripPP", bl1, sizeof(buf)));
+ memset(buf2, 0xad, sizeof(buf2));
+ bufferlist bl2;
+ bl2.append(buf2, sizeof(buf2));
+ ASSERT_EQ(0, striper.append("AppendRoundTripPP", bl2, sizeof(buf2)));
+ bufferlist bl3;
+ ASSERT_EQ((int)(sizeof(buf) + sizeof(buf2)),
+ striper.read("AppendRoundTripPP", &bl3, (sizeof(buf) + sizeof(buf2)), 0));
+ const char *bl3_str = bl3.c_str();
+ ASSERT_EQ(0, memcmp(bl3_str, buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(bl3_str + sizeof(buf), buf2, sizeof(buf2)));
+}
+
+TEST_F(StriperTest, TruncTest) {
+ char buf[128];
+ char buf2[sizeof(buf)];
+ memset(buf, 0xaa, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_append(striper, "TruncTest", buf, sizeof(buf)));
+ ASSERT_EQ(0, rados_striper_trunc(striper, "TruncTest", sizeof(buf) / 2));
+ memset(buf2, 0, sizeof(buf2));
+ ASSERT_EQ((int)(sizeof(buf)/2), rados_striper_read(striper, "TruncTest", buf2, sizeof(buf2), 0));
+ ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)/2));
+}
+
+TEST_F(StriperTestPP, TruncTestPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.append("TruncTestPP", bl, sizeof(buf)));
+ ASSERT_EQ(0, striper.trunc("TruncTestPP", sizeof(buf) / 2));
+ bufferlist bl2;
+ ASSERT_EQ((int)(sizeof(buf)/2), striper.read("TruncTestPP", &bl2, sizeof(buf), 0));
+ ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)/2));
+}
+
+TEST_F(StriperTest, TruncTestGrow) {
+ char buf[128];
+ char buf2[sizeof(buf)*2];
+ memset(buf, 0xaa, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_append(striper, "TruncTestGrow", buf, sizeof(buf)));
+ ASSERT_EQ(0, rados_striper_trunc(striper, "TruncTestGrow", sizeof(buf2)));
+ memset(buf2, 0xbb, sizeof(buf2));
+ ASSERT_EQ((int)sizeof(buf2), rados_striper_read(striper, "TruncTestGrow", buf2, sizeof(buf2), 0));
+ ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+ memset(buf, 0x00, sizeof(buf));
+ ASSERT_EQ(0, memcmp(buf, buf2+sizeof(buf), sizeof(buf)));
+}
+
+TEST_F(StriperTestPP, TruncTestGrowPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.append("TruncTestGrowPP", bl, sizeof(buf)));
+ ASSERT_EQ(0, striper.trunc("TruncTestGrowPP", sizeof(buf) * 2));
+ bufferlist bl2;
+ ASSERT_EQ(sizeof(buf)*2, (unsigned)striper.read("TruncTestGrowPP", &bl2, sizeof(buf)*2, 0));
+ ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)));
+ memset(buf, 0x00, sizeof(buf));
+ ASSERT_EQ(0, memcmp(bl2.c_str()+sizeof(buf), buf, sizeof(buf)));
+}
+
+TEST_F(StriperTest, RemoveTest) {
+ char buf[128];
+ char buf2[sizeof(buf)];
+ memset(buf, 0xaa, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "RemoveTest", buf, sizeof(buf), 0));
+ ASSERT_EQ(0, rados_striper_remove(striper, "RemoveTest"));
+ ASSERT_EQ(-ENOENT, rados_striper_read(striper, "RemoveTest", buf2, sizeof(buf2), 0));
+}
+
+TEST_F(StriperTestPP, RemoveTestPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("RemoveTestPP", bl, sizeof(buf), 0));
+ ASSERT_EQ(0, striper.remove("RemoveTestPP"));
+ bufferlist bl2;
+ ASSERT_EQ(-ENOENT, striper.read("RemoveTestPP", &bl2, sizeof(buf), 0));
+}
+
+TEST_F(StriperTest, XattrsRoundTrip) {
+ char buf[128];
+ char attr1_buf[] = "foo bar baz";
+ memset(buf, 0xaa, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "XattrsRoundTrip", buf, sizeof(buf), 0));
+ ASSERT_EQ(-ENODATA, rados_striper_getxattr(striper, "XattrsRoundTrip", "attr1", buf, sizeof(buf)));
+ ASSERT_EQ(0, rados_striper_setxattr(striper, "XattrsRoundTrip", "attr1", attr1_buf, sizeof(attr1_buf)));
+ ASSERT_EQ((int)sizeof(attr1_buf), rados_striper_getxattr(striper, "XattrsRoundTrip", "attr1", buf, sizeof(buf)));
+ ASSERT_EQ(0, memcmp(attr1_buf, buf, sizeof(attr1_buf)));
+}
+
+TEST_F(StriperTestPP, XattrsRoundTripPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("XattrsRoundTripPP", bl1, sizeof(buf), 0));
+ char attr1_buf[] = "foo bar baz";
+ bufferlist bl2;
+ ASSERT_EQ(-ENODATA, striper.getxattr("XattrsRoundTripPP", "attr1", bl2));
+ bufferlist bl3;
+ bl3.append(attr1_buf, sizeof(attr1_buf));
+ ASSERT_EQ(0, striper.setxattr("XattrsRoundTripPP", "attr1", bl3));
+ bufferlist bl4;
+ ASSERT_EQ((int)sizeof(attr1_buf), striper.getxattr("XattrsRoundTripPP", "attr1", bl4));
+ ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
+}
+
+TEST_F(StriperTest, RmXattr) {
+ char buf[128];
+ char attr1_buf[] = "foo bar baz";
+ memset(buf, 0xaa, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "RmXattr", buf, sizeof(buf), 0));
+ ASSERT_EQ(0, rados_striper_setxattr(striper, "RmXattr", "attr1", attr1_buf, sizeof(attr1_buf)));
+ ASSERT_EQ(0, rados_striper_rmxattr(striper, "RmXattr", "attr1"));
+ ASSERT_EQ(-ENODATA, rados_striper_getxattr(striper, "RmXattr", "attr1", buf, sizeof(buf)));
+}
+
+TEST_F(StriperTestPP, RmXattrPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("RmXattrPP", bl1, sizeof(buf), 0));
+ char attr1_buf[] = "foo bar baz";
+ bufferlist bl2;
+ bl2.append(attr1_buf, sizeof(attr1_buf));
+ ASSERT_EQ(0, striper.setxattr("RmXattrPP", "attr1", bl2));
+ ASSERT_EQ(0, striper.rmxattr("RmXattrPP", "attr1"));
+ bufferlist bl3;
+ ASSERT_EQ(-ENODATA, striper.getxattr("RmXattrPP", "attr1", bl3));
+}
+
+TEST_F(StriperTest, XattrIter) {
+ char buf[128];
+ char attr1_buf[] = "foo bar baz";
+ char attr2_buf[256];
+ for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
+ attr2_buf[j] = j % 0xff;
+ }
+ memset(buf, 0xaa, sizeof(buf));
+ ASSERT_EQ(0, rados_striper_write(striper, "RmXattr", buf, sizeof(buf), 0));
+ ASSERT_EQ(0, rados_striper_setxattr(striper, "RmXattr", "attr1", attr1_buf, sizeof(attr1_buf)));
+ ASSERT_EQ(0, rados_striper_setxattr(striper, "RmXattr", "attr2", attr2_buf, sizeof(attr2_buf)));
+ rados_xattrs_iter_t iter;
+ ASSERT_EQ(0, rados_striper_getxattrs(striper, "RmXattr", &iter));
+ int num_seen = 0;
+ while (true) {
+ const char *name;
+ const char *val;
+ size_t len;
+ ASSERT_EQ(0, rados_striper_getxattrs_next(iter, &name, &val, &len));
+ if (name == NULL) {
+ break;
+ }
+ ASSERT_LT(num_seen, 2) << "Extra attribute : " << name;
+ if ((strcmp(name, "attr1") == 0) && (val != NULL) && (memcmp(val, attr1_buf, len) == 0)) {
+ num_seen++;
+ continue;
+ }
+ else if ((strcmp(name, "attr2") == 0) && (val != NULL) && (memcmp(val, attr2_buf, len) == 0)) {
+ num_seen++;
+ continue;
+ }
+ else {
+ ASSERT_EQ(0, 1) << "Unexpected attribute : " << name;;
+ }
+ }
+ rados_striper_getxattrs_end(iter);
+}
+
+TEST_F(StriperTestPP, XattrListPP) {
+ char buf[128];
+ memset(buf, 0xaa, sizeof(buf));
+ bufferlist bl1;
+ bl1.append(buf, sizeof(buf));
+ ASSERT_EQ(0, striper.write("RmXattrPP", bl1, sizeof(buf), 0));
+ char attr1_buf[] = "foo bar baz";
+ bufferlist bl2;
+ bl2.append(attr1_buf, sizeof(attr1_buf));
+ ASSERT_EQ(0, striper.setxattr("RmXattrPP", "attr1", bl2));
+ char attr2_buf[256];
+ for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
+ attr2_buf[j] = j % 0xff;
+ }
+ bufferlist bl3;
+ bl3.append(attr2_buf, sizeof(attr2_buf));
+ ASSERT_EQ(0, striper.setxattr("RmXattrPP", "attr2", bl3));
+ std::map<std::string, bufferlist> attrset;
+ ASSERT_EQ(0, striper.getxattrs("RmXattrPP", attrset));
+ for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
+ i != attrset.end(); ++i) {
+ if (i->first == string("attr1")) {
+ ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
+ }
+ else if (i->first == string("attr2")) {
+ ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
+ }
+ else {
+ ASSERT_EQ(0, 1) << "Unexpected attribute : " << i->first;
+ }
+ }
+}
diff --git a/src/test/libradosstriper/striping.cc b/src/test/libradosstriper/striping.cc
new file mode 100644
index 00000000..647014c0
--- /dev/null
+++ b/src/test/libradosstriper/striping.cc
@@ -0,0 +1,329 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "include/compat.h"
+#include "include/types.h"
+#include "include/rados/librados.h"
+#include "include/rados/librados.hpp"
+#include "include/radosstriper/libradosstriper.h"
+#include "include/radosstriper/libradosstriper.hpp"
+#include "include/ceph_fs.h"
+#include "test/librados/test.h"
+#include "test/libradosstriper/TestCase.h"
+
+#include <string>
+#include <errno.h>
+using namespace librados;
+using namespace libradosstriper;
+
+class StriperTestRT : public StriperTestParam {
+public:
+ StriperTestRT() : StriperTestParam() {}
+protected:
+ char* getObjName(const std::string& soid, uint64_t nb)
+ {
+ char name[soid.size()+18];
+ sprintf(name, "%s.%016llx", soid.c_str(), (long long unsigned int)nb);
+ return strdup(name);
+ }
+
+ void checkObjectFromRados(const std::string& soid, bufferlist &bl,
+ uint64_t exp_stripe_unit, uint64_t exp_stripe_count,
+ uint64_t exp_object_size, size_t size)
+ {
+ checkObjectFromRados(soid, bl, exp_stripe_unit, exp_stripe_count, exp_object_size, size, size);
+ }
+
+ void checkObjectFromRados(const std::string& soid, bufferlist &bl,
+ uint64_t exp_stripe_unit, uint64_t exp_stripe_count,
+ uint64_t exp_object_size, size_t size,
+ size_t actual_size_if_sparse)
+ {
+ // checking first object's rados xattrs
+ bufferlist xattrbl;
+ char* firstOid = getObjName(soid, 0);
+ ASSERT_LT(0, ioctx.getxattr(firstOid, "striper.layout.stripe_unit", xattrbl));
+ std::string s_xattr(xattrbl.c_str(), xattrbl.length()); // adds 0 byte at the end
+ uint64_t stripe_unit = strtoll(s_xattr.c_str(), NULL, 10);
+ ASSERT_LT((unsigned)0, stripe_unit);
+ ASSERT_EQ(stripe_unit, exp_stripe_unit);
+ xattrbl.clear();
+ ASSERT_LT(0, ioctx.getxattr(firstOid, "striper.layout.stripe_count", xattrbl));
+ s_xattr = std::string(xattrbl.c_str(), xattrbl.length()); // adds 0 byte at the end
+ uint64_t stripe_count = strtoll(s_xattr.c_str(), NULL, 10);
+ ASSERT_LT(0U, stripe_count);
+ ASSERT_EQ(stripe_count, exp_stripe_count);
+ xattrbl.clear();
+ ASSERT_LT(0, ioctx.getxattr(firstOid, "striper.layout.object_size", xattrbl));
+ s_xattr = std::string(xattrbl.c_str(), xattrbl.length()); // adds 0 byte at the end
+ uint64_t object_size = strtoll(s_xattr.c_str(), NULL, 10);
+ ASSERT_EQ(object_size, exp_object_size);
+ xattrbl.clear();
+ ASSERT_LT(0, ioctx.getxattr(firstOid, "striper.size", xattrbl));
+ s_xattr = std::string(xattrbl.c_str(), xattrbl.length()); // adds 0 byte at the end
+ uint64_t xa_size = strtoll(s_xattr.c_str(), NULL, 10);
+ ASSERT_EQ(xa_size, size);
+ // checking object content from rados point of view
+ // we will go stripe by stripe, read the content of each of them and
+ // check with expectations
+ uint64_t stripe_per_object = object_size / stripe_unit;
+ uint64_t stripe_per_objectset = stripe_per_object * stripe_count;
+ uint64_t nb_stripes_in_object = (size+stripe_unit-1)/stripe_unit;
+ for (uint64_t stripe_nb = 0;
+ stripe_nb < nb_stripes_in_object;
+ stripe_nb++) {
+ // find out where this stripe is stored
+ uint64_t objectset = stripe_nb / stripe_per_objectset;
+ uint64_t stripe_in_object_set = stripe_nb % stripe_per_objectset;
+ uint64_t object_in_set = stripe_in_object_set % stripe_count;
+ uint64_t stripe_in_object = stripe_in_object_set / stripe_count;
+ uint64_t object_nb = objectset * stripe_count + object_in_set;
+ uint64_t start = stripe_in_object * stripe_unit;
+ uint64_t len = stripe_unit;
+ if (stripe_nb == nb_stripes_in_object-1 and size % stripe_unit != 0) {
+ len = size % stripe_unit;
+ }
+ // handle case of sparse object (can only be sparse at the end in our tests)
+ if (actual_size_if_sparse < size and
+ ((actual_size_if_sparse+stripe_unit-1)/stripe_unit)-1 == stripe_nb) {
+ len = actual_size_if_sparse % stripe_unit;
+ if (0 == len) len = stripe_unit;
+ }
+ bufferlist stripe_data;
+ // check object content
+ char* oid = getObjName(soid, object_nb);
+ int rc = ioctx.read(oid, stripe_data, len, start);
+ if (actual_size_if_sparse < size and
+ (actual_size_if_sparse+stripe_unit-1)/stripe_unit <= stripe_nb) {
+ // sparse object case : the stripe does not exist, but the rados object may
+ uint64_t object_start = (object_in_set + objectset*stripe_per_objectset) * stripe_unit;
+ if (actual_size_if_sparse <= object_start) {
+ ASSERT_EQ(rc, -ENOENT);
+ } else {
+ ASSERT_EQ(rc, 0);
+ }
+ } else {
+ ASSERT_EQ((uint64_t)rc, len);
+ bufferlist original_data;
+ original_data.substr_of(bl, stripe_nb*stripe_unit, len);
+ ASSERT_EQ(0, memcmp(original_data.c_str(), stripe_data.c_str(), len));
+ }
+ free(oid);
+ }
+ // checking rados object sizes; we go object by object
+ uint64_t nb_full_object_sets = nb_stripes_in_object / stripe_per_objectset;
+ uint64_t nb_extra_objects = nb_stripes_in_object % stripe_per_objectset;
+ if (nb_extra_objects > stripe_count) nb_extra_objects = stripe_count;
+ uint64_t nb_objects = nb_full_object_sets * stripe_count + nb_extra_objects;
+ for (uint64_t object_nb = 0; object_nb < nb_objects; object_nb++) {
+ uint64_t rados_size;
+ time_t mtime;
+ char* oid = getObjName(soid, object_nb);
+ uint64_t nb_full_object_set = object_nb / stripe_count;
+ uint64_t object_index_in_set = object_nb % stripe_count;
+ uint64_t object_start_stripe = nb_full_object_set * stripe_per_objectset + object_index_in_set;
+ uint64_t object_start_off = object_start_stripe * stripe_unit;
+ if (actual_size_if_sparse < size and actual_size_if_sparse <= object_start_off) {
+ ASSERT_EQ(-ENOENT, ioctx.stat(oid, &rados_size, &mtime));
+ } else {
+ ASSERT_EQ(0, ioctx.stat(oid, &rados_size, &mtime));
+ uint64_t offset;
+ uint64_t stripe_size = stripe_count * stripe_unit;
+ uint64_t set_size = stripe_count * object_size;
+ uint64_t len = 0;
+ for (offset = object_start_off;
+ (offset < (object_start_off) + set_size) && (offset < actual_size_if_sparse);
+ offset += stripe_size) {
+ if (offset + stripe_unit > actual_size_if_sparse) {
+ len += actual_size_if_sparse-offset;
+ } else {
+ len += stripe_unit;
+ }
+ }
+ ASSERT_EQ(len, rados_size);
+ }
+ free(oid);
+ }
+ // check we do not have an extra object behind
+ uint64_t rados_size;
+ time_t mtime;
+ char* oid = getObjName(soid, nb_objects);
+ ASSERT_EQ(-ENOENT, ioctx.stat(oid, &rados_size, &mtime));
+ free(oid);
+ free(firstOid);
+ }
+};
+
+TEST_P(StriperTestRT, StripedRoundtrip) {
+ // get striping parameters and apply them
+ TestData testData = GetParam();
+ ASSERT_EQ(0, striper.set_object_layout_stripe_unit(testData.stripe_unit));
+ ASSERT_EQ(0, striper.set_object_layout_stripe_count(testData.stripe_count));
+ ASSERT_EQ(0, striper.set_object_layout_object_size(testData.object_size));
+ std::ostringstream oss;
+ oss << "StripedRoundtrip_" << testData.stripe_unit << "_"
+ << testData.stripe_count << "_" << testData.object_size
+ << "_" << testData.size;
+ std::string soid = oss.str();
+ // writing striped data
+ std::unique_ptr<char[]> buf1;
+ bufferlist bl1;
+ {
+ SCOPED_TRACE("Writing initial object");
+ buf1 = std::make_unique<char[]>(testData.size);
+ for (unsigned int i = 0; i < testData.size; i++) buf1[i] = 13*((unsigned char)i);
+ bl1.append(buf1.get(), testData.size);
+ ASSERT_EQ(0, striper.write(soid, bl1, testData.size, 0));
+ // checking object state from Rados point of view
+ ASSERT_NO_FATAL_FAILURE(checkObjectFromRados(soid, bl1, testData.stripe_unit,
+ testData.stripe_count, testData.object_size,
+ testData.size));
+ }
+ // adding more data to object and checking again
+ std::unique_ptr<char[]> buf2;
+ bufferlist bl2;
+ {
+ SCOPED_TRACE("Testing append");
+ buf2 = std::make_unique<char[]>(testData.size);
+ for (unsigned int i = 0; i < testData.size; i++) buf2[i] = 17*((unsigned char)i);
+ bl2.append(buf2.get(), testData.size);
+ ASSERT_EQ(0, striper.append(soid, bl2, testData.size));
+ bl1.append(buf2.get(), testData.size);
+ ASSERT_NO_FATAL_FAILURE(checkObjectFromRados(soid, bl1, testData.stripe_unit,
+ testData.stripe_count, testData.object_size,
+ testData.size*2));
+ }
+ // truncating to half original size and checking again
+ {
+ SCOPED_TRACE("Testing trunc to truncate object");
+ ASSERT_EQ(0, striper.trunc(soid, testData.size/2));
+ ASSERT_NO_FATAL_FAILURE(checkObjectFromRados(soid, bl1, testData.stripe_unit,
+ testData.stripe_count, testData.object_size,
+ testData.size/2));
+ }
+ // truncating back to original size and checking again (especially for 0s)
+ {
+ SCOPED_TRACE("Testing trunc to extend object with 0s");
+ ASSERT_EQ(0, striper.trunc(soid, testData.size));
+ bufferlist bl3;
+ bl3.substr_of(bl1, 0, testData.size/2);
+ bl3.append_zero(testData.size - testData.size/2);
+ ASSERT_NO_FATAL_FAILURE(checkObjectFromRados(soid, bl3, testData.stripe_unit,
+ testData.stripe_count, testData.object_size,
+ testData.size, testData.size/2));
+ }
+ {
+ SCOPED_TRACE("Testing write_full");
+ // using write_full and checking again
+ ASSERT_EQ(0, striper.write_full(soid, bl2));
+ checkObjectFromRados(soid, bl2, testData.stripe_unit,
+ testData.stripe_count, testData.object_size,
+ testData.size);
+ }
+ {
+ SCOPED_TRACE("Testing standard remove");
+ // call remove
+ ASSERT_EQ(0, striper.remove(soid));
+ // check that the removal was successful
+ uint64_t size;
+ time_t mtime;
+ for (uint64_t object_nb = 0;
+ object_nb < testData.size*2/testData.object_size + testData.stripe_count;
+ object_nb++) {
+ char* oid = getObjName(soid, object_nb);
+ ASSERT_EQ(-ENOENT, ioctx.stat(oid, &size, &mtime));
+ free(oid);
+ }
+ }
+ {
+ SCOPED_TRACE("Testing remove when no object size");
+ // recreate object
+ ASSERT_EQ(0, striper.write(soid, bl1, testData.size*2, 0));
+ // remove the object size attribute from the striped object
+ char* firstOid = getObjName(soid, 0);
+ ASSERT_EQ(0, ioctx.rmxattr(firstOid, "striper.size"));
+ free(firstOid);
+ // check that stat fails
+ uint64_t size;
+ time_t mtime;
+ ASSERT_EQ(-ENODATA, striper.stat(soid, &size, &mtime));
+ // call remove
+ ASSERT_EQ(0, striper.remove(soid));
+ // check that the removal was successful
+ for (uint64_t object_nb = 0;
+ object_nb < testData.size*2/testData.object_size + testData.stripe_count;
+ object_nb++) {
+ char* oid = getObjName(soid, object_nb);
+ ASSERT_EQ(-ENOENT, ioctx.stat(oid, &size, &mtime));
+ free(oid);
+ }
+ }
+}
+
+const TestData simple_stripe_schemes[] = {
+ // stripe_unit, stripe_count, object_size, size
+ {CEPH_MIN_STRIPE_UNIT, 5, CEPH_MIN_STRIPE_UNIT, 2},
+ {CEPH_MIN_STRIPE_UNIT, 5, CEPH_MIN_STRIPE_UNIT, CEPH_MIN_STRIPE_UNIT},
+ {CEPH_MIN_STRIPE_UNIT, 5, CEPH_MIN_STRIPE_UNIT, CEPH_MIN_STRIPE_UNIT-1},
+ {CEPH_MIN_STRIPE_UNIT, 5, CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT},
+ {CEPH_MIN_STRIPE_UNIT, 5, CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT},
+ {CEPH_MIN_STRIPE_UNIT, 5, CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT-1},
+ {CEPH_MIN_STRIPE_UNIT, 5, CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT-1},
+ {CEPH_MIN_STRIPE_UNIT, 5, CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 5, CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 5, 3*CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 5, 3*CEPH_MIN_STRIPE_UNIT, 8*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 5, 3*CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 5, 3*CEPH_MIN_STRIPE_UNIT, 15*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 5, 3*CEPH_MIN_STRIPE_UNIT, 25*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 5, 3*CEPH_MIN_STRIPE_UNIT, 45*CEPH_MIN_STRIPE_UNIT+100},
+ {262144, 5, 262144, 2},
+ {262144, 5, 262144, 262144},
+ {262144, 5, 262144, 262144-1},
+ {262144, 5, 262144, 2*262144},
+ {262144, 5, 262144, 12*262144},
+ {262144, 5, 262144, 2*262144-1},
+ {262144, 5, 262144, 12*262144-1},
+ {262144, 5, 262144, 2*262144+100},
+ {262144, 5, 262144, 12*262144+100},
+ {262144, 5, 3*262144, 2*262144+100},
+ {262144, 5, 3*262144, 8*262144+100},
+ {262144, 5, 3*262144, 12*262144+100},
+ {262144, 5, 3*262144, 15*262144+100},
+ {262144, 5, 3*262144, 25*262144+100},
+ {262144, 5, 3*262144, 45*262144+100},
+ {CEPH_MIN_STRIPE_UNIT, 1, CEPH_MIN_STRIPE_UNIT, 2},
+ {CEPH_MIN_STRIPE_UNIT, 1, CEPH_MIN_STRIPE_UNIT, CEPH_MIN_STRIPE_UNIT},
+ {CEPH_MIN_STRIPE_UNIT, 1, CEPH_MIN_STRIPE_UNIT, CEPH_MIN_STRIPE_UNIT-1},
+ {CEPH_MIN_STRIPE_UNIT, 1, CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT},
+ {CEPH_MIN_STRIPE_UNIT, 1, CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT},
+ {CEPH_MIN_STRIPE_UNIT, 1, CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT-1},
+ {CEPH_MIN_STRIPE_UNIT, 1, CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT-1},
+ {CEPH_MIN_STRIPE_UNIT, 1, CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 1, CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 1, 3*CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 1, 3*CEPH_MIN_STRIPE_UNIT, 8*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 1, 3*CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 1, 3*CEPH_MIN_STRIPE_UNIT, 15*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 1, 3*CEPH_MIN_STRIPE_UNIT, 25*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 1, 3*CEPH_MIN_STRIPE_UNIT, 45*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 50, CEPH_MIN_STRIPE_UNIT, 2},
+ {CEPH_MIN_STRIPE_UNIT, 50, CEPH_MIN_STRIPE_UNIT, CEPH_MIN_STRIPE_UNIT},
+ {CEPH_MIN_STRIPE_UNIT, 50, CEPH_MIN_STRIPE_UNIT, CEPH_MIN_STRIPE_UNIT-1},
+ {CEPH_MIN_STRIPE_UNIT, 50, CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT},
+ {CEPH_MIN_STRIPE_UNIT, 50, CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT},
+ {CEPH_MIN_STRIPE_UNIT, 50, CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT-1},
+ {CEPH_MIN_STRIPE_UNIT, 50, CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT-1},
+ {CEPH_MIN_STRIPE_UNIT, 50, CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 50, CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 50, 3*CEPH_MIN_STRIPE_UNIT, 2*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 50, 3*CEPH_MIN_STRIPE_UNIT, 8*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 50, 3*CEPH_MIN_STRIPE_UNIT, 12*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 50, 3*CEPH_MIN_STRIPE_UNIT, 15*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 50, 3*CEPH_MIN_STRIPE_UNIT, 25*CEPH_MIN_STRIPE_UNIT+100},
+ {CEPH_MIN_STRIPE_UNIT, 50, 3*CEPH_MIN_STRIPE_UNIT, 45*CEPH_MIN_STRIPE_UNIT+100}
+};
+
+INSTANTIATE_TEST_CASE_P(SimpleStriping,
+ StriperTestRT,
+ ::testing::ValuesIn(simple_stripe_schemes));