diff options
Diffstat (limited to 'src/test/journal/test_ObjectPlayer.cc')
-rw-r--r-- | src/test/journal/test_ObjectPlayer.cc | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/src/test/journal/test_ObjectPlayer.cc b/src/test/journal/test_ObjectPlayer.cc new file mode 100644 index 00000000..b78bd219 --- /dev/null +++ b/src/test/journal/test_ObjectPlayer.cc @@ -0,0 +1,289 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "journal/ObjectPlayer.h" +#include "journal/Entry.h" +#include "include/stringify.h" +#include "common/Mutex.h" +#include "common/Timer.h" +#include "gtest/gtest.h" +#include "test/librados/test.h" +#include "test/journal/RadosTestFixture.h" + +template <typename T> +class TestObjectPlayer : public RadosTestFixture { +public: + static const uint32_t max_fetch_bytes = T::max_fetch_bytes; + + journal::ObjectPlayerPtr create_object(const std::string &oid, + uint8_t order) { + journal::ObjectPlayerPtr object(new journal::ObjectPlayer( + m_ioctx, oid + ".", 0, *m_timer, m_timer_lock, order, + max_fetch_bytes)); + return object; + } + + int fetch(journal::ObjectPlayerPtr object_player) { + while (true) { + C_SaferCond ctx; + object_player->set_refetch_state( + journal::ObjectPlayer::REFETCH_STATE_NONE); + object_player->fetch(&ctx); + int r = ctx.wait(); + if (r < 0 || !object_player->refetch_required()) { + return r; + } + } + return 0; + } + + int watch_and_wait_for_entries(journal::ObjectPlayerPtr object_player, + journal::ObjectPlayer::Entries *entries, + size_t count) { + for (size_t i = 0; i < 50; ++i) { + object_player->get_entries(entries); + if (entries->size() == count) { + break; + } + + C_SaferCond ctx; + object_player->watch(&ctx, 0.1); + + int r = ctx.wait(); + if (r < 0) { + return r; + } + } + return 0; + } + + std::string get_object_name(const std::string &oid) { + return oid + ".0"; + } +}; + +template <uint32_t _max_fetch_bytes> +struct TestObjectPlayerParams { + static const uint32_t max_fetch_bytes = _max_fetch_bytes; +}; + +typedef ::testing::Types<TestObjectPlayerParams<0>, + TestObjectPlayerParams<10> > TestObjectPlayerTypes; +TYPED_TEST_CASE(TestObjectPlayer, TestObjectPlayerTypes); + +TYPED_TEST(TestObjectPlayer, Fetch) { + std::string oid = this->get_temp_oid(); + + journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1'))); + journal::Entry entry2(234, 124, this->create_payload(std::string(24, '1'))); + + bufferlist bl; + encode(entry1, bl); + encode(entry2, bl); + ASSERT_EQ(0, this->append(this->get_object_name(oid), bl)); + + journal::ObjectPlayerPtr object = this->create_object(oid, 14); + ASSERT_LE(0, this->fetch(object)); + + journal::ObjectPlayer::Entries entries; + object->get_entries(&entries); + ASSERT_EQ(2U, entries.size()); + + journal::ObjectPlayer::Entries expected_entries = {entry1, entry2}; + ASSERT_EQ(expected_entries, entries); +} + +TYPED_TEST(TestObjectPlayer, FetchLarge) { + std::string oid = this->get_temp_oid(); + + journal::Entry entry1(234, 123, + this->create_payload(std::string(8192 - 32, '1'))); + journal::Entry entry2(234, 124, this->create_payload("")); + + bufferlist bl; + encode(entry1, bl); + encode(entry2, bl); + ASSERT_EQ(0, this->append(this->get_object_name(oid), bl)); + + journal::ObjectPlayerPtr object = this->create_object(oid, 12); + ASSERT_LE(0, this->fetch(object)); + + journal::ObjectPlayer::Entries entries; + object->get_entries(&entries); + ASSERT_EQ(2U, entries.size()); + + journal::ObjectPlayer::Entries expected_entries = {entry1, entry2}; + ASSERT_EQ(expected_entries, entries); +} + +TYPED_TEST(TestObjectPlayer, FetchDeDup) { + std::string oid = this->get_temp_oid(); + + journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1'))); + journal::Entry entry2(234, 123, this->create_payload(std::string(24, '2'))); + + bufferlist bl; + encode(entry1, bl); + encode(entry2, bl); + ASSERT_EQ(0, this->append(this->get_object_name(oid), bl)); + + journal::ObjectPlayerPtr object = this->create_object(oid, 14); + ASSERT_LE(0, this->fetch(object)); + + journal::ObjectPlayer::Entries entries; + object->get_entries(&entries); + ASSERT_EQ(1U, entries.size()); + + journal::ObjectPlayer::Entries expected_entries = {entry2}; + ASSERT_EQ(expected_entries, entries); +} + +TYPED_TEST(TestObjectPlayer, FetchEmpty) { + std::string oid = this->get_temp_oid(); + + bufferlist bl; + ASSERT_EQ(0, this->append(this->get_object_name(oid), bl)); + + journal::ObjectPlayerPtr object = this->create_object(oid, 14); + + ASSERT_EQ(0, this->fetch(object)); + ASSERT_TRUE(object->empty()); +} + +TYPED_TEST(TestObjectPlayer, FetchCorrupt) { + std::string oid = this->get_temp_oid(); + + journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1'))); + journal::Entry entry2(234, 124, this->create_payload(std::string(24, '2'))); + journal::Entry entry3(234, 125, this->create_payload(std::string(24, '3'))); + + bufferlist bl; + encode(entry1, bl); + encode(this->create_payload("corruption" + std::string(1024, 'X')), bl); + encode(entry2, bl); + encode(this->create_payload("corruption" + std::string(1024, 'Y')), bl); + encode(entry3, bl); + ASSERT_EQ(0, this->append(this->get_object_name(oid), bl)); + + journal::ObjectPlayerPtr object = this->create_object(oid, 14); + ASSERT_EQ(-EBADMSG, this->fetch(object)); + ASSERT_EQ(0, this->fetch(object)); + + journal::ObjectPlayer::Entries entries; + object->get_entries(&entries); + ASSERT_EQ(3U, entries.size()); + + journal::ObjectPlayer::Entries expected_entries = {entry1, entry2, entry3}; + ASSERT_EQ(expected_entries, entries); +} + +TYPED_TEST(TestObjectPlayer, FetchAppend) { + std::string oid = this->get_temp_oid(); + + journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1'))); + journal::Entry entry2(234, 124, this->create_payload(std::string(24, '2'))); + + bufferlist bl; + encode(entry1, bl); + ASSERT_EQ(0, this->append(this->get_object_name(oid), bl)); + + journal::ObjectPlayerPtr object = this->create_object(oid, 14); + ASSERT_LE(0, this->fetch(object)); + + journal::ObjectPlayer::Entries entries; + object->get_entries(&entries); + ASSERT_EQ(1U, entries.size()); + + journal::ObjectPlayer::Entries expected_entries = {entry1}; + ASSERT_EQ(expected_entries, entries); + + bl.clear(); + encode(entry2, bl); + ASSERT_EQ(0, this->append(this->get_object_name(oid), bl)); + ASSERT_LE(0, this->fetch(object)); + + object->get_entries(&entries); + ASSERT_EQ(2U, entries.size()); + + expected_entries = {entry1, entry2}; + ASSERT_EQ(expected_entries, entries); +} + +TYPED_TEST(TestObjectPlayer, PopEntry) { + std::string oid = this->get_temp_oid(); + + journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1'))); + journal::Entry entry2(234, 124, this->create_payload(std::string(24, '1'))); + + bufferlist bl; + encode(entry1, bl); + encode(entry2, bl); + ASSERT_EQ(0, this->append(this->get_object_name(oid), bl)); + + journal::ObjectPlayerPtr object = this->create_object(oid, 14); + ASSERT_LE(0, this->fetch(object)); + + journal::ObjectPlayer::Entries entries; + object->get_entries(&entries); + ASSERT_EQ(2U, entries.size()); + + journal::Entry entry; + object->front(&entry); + object->pop_front(); + ASSERT_EQ(entry1, entry); + object->front(&entry); + object->pop_front(); + ASSERT_EQ(entry2, entry); + ASSERT_TRUE(object->empty()); +} + +TYPED_TEST(TestObjectPlayer, Watch) { + std::string oid = this->get_temp_oid(); + journal::ObjectPlayerPtr object = this->create_object(oid, 14); + + C_SaferCond cond1; + object->watch(&cond1, 0.1); + + journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1'))); + journal::Entry entry2(234, 124, this->create_payload(std::string(24, '1'))); + + bufferlist bl; + encode(entry1, bl); + ASSERT_EQ(0, this->append(this->get_object_name(oid), bl)); + ASSERT_LE(0, cond1.wait()); + + journal::ObjectPlayer::Entries entries; + ASSERT_EQ(0, this->watch_and_wait_for_entries(object, &entries, 1U)); + ASSERT_EQ(1U, entries.size()); + + journal::ObjectPlayer::Entries expected_entries; + expected_entries = {entry1}; + ASSERT_EQ(expected_entries, entries); + + C_SaferCond cond2; + object->watch(&cond2, 0.1); + + bl.clear(); + encode(entry2, bl); + ASSERT_EQ(0, this->append(this->get_object_name(oid), bl)); + ASSERT_LE(0, cond2.wait()); + + ASSERT_EQ(0, this->watch_and_wait_for_entries(object, &entries, 2U)); + ASSERT_EQ(2U, entries.size()); + + expected_entries = {entry1, entry2}; + ASSERT_EQ(expected_entries, entries); +} + +TYPED_TEST(TestObjectPlayer, Unwatch) { + std::string oid = this->get_temp_oid(); + journal::ObjectPlayerPtr object = this->create_object(oid, 14); + + C_SaferCond watch_ctx; + object->watch(&watch_ctx, 600); + + usleep(200000); + + object->unwatch(); + ASSERT_EQ(-ECANCELED, watch_ctx.wait()); +} |