|
1 | | - // src/beman/execution/tests/exec-let.test.cpp -*-C++-*- |
2 | | - // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
3 | | - |
4 | | - #include <beman/execution/detail/let.hpp> |
5 | | - #include <beman/execution/detail/just.hpp> |
6 | | - #include <beman/execution/detail/get_scheduler.hpp> |
7 | | - #include <beman/execution/detail/then.hpp> |
8 | | - #include <beman/execution/detail/read_env.hpp> |
9 | | - #include <beman/execution/detail/sync_wait.hpp> |
10 | | - #include <test/execution.hpp> |
11 | | - #include <array> |
12 | | - #include <cstdlib> |
13 | | - #include <concepts> |
14 | | - #include <memory_resource> |
15 | | - #include <span> |
16 | | - #include <vector> |
17 | | - |
18 | | - // ---------------------------------------------------------------------------- |
19 | | - |
20 | | - namespace { |
21 | | - struct receiver { |
22 | | - using receiver_concept = test_std::receiver_t; |
23 | | - auto set_error(auto&&) && noexcept -> void {} |
24 | | - auto set_stopped() && noexcept -> void {} |
25 | | - auto set_value(auto&&...) && noexcept -> void {} |
26 | | - }; |
27 | | - template <typename... Sigs> |
28 | | - struct test_sender { |
29 | | - using sender_concept = test_std::sender_t; |
30 | | - using completion_signatures = test_std::completion_signatures<Sigs...>; |
31 | | - |
32 | | - struct state { |
33 | | - using operation_state_concept = test_std::operation_state_t; |
34 | | - auto start() & noexcept -> void {} |
35 | | - }; |
36 | | - auto connect(auto&&) -> state { return {}; } |
37 | | - }; |
38 | | - |
39 | | - auto test_let_value() { |
40 | | - auto s0{test_std::let_value(test_std::just(), [] { return test_std::just() | test_std::then([] {}); })}; |
41 | | - auto s1{test_std::just() | test_std::let_value([] { return test_std::just(); })}; |
42 | | - static_assert(test_std::sender<decltype(s0)>); |
43 | | - static_assert(test_std::sender<decltype(s1)>); |
44 | | - |
45 | | - static_assert(test_std::sender<test_sender<test_std::set_value_t()>>); |
46 | | - static_assert(test_std::operation_state<test_sender<test_std::set_value_t()>::state>); |
47 | | - auto s2{test_sender<test_std::set_value_t(), |
48 | | - test_std::set_value_t(int), |
49 | | - test_std::set_value_t(int&), |
50 | | - test_std::set_error_t(int), |
51 | | - test_std::set_stopped_t()>() | |
52 | | - test_std::let_value([]<typename... A>(A&&...) { |
53 | | - return test_sender<test_std::set_value_t(bool), |
54 | | - test_std::set_value_t(double, A...), |
55 | | - test_std::set_error_t(char)>(); |
56 | | - })}; |
57 | | - static_assert(test_std::sender<decltype(s2)>); |
58 | | - using type = decltype(test_std::get_completion_signatures(s2, test_std::empty_env{})); |
59 | | - static_assert(std::same_as<type, type>); |
60 | | - // static_assert(std::same_as<void, type>); |
61 | | - |
62 | | - auto state2{test_std::connect(s2, receiver{})}; |
63 | | - test::use(state2); |
64 | | - test_std::start(state2); |
65 | | - |
66 | | - auto state0{test_std::connect(s0, receiver{})}; |
67 | | - test::use(state0); |
68 | | - test_std::start(state0); |
69 | | - auto state1{test_std::connect(s1, receiver{})}; |
70 | | - test::use(state1); |
71 | | - test_std::start(state1); |
72 | | - } |
73 | | - |
74 | | - template <std::size_t Size> |
75 | | - struct inline_resource : std::pmr::memory_resource { |
76 | | - std::array<std::byte, Size> buffer; |
77 | | - std::byte* next{+this->buffer}; |
78 | | - |
79 | | - void* do_allocate(std::size_t size, std::size_t) override { |
80 | | - if (size <= std::size_t(std::distance(next, std::end(buffer)))) { |
81 | | - std::byte* rc{this->next}; |
82 | | - this->next += size; |
83 | | - return rc; |
84 | | - } |
85 | | - return nullptr; |
86 | | - } |
87 | | - void do_deallocate(void*, std::size_t, std::size_t) override {} |
88 | | - bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override { return this == &other; } |
89 | | - }; |
90 | | - |
91 | | - namespace ex = test_std; |
92 | | - |
93 | | - struct fun { |
94 | | - std::pmr::polymorphic_allocator<> allocator{}; |
95 | | - fun() {} |
96 | | - explicit fun(std::pmr::polymorphic_allocator<> alloc) : allocator(alloc) {} |
97 | | - auto operator()(std::span<int> s) noexcept { |
98 | | - return ex::just(std::pmr::vector<int>(s.begin(), s.end(), this->allocator)); |
99 | | - } |
100 | | - }; |
101 | | - |
102 | | - auto test_let_value_allocator() -> void { |
103 | | - std::vector<int> values{1, 2, 3}; |
104 | | - auto s{ex::just(std::span(values)) | ex::let_value(fun()) | ex::then([](auto&&) noexcept {})}; |
105 | | - static_assert(test_std::sender<decltype(s)>); |
106 | | - static_assert(test_std::sender_in<decltype(s)>); |
107 | | - // static_assert(std::same_as<void, decltype(test_std::get_completion_signatures(s, test_std::empty_env{}))>); |
108 | | - ex::sync_wait(s); |
109 | | - } |
110 | | - |
111 | | - auto test_let_value_env() -> void { |
112 | | - ex::sync_wait( |
113 | | - ex::just() |
114 | | - | ex::let_value([]{ return ex::read_env(ex::get_scheduler); }) |
115 | | - | ex::then([](auto s){ static_assert(ex::scheduler<decltype(s)>); }) |
116 | | - ); |
117 | | - } |
118 | | - } // namespace |
119 | | - |
120 | | - // ---------------------------------------------------------------------------- |
121 | | - |
122 | | - TEST(exec_let) { |
123 | | - static_assert(std::same_as<const test_std::let_error_t, decltype(test_std::let_error)>); |
124 | | - static_assert(std::same_as<const test_std::let_stopped_t, decltype(test_std::let_stopped)>); |
125 | | - static_assert(std::same_as<const test_std::let_value_t, decltype(test_std::let_value)>); |
126 | | - |
127 | | - try { |
128 | | - test_let_value(); |
129 | | - test_let_value_allocator(); |
130 | | - test_let_value_env(); |
131 | | - } catch (...) { |
132 | | - // NOLINTBEGIN(cert-dcl03-c,hicpp-static-assert,misc-static-assert) |
133 | | - ASSERT(nullptr == "let tests are not expected to throw"); |
134 | | - // NOLINTEND(cert-dcl03-c,hicpp-static-assert,misc-static-assert) |
135 | | - } |
136 | | - |
137 | | - return EXIT_SUCCESS; |
138 | | - } |
| 1 | +// src/beman/execution/tests/exec-let.test.cpp -*-C++-*- |
| 2 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 3 | + |
| 4 | +#include <beman/execution/detail/let.hpp> |
| 5 | +#include <beman/execution/detail/just.hpp> |
| 6 | +#include <beman/execution/detail/get_scheduler.hpp> |
| 7 | +#include <beman/execution/detail/then.hpp> |
| 8 | +#include <beman/execution/detail/read_env.hpp> |
| 9 | +#include <beman/execution/detail/sync_wait.hpp> |
| 10 | +#include <test/execution.hpp> |
| 11 | +#include <array> |
| 12 | +#include <cstdlib> |
| 13 | +#include <concepts> |
| 14 | +#include <memory_resource> |
| 15 | +#include <span> |
| 16 | +#include <vector> |
| 17 | + |
| 18 | +// ---------------------------------------------------------------------------- |
| 19 | + |
| 20 | +namespace { |
| 21 | +struct receiver { |
| 22 | + using receiver_concept = test_std::receiver_t; |
| 23 | + auto set_error(auto&&) && noexcept -> void {} |
| 24 | + auto set_stopped() && noexcept -> void {} |
| 25 | + auto set_value(auto&&...) && noexcept -> void {} |
| 26 | +}; |
| 27 | +template <typename... Sigs> |
| 28 | +struct test_sender { |
| 29 | + using sender_concept = test_std::sender_t; |
| 30 | + using completion_signatures = test_std::completion_signatures<Sigs...>; |
| 31 | + |
| 32 | + struct state { |
| 33 | + using operation_state_concept = test_std::operation_state_t; |
| 34 | + auto start() & noexcept -> void {} |
| 35 | + }; |
| 36 | + auto connect(auto&&) -> state { return {}; } |
| 37 | +}; |
| 38 | + |
| 39 | +auto test_let_value() { |
| 40 | + auto s0{test_std::let_value(test_std::just(), [] { return test_std::just() | test_std::then([] {}); })}; |
| 41 | + auto s1{test_std::just() | test_std::let_value([] { return test_std::just(); })}; |
| 42 | + static_assert(test_std::sender<decltype(s0)>); |
| 43 | + static_assert(test_std::sender<decltype(s1)>); |
| 44 | + |
| 45 | + static_assert(test_std::sender<test_sender<test_std::set_value_t()>>); |
| 46 | + static_assert(test_std::operation_state<test_sender<test_std::set_value_t()>::state>); |
| 47 | + auto s2{test_sender<test_std::set_value_t(), |
| 48 | + test_std::set_value_t(int), |
| 49 | + test_std::set_value_t(int&), |
| 50 | + test_std::set_error_t(int), |
| 51 | + test_std::set_stopped_t()>() | |
| 52 | + test_std::let_value([]<typename... A>(A&&...) { |
| 53 | + return test_sender<test_std::set_value_t(bool), |
| 54 | + test_std::set_value_t(double, A...), |
| 55 | + test_std::set_error_t(char)>(); |
| 56 | + })}; |
| 57 | + static_assert(test_std::sender<decltype(s2)>); |
| 58 | + using type = decltype(test_std::get_completion_signatures(s2, test_std::empty_env{})); |
| 59 | + static_assert(std::same_as<type, type>); |
| 60 | + // static_assert(std::same_as<void, type>); |
| 61 | + |
| 62 | + auto state2{test_std::connect(s2, receiver{})}; |
| 63 | + test::use(state2); |
| 64 | + test_std::start(state2); |
| 65 | + |
| 66 | + auto state0{test_std::connect(s0, receiver{})}; |
| 67 | + test::use(state0); |
| 68 | + test_std::start(state0); |
| 69 | + auto state1{test_std::connect(s1, receiver{})}; |
| 70 | + test::use(state1); |
| 71 | + test_std::start(state1); |
| 72 | +} |
| 73 | + |
| 74 | +template <std::size_t Size> |
| 75 | +struct inline_resource : std::pmr::memory_resource { |
| 76 | + std::array<std::byte, Size> buffer; |
| 77 | + std::byte* next{+this->buffer}; |
| 78 | + |
| 79 | + void* do_allocate(std::size_t size, std::size_t) override { |
| 80 | + if (size <= std::size_t(std::distance(next, std::end(buffer)))) { |
| 81 | + std::byte* rc{this->next}; |
| 82 | + this->next += size; |
| 83 | + return rc; |
| 84 | + } |
| 85 | + return nullptr; |
| 86 | + } |
| 87 | + void do_deallocate(void*, std::size_t, std::size_t) override {} |
| 88 | + bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override { return this == &other; } |
| 89 | +}; |
| 90 | + |
| 91 | +namespace ex = test_std; |
| 92 | + |
| 93 | +struct fun { |
| 94 | + std::pmr::polymorphic_allocator<> allocator{}; |
| 95 | + fun() {} |
| 96 | + explicit fun(std::pmr::polymorphic_allocator<> alloc) : allocator(alloc) {} |
| 97 | + auto operator()(std::span<int> s) noexcept { |
| 98 | + return ex::just(std::pmr::vector<int>(s.begin(), s.end(), this->allocator)); |
| 99 | + } |
| 100 | +}; |
| 101 | + |
| 102 | +auto test_let_value_allocator() -> void { |
| 103 | + std::vector<int> values{1, 2, 3}; |
| 104 | + auto s{ex::just(std::span(values)) | ex::let_value(fun()) | ex::then([](auto&&) noexcept {})}; |
| 105 | + static_assert(test_std::sender<decltype(s)>); |
| 106 | + static_assert(test_std::sender_in<decltype(s)>); |
| 107 | + // static_assert(std::same_as<void, decltype(test_std::get_completion_signatures(s, test_std::empty_env{}))>); |
| 108 | + ex::sync_wait(s); |
| 109 | +} |
| 110 | + |
| 111 | +auto test_let_value_env() -> void { |
| 112 | + ex::sync_wait(ex::just() | ex::let_value([] { return ex::read_env(ex::get_scheduler); }) | |
| 113 | + ex::then([](auto s) { static_assert(ex::scheduler<decltype(s)>); })); |
| 114 | +} |
| 115 | +} // namespace |
| 116 | + |
| 117 | +// ---------------------------------------------------------------------------- |
| 118 | + |
| 119 | +TEST(exec_let) { |
| 120 | + static_assert(std::same_as<const test_std::let_error_t, decltype(test_std::let_error)>); |
| 121 | + static_assert(std::same_as<const test_std::let_stopped_t, decltype(test_std::let_stopped)>); |
| 122 | + static_assert(std::same_as<const test_std::let_value_t, decltype(test_std::let_value)>); |
| 123 | + |
| 124 | + try { |
| 125 | + test_let_value(); |
| 126 | + test_let_value_allocator(); |
| 127 | + test_let_value_env(); |
| 128 | + } catch (...) { |
| 129 | + // NOLINTBEGIN(cert-dcl03-c,hicpp-static-assert,misc-static-assert) |
| 130 | + ASSERT(nullptr == "let tests are not expected to throw"); |
| 131 | + // NOLINTEND(cert-dcl03-c,hicpp-static-assert,misc-static-assert) |
| 132 | + } |
| 133 | + |
| 134 | + return EXIT_SUCCESS; |
| 135 | +} |
0 commit comments