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