diff options
Diffstat (limited to '3rdparty/asio/src/tests/unit/experimental/promise.cpp')
-rw-r--r-- | 3rdparty/asio/src/tests/unit/experimental/promise.cpp | 326 |
1 files changed, 116 insertions, 210 deletions
diff --git a/3rdparty/asio/src/tests/unit/experimental/promise.cpp b/3rdparty/asio/src/tests/unit/experimental/promise.cpp index 540cae2008b..67923a4c726 100644 --- a/3rdparty/asio/src/tests/unit/experimental/promise.cpp +++ b/3rdparty/asio/src/tests/unit/experimental/promise.cpp @@ -2,8 +2,8 @@ // promise.cpp // ~~~~~~~~~~~ // -// Copyright (c) 2021 Klemens D. Morgenstern -// (klemens dot morgenstern at gmx dot net) +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,6 +17,11 @@ // Test that header file is self-contained. #include "asio/experimental/promise.hpp" +#include "asio/append.hpp" +#include "asio/bind_cancellation_slot.hpp" +#include "asio/compose.hpp" +#include "asio/deferred.hpp" +#include "asio/experimental/use_promise.hpp" #include "asio/steady_timer.hpp" #include "../unit_test.hpp" @@ -25,7 +30,6 @@ namespace promise { void promise_tester() { using namespace asio; - using asio::error_code; using namespace std::chrono; io_context ctx; @@ -33,16 +37,15 @@ void promise_tester() steady_timer timer1{ctx}, timer2{ctx}; const auto started_when = steady_clock::now(); - timer1.expires_at(started_when + milliseconds(2000)); + timer1.expires_at(started_when + milliseconds(5000)); timer2.expires_at(started_when + milliseconds(1000)); - auto p = timer1.async_wait(experimental::use_promise); + auto p1 = timer1.async_wait(experimental::use_promise); steady_clock::time_point completed_when; - error_code ec; + asio::error_code ec; bool called = false; - p.async_wait( - [&](auto ec_) + p1([&](asio::error_code ec_) { ec = ec_; called = true; @@ -50,271 +53,174 @@ void promise_tester() }); steady_clock::time_point timer2_done; - timer2.async_wait([&](auto) { - timer2_done = steady_clock::now();; - p.cancel(); - }); + timer2.async_wait( + [&](asio::error_code) + { + timer2_done = steady_clock::now(); + p1.cancel(); + }); ctx.run(); - ASIO_CHECK(timer2_done + milliseconds(1) > completed_when); + static_assert( + asio::is_async_operation<decltype(p1)>::value, + "promise is async_op"); + + ASIO_CHECK(timer2_done + milliseconds(1) > started_when); + ASIO_CHECK(completed_when > timer2_done); ASIO_CHECK(called); ASIO_CHECK(ec == error::operation_aborted); -} -void promise_race_tester() -{ - using namespace asio; - using asio::error_code; - using namespace std::chrono; - - io_context ctx; + timer1.expires_after(milliseconds(0)); + auto p2 = timer1.async_wait( + asio::append(experimental::use_promise, 123)); - steady_timer timer1{ctx}, timer2{ctx}; + ec = asio::error::would_block; + called = false; - const auto started_when = steady_clock::now(); - timer1.expires_at(started_when + milliseconds(2000)); - timer2.expires_at(started_when + milliseconds(1000)); - - experimental::promise<void(std::variant<error_code, error_code>)> p = - experimental::promise<>::race( - timer1.async_wait(experimental::use_promise), - timer2.async_wait(experimental::use_promise)); - - auto called = false; - error_code ec; - steady_clock::time_point completed_when; - p.async_wait( - [&](auto v) + p2([&](asio::error_code ec_, int i) { - ASIO_CHECK(v.index() == 1); - ec = get<1>(v); + ASIO_CHECK(i == 123); + ec = ec_; called = true; - completed_when = steady_clock::now(); }); + ASIO_CHECK(ec == asio::error::would_block); + ASIO_CHECK(!called); + + ctx.restart(); ctx.run(); - ASIO_CHECK(started_when + milliseconds(1000) <= completed_when); - ASIO_CHECK(started_when + milliseconds(1500) > completed_when); - ASIO_CHECK(called); + static_assert( + asio::is_async_operation<decltype(p2)>::value, + "promise is async_op"); + ASIO_CHECK(!ec); + ASIO_CHECK(called); } -void promise_all_tester() +void promise_slot_tester() { using namespace asio; - using asio::error_code; using namespace std::chrono; io_context ctx; - steady_timer timer1{ctx}, - timer2{ctx}; + steady_timer timer1{ctx}, timer2{ctx}; const auto started_when = steady_clock::now(); - timer1.expires_at(started_when + milliseconds(2000)); + timer1.expires_at(started_when + milliseconds(2500)); timer2.expires_at(started_when + milliseconds(1000)); + auto p = timer1.async_wait(experimental::use_promise); - experimental::promise<void(error_code, error_code)> p = - experimental::promise<>::all( - timer1.async_wait(experimental::use_promise), - timer2.async_wait(experimental::use_promise)); - - bool called = false; steady_clock::time_point completed_when; + asio::error_code ec; + bool called = false; - p.async_wait( - [&](auto ec1, auto ec2) - { - ASIO_CHECK(!ec1); - ASIO_CHECK(!ec2); - called = true; - completed_when = steady_clock::now(); - }); - - ctx.run(); - - ASIO_CHECK(started_when + milliseconds(2000) <= completed_when); - ASIO_CHECK(started_when + milliseconds(2500) > completed_when); - ASIO_CHECK(called); -} - -void promise_race_ranged_tester() -{ - using namespace asio; - using asio::error_code; - using namespace std::chrono; - - io_context ctx; - - steady_timer timer1{ctx}, timer2{ctx}; + asio::cancellation_signal sig; - const auto started_when = steady_clock::now(); - timer1.expires_at(started_when + milliseconds(2000)); - timer2.expires_at(started_when + milliseconds(1000)); + p(asio::bind_cancellation_slot( + sig.slot(), + [&](asio::error_code ec_) + { + ec = ec_; + called = true; + completed_when = steady_clock::now(); + })); - // promise< - // std::variant< - // tuple<error_code, std::size_t>, - // tuple<error_code, std::size_t>>> - experimental::promise<void(std::size_t, error_code)> p = - experimental::promise<>::race( - std::array{ - timer1.async_wait(experimental::use_promise), - timer2.async_wait(experimental::use_promise) - }); - - auto called = false; - auto completed_when = steady_clock::time_point(); - - p.async_wait([&](auto idx, auto ec ) + steady_clock::time_point timer2_done; + timer2.async_wait( + [&](asio::error_code) { - ASIO_CHECK(idx == 1); - called = true; - completed_when = steady_clock::now(); - ASIO_CHECK(!ec); + timer2_done = steady_clock::now(); + sig.emit(asio::cancellation_type::all); }); - std::array<experimental::promise<void()>, 0u> arr; - - experimental::promise<>::race( - ctx.get_executor(), std::move(arr) - ).async_wait( - [](std::size_t idx) {ASIO_CHECK(idx == std::size_t(-1));} - ); - ctx.run(); - ASIO_CHECK(started_when + milliseconds(1000) <= completed_when); - ASIO_CHECK(started_when + milliseconds(1500) > completed_when); - ASIO_CHECK(called); - - std::exception_ptr ex; - - try - { - experimental::promise<>::race(std::move(arr)); - } - catch (...) - { - ex = std::current_exception(); - } + static_assert( + asio::is_async_operation<decltype(p)>::value, + "promise is async_op"); - ASIO_CHECK(ex); + ASIO_CHECK(timer2_done + milliseconds(1) > started_when); + ASIO_CHECK(completed_when > timer2_done); + ASIO_CHECK(called); + ASIO_CHECK(ec == error::operation_aborted); } -void promise_all_ranged_tester() +void early_completion() { using namespace asio; - using asio::error_code; using namespace std::chrono; io_context ctx; + auto p = asio::post(ctx, asio::experimental::use_promise); + ctx.run(); - steady_timer timer1{ctx}, timer2{ctx}; - - const auto started_when = steady_clock::now(); - timer1.expires_at(started_when + milliseconds(2000)); - timer2.expires_at(started_when + milliseconds(1000)); - - // promise< - // std::variant< - // tuple<error_code, std::size_t>, - // tuple<error_code, std::size_t>>> - experimental::promise<void(std::vector<error_code>)> p = - experimental::promise<>::all( - std::array{ - timer1.async_wait(experimental::use_promise), - timer2.async_wait(experimental::use_promise) - }); - - auto called = false; - auto completed_when = steady_clock::time_point(); - - p.async_wait( - [&](auto v){ - ASIO_CHECK(v.size() == 2u); - completed_when = steady_clock::now(); - ASIO_CHECK(!v[0]); - ASIO_CHECK(!v[1]); - called = true; - }); - - std::array<experimental::promise<void()>, 0u> arr; - experimental::promise<>::all( - ctx.get_executor(), std::move(arr) - ).async_wait( - [](auto v) {ASIO_CHECK(v.size() == 0);} - ); + ASIO_CHECK(p.completed()); + bool completed = false; + p([&]{completed = true;}); + ASIO_CHECK(!completed); + ctx.restart(); ctx.run(); + ASIO_CHECK(completed); +} - ASIO_CHECK(started_when + milliseconds(2000) <= completed_when); - ASIO_CHECK(started_when + milliseconds(2500) > completed_when); - ASIO_CHECK(called == true); - - std::exception_ptr ex; - try +struct test_cancel_impl_op +{ + asio::steady_timer & tim; + asio::error_code &ec; + template<typename Self> + void operator()(Self& self) { - experimental::promise<>::all(std::move(arr)); + tim.async_wait(std::forward<Self>(self)); } - catch (...) + + template<typename Self> + void operator()(Self& self, asio::error_code ec_) { - ex = std::current_exception(); + ec = ec_; + self.complete(ec_); } - - ASIO_CHECK(ex); +}; + +template <typename CompletionToken> +ASIO_INITFN_AUTO_RESULT_TYPE( + CompletionToken, void(asio::error_code)) +test_cancel_impl(asio::steady_timer & tim, + asio::error_code &ec, + CompletionToken&& token) +{ + return asio::async_compose<CompletionToken, void(asio::error_code)>( + test_cancel_impl_op{tim, ec}, token, tim); } -void promise_cancel_tester() +void test_cancel() { - using namespace asio; - using asio::error_code; - using namespace std::chrono; - - io_context ctx; - - steady_timer timer1{ctx}, timer2{ctx}; + asio::io_context ctx; + asio::steady_timer tim{ctx, std::chrono::seconds(10)}; + asio::error_code ec; - const auto started_when = steady_clock::now(); - timer1.expires_at(started_when + milliseconds(2000)); - timer2.expires_at(started_when + milliseconds(1000)); - - // promise< - // std::variant< - // tuple<error_code, std::size_t>, - // tuple<error_code, std::size_t>>> - experimental::promise<void(error_code, error_code)> p = - experimental::promise<>::all( - timer1.async_wait(experimental::use_promise), - timer2.async_wait(experimental::use_promise)); - - bool called = false; - p.async_wait( - [&](auto ec1, auto ec2) - { - called = true; - ASIO_CHECK(ec1 == error::operation_aborted); - ASIO_CHECK(ec2 == error::operation_aborted); - }); - - post(ctx, [&]{p.cancel();}); + { + auto p = test_cancel_impl( + tim, ec, asio::experimental::use_promise); + } ctx.run(); - ASIO_CHECK(called); + ASIO_CHECK_MESSAGE( + ec == asio::error::operation_aborted, + ec.message()); } } // namespace promise ASIO_TEST_SUITE ( - "promise", - ASIO_TEST_CASE(promise::promise_tester) - ASIO_TEST_CASE(promise::promise_race_tester) - ASIO_TEST_CASE(promise::promise_all_tester) - ASIO_TEST_CASE(promise::promise_race_ranged_tester) - ASIO_TEST_CASE(promise::promise_all_ranged_tester) - ASIO_TEST_CASE(promise::promise_cancel_tester) + "promise", + ASIO_TEST_CASE(promise::promise_tester) + ASIO_TEST_CASE(promise::promise_slot_tester) + ASIO_TEST_CASE(promise::early_completion) + ASIO_TEST_CASE(promise::test_cancel) ) |