]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/asio/test/system_timer.cpp
Add patch for failing prerm scripts
[ceph.git] / ceph / src / boost / libs / asio / test / system_timer.cpp
CommitLineData
7c673cae
FG
1//
2// system_timer.cpp
3// ~~~~~~~~~~~~~~~~
4//
11fdf7f2 5// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7c673cae
FG
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11// Disable autolinking for unit tests.
12#if !defined(BOOST_ALL_NO_LIB)
13#define BOOST_ALL_NO_LIB 1
14#endif // !defined(BOOST_ALL_NO_LIB)
15
16// Prevent link dependency on the Boost.System library.
17#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
18#define BOOST_SYSTEM_NO_DEPRECATED
19#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
20
21// Test that header file is self-contained.
22#include <boost/asio/system_timer.hpp>
23
24#include "unit_test.hpp"
25
26#if defined(BOOST_ASIO_HAS_STD_CHRONO)
27
b32b8144
FG
28#include <boost/asio/executor_work_guard.hpp>
29#include <boost/asio/io_context.hpp>
7c673cae
FG
30#include <boost/asio/detail/thread.hpp>
31
32#if defined(BOOST_ASIO_HAS_BOOST_BIND)
33# include <boost/bind.hpp>
34#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
35# include <functional>
36#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
37
38#if defined(BOOST_ASIO_HAS_BOOST_BIND)
39namespace bindns = boost;
40#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
41namespace bindns = std;
42#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
43
7c673cae
FG
44void increment(int* count)
45{
46 ++(*count);
47}
48
49void decrement_to_zero(boost::asio::system_timer* t, int* count)
50{
51 if (*count > 0)
52 {
53 --(*count);
54
55 int before_value = *count;
56
b32b8144 57 t->expires_at(t->expiry() + boost::asio::chrono::seconds(1));
7c673cae
FG
58 t->async_wait(bindns::bind(decrement_to_zero, t, count));
59
60 // Completion cannot nest, so count value should remain unchanged.
61 BOOST_ASIO_CHECK(*count == before_value);
62 }
63}
64
65void increment_if_not_cancelled(int* count,
66 const boost::system::error_code& ec)
67{
68 if (!ec)
69 ++(*count);
70}
71
72void cancel_timer(boost::asio::system_timer* t)
73{
74 std::size_t num_cancelled = t->cancel();
75 BOOST_ASIO_CHECK(num_cancelled == 1);
76}
77
78void cancel_one_timer(boost::asio::system_timer* t)
79{
80 std::size_t num_cancelled = t->cancel_one();
81 BOOST_ASIO_CHECK(num_cancelled == 1);
82}
83
84boost::asio::system_timer::time_point now()
85{
86 return boost::asio::system_timer::clock_type::now();
87}
88
89void system_timer_test()
90{
b32b8144
FG
91 using boost::asio::chrono::seconds;
92 using boost::asio::chrono::microseconds;
7c673cae
FG
93#if !defined(BOOST_ASIO_HAS_BOOST_BIND)
94 using std::placeholders::_1;
95 using std::placeholders::_2;
96#endif // !defined(BOOST_ASIO_HAS_BOOST_BIND)
97
b32b8144 98 boost::asio::io_context ioc;
7c673cae
FG
99 int count = 0;
100
101 boost::asio::system_timer::time_point start = now();
102
b32b8144 103 boost::asio::system_timer t1(ioc, seconds(1));
7c673cae
FG
104 t1.wait();
105
106 // The timer must block until after its expiry time.
107 boost::asio::system_timer::time_point end = now();
108 boost::asio::system_timer::time_point expected_end = start + seconds(1);
109 BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
110
111 start = now();
112
b32b8144 113 boost::asio::system_timer t2(ioc, seconds(1) + microseconds(500000));
7c673cae
FG
114 t2.wait();
115
116 // The timer must block until after its expiry time.
117 end = now();
118 expected_end = start + seconds(1) + microseconds(500000);
119 BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
120
b32b8144 121 t2.expires_at(t2.expiry() + seconds(1));
7c673cae
FG
122 t2.wait();
123
124 // The timer must block until after its expiry time.
125 end = now();
126 expected_end += seconds(1);
127 BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
128
129 start = now();
130
b32b8144 131 t2.expires_after(seconds(1) + microseconds(200000));
7c673cae
FG
132 t2.wait();
133
134 // The timer must block until after its expiry time.
135 end = now();
136 expected_end = start + seconds(1) + microseconds(200000);
137 BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
138
139 start = now();
140
b32b8144 141 boost::asio::system_timer t3(ioc, seconds(5));
7c673cae
FG
142 t3.async_wait(bindns::bind(increment, &count));
143
144 // No completions can be delivered until run() is called.
145 BOOST_ASIO_CHECK(count == 0);
146
b32b8144 147 ioc.run();
7c673cae
FG
148
149 // The run() call will not return until all operations have finished, and
150 // this should not be until after the timer's expiry time.
151 BOOST_ASIO_CHECK(count == 1);
152 end = now();
153 expected_end = start + seconds(1);
154 BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
155
156 count = 3;
157 start = now();
158
b32b8144 159 boost::asio::system_timer t4(ioc, seconds(1));
7c673cae
FG
160 t4.async_wait(bindns::bind(decrement_to_zero, &t4, &count));
161
162 // No completions can be delivered until run() is called.
163 BOOST_ASIO_CHECK(count == 3);
164
b32b8144
FG
165 ioc.restart();
166 ioc.run();
7c673cae
FG
167
168 // The run() call will not return until all operations have finished, and
169 // this should not be until after the timer's final expiry time.
170 BOOST_ASIO_CHECK(count == 0);
171 end = now();
172 expected_end = start + seconds(3);
173 BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
174
175 count = 0;
176 start = now();
177
b32b8144 178 boost::asio::system_timer t5(ioc, seconds(10));
7c673cae 179 t5.async_wait(bindns::bind(increment_if_not_cancelled, &count, _1));
b32b8144 180 boost::asio::system_timer t6(ioc, seconds(1));
7c673cae
FG
181 t6.async_wait(bindns::bind(cancel_timer, &t5));
182
183 // No completions can be delivered until run() is called.
184 BOOST_ASIO_CHECK(count == 0);
185
b32b8144
FG
186 ioc.restart();
187 ioc.run();
7c673cae
FG
188
189 // The timer should have been cancelled, so count should not have changed.
190 // The total run time should not have been much more than 1 second (and
191 // certainly far less than 10 seconds).
192 BOOST_ASIO_CHECK(count == 0);
193 end = now();
194 expected_end = start + seconds(2);
195 BOOST_ASIO_CHECK(end < expected_end);
196
197 // Wait on the timer again without cancelling it. This time the asynchronous
198 // wait should run to completion and increment the counter.
199 t5.async_wait(bindns::bind(increment_if_not_cancelled, &count, _1));
200
b32b8144
FG
201 ioc.restart();
202 ioc.run();
7c673cae
FG
203
204 // The timer should not have been cancelled, so count should have changed.
205 // The total time since the timer was created should be more than 10 seconds.
206 BOOST_ASIO_CHECK(count == 1);
207 end = now();
208 expected_end = start + seconds(10);
209 BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
210
211 count = 0;
212 start = now();
213
214 // Start two waits on a timer, one of which will be cancelled. The one
215 // which is not cancelled should still run to completion and increment the
216 // counter.
b32b8144 217 boost::asio::system_timer t7(ioc, seconds(3));
7c673cae
FG
218 t7.async_wait(bindns::bind(increment_if_not_cancelled, &count, _1));
219 t7.async_wait(bindns::bind(increment_if_not_cancelled, &count, _1));
b32b8144 220 boost::asio::system_timer t8(ioc, seconds(1));
7c673cae
FG
221 t8.async_wait(bindns::bind(cancel_one_timer, &t7));
222
b32b8144
FG
223 ioc.restart();
224 ioc.run();
7c673cae
FG
225
226 // One of the waits should not have been cancelled, so count should have
227 // changed. The total time since the timer was created should be more than 3
228 // seconds.
229 BOOST_ASIO_CHECK(count == 1);
230 end = now();
231 expected_end = start + seconds(3);
232 BOOST_ASIO_CHECK(expected_end < end || expected_end == end);
233}
234
b32b8144 235struct timer_handler
7c673cae 236{
b32b8144
FG
237 timer_handler() {}
238 void operator()(const boost::system::error_code&) {}
239#if defined(BOOST_ASIO_HAS_MOVE)
240 timer_handler(timer_handler&&) {}
241private:
242 timer_handler(const timer_handler&);
243#endif // defined(BOOST_ASIO_HAS_MOVE)
244};
7c673cae
FG
245
246void system_timer_cancel_test()
247{
b32b8144 248 static boost::asio::io_context io_context;
7c673cae
FG
249 struct timer
250 {
251 boost::asio::system_timer t;
b32b8144 252 timer() : t(io_context)
7c673cae
FG
253 {
254 t.expires_at((boost::asio::system_timer::time_point::max)());
255 }
256 } timers[50];
257
b32b8144
FG
258 timers[2].t.async_wait(timer_handler());
259 timers[41].t.async_wait(timer_handler());
7c673cae 260 for (int i = 10; i < 20; ++i)
b32b8144 261 timers[i].t.async_wait(timer_handler());
7c673cae
FG
262
263 BOOST_ASIO_CHECK(timers[2].t.cancel() == 1);
264 BOOST_ASIO_CHECK(timers[41].t.cancel() == 1);
265 for (int i = 10; i < 20; ++i)
266 BOOST_ASIO_CHECK(timers[i].t.cancel() == 1);
267}
268
269struct custom_allocation_timer_handler
270{
271 custom_allocation_timer_handler(int* count) : count_(count) {}
272 void operator()(const boost::system::error_code&) {}
273 int* count_;
274};
275
276void* asio_handler_allocate(std::size_t size,
277 custom_allocation_timer_handler* handler)
278{
279 ++(*handler->count_);
280 return ::operator new(size);
281}
282
283void asio_handler_deallocate(void* pointer, std::size_t,
284 custom_allocation_timer_handler* handler)
285{
286 --(*handler->count_);
287 ::operator delete(pointer);
288}
289
290void system_timer_custom_allocation_test()
291{
b32b8144 292 static boost::asio::io_context io_context;
7c673cae
FG
293 struct timer
294 {
295 boost::asio::system_timer t;
b32b8144 296 timer() : t(io_context) {}
7c673cae
FG
297 } timers[100];
298
299 int allocation_count = 0;
300
301 for (int i = 0; i < 50; ++i)
302 {
303 timers[i].t.expires_at((boost::asio::system_timer::time_point::max)());
304 timers[i].t.async_wait(custom_allocation_timer_handler(&allocation_count));
305 }
306
307 for (int i = 50; i < 100; ++i)
308 {
309 timers[i].t.expires_at((boost::asio::system_timer::time_point::min)());
310 timers[i].t.async_wait(custom_allocation_timer_handler(&allocation_count));
311 }
312
313 for (int i = 0; i < 50; ++i)
314 timers[i].t.cancel();
315
b32b8144 316 io_context.run();
7c673cae
FG
317
318 BOOST_ASIO_CHECK(allocation_count == 0);
319}
320
b32b8144 321void io_context_run(boost::asio::io_context* ioc)
7c673cae 322{
b32b8144 323 ioc->run();
7c673cae
FG
324}
325
326void system_timer_thread_test()
327{
b32b8144
FG
328 boost::asio::io_context ioc;
329 boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work
330 = boost::asio::make_work_guard(ioc);
331 boost::asio::system_timer t1(ioc);
332 boost::asio::system_timer t2(ioc);
7c673cae
FG
333 int count = 0;
334
b32b8144 335 boost::asio::detail::thread th(bindns::bind(io_context_run, &ioc));
7c673cae 336
b32b8144 337 t2.expires_after(boost::asio::chrono::seconds(2));
7c673cae
FG
338 t2.wait();
339
b32b8144 340 t1.expires_after(boost::asio::chrono::seconds(2));
7c673cae
FG
341 t1.async_wait(bindns::bind(increment, &count));
342
b32b8144 343 t2.expires_after(boost::asio::chrono::seconds(4));
7c673cae
FG
344 t2.wait();
345
b32b8144 346 ioc.stop();
7c673cae
FG
347 th.join();
348
349 BOOST_ASIO_CHECK(count == 1);
350}
351
b32b8144
FG
352#if defined(BOOST_ASIO_HAS_MOVE)
353boost::asio::system_timer make_timer(boost::asio::io_context& ioc, int* count)
354{
355 boost::asio::system_timer t(ioc);
356 t.expires_after(boost::asio::chrono::seconds(1));
357 t.async_wait(bindns::bind(increment, count));
358 return t;
359}
360#endif
361
362void system_timer_move_test()
363{
364#if defined(BOOST_ASIO_HAS_MOVE)
365 boost::asio::io_context io_context1;
366 boost::asio::io_context io_context2;
367 int count = 0;
368
369 boost::asio::system_timer t1 = make_timer(io_context1, &count);
370 boost::asio::system_timer t2 = make_timer(io_context2, &count);
371 boost::asio::system_timer t3 = std::move(t1);
372
373 t2 = std::move(t1);
374
375 io_context2.run();
376
377 BOOST_ASIO_CHECK(count == 1);
378
379 io_context1.run();
380
381 BOOST_ASIO_CHECK(count == 2);
382#endif // defined(BOOST_ASIO_HAS_MOVE)
383}
384
7c673cae
FG
385BOOST_ASIO_TEST_SUITE
386(
387 "system_timer",
388 BOOST_ASIO_TEST_CASE(system_timer_test)
389 BOOST_ASIO_TEST_CASE(system_timer_cancel_test)
390 BOOST_ASIO_TEST_CASE(system_timer_custom_allocation_test)
391 BOOST_ASIO_TEST_CASE(system_timer_thread_test)
b32b8144 392 BOOST_ASIO_TEST_CASE(system_timer_move_test)
7c673cae
FG
393)
394#else // defined(BOOST_ASIO_HAS_STD_CHRONO)
395BOOST_ASIO_TEST_SUITE
396(
397 "system_timer",
398 BOOST_ASIO_TEST_CASE(null_test)
399)
400#endif // defined(BOOST_ASIO_HAS_STD_CHRONO)