1 
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)
6 
7 #include <iostream>
8 #include <sstream>
9 #include <stdexcept>
10 #include <string>
11 #include <utility>
12 
13 #include <boost/array.hpp>
14 #include <boost/assert.hpp>
15 #include <boost/test/unit_test.hpp>
16 #include <boost/utility.hpp>
17 
18 #include <boost/context/all.hpp>
19 #include <boost/context/detail/config.hpp>
20 
21 #include "../example/simple_stack_allocator.hpp"
22 
23 namespace ctx = boost::context;
24 
25 typedef ctx::simple_stack_allocator<
26     8 * 1024 * 1024, // 8MB
27     64 * 1024, // 64kB
28     8 * 1024 // 8kB
29 >       stack_allocator;
30 
31 ctx::fcontext_t fcm = 0;
32 ctx::fcontext_t fc = 0;
33 ctx::fcontext_t fc1 = 0;
34 ctx::fcontext_t fc2 = 0;
35 int value1 = 0;
36 std::string value2;
37 double value3 = 0.;
38 
f1(intptr_t)39 void f1( intptr_t)
40 {
41     ++value1;
42     ctx::jump_fcontext( & fc, fcm, 0);
43 }
44 
f3(intptr_t)45 void f3( intptr_t)
46 {
47     ++value1;
48     ctx::jump_fcontext( & fc, fcm, 0);
49     ++value1;
50     ctx::jump_fcontext( & fc, fcm, 0);
51 }
52 
f4(intptr_t)53 void f4( intptr_t)
54 {
55     ctx::jump_fcontext( & fc, fcm, 7);
56 }
57 
f5(intptr_t arg)58 void f5( intptr_t arg)
59 {
60     ctx::jump_fcontext( & fc, fcm, arg);
61 }
62 
f6(intptr_t arg)63 void f6( intptr_t arg)
64 {
65     std::pair< int, int > data = * ( std::pair< int, int > * ) arg;
66     int res = data.first + data.second;
67     data = * ( std::pair< int, int > *)
68         ctx::jump_fcontext( & fc, fcm, ( intptr_t) res);
69     res = data.first + data.second;
70     ctx::jump_fcontext( & fc, fcm, ( intptr_t) res);
71 }
72 
f7(intptr_t arg)73 void f7( intptr_t arg)
74 {
75     try
76     { throw std::runtime_error( ( char *) arg); }
77     catch ( std::runtime_error const& e)
78     { value2 = e.what(); }
79     ctx::jump_fcontext( & fc, fcm, arg);
80 }
81 
f8(intptr_t arg)82 void f8( intptr_t arg)
83 {
84     double d = * ( double *) arg;
85     d += 3.45;
86     value3 = d;
87     ctx::jump_fcontext( & fc, fcm, 0);
88 }
89 
f10(intptr_t)90 void f10( intptr_t)
91 {
92     value1 = 3;
93     ctx::jump_fcontext( & fc2, fc1, 0);
94 }
95 
f9(intptr_t)96 void f9( intptr_t)
97 {
98     std::cout << "f1: entered" << std::endl;
99 
100     stack_allocator alloc;
101     void * sp = alloc.allocate( stack_allocator::default_stacksize());
102     fc2 = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f10);
103     ctx::jump_fcontext( & fc1, fc2, 0);
104     ctx::jump_fcontext( & fc1, fcm, 0);
105 }
106 
test_setup()107 void test_setup()
108 {
109     stack_allocator alloc;
110 
111     void * sp = alloc.allocate( stack_allocator::minimum_stacksize() );
112     fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f1);
113     BOOST_CHECK( fc);
114 }
115 
test_start()116 void test_start()
117 {
118     value1 = 0;
119 
120     stack_allocator alloc;
121 
122     void * sp = alloc.allocate( stack_allocator::minimum_stacksize() );
123     fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f1);
124     BOOST_CHECK( fc);
125 
126     BOOST_CHECK_EQUAL( 0, value1);
127     ctx::jump_fcontext( & fcm, fc, 0);
128     BOOST_CHECK_EQUAL( 1, value1);
129 }
130 
test_jump()131 void test_jump()
132 {
133     value1 = 0;
134 
135     stack_allocator alloc;
136 
137     void * sp = alloc.allocate( stack_allocator::minimum_stacksize() );
138     fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f3);
139     BOOST_CHECK( fc);
140 
141     BOOST_CHECK_EQUAL( 0, value1);
142     ctx::jump_fcontext( & fcm, fc, 0);
143     BOOST_CHECK_EQUAL( 1, value1);
144     ctx::jump_fcontext( & fcm, fc, 0);
145     BOOST_CHECK_EQUAL( 2, value1);
146 }
147 
test_result()148 void test_result()
149 {
150     stack_allocator alloc;
151 
152     void * sp = alloc.allocate( stack_allocator::minimum_stacksize() );
153     fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f4);
154     BOOST_CHECK( fc);
155 
156     int result = ( int) ctx::jump_fcontext( & fcm, fc, 0);
157     BOOST_CHECK_EQUAL( 7, result);
158 }
159 
test_arg()160 void test_arg()
161 {
162     stack_allocator alloc;
163 
164     int i = 7;
165     void * sp = alloc.allocate( stack_allocator::minimum_stacksize() );
166     fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f5);
167     BOOST_CHECK( fc);
168 
169     int result = ( int) ctx::jump_fcontext( & fcm, fc, i);
170     BOOST_CHECK_EQUAL( i, result);
171 }
172 
test_transfer()173 void test_transfer()
174 {
175     stack_allocator alloc;
176 
177     std::pair< int, int > data = std::make_pair( 3, 7);
178     void * sp = alloc.allocate( stack_allocator::minimum_stacksize() );
179     fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f6);
180     BOOST_CHECK( fc);
181 
182     int result = ( int) ctx::jump_fcontext( & fcm, fc, ( intptr_t) & data);
183     BOOST_CHECK_EQUAL( 10, result);
184     data = std::make_pair( 7, 7);
185     result = ( int) ctx::jump_fcontext( & fcm, fc, ( intptr_t) & data);
186     BOOST_CHECK_EQUAL( 14, result);
187 }
188 
test_exception()189 void test_exception()
190 {
191     stack_allocator alloc;
192 
193     const char * what = "hello world";
194     void * sp = alloc.allocate( stack_allocator::default_stacksize() );
195     fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f7);
196     BOOST_CHECK( fc);
197 
198     ctx::jump_fcontext( & fcm, fc, ( intptr_t) what);
199     BOOST_CHECK_EQUAL( std::string( what), value2);
200 }
201 
test_fp()202 void test_fp()
203 {
204     stack_allocator alloc;
205 
206     double d = 7.13;
207     void * sp = alloc.allocate( stack_allocator::minimum_stacksize() );
208     fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f8);
209     BOOST_CHECK( fc);
210 
211     ctx::jump_fcontext( & fcm, fc, (intptr_t) & d);
212     BOOST_CHECK_EQUAL( 10.58, value3);
213 }
214 
test_stacked()215 void test_stacked()
216 {
217     value1 = 0;
218     stack_allocator alloc;
219     void * sp = alloc.allocate( stack_allocator::default_stacksize());
220     fc1 = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f9);
221     ctx::jump_fcontext( & fcm, fc1, 0);
222     BOOST_CHECK_EQUAL( 3, value1);
223 }
224 
init_unit_test_suite(int,char * [])225 boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
226 {
227     boost::unit_test::test_suite * test =
228         BOOST_TEST_SUITE("Boost.Context: context test suite");
229 
230     test->add( BOOST_TEST_CASE( & test_setup) );
231     test->add( BOOST_TEST_CASE( & test_start) );
232     test->add( BOOST_TEST_CASE( & test_jump) );
233     test->add( BOOST_TEST_CASE( & test_result) );
234     test->add( BOOST_TEST_CASE( & test_arg) );
235     test->add( BOOST_TEST_CASE( & test_transfer) );
236     test->add( BOOST_TEST_CASE( & test_exception) );
237     test->add( BOOST_TEST_CASE( & test_fp) );
238     test->add( BOOST_TEST_CASE( & test_stacked) );
239 
240     return test;
241 }
242