Skip to content

Commit 02d97f8

Browse files
authored
Merge pull request #2046 from ericniebler/task-and-just-from-ref-tests
test reference handling of `task` and `just_from`
2 parents 45c4cee + 09f2163 commit 02d97f8

2 files changed

Lines changed: 116 additions & 72 deletions

File tree

test/exec/test_just_from.cpp

Lines changed: 79 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -20,75 +20,95 @@
2020

2121
#include <catch2/catch_all.hpp>
2222

23-
TEST_CASE("just_from is a sender", "[just_from]")
23+
namespace
2424
{
25-
SECTION("potentially throwing")
25+
constinit int global_int = 0;
26+
27+
TEST_CASE("just_from is a sender", "[just_from]")
2628
{
27-
auto s = exec::just_from([](auto sink) { return sink(42); });
28-
using S = decltype(s);
29-
STATIC_REQUIRE(ex::sender<S>);
30-
STATIC_REQUIRE(ex::sender_in<S>);
31-
::check_val_types<ex::__mset<pack<int>>>(s);
32-
::check_err_types<ex::__mset<std::exception_ptr>>(s);
33-
::check_sends_stopped<false>(s);
29+
SECTION("potentially throwing")
30+
{
31+
auto s = exec::just_from([](auto sink) { return sink(42); });
32+
using S = decltype(s);
33+
STATIC_REQUIRE(ex::sender<S>);
34+
STATIC_REQUIRE(ex::sender_in<S>);
35+
::check_val_types<ex::__mset<pack<int>>>(s);
36+
::check_err_types<ex::__mset<std::exception_ptr>>(s);
37+
::check_sends_stopped<false>(s);
38+
}
39+
40+
SECTION("not potentially throwing")
41+
{
42+
auto s = exec::just_from([](auto sink) noexcept { return sink(42); });
43+
using S = decltype(s);
44+
STATIC_REQUIRE(ex::sender<S>);
45+
STATIC_REQUIRE(ex::sender_in<S>);
46+
::check_val_types<ex::__mset<pack<int>>>(s);
47+
::check_err_types<ex::__mset<>>(s);
48+
::check_sends_stopped<false>(s);
49+
}
3450
}
3551

36-
SECTION("not potentially throwing")
52+
TEST_CASE("just_from basically works", "[just_from]")
3753
{
38-
auto s = exec::just_from([](auto sink) noexcept { return sink(42); });
39-
using S = decltype(s);
40-
STATIC_REQUIRE(ex::sender<S>);
41-
STATIC_REQUIRE(ex::sender_in<S>);
42-
::check_val_types<ex::__mset<pack<int>>>(s);
54+
auto s = exec::just_from([](auto sink) noexcept { return sink(42, 43, 44); });
55+
::check_val_types<ex::__mset<pack<int, int, int>>>(s);
4356
::check_err_types<ex::__mset<>>(s);
4457
::check_sends_stopped<false>(s);
45-
}
46-
}
47-
48-
TEST_CASE("just_from basically works", "[just_from]")
49-
{
50-
auto s = exec::just_from([](auto sink) noexcept { return sink(42, 43, 44); });
51-
::check_val_types<ex::__mset<pack<int, int, int>>>(s);
52-
::check_err_types<ex::__mset<>>(s);
53-
::check_sends_stopped<false>(s);
5458

55-
auto [a, b, c] = ex::sync_wait(s).value();
56-
CHECK(a == 42);
57-
CHECK(b == 43);
58-
CHECK(c == 44);
59-
}
59+
auto [a, b, c] = ex::sync_wait(s).value();
60+
CHECK(a == 42);
61+
CHECK(b == 43);
62+
CHECK(c == 44);
63+
}
6064

