]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/common/test_ceph_timer.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / test / common / test_ceph_timer.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2020 Red Hat
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include <chrono>
16 #include <future>
17 #include <vector>
18
19 #include <gtest/gtest.h>
20
21 #include "common/ceph_timer.h"
22
23 using namespace std::literals;
24
25 namespace {
26 template<typename TC>
27 void run_some()
28 {
29 static constexpr auto MAX_FUTURES = 5;
30 ceph::timer<TC> timer;
31 std::vector<std::future<void>> futures;
32 for (auto i = 0; i < MAX_FUTURES; ++i) {
33 auto t = TC::now() + 2s;
34 std::promise<void> p;
35 futures.push_back(p.get_future());
36 timer.add_event(t, [p = std::move(p)]() mutable {
37 p.set_value();
38 });
39 }
40 for (auto& f : futures)
41 f.get();
42 }
43
44 template<typename TC>
45 void run_orderly()
46 {
47 ceph::timer<TC> timer;
48
49 std::future<typename TC::time_point> first;
50 std::future<typename TC::time_point> second;
51
52
53 {
54 std::promise<typename TC::time_point> p;
55 second = p.get_future();
56 timer.add_event(4s, [p = std::move(p)]() mutable {
57 p.set_value(TC::now());
58 });
59 }
60 {
61 std::promise<typename TC::time_point> p;
62 first = p.get_future();
63 timer.add_event(2s, [p = std::move(p)]() mutable {
64 p.set_value(TC::now());
65 });
66 }
67
68 EXPECT_LT(first.get(), second.get());
69 }
70
71 struct Destructo {
72 bool armed = true;
73 std::promise<void> p;
74
75 Destructo(std::promise<void>&& p) : p(std::move(p)) {}
76 Destructo(const Destructo&) = delete;
77 Destructo& operator =(const Destructo&) = delete;
78 Destructo(Destructo&& rhs) {
79 p = std::move(rhs.p);
80 armed = rhs.armed;
81 rhs.armed = false;
82 }
83 Destructo& operator =(Destructo& rhs) {
84 p = std::move(rhs.p);
85 rhs.armed = false;
86 armed = rhs.armed;
87 rhs.armed = false;
88 return *this;
89 }
90
91 ~Destructo() {
92 if (armed)
93 p.set_value();
94 }
95 void operator ()() const {
96 FAIL();
97 }
98 };
99
100 template<typename TC>
101 void cancel_all()
102 {
103 ceph::timer<TC> timer;
104 static constexpr auto MAX_FUTURES = 5;
105 std::vector<std::future<void>> futures;
106 for (auto i = 0; i < MAX_FUTURES; ++i) {
107 std::promise<void> p;
108 futures.push_back(p.get_future());
109 timer.add_event(100s + i*1s, Destructo(std::move(p)));
110 }
111 timer.cancel_all_events();
112 for (auto& f : futures)
113 f.get();
114 }
115
116 template<typename TC>
117 void cancellation()
118 {
119 ceph::timer<TC> timer;
120 {
121 std::promise<void> p;
122 auto f = p.get_future();
123 auto e = timer.add_event(100s, Destructo(std::move(p)));
124 EXPECT_TRUE(timer.cancel_event(e));
125 }
126 {
127 std::promise<void> p;
128 auto f = p.get_future();
129 auto e = timer.add_event(1s, [p = std::move(p)]() mutable {
130 p.set_value();
131 });
132 f.get();
133 EXPECT_FALSE(timer.cancel_event(e));
134 }
135 }
136 }
137
138 TEST(RunSome, Steady)
139 {
140 run_some<std::chrono::steady_clock>();
141 }
142 TEST(RunSome, Wall)
143 {
144 run_some<std::chrono::system_clock>();
145 }
146
147 TEST(RunOrderly, Steady)
148 {
149 run_orderly<std::chrono::steady_clock>();
150 }
151 TEST(RunOrderly, Wall)
152 {
153 run_orderly<std::chrono::system_clock>();
154 }
155
156 TEST(CancelAll, Steady)
157 {
158 cancel_all<std::chrono::steady_clock>();
159 }
160 TEST(CancelAll, Wall)
161 {
162 cancel_all<std::chrono::system_clock>();
163 }