262 lines
7.2 KiB
Plaintext
262 lines
7.2 KiB
Plaintext
|
|
// 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 <memory>
|
|
#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/execution_context.hpp>
|
|
#include <boost/context/detail/config.hpp>
|
|
|
|
#ifdef BOOST_WINDOWS
|
|
#include <windows.h>
|
|
#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;
|
|
}
|