2
0
mirror of https://github.com/boostorg/cobalt.git synced 2026-01-19 04:02:16 +00:00
Files
cobalt/test/race.cpp
2024-12-13 10:22:18 +08:00

178 lines
5.0 KiB
C++

//
// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.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)
//
#include <boost/cobalt/race.hpp>
#include <boost/cobalt/generator.hpp>
#include <boost/cobalt/promise.hpp>
#include <boost/cobalt/op.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/test/unit_test.hpp>
#include "test.hpp"
using namespace boost;
static cobalt::promise<std::chrono::milliseconds::rep> dummy(
asio::any_io_executor exec,
std::chrono::milliseconds ms = std::chrono::milliseconds(50))
{
asio::steady_timer tim{exec, ms};
co_await tim.async_wait(cobalt::use_op);
co_return ms.count();
}
static cobalt::promise<std::chrono::milliseconds::rep> nothrow_dummy(
asio::any_io_executor exec,
std::chrono::milliseconds ms = std::chrono::milliseconds(50))
try {
asio::steady_timer tim{exec, ms};
co_await tim.async_wait(cobalt::use_op);
co_return ms.count();
}
catch(...)
{
co_return std::numeric_limits<std::chrono::milliseconds::rep>::max();
}
static cobalt::generator<int> gen(asio::any_io_executor exec)
{
asio::steady_timer tim{exec, std::chrono::milliseconds(50000)};
co_await tim.async_wait(cobalt::use_op);
co_return 123;
}
BOOST_AUTO_TEST_SUITE(race_);
CO_TEST_CASE(variadic)
{
auto exec = co_await asio::this_coro::executor;
auto d1 = dummy(exec, std::chrono::milliseconds(100));
auto d2 = dummy(exec, std::chrono::milliseconds( 50));
auto g = gen(exec);
std::mt19937 src{1u};
auto c = co_await race(src, d1, d2, dummy(exec, std::chrono::milliseconds(100000)), g);
BOOST_CHECK(c.index() == 1u);
BOOST_CHECK(boost::variant2::get<1>(c) == 50);
BOOST_CHECK(d1);
//BOOST_CHECK(!d1.ready()); NOTE: Inderministic on msvc, due to the additional post!
BOOST_CHECK( d2.ready());
BOOST_CHECK(100 == co_await d1);
BOOST_CHECK(!d1);
BOOST_CHECK( d1.ready());
co_await d2;
g.cancel();
try { BOOST_CHECK_THROW(co_await g, boost::system::system_error); }
catch (boost::system::system_error &) {}
}
cobalt::promise<void> list_step(std::default_random_engine::result_type seed)
{
std::mt19937 src{seed};
auto exec = co_await asio::this_coro::executor;
std::vector<cobalt::promise<std::chrono::milliseconds::rep>> vec;
vec.push_back(dummy(exec, std::chrono::milliseconds(100)));
vec.push_back(dummy(exec, std::chrono::milliseconds( 50)));
vec.push_back(dummy(exec, std::chrono::milliseconds(100000)));
auto c = ( co_await cobalt::as_result(race(src, vec))).value();
BOOST_CHECK(c.first == 1u);
BOOST_CHECK(c.second == 50);
BOOST_CHECK(!vec[0].ready());
BOOST_CHECK( vec[1].ready());
BOOST_CHECK(co_await vec[0]);
BOOST_CHECK( vec[0].ready());
BOOST_CHECK( vec[1].ready());
vec[2].cancel();
BOOST_CHECK( vec[2]);
BOOST_CHECK_THROW(co_await vec[2], boost::system::system_error);
BOOST_CHECK_THROW(co_await vec[2], boost::system::system_error);
BOOST_CHECK(!vec[2]);
}
CO_TEST_CASE(list_1u) { co_await list_step(1u);}
CO_TEST_CASE(list_2u) { co_await list_step(2u);}
CO_TEST_CASE(list_3u) { co_await list_step(3u);}
CO_TEST_CASE(list_4u) { co_await list_step(4u);}
CO_TEST_CASE(list_5u) { co_await list_step(5u);}
CO_TEST_CASE(list_6u) { co_await list_step(6u);}
CO_TEST_CASE(list_7u) { co_await list_step(7u);}
CO_TEST_CASE(list_8u) { co_await list_step(8u);}
CO_TEST_CASE(list_9u) { co_await list_step(9u);}
CO_TEST_CASE(empty_list)
{
auto exec = co_await asio::this_coro::executor;
std::vector<cobalt::promise<std::size_t>> vec;
try
{
BOOST_CHECK_THROW(co_await race(vec), boost::system::system_error);
}
catch(...) {}
}
CO_TEST_CASE(dummy_result)
{
auto exec = co_await asio::this_coro::executor;
std::vector<cobalt::promise<std::size_t>> vec;
vec.push_back([]() -> cobalt::promise<std::size_t> { co_return 42u;}());
const std::pair<std::size_t, std::size_t> cmp(0u, 42u);
BOOST_CHECK((co_await cobalt::as_result(race(vec))).value() == cmp);
}
CO_TEST_CASE(stop_)
{
auto d = nothrow_dummy(co_await asio::this_coro::executor,
std::chrono::milliseconds(10));
BOOST_CHECK((co_await left_race(d, stop())).index() == 0);
}
CO_TEST_CASE(compliance)
{
auto exec = co_await asio::this_coro::executor;
auto d = dummy(exec, std::chrono::milliseconds(100000));
{
immediate i;
BOOST_CHECK((co_await race(d, i)).index() == 1);
}
{
immediate_bool i;
BOOST_CHECK((co_await race(d, i)).index() == 1);
}
{
immediate_handle i;
BOOST_CHECK((co_await race(d, i)).index() == 1);
}
{
posted p;
BOOST_CHECK((co_await race(d, p)).index() == 1);
}
{
posted_bool p;
BOOST_CHECK((co_await race(d, p)).index() == 1);
}
{
posted_handle p;
BOOST_CHECK((co_await race(d, p)).index() == 1);
}
d.cancel();
BOOST_CHECK_THROW(co_await d, boost::system::system_error);
}
BOOST_AUTO_TEST_SUITE_END();