55#include < beman/execution/detail/queryable.hpp>
66#include < beman/execution/detail/sender.hpp>
77#include < beman/execution/detail/async_scope_token.hpp>
8+ #include < beman/execution/detail/receiver.hpp>
89#include < test/execution.hpp>
910#include < concepts>
1011
@@ -37,9 +38,10 @@ namespace
3738 static_assert (test_std::async_scope_token<token<true >>);
3839 static_assert (not test_std::async_scope_token<token<false >>);
3940
41+ struct exception { int value; };
4042 struct throws {
4143 throws () = default ;
42- throws (throws&&) noexcept (false ) = default ;
44+ throws (throws&&) noexcept (false ) { throw exception{ 42 }; }
4345 };
4446 static_assert (!std::is_nothrow_constructible_v<std::decay_t <throws>, throws>);
4547
@@ -53,7 +55,8 @@ namespace
5355
5456 template <typename Completions>
5557 struct state_base : test_detail::spawn_future_state_base<Completions> {
56- auto complete () noexcept -> void override {}
58+ bool called{false };
59+ auto complete () noexcept -> void override { this ->called = true ; }
5760 };
5861 auto test_state_base () {
5962 static_assert (noexcept (std::declval<test_detail::spawn_future_state_base<test_std::completion_signatures<>>&>().complete ()));
@@ -81,6 +84,83 @@ namespace
8184 [[maybe_unused]] state4_t b4;
8285 static_assert (std::same_as<std::variant<std::monostate, std::tuple<test_std::set_error_t , std::exception_ptr>, std::tuple<test_std::set_value_t , throws>>, typename state4_t ::variant_t >);
8386 static_assert (std::same_as<state4_t ::variant_t , decltype (b4.result )>);
87+
88+ using state5_t = state_base<test_std::completion_signatures<test_std::set_stopped_t ()>>;
89+ [[maybe_unused]] state5_t b5;
90+ static_assert (std::same_as<std::variant<std::monostate, std::tuple<test_std::set_stopped_t >>, typename state5_t ::variant_t >);
91+ static_assert (std::same_as<state5_t ::variant_t , decltype (b5.result )>);
92+ }
93+
94+ auto test_receiver () {
95+ {
96+ using c_t = test_std::completion_signatures<test_std::set_stopped_t ()>;
97+ state_base<c_t > state{};
98+ ASSERT (state.called == false );
99+ ASSERT (std::holds_alternative<std::monostate>(state.result ));
100+ static_assert (test_std::receiver<test_detail::spawn_future_receiver<c_t >>);
101+ [[maybe_unused]] test_detail::spawn_future_receiver<c_t > r0{&state};
102+ [](auto && r){ static_assert (not requires { r.set_stopped (); }); }(r0);
103+ static_assert (noexcept (std::move (r0).set_stopped ()));
104+ std::move (r0).set_stopped ();
105+ ASSERT (state.called == true );
106+ ASSERT ((std::holds_alternative<std::tuple<test_std::set_stopped_t >>(state.result )));
107+ }
108+
109+ {
110+ using c_t = test_std::completion_signatures<test_std::set_error_t (int )>;
111+ state_base<c_t > state{};
112+ ASSERT (state.called == false );
113+ ASSERT (std::holds_alternative<std::monostate>(state.result ));
114+ static_assert (test_std::receiver<test_detail::spawn_future_receiver<c_t >>);
115+ [[maybe_unused]] test_detail::spawn_future_receiver<c_t > r0{&state};
116+ [](auto && r){ static_assert (not requires { r.set_error (17 ); }); }(r0);
117+ static_assert (noexcept (std::move (r0).set_error (17 )));
118+ std::move (r0).set_error (17 );
119+ ASSERT (state.called == true );
120+ ASSERT ((std::holds_alternative<std::tuple<test_std::set_error_t , int >>(state.result )));
121+ ASSERT ((std::get<1 >(std::get<std::tuple<test_std::set_error_t , int >>(state.result )) == 17 ));
122+ }
123+
124+ {
125+ using c_t = test_std::completion_signatures<test_std::set_value_t (int , bool , char )>;
126+ state_base<c_t > state{};
127+ ASSERT (state.called == false );
128+ ASSERT (std::holds_alternative<std::monostate>(state.result ));
129+ static_assert (test_std::receiver<test_detail::spawn_future_receiver<c_t >>);
130+ [[maybe_unused]] test_detail::spawn_future_receiver<c_t > r0{&state};
131+ [](auto && r){ static_assert (not requires { r.set_value (17 , true , ' x' ); }); }(r0);
132+ static_assert (noexcept (std::move (r0).set_value (17 , true , ' x' )));
133+ std::move (r0).set_value (17 , true , ' x' );
134+ ASSERT (state.called == true );
135+ ASSERT ((std::holds_alternative<std::tuple<test_std::set_value_t , int , bool , char >>(state.result )));
136+ ASSERT ((std::get<1 >(std::get<std::tuple<test_std::set_value_t , int , bool , char >>(state.result )) == 17 ));
137+ ASSERT ((std::get<2 >(std::get<std::tuple<test_std::set_value_t , int , bool , char >>(state.result )) == true ));
138+ ASSERT ((std::get<3 >(std::get<std::tuple<test_std::set_value_t , int , bool , char >>(state.result )) == ' x' ));
139+ }
140+
141+ {
142+ using c_t = test_std::completion_signatures<test_std::set_value_t (int , throws, char )>;
143+ state_base<c_t > state{};
144+ ASSERT (state.called == false );
145+ ASSERT (std::holds_alternative<std::monostate>(state.result ));
146+ static_assert (test_std::receiver<test_detail::spawn_future_receiver<c_t >>);
147+ [[maybe_unused]] test_detail::spawn_future_receiver<c_t > r0{&state};
148+ [](auto && r){ static_assert (not requires { r.set_value (17 , throws (), ' x' ); }); }(r0);
149+ static_assert (noexcept (std::move (r0).set_value (17 , throws (), ' x' )));
150+ std::move (r0).set_value (17 , throws (), ' x' );
151+ ASSERT (state.called == true );
152+ ASSERT ((std::holds_alternative<std::tuple<test_std::set_error_t , std::exception_ptr>>(state.result )));
153+ try {
154+ std::rethrow_exception (std::get<1 >(std::get<std::tuple<test_std::set_error_t , std::exception_ptr>>(state.result )));
155+ ASSERT (nullptr == " not reached" );
156+ }
157+ catch (exception const & ex) {
158+ ASSERT (ex.value == 42 );
159+ }
160+ catch (...) {
161+ ASSERT (nullptr == " not reached" );
162+ }
163+ }
84164 }
85165}
86166
@@ -92,4 +172,5 @@ TEST(exec_spawn_future) {
92172 test_spawn_future_interface<false >(sender{}, token<true >{}, *new non_env{});
93173
94174 test_state_base ();
175+ test_receiver ();
95176}
0 commit comments