summaryrefslogtreecommitdiffstats
path: root/src/test/common/test_ceph_timer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/common/test_ceph_timer.cc')
-rw-r--r--src/test/common/test_ceph_timer.cc163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/test/common/test_ceph_timer.cc b/src/test/common/test_ceph_timer.cc
new file mode 100644
index 000000000..12391c7ea
--- /dev/null
+++ b/src/test/common/test_ceph_timer.cc
@@ -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>();
+}