diff options
Diffstat (limited to 'src/boost/libs/coroutine2/test')
-rw-r--r-- | src/boost/libs/coroutine2/test/Jamfile.v2 | 88 | ||||
-rw-r--r-- | src/boost/libs/coroutine2/test/test_coroutine.cpp | 679 |
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; +} |