123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627 |
- // Copyright Oliver Kowalke 2009.
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #include <boost/coroutine/asymmetric_coroutine.hpp>
- #include <algorithm>
- #include <iostream>
- #include <sstream>
- #include <stdexcept>
- #include <string>
- #include <vector>
- #include <cstdio>
- #include <boost/assert.hpp>
- #include <boost/bind.hpp>
- #include <boost/foreach.hpp>
- #include <boost/move/move.hpp>
- #include <boost/range.hpp>
- #include <boost/ref.hpp>
- #include <boost/test/unit_test.hpp>
- #include <boost/tuple/tuple.hpp>
- #include <boost/utility.hpp>
- namespace coro = boost::coroutines;
- int value1 = 0;
- std::string value2 = "";
- bool value3 = false;
- double value4 = .0;
- int * value5 = 0;
- int& value6 = value1;
- int& value7 = value1;
- int value8 = 0;
- int value9 = 0;
- struct X : private boost::noncopyable
- {
- X() { value1 = 7; }
- ~X() { value1 = 0; }
- };
- class copyable
- {
- public:
- bool state;
- copyable() :
- state( false)
- {}
- copyable( int) :
- state( true)
- {}
- void operator()( coro::asymmetric_coroutine< int >::push_type &)
- { value3 = state; }
- };
- class moveable
- {
- private:
- BOOST_MOVABLE_BUT_NOT_COPYABLE( moveable)
- public:
- bool state;
- moveable() :
- state( false)
- {}
- moveable( int) :
- state( true)
- {}
- moveable( BOOST_RV_REF( moveable) other) :
- state( false)
- { std::swap( state, other.state); }
- moveable & operator=( BOOST_RV_REF( moveable) other)
- {
- if ( this == & other) return * this;
- moveable tmp( boost::move( other) );
- std::swap( state, tmp.state);
- return * this;
- }
- void operator()( coro::asymmetric_coroutine< int >::push_type &)
- { value3 = state; }
- };
- struct my_exception {};
- void f1( coro::asymmetric_coroutine< void >::push_type & c)
- {
- while ( c)
- c();
- }
- void f2( coro::asymmetric_coroutine< void >::push_type &)
- { ++value1; }
- void f3( coro::asymmetric_coroutine< void >::push_type & c)
- {
- ++value1;
- c();
- ++value1;
- }
- void f4( coro::asymmetric_coroutine< int >::push_type & c)
- {
- c( 3);
- c( 7);
- }
- void f5( coro::asymmetric_coroutine< std::string >::push_type & c)
- {
- std::string res("abc");
- c( res);
- res = "xyz";
- c( res);
- }
- void f6( coro::asymmetric_coroutine< int >::pull_type & c)
- { value1 = c.get(); }
- void f7( coro::asymmetric_coroutine< std::string >::pull_type & c)
- { value2 = c.get(); }
- void f8( coro::asymmetric_coroutine< boost::tuple< double, double > >::pull_type & c)
- {
- double x = 0, y = 0;
- boost::tie( x, y) = c.get();
- value4 = x + y;
- c();
- boost::tie( x, y) = c.get();
- value4 = x + y;
- }
- void f9( coro::asymmetric_coroutine< int * >::pull_type & c)
- { value5 = c.get(); }
- void f91( coro::asymmetric_coroutine< int const* >::pull_type & c)
- { value5 = const_cast< int * >( c.get() ); }
- void f10( coro::asymmetric_coroutine< int & >::pull_type & c)
- {
- int const& i = c.get();
- value5 = const_cast< int * >( & i);
- }
- void f101( coro::asymmetric_coroutine< int const& >::pull_type & c)
- {
- int const& i = c.get();
- value5 = const_cast< int * >( & i);
- }
- void f11( coro::asymmetric_coroutine< boost::tuple< int, int > >::pull_type & c)
- {
- boost::tie( value8, value9) = c.get();
- }
- void f12( coro::asymmetric_coroutine< void >::pull_type & c)
- {
- X x_;
- c();
- c();
- }
- template< typename E >
- void f14( coro::asymmetric_coroutine< void >::pull_type &, E const& e)
- { throw e; }
- void f16( coro::asymmetric_coroutine< int >::push_type & c)
- {
- c( 1);
- c( 2);
- c( 3);
- c( 4);
- c( 5);
- }
- void f17( coro::asymmetric_coroutine< int >::pull_type & c, std::vector< int > & vec)
- {
- int x = c.get();
- while ( 5 > x)
- {
- vec.push_back( x);
- x = c().get();
- }
- }
- void f19( coro::asymmetric_coroutine< int* >::push_type & c, std::vector< int * > & vec)
- {
- BOOST_FOREACH( int * ptr, vec)
- { c( ptr); }
- }
- void f20( coro::asymmetric_coroutine< int >::push_type &)
- {}
- void f21( coro::asymmetric_coroutine< int >::pull_type & c)
- {
- while ( c)
- {
- value1 = c.get();
- c();
- }
- }
- void test_move()
- {
- {
- coro::asymmetric_coroutine< void >::pull_type coro1;
- coro::asymmetric_coroutine< void >::pull_type coro2( f1);
- BOOST_CHECK( ! coro1);
- BOOST_CHECK( coro2);
- coro2();
- coro1 = boost::move( coro2);
- BOOST_CHECK( coro1);
- coro1();
- BOOST_CHECK( ! coro2);
- }
- {
- value3 = false;
- copyable cp( 3);
- BOOST_CHECK( cp.state);
- BOOST_CHECK( ! value3);
- coro::asymmetric_coroutine< int >::pull_type coro( cp);
- BOOST_CHECK( cp.state);
- BOOST_CHECK( value3);
- }
- {
- value3 = false;
- moveable mv( 7);
- BOOST_CHECK( mv.state);
- BOOST_CHECK( ! value3);
- coro::asymmetric_coroutine< int >::pull_type coro( boost::move( mv) );
- BOOST_CHECK( ! mv.state);
- BOOST_CHECK( value3);
- }
- }
- void test_complete()
- {
- value1 = 0;
- coro::asymmetric_coroutine< void >::pull_type coro( f2);
- BOOST_CHECK( ! coro);
- BOOST_CHECK_EQUAL( ( int)1, value1);
- }
- void test_jump()
- {
- value1 = 0;
- coro::asymmetric_coroutine< void >::pull_type coro( f3);
- BOOST_CHECK( coro);
- BOOST_CHECK_EQUAL( ( int)1, value1);
- coro();
- BOOST_CHECK( ! coro);
- BOOST_CHECK_EQUAL( ( int)2, value1);
- }
- void test_result_int()
- {
- coro::asymmetric_coroutine< int >::pull_type coro( f4);
- BOOST_CHECK( coro);
- int result = coro.get();
- BOOST_CHECK( coro);
- BOOST_CHECK_EQUAL( 3, result);
- result = coro().get();
- BOOST_CHECK( coro);
- BOOST_CHECK_EQUAL( 7, result);
- coro();
- BOOST_CHECK( ! coro);
- }
- void test_result_string()
- {
- coro::asymmetric_coroutine< std::string >::pull_type coro( f5);
- BOOST_CHECK( coro);
- std::string result = coro.get();
- BOOST_CHECK( coro);
- BOOST_CHECK_EQUAL( std::string("abc"), result);
- result = coro().get();
- BOOST_CHECK( coro);
- BOOST_CHECK_EQUAL( std::string("xyz"), result);
- coro();
- BOOST_CHECK( ! coro);
- }
- void test_arg_int()
- {
- value1 = 0;
- coro::asymmetric_coroutine< int >::push_type coro( f6);
- BOOST_CHECK( coro);
- coro( 3);
- BOOST_CHECK( ! coro);
- BOOST_CHECK_EQUAL( 3, value1);
- }
- void test_arg_string()
- {
- value2 = "";
- coro::asymmetric_coroutine< std::string >::push_type coro( f7);
- BOOST_CHECK( coro);
- coro( std::string("abc") );
- BOOST_CHECK( ! coro);
- BOOST_CHECK_EQUAL( std::string("abc"), value2);
- }
- void test_fp()
- {
- value4 = 0;
- coro::asymmetric_coroutine< boost::tuple< double, double > >::push_type coro( f8);
- BOOST_CHECK( coro);
- coro( boost::make_tuple( 7.35, 3.14) );
- BOOST_CHECK( coro);
- BOOST_CHECK_EQUAL( ( double) 10.49, value4);
- value4 = 0;
- coro( boost::make_tuple( 1.15, 3.14) );
- BOOST_CHECK( ! coro);
- BOOST_CHECK_EQUAL( ( double) 4.29, value4);
- }
- void test_ptr()
- {
- value5 = 0;
- int a = 3;
- coro::asymmetric_coroutine< int * >::push_type coro( f9);
- BOOST_CHECK( coro);
- coro( & a);
- BOOST_CHECK( ! coro);
- BOOST_CHECK_EQUAL( & a, value5);
- }
- void test_const_ptr()
- {
- value5 = 0;
- int a = 3;
- coro::asymmetric_coroutine< int const* >::push_type coro( f91);
- BOOST_CHECK( coro);
- coro( & a);
- BOOST_CHECK( ! coro);
- BOOST_CHECK_EQUAL( & a, value5);
- }
- void test_ref()
- {
- value5 = 0;
- int a = 3;
- coro::asymmetric_coroutine< int & >::push_type coro( f10);
- BOOST_CHECK( coro);
- coro( a);
- BOOST_CHECK( ! coro);
- BOOST_CHECK_EQUAL( & a, value5);
- }
- void test_const_ref()
- {
- value5 = 0;
- int a = 3;
- coro::asymmetric_coroutine< int const& >::push_type coro( f101);
- BOOST_CHECK( coro);
- coro( a);
- BOOST_CHECK( ! coro);
- BOOST_CHECK_EQUAL( & a, value5);
- }
- void test_tuple()
- {
- value8 = 0;
- value9 = 0;
- int a = 3, b = 7;
- boost::tuple< int, int > tpl( a, b);
- BOOST_CHECK_EQUAL( a, tpl.get< 0 >() );
- BOOST_CHECK_EQUAL( b, tpl.get< 1 >() );
- coro::asymmetric_coroutine< boost::tuple< int, int > >::push_type coro( f11);
- BOOST_CHECK( coro);
- coro( tpl);
- BOOST_CHECK( ! coro);
- BOOST_CHECK_EQUAL( a, value8);
- BOOST_CHECK_EQUAL( b, value9);
- }
- void test_unwind()
- {
- value1 = 0;
- {
- coro::asymmetric_coroutine< void >::push_type coro( f12);
- BOOST_CHECK( coro);
- BOOST_CHECK_EQUAL( ( int) 0, value1);
- coro();
- BOOST_CHECK( coro);
- BOOST_CHECK_EQUAL( ( int) 7, value1);
- coro();
- BOOST_CHECK_EQUAL( ( int) 7, value1);
- }
- BOOST_CHECK_EQUAL( ( int) 0, value1);
- }
- void test_no_unwind()
- {
- value1 = 0;
- {
- coro::asymmetric_coroutine< void >::push_type coro(
- f12,
- coro::attributes(
- coro::stack_allocator::traits_type::default_size(),
- coro::no_stack_unwind) );
- BOOST_CHECK( coro);
- BOOST_CHECK_EQUAL( ( int) 0, value1);
- coro();
- BOOST_CHECK( coro);
- BOOST_CHECK_EQUAL( ( int) 7, value1);
- coro();
- BOOST_CHECK_EQUAL( ( int) 7, value1);
- }
- BOOST_CHECK_EQUAL( ( int) 7, value1);
- }
- void test_exceptions()
- {
- bool thrown = false;
- std::runtime_error ex("abc");
- try
- {
- coro::asymmetric_coroutine< void >::push_type coro( boost::bind( f14< std::runtime_error >, _1, ex) );
- BOOST_CHECK( coro);
- coro();
- BOOST_CHECK( ! coro);
- BOOST_CHECK( false);
- }
- catch ( std::runtime_error const&)
- { thrown = true; }
- catch ( std::exception const&)
- {}
- catch (...)
- {}
- BOOST_CHECK( thrown);
- }
- void test_input_iterator()
- {
- {
- std::vector< int > vec;
- coro::asymmetric_coroutine< int >::pull_type coro( f16);
- BOOST_FOREACH( int i, coro)
- { vec.push_back( i); }
- BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
- BOOST_CHECK_EQUAL( ( int)1, vec[0] );
- BOOST_CHECK_EQUAL( ( int)2, vec[1] );
- BOOST_CHECK_EQUAL( ( int)3, vec[2] );
- BOOST_CHECK_EQUAL( ( int)4, vec[3] );
- BOOST_CHECK_EQUAL( ( int)5, vec[4] );
- }
- {
- std::vector< int > vec;
- coro::asymmetric_coroutine< int >::pull_type coro( f16);
- coro::asymmetric_coroutine< int >::pull_type::iterator e = boost::end( coro);
- for (
- coro::asymmetric_coroutine< int >::pull_type::iterator i = boost::begin( coro);
- i != e; ++i)
- { vec.push_back( * i); }
- BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
- BOOST_CHECK_EQUAL( ( int)1, vec[0] );
- BOOST_CHECK_EQUAL( ( int)2, vec[1] );
- BOOST_CHECK_EQUAL( ( int)3, vec[2] );
- BOOST_CHECK_EQUAL( ( int)4, vec[3] );
- BOOST_CHECK_EQUAL( ( int)5, vec[4] );
- }
- {
- int i1 = 1, i2 = 2, i3 = 3;
- std::vector< int* > vec_in;
- vec_in.push_back( & i1);
- vec_in.push_back( & i2);
- vec_in.push_back( & i3);
- std::vector< int* > vec_out;
- coro::asymmetric_coroutine< int* >::pull_type coro( boost::bind( f19, _1, boost::ref( vec_in) ) );
- coro::asymmetric_coroutine< int* >::pull_type::iterator e = boost::end( coro);
- for (
- coro::asymmetric_coroutine< int* >::pull_type::iterator i = boost::begin( coro);
- i != e; ++i)
- {
- int * p = * i;
- vec_out.push_back( p);
- }
- BOOST_CHECK_EQUAL( ( std::size_t)3, vec_out.size() );
- BOOST_CHECK_EQUAL( & i1, vec_out[0] );
- BOOST_CHECK_EQUAL( & i2, vec_out[1] );
- BOOST_CHECK_EQUAL( & i3, vec_out[2] );
- }
- }
- void test_output_iterator()
- {
- int counter = 0;
- std::vector< int > vec;
- coro::asymmetric_coroutine< int >::push_type coro(
- boost::bind( f17, _1, boost::ref( vec) ) );
- coro::asymmetric_coroutine< int >::push_type::iterator e( boost::end( coro) );
- for ( coro::asymmetric_coroutine< int >::push_type::iterator i( boost::begin( coro) );
- i != e; ++i)
- {
- i = ++counter;
- }
- BOOST_CHECK_EQUAL( ( std::size_t)4, vec.size() );
- BOOST_CHECK_EQUAL( ( int)1, vec[0] );
- BOOST_CHECK_EQUAL( ( int)2, vec[1] );
- BOOST_CHECK_EQUAL( ( int)3, vec[2] );
- BOOST_CHECK_EQUAL( ( int)4, vec[3] );
- }
- void test_invalid_result()
- {
- bool catched = false;
- coro::asymmetric_coroutine< int >::pull_type coro( f20);
- BOOST_CHECK( ! coro);
- try
- {
- int i = coro.get();
- (void)i;
- }
- catch ( coro::invalid_result const&)
- {
- catched = true;
- }
- BOOST_CHECK( catched);
- }
- void test_move_coro()
- {
- value1 = 0;
- coro::asymmetric_coroutine< int >::push_type coro1( f21);
- coro::asymmetric_coroutine< int >::push_type coro2;
- BOOST_CHECK( coro1);
- BOOST_CHECK( ! coro2);
- coro1( 1);
- BOOST_CHECK_EQUAL( ( int)1, value1);
- coro2 = boost::move( coro1);
- BOOST_CHECK( ! coro1);
- BOOST_CHECK( coro2);
- coro2( 2);
- BOOST_CHECK_EQUAL( ( int)2, value1);
- coro1 = boost::move( coro2);
- BOOST_CHECK( coro1);
- BOOST_CHECK( ! coro2);
- coro1( 3);
- BOOST_CHECK_EQUAL( ( int)3, value1);
- coro2 = boost::move( coro1);
- BOOST_CHECK( ! coro1);
- BOOST_CHECK( coro2);
- coro2( 4);
- BOOST_CHECK_EQUAL( ( int)4, value1);
- }
- void foo( coro::asymmetric_coroutine< int >::push_type & yield)
- {
- yield( 1);
- }
- coro::asymmetric_coroutine< int >::pull_type make_range()
- {
- return coro::asymmetric_coroutine< int >::pull_type( foo);
- }
- template< typename Range >
- void const_func( Range const& r)
- {
- begin( r);
- }
- void test_range()
- {
- const_func( make_range() );
- }
- boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
- {
- boost::unit_test::test_suite * test =
- BOOST_TEST_SUITE("Boost.coroutine: asymmetric coroutine test suite");
- test->add( BOOST_TEST_CASE( & test_move) );
- test->add( BOOST_TEST_CASE( & test_complete) );
- test->add( BOOST_TEST_CASE( & test_jump) );
- test->add( BOOST_TEST_CASE( & test_result_int) );
- test->add( BOOST_TEST_CASE( & test_result_string) );
- test->add( BOOST_TEST_CASE( & test_arg_int) );
- test->add( BOOST_TEST_CASE( & test_arg_string) );
- test->add( BOOST_TEST_CASE( & test_fp) );
- test->add( BOOST_TEST_CASE( & test_ptr) );
- test->add( BOOST_TEST_CASE( & test_const_ptr) );
- test->add( BOOST_TEST_CASE( & test_invalid_result) );
- test->add( BOOST_TEST_CASE( & test_ref) );
- test->add( BOOST_TEST_CASE( & test_const_ref) );
- test->add( BOOST_TEST_CASE( & test_tuple) );
- test->add( BOOST_TEST_CASE( & test_unwind) );
- test->add( BOOST_TEST_CASE( & test_no_unwind) );
- test->add( BOOST_TEST_CASE( & test_exceptions) );
- test->add( BOOST_TEST_CASE( & test_input_iterator) );
- test->add( BOOST_TEST_CASE( & test_output_iterator) );
- test->add( BOOST_TEST_CASE( & test_range) );
- return test;
- }
|