diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/coroutine/test | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/coroutine/test')
-rw-r--r-- | src/boost/libs/coroutine/test/Jamfile.v2 | 33 | ||||
-rw-r--r-- | src/boost/libs/coroutine/test/test_asymmetric_coroutine.cpp | 627 | ||||
-rw-r--r-- | src/boost/libs/coroutine/test/test_symmetric_coroutine.cpp | 604 |
3 files changed, 1264 insertions, 0 deletions
diff --git a/src/boost/libs/coroutine/test/Jamfile.v2 b/src/boost/libs/coroutine/test/Jamfile.v2 new file mode 100644 index 000000000..3481e0f7e --- /dev/null +++ b/src/boost/libs/coroutine/test/Jamfile.v2 @@ -0,0 +1,33 @@ +# Boost.Coroutine Library Tests Jamfile + +# 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) + +import common ; +import feature ; +import indirect ; +import modules ; +import os ; +import testing ; +import toolset ; + +project boost/coroutine/test + : requirements + <library>/boost/context//boost_context + <library>/boost/coroutine//boost_coroutine + <library>/boost/program_options//boost_program_options + <library>/boost/test///boost_unit_test_framework + <toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack + <toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS + <toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack + <toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS + <link>static + <threading>multi + ; + +test-suite "coroutine" : + [ run test_asymmetric_coroutine.cpp ] + [ run test_symmetric_coroutine.cpp ] + ; diff --git a/src/boost/libs/coroutine/test/test_asymmetric_coroutine.cpp b/src/boost/libs/coroutine/test/test_asymmetric_coroutine.cpp new file mode 100644 index 000000000..124271a17 --- /dev/null +++ b/src/boost/libs/coroutine/test/test_asymmetric_coroutine.cpp @@ -0,0 +1,627 @@ + +// 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; +} diff --git a/src/boost/libs/coroutine/test/test_symmetric_coroutine.cpp b/src/boost/libs/coroutine/test/test_symmetric_coroutine.cpp new file mode 100644 index 000000000..55015ceec --- /dev/null +++ b/src/boost/libs/coroutine/test/test_symmetric_coroutine.cpp @@ -0,0 +1,604 @@ + +// 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/symmetric_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/lexical_cast.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; + +bool value1 = false; +int value2 = 0; +std::string value3; + +typedef void( * coro_fn_void)(coro::symmetric_coroutine< void* >::yield_type &); + +coro::symmetric_coroutine< void >::call_type * term_coro = 0; + +struct X +{ + int i; + + X() : + i( 0) + {} + + X( int i_) : + i( i_) + {} +}; + +X * p = 0; + +struct Y +{ + Y() + { value2 = 7; } + + ~Y() + { value2 = 0; } +}; + +template< typename X, typename I > +void trampoline( coro::symmetric_coroutine< void* >::yield_type & yield) +{ + void * vp = yield.get(); + X * x = static_cast< X * >( vp); + I i( yield); + x->d = & i; + i.suspend(); + i.run(); +} + +struct B +{ + virtual ~B() {} + + virtual void foo() = 0; +}; + +class D : public B +{ +public: + int count; + coro::symmetric_coroutine< void* >::call_type call; + coro::symmetric_coroutine< void* >::yield_type * yield; + + D( coro::symmetric_coroutine< void* >::yield_type & yield_) : + B(), + count( 0), + call(), + yield( & yield_) + {} + + void foo() {} + + void resume() + { call( 0); } + + void suspend() + { ( *yield)(); } + + void run() + { + while ( yield && * yield) + { + ++count; + suspend(); + } + } +}; + +struct T +{ + D * d; + + T() : + d( 0) + {} +}; + +class copyable +{ +public: + bool state; + + copyable() : + state( false) + {} + + copyable( int) : + state( true) + {} + + void operator()( coro::symmetric_coroutine< bool >::yield_type & yield) + { + if ( yield) + value1 = yield.get(); + } +}; + +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::symmetric_coroutine< int >::yield_type &) + { value1 = state; } +}; + +void empty( coro::symmetric_coroutine< void >::yield_type &) {} + +void f2( coro::symmetric_coroutine< void >::yield_type &) +{ ++value2; } + +void f3( coro::symmetric_coroutine< X >::yield_type & yield) +{ value2 = yield.get().i; } + +void f4( coro::symmetric_coroutine< X& >::yield_type & yield) +{ + X & x = yield.get(); + p = & x; +} + +void f5( coro::symmetric_coroutine< X* >::yield_type & yield) +{ p = yield.get(); } + +void f6( coro::symmetric_coroutine< void >::yield_type & yield) +{ + Y y; + yield( *term_coro); +} + +void f7( coro::symmetric_coroutine< int >::yield_type & yield) +{ + value2 = yield.get(); + yield( *term_coro); + value2 = yield.get(); +} + +template< typename E > +void f9( coro::symmetric_coroutine< void >::yield_type &, E const& e) +{ throw e; } + +void f10( coro::symmetric_coroutine< int >::yield_type & yield, + coro::symmetric_coroutine< int >::call_type & other) +{ + int i = yield.get(); + yield( other, i); + value2 = yield.get(); +} + +void f101( coro::symmetric_coroutine< int >::yield_type & yield) +{ value2 = yield.get(); } + +void f11( coro::symmetric_coroutine< void >::yield_type & yield, + coro::symmetric_coroutine< void >::call_type & other) +{ + yield( other); + value2 = 7; +} + +void f111( coro::symmetric_coroutine< void >::yield_type &) +{ value2 = 3; } + +void f12( coro::symmetric_coroutine< X& >::yield_type & yield, + coro::symmetric_coroutine< X& >::call_type & other) +{ + yield( other, yield.get()); + p = & yield.get(); +} + +void f121( coro::symmetric_coroutine< X& >::yield_type & yield) +{ p = & yield.get(); } + +void f14( coro::symmetric_coroutine< int >::yield_type & yield, + coro::symmetric_coroutine< std::string >::call_type & other) +{ + std::string str( boost::lexical_cast< std::string >( yield.get() ) ); + yield( other, str); + value2 = yield.get(); +} + +void f141( coro::symmetric_coroutine< std::string >::yield_type & yield) +{ value3 = yield.get(); } + +void f15( coro::symmetric_coroutine< int >::yield_type & yield, + int offset, + coro::symmetric_coroutine< int >::call_type & other) +{ + int x = yield.get(); + value2 += x + offset; + yield( other, x); + x = yield.get(); + value2 += x + offset; + yield( other, x); +} + +void f151( coro::symmetric_coroutine< int >::yield_type & yield, + int offset) +{ + int x = yield.get(); + value2 += x + offset; + yield(); + x = yield.get(); + value2 += x + offset; +} + +void f16( coro::symmetric_coroutine< int >::yield_type & yield) +{ + while ( yield) + { + value2 = yield.get(); + yield(); + } +} + +void test_move() +{ + { + coro::symmetric_coroutine< void >::call_type coro1; + coro::symmetric_coroutine< void >::call_type coro2( empty); + BOOST_CHECK( ! coro1); + BOOST_CHECK( coro2); + coro1 = boost::move( coro2); + BOOST_CHECK( coro1); + BOOST_CHECK( ! coro2); + } + + { + value1 = false; + copyable cp( 3); + BOOST_CHECK( cp.state); + BOOST_CHECK( ! value1); + coro::symmetric_coroutine< bool >::call_type coro( cp); + coro( true); + BOOST_CHECK( cp.state); + BOOST_CHECK( value1); + } + + { + value1 = false; + moveable mv( 7); + BOOST_CHECK( mv.state); + BOOST_CHECK( ! value1); + coro::symmetric_coroutine< int >::call_type coro( boost::move( mv) ); + coro( 7); + BOOST_CHECK( ! mv.state); + BOOST_CHECK( value1); + } +} + +void test_complete() +{ + value2 = 0; + + coro::symmetric_coroutine< void >::call_type coro( f2); + BOOST_CHECK( coro); + coro(); + BOOST_CHECK( ! coro); + BOOST_CHECK_EQUAL( ( int)1, value2); +} + +void test_yield() +{ + value2 = 0; + + coro::symmetric_coroutine< int >::call_type coro3( + boost::bind( f151, _1, 3) ); + BOOST_CHECK( coro3); + coro::symmetric_coroutine< int >::call_type coro2( + boost::bind( f15, _1, 2, boost::ref( coro3) ) ); + BOOST_CHECK( coro2); + coro::symmetric_coroutine< int >::call_type coro1( + boost::bind( f15, _1, 1, boost::ref( coro2) ) ); + BOOST_CHECK( coro1); + + BOOST_CHECK_EQUAL( ( int)0, value2); + coro1( 1); + BOOST_CHECK( coro3); + BOOST_CHECK( coro2); + BOOST_CHECK( coro1); + BOOST_CHECK_EQUAL( ( int)9, value2); + coro1( 2); + BOOST_CHECK( ! coro3); + BOOST_CHECK( coro2); + BOOST_CHECK( coro1); + BOOST_CHECK_EQUAL( ( int)21, value2); +} + +void test_pass_value() +{ + value2 = 0; + + X x(7); + BOOST_CHECK_EQUAL( ( int)7, x.i); + BOOST_CHECK_EQUAL( 0, value2); + coro::symmetric_coroutine< X >::call_type coro( f3); + BOOST_CHECK( coro); + coro(7); + BOOST_CHECK( ! coro); + BOOST_CHECK_EQUAL( ( int)7, x.i); + BOOST_CHECK_EQUAL( 7, value2); +} + +void test_pass_reference() +{ + p = 0; + + X x; + coro::symmetric_coroutine< X& >::call_type coro( f4); + BOOST_CHECK( coro); + coro( x); + BOOST_CHECK( ! coro); + BOOST_CHECK( p == & x); +} + +void test_pass_pointer() +{ + p = 0; + + X x; + coro::symmetric_coroutine< X* >::call_type coro( f5); + BOOST_CHECK( coro); + coro( & x); + BOOST_CHECK( ! coro); + BOOST_CHECK( p == & x); +} + +void test_unwind() +{ + value2 = 0; + { + coro::symmetric_coroutine< void >::call_type coro( f6); + coro::symmetric_coroutine< void >::call_type coro_e( empty); + BOOST_CHECK( coro); + BOOST_CHECK( coro_e); + term_coro = & coro_e; + BOOST_CHECK_EQUAL( ( int) 0, value2); + coro(); + BOOST_CHECK( coro); + BOOST_CHECK_EQUAL( ( int) 7, value2); + } + BOOST_CHECK_EQUAL( ( int) 0, value2); +} + +void test_no_unwind() +{ + value2 = 0; + { + coro::symmetric_coroutine< void >::call_type coro( f6, + coro::attributes( + coro::stack_allocator::traits_type::default_size(), + coro::no_stack_unwind) ); + coro::symmetric_coroutine< void >::call_type coro_e( empty); + BOOST_CHECK( coro); + BOOST_CHECK( coro_e); + term_coro = & coro_e; + BOOST_CHECK_EQUAL( ( int) 0, value2); + coro(); + BOOST_CHECK( coro); + BOOST_CHECK_EQUAL( ( int) 7, value2); + } + BOOST_CHECK_EQUAL( ( int) 7, value2); +} + +void test_termination() +{ + value2 = 0; + + coro::symmetric_coroutine< int >::call_type coro( f7); + coro::symmetric_coroutine< void >::call_type coro_e( empty); + BOOST_CHECK( coro); + BOOST_CHECK( coro_e); + term_coro = & coro_e; + BOOST_CHECK_EQUAL( ( int) 0, value2); + coro(3); + BOOST_CHECK( coro); + BOOST_CHECK_EQUAL( ( int) 3, value2); + coro(7); + BOOST_CHECK( ! coro); + BOOST_CHECK_EQUAL( ( int) 7, value2); +} + +void test_yield_to_void() +{ + value2 = 0; + + coro::symmetric_coroutine< void >::call_type coro_other( f111); + coro::symmetric_coroutine< void >::call_type coro( boost::bind( f11, _1, boost::ref( coro_other) ) ); + BOOST_CHECK( coro_other); + BOOST_CHECK( coro); + BOOST_CHECK_EQUAL( ( int) 0, value2); + coro(); + BOOST_CHECK( ! coro_other); + BOOST_CHECK( coro); + BOOST_CHECK_EQUAL( ( int) 3, value2); + coro(); + BOOST_CHECK( ! coro_other); + BOOST_CHECK( ! coro); + BOOST_CHECK_EQUAL( ( int) 7, value2); +} + +void test_yield_to_int() +{ + value2 = 0; + + coro::symmetric_coroutine< int >::call_type coro_other( f101); + coro::symmetric_coroutine< int >::call_type coro( boost::bind( f10, _1, boost::ref( coro_other) ) ); + BOOST_CHECK( coro_other); + BOOST_CHECK( coro); + BOOST_CHECK_EQUAL( ( int) 0, value2); + coro(3); + BOOST_CHECK( ! coro_other); + BOOST_CHECK( coro); + BOOST_CHECK_EQUAL( ( int) 3, value2); + coro(7); + BOOST_CHECK( ! coro_other); + BOOST_CHECK( ! coro); + BOOST_CHECK_EQUAL( ( int) 7, value2); +} + +void test_yield_to_ref() +{ + p = 0; + + coro::symmetric_coroutine< X& >::call_type coro_other( f121); + coro::symmetric_coroutine< X& >::call_type coro( boost::bind( f12, _1, boost::ref( coro_other) ) ); + BOOST_CHECK( coro_other); + BOOST_CHECK( coro); + BOOST_CHECK( 0 == p); + X x1(3); + coro( x1); + BOOST_CHECK( ! coro_other); + BOOST_CHECK( coro); + BOOST_CHECK_EQUAL( p->i, x1.i); + BOOST_CHECK( p == & x1); + X x2(7); + coro(x2); + BOOST_CHECK( ! coro_other); + BOOST_CHECK( ! coro); + BOOST_CHECK_EQUAL( p->i, x2.i); + BOOST_CHECK( p == & x2); +} + +void test_yield_to_different() +{ + value2 = 0; + value3 = ""; + + coro::symmetric_coroutine< std::string >::call_type coro_other( f141); + coro::symmetric_coroutine< int >::call_type coro( boost::bind( f14, _1, boost::ref( coro_other) ) ); + BOOST_CHECK( coro_other); + BOOST_CHECK( coro); + BOOST_CHECK_EQUAL( ( int) 0, value2); + BOOST_CHECK( value3.empty() ); + coro(3); + BOOST_CHECK( ! coro_other); + BOOST_CHECK( coro); + BOOST_CHECK_EQUAL( "3", value3); + coro(7); + BOOST_CHECK( ! coro_other); + BOOST_CHECK( ! coro); + BOOST_CHECK_EQUAL( ( int) 7, value2); +} + +void test_move_coro() +{ + value2 = 0; + + coro::symmetric_coroutine< int >::call_type coro1( f16); + coro::symmetric_coroutine< int >::call_type coro2; + BOOST_CHECK( coro1); + BOOST_CHECK( ! coro2); + + coro1( 1); + BOOST_CHECK_EQUAL( ( int)1, value2); + + coro2 = boost::move( coro1); + BOOST_CHECK( ! coro1); + BOOST_CHECK( coro2); + + coro2( 2); + BOOST_CHECK_EQUAL( ( int)2, value2); + + coro1 = boost::move( coro2); + BOOST_CHECK( coro1); + BOOST_CHECK( ! coro2); + + coro1( 3); + BOOST_CHECK_EQUAL( ( int)3, value2); + + coro2 = boost::move( coro1); + BOOST_CHECK( ! coro1); + BOOST_CHECK( coro2); + + coro2( 4); + BOOST_CHECK_EQUAL( ( int)4, value2); +} + +void test_vptr() +{ + D * d = 0; + T t; + coro_fn_void fn = trampoline< T, D >; + coro::symmetric_coroutine< void* >::call_type call( fn); + call( & t); + d = t.d; + BOOST_CHECK( 0 != d); + d->call = boost::move( call); + + BOOST_CHECK_EQUAL( ( int) 0, d->count); + d->resume(); + BOOST_CHECK_EQUAL( ( int) 1, d->count); + d->resume(); + BOOST_CHECK_EQUAL( ( int) 2, d->count); +} + +boost::unit_test::test_suite * init_unit_test_suite( int, char* []) +{ + boost::unit_test::test_suite * test = + BOOST_TEST_SUITE("Boost.coroutine: symmetric coroutine test suite"); + + test->add( BOOST_TEST_CASE( & test_move) ); + test->add( BOOST_TEST_CASE( & test_complete) ); + test->add( BOOST_TEST_CASE( & test_yield) ); + test->add( BOOST_TEST_CASE( & test_pass_value) ); + test->add( BOOST_TEST_CASE( & test_pass_reference) ); + test->add( BOOST_TEST_CASE( & test_pass_pointer) ); + test->add( BOOST_TEST_CASE( & test_termination) ); + test->add( BOOST_TEST_CASE( & test_unwind) ); + test->add( BOOST_TEST_CASE( & test_no_unwind) ); + test->add( BOOST_TEST_CASE( & test_yield_to_void) ); + test->add( BOOST_TEST_CASE( & test_yield_to_int) ); + test->add( BOOST_TEST_CASE( & test_yield_to_ref) ); + test->add( BOOST_TEST_CASE( & test_yield_to_different) ); + test->add( BOOST_TEST_CASE( & test_move_coro) ); + test->add( BOOST_TEST_CASE( & test_vptr) ); + + return test; +} |