]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | #include "common/ceph_argparse.h" |
9f95a23c | 2 | #include "common/ceph_mutex.h" |
7c673cae FG |
3 | #include "common/Timer.h" |
4 | #include "global/global_init.h" | |
9f95a23c | 5 | #include "include/Context.h" |
7c673cae FG |
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 | ||
9f95a23c | 24 | ceph::mutex array_lock = ceph::make_mutex("test_timers_mutex"); |
7c673cae FG |
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 | { | |
9f95a23c | 37 | std::lock_guard locker{array_lock}; |
7c673cae FG |
38 | cout << "TestContext " << num << std::endl; |
39 | test_array[array_idx++] = num; | |
7c673cae FG |
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 | { | |
9f95a23c | 60 | std::lock_guard locker{array_lock}; |
7c673cae FG |
61 | cout << "StrictOrderTestContext " << num << std::endl; |
62 | test_array[num] = num; | |
7c673cae FG |
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> | |
9f95a23c | 78 | static int basic_timer_test(T &timer, ceph::mutex *lock) |
7c673cae FG |
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) | |
9f95a23c TL |
94 | lock->lock(); |
95 | auto t = ceph::real_clock::now() + std::chrono::seconds(2 * i); | |
7c673cae FG |
96 | timer.add_event_at(t, test_contexts[i]); |
97 | if (lock) | |
9f95a23c | 98 | lock->unlock(); |
7c673cae FG |
99 | } |
100 | ||
101 | bool done = false; | |
102 | do { | |
103 | sleep(1); | |
9f95a23c | 104 | std::lock_guard locker{array_lock}; |
7c673cae | 105 | done = (array_idx == MAX_TEST_CONTEXTS); |
7c673cae FG |
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 | ||
9f95a23c | 119 | static int test_out_of_order_insertion(SafeTimer &timer, ceph::mutex *lock) |
7c673cae FG |
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 | { | |
9f95a23c TL |
132 | auto t = ceph::real_clock::now() + 100s; |
133 | std::lock_guard locker{*lock}; | |
7c673cae | 134 | timer.add_event_at(t, test_contexts[0]); |
7c673cae FG |
135 | } |
136 | ||
137 | { | |
9f95a23c TL |
138 | auto t = ceph::real_clock::now() + 2s; |
139 | std::lock_guard locker{*lock}; | |
7c673cae | 140 | timer.add_event_at(t, test_contexts[1]); |
7c673cae FG |
141 | } |
142 | ||
143 | int secs = 0; | |
144 | for (; secs < 100 ; ++secs) { | |
145 | sleep(1); | |
9f95a23c | 146 | array_lock.lock(); |
7c673cae | 147 | int a = test_array[1]; |
9f95a23c | 148 | array_lock.unlock(); |
7c673cae FG |
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 | ||
9f95a23c TL |
162 | static int safe_timer_cancel_all_test(SafeTimer &safe_timer, |
163 | ceph::mutex& safe_timer_lock) | |
7c673cae FG |
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 | ||
9f95a23c | 176 | safe_timer_lock.lock(); |
7c673cae | 177 | for (int i = 0; i < MAX_TEST_CONTEXTS; ++i) { |
9f95a23c | 178 | auto t = ceph::real_clock::now() + std::chrono::seconds(4 * i); |
7c673cae FG |
179 | safe_timer.add_event_at(t, test_contexts[i]); |
180 | } | |
9f95a23c | 181 | safe_timer_lock.unlock(); |
7c673cae FG |
182 | |
183 | sleep(10); | |
184 | ||
9f95a23c | 185 | safe_timer_lock.lock(); |
7c673cae | 186 | safe_timer.cancel_all_events(); |
9f95a23c | 187 | safe_timer_lock.unlock(); |
7c673cae FG |
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 | ||
9f95a23c TL |
200 | static int safe_timer_cancellation_test(SafeTimer &safe_timer, |
201 | ceph::mutex& safe_timer_lock) | |
7c673cae FG |
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 | ||
9f95a23c | 214 | safe_timer_lock.lock(); |
7c673cae | 215 | for (int i = 0; i < MAX_TEST_CONTEXTS; ++i) { |
9f95a23c | 216 | auto t = ceph::real_clock::now() + std::chrono::seconds(4 * i); |
7c673cae FG |
217 | safe_timer.add_event_at(t, test_contexts[i]); |
218 | } | |
9f95a23c | 219 | safe_timer_lock.unlock(); |
7c673cae FG |
220 | |
221 | // cancel the even-numbered events | |
222 | for (int i = 0; i < MAX_TEST_CONTEXTS; i += 2) { | |
9f95a23c | 223 | safe_timer_lock.lock(); |
7c673cae | 224 | safe_timer.cancel_event(test_contexts[i]); |
9f95a23c | 225 | safe_timer_lock.unlock(); |
7c673cae FG |
226 | } |
227 | ||
228 | sleep(20); | |
229 | ||
9f95a23c | 230 | safe_timer_lock.lock(); |
7c673cae | 231 | safe_timer.cancel_all_events(); |
9f95a23c | 232 | safe_timer_lock.unlock(); |
7c673cae FG |
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); | |
7c673cae FG |
249 | |
250 | auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, | |
11fdf7f2 TL |
251 | CODE_ENVIRONMENT_UTILITY, |
252 | CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); | |
7c673cae FG |
253 | common_init_finish(g_ceph_context); |
254 | ||
255 | int ret; | |
9f95a23c | 256 | ceph::mutex safe_timer_lock = ceph::make_mutex("safe_timer_lock"); |
7c673cae FG |
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 | } |