From c69133dff49f42a2131094e652cc545fc42c7339 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Wed, 21 Jan 2026 20:01:02 -0800 Subject: [PATCH 1/2] http has a copy of run_sync --- CMakePresets.json | 10 +++ src/server/route_handler.cpp | 1 - test/unit/run_sync.hpp | 108 +++++++++++++++++++++++++++++ test/unit/server/flat_router.cpp | 10 +-- test/unit/server/route_handler.cpp | 11 ++- test/unit/server/router.cpp | 13 ++-- 6 files changed, 138 insertions(+), 15 deletions(-) create mode 100644 CMakePresets.json create mode 100644 test/unit/run_sync.hpp diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 00000000..5aa94bfe --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,10 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 25, + "patch": 0 + }, + "configurePresets": [], + "buildPresets": [] +} diff --git a/src/server/route_handler.cpp b/src/server/route_handler.cpp index f8b60159..f03f3010 100644 --- a/src/server/route_handler.cpp +++ b/src/server/route_handler.cpp @@ -9,7 +9,6 @@ #include #include -#include namespace boost { namespace http { diff --git a/test/unit/run_sync.hpp b/test/unit/run_sync.hpp new file mode 100644 index 00000000..9839845f --- /dev/null +++ b/test/unit/run_sync.hpp @@ -0,0 +1,108 @@ +// +// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail 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) +// +// Official repository: https://github.com/cppalliance/http +// + +#ifndef BOOST_HTTP_TEST_RUN_SYNC_HPP +#define BOOST_HTTP_TEST_RUN_SYNC_HPP + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace http { + +// Trivial execution context for synchronous execution. +class sync_context : public capy::execution_context +{ +}; + +// Trivial executor for synchronous execution. +struct sync_executor +{ + static sync_context ctx_; + + bool operator==(sync_executor const&) const noexcept { return true; } + capy::execution_context& context() const noexcept { return ctx_; } + void on_work_started() const noexcept {} + void on_work_finished() const noexcept {} + + capy::coro dispatch(capy::coro h) const + { + return h; + } + + void post(capy::coro h) const + { + h.resume(); + } +}; + +inline sync_context sync_executor::ctx_; + +// Synchronous task runner for tests. +class sync_runner +{ +public: + sync_runner() = default; + + sync_runner(sync_runner const&) = delete; + sync_runner& operator=(sync_runner const&) = delete; + sync_runner(sync_runner&&) = default; + sync_runner& operator=(sync_runner&&) = default; + + template + T operator()(capy::task t) && + { + auto h = t.handle(); + t.release(); + sync_executor ex; + + h.promise().set_continuation(std::noop_coroutine(), ex); + h.promise().set_executor(ex); + + ex.dispatch(capy::coro{h}).resume(); + + std::exception_ptr ep = h.promise().exception(); + + if constexpr (std::is_void_v) + { + h.destroy(); + if (ep) + std::rethrow_exception(ep); + } + else + { + if (ep) + { + h.destroy(); + std::rethrow_exception(ep); + } + auto result = std::move(h.promise().result()); + h.destroy(); + return result; + } + } +}; + +inline +sync_runner +run_sync() +{ + return sync_runner{}; +} + +} // namespace http +} // namespace boost + +#endif diff --git a/test/unit/server/flat_router.cpp b/test/unit/server/flat_router.cpp index 6505b0af..113a39c0 100644 --- a/test/unit/server/flat_router.cpp +++ b/test/unit/server/flat_router.cpp @@ -13,8 +13,8 @@ // Full functional tests are in beast2/test/unit/server/router.cpp #include -#include +#include "run_sync.hpp" #include "test_suite.hpp" namespace boost { @@ -39,11 +39,11 @@ struct flat_router_test flat_router fr2(fr1); params req; - capy::run_sync()(fr1.dispatch( + run_sync()(fr1.dispatch( http::method::get, urls::url_view("/"), req)); BOOST_TEST_EQ(*counter, 1); - capy::run_sync()(fr2.dispatch( + run_sync()(fr2.dispatch( http::method::get, urls::url_view("/"), req)); BOOST_TEST_EQ(*counter, 2); } @@ -70,11 +70,11 @@ struct flat_router_test fr2 = fr1; params req; - capy::run_sync()(fr1.dispatch( + run_sync()(fr1.dispatch( http::method::get, urls::url_view("/"), req)); BOOST_TEST_EQ(*counter, 1); - capy::run_sync()(fr2.dispatch( + run_sync()(fr2.dispatch( http::method::get, urls::url_view("/"), req)); BOOST_TEST_EQ(*counter, 2); } diff --git a/test/unit/server/route_handler.cpp b/test/unit/server/route_handler.cpp index 1048327c..dcc10187 100644 --- a/test/unit/server/route_handler.cpp +++ b/test/unit/server/route_handler.cpp @@ -13,14 +13,21 @@ #include #include #include -#include +#include "run_sync.hpp" #include "test_route_handler.hpp" #include "test_suite.hpp" +#include + namespace boost { namespace http { +struct any_write_buffers +{ + std::array v_; +}; + struct route_handler_test { using test_router = router; @@ -33,7 +40,7 @@ struct route_handler_test { flat_router fr(std::move(r)); test_route_params p; - auto rv = capy::run_sync()(fr.dispatch( + auto rv = run_sync()(fr.dispatch( verb, urls::url_view(url), p)); if(BOOST_TEST_EQ(rv.message(), rv0.message())) BOOST_TEST(rv == rv0); diff --git a/test/unit/server/router.cpp b/test/unit/server/router.cpp index d027f22b..d2aa5725 100644 --- a/test/unit/server/router.cpp +++ b/test/unit/server/router.cpp @@ -12,8 +12,7 @@ #include #include -#include - +#include "run_sync.hpp" #include "test_suite.hpp" namespace boost { @@ -108,7 +107,7 @@ struct router_test { flat_router fr(std::move(r)); params req; - auto rv = capy::run_sync()(fr.dispatch( + auto rv = run_sync()(fr.dispatch( http::method::get, urls::url_view(url), req)); BOOST_TEST_EQ(rv.message(), rv0.message()); } @@ -121,7 +120,7 @@ struct router_test { flat_router fr(std::move(r)); params req; - auto rv = capy::run_sync()(fr.dispatch( + auto rv = run_sync()(fr.dispatch( verb, urls::url_view(url), req)); BOOST_TEST_EQ(rv.message(), rv0.message()); } @@ -134,7 +133,7 @@ struct router_test { flat_router fr(std::move(r)); params req; - auto rv = capy::run_sync()(fr.dispatch( + auto rv = run_sync()(fr.dispatch( verb, urls::url_view(url), req)); BOOST_TEST_EQ(rv.message(), rv0.message()); } @@ -411,7 +410,7 @@ struct router_test flat_router fr(std::move(r)); params req; BOOST_TEST_THROWS( - capy::run_sync()(fr.dispatch( + run_sync()(fr.dispatch( http::method::unknown, urls::url_view("/"), req)), std::invalid_argument); } @@ -423,7 +422,7 @@ struct router_test flat_router fr(std::move(r)); params req; BOOST_TEST_THROWS( - capy::run_sync()(fr.dispatch( + run_sync()(fr.dispatch( "", urls::url_view("/"), req)), std::invalid_argument); } From 4851988e9aeecbe74d2bf595cf3a8aa243b8ffa4 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Thu, 22 Jan 2026 08:15:32 -0800 Subject: [PATCH 2/2] run_blocking replaces run_sync --- test/unit/run_sync.hpp | 108 ----------------------------- test/unit/server/flat_router.cpp | 10 +-- test/unit/server/route_handler.cpp | 7 +- test/unit/server/router.cpp | 21 +++--- 4 files changed, 21 insertions(+), 125 deletions(-) delete mode 100644 test/unit/run_sync.hpp diff --git a/test/unit/run_sync.hpp b/test/unit/run_sync.hpp deleted file mode 100644 index 9839845f..00000000 --- a/test/unit/run_sync.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail 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) -// -// Official repository: https://github.com/cppalliance/http -// - -#ifndef BOOST_HTTP_TEST_RUN_SYNC_HPP -#define BOOST_HTTP_TEST_RUN_SYNC_HPP - -#include -#include -#include - -#include -#include -#include -#include - -namespace boost { -namespace http { - -// Trivial execution context for synchronous execution. -class sync_context : public capy::execution_context -{ -}; - -// Trivial executor for synchronous execution. -struct sync_executor -{ - static sync_context ctx_; - - bool operator==(sync_executor const&) const noexcept { return true; } - capy::execution_context& context() const noexcept { return ctx_; } - void on_work_started() const noexcept {} - void on_work_finished() const noexcept {} - - capy::coro dispatch(capy::coro h) const - { - return h; - } - - void post(capy::coro h) const - { - h.resume(); - } -}; - -inline sync_context sync_executor::ctx_; - -// Synchronous task runner for tests. -class sync_runner -{ -public: - sync_runner() = default; - - sync_runner(sync_runner const&) = delete; - sync_runner& operator=(sync_runner const&) = delete; - sync_runner(sync_runner&&) = default; - sync_runner& operator=(sync_runner&&) = default; - - template - T operator()(capy::task t) && - { - auto h = t.handle(); - t.release(); - sync_executor ex; - - h.promise().set_continuation(std::noop_coroutine(), ex); - h.promise().set_executor(ex); - - ex.dispatch(capy::coro{h}).resume(); - - std::exception_ptr ep = h.promise().exception(); - - if constexpr (std::is_void_v) - { - h.destroy(); - if (ep) - std::rethrow_exception(ep); - } - else - { - if (ep) - { - h.destroy(); - std::rethrow_exception(ep); - } - auto result = std::move(h.promise().result()); - h.destroy(); - return result; - } - } -}; - -inline -sync_runner -run_sync() -{ - return sync_runner{}; -} - -} // namespace http -} // namespace boost - -#endif diff --git a/test/unit/server/flat_router.cpp b/test/unit/server/flat_router.cpp index 113a39c0..97d07236 100644 --- a/test/unit/server/flat_router.cpp +++ b/test/unit/server/flat_router.cpp @@ -14,7 +14,7 @@ #include -#include "run_sync.hpp" +#include #include "test_suite.hpp" namespace boost { @@ -39,11 +39,11 @@ struct flat_router_test flat_router fr2(fr1); params req; - run_sync()(fr1.dispatch( + capy::test::run_blocking()(fr1.dispatch( http::method::get, urls::url_view("/"), req)); BOOST_TEST_EQ(*counter, 1); - run_sync()(fr2.dispatch( + capy::test::run_blocking()(fr2.dispatch( http::method::get, urls::url_view("/"), req)); BOOST_TEST_EQ(*counter, 2); } @@ -70,11 +70,11 @@ struct flat_router_test fr2 = fr1; params req; - run_sync()(fr1.dispatch( + capy::test::run_blocking()(fr1.dispatch( http::method::get, urls::url_view("/"), req)); BOOST_TEST_EQ(*counter, 1); - run_sync()(fr2.dispatch( + capy::test::run_blocking()(fr2.dispatch( http::method::get, urls::url_view("/"), req)); BOOST_TEST_EQ(*counter, 2); } diff --git a/test/unit/server/route_handler.cpp b/test/unit/server/route_handler.cpp index dcc10187..5c49e7b2 100644 --- a/test/unit/server/route_handler.cpp +++ b/test/unit/server/route_handler.cpp @@ -14,7 +14,7 @@ #include #include -#include "run_sync.hpp" +#include #include "test_route_handler.hpp" #include "test_suite.hpp" @@ -40,8 +40,9 @@ struct route_handler_test { flat_router fr(std::move(r)); test_route_params p; - auto rv = run_sync()(fr.dispatch( - verb, urls::url_view(url), p)); + route_result rv; + capy::test::run_blocking([&](route_result r) { rv = r; })( + fr.dispatch(verb, urls::url_view(url), p)); if(BOOST_TEST_EQ(rv.message(), rv0.message())) BOOST_TEST(rv == rv0); } diff --git a/test/unit/server/router.cpp b/test/unit/server/router.cpp index d2aa5725..89fc8de3 100644 --- a/test/unit/server/router.cpp +++ b/test/unit/server/router.cpp @@ -12,7 +12,7 @@ #include #include -#include "run_sync.hpp" +#include #include "test_suite.hpp" namespace boost { @@ -107,8 +107,9 @@ struct router_test { flat_router fr(std::move(r)); params req; - auto rv = run_sync()(fr.dispatch( - http::method::get, urls::url_view(url), req)); + route_result rv; + capy::test::run_blocking([&](route_result res) { rv = res; })( + fr.dispatch(http::method::get, urls::url_view(url), req)); BOOST_TEST_EQ(rv.message(), rv0.message()); } @@ -120,8 +121,9 @@ struct router_test { flat_router fr(std::move(r)); params req; - auto rv = run_sync()(fr.dispatch( - verb, urls::url_view(url), req)); + route_result rv; + capy::test::run_blocking([&](route_result res) { rv = res; })( + fr.dispatch(verb, urls::url_view(url), req)); BOOST_TEST_EQ(rv.message(), rv0.message()); } @@ -133,8 +135,9 @@ struct router_test { flat_router fr(std::move(r)); params req; - auto rv = run_sync()(fr.dispatch( - verb, urls::url_view(url), req)); + route_result rv; + capy::test::run_blocking([&](route_result res) { rv = res; })( + fr.dispatch(verb, urls::url_view(url), req)); BOOST_TEST_EQ(rv.message(), rv0.message()); } @@ -410,7 +413,7 @@ struct router_test flat_router fr(std::move(r)); params req; BOOST_TEST_THROWS( - run_sync()(fr.dispatch( + capy::test::run_blocking()(fr.dispatch( http::method::unknown, urls::url_view("/"), req)), std::invalid_argument); } @@ -422,7 +425,7 @@ struct router_test flat_router fr(std::move(r)); params req; BOOST_TEST_THROWS( - run_sync()(fr.dispatch( + capy::test::run_blocking()(fr.dispatch( "", urls::url_view("/"), req)), std::invalid_argument); }