From 19fcec84d8d7d21e796c7624e521b60d28ee21ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:45:59 +0200 Subject: Adding upstream version 16.2.11+ds. Signed-off-by: Daniel Baumann --- src/spawn/test/test_spawn.cc | 383 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 383 insertions(+) create mode 100644 src/spawn/test/test_spawn.cc (limited to 'src/spawn/test/test_spawn.cc') diff --git a/src/spawn/test/test_spawn.cc b/src/spawn/test/test_spawn.cc new file mode 100644 index 000000000..30285f1ea --- /dev/null +++ b/src/spawn/test/test_spawn.cc @@ -0,0 +1,383 @@ +// +// spawn.cpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2019 Casey Bodley (cbodley at redhat 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) +// + +// Test that header file is self-contained. +#include + +#include +#include +#include +#include +#include + + +boost::context::protected_fixedsize_stack with_stack_allocator() +{ + return boost::context::protected_fixedsize_stack(65536); +} + +struct counting_handler { + int& count; + counting_handler(int& count) : count(count) {} + void operator()() { ++count; } + template + void operator()(spawn::basic_yield_context) { ++count; } +}; + +TEST(Spawn, SpawnFunction) +{ + boost::asio::io_context ioc; + int called = 0; + spawn::spawn(counting_handler(called)); + ASSERT_EQ(0, ioc.run()); // runs in system executor + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(1, called); +} + +TEST(Spawn, SpawnBoundFunction) +{ + boost::asio::io_context ioc; + int called = 0; + spawn::spawn(bind_executor(ioc.get_executor(), counting_handler(called))); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(1, called); +} + +TEST(Spawn, SpawnFunctionStackAllocator) +{ + boost::asio::io_context ioc; + int called = 0; + spawn::spawn(counting_handler(called), + with_stack_allocator()); + ASSERT_EQ(0, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(1, called); +} + +TEST(Spawn, SpawnHandler) +{ + boost::asio::io_context ioc; + boost::asio::strand strand(ioc.get_executor()); + int called = 0; + spawn::spawn(bind_executor(strand, counting_handler(called)), + counting_handler(called)); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(2, called); +} + +TEST(Spawn, SpawnHandlerStackAllocator) +{ + boost::asio::io_context ioc; + typedef boost::asio::io_context::executor_type executor_type; + boost::asio::strand strand(ioc.get_executor()); + int called = 0; + spawn::spawn(bind_executor(strand, counting_handler(called)), + counting_handler(called), + with_stack_allocator()); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(2, called); +} + +struct spawn_counting_handler { + int& count; + spawn_counting_handler(int& count) : count(count) {} + template + void operator()(spawn::basic_yield_context y) + { + spawn::spawn(y, counting_handler(count)); + ++count; + } +}; + +TEST(Spawn, SpawnYieldContext) +{ + boost::asio::io_context ioc; + int called = 0; + spawn::spawn(bind_executor(ioc.get_executor(), + counting_handler(called)), + spawn_counting_handler(called)); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(3, called); +} + +struct spawn_alloc_counting_handler { + int& count; + spawn_alloc_counting_handler(int& count) : count(count) {} + template + void operator()(spawn::basic_yield_context y) + { + spawn::spawn(y, counting_handler(count), + with_stack_allocator()); + ++count; + } +}; + +TEST(Spawn, SpawnYieldContextStackAllocator) +{ + boost::asio::io_context ioc; + int called = 0; + spawn::spawn(bind_executor(ioc.get_executor(), + counting_handler(called)), + spawn_alloc_counting_handler(called)); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(3, called); +} + +TEST(Spawn, SpawnExecutor) +{ + boost::asio::io_context ioc; + int called = 0; + spawn::spawn(ioc.get_executor(), counting_handler(called)); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(1, called); +} + +TEST(Spawn, SpawnExecutorStackAllocator) +{ + boost::asio::io_context ioc; + int called = 0; + spawn::spawn(ioc.get_executor(), + counting_handler(called), + with_stack_allocator()); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(1, called); +} + +TEST(Spawn, SpawnStrand) +{ + boost::asio::io_context ioc; + typedef boost::asio::io_context::executor_type executor_type; + int called = 0; + spawn::spawn(boost::asio::strand(ioc.get_executor()), + counting_handler(called)); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(1, called); +} + +TEST(Spawn, SpawnStrandStackAllocator) +{ + boost::asio::io_context ioc; + typedef boost::asio::io_context::executor_type executor_type; + int called = 0; + spawn::spawn(boost::asio::strand(ioc.get_executor()), + counting_handler(called), + with_stack_allocator()); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(1, called); +} + +TEST(Spawn, SpawnExecutionContext) +{ + boost::asio::io_context ioc; + int called = 0; + spawn::spawn(ioc, counting_handler(called)); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(1, called); +} + +TEST(Spawn, SpawnExecutionContextStackAllocator) +{ + boost::asio::io_context ioc; + int called = 0; + spawn::spawn(ioc, counting_handler(called), + with_stack_allocator()); + ASSERT_EQ(1, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + ASSERT_EQ(1, called); +} + +typedef boost::asio::system_timer timer_type; + +struct spawn_wait_handler { + timer_type& timer; + spawn_wait_handler(timer_type& timer) : timer(timer) {} + template + void operator()(spawn::basic_yield_context yield) + { + timer.async_wait(yield); + } +}; + +TEST(Spawn, SpawnTimer) +{ + int called = 0; + { + boost::asio::io_context ioc; + timer_type timer(ioc, boost::asio::chrono::hours(0)); + + spawn::spawn(bind_executor(ioc.get_executor(), + counting_handler(called)), + spawn_wait_handler(timer)); + ASSERT_EQ(2, ioc.run()); + ASSERT_TRUE(ioc.stopped()); + } + ASSERT_EQ(1, called); +} + +TEST(Spawn, SpawnTimerDestruct) +{ + int called = 0; + { + boost::asio::io_context ioc; + timer_type timer(ioc, boost::asio::chrono::hours(65536)); + + spawn::spawn(bind_executor(ioc.get_executor(), + counting_handler(called)), + spawn_wait_handler(timer)); + ASSERT_EQ(1, ioc.run_one()); + ASSERT_TRUE(!ioc.stopped()); + } + ASSERT_EQ(0, called); +} + +using boost::system::error_code; + +template +void post(Handler& h, Args&& ...args) +{ + auto ex = boost::asio::get_associated_executor(h); + auto a = boost::asio::get_associated_allocator(h); + auto b = std::bind(std::move(h), std::forward(args)...); + ex.post(std::move(b), a); +} + +struct single_tuple_handler { + std::tuple& result; + void operator()(spawn::yield_context y) { + using Signature = void(std::tuple); + boost::asio::async_completion init(y); + post(init.completion_handler, std::make_tuple(42, std::string{"test"})); + result = init.result.get(); + } +}; + +TEST(Spawn, ReturnSingleTuple) +{ + boost::asio::io_context ioc; + std::tuple result; + spawn::spawn(ioc, single_tuple_handler{result}); + ASSERT_EQ(2, ioc.poll()); + EXPECT_EQ(std::make_tuple(42, std::string{"test"}), result); +} + +struct multiple2_handler { + std::tuple& result; + void operator()(spawn::yield_context y) { + using Signature = void(error_code, int, std::string); + boost::asio::async_completion init(y); + post(init.completion_handler, error_code{}, 42, std::string{"test"}); + result = init.result.get(); + } +}; + +TEST(Spawn, ReturnMultiple2) +{ + boost::asio::io_context ioc; + std::tuple result; + spawn::spawn(ioc, multiple2_handler{result}); + ASSERT_EQ(2, ioc.poll()); + EXPECT_EQ(std::make_tuple(42, std::string{"test"}), result); +} + +struct multiple2_with_moveonly_handler { + std::tuple>& result; + void operator()(spawn::yield_context y) { + using Signature = void(int, std::unique_ptr); + boost::asio::async_completion init(y); + std::unique_ptr ptr{new int(42)}; + init.completion_handler(42, std::move(ptr)); + result = init.result.get(); + } +}; + +TEST(Spawn, ReturnMultiple2MoveOnly) +{ + boost::asio::io_context ioc; + std::tuple> result; + spawn::spawn(ioc, multiple2_with_moveonly_handler{result}); + ASSERT_EQ(1, ioc.poll()); + EXPECT_EQ(42, std::get<0>(result)); + ASSERT_TRUE(std::get<1>(result)); + EXPECT_EQ(42, *std::get<1>(result)); +} + +struct multiple3_handler { + std::tuple& result; + void operator()(spawn::yield_context y) { + using Signature = void(error_code, int, std::string, double); + boost::asio::async_completion init(y); + post(init.completion_handler, error_code{}, 42, std::string{"test"}, 2.0); + result = init.result.get(); + } +}; + +TEST(Spawn, ReturnMultiple3) +{ + boost::asio::io_context ioc; + std::tuple result; + spawn::spawn(ioc, multiple3_handler{result}); + ASSERT_EQ(2, ioc.poll()); + EXPECT_EQ(std::make_tuple(42, std::string{"test"}, 2.0), result); +} + +struct non_default_constructible { + non_default_constructible() = delete; + non_default_constructible(std::nullptr_t) {} +}; + +struct non_default_constructible_handler { + boost::optional& result; + void operator()(spawn::yield_context y) { + using Signature = void(non_default_constructible); + boost::asio::async_completion init(y); + post(init.completion_handler, non_default_constructible{nullptr}); + result = init.result.get(); + } +}; + +TEST(Spawn, ReturnNonDefaultConstructible) +{ + boost::asio::io_context ioc; + boost::optional result; + spawn::spawn(ioc, non_default_constructible_handler{result}); + ASSERT_EQ(2, ioc.poll()); + ASSERT_TRUE(result); +} + +struct multiple_non_default_constructible_handler { + boost::optional>& result; + void operator()(spawn::yield_context y) { + using Signature = void(error_code, int, non_default_constructible); + boost::asio::async_completion init(y); + post(init.completion_handler, error_code{}, 42, + non_default_constructible{nullptr}); + result = init.result.get(); + } +}; + +TEST(Spawn, ReturnMultipleNonDefaultConstructible) +{ + boost::asio::io_context ioc; + boost::optional> result; + spawn::spawn(ioc, multiple_non_default_constructible_handler{result}); + ASSERT_EQ(2, ioc.poll()); + ASSERT_TRUE(result); +} -- cgit v1.2.3