From: Sebastien Ponce Date: Thu, 6 Feb 2014 10:38:44 +0000 (+0100) Subject: Added unit test suite for the Rados striping API. X-Git-Tag: v0.83~124^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=fa01ca65981bca455f31a3cd7813c081a8d128d0;p=ceph.git Added unit test suite for the Rados striping API. This includes tests for standard io and asynchronous io, similar to what is tested in the rados tests. In addition, it includes in depth tests of the striping itself. Signed-off-by: Sebastien Ponce --- diff --git a/src/test/Makefile.am b/src/test/Makefile.am index 79668ec6fec1..3de19a4b5550 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -629,6 +629,12 @@ noinst_LTLIBRARIES += libradostest.la libradostest_la_CXXFLAGS = $(UNITTEST_CXXFLAGS) RADOS_TEST_LDADD = libradostest.la +libradosstripertest_la_SOURCES = test/libradosstriper/TestCase.cc +noinst_LTLIBRARIES += libradosstripertest.la +libradosstripertest_la_LIBADD = $(RADOS_TEST_LDADD) +libradosstripertest_la_CXXFLAGS = $(UNITTEST_CXXFLAGS) +RADOS_STRIPER_TEST_LDADD = libradosstripertest.la + ceph_multi_stress_watch_SOURCES = test/multi_stress_watch.cc ceph_multi_stress_watch_LDADD = $(LIBRADOS) $(CEPH_GLOBAL) $(RADOS_TEST_LDADD) bin_DEBUGPROGRAMS += ceph_multi_stress_watch @@ -775,6 +781,21 @@ ceph_test_rados_api_lock_LDADD = $(LIBRADOS) $(UNITTEST_LDADD) $(RADOS_TEST_LDAD ceph_test_rados_api_lock_CXXFLAGS = $(UNITTEST_CXXFLAGS) bin_DEBUGPROGRAMS += ceph_test_rados_api_lock +ceph_test_rados_striper_api_io_SOURCES = test/libradosstriper/io.cc +ceph_test_rados_striper_api_io_LDADD = $(LIBRADOS) $(LIBRADOSSTRIPER) $(UNITTEST_LDADD) $(RADOS_STRIPER_TEST_LDADD) +ceph_test_rados_striper_api_io_CXXFLAGS = $(UNITTEST_CXXFLAGS) +bin_DEBUGPROGRAMS += ceph_test_rados_striper_api_io + +ceph_test_rados_striper_api_aio_SOURCES = test/libradosstriper/aio.cc +ceph_test_rados_striper_api_aio_LDADD = $(LIBRADOS) $(LIBRADOSSTRIPER) $(UNITTEST_LDADD) $(RADOS_STRIPER_TEST_LDADD) +ceph_test_rados_striper_api_aio_CXXFLAGS = $(UNITTEST_CXXFLAGS) +bin_DEBUGPROGRAMS += ceph_test_rados_striper_api_aio + +ceph_test_rados_striper_api_striping_SOURCES = test/libradosstriper/striping.cc +ceph_test_rados_striper_api_striping_LDADD = $(LIBRADOS) $(LIBRADOSSTRIPER) $(UNITTEST_LDADD) $(RADOS_STRIPER_TEST_LDADD) +ceph_test_rados_striper_api_striping_CXXFLAGS = $(UNITTEST_CXXFLAGS) +bin_DEBUGPROGRAMS += ceph_test_rados_striper_api_striping + ceph_test_libcephfs_SOURCES = \ test/libcephfs/test.cc \ test/libcephfs/readdir_r_cb.cc \ @@ -893,6 +914,7 @@ noinst_HEADERS += \ test/kv_store_bench.h \ test/librados/test.h \ test/librados/TestCase.h \ + test/libradosstriper/TestCase.h \ test/ObjectMap/KeyValueDBMemory.h \ test/omap_bench.h \ test/osdc/FakeWriteback.h \ diff --git a/src/test/librados/io.cc b/src/test/librados/io.cc index 5daca3c15ec6..ede81a326f5b 100644 --- a/src/test/librados/io.cc +++ b/src/test/librados/io.cc @@ -218,9 +218,9 @@ TEST_F(LibRadosIo, WriteFullRoundTrip) { ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0)); memset(buf2, 0xdd, sizeof(buf2)); ASSERT_EQ(0, rados_write_full(ioctx, "foo", buf2, sizeof(buf2))); - memset(buf3, 0xdd, sizeof(buf3)); + memset(buf3, 0x00, sizeof(buf3)); ASSERT_EQ((int)sizeof(buf2), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0)); - ASSERT_EQ(0, memcmp(buf2, buf2, sizeof(buf2))); + ASSERT_EQ(0, memcmp(buf2, buf3, sizeof(buf2))); } TEST_F(LibRadosIoPP, WriteFullRoundTripPP) { diff --git a/src/test/libradosstriper/TestCase.cc b/src/test/libradosstriper/TestCase.cc new file mode 100644 index 000000000000..5e1d34a9f0a4 --- /dev/null +++ b/src/test/libradosstriper/TestCase.cc @@ -0,0 +1,79 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include +#include "test/librados/test.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 000000000000..cfa9f72ad747 --- /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 + +/** + * 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() {} + virtual ~StriperTest() {} +protected: + static void SetUpTestCase(); + static void TearDownTestCase(); + static rados_t s_cluster; + static std::string pool_name; + + virtual void SetUp(); + virtual void TearDown(); + rados_t cluster; + rados_ioctx_t ioctx; + rados_striper_t striper; +}; + +class StriperTestPP : public ::testing::Test { +public: + StriperTestPP() : cluster(s_cluster) {} + virtual ~StriperTestPP() {} + static void SetUpTestCase(); + static void TearDownTestCase(); +protected: + static librados::Rados s_cluster; + static std::string pool_name; + + virtual void SetUp(); + 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 { +public: + StriperTestParam() : cluster(s_cluster) {} + virtual ~StriperTestParam() {} + static void SetUpTestCase(); + static void TearDownTestCase(); +protected: + static librados::Rados s_cluster; + static std::string pool_name; + + virtual void SetUp(); + 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 000000000000..873c803dc294 --- /dev/null +++ b/src/test/libradosstriper/aio.cc @@ -0,0 +1,542 @@ +#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 +#include + +using namespace librados; +using namespace libradosstriper; +using std::pair; + +class AioTestData +{ +public: + AioTestData() : m_complete(false), m_safe(false) { + sem_init(&m_sem, 0, 0); + } + + ~AioTestData() { + sem_destroy(&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(arg); + test->m_complete = true; + sem_post(&test->m_sem); +} + +void set_completion_safe(rados_completion_t cb, void *arg) +{ + AioTestData *test = static_cast(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); + 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(); + 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))); + 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))); + 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))); + 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))); + 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))); + 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))); + 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))); + 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))); + 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))); + 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), 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))); + 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))); + 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))); + 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), rados_aio_get_return_value(my_completion3)); + ASSERT_EQ(0, memcmp(buf3, buf2, sizeof(buf2))); + 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), my_completion3->get_return_value()); + ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2))); + my_completion->release(); + my_completion2->release(); + my_completion3->release(); +} diff --git a/src/test/libradosstriper/io.cc b/src/test/libradosstriper/io.cc new file mode 100644 index 000000000000..9ea7bfcffa52 --- /dev/null +++ b/src/test/libradosstriper/io.cc @@ -0,0 +1,392 @@ +#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 +#include +#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, 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, 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_getxattrs_next(iter, &name, &val, &len)); + if (name == NULL) { + break; + } + ASSERT_LT(num_seen, 2) << "Extra attribute : " << name; + if ((strcmp(name, "attr1") == 0) && (memcmp(val, attr1_buf, len) == 0)) { + num_seen++; + continue; + } + else if ((strcmp(name, "attr2") == 0) && (memcmp(val, attr2_buf, len) == 0)) { + num_seen++; + continue; + } + else { + ASSERT_EQ(0, 1) << "Unexpected attribute : " << name;; + } + } + rados_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 attrset; + ASSERT_EQ(0, striper.getxattrs("RmXattrPP", attrset)); + for (std::map::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 000000000000..c65f0498de58 --- /dev/null +++ b/src/test/libradosstriper/striping.cc @@ -0,0 +1,307 @@ +#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 +#include +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; + std::string 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_EQ(stripe_unit, exp_stripe_unit); + 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_EQ(stripe_count, exp_stripe_count); + 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); + 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 + std::string 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)); + } + } + // 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; + std::string 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 = object_start_off; + 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); + } + } + // check we do not have an extra object behind + uint64_t rados_size; + time_t mtime; + ASSERT_EQ(-ENOENT, ioctx.stat(getObjName(soid, nb_objects), &rados_size, &mtime)); + } +}; + +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 + bufferlist bl1; + { + SCOPED_TRACE("Writing initial object"); + char buf[testData.size]; + for (unsigned int i = 0; i < testData.size; i++) buf[i] = 13*((unsigned char)i); + bl1.append(buf, 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 + bufferlist bl2; + { + SCOPED_TRACE("Testing append"); + char buf2[testData.size]; + for (unsigned int i = 0; i < testData.size; i++) buf2[i] = 17*((unsigned char)i); + bl2.append(buf2, testData.size); + ASSERT_EQ(0, striper.append(soid, bl2, testData.size)); + bl1.append(buf2, 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++) { + ASSERT_EQ(-ENOENT, ioctx.stat(getObjName(soid, object_nb), &size, &mtime)); + } + } + { + 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 + std::string firstOid = getObjName(soid, 0); + ASSERT_EQ(0, ioctx.rmxattr(firstOid, "striper.size")); + // 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++) { + ASSERT_EQ(-ENOENT, ioctx.stat(getObjName(soid, object_nb), &size, &mtime)); + } + } +} + +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));