2 // Copyright Oliver Kowalke 2009.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
22 #include <boost/array.hpp>
23 #include <boost/assert.hpp>
24 #include <boost/lexical_cast.hpp>
25 #include <boost/test/unit_test.hpp>
26 #include <boost/utility.hpp>
27 #include <boost/variant.hpp>
29 #include <boost/context/continuation.hpp>
30 #include <boost/context/detail/config.hpp>
36 #if defined(BOOST_MSVC)
37 # pragma warning(push)
38 # pragma warning(disable: 4702 4723 4996)
41 typedef boost::variant
<int,std::string
> variant_t
;
43 namespace ctx
= boost::context
;
50 ctx::continuation
foo( ctx::continuation
&& c
, int i
) {
61 Y( Y
const&) = delete;
62 Y
& operator=( Y
const&) = delete;
84 moveable( moveable
&& other
) :
91 moveable
& operator=( moveable
&& other
) {
92 if ( this == & other
) return * this;
100 moveable( moveable
const& other
) = delete;
101 moveable
& operator=( moveable
const& other
) = delete;
108 struct my_exception
: public std::runtime_error
{
110 my_exception( ctx::continuation
&& c_
, char const* what
) :
111 std::runtime_error( what
),
112 c
{ std::move( c_
) } {
117 // Optimizations can remove the integer-divide-by-zero here.
118 #pragma optimize("", off)
119 void seh( bool & catched
) {
123 } __except( EXCEPTION_EXECUTE_HANDLER
) {
127 #pragma optimize("", on)
133 BOOST_CHECK_EQUAL( 0, value1
);
134 ctx::continuation c1
= ctx::callcc(
135 [&i
](ctx::continuation
&& c
) {
139 return std::move( c
);
141 BOOST_CHECK_EQUAL( 1, value1
);
143 ctx::continuation c2
;
150 BOOST_CHECK_EQUAL( 3, value1
);
158 ctx::continuation c
= ctx::callcc( std::bind( & X::foo
, x
, std::placeholders::_1
, 7) );
159 BOOST_CHECK_EQUAL( 7, value1
);
162 void test_exception() {
164 const char * what
= "hello world";
165 ctx::continuation c
= ctx::callcc(
166 [&what
](ctx::continuation
&& c
) {
168 throw std::runtime_error( what
);
169 } catch ( std::runtime_error
const& e
) {
172 return std::move( c
);
174 BOOST_CHECK_EQUAL( std::string( what
), value2
);
179 bool catched
= false;
180 std::thread([&catched
](){
181 ctx::continuation c
= ctx::callcc([&catched
](ctx::continuation
&& c
){
184 return std::move( c
);
189 BOOST_CHECK( catched
);
197 ctx::continuation c
= ctx::callcc(
198 [&d
]( ctx::continuation
&& c
) {
201 return std::move( c
);
203 BOOST_CHECK_EQUAL( 10.58, value3
);
207 void test_stacked() {
210 ctx::continuation c
= ctx::callcc(
211 [](ctx::continuation
&& c
) {
212 ctx::continuation c1
= ctx::callcc(
213 [](ctx::continuation
&& c
) {
215 return std::move( c
);
218 return std::move( c
);
220 BOOST_CHECK_EQUAL( 3, value1
);
221 BOOST_CHECK_EQUAL( 3.14, value3
);
225 void test_prealloc() {
227 ctx::default_stack alloc
;
228 ctx::stack_context
sctx( alloc
.allocate() );
229 void * sp
= static_cast< char * >( sctx
.sp
) - 10;
230 std::size_t size
= sctx
.size
- 10;
232 ctx::continuation c
= ctx::callcc(
233 std::allocator_arg
, ctx::preallocated( sp
, size
, sctx
), alloc
,
234 [&i
]( ctx::continuation
&& c
) {
236 return std::move( c
);
238 BOOST_CHECK_EQUAL( 7, value1
);
245 ctx::continuation c
= ctx::callcc([&i
](ctx::continuation
&& c
) {
250 return std::move( c
);
253 [&i
](ctx::continuation
&& c
){
255 return std::move( c
);
258 BOOST_CHECK_EQUAL( i
, 200);
261 ctx::continuation c1
;
262 ctx::continuation c
= ctx::callcc([&c1
](ctx::continuation
&& c
) {
265 return std::move( c1
);
268 [&c1
](ctx::continuation
&& c
){
270 return std::move( c
);
275 void test_ontop_exception() {
278 ctx::continuation c
= ctx::callcc([](ctx::continuation
&& c
){
283 } catch ( my_exception
& ex
) {
285 return std::move( ex
.c
);
288 return std::move( c
);
291 BOOST_CHECK_EQUAL( 3, value1
);
292 const char * what
= "hello world";
294 [what
](ctx::continuation
&& c
){
295 throw my_exception( std::move( c
), what
);
296 return std::move( c
);
298 BOOST_CHECK_EQUAL( 3, value1
);
299 BOOST_CHECK_EQUAL( std::string( what
), value2
);
302 void test_termination() {
305 ctx::continuation c
= ctx::callcc(
306 [](ctx::continuation
&& c
){
310 BOOST_CHECK_EQUAL( 3, value1
);
312 BOOST_CHECK_EQUAL( 7, value1
);
315 BOOST_CHECK_EQUAL( 0, value1
);
316 ctx::continuation c
= ctx::callcc(
317 [](ctx::continuation
&& c
) {
319 return std::move( c
);
321 BOOST_CHECK_EQUAL( 3, value1
);
326 BOOST_CHECK_EQUAL( 0, value1
);
328 ctx::continuation c
= ctx::callcc(
329 [&i
](ctx::continuation
&& c
){
333 return std::move( c
);
336 BOOST_CHECK_EQUAL( i
, value1
);
341 BOOST_CHECK_EQUAL( i
, value1
);
346 ctx::continuation c
= ctx::callcc(
347 []( ctx::continuation
&& c
) {
351 sscanf("3.14 7.13", "%lf %lf", & n1
, & n2
);
352 BOOST_CHECK( n1
== 3.14);
353 BOOST_CHECK( n2
== 7.13);
358 sscanf("1 23", "%d %d", & n1
, & n2
);
359 BOOST_CHECK( n1
== 1);
360 BOOST_CHECK( n2
== 23);
365 sscanf("1 jjj 23", "%d %*[j] %d", & n1
, & n2
);
366 BOOST_CHECK( n1
== 1);
367 BOOST_CHECK( n2
== 23);
369 return std::move( c
);
373 void test_snprintf() {
374 ctx::continuation c
= ctx::callcc(
375 []( ctx::continuation
&& c
) {
377 const char *fmt
= "sqrt(2) = %f";
379 snprintf( buf
, sizeof( buf
), fmt
, std::sqrt( 2) );
380 BOOST_CHECK( 0 < sizeof( buf
) );
381 BOOST_ASSERT( std::string("sqrt(2) = 1.41") == std::string( buf
, 14) );
384 std::uint64_t n
= 0xbcdef1234567890;
385 const char *fmt
= "0x%016llX";
387 snprintf( buf
, sizeof( buf
), fmt
, n
);
388 BOOST_ASSERT( std::string("0x0BCDEF1234567890") == std::string( buf
, 18) );
390 return std::move( c
);
395 void test_bug12215() {
396 ctx::continuation c
= ctx::callcc(
397 [](ctx::continuation
&& c
) {
398 char buffer
[MAX_PATH
];
399 GetModuleFileName( nullptr, buffer
, MAX_PATH
);
400 return std::move( c
);
405 boost::unit_test::test_suite
* init_unit_test_suite( int, char* [])
407 boost::unit_test::test_suite
* test
=
408 BOOST_TEST_SUITE("Boost.Context: callcc test suite");
410 test
->add( BOOST_TEST_CASE( & test_move
) );
411 test
->add( BOOST_TEST_CASE( & test_bind
) );
412 test
->add( BOOST_TEST_CASE( & test_exception
) );
413 test
->add( BOOST_TEST_CASE( & test_fp
) );
414 test
->add( BOOST_TEST_CASE( & test_stacked
) );
415 test
->add( BOOST_TEST_CASE( & test_prealloc
) );
416 test
->add( BOOST_TEST_CASE( & test_ontop
) );
417 test
->add( BOOST_TEST_CASE( & test_ontop_exception
) );
418 test
->add( BOOST_TEST_CASE( & test_termination
) );
419 test
->add( BOOST_TEST_CASE( & test_sscanf
) );
420 test
->add( BOOST_TEST_CASE( & test_snprintf
) );
422 test
->add( BOOST_TEST_CASE( & test_bug12215
) );
428 #if defined(BOOST_MSVC)
429 # pragma warning(pop)