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;
51 boost::fibers::buffered_channel
< int > c( 0);
52 } catch ( boost::fibers::fiber_error
const&) {
59 boost::fibers::buffered_channel
< int > c( 16);
60 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 1) );
63 void test_push_closed() {
64 boost::fibers::buffered_channel
< int > c( 16);
66 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.push( 1) );
69 void test_try_push() {
70 boost::fibers::buffered_channel
< int > c( 2);
71 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 1) );
74 void test_try_push_closed() {
75 boost::fibers::buffered_channel
< int > c( 2);
76 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.try_push( 1) );
78 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.try_push( 2) );
81 void test_try_push_full() {
82 boost::fibers::buffered_channel
< int > c( 2);
83 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.try_push( 1) );
84 BOOST_CHECK( boost::fibers::channel_op_status::full
== c
.try_push( 1) );
87 void test_push_wait_for() {
88 boost::fibers::buffered_channel
< int > c( 2);
89 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push_wait_for( 1, std::chrono::seconds( 1) ) );
92 void test_push_wait_for_closed() {
93 boost::fibers::buffered_channel
< int > c( 2);
95 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.push_wait_for( 1, std::chrono::seconds( 1) ) );
98 void test_push_wait_for_timeout() {
99 boost::fibers::buffered_channel
< int > c( 2);
100 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push_wait_for( 1, std::chrono::seconds( 1) ) );
101 BOOST_CHECK( boost::fibers::channel_op_status::timeout
== c
.push_wait_for( 1, std::chrono::seconds( 1) ) );
104 void test_push_wait_until() {
105 boost::fibers::buffered_channel
< int > c( 2);
106 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push_wait_until( 1,
107 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
110 void test_push_wait_until_closed() {
111 boost::fibers::buffered_channel
< int > c( 2);
113 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.push_wait_until( 1,
114 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
117 void test_push_wait_until_timeout() {
118 boost::fibers::buffered_channel
< int > c( 2);
119 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push_wait_until( 1,
120 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
121 BOOST_CHECK( boost::fibers::channel_op_status::timeout
== c
.push_wait_until( 1,
122 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
126 boost::fibers::buffered_channel
< int > c( 16);
128 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
129 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( v2
) );
130 BOOST_CHECK_EQUAL( v1
, v2
);
133 void test_pop_closed() {
134 boost::fibers::buffered_channel
< int > c( 16);
136 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
138 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( v2
) );
139 BOOST_CHECK_EQUAL( v1
, v2
);
140 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.pop( v2
) );
143 void test_pop_success() {
144 boost::fibers::buffered_channel
< int > c( 16);
146 boost::fibers::fiber
f1( boost::fibers::launch::dispatch
, [&c
,&v2
](){
147 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( v2
) );
149 boost::fibers::fiber
f2( boost::fibers::launch::dispatch
, [&c
,v1
](){
150 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
154 BOOST_CHECK_EQUAL( v1
, v2
);
157 void test_value_pop() {
158 boost::fibers::buffered_channel
< int > c( 16);
160 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
162 BOOST_CHECK_EQUAL( v1
, v2
);
165 void test_value_pop_closed() {
166 boost::fibers::buffered_channel
< int > c( 16);
168 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
171 BOOST_CHECK_EQUAL( v1
, v2
);
175 } catch ( boost::fibers::fiber_error
const&) {
178 BOOST_CHECK( thrown
);
181 void test_value_pop_success() {
182 boost::fibers::buffered_channel
< int > c( 16);
184 boost::fibers::fiber
f1( boost::fibers::launch::dispatch
, [&c
,&v2
](){
187 boost::fibers::fiber
f2( boost::fibers::launch::dispatch
, [&c
,v1
](){
188 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
192 BOOST_CHECK_EQUAL( v1
, v2
);
195 void test_try_pop() {
196 boost::fibers::buffered_channel
< int > c( 16);
198 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
199 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.try_pop( v2
) );
200 BOOST_CHECK_EQUAL( v1
, v2
);
203 void test_try_pop_closed() {
204 boost::fibers::buffered_channel
< int > c( 16);
206 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
208 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.try_pop( v2
) );
209 BOOST_CHECK_EQUAL( v1
, v2
);
210 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.try_pop( v2
) );
213 void test_try_pop_success() {
214 boost::fibers::buffered_channel
< int > c( 16);
216 boost::fibers::fiber
f1( boost::fibers::launch::dispatch
, [&c
,&v2
](){
217 while ( boost::fibers::channel_op_status::success
!= c
.try_pop( v2
) ) {
218 boost::this_fiber::yield();
221 boost::fibers::fiber
f2( boost::fibers::launch::dispatch
, [&c
,v1
](){
222 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
226 BOOST_CHECK_EQUAL( v1
, v2
);
229 void test_pop_wait_for() {
230 boost::fibers::buffered_channel
< int > c( 16);
232 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
233 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_for( v2
, std::chrono::seconds( 1) ) );
234 BOOST_CHECK_EQUAL( v1
, v2
);
237 void test_pop_wait_for_closed() {
238 boost::fibers::buffered_channel
< int > c( 16);
240 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
242 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_for( v2
, std::chrono::seconds( 1) ) );
243 BOOST_CHECK_EQUAL( v1
, v2
);
244 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.pop_wait_for( v2
, std::chrono::seconds( 1) ) );
247 void test_pop_wait_for_success() {
248 boost::fibers::buffered_channel
< int > c( 16);
250 boost::fibers::fiber
f1( boost::fibers::launch::dispatch
, [&c
,&v2
](){
251 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_for( v2
, std::chrono::seconds( 1) ) );
253 boost::fibers::fiber
f2( boost::fibers::launch::dispatch
, [&c
,v1
](){
254 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
258 BOOST_CHECK_EQUAL( v1
, v2
);
261 void test_pop_wait_for_timeout() {
262 boost::fibers::buffered_channel
< int > c( 16);
264 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v
](){
265 BOOST_CHECK( boost::fibers::channel_op_status::timeout
== c
.pop_wait_for( v
, std::chrono::seconds( 1) ) );
270 void test_pop_wait_until() {
271 boost::fibers::buffered_channel
< int > c( 16);
273 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
274 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_until( v2
,
275 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
276 BOOST_CHECK_EQUAL( v1
, v2
);
279 void test_pop_wait_until_closed() {
280 boost::fibers::buffered_channel
< int > c( 16);
282 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
284 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_until( v2
,
285 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
286 BOOST_CHECK_EQUAL( v1
, v2
);
287 BOOST_CHECK( boost::fibers::channel_op_status::closed
== c
.pop_wait_until( v2
,
288 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
291 void test_pop_wait_until_success() {
292 boost::fibers::buffered_channel
< int > c( 16);
294 boost::fibers::fiber
f1( boost::fibers::launch::dispatch
, [&c
,&v2
](){
295 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop_wait_until( v2
,
296 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
298 boost::fibers::fiber
f2( boost::fibers::launch::dispatch
, [&c
,v1
](){
299 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( v1
) );
303 BOOST_CHECK_EQUAL( v1
, v2
);
306 void test_pop_wait_until_timeout() {
307 boost::fibers::buffered_channel
< int > c( 16);
309 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, [&c
,&v
](){
310 BOOST_CHECK( boost::fibers::channel_op_status::timeout
== c
.pop_wait_until( v
,
311 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
317 boost::fibers::buffered_channel
< int > c( 4);
318 std::vector
< boost::fibers::fiber::id
> ids
;
319 boost::fibers::fiber
f1( boost::fibers::launch::dispatch
, [&c
,&ids
](){
320 ids
.push_back( boost::this_fiber::get_id() );
321 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 1) );
323 ids
.push_back( boost::this_fiber::get_id() );
324 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 2) );
326 ids
.push_back( boost::this_fiber::get_id() );
327 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 3) );
329 ids
.push_back( boost::this_fiber::get_id() );
330 // would be blocked because channel is full
331 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 4) );
333 ids
.push_back( boost::this_fiber::get_id() );
334 // would be blocked because channel is full
335 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 5) );
337 ids
.push_back( boost::this_fiber::get_id() );
339 boost::fibers::fiber
f2( boost::fibers::launch::dispatch
, [&c
,&ids
](){
340 ids
.push_back( boost::this_fiber::get_id() );
341 BOOST_CHECK_EQUAL( 1, c
.value_pop() );
343 // let other fiber run
344 boost::this_fiber::yield();
346 ids
.push_back( boost::this_fiber::get_id() );
347 BOOST_CHECK_EQUAL( 2, c
.value_pop() );
349 ids
.push_back( boost::this_fiber::get_id() );
350 BOOST_CHECK_EQUAL( 3, c
.value_pop() );
352 ids
.push_back( boost::this_fiber::get_id() );
353 BOOST_CHECK_EQUAL( 4, c
.value_pop() );
355 ids
.push_back( boost::this_fiber::get_id() );
356 // would block because channel is empty
357 BOOST_CHECK_EQUAL( 5, c
.value_pop() );
359 ids
.push_back( boost::this_fiber::get_id() );
361 boost::fibers::fiber::id id1
= f1
.get_id();
362 boost::fibers::fiber::id id2
= f2
.get_id();
365 BOOST_CHECK_EQUAL( 12u, ids
.size() );
366 BOOST_CHECK_EQUAL( id1
, ids
[0]);
367 BOOST_CHECK_EQUAL( id1
, ids
[1]);
368 BOOST_CHECK_EQUAL( id1
, ids
[2]);
369 BOOST_CHECK_EQUAL( id1
, ids
[3]);
370 BOOST_CHECK_EQUAL( id2
, ids
[4]);
371 BOOST_CHECK_EQUAL( id1
, ids
[5]);
372 BOOST_CHECK_EQUAL( id2
, ids
[6]);
373 BOOST_CHECK_EQUAL( id2
, ids
[7]);
374 BOOST_CHECK_EQUAL( id2
, ids
[8]);
375 BOOST_CHECK_EQUAL( id2
, ids
[9]);
376 BOOST_CHECK_EQUAL( id1
, ids
[10]);
377 BOOST_CHECK_EQUAL( id2
, ids
[11]);
381 boost::fibers::buffered_channel
< int > c( 4);
382 std::vector
< boost::fibers::fiber::id
> ids
;
383 boost::fibers::fiber
f1( boost::fibers::launch::dispatch
, [&c
,&ids
](){
384 ids
.push_back( boost::this_fiber::get_id() );
385 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 1) );
387 ids
.push_back( boost::this_fiber::get_id() );
388 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 2) );
390 ids
.push_back( boost::this_fiber::get_id() );
391 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 3) );
393 ids
.push_back( boost::this_fiber::get_id() );
394 // would be blocked because channel is full
395 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 4) );
397 ids
.push_back( boost::this_fiber::get_id() );
398 // would be blocked because channel is full
399 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( 5) );
401 ids
.push_back( boost::this_fiber::get_id() );
403 boost::fibers::fiber
f2( boost::fibers::launch::dispatch
, [&c
,&ids
](){
404 ids
.push_back( boost::this_fiber::get_id() );
405 BOOST_CHECK_EQUAL( 1, c
.value_pop() );
407 // let other fiber run
408 boost::this_fiber::yield();
410 ids
.push_back( boost::this_fiber::get_id() );
411 BOOST_CHECK_EQUAL( 2, c
.value_pop() );
413 // let other fiber run
414 boost::this_fiber::yield();
416 ids
.push_back( boost::this_fiber::get_id() );
417 BOOST_CHECK_EQUAL( 3, c
.value_pop() );
419 ids
.push_back( boost::this_fiber::get_id() );
420 BOOST_CHECK_EQUAL( 4, c
.value_pop() );
422 ids
.push_back( boost::this_fiber::get_id() );
423 BOOST_CHECK_EQUAL( 5, c
.value_pop() );
425 ids
.push_back( boost::this_fiber::get_id() );
427 boost::fibers::fiber::id id1
= f1
.get_id();
428 boost::fibers::fiber::id id2
= f2
.get_id();
431 BOOST_CHECK_EQUAL( (std::size_t)12, ids
.size() );
432 BOOST_CHECK_EQUAL( id1
, ids
[0]);
433 BOOST_CHECK_EQUAL( id1
, ids
[1]);
434 BOOST_CHECK_EQUAL( id1
, ids
[2]);
435 BOOST_CHECK_EQUAL( id1
, ids
[3]);
436 BOOST_CHECK_EQUAL( id2
, ids
[4]);
437 BOOST_CHECK_EQUAL( id1
, ids
[5]);
438 BOOST_CHECK_EQUAL( id2
, ids
[6]);
439 BOOST_CHECK_EQUAL( id1
, ids
[7]);
440 BOOST_CHECK_EQUAL( id2
, ids
[8]);
441 BOOST_CHECK_EQUAL( id2
, ids
[9]);
442 BOOST_CHECK_EQUAL( id2
, ids
[10]);
443 BOOST_CHECK_EQUAL( id2
, ids
[11]);
446 void test_moveable() {
447 boost::fibers::buffered_channel
< moveable
> c( 16);
449 BOOST_CHECK( m1
.state
);
450 BOOST_CHECK_EQUAL( 3, m1
.value
);
451 BOOST_CHECK( ! m2
.state
);
452 BOOST_CHECK_EQUAL( -1, m2
.value
);
453 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.push( std::move( m1
) ) );
454 BOOST_CHECK( ! m1
.state
);
455 BOOST_CHECK( ! m2
.state
);
456 BOOST_CHECK( boost::fibers::channel_op_status::success
== c
.pop( m2
) );
457 BOOST_CHECK( ! m1
.state
);
458 BOOST_CHECK_EQUAL( -1, m1
.value
);
459 BOOST_CHECK( m2
.state
);
460 BOOST_CHECK_EQUAL( 3, m2
.value
);
463 void test_rangefor() {
464 boost::fibers::buffered_channel
< int > chan
{ 4 };
465 std::vector
< int > vec
;
466 boost::fibers::fiber
f1( boost::fibers::launch::dispatch
, [&chan
]{
476 boost::fibers::fiber
f2( boost::fibers::launch::dispatch
, [&vec
,&chan
]{
477 for ( int value
: chan
) {
478 vec
.push_back( value
);
483 BOOST_CHECK_EQUAL( 1, vec
[0]);
484 BOOST_CHECK_EQUAL( 1, vec
[1]);
485 BOOST_CHECK_EQUAL( 2, vec
[2]);
486 BOOST_CHECK_EQUAL( 3, vec
[3]);
487 BOOST_CHECK_EQUAL( 5, vec
[4]);
488 BOOST_CHECK_EQUAL( 8, vec
[5]);
489 BOOST_CHECK_EQUAL( 12, vec
[6]);
492 boost::unit_test::test_suite
* init_unit_test_suite( int, char* []) {
493 boost::unit_test::test_suite
* test
=
494 BOOST_TEST_SUITE("Boost.Fiber: buffered_channel test suite");
496 test
->add( BOOST_TEST_CASE( & test_zero_wm
) );
497 test
->add( BOOST_TEST_CASE( & test_push
) );
498 test
->add( BOOST_TEST_CASE( & test_push_closed
) );
499 test
->add( BOOST_TEST_CASE( & test_try_push
) );
500 test
->add( BOOST_TEST_CASE( & test_try_push_closed
) );
501 test
->add( BOOST_TEST_CASE( & test_try_push_full
) );
502 test
->add( BOOST_TEST_CASE( & test_push_wait_for
) );
503 test
->add( BOOST_TEST_CASE( & test_push_wait_for_closed
) );
504 test
->add( BOOST_TEST_CASE( & test_push_wait_for_timeout
) );
505 test
->add( BOOST_TEST_CASE( & test_push_wait_until
) );
506 test
->add( BOOST_TEST_CASE( & test_push_wait_until_closed
) );
507 test
->add( BOOST_TEST_CASE( & test_push_wait_until_timeout
) );
508 test
->add( BOOST_TEST_CASE( & test_pop
) );
509 test
->add( BOOST_TEST_CASE( & test_pop_closed
) );
510 test
->add( BOOST_TEST_CASE( & test_pop_success
) );
511 test
->add( BOOST_TEST_CASE( & test_value_pop
) );
512 test
->add( BOOST_TEST_CASE( & test_value_pop_closed
) );
513 test
->add( BOOST_TEST_CASE( & test_value_pop_success
) );
514 test
->add( BOOST_TEST_CASE( & test_try_pop
) );
515 test
->add( BOOST_TEST_CASE( & test_try_pop_closed
) );
516 test
->add( BOOST_TEST_CASE( & test_try_pop_success
) );
517 test
->add( BOOST_TEST_CASE( & test_pop_wait_for
) );
518 test
->add( BOOST_TEST_CASE( & test_pop_wait_for_closed
) );
519 test
->add( BOOST_TEST_CASE( & test_pop_wait_for_success
) );
520 test
->add( BOOST_TEST_CASE( & test_pop_wait_for_timeout
) );
521 test
->add( BOOST_TEST_CASE( & test_pop_wait_until
) );
522 test
->add( BOOST_TEST_CASE( & test_pop_wait_until_closed
) );
523 test
->add( BOOST_TEST_CASE( & test_pop_wait_until_success
) );
524 test
->add( BOOST_TEST_CASE( & test_pop_wait_until_timeout
) );
525 test
->add( BOOST_TEST_CASE( & test_wm_1
) );
526 test
->add( BOOST_TEST_CASE( & test_wm_2
) );
527 test
->add( BOOST_TEST_CASE( & test_moveable
) );
528 test
->add( BOOST_TEST_CASE( & test_rangefor
) );