]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/coroutine2/test/test_coroutine.cpp
add subtree-ish sources for 12.0.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;
27int * value5 = 0;
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{
174 int const& i = c.get();
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
293void test_jump()
294{
295 value1 = 0;
296
297 coro::coroutine< void >::pull_type coro( f3);
298 BOOST_CHECK( coro);
299 BOOST_CHECK_EQUAL( ( int)1, value1);
300 coro();
301 BOOST_CHECK( ! coro);
302 BOOST_CHECK_EQUAL( ( int)2, value1);
303}
304
305void test_result_int()
306{
307 coro::coroutine< int >::pull_type coro( f4);
308 BOOST_CHECK( coro);
309 int result = coro.get();
310 BOOST_CHECK( coro);
311 BOOST_CHECK_EQUAL( 3, result);
312 result = coro().get();
313 BOOST_CHECK( coro);
314 BOOST_CHECK_EQUAL( 7, result);
315 coro();
316 BOOST_CHECK( ! coro);
317}
318
319void test_result_string()
320{
321 coro::coroutine< std::string >::pull_type coro( f5);
322 BOOST_CHECK( coro);
323 std::string result = coro.get();
324 BOOST_CHECK( coro);
325 BOOST_CHECK_EQUAL( std::string("abc"), result);
326 result = coro().get();
327 BOOST_CHECK( coro);
328 BOOST_CHECK_EQUAL( std::string("xyz"), result);
329 coro();
330 BOOST_CHECK( ! coro);
331}
332
333void test_arg_int()
334{
335 value1 = 0;
336
337 coro::coroutine< int >::push_type coro( f6);
338 BOOST_CHECK( coro);
339 coro( 3);
340 BOOST_CHECK( ! coro);
341 BOOST_CHECK_EQUAL( 3, value1);
342}
343
344void test_arg_string()
345{
346 value2 = "";
347
348 coro::coroutine< std::string >::push_type coro( f7);
349 BOOST_CHECK( coro);
350 coro( std::string("abc") );
351 BOOST_CHECK( ! coro);
352 BOOST_CHECK_EQUAL( std::string("abc"), value2);
353}
354
355void test_fp()
356{
357 value4 = 0;
358
359 coro::coroutine< std::tuple< double, double > >::push_type coro( f8);
360 BOOST_CHECK( coro);
361 coro( std::make_tuple( 7.35, 3.14) );
362 BOOST_CHECK( coro);
363 BOOST_CHECK_EQUAL( ( double) 10.49, value4);
364
365 value4 = 0;
366 coro( std::make_tuple( 1.15, 3.14) );
367 BOOST_CHECK( ! coro);
368 BOOST_CHECK_EQUAL( ( double) 4.29, value4);
369}
370
371void test_ptr()
372{
373 value5 = 0;
374
375 int a = 3;
376 coro::coroutine< int * >::push_type coro( f9);
377 BOOST_CHECK( coro);
378 coro( & a);
379 BOOST_CHECK( ! coro);
380 BOOST_CHECK_EQUAL( & a, value5);
381}
382
383void test_const_ptr()
384{
385 value5 = 0;
386
387 int a = 3;
388 coro::coroutine< int const* >::push_type coro( f91);
389 BOOST_CHECK( coro);
390 coro( & a);
391 BOOST_CHECK( ! coro);
392 BOOST_CHECK_EQUAL( & a, value5);
393}
394
395void test_ref()
396{
397 value5 = 0;
398
399 int a = 3;
400 coro::coroutine< int & >::push_type coro( f10);
401 BOOST_CHECK( coro);
402 coro( a);
403 BOOST_CHECK( ! coro);
404 BOOST_CHECK_EQUAL( & a, value5);
405}
406
407void test_const_ref()
408{
409 value5 = 0;
410
411 int a = 3;
412 coro::coroutine< int const& >::push_type coro( f101);
413 BOOST_CHECK( coro);
414 coro( a);
415 BOOST_CHECK( ! coro);
416 BOOST_CHECK_EQUAL( & a, value5);
417}
418
419void test_no_result()
420{
421 coro::coroutine< int >::pull_type coro( f20);
422 BOOST_CHECK( ! coro);
423}
424
425void test_tuple()
426{
427 value8 = 0;
428 value9 = 0;
429
430 int a = 3, b = 7;
431 std::tuple< int, int > tpl( a, b);
432 BOOST_CHECK_EQUAL( a, std::get< 0 >( tpl) );
433 BOOST_CHECK_EQUAL( b, std::get< 1 >( tpl) );
434 coro::coroutine< std::tuple< int, int > >::push_type coro( f11);
435 BOOST_CHECK( coro);
436 coro( tpl);
437 BOOST_CHECK( ! coro);
438 BOOST_CHECK_EQUAL( a, value8);
439 BOOST_CHECK_EQUAL( b, value9);
440}
441
442void test_unwind()
443{
444 value1 = 0;
445 {
446 coro::coroutine< void >::push_type coro( f12);
447 BOOST_CHECK( coro);
448 BOOST_CHECK_EQUAL( ( int) 0, value1);
449 coro();
450 BOOST_CHECK( coro);
451 BOOST_CHECK_EQUAL( ( int) 7, value1);
452 coro();
453 BOOST_CHECK_EQUAL( ( int) 7, value1);
454 }
455 BOOST_CHECK_EQUAL( ( int) 0, value1);
456 int i = 0;
457 {
458 coro::coroutine< void >::push_type coro(
459 [&i](coro::coroutine< void >::pull_type &) mutable {
460 i = 7;
461 });
462 }
463 BOOST_CHECK_EQUAL( ( int) 0, i);
464}
465
466void test_exceptions()
467{
468 std::string msg("abc"), value;
469 std::runtime_error ex( msg);
470 try
471 {
472 coro::coroutine< void >::push_type coro(
473 [&msg]( coro::coroutine< void >::pull_type &) {
474 throw std::runtime_error( msg);
475 });
476 BOOST_CHECK( coro);
477 coro();
478 BOOST_CHECK( ! coro);
479 BOOST_CHECK( false);
480 }
481 catch ( std::runtime_error const& ex)
482 { value = ex.what(); }
483 BOOST_CHECK_EQUAL( value, msg);
484}
485
486void test_input_iterator()
487{
488 {
489 using std::begin;
490 using std::end;
491
492 std::vector< int > vec;
493 coro::coroutine< int >::pull_type coro( f16);
494 coro::coroutine< int >::pull_type::iterator e = end( coro);
495 for (
496 coro::coroutine< int >::pull_type::iterator i = begin( coro);
497 i != e; ++i)
498 { vec.push_back( * i); }
499 BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
500 BOOST_CHECK_EQUAL( ( int)1, vec[0] );
501 BOOST_CHECK_EQUAL( ( int)2, vec[1] );
502 BOOST_CHECK_EQUAL( ( int)3, vec[2] );
503 BOOST_CHECK_EQUAL( ( int)4, vec[3] );
504 BOOST_CHECK_EQUAL( ( int)5, vec[4] );
505 }
506 {
507 std::vector< int > vec;
508 coro::coroutine< int >::pull_type coro( f16);
509 for ( auto i : coro)
510 { vec.push_back( i); }
511 BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
512 BOOST_CHECK_EQUAL( ( int)1, vec[0] );
513 BOOST_CHECK_EQUAL( ( int)2, vec[1] );
514 BOOST_CHECK_EQUAL( ( int)3, vec[2] );
515 BOOST_CHECK_EQUAL( ( int)4, vec[3] );
516 BOOST_CHECK_EQUAL( ( int)5, vec[4] );
517 }
518 {
519 int i1 = 1, i2 = 2, i3 = 3;
520 coro::coroutine< int& >::pull_type coro(
521 [&i1,&i2,&i3](coro::coroutine< int& >::push_type & c){
522 c( i1);
523 c( i2);
524 c( i3);
525 });
526
527 int counter = 1;
528 for ( int & i : coro) {
529 switch ( counter) {
530 case 1:
531 BOOST_CHECK_EQUAL( & i1, & i);
532 break;
533 case 2:
534 BOOST_CHECK_EQUAL( & i2, & i);
535 break;
536 case 3:
537 BOOST_CHECK_EQUAL( & i3, & i);
538 break;
539 default:
540 BOOST_ASSERT( false);
541 }
542 ++counter;
543 }
544 }
545}
546
547void test_output_iterator()
548{
549 using std::begin;
550 using std::end;
551
552 int counter = 0;
553 std::vector< int > vec;
554 coro::coroutine< int >::push_type coro(
555 [&vec]( coro::coroutine< int >::pull_type & c) {
556 int x = c.get();
557 while ( 5 > x)
558 {
559 vec.push_back( x);
560 x = c().get();
561 }
562 });
563// coro::coroutine< int >::push_type coro(
564// std::bind( f17, std::placeholders::_1, std::ref( vec) ) );
565 coro::coroutine< int >::push_type::iterator e( end( coro) );
566 for ( coro::coroutine< int >::push_type::iterator i( begin( coro) );
567 i != e; ++i)
568 {
569 i = ++counter;
570 }
571 BOOST_CHECK_EQUAL( ( std::size_t)4, vec.size() );
572 BOOST_CHECK_EQUAL( ( int)1, vec[0] );
573 BOOST_CHECK_EQUAL( ( int)2, vec[1] );
574 BOOST_CHECK_EQUAL( ( int)3, vec[2] );
575 BOOST_CHECK_EQUAL( ( int)4, vec[3] );
576}
577
578std::vector< int > vec;
579coro::coroutine< void >::pull_type * child = nullptr;
580
581void start_child_coroutine() {
582 child = new coro::coroutine< void >::pull_type([](coro::coroutine< void >::push_type & yield) {
583 vec.push_back( 2);
584 yield();
585 vec.push_back( 2);
586 yield();
587 vec.push_back( 2);
588 yield();
589 vec.push_back( 2);
590 yield();
591 vec.push_back( 2);
592 yield();
593 vec.push_back( 2);
594 });
595}
596
597coro::coroutine< void >::pull_type start_parent_coroutine() {
598 return coro::coroutine< void >::pull_type([=](coro::coroutine< void >::push_type & yield) {
599 vec.push_back( 1);
600 start_child_coroutine();
601 yield();
602 vec.push_back( 1);
603 });
604}
605
606void test_chaining()
607{
608 auto parent = start_parent_coroutine();
609 while ( * child) {
610 ( * child)();
611 }
612 BOOST_CHECK_EQUAL( 7, vec.size() );
613 BOOST_CHECK_EQUAL( 1, vec[0]);
614 BOOST_CHECK_EQUAL( 2, vec[1]);
615 BOOST_CHECK_EQUAL( 2, vec[2]);
616 BOOST_CHECK_EQUAL( 2, vec[3]);
617 BOOST_CHECK_EQUAL( 2, vec[4]);
618 BOOST_CHECK_EQUAL( 2, vec[5]);
619 BOOST_CHECK_EQUAL( 2, vec[6]);
620}
621
622boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
623{
624 boost::unit_test::test_suite * test =
625 BOOST_TEST_SUITE("Boost.Coroutine2: coroutine test suite");
626
627 test->add( BOOST_TEST_CASE( & test_move) );
628 test->add( BOOST_TEST_CASE( & test_complete) );
629 test->add( BOOST_TEST_CASE( & test_jump) );
630 test->add( BOOST_TEST_CASE( & test_result_int) );
631 test->add( BOOST_TEST_CASE( & test_result_string) );
632 test->add( BOOST_TEST_CASE( & test_arg_int) );
633 test->add( BOOST_TEST_CASE( & test_arg_string) );
634 test->add( BOOST_TEST_CASE( & test_fp) );
635 test->add( BOOST_TEST_CASE( & test_ptr) );
636 test->add( BOOST_TEST_CASE( & test_const_ptr) );
637 test->add( BOOST_TEST_CASE( & test_no_result) );
638 test->add( BOOST_TEST_CASE( & test_ref) );
639 test->add( BOOST_TEST_CASE( & test_const_ref) );
640 test->add( BOOST_TEST_CASE( & test_tuple) );
641 test->add( BOOST_TEST_CASE( & test_unwind) );
642 test->add( BOOST_TEST_CASE( & test_exceptions) );
643 test->add( BOOST_TEST_CASE( & test_input_iterator) );
644 test->add( BOOST_TEST_CASE( & test_output_iterator) );
645 test->add( BOOST_TEST_CASE( & test_chaining) );
646
647 return test;
648}