]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/TestTimers.cc
update ceph source to reef 18.2.0
[ceph.git] / ceph / src / test / TestTimers.cc
1 #include "common/ceph_argparse.h"
2 #include "common/ceph_mutex.h"
3 #include "common/Timer.h"
4 #include "global/global_init.h"
5 #include "include/Context.h"
6
7 #include <iostream>
8
9 /*
10 * TestTimers
11 *
12 * Tests the timer classes
13 */
14 #define MAX_TEST_CONTEXTS 5
15
16 using namespace std;
17
18 class TestContext;
19
20 namespace
21 {
22 int test_array[MAX_TEST_CONTEXTS];
23 int array_idx;
24 TestContext* test_contexts[MAX_TEST_CONTEXTS];
25
26 ceph::mutex array_lock = ceph::make_mutex("test_timers_mutex");
27 }
28
29 class TestContext : public Context
30 {
31 public:
32 explicit TestContext(int num_)
33 : num(num_)
34 {
35 }
36
37 void finish(int r) override
38 {
39 std::lock_guard locker{array_lock};
40 cout << "TestContext " << num << std::endl;
41 test_array[array_idx++] = num;
42 }
43
44 ~TestContext() override
45 {
46 }
47
48 protected:
49 int num;
50 };
51
52 class StrictOrderTestContext : public TestContext
53 {
54 public:
55 explicit StrictOrderTestContext (int num_)
56 : TestContext(num_)
57 {
58 }
59
60 void finish(int r) override
61 {
62 std::lock_guard locker{array_lock};
63 cout << "StrictOrderTestContext " << num << std::endl;
64 test_array[num] = num;
65 }
66
67 ~StrictOrderTestContext() override
68 {
69 }
70 };
71
72 static void print_status(const char *str, int ret)
73 {
74 cout << str << ": ";
75 cout << ((ret == 0) ? "SUCCESS" : "FAILURE");
76 cout << std::endl;
77 }
78
79 template <typename T>
80 static int basic_timer_test(T &timer, ceph::mutex *lock)
81 {
82 int ret = 0;
83 memset(&test_array, 0, sizeof(test_array));
84 array_idx = 0;
85 memset(&test_contexts, 0, sizeof(test_contexts));
86
87 cout << __PRETTY_FUNCTION__ << std::endl;
88
89 for (int i = 0; i < MAX_TEST_CONTEXTS; ++i) {
90 test_contexts[i] = new TestContext(i);
91 }
92
93
94 for (int i = 0; i < MAX_TEST_CONTEXTS; ++i) {
95 if (lock)
96 lock->lock();
97 auto t = ceph::real_clock::now() + std::chrono::seconds(2 * i);
98 timer.add_event_at(t, test_contexts[i]);
99 if (lock)
100 lock->unlock();
101 }
102
103 bool done = false;
104 do {
105 sleep(1);
106 std::lock_guard locker{array_lock};
107 done = (array_idx == MAX_TEST_CONTEXTS);
108 } while (!done);
109
110 for (int i = 0; i < MAX_TEST_CONTEXTS; ++i) {
111 if (test_array[i] != i) {
112 ret = 1;
113 cout << "error: expected test_array[" << i << "] = " << i
114 << "; got " << test_array[i] << " instead." << std::endl;
115 }
116 }
117
118 return ret;
119 }
120
121 static int test_out_of_order_insertion(SafeTimer &timer, ceph::mutex *lock)
122 {
123 int ret = 0;
124 memset(&test_array, 0, sizeof(test_array));
125 array_idx = 0;
126 memset(&test_contexts, 0, sizeof(test_contexts));
127
128 cout << __PRETTY_FUNCTION__ << std::endl;
129
130 test_contexts[0] = new StrictOrderTestContext(0);
131 test_contexts[1] = new StrictOrderTestContext(1);
132
133 {
134 auto t = ceph::real_clock::now() + 100s;
135 std::lock_guard locker{*lock};
136 timer.add_event_at(t, test_contexts[0]);
137 }
138
139 {
140 auto t = ceph::real_clock::now() + 2s;
141 std::lock_guard locker{*lock};
142 timer.add_event_at(t, test_contexts[1]);
143 }
144
145 int secs = 0;
146 for (; secs < 100 ; ++secs) {
147 sleep(1);
148 array_lock.lock();
149 int a = test_array[1];
150 array_lock.unlock();
151 if (a == 1)
152 break;
153 }
154
155 if (secs == 100) {
156 ret = 1;
157 cout << "error: expected test_array[" << 1 << "] = " << 1
158 << "; got " << test_array[1] << " instead." << std::endl;
159 }
160
161 return ret;
162 }
163
164 static int safe_timer_cancel_all_test(SafeTimer &safe_timer,
165 ceph::mutex& safe_timer_lock)
166 {
167 cout << __PRETTY_FUNCTION__ << std::endl;
168
169 int ret = 0;
170 memset(&test_array, 0, sizeof(test_array));
171 array_idx = 0;
172 memset(&test_contexts, 0, sizeof(test_contexts));
173
174 for (int i = 0; i < MAX_TEST_CONTEXTS; ++i) {
175 test_contexts[i] = new TestContext(i);
176 }
177
178 safe_timer_lock.lock();
179 for (int i = 0; i < MAX_TEST_CONTEXTS; ++i) {
180 auto t = ceph::real_clock::now() + std::chrono::seconds(4 * i);
181 safe_timer.add_event_at(t, test_contexts[i]);
182 }
183 safe_timer_lock.unlock();
184
185 sleep(10);
186
187 safe_timer_lock.lock();
188 safe_timer.cancel_all_events();
189 safe_timer_lock.unlock();
190
191 for (int i = 0; i < array_idx; ++i) {
192 if (test_array[i] != i) {
193 ret = 1;
194 cout << "error: expected test_array[" << i << "] = " << i
195 << "; got " << test_array[i] << " instead." << std::endl;
196 }
197 }
198
199 return ret;
200 }
201
202 static int safe_timer_cancellation_test(SafeTimer &safe_timer,
203 ceph::mutex& safe_timer_lock)
204 {
205 cout << __PRETTY_FUNCTION__ << std::endl;
206
207 int ret = 0;
208 memset(&test_array, 0, sizeof(test_array));
209 array_idx = 0;
210 memset(&test_contexts, 0, sizeof(test_contexts));
211
212 for (int i = 0; i < MAX_TEST_CONTEXTS; ++i) {
213 test_contexts[i] = new StrictOrderTestContext(i);
214 }
215
216 safe_timer_lock.lock();
217 for (int i = 0; i < MAX_TEST_CONTEXTS; ++i) {
218 auto t = ceph::real_clock::now() + std::chrono::seconds(4 * i);
219 safe_timer.add_event_at(t, test_contexts[i]);
220 }
221 safe_timer_lock.unlock();
222
223 // cancel the even-numbered events
224 for (int i = 0; i < MAX_TEST_CONTEXTS; i += 2) {
225 safe_timer_lock.lock();
226 safe_timer.cancel_event(test_contexts[i]);
227 safe_timer_lock.unlock();
228 }
229
230 sleep(20);
231
232 safe_timer_lock.lock();
233 safe_timer.cancel_all_events();
234 safe_timer_lock.unlock();
235
236 for (int i = 1; i < array_idx; i += 2) {
237 if (test_array[i] != i) {
238 ret = 1;
239 cout << "error: expected test_array[" << i << "] = " << i
240 << "; got " << test_array[i] << " instead." << std::endl;
241 }
242 }
243
244 return ret;
245 }
246
247 int main(int argc, const char **argv)
248 {
249 auto args = argv_to_vec(argc, argv);
250
251 auto cct = global_init(nullptr, args, CEPH_ENTITY_TYPE_CLIENT,
252 CODE_ENVIRONMENT_UTILITY,
253 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
254 common_init_finish(g_ceph_context);
255
256 int ret;
257 ceph::mutex safe_timer_lock = ceph::make_mutex("safe_timer_lock");
258 SafeTimer safe_timer(g_ceph_context, safe_timer_lock);
259 safe_timer.init();
260
261 ret = basic_timer_test <SafeTimer>(safe_timer, &safe_timer_lock);
262 if (ret)
263 goto done;
264
265 ret = safe_timer_cancel_all_test(safe_timer, safe_timer_lock);
266 if (ret)
267 goto done;
268
269 ret = safe_timer_cancellation_test(safe_timer, safe_timer_lock);
270 if (ret)
271 goto done;
272
273 ret = test_out_of_order_insertion(safe_timer, &safe_timer_lock);
274 if (ret)
275 goto done;
276
277 done:
278 safe_timer.shutdown();
279 print_status(argv[0], ret);
280 return ret;
281 }