| |
| // 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 <iostream> |
| #include <sstream> |
| #include <stdexcept> |
| #include <string> |
| #include <utility> |
| |
| #include <boost/array.hpp> |
| #include <boost/assert.hpp> |
| #include <boost/test/unit_test.hpp> |
| #include <boost/utility.hpp> |
| |
| #include <boost/context/all.hpp> |
| #include <boost/context/detail/config.hpp> |
| |
| #include "../example/simple_stack_allocator.hpp" |
| |
| namespace ctx = boost::context; |
| |
| typedef ctx::simple_stack_allocator< |
| 8 * 1024 * 1024, // 8MB |
| 64 * 1024, // 64kB |
| 8 * 1024 // 8kB |
| > stack_allocator; |
| |
| ctx::fcontext_t fcm = 0; |
| ctx::fcontext_t fc = 0; |
| ctx::fcontext_t fc1 = 0; |
| ctx::fcontext_t fc2 = 0; |
| int value1 = 0; |
| std::string value2; |
| double value3 = 0.; |
| |
| void f1( intptr_t) |
| { |
| ++value1; |
| ctx::jump_fcontext( & fc, fcm, 0); |
| } |
| |
| void f3( intptr_t) |
| { |
| ++value1; |
| ctx::jump_fcontext( & fc, fcm, 0); |
| ++value1; |
| ctx::jump_fcontext( & fc, fcm, 0); |
| } |
| |
| void f4( intptr_t) |
| { |
| ctx::jump_fcontext( & fc, fcm, 7); |
| } |
| |
| void f5( intptr_t arg) |
| { |
| ctx::jump_fcontext( & fc, fcm, arg); |
| } |
| |
| void f6( intptr_t arg) |
| { |
| std::pair< int, int > data = * ( std::pair< int, int > * ) arg; |
| int res = data.first + data.second; |
| data = * ( std::pair< int, int > *) |
| ctx::jump_fcontext( & fc, fcm, ( intptr_t) res); |
| res = data.first + data.second; |
| ctx::jump_fcontext( & fc, fcm, ( intptr_t) res); |
| } |
| |
| void f7( intptr_t arg) |
| { |
| try |
| { throw std::runtime_error( ( char *) arg); } |
| catch ( std::runtime_error const& e) |
| { value2 = e.what(); } |
| ctx::jump_fcontext( & fc, fcm, arg); |
| } |
| |
| void f8( intptr_t arg) |
| { |
| double d = * ( double *) arg; |
| d += 3.45; |
| value3 = d; |
| ctx::jump_fcontext( & fc, fcm, 0); |
| } |
| |
| void f10( intptr_t) |
| { |
| value1 = 3; |
| ctx::jump_fcontext( & fc2, fc1, 0); |
| } |
| |
| void f9( intptr_t) |
| { |
| std::cout << "f1: entered" << std::endl; |
| |
| stack_allocator alloc; |
| void * sp = alloc.allocate( stack_allocator::default_stacksize()); |
| fc2 = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f10); |
| ctx::jump_fcontext( & fc1, fc2, 0); |
| ctx::jump_fcontext( & fc1, fcm, 0); |
| } |
| |
| void test_setup() |
| { |
| stack_allocator alloc; |
| |
| void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); |
| fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f1); |
| BOOST_CHECK( fc); |
| } |
| |
| void test_start() |
| { |
| value1 = 0; |
| |
| stack_allocator alloc; |
| |
| void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); |
| fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f1); |
| BOOST_CHECK( fc); |
| |
| BOOST_CHECK_EQUAL( 0, value1); |
| ctx::jump_fcontext( & fcm, fc, 0); |
| BOOST_CHECK_EQUAL( 1, value1); |
| } |
| |
| void test_jump() |
| { |
| value1 = 0; |
| |
| stack_allocator alloc; |
| |
| void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); |
| fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f3); |
| BOOST_CHECK( fc); |
| |
| BOOST_CHECK_EQUAL( 0, value1); |
| ctx::jump_fcontext( & fcm, fc, 0); |
| BOOST_CHECK_EQUAL( 1, value1); |
| ctx::jump_fcontext( & fcm, fc, 0); |
| BOOST_CHECK_EQUAL( 2, value1); |
| } |
| |
| void test_result() |
| { |
| stack_allocator alloc; |
| |
| void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); |
| fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f4); |
| BOOST_CHECK( fc); |
| |
| int result = ( int) ctx::jump_fcontext( & fcm, fc, 0); |
| BOOST_CHECK_EQUAL( 7, result); |
| } |
| |
| void test_arg() |
| { |
| stack_allocator alloc; |
| |
| int i = 7; |
| void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); |
| fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f5); |
| BOOST_CHECK( fc); |
| |
| int result = ( int) ctx::jump_fcontext( & fcm, fc, i); |
| BOOST_CHECK_EQUAL( i, result); |
| } |
| |
| void test_transfer() |
| { |
| stack_allocator alloc; |
| |
| std::pair< int, int > data = std::make_pair( 3, 7); |
| void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); |
| fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f6); |
| BOOST_CHECK( fc); |
| |
| int result = ( int) ctx::jump_fcontext( & fcm, fc, ( intptr_t) & data); |
| BOOST_CHECK_EQUAL( 10, result); |
| data = std::make_pair( 7, 7); |
| result = ( int) ctx::jump_fcontext( & fcm, fc, ( intptr_t) & data); |
| BOOST_CHECK_EQUAL( 14, result); |
| } |
| |
| void test_exception() |
| { |
| stack_allocator alloc; |
| |
| const char * what = "hello world"; |
| void * sp = alloc.allocate( stack_allocator::default_stacksize() ); |
| fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f7); |
| BOOST_CHECK( fc); |
| |
| ctx::jump_fcontext( & fcm, fc, ( intptr_t) what); |
| BOOST_CHECK_EQUAL( std::string( what), value2); |
| } |
| |
| void test_fp() |
| { |
| stack_allocator alloc; |
| |
| double d = 7.13; |
| void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); |
| fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f8); |
| BOOST_CHECK( fc); |
| |
| ctx::jump_fcontext( & fcm, fc, (intptr_t) & d); |
| BOOST_CHECK_EQUAL( 10.58, value3); |
| } |
| |
| void test_stacked() |
| { |
| value1 = 0; |
| stack_allocator alloc; |
| void * sp = alloc.allocate( stack_allocator::default_stacksize()); |
| fc1 = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f9); |
| ctx::jump_fcontext( & fcm, fc1, 0); |
| BOOST_CHECK_EQUAL( 3, value1); |
| } |
| |
| #if ! defined(BOOST_CONTEXT_NO_EXECUTION_CONTEXT) |
| ctx::execution_context * mctx = nullptr; |
| |
| void f11() { |
| value1 = 3; |
| mctx->resume(); |
| } |
| |
| void f12( int i) { |
| value1 = i; |
| mctx->resume(); |
| } |
| |
| void test_ectx() { |
| boost::context::execution_context ctx( boost::context::execution_context::current() ); |
| mctx = & ctx; |
| value1 = 0; |
| ctx::fixedsize_stack alloc; |
| ctx::execution_context ectx( alloc, f11); |
| ectx.resume(); |
| BOOST_CHECK_EQUAL( 3, value1); |
| } |
| |
| void test_variadric() { |
| boost::context::execution_context ctx( boost::context::execution_context::current() ); |
| mctx = & ctx; |
| value1 = 0; |
| ctx::fixedsize_stack alloc; |
| ctx::execution_context ectx( alloc, f12, 5); |
| ectx.resume(); |
| BOOST_CHECK_EQUAL( 5, value1); |
| } |
| |
| void test_prealloc() { |
| boost::context::execution_context ctx( boost::context::execution_context::current() ); |
| mctx = & ctx; |
| value1 = 0; |
| ctx::fixedsize_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( ctx::preallocated( sp, size, sctx), alloc, f12, 7); |
| ectx.resume(); |
| BOOST_CHECK_EQUAL( 7, value1); |
| } |
| #endif |
| |
| boost::unit_test::test_suite * init_unit_test_suite( int, char* []) |
| { |
| boost::unit_test::test_suite * test = |
| BOOST_TEST_SUITE("Boost.Context: context test suite"); |
| |
| test->add( BOOST_TEST_CASE( & test_setup) ); |
| test->add( BOOST_TEST_CASE( & test_start) ); |
| test->add( BOOST_TEST_CASE( & test_jump) ); |
| test->add( BOOST_TEST_CASE( & test_result) ); |
| test->add( BOOST_TEST_CASE( & test_arg) ); |
| test->add( BOOST_TEST_CASE( & test_transfer) ); |
| test->add( BOOST_TEST_CASE( & test_exception) ); |
| test->add( BOOST_TEST_CASE( & test_fp) ); |
| test->add( BOOST_TEST_CASE( & test_stacked) ); |
| |
| #if ! defined(BOOST_CONTEXT_NO_EXECUTION_CONTEXT) |
| test->add( BOOST_TEST_CASE( & test_ectx) ); |
| test->add( BOOST_TEST_CASE( & test_variadric) ); |
| test->add( BOOST_TEST_CASE( & test_prealloc) ); |
| #endif |
| |
| return test; |
| } |