]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/coroutine2/test/test_coroutine.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / coroutine2 / test / test_coroutine.cpp
CommitLineData
7c673cae
FG
1
2// Copyright Oliver Kowalke 2014.
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 <algorithm>
8#include <cstdio>
9#include <iostream>
10#include <sstream>
11#include <stdexcept>
12#include <string>
13#include <tuple>
14#include <vector>
15
16#include <boost/assert.hpp>
17#include <boost/test/unit_test.hpp>
18
19#include <boost/coroutine2/coroutine.hpp>
20
21namespace coro = boost::coroutines2;
22
23int value1 = 0;
24std::string value2 = "";
25bool value3 = false;
26double value4 = .0;
b32b8144 27int * value5 = nullptr;
7c673cae
FG
28int& value6 = value1;
29int& value7 = value1;
30int value8 = 0;
31int value9 = 0;
32
33struct X
34{
35 X() { value1 = 7; }
36 ~X() { value1 = 0; }
37
38 X( X const&) = delete;
39 X & operator=( X const&) = delete;
40};
41
42class copyable
43{
44public:
45 bool state;
46
47 copyable() :
48 state( false)
49 {}
50
51 copyable( int) :
52 state( true)
53 {}
54
55 void operator()( coro::coroutine< int >::push_type &)
56 { value3 = state; }
57};
58
59class moveable
60{
61public:
62 bool state;
63
64 moveable() :
65 state( false)
66 {}
67
68 moveable( int) :
69 state( true)
70 {}
71
72 moveable( moveable const&) = delete;
73 moveable & operator=( moveable const&) = delete;
74
75 moveable( moveable && other) :
76 state( false)
77 { std::swap( state, other.state); }
78
79 moveable & operator=( moveable && other)
80 {
81 if ( this != & other) {
82 state = other.state;
83 other.state = false;
84 }
85 return * this;
86 }
87
88 void operator()( coro::coroutine< int >::push_type &)
89 { value3 = state; }
90};
91
92class movedata
93{
94public:
95 int i;
96
97 movedata( int i_) :
98 i( i_)
99 {}
100
101 movedata( movedata const&) = delete;
102 movedata & operator=( movedata const&) = delete;
103
104 movedata( movedata && other) :
105 i( 0)
106 { std::swap( i, other.i); }
107
108 movedata & operator=( movedata && other)
109 {
110 if ( this != & other) {
111 i = other.i;
112 other.i = 0;
113 }
114 return * this;
115 }
116};
117
118struct my_exception {};
119
120void f1( coro::coroutine< void >::push_type & c)
121{
122 while ( c)
123 c();
124}
125
126void f2( coro::coroutine< void >::push_type &)
127{ ++value1; }
128
129void f3( coro::coroutine< void >::push_type & c)
130{
131 ++value1;
132 c();
133 ++value1;
134}
135
136void f4( coro::coroutine< int >::push_type & c)
137{
138 c( 3);
139 c( 7);
140}
141
142void f5( coro::coroutine< std::string >::push_type & c)
143{
144 std::string res("abc");
145 c( res);
146 res = "xyz";
147 c( res);
148}
149
150void f6( coro::coroutine< int >::pull_type & c)
151{ value1 = c.get(); }
152
153void f7( coro::coroutine< std::string >::pull_type & c)
154{ value2 = c.get(); }
155
156void f8( coro::coroutine< std::tuple< double, double > >::pull_type & c)
157{
158 double x = 0, y = 0;
159 std::tie( x, y) = c.get();
160 value4 = x + y;
161 c();
162 std::tie( x, y) = c.get();
163 value4 = x + y;
164}
165
166void f9( coro::coroutine< int * >::pull_type & c)
167{ value5 = c.get(); }
168
169void f91( coro::coroutine< int const* >::pull_type & c)
170{ value5 = const_cast< int * >( c.get() ); }
171
172void f10( coro::coroutine< int & >::pull_type & c)
173{
b32b8144 174 int & i = c.get();
7c673cae
FG
175 value5 = const_cast< int * >( & i);
176}
177
178void f101( coro::coroutine< int const& >::pull_type & c)
179{
180 int const& i = c.get();
181 value5 = const_cast< int * >( & i);
182}
183
184void f11( coro::coroutine< std::tuple< int, int > >::pull_type & c)
185{
186 std::tie( value8, value9) = c.get();
187}
188
189void f12( coro::coroutine< void >::pull_type & c)
190{
191 value1 = 7;
192 X x_;
193 c();
194 c();
195}
196
197void f16( coro::coroutine< int >::push_type & c)
198{
199 c( 1);
200 c( 2);
201 c( 3);
202 c( 4);
203 c( 5);
204}
205
206void f17( coro::coroutine< int >::pull_type & c, std::vector< int > & vec)
207{
208 int x = c.get();
209 while ( 5 > x)
210 {
211 vec.push_back( x);
212 x = c().get();
213 }
214}
215
216void f20( coro::coroutine< int >::push_type &)
217{}
218
219void f21( coro::coroutine< int >::pull_type & c)
220{
221 while ( c)
222 {
223 value1 = c.get();
224 c();
225 }
226}
227
228void f22( coro::coroutine< movedata >::pull_type & c)
229{
230 movedata mv( c.get() );
231 value1 = mv.i;
232}
233
234void test_move()
235{
236 {
237 coro::coroutine< int >::pull_type coro1( f20);
238 coro::coroutine< int >::pull_type coro2( f16);
239 BOOST_CHECK( ! coro1);
240 BOOST_CHECK( coro2);
241 BOOST_CHECK_EQUAL( 1, coro2.get() );
242 coro2();
243 BOOST_CHECK_EQUAL( 2, coro2.get() );
244 coro1 = std::move( coro2);
245 BOOST_CHECK( coro1);
246 BOOST_CHECK( ! coro2);
247 coro1();
248 BOOST_CHECK_EQUAL( 3, coro1.get() );
249 BOOST_CHECK( ! coro2);
250 }
251
252 {
253 value3 = false;
254 copyable cp( 3);
255 BOOST_CHECK( cp.state);
256 BOOST_CHECK( ! value3);
257 coro::coroutine< int >::pull_type coro( cp);
258 BOOST_CHECK( cp.state);
259 BOOST_CHECK( value3);
260 }
261
262 {
263 value3 = false;
264 moveable mv( 7);
265 BOOST_CHECK( mv.state);
266 BOOST_CHECK( ! value3);
267 coro::coroutine< int >::pull_type coro( std::move( mv) );
268 BOOST_CHECK( ! mv.state);
269 BOOST_CHECK( value3);
270 }
271
272 {
273 value1 = 0;
274 movedata mv( 7);
275 BOOST_CHECK_EQUAL( 0, value1);
276 BOOST_CHECK_EQUAL( 7, mv.i);
277 coro::coroutine< movedata >::push_type coro( f22);
278 coro( std::move( mv) );
279 BOOST_CHECK_EQUAL( 7, value1);
280 BOOST_CHECK_EQUAL( 0, mv.i);
281 }
282}
283
284void test_complete()
285{
286 value1 = 0;
287
288 coro::coroutine< void >::pull_type coro( f2);
289 BOOST_CHECK( ! coro);
290 BOOST_CHECK_EQUAL( ( int)1, value1);
291}
292
b32b8144
FG
293void test_bind()
294{
295 value1 = 0;
296
297 coro::coroutine< void >::pull_type coro( std::bind( f2, std::placeholders::_1) );
298 BOOST_CHECK( ! coro);
299 BOOST_CHECK_EQUAL( ( int)1, value1);
300}
301
7c673cae
FG
302void test_jump()
303{
304 value1 = 0;
305
306 coro::coroutine< void >::pull_type coro( f3);
307 BOOST_CHECK( coro);
308 BOOST_CHECK_EQUAL( ( int)1, value1);
309 coro();
310 BOOST_CHECK( ! coro);
311 BOOST_CHECK_EQUAL( ( int)2, value1);
312}
313
314void test_result_int()
315{
316 coro::coroutine< int >::pull_type coro( f4);
317 BOOST_CHECK( coro);
318 int result = coro.get();
319 BOOST_CHECK( coro);
320 BOOST_CHECK_EQUAL( 3, result);
321 result = coro().get();
322 BOOST_CHECK( coro);
323 BOOST_CHECK_EQUAL( 7, result);
324 coro();
325 BOOST_CHECK( ! coro);
326}
327
328void test_result_string()
329{
330 coro::coroutine< std::string >::pull_type coro( f5);
331 BOOST_CHECK( coro);
332 std::string result = coro.get();
333 BOOST_CHECK( coro);
334 BOOST_CHECK_EQUAL( std::string("abc"), result);
335 result = coro().get();
336 BOOST_CHECK( coro);
337 BOOST_CHECK_EQUAL( std::string("xyz"), result);
338 coro();
339 BOOST_CHECK( ! coro);
340}
341
342void test_arg_int()
343{
344 value1 = 0;
345
346 coro::coroutine< int >::push_type coro( f6);
347 BOOST_CHECK( coro);
348 coro( 3);
349 BOOST_CHECK( ! coro);
350 BOOST_CHECK_EQUAL( 3, value1);
351}
352
353void test_arg_string()
354{
355 value2 = "";
356
357 coro::coroutine< std::string >::push_type coro( f7);
358 BOOST_CHECK( coro);
359 coro( std::string("abc") );
360 BOOST_CHECK( ! coro);
361 BOOST_CHECK_EQUAL( std::string("abc"), value2);
362}
363
364void test_fp()
365{
366 value4 = 0;
367
368 coro::coroutine< std::tuple< double, double > >::push_type coro( f8);
369 BOOST_CHECK( coro);
370 coro( std::make_tuple( 7.35, 3.14) );
371 BOOST_CHECK( coro);
372 BOOST_CHECK_EQUAL( ( double) 10.49, value4);
373
374 value4 = 0;
375 coro( std::make_tuple( 1.15, 3.14) );
376 BOOST_CHECK( ! coro);
377 BOOST_CHECK_EQUAL( ( double) 4.29, value4);
378}
379
380void test_ptr()
381{
b32b8144 382 value5 = nullptr;
7c673cae
FG
383
384 int a = 3;
385 coro::coroutine< int * >::push_type coro( f9);
386 BOOST_CHECK( coro);
387 coro( & a);
388 BOOST_CHECK( ! coro);
389 BOOST_CHECK_EQUAL( & a, value5);
390}
391
392void test_const_ptr()
393{
b32b8144 394 value5 = nullptr;
7c673cae
FG
395
396 int a = 3;
397 coro::coroutine< int const* >::push_type coro( f91);
398 BOOST_CHECK( coro);
399 coro( & a);
400 BOOST_CHECK( ! coro);
401 BOOST_CHECK_EQUAL( & a, value5);
402}
403
404void test_ref()
405{
b32b8144 406 value5 = nullptr;
7c673cae 407
b32b8144
FG
408 int a_ = 3;
409 int & a = a_;
7c673cae
FG
410 coro::coroutine< int & >::push_type coro( f10);
411 BOOST_CHECK( coro);
b32b8144 412 coro( std::ref( a) );
7c673cae
FG
413 BOOST_CHECK( ! coro);
414 BOOST_CHECK_EQUAL( & a, value5);
415}
416
417void test_const_ref()
418{
b32b8144 419 value5 = nullptr;
7c673cae
FG
420
421 int a = 3;
422 coro::coroutine< int const& >::push_type coro( f101);
423 BOOST_CHECK( coro);
424 coro( a);
425 BOOST_CHECK( ! coro);
426 BOOST_CHECK_EQUAL( & a, value5);
427}
428
429void test_no_result()
430{
431 coro::coroutine< int >::pull_type coro( f20);
432 BOOST_CHECK( ! coro);
433}
434
435void test_tuple()
436{
437 value8 = 0;
438 value9 = 0;
439
440 int a = 3, b = 7;
441 std::tuple< int, int > tpl( a, b);
442 BOOST_CHECK_EQUAL( a, std::get< 0 >( tpl) );
443 BOOST_CHECK_EQUAL( b, std::get< 1 >( tpl) );
444 coro::coroutine< std::tuple< int, int > >::push_type coro( f11);
445 BOOST_CHECK( coro);
446 coro( tpl);
447 BOOST_CHECK( ! coro);
448 BOOST_CHECK_EQUAL( a, value8);
449 BOOST_CHECK_EQUAL( b, value9);
450}
451
452void test_unwind()
453{
454 value1 = 0;
455 {
456 coro::coroutine< void >::push_type coro( f12);
457 BOOST_CHECK( coro);
458 BOOST_CHECK_EQUAL( ( int) 0, value1);
459 coro();
460 BOOST_CHECK( coro);
461 BOOST_CHECK_EQUAL( ( int) 7, value1);
462 coro();
463 BOOST_CHECK_EQUAL( ( int) 7, value1);
464 }
465 BOOST_CHECK_EQUAL( ( int) 0, value1);
466 int i = 0;
467 {
468 coro::coroutine< void >::push_type coro(
469 [&i](coro::coroutine< void >::pull_type &) mutable {
470 i = 7;
471 });
472 }
b32b8144
FG
473 {
474 BOOST_CHECK_EQUAL( ( int) 0, value1);
475 auto * coro = new coro::coroutine< void >::pull_type(
476 [](coro::coroutine< void >::push_type & coro) mutable {
477 X x;
478 coro();
479 });
480 BOOST_CHECK_EQUAL( ( int) 7, value1);
481 delete coro;
482 BOOST_CHECK_EQUAL( ( int) 0, value1);
483 }
484 {
485 BOOST_CHECK_EQUAL( ( int) 0, value1);
486 auto * coro = new coro::coroutine< void >::push_type(
487 [](coro::coroutine< void >::pull_type & coro) mutable {
488 X x;
489 coro();
490 });
491 ( * coro)();
492 BOOST_CHECK_EQUAL( ( int) 7, value1);
493 delete coro;
494 BOOST_CHECK_EQUAL( ( int) 0, value1);
495 }
7c673cae
FG
496}
497
498void test_exceptions()
499{
500 std::string msg("abc"), value;
501 std::runtime_error ex( msg);
502 try
503 {
504 coro::coroutine< void >::push_type coro(
505 [&msg]( coro::coroutine< void >::pull_type &) {
506 throw std::runtime_error( msg);
507 });
508 BOOST_CHECK( coro);
509 coro();
510 BOOST_CHECK( ! coro);
511 BOOST_CHECK( false);
512 }
513 catch ( std::runtime_error const& ex)
514 { value = ex.what(); }
515 BOOST_CHECK_EQUAL( value, msg);
516}
517
518void test_input_iterator()
519{
520 {
521 using std::begin;
522 using std::end;
523
524 std::vector< int > vec;
525 coro::coroutine< int >::pull_type coro( f16);
526 coro::coroutine< int >::pull_type::iterator e = end( coro);
527 for (
528 coro::coroutine< int >::pull_type::iterator i = begin( coro);
529 i != e; ++i)
530 { vec.push_back( * i); }
531 BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
532 BOOST_CHECK_EQUAL( ( int)1, vec[0] );
533 BOOST_CHECK_EQUAL( ( int)2, vec[1] );
534 BOOST_CHECK_EQUAL( ( int)3, vec[2] );
535 BOOST_CHECK_EQUAL( ( int)4, vec[3] );
536 BOOST_CHECK_EQUAL( ( int)5, vec[4] );
537 }
538 {
539 std::vector< int > vec;
540 coro::coroutine< int >::pull_type coro( f16);
541 for ( auto i : coro)
542 { vec.push_back( i); }
543 BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
544 BOOST_CHECK_EQUAL( ( int)1, vec[0] );
545 BOOST_CHECK_EQUAL( ( int)2, vec[1] );
546 BOOST_CHECK_EQUAL( ( int)3, vec[2] );
547 BOOST_CHECK_EQUAL( ( int)4, vec[3] );
548 BOOST_CHECK_EQUAL( ( int)5, vec[4] );
549 }
550 {
551 int i1 = 1, i2 = 2, i3 = 3;
552 coro::coroutine< int& >::pull_type coro(
553 [&i1,&i2,&i3](coro::coroutine< int& >::push_type & c){
554 c( i1);
555 c( i2);
556 c( i3);
557 });
558
559 int counter = 1;
560 for ( int & i : coro) {
561 switch ( counter) {
562 case 1:
563 BOOST_CHECK_EQUAL( & i1, & i);
564 break;
565 case 2:
566 BOOST_CHECK_EQUAL( & i2, & i);
567 break;
568 case 3:
569 BOOST_CHECK_EQUAL( & i3, & i);
570 break;
571 default:
572 BOOST_ASSERT( false);
573 }
574 ++counter;
575 }
576 }
577}
578
579void test_output_iterator()
580{
581 using std::begin;
582 using std::end;
583
584 int counter = 0;
585 std::vector< int > vec;
586 coro::coroutine< int >::push_type coro(
587 [&vec]( coro::coroutine< int >::pull_type & c) {
588 int x = c.get();
589 while ( 5 > x)
590 {
591 vec.push_back( x);
592 x = c().get();
593 }
594 });
7c673cae
FG
595 coro::coroutine< int >::push_type::iterator e( end( coro) );
596 for ( coro::coroutine< int >::push_type::iterator i( begin( coro) );
597 i != e; ++i)
598 {
599 i = ++counter;
600 }
601 BOOST_CHECK_EQUAL( ( std::size_t)4, vec.size() );
602 BOOST_CHECK_EQUAL( ( int)1, vec[0] );
603 BOOST_CHECK_EQUAL( ( int)2, vec[1] );
604 BOOST_CHECK_EQUAL( ( int)3, vec[2] );
605 BOOST_CHECK_EQUAL( ( int)4, vec[3] );
606}
607
608std::vector< int > vec;
609coro::coroutine< void >::pull_type * child = nullptr;
610
611void start_child_coroutine() {
612 child = new coro::coroutine< void >::pull_type([](coro::coroutine< void >::push_type & yield) {
613 vec.push_back( 2);
614 yield();
615 vec.push_back( 2);
616 yield();
617 vec.push_back( 2);
618 yield();
619 vec.push_back( 2);
620 yield();
621 vec.push_back( 2);
622 yield();
623 vec.push_back( 2);
624 });
625}
626
627coro::coroutine< void >::pull_type start_parent_coroutine() {
628 return coro::coroutine< void >::pull_type([=](coro::coroutine< void >::push_type & yield) {
629 vec.push_back( 1);
630 start_child_coroutine();
631 yield();
632 vec.push_back( 1);
633 });
634}
635
636void test_chaining()
637{
638 auto parent = start_parent_coroutine();
639 while ( * child) {
640 ( * child)();
641 }
642 BOOST_CHECK_EQUAL( 7, vec.size() );
643 BOOST_CHECK_EQUAL( 1, vec[0]);
644 BOOST_CHECK_EQUAL( 2, vec[1]);
645 BOOST_CHECK_EQUAL( 2, vec[2]);
646 BOOST_CHECK_EQUAL( 2, vec[3]);
647 BOOST_CHECK_EQUAL( 2, vec[4]);
648 BOOST_CHECK_EQUAL( 2, vec[5]);
649 BOOST_CHECK_EQUAL( 2, vec[6]);
650}
651
652boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
653{
654 boost::unit_test::test_suite * test =
655 BOOST_TEST_SUITE("Boost.Coroutine2: coroutine test suite");
656
657 test->add( BOOST_TEST_CASE( & test_move) );
658 test->add( BOOST_TEST_CASE( & test_complete) );
b32b8144 659 test->add( BOOST_TEST_CASE( & test_bind) );
7c673cae
FG
660 test->add( BOOST_TEST_CASE( & test_jump) );
661 test->add( BOOST_TEST_CASE( & test_result_int) );
662 test->add( BOOST_TEST_CASE( & test_result_string) );
663 test->add( BOOST_TEST_CASE( & test_arg_int) );
664 test->add( BOOST_TEST_CASE( & test_arg_string) );
665 test->add( BOOST_TEST_CASE( & test_fp) );
666 test->add( BOOST_TEST_CASE( & test_ptr) );
667 test->add( BOOST_TEST_CASE( & test_const_ptr) );
668 test->add( BOOST_TEST_CASE( & test_no_result) );
669 test->add( BOOST_TEST_CASE( & test_ref) );
670 test->add( BOOST_TEST_CASE( & test_const_ref) );
671 test->add( BOOST_TEST_CASE( & test_tuple) );
672 test->add( BOOST_TEST_CASE( & test_unwind) );
673 test->add( BOOST_TEST_CASE( & test_exceptions) );
674 test->add( BOOST_TEST_CASE( & test_input_iterator) );
675 test->add( BOOST_TEST_CASE( & test_output_iterator) );
676 test->add( BOOST_TEST_CASE( & test_chaining) );
677
678 return test;
679}