]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/context/test/test_callcc.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / context / test / test_callcc.cpp
1
2 // Copyright Oliver Kowalke 2009.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #include <stdio.h>
8 #include <stdlib.h>
9
10 #include <cmath>
11 #include <cstdint>
12 #include <cstdio>
13 #include <iostream>
14 #include <memory>
15 #include <sstream>
16 #include <stdexcept>
17 #include <string>
18 #include <thread>
19 #include <utility>
20 #include <vector>
21
22 #include <boost/array.hpp>
23 #include <boost/assert.hpp>
24 #include <boost/lexical_cast.hpp>
25 #include <boost/test/unit_test.hpp>
26 #include <boost/utility.hpp>
27 #include <boost/variant.hpp>
28
29 #include <boost/context/continuation.hpp>
30 #include <boost/context/detail/config.hpp>
31
32 #ifdef BOOST_WINDOWS
33 #include <windows.h>
34 #endif
35
36 #if defined(BOOST_MSVC)
37 # pragma warning(push)
38 # pragma warning(disable: 4702 4723 4996)
39 #endif
40
41 typedef boost::variant<int,std::string> variant_t;
42
43 namespace ctx = boost::context;
44
45 int value1 = 0;
46 std::string value2;
47 double value3 = 0.;
48
49 struct X {
50 ctx::continuation foo( ctx::continuation && c, int i) {
51 value1 = i;
52 return std::move( c);
53 }
54 };
55
56 struct Y {
57 Y() {
58 value1 = 3;
59 }
60
61 Y( Y const&) = delete;
62 Y & operator=( Y const&) = delete;
63
64 ~Y() {
65 value1 = 7;
66 }
67 };
68
69 class moveable {
70 public:
71 bool state;
72 int value;
73
74 moveable() :
75 state( false),
76 value( -1) {
77 }
78
79 moveable( int v) :
80 state( true),
81 value( v) {
82 }
83
84 moveable( moveable && other) :
85 state( other.state),
86 value( other.value) {
87 other.state = false;
88 other.value = -1;
89 }
90
91 moveable & operator=( moveable && other) {
92 if ( this == & other) return * this;
93 state = other.state;
94 value = other.value;
95 other.state = false;
96 other.value = -1;
97 return * this;
98 }
99
100 moveable( moveable const& other) = delete;
101 moveable & operator=( moveable const& other) = delete;
102
103 void operator()() {
104 value1 = value;
105 }
106 };
107
108 struct my_exception : public std::runtime_error {
109 ctx::continuation c;
110 my_exception( ctx::continuation && c_, char const* what) :
111 std::runtime_error( what),
112 c{ std::move( c_) } {
113 }
114 };
115
116 #ifdef BOOST_MSVC
117 // Optimizations can remove the integer-divide-by-zero here.
118 #pragma optimize("", off)
119 void seh( bool & catched) {
120 __try {
121 int i = 1;
122 i /= 0;
123 } __except( EXCEPTION_EXECUTE_HANDLER) {
124 catched = true;
125 }
126 }
127 #pragma optimize("", on)
128 #endif
129
130 void test_move() {
131 value1 = 0;
132 int i = 1;
133 BOOST_CHECK_EQUAL( 0, value1);
134 ctx::continuation c1 = ctx::callcc(
135 [&i](ctx::continuation && c) {
136 value1 = i;
137 c = c.resume();
138 value1 = i;
139 return std::move( c);
140 });
141 BOOST_CHECK_EQUAL( 1, value1);
142 BOOST_CHECK( c1);
143 ctx::continuation c2;
144 BOOST_CHECK( ! c2);
145 c2 = std::move( c1);
146 BOOST_CHECK( ! c1);
147 BOOST_CHECK( c2);
148 i = 3;
149 c2.resume();
150 BOOST_CHECK_EQUAL( 3, value1);
151 BOOST_CHECK( ! c1);
152 BOOST_CHECK( ! c2);
153 }
154
155 void test_bind() {
156 value1 = 0;
157 X x;
158 ctx::continuation c = ctx::callcc( std::bind( & X::foo, x, std::placeholders::_1, 7) );
159 BOOST_CHECK_EQUAL( 7, value1);
160 }
161
162 void test_exception() {
163 {
164 const char * what = "hello world";
165 ctx::continuation c = ctx::callcc(
166 [&what](ctx::continuation && c) {
167 try {
168 throw std::runtime_error( what);
169 } catch ( std::runtime_error const& e) {
170 value2 = e.what();
171 }
172 return std::move( c);
173 });
174 BOOST_CHECK_EQUAL( std::string( what), value2);
175 BOOST_CHECK( ! c);
176 }
177 #ifdef BOOST_MSVC
178 {
179 bool catched = false;
180 std::thread([&catched](){
181 ctx::continuation c = ctx::callcc([&catched](ctx::continuation && c){
182 c = c.resume();
183 seh( catched);
184 return std::move( c);
185 });
186 BOOST_CHECK( c );
187 c.resume();
188 }).join();
189 BOOST_CHECK( catched);
190 }
191 #endif
192 }
193
194 void test_fp() {
195 value3 = 0.;
196 double d = 7.13;
197 ctx::continuation c = ctx::callcc(
198 [&d]( ctx::continuation && c) {
199 d += 3.45;
200 value3 = d;
201 return std::move( c);
202 });
203 BOOST_CHECK_EQUAL( 10.58, value3);
204 BOOST_CHECK( ! c);
205 }
206
207 void test_stacked() {
208 value1 = 0;
209 value3 = 0.;
210 ctx::continuation c = ctx::callcc(
211 [](ctx::continuation && c) {
212 ctx::continuation c1 = ctx::callcc(
213 [](ctx::continuation && c) {
214 value1 = 3;
215 return std::move( c);
216 });
217 value3 = 3.14;
218 return std::move( c);
219 });
220 BOOST_CHECK_EQUAL( 3, value1);
221 BOOST_CHECK_EQUAL( 3.14, value3);
222 BOOST_CHECK( ! c );
223 }
224
225 void test_prealloc() {
226 value1 = 0;
227 ctx::default_stack alloc;
228 ctx::stack_context sctx( alloc.allocate() );
229 void * sp = static_cast< char * >( sctx.sp) - 10;
230 std::size_t size = sctx.size - 10;
231 int i = 7;
232 ctx::continuation c = ctx::callcc(
233 std::allocator_arg, ctx::preallocated( sp, size, sctx), alloc,
234 [&i]( ctx::continuation && c) {
235 value1 = i;
236 return std::move( c);
237 });
238 BOOST_CHECK_EQUAL( 7, value1);
239 BOOST_CHECK( ! c);
240 }
241
242 void test_ontop() {
243 {
244 int i = 3;
245 ctx::continuation c = ctx::callcc([&i](ctx::continuation && c) {
246 for (;;) {
247 i *= 10;
248 c = c.resume();
249 }
250 return std::move( c);
251 });
252 c = c.resume_with(
253 [&i](ctx::continuation && c){
254 i -= 10;
255 return std::move( c);
256 });
257 BOOST_CHECK( c);
258 BOOST_CHECK_EQUAL( i, 200);
259 }
260 {
261 ctx::continuation c1;
262 ctx::continuation c = ctx::callcc([&c1](ctx::continuation && c) {
263 c = c.resume();
264 BOOST_CHECK( ! c);
265 return std::move( c1);
266 });
267 c = c.resume_with(
268 [&c1](ctx::continuation && c){
269 c1 = std::move( c);
270 return std::move( c);
271 });
272 }
273 }
274
275 void test_ontop_exception() {
276 value1 = 0;
277 value2 = "";
278 ctx::continuation c = ctx::callcc([](ctx::continuation && c){
279 for (;;) {
280 value1 = 3;
281 try {
282 c = c.resume();
283 } catch ( my_exception & ex) {
284 value2 = ex.what();
285 return std::move( ex.c);
286 }
287 }
288 return std::move( c);
289 });
290 c = c.resume();
291 BOOST_CHECK_EQUAL( 3, value1);
292 const char * what = "hello world";
293 c.resume_with(
294 [what](ctx::continuation && c){
295 throw my_exception( std::move( c), what);
296 return std::move( c);
297 });
298 BOOST_CHECK_EQUAL( 3, value1);
299 BOOST_CHECK_EQUAL( std::string( what), value2);
300 }
301
302 void test_termination() {
303 {
304 value1 = 0;
305 ctx::continuation c = ctx::callcc(
306 [](ctx::continuation && c){
307 Y y;
308 return c.resume();
309 });
310 BOOST_CHECK_EQUAL( 3, value1);
311 }
312 BOOST_CHECK_EQUAL( 7, value1);
313 {
314 value1 = 0;
315 BOOST_CHECK_EQUAL( 0, value1);
316 ctx::continuation c = ctx::callcc(
317 [](ctx::continuation && c) {
318 value1 = 3;
319 return std::move( c);
320 });
321 BOOST_CHECK_EQUAL( 3, value1);
322 BOOST_CHECK( ! c );
323 }
324 {
325 value1 = 0;
326 BOOST_CHECK_EQUAL( 0, value1);
327 int i = 3;
328 ctx::continuation c = ctx::callcc(
329 [&i](ctx::continuation && c){
330 value1 = i;
331 c = c.resume();
332 value1 = i;
333 return std::move( c);
334 });
335 BOOST_CHECK( c);
336 BOOST_CHECK_EQUAL( i, value1);
337 BOOST_CHECK( c);
338 i = 7;
339 c = c.resume();
340 BOOST_CHECK( ! c);
341 BOOST_CHECK_EQUAL( i, value1);
342 }
343 }
344
345 void test_sscanf() {
346 ctx::continuation c = ctx::callcc(
347 []( ctx::continuation && c) {
348 {
349 double n1 = 0;
350 double n2 = 0;
351 sscanf("3.14 7.13", "%lf %lf", & n1, & n2);
352 BOOST_CHECK( n1 == 3.14);
353 BOOST_CHECK( n2 == 7.13);
354 }
355 {
356 int n1=0;
357 int n2=0;
358 sscanf("1 23", "%d %d", & n1, & n2);
359 BOOST_CHECK( n1 == 1);
360 BOOST_CHECK( n2 == 23);
361 }
362 {
363 int n1=0;
364 int n2=0;
365 sscanf("1 jjj 23", "%d %*[j] %d", & n1, & n2);
366 BOOST_CHECK( n1 == 1);
367 BOOST_CHECK( n2 == 23);
368 }
369 return std::move( c);
370 });
371 }
372
373 void test_snprintf() {
374 ctx::continuation c = ctx::callcc(
375 []( ctx::continuation && c) {
376 {
377 const char *fmt = "sqrt(2) = %f";
378 char buf[15];
379 snprintf( buf, sizeof( buf), fmt, std::sqrt( 2) );
380 BOOST_CHECK( 0 < sizeof( buf) );
381 BOOST_ASSERT( std::string("sqrt(2) = 1.41") == std::string( buf, 14) );
382 }
383 {
384 std::uint64_t n = 0xbcdef1234567890;
385 const char *fmt = "0x%016llX";
386 char buf[100];
387 snprintf( buf, sizeof( buf), fmt, n);
388 BOOST_ASSERT( std::string("0x0BCDEF1234567890") == std::string( buf, 18) );
389 }
390 return std::move( c);
391 });
392 }
393
394 #ifdef BOOST_WINDOWS
395 void test_bug12215() {
396 ctx::continuation c = ctx::callcc(
397 [](ctx::continuation && c) {
398 char buffer[MAX_PATH];
399 GetModuleFileName( nullptr, buffer, MAX_PATH);
400 return std::move( c);
401 });
402 }
403 #endif
404
405 boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
406 {
407 boost::unit_test::test_suite * test =
408 BOOST_TEST_SUITE("Boost.Context: callcc test suite");
409
410 test->add( BOOST_TEST_CASE( & test_move) );
411 test->add( BOOST_TEST_CASE( & test_bind) );
412 test->add( BOOST_TEST_CASE( & test_exception) );
413 test->add( BOOST_TEST_CASE( & test_fp) );
414 test->add( BOOST_TEST_CASE( & test_stacked) );
415 test->add( BOOST_TEST_CASE( & test_prealloc) );
416 test->add( BOOST_TEST_CASE( & test_ontop) );
417 test->add( BOOST_TEST_CASE( & test_ontop_exception) );
418 test->add( BOOST_TEST_CASE( & test_termination) );
419 test->add( BOOST_TEST_CASE( & test_sscanf) );
420 test->add( BOOST_TEST_CASE( & test_snprintf) );
421 #ifdef BOOST_WINDOWS
422 test->add( BOOST_TEST_CASE( & test_bug12215) );
423 #endif
424
425 return test;
426 }
427
428 #if defined(BOOST_MSVC)
429 # pragma warning(pop)
430 #endif