Files
ligo/tests/lifecycle.cpp
T
khodowany 17a621f240
publish / publish (push) Successful in 26m41s
Cleanup
2026-10-08 02:12:58 -05:00

76 lines
3.1 KiB
C++

#include <boost/test/unit_test.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/use_future.hpp>
#include <ligo/detail/lifecycle.hpp>
#include <future>
#include <thread>
BOOST_AUTO_TEST_CASE(session_drain_handles_notifications_before_and_during_registration) {
for (int iteration = 0; iteration < 64; ++iteration) {
auto io = boost::asio::io_context{};
auto registry = ligo::detail::session_registry<int>{};
auto session = std::make_shared<int>(1);
registry.add(session);
auto result = boost::asio::co_spawn(io, registry.wait_empty(std::chrono::seconds{2}), boost::asio::use_future);
auto work = boost::asio::make_work_guard(io);
auto first = std::thread{[&] { io.run(); }};
auto second = std::thread{[&] { io.run(); }};
registry.remove(session);
auto ready = result.wait_for(std::chrono::milliseconds{500}) == std::future_status::ready;
work.reset();
io.stop();
first.join();
second.join();
BOOST_REQUIRE(ready);
BOOST_CHECK(result.get());
}
}
BOOST_AUTO_TEST_CASE(session_drain_keeps_absolute_deadline_under_repeated_notifications) {
auto io = boost::asio::io_context{};
auto registry = ligo::detail::session_registry<int>{};
auto session = std::make_shared<int>(1);
registry.add(session);
auto result = boost::asio::co_spawn(io, registry.wait_empty(std::chrono::milliseconds{20}), boost::asio::use_future);
auto work = boost::asio::make_work_guard(io);
auto first = std::thread{[&] { io.run(); }};
auto second = std::thread{[&] { io.run(); }};
for (int i = 0; i < 200 && result.wait_for(std::chrono::milliseconds{1}) != std::future_status::ready; ++i) {
registry.notify_waiters();
}
auto ready = result.wait_for(std::chrono::milliseconds{0}) == std::future_status::ready;
work.reset();
io.stop();
first.join();
second.join();
BOOST_REQUIRE(ready);
auto value = result.get();
BOOST_REQUIRE(!value);
BOOST_CHECK(value.error().code() == ligo::detail::error_timeout);
}
BOOST_AUTO_TEST_CASE(session_drain_observes_expiry_and_removal_before_wait_is_armed) {
auto io = boost::asio::io_context{};
auto registry = ligo::detail::session_registry<int>{};
auto session = std::make_shared<int>(1);
registry.add(session);
auto timer = std::make_shared<boost::asio::steady_timer>(boost::asio::make_strand(io));
registry.waiters.push_back(timer);
// A notification is queued before registration. It must neither extend an
// elapsed deadline nor prevent observing a session that already finished.
registry.notify_waiters();
auto expired = boost::asio::co_spawn(timer->get_executor(), registry.wait_registered(timer, std::chrono::steady_clock::now()), boost::asio::use_future);
io.run();
auto result = expired.get();
BOOST_REQUIRE(!result);
BOOST_CHECK(result.error().code() == ligo::detail::error_timeout);
io.restart();
registry.remove(session);
auto drained = boost::asio::co_spawn(timer->get_executor(), registry.wait_registered(timer, std::chrono::steady_clock::now() + std::chrono::hours{1}), boost::asio::use_future);
io.run();
BOOST_CHECK(drained.get());
}