]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/coroutine/test/test_asymmetric_coroutine.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / coroutine / test / test_asymmetric_coroutine.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 <boost/coroutine/asymmetric_coroutine.hpp>
8
9 #include <algorithm>
10 #include <iostream>
11 #include <sstream>
12 #include <stdexcept>
13 #include <string>
14 #include <vector>
15
16 #include <cstdio>
17
18 #include <boost/assert.hpp>
19 #include <boost/bind.hpp>
20 #include <boost/foreach.hpp>
21 #include <boost/move/move.hpp>
22 #include <boost/range.hpp>
23 #include <boost/ref.hpp>
24 #include <boost/test/unit_test.hpp>
25 #include <boost/tuple/tuple.hpp>
26 #include <boost/utility.hpp>
27
28 namespace coro = boost::coroutines;
29
30 int value1 = 0;
31 std::string value2 = "";
32 bool value3 = false;
33 double value4 = .0;
34 int * value5 = 0;
35 int& value6 = value1;
36 int& value7 = value1;
37 int value8 = 0;
38 int value9 = 0;
39
40 struct X : private boost::noncopyable
41 {
42 X() { value1 = 7; }
43 ~X() { value1 = 0; }
44 };
45
46 class copyable
47 {
48 public:
49 bool state;
50
51 copyable() :
52 state( false)
53 {}
54
55 copyable( int) :
56 state( true)
57 {}
58
59 void operator()( coro::asymmetric_coroutine< int >::push_type &)
60 { value3 = state; }
61 };
62
63 class moveable
64 {
65 private:
66 BOOST_MOVABLE_BUT_NOT_COPYABLE( moveable)
67
68 public:
69 bool state;
70
71 moveable() :
72 state( false)
73 {}
74
75 moveable( int) :
76 state( true)
77 {}
78
79 moveable( BOOST_RV_REF( moveable) other) :
80 state( false)
81 { std::swap( state, other.state); }
82
83 moveable & operator=( BOOST_RV_REF( moveable) other)
84 {
85 if ( this == & other) return * this;
86 moveable tmp( boost::move( other) );
87 std::swap( state, tmp.state);
88 return * this;
89 }
90
91 void operator()( coro::asymmetric_coroutine< int >::push_type &)
92 { value3 = state; }
93 };
94
95 struct my_exception {};
96
97 void f1( coro::asymmetric_coroutine< void >::push_type & c)
98 {
99 while ( c)
100 c();
101 }
102
103 void f2( coro::asymmetric_coroutine< void >::push_type &)
104 { ++value1; }
105
106 void f3( coro::asymmetric_coroutine< void >::push_type & c)
107 {
108 ++value1;
109 c();
110 ++value1;
111 }
112
113 void f4( coro::asymmetric_coroutine< int >::push_type & c)
114 {
115 c( 3);
116 c( 7);
117 }
118
119 void f5( coro::asymmetric_coroutine< std::string >::push_type & c)
120 {
121 std::string res("abc");
122 c( res);
123 res = "xyz";
124 c( res);
125 }
126
127 void f6( coro::asymmetric_coroutine< int >::pull_type & c)
128 { value1 = c.get(); }
129
130 void f7( coro::asymmetric_coroutine< std::string >::pull_type & c)
131 { value2 = c.get(); }
132
133 void f8( coro::asymmetric_coroutine< boost::tuple< double, double > >::pull_type & c)
134 {
135 double x = 0, y = 0;
136 boost::tie( x, y) = c.get();
137 value4 = x + y;
138 c();
139 boost::tie( x, y) = c.get();
140 value4 = x + y;
141 }
142
143 void f9( coro::asymmetric_coroutine< int * >::pull_type & c)
144 { value5 = c.get(); }
145
146 void f91( coro::asymmetric_coroutine< int const* >::pull_type & c)
147 { value5 = const_cast< int * >( c.get() ); }
148
149 void f10( coro::asymmetric_coroutine< int & >::pull_type & c)
150 {
151 int const& i = c.get();
152 value5 = const_cast< int * >( & i);
153 }
154
155 void f101( coro::asymmetric_coroutine< int const& >::pull_type & c)
156 {
157 int const& i = c.get();
158 value5 = const_cast< int * >( & i);
159 }
160
161 void f11( coro::asymmetric_coroutine< boost::tuple< int, int > >::pull_type & c)
162 {
163 boost::tie( value8, value9) = c.get();
164 }
165
166 void f12( coro::asymmetric_coroutine< void >::pull_type & c)
167 {
168 X x_;
169 c();
170 c();
171 }
172
173 template< typename E >
174 void f14( coro::asymmetric_coroutine< void >::pull_type &, E const& e)
175 { throw e; }
176
177 void f16( coro::asymmetric_coroutine< int >::push_type & c)
178 {
179 c( 1);
180 c( 2);
181 c( 3);
182 c( 4);
183 c( 5);
184 }
185
186 void f17( coro::asymmetric_coroutine< int >::pull_type & c, std::vector< int > & vec)
187 {
188 int x = c.get();
189 while ( 5 > x)
190 {
191 vec.push_back( x);
192 x = c().get();
193 }
194 }
195
196 void f19( coro::asymmetric_coroutine< int* >::push_type & c, std::vector< int * > & vec)
197 {
198 BOOST_FOREACH( int * ptr, vec)
199 { c( ptr); }
200 }
201
202 void f20( coro::asymmetric_coroutine< int >::push_type &)
203 {}
204
205 void f21( coro::asymmetric_coroutine< int >::pull_type & c)
206 {
207 while ( c)
208 {
209 value1 = c.get();
210 c();
211 }
212 }
213
214 void test_move()
215 {
216 {
217 coro::asymmetric_coroutine< void >::pull_type coro1;
218 coro::asymmetric_coroutine< void >::pull_type coro2( f1);
219 BOOST_CHECK( ! coro1);
220 BOOST_CHECK( coro2);
221 coro2();
222 coro1 = boost::move( coro2);
223 BOOST_CHECK( coro1);
224 coro1();
225 BOOST_CHECK( ! coro2);
226 }
227
228 {
229 value3 = false;
230 copyable cp( 3);
231 BOOST_CHECK( cp.state);
232 BOOST_CHECK( ! value3);
233 coro::asymmetric_coroutine< int >::pull_type coro( cp);
234 BOOST_CHECK( cp.state);
235 BOOST_CHECK( value3);
236 }
237
238 {
239 value3 = false;
240 moveable mv( 7);
241 BOOST_CHECK( mv.state);
242 BOOST_CHECK( ! value3);
243 coro::asymmetric_coroutine< int >::pull_type coro( boost::move( mv) );
244 BOOST_CHECK( ! mv.state);
245 BOOST_CHECK( value3);
246 }
247 }
248
249 void test_complete()
250 {
251 value1 = 0;
252
253 coro::asymmetric_coroutine< void >::pull_type coro( f2);
254 BOOST_CHECK( ! coro);
255 BOOST_CHECK_EQUAL( ( int)1, value1);
256 }
257
258 void test_jump()
259 {
260 value1 = 0;
261
262 coro::asymmetric_coroutine< void >::pull_type coro( f3);
263 BOOST_CHECK( coro);
264 BOOST_CHECK_EQUAL( ( int)1, value1);
265 coro();
266 BOOST_CHECK( ! coro);
267 BOOST_CHECK_EQUAL( ( int)2, value1);
268 }
269
270 void test_result_int()
271 {
272 coro::asymmetric_coroutine< int >::pull_type coro( f4);
273 BOOST_CHECK( coro);
274 int result = coro.get();
275 BOOST_CHECK( coro);
276 BOOST_CHECK_EQUAL( 3, result);
277 result = coro().get();
278 BOOST_CHECK( coro);
279 BOOST_CHECK_EQUAL( 7, result);
280 coro();
281 BOOST_CHECK( ! coro);
282 }
283
284 void test_result_string()
285 {
286 coro::asymmetric_coroutine< std::string >::pull_type coro( f5);
287 BOOST_CHECK( coro);
288 std::string result = coro.get();
289 BOOST_CHECK( coro);
290 BOOST_CHECK_EQUAL( std::string("abc"), result);
291 result = coro().get();
292 BOOST_CHECK( coro);
293 BOOST_CHECK_EQUAL( std::string("xyz"), result);
294 coro();
295 BOOST_CHECK( ! coro);
296 }
297
298 void test_arg_int()
299 {
300 value1 = 0;
301
302 coro::asymmetric_coroutine< int >::push_type coro( f6);
303 BOOST_CHECK( coro);
304 coro( 3);
305 BOOST_CHECK( ! coro);
306 BOOST_CHECK_EQUAL( 3, value1);
307 }
308
309 void test_arg_string()
310 {
311 value2 = "";
312
313 coro::asymmetric_coroutine< std::string >::push_type coro( f7);
314 BOOST_CHECK( coro);
315 coro( std::string("abc") );
316 BOOST_CHECK( ! coro);
317 BOOST_CHECK_EQUAL( std::string("abc"), value2);
318 }
319
320 void test_fp()
321 {
322 value4 = 0;
323
324 coro::asymmetric_coroutine< boost::tuple< double, double > >::push_type coro( f8);
325 BOOST_CHECK( coro);
326 coro( boost::make_tuple( 7.35, 3.14) );
327 BOOST_CHECK( coro);
328 BOOST_CHECK_EQUAL( ( double) 10.49, value4);
329
330 value4 = 0;
331 coro( boost::make_tuple( 1.15, 3.14) );
332 BOOST_CHECK( ! coro);
333 BOOST_CHECK_EQUAL( ( double) 4.29, value4);
334 }
335
336 void test_ptr()
337 {
338 value5 = 0;
339
340 int a = 3;
341 coro::asymmetric_coroutine< int * >::push_type coro( f9);
342 BOOST_CHECK( coro);
343 coro( & a);
344 BOOST_CHECK( ! coro);
345 BOOST_CHECK_EQUAL( & a, value5);
346 }
347
348 void test_const_ptr()
349 {
350 value5 = 0;
351
352 int a = 3;
353 coro::asymmetric_coroutine< int const* >::push_type coro( f91);
354 BOOST_CHECK( coro);
355 coro( & a);
356 BOOST_CHECK( ! coro);
357 BOOST_CHECK_EQUAL( & a, value5);
358 }
359
360 void test_ref()
361 {
362 value5 = 0;
363
364 int a = 3;
365 coro::asymmetric_coroutine< int & >::push_type coro( f10);
366 BOOST_CHECK( coro);
367 coro( a);
368 BOOST_CHECK( ! coro);
369 BOOST_CHECK_EQUAL( & a, value5);
370 }
371
372 void test_const_ref()
373 {
374 value5 = 0;
375
376 int a = 3;
377 coro::asymmetric_coroutine< int const& >::push_type coro( f101);
378 BOOST_CHECK( coro);
379 coro( a);
380 BOOST_CHECK( ! coro);
381 BOOST_CHECK_EQUAL( & a, value5);
382 }
383
384 void test_tuple()
385 {
386 value8 = 0;
387 value9 = 0;
388
389 int a = 3, b = 7;
390 boost::tuple< int, int > tpl( a, b);
391 BOOST_CHECK_EQUAL( a, tpl.get< 0 >() );
392 BOOST_CHECK_EQUAL( b, tpl.get< 1 >() );
393 coro::asymmetric_coroutine< boost::tuple< int, int > >::push_type coro( f11);
394 BOOST_CHECK( coro);
395 coro( tpl);
396 BOOST_CHECK( ! coro);
397 BOOST_CHECK_EQUAL( a, value8);
398 BOOST_CHECK_EQUAL( b, value9);
399 }
400
401 void test_unwind()
402 {
403 value1 = 0;
404 {
405 coro::asymmetric_coroutine< void >::push_type coro( f12);
406 BOOST_CHECK( coro);
407 BOOST_CHECK_EQUAL( ( int) 0, value1);
408 coro();
409 BOOST_CHECK( coro);
410 BOOST_CHECK_EQUAL( ( int) 7, value1);
411 coro();
412 BOOST_CHECK_EQUAL( ( int) 7, value1);
413 }
414 BOOST_CHECK_EQUAL( ( int) 0, value1);
415 }
416
417 void test_no_unwind()
418 {
419 value1 = 0;
420 {
421 coro::asymmetric_coroutine< void >::push_type coro(
422 f12,
423 coro::attributes(
424 coro::stack_allocator::traits_type::default_size(),
425 coro::no_stack_unwind) );
426 BOOST_CHECK( coro);
427 BOOST_CHECK_EQUAL( ( int) 0, value1);
428 coro();
429 BOOST_CHECK( coro);
430 BOOST_CHECK_EQUAL( ( int) 7, value1);
431 coro();
432 BOOST_CHECK_EQUAL( ( int) 7, value1);
433 }
434 BOOST_CHECK_EQUAL( ( int) 7, value1);
435 }
436
437 void test_exceptions()
438 {
439 bool thrown = false;
440 std::runtime_error ex("abc");
441 try
442 {
443 coro::asymmetric_coroutine< void >::push_type coro( boost::bind( f14< std::runtime_error >, _1, ex) );
444 BOOST_CHECK( coro);
445 coro();
446 BOOST_CHECK( ! coro);
447 BOOST_CHECK( false);
448 }
449 catch ( std::runtime_error const&)
450 { thrown = true; }
451 catch ( std::exception const&)
452 {}
453 catch (...)
454 {}
455 BOOST_CHECK( thrown);
456 }
457
458 void test_input_iterator()
459 {
460 {
461 std::vector< int > vec;
462 coro::asymmetric_coroutine< int >::pull_type coro( f16);
463 BOOST_FOREACH( int i, coro)
464 { vec.push_back( i); }
465 BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
466 BOOST_CHECK_EQUAL( ( int)1, vec[0] );
467 BOOST_CHECK_EQUAL( ( int)2, vec[1] );
468 BOOST_CHECK_EQUAL( ( int)3, vec[2] );
469 BOOST_CHECK_EQUAL( ( int)4, vec[3] );
470 BOOST_CHECK_EQUAL( ( int)5, vec[4] );
471 }
472 {
473 std::vector< int > vec;
474 coro::asymmetric_coroutine< int >::pull_type coro( f16);
475 coro::asymmetric_coroutine< int >::pull_type::iterator e = boost::end( coro);
476 for (
477 coro::asymmetric_coroutine< int >::pull_type::iterator i = boost::begin( coro);
478 i != e; ++i)
479 { vec.push_back( * i); }
480 BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
481 BOOST_CHECK_EQUAL( ( int)1, vec[0] );
482 BOOST_CHECK_EQUAL( ( int)2, vec[1] );
483 BOOST_CHECK_EQUAL( ( int)3, vec[2] );
484 BOOST_CHECK_EQUAL( ( int)4, vec[3] );
485 BOOST_CHECK_EQUAL( ( int)5, vec[4] );
486 }
487 {
488 int i1 = 1, i2 = 2, i3 = 3;
489 std::vector< int* > vec_in;
490 vec_in.push_back( & i1);
491 vec_in.push_back( & i2);
492 vec_in.push_back( & i3);
493 std::vector< int* > vec_out;
494 coro::asymmetric_coroutine< int* >::pull_type coro( boost::bind( f19, _1, boost::ref( vec_in) ) );
495 coro::asymmetric_coroutine< int* >::pull_type::iterator e = boost::end( coro);
496 for (
497 coro::asymmetric_coroutine< int* >::pull_type::iterator i = boost::begin( coro);
498 i != e; ++i)
499 {
500 int * p = * i;
501 vec_out.push_back( p);
502 }
503 BOOST_CHECK_EQUAL( ( std::size_t)3, vec_out.size() );
504 BOOST_CHECK_EQUAL( & i1, vec_out[0] );
505 BOOST_CHECK_EQUAL( & i2, vec_out[1] );
506 BOOST_CHECK_EQUAL( & i3, vec_out[2] );
507 }
508 }
509
510 void test_output_iterator()
511 {
512 int counter = 0;
513 std::vector< int > vec;
514 coro::asymmetric_coroutine< int >::push_type coro(
515 boost::bind( f17, _1, boost::ref( vec) ) );
516 coro::asymmetric_coroutine< int >::push_type::iterator e( boost::end( coro) );
517 for ( coro::asymmetric_coroutine< int >::push_type::iterator i( boost::begin( coro) );
518 i != e; ++i)
519 {
520 i = ++counter;
521 }
522 BOOST_CHECK_EQUAL( ( std::size_t)4, vec.size() );
523 BOOST_CHECK_EQUAL( ( int)1, vec[0] );
524 BOOST_CHECK_EQUAL( ( int)2, vec[1] );
525 BOOST_CHECK_EQUAL( ( int)3, vec[2] );
526 BOOST_CHECK_EQUAL( ( int)4, vec[3] );
527 }
528
529 void test_invalid_result()
530 {
531 bool catched = false;
532 coro::asymmetric_coroutine< int >::pull_type coro( f20);
533 BOOST_CHECK( ! coro);
534 try
535 {
536 int i = coro.get();
537 (void)i;
538 }
539 catch ( coro::invalid_result const&)
540 {
541 catched = true;
542 }
543 BOOST_CHECK( catched);
544 }
545 void test_move_coro()
546 {
547 value1 = 0;
548
549 coro::asymmetric_coroutine< int >::push_type coro1( f21);
550 coro::asymmetric_coroutine< int >::push_type coro2;
551 BOOST_CHECK( coro1);
552 BOOST_CHECK( ! coro2);
553
554 coro1( 1);
555 BOOST_CHECK_EQUAL( ( int)1, value1);
556
557 coro2 = boost::move( coro1);
558 BOOST_CHECK( ! coro1);
559 BOOST_CHECK( coro2);
560
561 coro2( 2);
562 BOOST_CHECK_EQUAL( ( int)2, value1);
563
564 coro1 = boost::move( coro2);
565 BOOST_CHECK( coro1);
566 BOOST_CHECK( ! coro2);
567
568 coro1( 3);
569 BOOST_CHECK_EQUAL( ( int)3, value1);
570
571 coro2 = boost::move( coro1);
572 BOOST_CHECK( ! coro1);
573 BOOST_CHECK( coro2);
574
575 coro2( 4);
576 BOOST_CHECK_EQUAL( ( int)4, value1);
577 }
578
579 void foo( coro::asymmetric_coroutine< int >::push_type & yield)
580 {
581 yield( 1);
582 }
583
584 coro::asymmetric_coroutine< int >::pull_type make_range()
585 {
586 return coro::asymmetric_coroutine< int >::pull_type( foo);
587 }
588
589 template< typename Range >
590 void const_func( Range const& r)
591 {
592 begin( r);
593 }
594
595 void test_range()
596 {
597 const_func( make_range() );
598 }
599
600 boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
601 {
602 boost::unit_test::test_suite * test =
603 BOOST_TEST_SUITE("Boost.coroutine: asymmetric coroutine test suite");
604
605 test->add( BOOST_TEST_CASE( & test_move) );
606 test->add( BOOST_TEST_CASE( & test_complete) );
607 test->add( BOOST_TEST_CASE( & test_jump) );
608 test->add( BOOST_TEST_CASE( & test_result_int) );
609 test->add( BOOST_TEST_CASE( & test_result_string) );
610 test->add( BOOST_TEST_CASE( & test_arg_int) );
611 test->add( BOOST_TEST_CASE( & test_arg_string) );
612 test->add( BOOST_TEST_CASE( & test_fp) );
613 test->add( BOOST_TEST_CASE( & test_ptr) );
614 test->add( BOOST_TEST_CASE( & test_const_ptr) );
615 test->add( BOOST_TEST_CASE( & test_invalid_result) );
616 test->add( BOOST_TEST_CASE( & test_ref) );
617 test->add( BOOST_TEST_CASE( & test_const_ref) );
618 test->add( BOOST_TEST_CASE( & test_tuple) );
619 test->add( BOOST_TEST_CASE( & test_unwind) );
620 test->add( BOOST_TEST_CASE( & test_no_unwind) );
621 test->add( BOOST_TEST_CASE( & test_exceptions) );
622 test->add( BOOST_TEST_CASE( & test_input_iterator) );
623 test->add( BOOST_TEST_CASE( & test_output_iterator) );
624 test->add( BOOST_TEST_CASE( & test_range) );
625
626 return test;
627 }