initial code repo
[stor4nfv.git] / src / ceph / src / test / journal / test_FutureImpl.cc
diff --git a/src/ceph/src/test/journal/test_FutureImpl.cc b/src/ceph/src/test/journal/test_FutureImpl.cc
new file mode 100644 (file)
index 0000000..f904c6e
--- /dev/null
@@ -0,0 +1,281 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "journal/FutureImpl.h"
+#include "common/Cond.h"
+#include "common/Mutex.h"
+#include "gtest/gtest.h"
+#include "test/journal/RadosTestFixture.h"
+
+class TestFutureImpl : public RadosTestFixture {
+public:
+  struct FlushHandler : public journal::FutureImpl::FlushHandler {
+    uint64_t refs;
+    uint64_t flushes;
+    FlushHandler() : refs(0), flushes(0) {}
+    void get() override {
+      ++refs;
+    }
+    void put() override {
+      assert(refs > 0);
+      --refs;
+    }
+    void flush(const journal::FutureImplPtr &future) override {
+      ++flushes;
+    }
+  };
+
+  journal::FutureImplPtr create_future(uint64_t tag_tid, uint64_t entry_tid,
+                                       uint64_t commit_tid,
+                                       const journal::FutureImplPtr &prev =
+                                         journal::FutureImplPtr()) {
+    journal::FutureImplPtr future(new journal::FutureImpl(tag_tid,
+                                                          entry_tid,
+                                                          commit_tid));
+    future->init(prev);
+    return future;
+  }
+
+  void flush(const journal::FutureImplPtr &future) {
+  }
+
+  FlushHandler m_flush_handler;
+};
+
+TEST_F(TestFutureImpl, Getters) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future = create_future(234, 123, 456);
+  ASSERT_EQ(234U, future->get_tag_tid());
+  ASSERT_EQ(123U, future->get_entry_tid());
+  ASSERT_EQ(456U, future->get_commit_tid());
+}
+
+TEST_F(TestFutureImpl, Attach) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future = create_future(234, 123, 456);
+  ASSERT_FALSE(future->attach(&m_flush_handler));
+  ASSERT_EQ(1U, m_flush_handler.refs);
+}
+
+TEST_F(TestFutureImpl, AttachWithPendingFlush) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future = create_future(234, 123, 456);
+  future->flush(NULL);
+
+  ASSERT_TRUE(future->attach(&m_flush_handler));
+  ASSERT_EQ(1U, m_flush_handler.refs);
+}
+
+TEST_F(TestFutureImpl, Detach) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future = create_future(234, 123, 456);
+  ASSERT_FALSE(future->attach(&m_flush_handler));
+  future->detach();
+  ASSERT_EQ(0U, m_flush_handler.refs);
+}
+
+TEST_F(TestFutureImpl, DetachImplicit) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future = create_future(234, 123, 456);
+  ASSERT_FALSE(future->attach(&m_flush_handler));
+  future.reset();
+  ASSERT_EQ(0U, m_flush_handler.refs);
+}
+
+TEST_F(TestFutureImpl, Flush) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future = create_future(234, 123, 456);
+  ASSERT_FALSE(future->attach(&m_flush_handler));
+
+  C_SaferCond cond;
+  future->flush(&cond);
+
+  ASSERT_EQ(1U, m_flush_handler.flushes);
+  future->safe(-EIO);
+  ASSERT_EQ(-EIO, cond.wait());
+}
+
+TEST_F(TestFutureImpl, FlushWithoutContext) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future = create_future(234, 123, 456);
+  ASSERT_FALSE(future->attach(&m_flush_handler));
+
+  future->flush(NULL);
+  ASSERT_EQ(1U, m_flush_handler.flushes);
+  future->safe(-EIO);
+  ASSERT_TRUE(future->is_complete());
+  ASSERT_EQ(-EIO, future->get_return_value());
+}
+
+TEST_F(TestFutureImpl, FlushChain) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future1 = create_future(234, 123, 456);
+  journal::FutureImplPtr future2 = create_future(234, 124, 457,
+                                                 future1);
+  journal::FutureImplPtr future3 = create_future(235, 1, 458,
+                                                 future2);
+
+  FlushHandler flush_handler;
+  ASSERT_FALSE(future1->attach(&m_flush_handler));
+  ASSERT_FALSE(future2->attach(&flush_handler));
+  ASSERT_FALSE(future3->attach(&m_flush_handler));
+
+  C_SaferCond cond;
+  future3->flush(&cond);
+
+  ASSERT_EQ(1U, m_flush_handler.flushes);
+  ASSERT_EQ(1U, flush_handler.flushes);
+
+  future3->safe(0);
+  ASSERT_FALSE(future3->is_complete());
+
+  future1->safe(0);
+  ASSERT_FALSE(future3->is_complete());
+
+  future2->safe(-EIO);
+  ASSERT_TRUE(future3->is_complete());
+  ASSERT_EQ(-EIO, future3->get_return_value());
+  ASSERT_EQ(-EIO, cond.wait());
+  ASSERT_EQ(0, future1->get_return_value());
+}
+
+TEST_F(TestFutureImpl, FlushInProgress) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future1 = create_future(234, 123, 456);
+  journal::FutureImplPtr future2 = create_future(234, 124, 457,
+                                                 future1);
+  ASSERT_FALSE(future1->attach(&m_flush_handler));
+  ASSERT_FALSE(future2->attach(&m_flush_handler));
+
+  future1->set_flush_in_progress();
+  ASSERT_TRUE(future1->is_flush_in_progress());
+
+  future1->flush(NULL);
+  ASSERT_EQ(0U, m_flush_handler.flushes);
+
+  future1->safe(0);
+}
+
+TEST_F(TestFutureImpl, FlushAlreadyComplete) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future = create_future(234, 123, 456);
+  future->safe(-EIO);
+
+  C_SaferCond cond;
+  future->flush(&cond);
+  ASSERT_EQ(-EIO, cond.wait());
+}
+
+TEST_F(TestFutureImpl, Wait) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future = create_future(234, 1, 456);
+
+  C_SaferCond cond;
+  future->wait(&cond);
+  future->safe(-EEXIST);
+  ASSERT_EQ(-EEXIST, cond.wait());
+}
+
+TEST_F(TestFutureImpl, WaitAlreadyComplete) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future = create_future(234, 1, 456);
+  future->safe(-EEXIST);
+
+  C_SaferCond cond;
+  future->wait(&cond);
+  ASSERT_EQ(-EEXIST, cond.wait());
+}
+
+TEST_F(TestFutureImpl, SafePreservesError) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future1 = create_future(234, 123, 456);
+  journal::FutureImplPtr future2 = create_future(234, 124, 457,
+                                                 future1);
+
+  future1->safe(-EIO);
+  future2->safe(-EEXIST);
+  ASSERT_TRUE(future2->is_complete());
+  ASSERT_EQ(-EIO, future2->get_return_value());
+}
+
+TEST_F(TestFutureImpl, ConsistentPreservesError) {
+  std::string oid = get_temp_oid();
+  ASSERT_EQ(0, create(oid));
+  ASSERT_EQ(0, client_register(oid));
+  journal::JournalMetadataPtr metadata = create_metadata(oid);
+  ASSERT_EQ(0, init_metadata(metadata));
+
+  journal::FutureImplPtr future1 = create_future(234, 123, 456);
+  journal::FutureImplPtr future2 = create_future(234, 124, 457,
+                                                 future1);
+
+  future2->safe(-EEXIST);
+  future1->safe(-EIO);
+  ASSERT_TRUE(future2->is_complete());
+  ASSERT_EQ(-EEXIST, future2->get_return_value());
+}