1// Copyright (c) 2022 Klemens D. Morgenstern
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#include <boost/cobalt/this_coro.hpp>
7#include <boost/cobalt/detail/util.hpp>
8
9#include <boost/test/unit_test.hpp>
10#include "test.hpp"
11
12using namespace boost;
13
14struct sig_helper
15{
16 asio::cancellation_signal sig;
17};
18
19struct coro_feature_tester
20 : sig_helper,
21 cobalt::promise_cancellation_base<>,
22 cobalt::promise_throw_if_cancelled_base,
23 cobalt::enable_await_allocator<coro_feature_tester>
24{
25 using cobalt::promise_cancellation_base<>::await_transform;
26 using cobalt::promise_throw_if_cancelled_base::await_transform;
27 using cobalt::enable_await_allocator<coro_feature_tester>::await_transform;
28
29 std::suspend_never initial_suspend() {return {};}
30 std::suspend_never final_suspend() noexcept {return {};}
31
32 coro_feature_tester(coro_feature_tester * & ref)
33 : cobalt::promise_cancellation_base<>(sig.slot())
34 {
35 ref = this;
36 }
37 void return_void() {}
38 void unhandled_exception() {throw;}
39 void get_return_object() {}
40
41#if !defined(BOOST_COBALT_NO_PMR)
42 cobalt::pmr::unsynchronized_pool_resource res;
43 using allocator_type = cobalt::pmr::polymorphic_allocator<void>;
44 allocator_type get_allocator() {return alloc;}
45 allocator_type alloc{&res};
46#endif
47};
48
49
50namespace std
51{
52template<>
53struct coroutine_traits<void, coro_feature_tester*> //< don't do THIS at
54{
55 using promise_type = coro_feature_tester;
56};
57}
58
59#define SELF_TEST_CASE(Function) \
60static void Function##_impl(coro_feature_tester * this_); \
61BOOST_AUTO_TEST_CASE(Function) \
62{ \
63 Function##_impl(nullptr); \
64} \
65static void Function##_impl(coro_feature_tester * this_)
66
67BOOST_AUTO_TEST_SUITE(this_coro);
68
69SELF_TEST_CASE(promise_cancellation_base)
70{
71 BOOST_CHECK(!this_->cancelled());
72 BOOST_CHECK(this_->cancellation_state().cancelled() == asio::cancellation_type::none);
73
74 this_->sig.emit(type: asio::cancellation_type::terminal);
75
76 BOOST_CHECK(this_->cancelled() == asio::cancellation_type::terminal);
77 BOOST_CHECK(this_->cancellation_state().cancelled() == asio::cancellation_type::terminal);
78
79 co_await cobalt::this_coro::reset_cancellation_state();
80
81 BOOST_CHECK(!this_->cancelled());
82 BOOST_CHECK(this_->cancellation_state().cancelled() == asio::cancellation_type::none);
83
84 this_->sig.emit(type: asio::cancellation_type::terminal);
85
86 BOOST_CHECK(this_->cancelled() == asio::cancellation_type::terminal);
87 BOOST_CHECK(this_->cancellation_state().cancelled() == asio::cancellation_type::terminal);
88
89 co_await cobalt::this_coro::reset_cancellation_state(filter: asio::enable_partial_cancellation());
90
91 BOOST_CHECK(!this_->cancelled());
92 BOOST_CHECK(this_->cancellation_state().cancelled() == asio::cancellation_type::none);
93
94 this_->sig.emit(type: asio::cancellation_type::total);
95
96 BOOST_CHECK(!this_->cancelled());
97 BOOST_CHECK(this_->cancellation_state().cancelled() == asio::cancellation_type::none);
98 this_->sig.emit(type: asio::cancellation_type::all);
99 BOOST_CHECK(this_->cancelled() == (asio::cancellation_type::terminal | asio::cancellation_type::partial));
100
101
102 co_await cobalt::this_coro::reset_cancellation_state(
103 in_filter: asio::enable_partial_cancellation(),
104 out_filter: asio::enable_terminal_cancellation());
105
106 BOOST_CHECK(!this_->cancelled());
107 BOOST_CHECK(this_->cancellation_state().cancelled() == asio::cancellation_type::none);
108
109 this_->sig.emit(type: asio::cancellation_type::total);
110
111 BOOST_CHECK(!this_->cancelled());
112 BOOST_CHECK(this_->cancellation_state().cancelled() == asio::cancellation_type::none);
113 this_->sig.emit(type: asio::cancellation_type::all);
114 BOOST_CHECK(this_->cancelled() == (asio::cancellation_type::terminal | asio::cancellation_type::partial));
115}
116
117
118SELF_TEST_CASE(promise_throw_if_cancelled_base)
119{
120 BOOST_CHECK(co_await asio::this_coro::throw_if_cancelled());
121 co_await asio::this_coro::throw_if_cancelled(value: false);
122 BOOST_CHECK(!co_await asio::this_coro::throw_if_cancelled());
123}
124
125#if !defined(BOOST_COBALT_NO_PMR)
126SELF_TEST_CASE(enable_await_allocator)
127{
128 BOOST_CHECK(this_->get_allocator() == co_await cobalt::this_coro::allocator);
129}
130#endif
131
132
133BOOST_AUTO_TEST_SUITE_END();

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