2 // Copyright Oliver Kowalke 2013.
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)
12 #include <boost/assert.hpp>
13 #include <boost/test/unit_test.hpp>
15 #include <boost/fiber/all.hpp>
31 moveable( moveable
&& other
) :
38 moveable
& operator=( moveable
&& other
) {
39 if ( this == & other
) return * this;
49 boost::fibers::unbuffered_channel
< int > c
;
50 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
](){
51 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 1) );
54 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( value
) );
55 BOOST_CHECK_EQUAL( 1, value
);
59 void test_push_closed() {
60 boost::fibers::unbuffered_channel
< int > c
;
62 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.push( 1) );
66 void test_push_wait_for() {
67 boost::fibers::unbuffered_channel
< int > c
;
68 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
](){
69 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push_wait_for( 1, std::chrono::seconds( 1) ) );
72 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( value
) );
73 BOOST_CHECK_EQUAL( 1, value
);
77 void test_push_wait_for_closed() {
78 boost::fibers::unbuffered_channel
< int > c
;
80 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.push_wait_for( 1, std::chrono::seconds( 1) ) );
83 void test_push_wait_for_timeout() {
84 boost::fibers::unbuffered_channel
< int > c
;
85 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
](){
87 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( value
) );
88 BOOST_CHECK_EQUAL( 1, value
);
90 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push_wait_for( 1, std::chrono::seconds( 1) ) );
91 BOOST_CHECK( boost::fibers::channel_op_status::timeout
== c
.push_wait_for( 1, std::chrono::seconds( 1) ) );
95 void test_push_wait_until() {
96 boost::fibers::unbuffered_channel
< int > c
;
97 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
](){
98 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push_wait_until( 1,
99 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
102 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( value
) );
103 BOOST_CHECK_EQUAL( 1, value
);
107 void test_push_wait_until_closed() {
108 boost::fibers::unbuffered_channel
< int > c
;
110 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.push_wait_until( 1,
111 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
114 void test_push_wait_until_timeout() {
115 boost::fibers::unbuffered_channel
< int > c
;
116 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
](){
118 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( value
) );
119 BOOST_CHECK_EQUAL( 1, value
);
121 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push_wait_until( 1,
122 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
123 BOOST_CHECK( boost::fibers::channel_op_status::timeout
== c
.push_wait_until( 1,
124 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
129 boost::fibers::unbuffered_channel
< int > c
;
131 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&v1
,&c
](){
132 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
134 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( v2
) );
135 BOOST_CHECK_EQUAL( v1
, v2
);
139 void test_pop_closed() {
140 boost::fibers::unbuffered_channel
< int > c
;
142 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&v1
,&c
](){
143 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
146 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( v2
) );
147 BOOST_CHECK_EQUAL( v1
, v2
);
148 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.pop( v2
) );
152 void test_pop_success() {
153 boost::fibers::unbuffered_channel
< int > c
;
155 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v2
](){
156 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( v2
) );
158 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
160 BOOST_CHECK_EQUAL( v1
, v2
);
163 void test_value_pop() {
164 boost::fibers::unbuffered_channel
< int > c
;
166 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v1
](){
167 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
171 BOOST_CHECK_EQUAL( v1
, v2
);
174 void test_value_pop_closed() {
175 boost::fibers::unbuffered_channel
< int > c
;
177 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v1
](){
178 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
181 int v2
= c
.value_pop();
182 BOOST_CHECK_EQUAL( v1
, v2
);
187 } catch ( boost::fibers::fiber_error
const&) {
190 BOOST_CHECK( thrown
);
193 void test_value_pop_success() {
194 boost::fibers::unbuffered_channel
< int > c
;
196 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v2
](){
199 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
201 BOOST_CHECK_EQUAL( v1
, v2
);
204 void test_pop_wait_for() {
205 boost::fibers::unbuffered_channel
< int > c
;
207 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v1
](){
208 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
210 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_for( v2
, std::chrono::seconds( 1) ) );
212 BOOST_CHECK_EQUAL( v1
, v2
);
215 void test_pop_wait_for_closed() {
216 boost::fibers::unbuffered_channel
< int > c
;
218 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v1
](){
219 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
222 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_for( v2
, std::chrono::seconds( 1) ) );
223 BOOST_CHECK_EQUAL( v1
, v2
);
224 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.pop_wait_for( v2
, std::chrono::seconds( 1) ) );
228 void test_pop_wait_for_success() {
229 boost::fibers::unbuffered_channel
< int > c
;
231 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v2
](){
232 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_for( v2
, std::chrono::seconds( 1) ) );
234 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
236 BOOST_CHECK_EQUAL( v1
, v2
);
239 void test_pop_wait_for_timeout() {
240 boost::fibers::unbuffered_channel
< int > c
;
242 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v
](){
243 BOOST_CHECK( boost::fibers::channel_op_status::timeout
== c
.pop_wait_for( v
, std::chrono::seconds( 1) ) );
248 void test_pop_wait_until() {
249 boost::fibers::unbuffered_channel
< int > c
;
251 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v1
](){
252 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
254 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_until( v2
,
255 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
256 BOOST_CHECK_EQUAL( v1
, v2
);
260 void test_pop_wait_until_closed() {
261 boost::fibers::unbuffered_channel
< int > c
;
263 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v1
](){
264 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
267 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_until( v2
,
268 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
269 BOOST_CHECK_EQUAL( v1
, v2
);
270 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.pop_wait_until( v2
,
271 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
275 void test_pop_wait_until_success() {
276 boost::fibers::unbuffered_channel
< int > c
;
278 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v2
](){
279 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_until( v2
,
280 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
282 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
284 BOOST_CHECK_EQUAL( v1
, v2
);
287 void test_pop_wait_until_timeout() {
288 boost::fibers::unbuffered_channel
< int > c
;
291 boost::fibers::channel_op_status::timeout
== c
.pop_wait_until( v
,
292 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
296 boost::fibers::unbuffered_channel
< int > c
;
297 std::vector
< boost::fibers::fiber::id
> ids
;
298 boost::fibers::fiber
f1( boost::fibers::launch::dispatch
, [&c
,&ids
](){
299 ids
.push_back( boost::this_fiber::get_id() );
300 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 1) );
302 ids
.push_back( boost::this_fiber::get_id() );
303 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 2) );
305 ids
.push_back( boost::this_fiber::get_id() );
306 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 3) );
308 ids
.push_back( boost::this_fiber::get_id() );
309 // would be blocked because channel is full
310 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 4) );
312 ids
.push_back( boost::this_fiber::get_id() );
313 // would be blocked because channel is full
314 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 5) );
316 ids
.push_back( boost::this_fiber::get_id() );
318 boost::fibers::fiber
f2( boost::fibers::launch::dispatch
, [&c
,&ids
](){
319 ids
.push_back( boost::this_fiber::get_id() );
320 BOOST_CHECK_EQUAL( 1, c
.value_pop() );
322 // let other fiber run
323 boost::this_fiber::yield();
325 ids
.push_back( boost::this_fiber::get_id() );
326 BOOST_CHECK_EQUAL( 2, c
.value_pop() );
328 ids
.push_back( boost::this_fiber::get_id() );
329 BOOST_CHECK_EQUAL( 3, c
.value_pop() );
331 ids
.push_back( boost::this_fiber::get_id() );
332 BOOST_CHECK_EQUAL( 4, c
.value_pop() );
334 ids
.push_back( boost::this_fiber::get_id() );
335 // would block because channel is empty
336 BOOST_CHECK_EQUAL( 5, c
.value_pop() );
338 ids
.push_back( boost::this_fiber::get_id() );
340 boost::fibers::fiber::id id1
= f1
.get_id();
341 boost::fibers::fiber::id id2
= f2
.get_id();
344 BOOST_CHECK_EQUAL( 12u, ids
.size() );
345 BOOST_CHECK_EQUAL( id1
, ids
[0]);
346 BOOST_CHECK_EQUAL( id2
, ids
[1]);
347 BOOST_CHECK_EQUAL( id1
, ids
[2]);
348 BOOST_CHECK_EQUAL( id2
, ids
[3]);
349 BOOST_CHECK_EQUAL( id2
, ids
[4]);
350 BOOST_CHECK_EQUAL( id1
, ids
[5]);
351 BOOST_CHECK_EQUAL( id2
, ids
[6]);
352 BOOST_CHECK_EQUAL( id1
, ids
[7]);
353 BOOST_CHECK_EQUAL( id2
, ids
[8]);
354 BOOST_CHECK_EQUAL( id1
, ids
[9]);
355 BOOST_CHECK_EQUAL( id2
, ids
[10]);
356 BOOST_CHECK_EQUAL( id1
, ids
[11]);
359 void test_moveable() {
360 boost::fibers::unbuffered_channel
< moveable
> c
;
361 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
]{
363 BOOST_CHECK( m1
.state
);
364 BOOST_CHECK_EQUAL( 3, m1
.value
);
365 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( std::move( m1
) ) );
368 BOOST_CHECK( ! m2
.state
);
369 BOOST_CHECK_EQUAL( -1, m2
.value
);
370 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( m2
) );
371 BOOST_CHECK( m2
.state
);
372 BOOST_CHECK_EQUAL( 3, m2
.value
);
376 void test_rangefor() {
377 boost::fibers::unbuffered_channel
< int > chan
;
378 std::vector
< int > vec
;
379 boost::fibers::fiber
f1( boost::fibers::launch::dispatch
, [&chan
]{
389 boost::fibers::fiber
f2( boost::fibers::launch::dispatch
, [&vec
,&chan
]{
390 for ( int value
: chan
) {
391 vec
.push_back( value
);
396 BOOST_CHECK_EQUAL( 1, vec
[0]);
397 BOOST_CHECK_EQUAL( 1, vec
[1]);
398 BOOST_CHECK_EQUAL( 2, vec
[2]);
399 BOOST_CHECK_EQUAL( 3, vec
[3]);
400 BOOST_CHECK_EQUAL( 5, vec
[4]);
401 BOOST_CHECK_EQUAL( 8, vec
[5]);
402 BOOST_CHECK_EQUAL( 12, vec
[6]);
405 boost::unit_test::test_suite
* init_unit_test_suite( int, char* []) {
406 boost::unit_test::test_suite
* test
=
407 BOOST_TEST_SUITE("Boost.Fiber: unbuffered_channel test suite");
409 test
->add( BOOST_TEST_CASE( & test_push
) );
410 test
->add( BOOST_TEST_CASE( & test_push_closed
) );
411 test
->add( BOOST_TEST_CASE( & test_push_wait_for
) );
412 test
->add( BOOST_TEST_CASE( & test_push_wait_for_closed
) );
413 test
->add( BOOST_TEST_CASE( & test_push_wait_for_timeout
) );
414 test
->add( BOOST_TEST_CASE( & test_push_wait_until
) );
415 test
->add( BOOST_TEST_CASE( & test_push_wait_until_closed
) );
416 test
->add( BOOST_TEST_CASE( & test_push_wait_until_timeout
) );
417 test
->add( BOOST_TEST_CASE( & test_pop
) );
418 test
->add( BOOST_TEST_CASE( & test_pop_closed
) );
419 test
->add( BOOST_TEST_CASE( & test_pop_success
) );
420 test
->add( BOOST_TEST_CASE( & test_value_pop
) );
421 test
->add( BOOST_TEST_CASE( & test_value_pop_closed
) );
422 test
->add( BOOST_TEST_CASE( & test_value_pop_success
) );
423 test
->add( BOOST_TEST_CASE( & test_pop_wait_for
) );
424 test
->add( BOOST_TEST_CASE( & test_pop_wait_for_closed
) );
425 test
->add( BOOST_TEST_CASE( & test_pop_wait_for_success
) );
426 test
->add( BOOST_TEST_CASE( & test_pop_wait_for_timeout
) );
427 test
->add( BOOST_TEST_CASE( & test_pop_wait_until
) );
428 test
->add( BOOST_TEST_CASE( & test_pop_wait_until_closed
) );
429 test
->add( BOOST_TEST_CASE( & test_pop_wait_until_success
) );
430 test
->add( BOOST_TEST_CASE( & test_pop_wait_until_timeout
) );
431 test
->add( BOOST_TEST_CASE( & test_wm_1
) );
432 test
->add( BOOST_TEST_CASE( & test_moveable
) );
433 test
->add( BOOST_TEST_CASE( & test_rangefor
) );