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 <memory>
9 #include <sstream>
10 #include <stdexcept>
11 #include <string>
12 #include <tuple>
13 #include <utility>
14
15 #include <boost/assert.hpp>
16 #include <boost/test/unit_test.hpp>
17
18 #include <boost/context/detail/invoke.hpp>
19 #include <boost/context/detail/config.hpp>
20
21 namespace ctx = boost::context;
22
23 struct callable {
24 int k{ 0 };
25
26 callable() = default;
27
callablecallable28 callable( int k_) :
29 k{ k_ } {
30 }
31
foocallable32 int foo( int i, int j) const {
33 return i + j + k;
34 }
35
operator ()callable36 int operator()( int i, int j) const {
37 return foo( i, j);
38 }
39 };
40
41 struct movable {
42 int k{ 0 };
43
44 movable() = default;
45
movablemovable46 movable( int k_) :
47 k{ k_ } {
48 }
49
50 movable( movable const&) = delete;
51 movable & operator=( movable const&) = delete;
52
movablemovable53 movable( movable && other) :
54 k{ other.k } {
55 other.k = -1;
56 }
57
operator =movable58 movable & operator=( movable && other) {
59 if ( this == & other) return * this;
60 k = other.k;
61 other.k = -1;
62 return * this;
63 }
64
foomovable65 int foo( int i, int j) const {
66 return i + j + k;
67 }
68
operator ()movable69 int operator()( int i, int j) const {
70 return foo( i, j);
71 }
72 };
73
fn1(int i,int j)74 int fn1( int i, int j) {
75 return i + j;
76 }
77
fn2(int * ip)78 int * fn2( int * ip) {
79 return ip;
80 }
81
fn3(int & ir)82 int * fn3( int & ir) {
83 return & ir;
84 }
85
fn4(int & ir)86 int & fn4( int & ir) {
87 return ir;
88 }
89
90 template< typename T >
fn5(int i,T && t_)91 int fn5( int i, T && t_) {
92 T t = std::forward< T >( t_);
93 return i + t.k;
94 }
95
test1()96 void test1() {
97 int result = ctx::detail::invoke( fn1, 1, 2);
98 BOOST_CHECK_EQUAL( result, 3);
99 }
100
test2()101 void test2() {
102 {
103 int i = 3;
104 int * ip = & i;
105 int * result = ctx::detail::invoke( fn2, ip);
106 BOOST_CHECK_EQUAL( result, ip);
107 BOOST_CHECK_EQUAL( * result, i);
108 }
109 {
110 int i = 3;
111 int * result = ctx::detail::invoke( fn2, & i);
112 BOOST_CHECK_EQUAL( result, & i);
113 BOOST_CHECK_EQUAL( * result, i);
114 }
115 }
116
test3()117 void test3() {
118 {
119 int i = 3;
120 int & ir = i;
121 int * result = ctx::detail::invoke( fn3, ir);
122 BOOST_CHECK_EQUAL( result, & ir);
123 BOOST_CHECK_EQUAL( * result, i);
124 }
125 {
126 int i = 3;
127 int * result = ctx::detail::invoke( fn3, i);
128 BOOST_CHECK_EQUAL( result, & i);
129 BOOST_CHECK_EQUAL( * result, i);
130 }
131 }
132
test4()133 void test4() {
134 {
135 int i = 3;
136 int & ir = i;
137 int & result = ctx::detail::invoke( fn4, ir);
138 BOOST_CHECK_EQUAL( result, ir);
139 BOOST_CHECK_EQUAL( & result, & ir);
140 BOOST_CHECK_EQUAL( result, i);
141 }
142 {
143 int i = 3;
144 int & result = ctx::detail::invoke( fn4, i);
145 BOOST_CHECK_EQUAL( & result, & i);
146 BOOST_CHECK_EQUAL( result, i);
147 }
148 }
149
test5()150 void test5() {
151 {
152 callable c( 5);
153 int result = ctx::detail::invoke( fn5< callable >, 1, std::move( c) );
154 BOOST_CHECK_EQUAL( result, 6);
155 BOOST_CHECK_EQUAL( c.k, 5);
156 }
157 {
158 movable m( 5);
159 int result = ctx::detail::invoke( fn5< movable >, 1, std::move( m) );
160 BOOST_CHECK_EQUAL( result, 6);
161 BOOST_CHECK_EQUAL( m.k, -1);
162 }
163 }
164
test6()165 void test6() {
166 {
167 callable c;
168 int result = ctx::detail::invoke( c, 1, 2);
169 BOOST_CHECK_EQUAL( result, 3);
170 BOOST_CHECK_EQUAL( c.k, 0);
171 }
172 {
173 callable c;
174 int result = ctx::detail::invoke( & callable::foo, c, 1, 2);
175 BOOST_CHECK_EQUAL( result, 3);
176 BOOST_CHECK_EQUAL( c.k, 0);
177 }
178 }
179
test7()180 void test7() {
181 {
182 int result = ctx::detail::invoke( movable{}, 1, 2);
183 BOOST_CHECK_EQUAL( result, 3);
184 }
185 {
186 int result = ctx::detail::invoke( & movable::foo, movable{}, 1, 2);
187 BOOST_CHECK_EQUAL( result, 3);
188 }
189 }
190
191 template< typename R, typename Fn, typename ... Args >
apply(Fn && fn,Args &&...args)192 R apply( Fn && fn, Args && ... args) {
193 return ctx::detail::invoke(
194 std::forward< Fn >( fn),
195 std::forward< Args >( args) ... );
196 }
197
test8()198 void test8() {
199 {
200 int result = apply< int >( fn1, 1, 2);
201 BOOST_CHECK_EQUAL( result, 3);
202 }
203 {
204 int i = 3;
205 int & ir = i;
206 int * result = apply< int * >( fn3, ir);
207 BOOST_CHECK_EQUAL( result, & ir);
208 BOOST_CHECK_EQUAL( * result, i);
209 }
210 {
211 movable m( 5);
212 int result = apply< int >( fn5< movable >, 1, std::move( m) );
213 BOOST_CHECK_EQUAL( result, 6);
214 BOOST_CHECK_EQUAL( m.k, -1);
215 }
216 }
217
init_unit_test_suite(int,char * [])218 boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
219 {
220 boost::unit_test::test_suite * test =
221 BOOST_TEST_SUITE("Boost.Context: invoke test suite");
222
223 test->add( BOOST_TEST_CASE( & test1) );
224 test->add( BOOST_TEST_CASE( & test2) );
225 test->add( BOOST_TEST_CASE( & test3) );
226 test->add( BOOST_TEST_CASE( & test4) );
227 test->add( BOOST_TEST_CASE( & test5) );
228 test->add( BOOST_TEST_CASE( & test6) );
229 test->add( BOOST_TEST_CASE( & test7) );
230 test->add( BOOST_TEST_CASE( & test8) );
231
232 return test;
233 }
234