61-
TEST_CASE("just_from with multiple completions", "[just_from]")
62-
{
63-
auto fn = [](auto sink) noexcept
65+
TEST_CASE("just_from with multiple completions", "[just_from]")
6466
{
65-
if (sizeof(sink) == ~0ul)
66-
{
67-
std::puts("sink(42)");
68-
sink(42);
69-
}
70-
else
67+
auto fn = [](auto sink) noexcept
7168
{
72-
std::puts("sink(43, 44)");
73-
sink(43, 44);
74-
}
75-
return ex::completion_signatures<ex::set_value_t(int), ex::set_value_t(int, int)>{};
76-
};
77-
auto s = exec::just_from(fn);
78-
::check_val_types<ex::__mset<pack<int>, pack<int, int>>>(s);
79-
::check_err_types<ex::__mset<>>(s);
80-
::check_sends_stopped<false>(s);
81-
82-
auto var = ex::sync_wait_with_variant(s).value();
83-
std::visit(
84-
[]<class Tupl>(Tupl tupl)
85-
{
86-
constexpr auto N = std::tuple_size_v<Tupl>;
87-
CHECK(N == 2);
88-
if constexpr (N == 2)
69+
if (sizeof(sink) == ~0ul)
8970
{
90-
CHECK_TUPLE(tupl == std::tuple{43, 44});
71+
std::puts("sink(42)");
72+
sink(42);
9173
}
92-
},
93-
var);
94-
}
74+
else
75+
{
76+
std::puts("sink(43, 44)");
77+
sink(43, 44);
78+
}
79+
return ex::completion_signatures<ex::set_value_t(int), ex::set_value_t(int, int)>{};
80+
};
81+
auto s = exec::just_from(fn);
82+
::check_val_types<ex::__mset<pack<int>, pack<int, int>>>(s);
83+
::check_err_types<ex::__mset<>>(s);
84+
::check_sends_stopped<false>(s);
85+
86+
auto var = ex::sync_wait_with_variant(s).value();
87+
std::visit(
88+
[]<class Tupl>(Tupl tupl)
89+
{
90+
constexpr auto N = std::tuple_size_v<Tupl>;
91+
CHECK(N == 2);
92+
if constexpr (N == 2)
93+
{
94+
CHECK_TUPLE(tupl == std::tuple{43, 44});
95+
}
96+
},
97+
var);
98+
}
99+
100+
TEST_CASE("just_from can send references", "[just_from]")
101+
{
102+
global_int = 42;
103+
auto s = exec::just_from([](auto sink) noexcept { return sink(global_int); })
104+
| ex::then(
105+
[](int& i) noexcept
106+
{
107+
CHECK(&i == &global_int);
108+
return std::ref(i);
109+
});
110+
::check_val_types<ex::__mset<pack<std::reference_wrapper<int>>>>(s);
111+
auto [iref] = ex::sync_wait(s).value();
112+
CHECK(&iref.get() == &global_int);
113+
}
114+
} // anonymous namespace

test/stdexec/types/test_task.cpp

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121

2222
# include <stdexec/execution.hpp>
2323

24+
# include <exec/just_from.hpp>
2425
# include <exec/single_thread_context.hpp>
2526
# include <exec/static_thread_pool.hpp>
26-
# include <stdexec/__detail/__task.hpp>
2727

2828
# include <atomic>
2929

@@ -328,18 +328,42 @@ namespace
328328
}
329329

330330
// FUTURE TODO: add support so that `co_await sndr` can return a reference.
331-
// auto test_task_awaits_just_ref_sender() -> ex::task<void> {
332-
// int value = 42;
333-
// decltype(auto) value_ref = co_await just_ref(value);
334-
// STATIC_REQUIRE(std::same_as<decltype(value_ref), int&>);
335-
// CHECK(&value_ref == &value);
336-
// co_return;
337-
// }
338-
339-
// TEST_CASE("test task can await a just_ref sender", "[types][task]") {
340-
// auto t = test_task_awaits_just_ref_sender();
341-
// ex::sync_wait(std::move(t));
342-
// }
331+
332+
constinit int global_int = 0;
333+
334+
constexpr auto wrap_ref = ex::then([](auto &i) noexcept { return std::ref(i); });
335+
336+
auto test_task_of_reference_type() -> ex::task<int &>
337+
{
338+
int &i = co_await []() -> ex::task<int &>
339+
{
340+
co_return global_int;
341+
}();
342+
CHECK(&i == &global_int);
343+
co_return i;
344+
}
345+
346+
TEST_CASE("task supports reference types", "[types][task]")
347+
{
348+
global_int = 42;
349+
auto t = test_task_of_reference_type();
350+
auto [i] = ex::sync_wait(std::move(t)).value();
351+
CHECK(i == 42);
352+
}
353+
354+
TEST_CASE("task can co_await a sender of reference type", "[types][task]")
355+
{
356+
global_int = 42;
357+
auto t = []() -> ex::task<int &>
358+
{
359+
int &i = co_await wrap_ref(
360+
exec::just_from([](auto sink) noexcept { return sink(global_int); }));
361+
CHECK(&i == &global_int);
362+
co_return i;
363+
}();
364+
auto [i] = ex::sync_wait(std::move(t)).value();
365+
CHECK(i == 42);
366+
}
343367

344368
struct inline_affine_stopped_sender
345369
{

0 commit comments

Comments
 (0)