1//
2// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7
8#include <boost/cobalt/gather.hpp>
9#include <boost/cobalt/generator.hpp>
10#include <boost/cobalt/promise.hpp>
11#include <boost/cobalt/op.hpp>
12
13#include <boost/asio/steady_timer.hpp>
14
15#include <boost/test/unit_test.hpp>
16#include "test.hpp"
17
18using namespace boost;
19
20static cobalt::promise<std::chrono::milliseconds::rep> wdummy(
21 asio::any_io_executor exec,
22 std::chrono::milliseconds ms = std::chrono::milliseconds(25))
23{
24 if (ms == std::chrono::milliseconds ::max())
25 throw std::runtime_error("wdummy_throw");
26
27 asio::steady_timer tim{exec, ms};
28 co_await tim.async_wait(token: cobalt::use_op);
29 co_return ms.count();
30}
31
32static cobalt::generator<int> wgen(asio::any_io_executor exec)
33{
34 asio::steady_timer tim{exec, std::chrono::milliseconds(25)};
35 co_await tim.async_wait(token: cobalt::use_op);
36 co_return 123;
37}
38
39static cobalt::promise<void> wthrow()
40{
41 throw std::runtime_error("wthrow");
42 co_return;
43}
44
45
46BOOST_AUTO_TEST_SUITE(gather_);
47
48CO_TEST_CASE(variadic)
49{
50 auto exec = co_await asio::this_coro::executor;
51 auto d1 = wdummy(exec, ms: std::chrono::milliseconds(100));
52 auto d2 = wdummy(exec, ms: std::chrono::milliseconds( 50));
53 asio::steady_timer tim{co_await asio::this_coro::executor};
54 auto g = wgen(exec);
55 auto c = co_await cobalt::gather(p&: d1, p&: d2, p: wdummy(exec, ms: std::chrono::milliseconds(150)),
56 p&: g, p: wthrow());
57
58 BOOST_CHECK( std::get<0>(c).has_value());
59 BOOST_CHECK(!std::get<0>(c).has_error());
60 BOOST_CHECK(*std::get<0>(c) == 100);
61 BOOST_CHECK( std::get<2>(c).has_value());
62 BOOST_CHECK(!std::get<1>(c).has_error());
63 BOOST_CHECK(*std::get<1>(c) == 50);
64 BOOST_CHECK( std::get<2>(c).has_value());
65 BOOST_CHECK(!std::get<2>(c).has_error());
66 BOOST_CHECK(*std::get<2>(c) == 150);
67 BOOST_CHECK( std::get<3>(c).has_value());
68 BOOST_CHECK(!std::get<3>(c).has_error());
69 BOOST_CHECK(*std::get<3>(c) == 123);
70 BOOST_CHECK(!std::get<4>(c).has_value());
71 BOOST_CHECK( std::get<4>(c).has_error());
72 try {
73 BOOST_CHECK_THROW(std::get<4>(c).value(), boost::system::system_error);
74 } catch(...) {}
75}
76
77CO_TEST_CASE(list)
78{
79 auto exec = co_await asio::this_coro::executor;
80 std::vector<cobalt::promise<std::chrono::milliseconds::rep>> vec;
81 vec.push_back(x: wdummy(exec, ms: std::chrono::milliseconds(100)));
82 vec.push_back(x: wdummy(exec, ms: std::chrono::milliseconds( 50)));
83 vec.push_back(x: wdummy(exec, ms: std::chrono::milliseconds(150)));
84 vec.push_back(x: wdummy(exec, ms: std::chrono::milliseconds::max()));
85
86 auto res = co_await gather(p&: vec);
87 BOOST_REQUIRE(res.size() == 4);
88 BOOST_CHECK( res[0].has_value());
89 BOOST_CHECK(!res[0].has_error());
90 BOOST_CHECK( res[0].value() == 100);
91 BOOST_CHECK( res[1].has_value());
92 BOOST_CHECK(!res[1].has_error());
93 BOOST_CHECK( res[1].value() == 50);
94 BOOST_CHECK( res[2].has_value());
95 BOOST_CHECK(!res[2].has_error());
96 BOOST_CHECK( res[2].value() == 150);
97 BOOST_CHECK(!res[3].has_value());
98 BOOST_CHECK( res[3].has_error());
99 try {
100 BOOST_CHECK_THROW(res[3].value(), boost::system::system_error);
101 } catch(...) {}
102}
103
104CO_TEST_CASE(compliance)
105{
106 auto exec = co_await asio::this_coro::executor;
107 {
108 auto d = wdummy(exec, ms: std::chrono::milliseconds(1));
109 immediate i;
110 co_await gather(p&: d, p&: i);
111 }
112
113 {
114 auto d = wdummy(exec, ms: std::chrono::milliseconds(1));
115 immediate_bool i;
116 co_await gather(p&: d, p&: i);
117 }
118 {
119 auto d = wdummy(exec, ms: std::chrono::milliseconds(1));
120 immediate_handle i;
121 co_await gather(p&: d, p&: i);
122 }
123 {
124 auto d = wdummy(exec, ms: std::chrono::milliseconds(1));
125 posted p;
126 co_await gather(p&: d, p);
127 }
128 {
129 auto d = wdummy(exec, ms: std::chrono::milliseconds(1));
130 posted_bool p;
131 co_await gather(p&: d, p);
132 }
133 {
134 auto d = wdummy(exec, ms: std::chrono::milliseconds(1));
135 posted_handle p;
136 co_await gather(p&: d, p);
137 }
138}
139
140BOOST_AUTO_TEST_SUITE_END();

source code of boost/libs/cobalt/test/gather.cpp