// 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 #include #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_WINDOWS #include #endif namespace ctx = boost::context; int value1 = 0; std::string value2; double value3 = 0.; #ifdef BOOST_WINDOWS void seh( bool & catched) { __try { int i = 1; i /= 0; } __except( EXCEPTION_EXECUTE_HANDLER) { catched = true; } } #endif void fn1( void * vp) { value1 = 3; ctx::execution_context * mctx = static_cast< ctx::execution_context * >( vp); ( * mctx)(); } void fn2( int i, void * vp) { value1 = i; ctx::execution_context * mctx = static_cast< ctx::execution_context * >( vp); ( * mctx)(); } void fn3( const char * what, void * vp) { try { throw std::runtime_error( what); } catch ( std::runtime_error const& e) { value2 = e.what(); } ctx::execution_context * mctx = static_cast< ctx::execution_context * >( vp); ( * mctx)(); } void fn4( double d, void * vp) { d += 3.45; value3 = d; ctx::execution_context * mctx = static_cast< ctx::execution_context * >( vp); ( * mctx)(); } void fn6( void * vp) { value1 = 3; ctx::execution_context * mctx = static_cast< ctx::execution_context * >( vp); ( * mctx)(); } void fn5( void * vp) { std::cout << "fn5: entered" << std::endl; ctx::execution_context ectx( fn6); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); value3 = 3.14; ctx::execution_context * mctx = static_cast< ctx::execution_context * >( vp); ( * mctx)(); } void fn7( void * vp) { ctx::execution_context * mctx = static_cast< ctx::execution_context * >( vp); try { value1 = 3; void * data = ( * mctx)( vp); value1 = 7; ( * mctx)( data); } catch ( std::runtime_error const& e) { value2 = e.what(); } ( * mctx)(); } struct X { int foo( int i, void * vp) { value1 = i; ctx::execution_context * mctx = static_cast< ctx::execution_context * >( vp); ( * mctx)(); return i; } }; void test_ectx() { value1 = 0; ctx::execution_context ectx( fn1); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); BOOST_CHECK_EQUAL( 3, value1); } void test_variadric() { value1 = 0; ctx::execution_context ectx( fn2, 5); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); BOOST_CHECK_EQUAL( 5, value1); } void test_memfn() { value1 = 0; X x; ctx::execution_context ectx( & X::foo, x, 7); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); BOOST_CHECK_EQUAL( 7, value1); } void test_exception() { { const char * what = "hello world"; ctx::execution_context ectx( fn3, what); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); BOOST_CHECK_EQUAL( std::string( what), value2); } #ifdef BOOST_WINDOWS { bool catched = false; ctx::execution_context ectx([&catched]( void * vp){ ctx::execution_context * mctx = static_cast< ctx::execution_context * >( vp); seh( catched); ( * mctx)(); }); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); BOOST_CHECK( catched); } #endif } void test_fp() { double d = 7.13; ctx::execution_context ectx( fn4, d); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); BOOST_CHECK_EQUAL( 10.58, value3); } void test_stacked() { value1 = 0; value3 = 0.; ctx::execution_context ectx( fn5); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); BOOST_CHECK_EQUAL( 3, value1); BOOST_CHECK_EQUAL( 3.14, value3); } void test_prealloc() { value1 = 0; ctx::default_stack alloc; ctx::stack_context sctx( alloc.allocate() ); void * sp = static_cast< char * >( sctx.sp) - 10; std::size_t size = sctx.size - 10; ctx::execution_context ectx( std::allocator_arg, ctx::preallocated( sp, size, sctx), alloc, fn2, 7); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); BOOST_CHECK_EQUAL( 7, value1); } void test_ontop() { value1 = 0; value2 = ""; ctx::execution_context ectx( fn7); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); BOOST_CHECK_EQUAL( 3, value1); BOOST_CHECK( value2.empty() ); std::string str("abc"); int i = 3; void * data = ectx( ctx::exec_ontop_arg, [str](void * data){ value2 = str; return data; }, & i); BOOST_CHECK_EQUAL( 7, value1); BOOST_CHECK_EQUAL( str, value2); BOOST_CHECK_EQUAL( data, & i); BOOST_CHECK_EQUAL( i, *( int*) data); } void test_ontop_exception() { value1 = 0; value2 = ""; ctx::execution_context ectx( fn7); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); BOOST_CHECK_EQUAL( 3, value1); const char * what = "hello world"; ectx( ctx::exec_ontop_arg, [what](void * data){ throw std::runtime_error( what); return data; }, nullptr); BOOST_CHECK_EQUAL( 3, value1); BOOST_CHECK_EQUAL( std::string( what), value2); } #ifdef BOOST_WINDOWS void test_test_bug12215() { ctx::execution_context ectx( [](void * vp) { ctx::execution_context * mctx = static_cast< ctx::execution_context * >( vp); char buffer[MAX_PATH]; GetModuleFileName( nullptr, buffer, MAX_PATH); ( * mctx)(); }); boost::context::execution_context ctx( boost::context::execution_context::current() ); ectx( & ctx); } #endif boost::unit_test::test_suite * init_unit_test_suite( int, char* []) { boost::unit_test::test_suite * test = BOOST_TEST_SUITE("Boost.Context: execution_context v1 test suite"); test->add( BOOST_TEST_CASE( & test_ectx) ); test->add( BOOST_TEST_CASE( & test_variadric) ); test->add( BOOST_TEST_CASE( & test_memfn) ); test->add( BOOST_TEST_CASE( & test_exception) ); test->add( BOOST_TEST_CASE( & test_fp) ); test->add( BOOST_TEST_CASE( & test_stacked) ); test->add( BOOST_TEST_CASE( & test_prealloc) ); test->add( BOOST_TEST_CASE( & test_ontop) ); test->add( BOOST_TEST_CASE( & test_ontop_exception) ); #ifdef BOOST_WINDOWS test->add( BOOST_TEST_CASE( & test_test_bug12215) ); #endif return test; }