summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/src/tests/unit/experimental/co_composed.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/src/tests/unit/experimental/co_composed.cpp')
-rw-r--r--3rdparty/asio/src/tests/unit/experimental/co_composed.cpp518
1 files changed, 518 insertions, 0 deletions
diff --git a/3rdparty/asio/src/tests/unit/experimental/co_composed.cpp b/3rdparty/asio/src/tests/unit/experimental/co_composed.cpp
new file mode 100644
index 00000000000..755cd46d788
--- /dev/null
+++ b/3rdparty/asio/src/tests/unit/experimental/co_composed.cpp
@@ -0,0 +1,518 @@
+//
+// experimental/co_composed.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// 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)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Prevent link dependency on the Boost.System library.
+#if !defined(BOOST_SYSTEM_NO_DEPRECATED)
+#define BOOST_SYSTEM_NO_DEPRECATED
+#endif // !defined(BOOST_SYSTEM_NO_DEPRECATED)
+
+// Test that header file is self-contained.
+#include "asio/experimental/co_composed.hpp"
+
+#include "asio/bind_cancellation_slot.hpp"
+#include "asio/deferred.hpp"
+#include "asio/detached.hpp"
+#include "asio/io_context.hpp"
+#include "asio/post.hpp"
+#include "../unit_test.hpp"
+
+template <typename CompletionToken>
+auto async_throw(CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void()>(
+ [](auto) { throw 42; }, token);
+}
+
+template <typename CompletionToken>
+auto throw_first(CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void()>(
+ asio::experimental::co_composed(
+ [](auto state) -> void
+ {
+ throw 42;
+ co_yield state.complete();
+ }), token);
+}
+
+void test_throw_first()
+{
+ try
+ {
+ throw_first(asio::detached);
+ ASIO_CHECK(0);
+ }
+ catch (int)
+ {
+ }
+}
+
+template <typename CompletionToken>
+auto throw_after_await(asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void()>(
+ asio::experimental::co_composed(
+ [](auto state, asio::io_context& ctx) -> void
+ {
+ co_await asio::post(ctx, asio::deferred);
+ throw 42;
+ co_yield state.complete();
+ }), token, std::ref(ctx));
+}
+
+void test_throw_after_await()
+{
+ try
+ {
+ asio::io_context ctx(1);
+ throw_after_await(ctx, asio::detached);
+ ctx.run();
+ ASIO_CHECK(0);
+ }
+ catch (int)
+ {
+ }
+}
+
+template <typename CompletionToken>
+auto throw_in_first_suspend(CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void()>(
+ asio::experimental::co_composed(
+ [](auto state) -> void
+ {
+ co_await async_throw(asio::deferred);
+ co_yield state.complete();
+ }), token);
+}
+
+void test_throw_in_first_suspend()
+{
+ try
+ {
+ throw_in_first_suspend(asio::detached);
+ ASIO_CHECK(0);
+ }
+ catch (int)
+ {
+ }
+}
+
+template <typename CompletionToken>
+auto throw_in_suspend_after_await(
+ asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void()>(
+ asio::experimental::co_composed(
+ [](auto state, asio::io_context& ctx) -> void
+ {
+ co_await asio::post(ctx, asio::deferred);
+ co_await async_throw(asio::deferred);
+ co_yield state.complete();
+ }), token, std::ref(ctx));
+}
+
+void test_throw_in_suspend_after_await()
+{
+ try
+ {
+ asio::io_context ctx(1);
+ throw_in_suspend_after_await(ctx, asio::detached);
+ ctx.run();
+ ASIO_CHECK(0);
+ }
+ catch (int)
+ {
+ }
+}
+
+template <typename CompletionToken>
+auto post_loop(asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void(int)>(
+ asio::experimental::co_composed(
+ [](auto state, asio::io_context& ctx) -> void
+ {
+ int i = 0;
+ for (; i < 100; ++i)
+ co_await asio::post(ctx, asio::deferred);
+ co_yield state.complete(i);
+ }, ctx), token, std::ref(ctx));
+}
+
+void test_post_loop()
+{
+ asio::io_context ctx(1);
+ int count = 0;
+ post_loop(ctx, [&](int i){ count = i; });
+ ctx.run();
+ ASIO_CHECK(count == 100);
+}
+
+template <typename CompletionToken>
+auto nested_post(asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void()>(
+ asio::experimental::co_composed(
+ [](auto state, asio::io_context& ctx) -> void
+ {
+ co_await asio::post(ctx, asio::deferred);
+ co_yield state.complete();
+ }, ctx), token, std::ref(ctx));
+}
+
+template <typename CompletionToken>
+auto nested_post_loop(asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void(int)>(
+ asio::experimental::co_composed(
+ [](auto state, asio::io_context& ctx) -> void
+ {
+ int i = 0;
+ for (; i < 100; ++i)
+ co_await nested_post(ctx, asio::deferred);
+ co_yield state.complete(i);
+ }, ctx), token, std::ref(ctx));
+}
+
+void test_nested_post_loop()
+{
+ asio::io_context ctx(1);
+ int count = 0;
+ nested_post_loop(ctx, [&](int i){ count = i; });
+ ctx.run();
+ ASIO_CHECK(count == 100);
+}
+
+template <typename CompletionToken>
+auto post_loop_return_1_0(asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void()>(
+ asio::experimental::co_composed<void()>(
+ [](auto, asio::io_context& ctx) -> void
+ {
+ int i = 0;
+ for (; i < 100; ++i)
+ co_await asio::post(ctx, asio::deferred);
+ co_return {};
+ }, ctx), token, std::ref(ctx));
+}
+
+void test_post_loop_return_1_0()
+{
+ asio::io_context ctx(1);
+ bool done = false;
+ post_loop_return_1_0(ctx, [&]{ done = true; });
+ ctx.run();
+ ASIO_CHECK(done);
+}
+
+template <typename CompletionToken>
+auto post_loop_return_1_1(asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void(int)>(
+ asio::experimental::co_composed<void(int)>(
+ [](auto, asio::io_context& ctx) -> void
+ {
+ int i = 0;
+ for (; i < 100; ++i)
+ co_await asio::post(ctx, asio::deferred);
+ co_return {i};
+ }, ctx), token, std::ref(ctx));
+}
+
+void test_post_loop_return_1_1()
+{
+ asio::io_context ctx(1);
+ int count = 0;
+ post_loop_return_1_1(ctx, [&](int i){ count = i; });
+ ctx.run();
+ ASIO_CHECK(count == 100);
+}
+
+template <typename CompletionToken>
+auto post_loop_return_1_2(asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void(int, char)>(
+ asio::experimental::co_composed<void(int, char)>(
+ [](auto, asio::io_context& ctx) -> void
+ {
+ int i = 0;
+ for (; i < 100; ++i)
+ co_await asio::post(ctx, asio::deferred);
+ co_return {i, 'A'};
+ }, ctx), token, std::ref(ctx));
+}
+
+void test_post_loop_return_1_2()
+{
+ asio::io_context ctx(1);
+ int count = 0;
+ char ch = 0;
+ post_loop_return_1_2(ctx, [&](int i, char c){ count = i, ch = c; });
+ ctx.run();
+ ASIO_CHECK(count == 100);
+ ASIO_CHECK(ch == 'A');
+}
+
+template <typename CompletionToken>
+auto post_loop_return_2(asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<CompletionToken, void(), void(int)>(
+ asio::experimental::co_composed<void(), void(int)>(
+ [](auto, asio::io_context& ctx) -> void
+ {
+ int i = 0;
+ for (; i < 100; ++i)
+ co_await asio::post(ctx, asio::deferred);
+ co_return {i};
+ }, ctx), token, std::ref(ctx));
+}
+
+void test_post_loop_return_2()
+{
+ asio::io_context ctx(1);
+ int count = 0;
+ post_loop_return_2(ctx, [&](int i = 0){ count = i; });
+ ctx.run();
+ ASIO_CHECK(count == 100);
+}
+
+template <typename CompletionToken>
+auto complete_on_cancel(asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<
+ CompletionToken, void(asio::error_code, int)>(
+ asio::experimental::co_composed<
+ void(asio::error_code, int)>(
+ [](auto state, asio::io_context& ctx) -> void
+ {
+ state.on_cancellation_complete_with(
+ asio::error::invalid_argument, 42);
+ int i = 0;
+ for (; i < 100; ++i)
+ co_await asio::post(ctx, asio::deferred);
+ co_return {asio::error::eof, i};
+ }, ctx), token, std::ref(ctx));
+}
+
+void test_complete_on_cancel()
+{
+ asio::io_context ctx(1);
+ int count = 0;
+ asio::error_code ec;
+ asio::cancellation_signal cancel;
+
+ complete_on_cancel(ctx,
+ [&](asio::error_code e, int i)
+ {
+ ec = e;
+ count = i;
+ });
+
+ ctx.run();
+
+ ASIO_CHECK(ec == asio::error::eof);
+ ASIO_CHECK(count == 100);
+
+ complete_on_cancel(ctx,
+ asio::bind_cancellation_slot(cancel.slot(),
+ [&](asio::error_code e, int i)
+ {
+ ec = e;
+ count = i;
+ }));
+
+ ctx.restart();
+ ctx.run_one();
+ cancel.emit(asio::cancellation_type::all);
+ ctx.run();
+
+ ASIO_CHECK(ec == asio::error::invalid_argument);
+ ASIO_CHECK(count == 42);
+
+ complete_on_cancel(ctx,
+ asio::bind_cancellation_slot(cancel.slot(),
+ [&](asio::error_code e, int i)
+ {
+ ec = e;
+ count = i;
+ }));
+
+ ctx.restart();
+ ctx.run();
+
+ ASIO_CHECK(ec == asio::error::eof);
+ ASIO_CHECK(count == 100);
+}
+
+template <typename CompletionToken>
+auto complete_with_default_on_cancel(
+ asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<
+ CompletionToken, void(asio::error_code, int)>(
+ asio::experimental::co_composed<
+ void(asio::error_code, int)>(
+ [](auto, asio::io_context& ctx) -> void
+ {
+ int i = 0;
+ for (; i < 100; ++i)
+ co_await asio::post(ctx, asio::deferred);
+ co_return {asio::error::eof, i};
+ }, ctx), token, std::ref(ctx));
+}
+
+void test_complete_with_default_on_cancel()
+{
+ asio::io_context ctx(1);
+ int count = 0;
+ asio::error_code ec;
+ asio::cancellation_signal cancel;
+
+ complete_with_default_on_cancel(ctx,
+ [&](asio::error_code e, int i)
+ {
+ ec = e;
+ count = i;
+ });
+
+ ctx.run();
+
+ ASIO_CHECK(ec == asio::error::eof);
+ ASIO_CHECK(count == 100);
+
+ complete_with_default_on_cancel(ctx,
+ asio::bind_cancellation_slot(cancel.slot(),
+ [&](asio::error_code e, int i)
+ {
+ ec = e;
+ count = i;
+ }));
+
+ ctx.restart();
+ ctx.run_one();
+ cancel.emit(asio::cancellation_type::all);
+ ctx.run();
+
+ ASIO_CHECK(ec == asio::error::operation_aborted);
+ ASIO_CHECK(count == 0);
+
+ complete_with_default_on_cancel(ctx,
+ asio::bind_cancellation_slot(cancel.slot(),
+ [&](asio::error_code e, int i)
+ {
+ ec = e;
+ count = i;
+ }));
+
+ ctx.restart();
+ ctx.run();
+
+ ASIO_CHECK(ec == asio::error::eof);
+ ASIO_CHECK(count == 100);
+}
+
+template <typename CompletionToken>
+auto throw_on_cancel(asio::io_context& ctx, CompletionToken&& token)
+{
+ return asio::async_initiate<
+ CompletionToken, void(asio::error_code, int)>(
+ asio::experimental::co_composed<
+ void(asio::error_code, int)>(
+ [](auto state, asio::io_context& ctx) -> void
+ {
+ try
+ {
+ state.throw_if_cancelled(true);
+ int i = 0;
+ for (; i < 100; ++i)
+ co_await asio::post(ctx, asio::deferred);
+ co_return {asio::error::eof, i};
+ }
+ catch (...)
+ {
+ co_return {asio::error::invalid_argument, 42};
+ }
+ }, ctx), token, std::ref(ctx));
+}
+
+void test_throw_on_cancel()
+{
+ asio::io_context ctx(1);
+ int count = 0;
+ asio::error_code ec;
+ asio::cancellation_signal cancel;
+
+ throw_on_cancel(ctx,
+ [&](asio::error_code e, int i)
+ {
+ ec = e;
+ count = i;
+ });
+
+ ctx.run();
+
+ ASIO_CHECK(ec == asio::error::eof);
+ ASIO_CHECK(count == 100);
+
+ throw_on_cancel(ctx,
+ asio::bind_cancellation_slot(cancel.slot(),
+ [&](asio::error_code e, int i)
+ {
+ ec = e;
+ count = i;
+ }));
+
+ ctx.restart();
+ ctx.run_one();
+ cancel.emit(asio::cancellation_type::all);
+ ctx.run();
+
+ ASIO_CHECK(ec == asio::error::invalid_argument);
+ ASIO_CHECK(count == 42);
+
+ throw_on_cancel(ctx,
+ asio::bind_cancellation_slot(cancel.slot(),
+ [&](asio::error_code e, int i)
+ {
+ ec = e;
+ count = i;
+ }));
+
+ ctx.restart();
+ ctx.run();
+
+ ASIO_CHECK(ec == asio::error::eof);
+ ASIO_CHECK(count == 100);
+}
+
+ASIO_TEST_SUITE
+(
+ "experimental/co_composed",
+ ASIO_TEST_CASE(test_throw_first)
+ ASIO_TEST_CASE(test_throw_after_await)
+ ASIO_TEST_CASE(test_throw_in_first_suspend)
+ ASIO_TEST_CASE(test_throw_in_suspend_after_await)
+ ASIO_TEST_CASE(test_post_loop)
+ ASIO_TEST_CASE(test_nested_post_loop)
+ ASIO_TEST_CASE(test_post_loop_return_1_0)
+ ASIO_TEST_CASE(test_post_loop_return_1_1)
+ ASIO_TEST_CASE(test_post_loop_return_1_2)
+ ASIO_TEST_CASE(test_post_loop_return_2)
+ ASIO_TEST_CASE(test_complete_on_cancel)
+ ASIO_TEST_CASE(test_complete_with_default_on_cancel)
+ ASIO_TEST_CASE(test_throw_on_cancel)
+)