]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/outcome/test/tests/coroutine-support.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / outcome / test / tests / coroutine-support.cpp
1 /* Unit testing for outcomes
2 (C) 2013-2022 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
3
4
5 Boost Software License - Version 1.0 - August 17th, 2003
6
7 Permission is hereby granted, free of charge, to any person or organization
8 obtaining a copy of the software and accompanying documentation covered by
9 this license (the "Software") to use, reproduce, display, distribute,
10 execute, and transmit the Software, and to prepare derivative works of the
11 Software, and to permit third-parties to whom the Software is furnished to
12 do so, all subject to the following:
13
14 The copyright notices in the Software and this entire statement, including
15 the above license grant, this restriction and the following disclaimer,
16 must be included in all copies of the Software, in whole or in part, and
17 all derivative works of the Software, unless such copies or derivative
18 works are solely in the form of machine-executable object code generated by
19 a source language processor.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 DEALINGS IN THE SOFTWARE.
28 */
29
30 #include <boost/outcome/coroutine_support.hpp>
31 #include <boost/outcome.hpp>
32 #include <boost/outcome/try.hpp>
33
34 #if BOOST_OUTCOME_FOUND_COROUTINE_HEADER
35
36 #include <boost/test/unit_test.hpp>
37 #include <boost/test/unit_test_monitor.hpp>
38
39 namespace coroutines
40 {
41 template <class T> using eager = BOOST_OUTCOME_V2_NAMESPACE::awaitables::eager<T>;
42 template <class T> using lazy = BOOST_OUTCOME_V2_NAMESPACE::awaitables::lazy<T>;
43 template <class T, class E = boost::system::error_code> using result = BOOST_OUTCOME_V2_NAMESPACE::result<T, E>;
44
45 inline eager<result<int>> eager_int(int x) { co_return x + 1; }
46 inline lazy<result<int>> lazy_int(int x) { co_return x + 1; }
47 inline eager<result<int>> eager_error() { co_return boost::system::errc::not_enough_memory; }
48 inline lazy<result<int>> lazy_error() { co_return boost::system::errc::not_enough_memory; }
49 inline eager<result<void>> eager_void() { co_return boost::system::errc::not_enough_memory; }
50 inline lazy<result<void>> lazy_void() { co_return boost::system::errc::not_enough_memory; }
51
52 template <class U, class... Args> inline eager<result<std::string>> eager_coawait(U &&f, Args... args)
53 {
54 BOOST_OUTCOME_CO_TRYV2(auto &&, co_await f(args...));
55 co_return "hi";
56 }
57 template <class U, class... Args> inline lazy<result<std::string>> lazy_coawait(U &&f, Args... args)
58 {
59 BOOST_OUTCOME_CO_TRYV2(auto &&, co_await f(args...));
60 co_return "hi";
61 }
62
63 #ifndef BOOST_NO_EXCEPTIONS
64 struct custom_exception_type
65 {
66 };
67 inline lazy<result<int, boost::exception_ptr>> result_exception(boost::exception_ptr e)
68 {
69 boost::rethrow_exception(e);
70 co_return 5;
71 }
72
73 inline lazy<BOOST_OUTCOME_V2_NAMESPACE::outcome<int>> outcome_exception(boost::exception_ptr e)
74 {
75 boost::rethrow_exception(e);
76 co_return 5;
77 }
78 #endif
79
80 inline eager<int> eager_int2(int x) { co_return x + 1; }
81 inline lazy<int> lazy_int2(int x) { co_return x + 1; }
82 inline eager<void> eager_void2() { co_return; }
83 inline lazy<void> lazy_void2() { co_return; }
84 } // namespace coroutines
85
86 BOOST_OUTCOME_AUTO_TEST_CASE(works_result_coroutine, "Tests that results are eager and lazy awaitable")
87 {
88 using namespace coroutines;
89 auto ensure_coroutine_completed_immediately = [](auto t) {
90 BOOST_CHECK(t.await_ready()); // must have eagerly evaluated
91 return t.await_resume(); // fetch the value returned into the promise by the coroutine
92 };
93 auto ensure_coroutine_needs_resuming_once = [](auto t) {
94 BOOST_CHECK(!t.await_ready()); // must not have eagerly evaluated
95 #if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
96 t.await_suspend({}).resume(); // resume execution, which sets the promise
97 #else
98 t.await_suspend({}); // resume execution, which sets the promise
99 #endif
100 BOOST_CHECK(t.await_ready()); // must now be ready
101 return t.await_resume(); // fetch the value returned into the promise by the coroutine
102 };
103
104 // eager_int never suspends, sets promise immediately, must be able to retrieve immediately
105 BOOST_CHECK(ensure_coroutine_completed_immediately(eager_int(5)).value() == 6);
106 // lazy_int suspends before execution, needs resuming to set the promise
107 BOOST_CHECK(ensure_coroutine_needs_resuming_once(lazy_int(5)).value() == 6);
108 BOOST_CHECK(ensure_coroutine_completed_immediately(eager_error()).error() == boost::system::errc::not_enough_memory);
109 BOOST_CHECK(ensure_coroutine_needs_resuming_once(lazy_error()).error() == boost::system::errc::not_enough_memory);
110 BOOST_CHECK(ensure_coroutine_completed_immediately(eager_void()).error() == boost::system::errc::not_enough_memory);
111 BOOST_CHECK(ensure_coroutine_needs_resuming_once(lazy_void()).error() == boost::system::errc::not_enough_memory);
112
113 // co_await eager_int realises it has already completed, does not suspend.
114 BOOST_CHECK(ensure_coroutine_completed_immediately(eager_coawait(eager_int, 5)).value() == "hi");
115 // co_await lazy_int resumes the suspended coroutine.
116 BOOST_CHECK(ensure_coroutine_needs_resuming_once(lazy_coawait(lazy_int, 5)).value() == "hi");
117
118 #ifndef BOOST_NO_EXCEPTIONS
119 auto e = boost::copy_exception(custom_exception_type());
120 BOOST_CHECK_THROW(ensure_coroutine_needs_resuming_once(result_exception(e)).value(), custom_exception_type);
121 BOOST_CHECK_THROW(ensure_coroutine_needs_resuming_once(outcome_exception(e)).value(), custom_exception_type);
122 #endif
123
124 BOOST_CHECK(ensure_coroutine_completed_immediately(eager_int2(5)) == 6);
125 BOOST_CHECK(ensure_coroutine_needs_resuming_once(lazy_int2(5)) == 6);
126 ensure_coroutine_completed_immediately(eager_void2());
127 ensure_coroutine_needs_resuming_once(lazy_void2());
128 }
129 #else
130 int main(void)
131 {
132 return 0;
133 }
134 #endif