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