]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
common/ceph_timer: Add test
authorAdam C. Emerson <aemerson@redhat.com>
Fri, 6 Mar 2020 02:45:11 +0000 (21:45 -0500)
committerAdam C. Emerson <aemerson@redhat.com>
Mon, 9 Mar 2020 15:52:45 +0000 (11:52 -0400)
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
src/test/common/CMakeLists.txt
src/test/common/test_ceph_timer.cc [new file with mode: 0644]

index 0fa36a24d1778796d194513dda1eaeb9347e66fb..e67d9718b2998271263fee2923190b32fd55ed21 100644 (file)
@@ -327,4 +327,6 @@ add_executable(unittest_rabin_chunk test_rabin_chunk.cc
 target_link_libraries(unittest_rabin_chunk global ceph-common)
 add_ceph_unittest(unittest_rabin_chunk)
 
-
+add_executable(unittest_ceph_timer test_ceph_timer.cc)
+target_link_libraries(unittest_rabin_chunk GTest::GTest)
+add_ceph_unittest(unittest_ceph_timer)
diff --git a/src/test/common/test_ceph_timer.cc b/src/test/common/test_ceph_timer.cc
new file mode 100644 (file)
index 0000000..12391c7
--- /dev/null
@@ -0,0 +1,163 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2020 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include <chrono>
+#include <future>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "common/ceph_timer.h"
+
+using namespace std::literals;
+
+namespace {
+template<typename TC>
+void run_some()
+{
+  static constexpr auto MAX_FUTURES = 5;
+  ceph::timer<TC> timer;
+  std::vector<std::future<void>> futures;
+  for (auto i = 0; i < MAX_FUTURES; ++i) {
+    auto t = TC::now() + 2s;
+    std::promise<void> p;
+    futures.push_back(p.get_future());
+    timer.add_event(t, [p = std::move(p)]() mutable {
+                         p.set_value();
+                       });
+  }
+  for (auto& f : futures)
+    f.get();
+}
+
+template<typename TC>
+void run_orderly()
+{
+  ceph::timer<TC> timer;
+
+  std::future<typename TC::time_point> first;
+  std::future<typename TC::time_point> second;
+
+
+  {
+    std::promise<typename TC::time_point> p;
+    second = p.get_future();
+    timer.add_event(4s, [p = std::move(p)]() mutable {
+                          p.set_value(TC::now());
+                        });
+  }
+  {
+    std::promise<typename TC::time_point> p;
+    first = p.get_future();
+    timer.add_event(2s, [p = std::move(p)]() mutable {
+                          p.set_value(TC::now());
+                        });
+  }
+
+  EXPECT_LT(first.get(), second.get());
+}
+
+struct Destructo {
+  bool armed = true;
+  std::promise<void> p;
+
+  Destructo(std::promise<void>&& p) : p(std::move(p)) {}
+  Destructo(const Destructo&) = delete;
+  Destructo& operator =(const Destructo&) = delete;
+  Destructo(Destructo&& rhs) {
+    p = std::move(rhs.p);
+    armed = rhs.armed;
+    rhs.armed = false;
+  }
+  Destructo& operator =(Destructo& rhs) {
+    p = std::move(rhs.p);
+    rhs.armed = false;
+    armed = rhs.armed;
+    rhs.armed = false;
+    return *this;
+  }
+
+  ~Destructo() {
+    if (armed)
+      p.set_value();
+  }
+  void operator ()() const {
+    FAIL();
+  }
+};
+
+template<typename TC>
+void cancel_all()
+{
+  ceph::timer<TC> timer;
+  static constexpr auto MAX_FUTURES = 5;
+  std::vector<std::future<void>> futures;
+  for (auto i = 0; i < MAX_FUTURES; ++i) {
+    std::promise<void> p;
+    futures.push_back(p.get_future());
+    timer.add_event(100s + i*1s, Destructo(std::move(p)));
+  }
+  timer.cancel_all_events();
+  for (auto& f : futures)
+    f.get();
+}
+
+template<typename TC>
+void cancellation()
+{
+  ceph::timer<TC> timer;
+  {
+    std::promise<void> p;
+    auto f = p.get_future();
+    auto e = timer.add_event(100s, Destructo(std::move(p)));
+    EXPECT_TRUE(timer.cancel_event(e));
+  }
+  {
+    std::promise<void> p;
+    auto f = p.get_future();
+    auto e = timer.add_event(1s, [p = std::move(p)]() mutable {
+                                   p.set_value();
+                                 });
+    f.get();
+    EXPECT_FALSE(timer.cancel_event(e));
+  }
+}
+}
+
+TEST(RunSome, Steady)
+{
+  run_some<std::chrono::steady_clock>();
+}
+TEST(RunSome, Wall)
+{
+  run_some<std::chrono::system_clock>();
+}
+
+TEST(RunOrderly, Steady)
+{
+  run_orderly<std::chrono::steady_clock>();
+}
+TEST(RunOrderly, Wall)
+{
+  run_orderly<std::chrono::system_clock>();
+}
+
+TEST(CancelAll, Steady)
+{
+  cancel_all<std::chrono::steady_clock>();
+}
+TEST(CancelAll, Wall)
+{
+  cancel_all<std::chrono::system_clock>();
+}