summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/coroutine2/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/coroutine2/test')
-rw-r--r--src/boost/libs/coroutine2/test/Jamfile.v288
-rw-r--r--src/boost/libs/coroutine2/test/test_coroutine.cpp679
2 files changed, 767 insertions, 0 deletions
diff --git a/src/boost/libs/coroutine2/test/Jamfile.v2 b/src/boost/libs/coroutine2/test/Jamfile.v2
new file mode 100644
index 000000000..498a763d4
--- /dev/null
+++ b/src/boost/libs/coroutine2/test/Jamfile.v2
@@ -0,0 +1,88 @@
+
+# Copyright Oliver Kowalke 2014.
+# 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 path ;
+import testing ;
+import toolset ;
+import ../../config/checks/config : requires ;
+
+project boost/coroutine2/test
+ : requirements
+ <library>../../test/build//boost_unit_test_framework
+ <library>/boost/context//boost_context
+ <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
+ <optimization>speed
+ <variant>release
+ ;
+
+rule native-impl ( properties * )
+{
+ local result ;
+ if ( <target-os>darwin in $(properties) || <target-os>android in $(properties) )
+ {
+ result = <build>no ;
+ }
+ else if ( ! ( <target-os>windows in $(properties) ) )
+ {
+ result = <context-impl>ucontext ;
+ }
+ else
+ {
+ result = <context-impl>winfib ;
+ }
+ return $(result) ;
+}
+
+test-suite minimal :
+[ run test_coroutine.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_variadic_templates ]
+ : test_coroutine_asm ]
+
+[ run test_coroutine.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_variadic_templates ]
+ : test_coroutine_native ] ;
+
+test-suite full :
+ minimal ;
+
+test-suite extra ;
+
+explicit minimal ;
+explicit extra ;
diff --git a/src/boost/libs/coroutine2/test/test_coroutine.cpp b/src/boost/libs/coroutine2/test/test_coroutine.cpp
new file mode 100644
index 000000000..0a9da6ac0
--- /dev/null
+++ b/src/boost/libs/coroutine2/test/test_coroutine.cpp
@@ -0,0 +1,679 @@
+
+// Copyright Oliver Kowalke 2014.
+// 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 <algorithm>
+#include <cstdio>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <boost/coroutine2/coroutine.hpp>
+
+namespace coro = boost::coroutines2;
+
+int value1 = 0;
+std::string value2 = "";
+bool value3 = false;
+double value4 = .0;
+int * value5 = nullptr;
+int& value6 = value1;
+int& value7 = value1;
+int value8 = 0;
+int value9 = 0;
+
+struct X
+{
+ X() { value1 = 7; }
+ ~X() { value1 = 0; }
+
+ X( X const&) = delete;
+ X & operator=( X const&) = delete;
+};
+
+class copyable
+{
+public:
+ bool state;
+
+ copyable() :
+ state( false)
+ {}
+
+ copyable( int) :
+ state( true)
+ {}
+
+ void operator()( coro::coroutine< int >::push_type &)
+ { value3 = state; }
+};
+
+class moveable
+{
+public:
+ bool state;
+
+ moveable() :
+ state( false)
+ {}
+
+ moveable( int) :
+ state( true)
+ {}
+
+ moveable( moveable const&) = delete;
+ moveable & operator=( moveable const&) = delete;
+
+ moveable( moveable && other) :
+ state( false)
+ { std::swap( state, other.state); }
+
+ moveable & operator=( moveable && other)
+ {
+ if ( this != & other) {
+ state = other.state;
+ other.state = false;
+ }
+ return * this;
+ }
+
+ void operator()( coro::coroutine< int >::push_type &)
+ { value3 = state; }
+};
+
+class movedata
+{
+public:
+ int i;
+
+ movedata( int i_) :
+ i( i_)
+ {}
+
+ movedata( movedata const&) = delete;
+ movedata & operator=( movedata const&) = delete;
+
+ movedata( movedata && other) :
+ i( 0)
+ { std::swap( i, other.i); }
+
+ movedata & operator=( movedata && other)
+ {
+ if ( this != & other) {
+ i = other.i;
+ other.i = 0;
+ }
+ return * this;
+ }
+};
+
+struct my_exception {};
+
+void f1( coro::coroutine< void >::push_type & c)
+{
+ while ( c)
+ c();
+}
+
+void f2( coro::coroutine< void >::push_type &)
+{ ++value1; }
+
+void f3( coro::coroutine< void >::push_type & c)
+{
+ ++value1;
+ c();
+ ++value1;
+}
+
+void f4( coro::coroutine< int >::push_type & c)
+{
+ c( 3);
+ c( 7);
+}
+
+void f5( coro::coroutine< std::string >::push_type & c)
+{
+ std::string res("abc");
+ c( res);
+ res = "xyz";
+ c( res);
+}
+
+void f6( coro::coroutine< int >::pull_type & c)
+{ value1 = c.get(); }
+
+void f7( coro::coroutine< std::string >::pull_type & c)
+{ value2 = c.get(); }
+
+void f8( coro::coroutine< std::tuple< double, double > >::pull_type & c)
+{
+ double x = 0, y = 0;
+ std::tie( x, y) = c.get();
+ value4 = x + y;
+ c();
+ std::tie( x, y) = c.get();
+ value4 = x + y;
+}
+
+void f9( coro::coroutine< int * >::pull_type & c)
+{ value5 = c.get(); }
+
+void f91( coro::coroutine< int const* >::pull_type & c)
+{ value5 = const_cast< int * >( c.get() ); }
+
+void f10( coro::coroutine< int & >::pull_type & c)
+{
+ int & i = c.get();
+ value5 = const_cast< int * >( & i);
+}
+
+void f101( coro::coroutine< int const& >::pull_type & c)
+{
+ int const& i = c.get();
+ value5 = const_cast< int * >( & i);
+}
+
+void f11( coro::coroutine< std::tuple< int, int > >::pull_type & c)
+{
+ std::tie( value8, value9) = c.get();
+}
+
+void f12( coro::coroutine< void >::pull_type & c)
+{
+ value1 = 7;
+ X x_;
+ c();
+ c();
+}
+
+void f16( coro::coroutine< int >::push_type & c)
+{
+ c( 1);
+ c( 2);
+ c( 3);
+ c( 4);
+ c( 5);
+}
+
+void f17( coro::coroutine< int >::pull_type & c, std::vector< int > & vec)
+{
+ int x = c.get();
+ while ( 5 > x)
+ {
+ vec.push_back( x);
+ x = c().get();
+ }
+}
+
+void f20( coro::coroutine< int >::push_type &)
+{}
+
+void f21( coro::coroutine< int >::pull_type & c)
+{
+ while ( c)
+ {
+ value1 = c.get();
+ c();
+ }
+}
+
+void f22( coro::coroutine< movedata >::pull_type & c)
+{
+ movedata mv( c.get() );
+ value1 = mv.i;
+}
+
+void test_move()
+{
+ {
+ coro::coroutine< int >::pull_type coro1( f20);
+ coro::coroutine< int >::pull_type coro2( f16);
+ BOOST_CHECK( ! coro1);
+ BOOST_CHECK( coro2);
+ BOOST_CHECK_EQUAL( 1, coro2.get() );
+ coro2();
+ BOOST_CHECK_EQUAL( 2, coro2.get() );
+ coro1 = std::move( coro2);
+ BOOST_CHECK( coro1);
+ BOOST_CHECK( ! coro2);
+ coro1();
+ BOOST_CHECK_EQUAL( 3, coro1.get() );
+ BOOST_CHECK( ! coro2);
+ }
+
+ {
+ value3 = false;
+ copyable cp( 3);
+ BOOST_CHECK( cp.state);
+ BOOST_CHECK( ! value3);
+ coro::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::coroutine< int >::pull_type coro( std::move( mv) );
+ BOOST_CHECK( ! mv.state);
+ BOOST_CHECK( value3);
+ }
+
+ {
+ value1 = 0;
+ movedata mv( 7);
+ BOOST_CHECK_EQUAL( 0, value1);
+ BOOST_CHECK_EQUAL( 7, mv.i);
+ coro::coroutine< movedata >::push_type coro( f22);
+ coro( std::move( mv) );
+ BOOST_CHECK_EQUAL( 7, value1);
+ BOOST_CHECK_EQUAL( 0, mv.i);
+ }
+}
+
+void test_complete()
+{
+ value1 = 0;
+
+ coro::coroutine< void >::pull_type coro( f2);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( ( int)1, value1);
+}
+
+void test_bind()
+{
+ value1 = 0;
+
+ coro::coroutine< void >::pull_type coro( std::bind( f2, std::placeholders::_1) );
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( ( int)1, value1);
+}
+
+void test_jump()
+{
+ value1 = 0;
+
+ coro::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::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::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::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::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::coroutine< std::tuple< double, double > >::push_type coro( f8);
+ BOOST_CHECK( coro);
+ coro( std::make_tuple( 7.35, 3.14) );
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( double) 10.49, value4);
+
+ value4 = 0;
+ coro( std::make_tuple( 1.15, 3.14) );
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( ( double) 4.29, value4);
+}
+
+void test_ptr()
+{
+ value5 = nullptr;
+
+ int a = 3;
+ coro::coroutine< int * >::push_type coro( f9);
+ BOOST_CHECK( coro);
+ coro( & a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_const_ptr()
+{
+ value5 = nullptr;
+
+ int a = 3;
+ coro::coroutine< int const* >::push_type coro( f91);
+ BOOST_CHECK( coro);
+ coro( & a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_ref()
+{
+ value5 = nullptr;
+
+ int a_ = 3;
+ int & a = a_;
+ coro::coroutine< int & >::push_type coro( f10);
+ BOOST_CHECK( coro);
+ coro( std::ref( a) );
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_const_ref()
+{
+ value5 = nullptr;
+
+ int a = 3;
+ coro::coroutine< int const& >::push_type coro( f101);
+ BOOST_CHECK( coro);
+ coro( a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_no_result()
+{
+ coro::coroutine< int >::pull_type coro( f20);
+ BOOST_CHECK( ! coro);
+}
+
+void test_tuple()
+{
+ value8 = 0;
+ value9 = 0;
+
+ int a = 3, b = 7;
+ std::tuple< int, int > tpl( a, b);
+ BOOST_CHECK_EQUAL( a, std::get< 0 >( tpl) );
+ BOOST_CHECK_EQUAL( b, std::get< 1 >( tpl) );
+ coro::coroutine< std::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::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);
+ int i = 0;
+ {
+ coro::coroutine< void >::push_type coro(
+ [&i](coro::coroutine< void >::pull_type &) mutable {
+ i = 7;
+ });
+ }
+ {
+ BOOST_CHECK_EQUAL( ( int) 0, value1);
+ auto * coro = new coro::coroutine< void >::pull_type(
+ [](coro::coroutine< void >::push_type & coro) mutable {
+ X x;
+ coro();
+ });
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+ delete coro;
+ BOOST_CHECK_EQUAL( ( int) 0, value1);
+ }
+ {
+ BOOST_CHECK_EQUAL( ( int) 0, value1);
+ auto * coro = new coro::coroutine< void >::push_type(
+ [](coro::coroutine< void >::pull_type & coro) mutable {
+ X x;
+ coro();
+ });
+ ( * coro)();
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+ delete coro;
+ BOOST_CHECK_EQUAL( ( int) 0, value1);
+ }
+}
+
+void test_exceptions()
+{
+ std::string msg("abc"), value;
+ std::runtime_error ex( msg);
+ try
+ {
+ coro::coroutine< void >::push_type coro(
+ [&msg]( coro::coroutine< void >::pull_type &) {
+ throw std::runtime_error( msg);
+ });
+ BOOST_CHECK( coro);
+ coro();
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK( false);
+ }
+ catch ( std::runtime_error const& ex)
+ { value = ex.what(); }
+ BOOST_CHECK_EQUAL( value, msg);
+}
+
+void test_input_iterator()
+{
+ {
+ using std::begin;
+ using std::end;
+
+ std::vector< int > vec;
+ coro::coroutine< int >::pull_type coro( f16);
+ coro::coroutine< int >::pull_type::iterator e = end( coro);
+ for (
+ coro::coroutine< int >::pull_type::iterator i = 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] );
+ }
+ {
+ std::vector< int > vec;
+ coro::coroutine< int >::pull_type coro( f16);
+ for ( auto 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] );
+ }
+ {
+ int i1 = 1, i2 = 2, i3 = 3;
+ coro::coroutine< int& >::pull_type coro(
+ [&i1,&i2,&i3](coro::coroutine< int& >::push_type & c){
+ c( i1);
+ c( i2);
+ c( i3);
+ });
+
+ int counter = 1;
+ for ( int & i : coro) {
+ switch ( counter) {
+ case 1:
+ BOOST_CHECK_EQUAL( & i1, & i);
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( & i2, & i);
+ break;
+ case 3:
+ BOOST_CHECK_EQUAL( & i3, & i);
+ break;
+ default:
+ BOOST_ASSERT( false);
+ }
+ ++counter;
+ }
+ }
+}
+
+void test_output_iterator()
+{
+ using std::begin;
+ using std::end;
+
+ int counter = 0;
+ std::vector< int > vec;
+ coro::coroutine< int >::push_type coro(
+ [&vec]( coro::coroutine< int >::pull_type & c) {
+ int x = c.get();
+ while ( 5 > x)
+ {
+ vec.push_back( x);
+ x = c().get();
+ }
+ });
+ coro::coroutine< int >::push_type::iterator e( end( coro) );
+ for ( coro::coroutine< int >::push_type::iterator i( 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] );
+}
+
+std::vector< int > vec;
+coro::coroutine< void >::pull_type * child = nullptr;
+
+void start_child_coroutine() {
+ child = new coro::coroutine< void >::pull_type([](coro::coroutine< void >::push_type & yield) {
+ vec.push_back( 2);
+ yield();
+ vec.push_back( 2);
+ yield();
+ vec.push_back( 2);
+ yield();
+ vec.push_back( 2);
+ yield();
+ vec.push_back( 2);
+ yield();
+ vec.push_back( 2);
+ });
+}
+
+coro::coroutine< void >::pull_type start_parent_coroutine() {
+ return coro::coroutine< void >::pull_type([=](coro::coroutine< void >::push_type & yield) {
+ vec.push_back( 1);
+ start_child_coroutine();
+ yield();
+ vec.push_back( 1);
+ });
+}
+
+void test_chaining()
+{
+ auto parent = start_parent_coroutine();
+ while ( * child) {
+ ( * child)();
+ }
+ BOOST_CHECK_EQUAL( 7, vec.size() );
+ BOOST_CHECK_EQUAL( 1, vec[0]);
+ BOOST_CHECK_EQUAL( 2, vec[1]);
+ BOOST_CHECK_EQUAL( 2, vec[2]);
+ BOOST_CHECK_EQUAL( 2, vec[3]);
+ BOOST_CHECK_EQUAL( 2, vec[4]);
+ BOOST_CHECK_EQUAL( 2, vec[5]);
+ BOOST_CHECK_EQUAL( 2, vec[6]);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Coroutine2: coroutine test suite");
+
+ test->add( BOOST_TEST_CASE( & test_move) );
+ test->add( BOOST_TEST_CASE( & test_complete) );
+ test->add( BOOST_TEST_CASE( & test_bind) );
+ 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_no_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_exceptions) );
+ test->add( BOOST_TEST_CASE( & test_input_iterator) );
+ test->add( BOOST_TEST_CASE( & test_output_iterator) );
+ test->add( BOOST_TEST_CASE( & test_chaining) );
+
+ return test;
+}