summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/coroutine/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/coroutine/test
parentInitial commit. (diff)
downloadceph-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.v233
-rw-r--r--src/boost/libs/coroutine/test/test_asymmetric_coroutine.cpp627
-rw-r--r--src/boost/libs/coroutine/test/test_symmetric_coroutine.cpp604
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;
+}