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)
7 #include <boost/coroutine/asymmetric_coroutine.hpp>
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>
28 namespace coro = boost::coroutines;
31 std::string value2 = "";
40 struct X : private boost::noncopyable
59 void operator()( coro::asymmetric_coroutine< int >::push_type &)
66 BOOST_MOVABLE_BUT_NOT_COPYABLE( moveable)
79 moveable( BOOST_RV_REF( moveable) other) :
81 { std::swap( state, other.state); }
83 moveable & operator=( BOOST_RV_REF( moveable) other)
85 if ( this == & other) return * this;
86 moveable tmp( boost::move( other) );
87 std::swap( state, tmp.state);
91 void operator()( coro::asymmetric_coroutine< int >::push_type &)
95 struct my_exception {};
97 void f1( coro::asymmetric_coroutine< void >::push_type & c)
103 void f2( coro::asymmetric_coroutine< void >::push_type &)
106 void f3( coro::asymmetric_coroutine< void >::push_type & c)
113 void f4( coro::asymmetric_coroutine< int >::push_type & c)
119 void f5( coro::asymmetric_coroutine< std::string >::push_type & c)
121 std::string res("abc");
127 void f6( coro::asymmetric_coroutine< int >::pull_type & c)
128 { value1 = c.get(); }
130 void f7( coro::asymmetric_coroutine< std::string >::pull_type & c)
131 { value2 = c.get(); }
133 void f8( coro::asymmetric_coroutine< boost::tuple< double, double > >::pull_type & c)
136 boost::tie( x, y) = c.get();
139 boost::tie( x, y) = c.get();
143 void f9( coro::asymmetric_coroutine< int * >::pull_type & c)
144 { value5 = c.get(); }
146 void f91( coro::asymmetric_coroutine< int const* >::pull_type & c)
147 { value5 = const_cast< int * >( c.get() ); }
149 void f10( coro::asymmetric_coroutine< int & >::pull_type & c)
151 int const& i = c.get();
152 value5 = const_cast< int * >( & i);
155 void f101( coro::asymmetric_coroutine< int const& >::pull_type & c)
157 int const& i = c.get();
158 value5 = const_cast< int * >( & i);
161 void f11( coro::asymmetric_coroutine< boost::tuple< int, int > >::pull_type & c)
163 boost::tie( value8, value9) = c.get();
166 void f12( coro::asymmetric_coroutine< void >::pull_type & c)
173 template< typename E >
174 void f14( coro::asymmetric_coroutine< void >::pull_type &, E const& e)
177 void f16( coro::asymmetric_coroutine< int >::push_type & c)
186 void f17( coro::asymmetric_coroutine< int >::pull_type & c, std::vector< int > & vec)
196 void f19( coro::asymmetric_coroutine< int* >::push_type & c, std::vector< int * > & vec)
198 BOOST_FOREACH( int * ptr, vec)
202 void f20( coro::asymmetric_coroutine< int >::push_type &)
205 void f21( coro::asymmetric_coroutine< int >::pull_type & c)
217 coro::asymmetric_coroutine< void >::pull_type coro1;
218 coro::asymmetric_coroutine< void >::pull_type coro2( f1);
219 BOOST_CHECK( ! coro1);
222 coro1 = boost::move( coro2);
225 BOOST_CHECK( ! coro2);
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);
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);
253 coro::asymmetric_coroutine< void >::pull_type coro( f2);
254 BOOST_CHECK( ! coro);
255 BOOST_CHECK_EQUAL( ( int)1, value1);
262 coro::asymmetric_coroutine< void >::pull_type coro( f3);
264 BOOST_CHECK_EQUAL( ( int)1, value1);
266 BOOST_CHECK( ! coro);
267 BOOST_CHECK_EQUAL( ( int)2, value1);
270 void test_result_int()
272 coro::asymmetric_coroutine< int >::pull_type coro( f4);
274 int result = coro.get();
276 BOOST_CHECK_EQUAL( 3, result);
277 result = coro().get();
279 BOOST_CHECK_EQUAL( 7, result);
281 BOOST_CHECK( ! coro);
284 void test_result_string()
286 coro::asymmetric_coroutine< std::string >::pull_type coro( f5);
288 std::string result = coro.get();
290 BOOST_CHECK_EQUAL( std::string("abc"), result);
291 result = coro().get();
293 BOOST_CHECK_EQUAL( std::string("xyz"), result);
295 BOOST_CHECK( ! coro);
302 coro::asymmetric_coroutine< int >::push_type coro( f6);
305 BOOST_CHECK( ! coro);
306 BOOST_CHECK_EQUAL( 3, value1);
309 void test_arg_string()
313 coro::asymmetric_coroutine< std::string >::push_type coro( f7);
315 coro( std::string("abc") );
316 BOOST_CHECK( ! coro);
317 BOOST_CHECK_EQUAL( std::string("abc"), value2);
324 coro::asymmetric_coroutine< boost::tuple< double, double > >::push_type coro( f8);
326 coro( boost::make_tuple( 7.35, 3.14) );
328 BOOST_CHECK_EQUAL( ( double) 10.49, value4);
331 coro( boost::make_tuple( 1.15, 3.14) );
332 BOOST_CHECK( ! coro);
333 BOOST_CHECK_EQUAL( ( double) 4.29, value4);
341 coro::asymmetric_coroutine< int * >::push_type coro( f9);
344 BOOST_CHECK( ! coro);
345 BOOST_CHECK_EQUAL( & a, value5);
348 void test_const_ptr()
353 coro::asymmetric_coroutine< int const* >::push_type coro( f91);
356 BOOST_CHECK( ! coro);
357 BOOST_CHECK_EQUAL( & a, value5);
365 coro::asymmetric_coroutine< int & >::push_type coro( f10);
368 BOOST_CHECK( ! coro);
369 BOOST_CHECK_EQUAL( & a, value5);
372 void test_const_ref()
377 coro::asymmetric_coroutine< int const& >::push_type coro( f101);
380 BOOST_CHECK( ! coro);
381 BOOST_CHECK_EQUAL( & a, value5);
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);
396 BOOST_CHECK( ! coro);
397 BOOST_CHECK_EQUAL( a, value8);
398 BOOST_CHECK_EQUAL( b, value9);
405 coro::asymmetric_coroutine< void >::push_type coro( f12);
407 BOOST_CHECK_EQUAL( ( int) 0, value1);
410 BOOST_CHECK_EQUAL( ( int) 7, value1);
412 BOOST_CHECK_EQUAL( ( int) 7, value1);
414 BOOST_CHECK_EQUAL( ( int) 0, value1);
417 void test_no_unwind()
421 coro::asymmetric_coroutine< void >::push_type coro(
424 coro::stack_allocator::traits_type::default_size(),
425 coro::no_stack_unwind) );
427 BOOST_CHECK_EQUAL( ( int) 0, value1);
430 BOOST_CHECK_EQUAL( ( int) 7, value1);
432 BOOST_CHECK_EQUAL( ( int) 7, value1);
434 BOOST_CHECK_EQUAL( ( int) 7, value1);
437 void test_exceptions()
440 std::runtime_error ex("abc");
443 coro::asymmetric_coroutine< void >::push_type coro( boost::bind( f14< std::runtime_error >, _1, ex) );
446 BOOST_CHECK( ! coro);
449 catch ( std::runtime_error const&)
451 catch ( std::exception const&)
455 BOOST_CHECK( thrown);
458 void test_input_iterator()
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] );
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);
477 coro::asymmetric_coroutine< int >::pull_type::iterator i = boost::begin( coro);
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] );
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);
497 coro::asymmetric_coroutine< int* >::pull_type::iterator i = boost::begin( coro);
501 vec_out.push_back( p);
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] );
510 void test_output_iterator()
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) );
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] );
529 void test_invalid_result()
531 bool catched = false;
532 coro::asymmetric_coroutine< int >::pull_type coro( f20);
533 BOOST_CHECK( ! coro);
539 catch ( coro::invalid_result const&)
543 BOOST_CHECK( catched);
545 void test_move_coro()
549 coro::asymmetric_coroutine< int >::push_type coro1( f21);
550 coro::asymmetric_coroutine< int >::push_type coro2;
552 BOOST_CHECK( ! coro2);
555 BOOST_CHECK_EQUAL( ( int)1, value1);
557 coro2 = boost::move( coro1);
558 BOOST_CHECK( ! coro1);
562 BOOST_CHECK_EQUAL( ( int)2, value1);
564 coro1 = boost::move( coro2);
566 BOOST_CHECK( ! coro2);
569 BOOST_CHECK_EQUAL( ( int)3, value1);
571 coro2 = boost::move( coro1);
572 BOOST_CHECK( ! coro1);
576 BOOST_CHECK_EQUAL( ( int)4, value1);
579 void foo( coro::asymmetric_coroutine< int >::push_type & yield)
584 coro::asymmetric_coroutine< int >::pull_type make_range()
586 return coro::asymmetric_coroutine< int >::pull_type( foo);
589 template< typename Range >
590 void const_func( Range const& r)
597 const_func( make_range() );
600 boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
602 boost::unit_test::test_suite * test =
603 BOOST_TEST_SUITE("Boost.coroutine: asymmetric coroutine test suite");
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) );