#define BOOST_TEST_DYN_LINK #include "core/tristate_obj.h" #include "utility/bit_operations.hpp" #include "utility/debug_utility.hpp" #include #include #include #include #include #include #include using boost::asio::awaitable; using boost::asio::co_spawn; using boost::asio::detached; using boost::asio::use_awaitable; using namespace sophiar; using namespace std::chrono_literals; awaitable test_tristate_obj_1() { struct type_a : public tristate_obj { unsigned int cnt = 0; awaitable on_init(const nlohmann::json &) noexcept { set_bit(cnt, 0); co_return true; } awaitable on_start(const nlohmann::json &) noexcept { set_bit(cnt, 1); co_return true; } awaitable on_stop() noexcept { set_bit(cnt, 2); co_return; } awaitable on_reset() noexcept { set_bit(cnt, 3); co_return; } } node_a; co_await node_a.init({}); BOOST_TEST(node_a.cnt == 0b0001); BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING)); co_await node_a.start({}); BOOST_TEST(node_a.cnt == 0b0011); BOOST_TEST((node_a.get_state() == type_a::state_type::RUNNING)); co_await node_a.stop(); BOOST_TEST(node_a.cnt == 0b0111); BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING)); co_await node_a.reset(); BOOST_TEST(node_a.cnt == 0b1111); BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL)); node_a.cnt = 0; co_await node_a.start({}); // test start before init BOOST_TEST(node_a.cnt == 0b0000); BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL)); co_await node_a.init({}); co_await node_a.start({}); BOOST_TEST(node_a.cnt == 0b0011); BOOST_TEST((node_a.get_state() == type_a::state_type::RUNNING)); co_await node_a.reset(); // test force reset BOOST_TEST(node_a.cnt == 0b1111); BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL)); co_return; } awaitable test_tristate_obj_2() { struct type_a : public tristate_obj { int cnt = 0; boost::asio::high_resolution_timer timer; type_a() : timer(*global_context) {} awaitable on_init(const nlohmann::json &) noexcept { timer.expires_from_now(100ms); co_await timer.async_wait(use_awaitable); set_bit(cnt, 0); co_return true; } awaitable on_start(const nlohmann::json &) noexcept { timer.expires_from_now(100ms); co_await timer.async_wait(use_awaitable); set_bit(cnt, 1); co_return true; } awaitable on_stop() noexcept { timer.expires_from_now(100ms); co_await timer.async_wait(use_awaitable); set_bit(cnt, 2); co_return; } awaitable on_reset() noexcept { timer.expires_from_now(100ms); co_await timer.async_wait(use_awaitable); set_bit(cnt, 3); co_return; } } node_a; co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { co_await coro_sleep(50ms); co_await node_a.reset(); co_return; }, detached); BOOST_TEST((co_await node_a.init({}) == false)); BOOST_TEST(node_a.cnt == 0b1000); BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL)); node_a.cnt = 0; BOOST_TEST((co_await node_a.init({}) == true)); BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING)); co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { co_await coro_sleep(50ms); co_await node_a.stop(); co_return; }, detached); BOOST_TEST((co_await node_a.start({}) == false)); BOOST_TEST(node_a.cnt == 0b0101); BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING)); node_a.cnt = 0b0001; co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { co_await coro_sleep(50ms); co_await node_a.reset(); co_return; }, detached); BOOST_TEST((co_await node_a.start({}) == false)); BOOST_TEST(node_a.cnt = 0b0101); BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING)); co_await coro_sleep(150ms); BOOST_TEST(node_a.cnt == 0b1101); BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL)); co_return; } awaitable test_tristate_obj_3() { struct type_a : public tristate_obj { int cnt = 0; boost::asio::high_resolution_timer timer; type_a() : timer(*global_context) {} awaitable on_init(const nlohmann::json &) noexcept { timer.expires_from_now(100ms); co_await timer.async_wait(use_awaitable); ++cnt; co_return true; } awaitable on_start(const nlohmann::json &) noexcept { timer.expires_from_now(100ms); co_await timer.async_wait(use_awaitable); ++cnt; co_return true; } awaitable on_stop() noexcept { timer.expires_from_now(100ms); co_await timer.async_wait(use_awaitable); ++cnt; co_return; } awaitable on_reset() noexcept { timer.expires_from_now(100ms); co_await timer.async_wait(use_awaitable); ++cnt; co_return; } } node_a; node_a.cnt = 0; co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { BOOST_TEST(co_await node_a.init({}) == true); BOOST_TEST(node_a.cnt == 1); }, detached); BOOST_TEST(co_await node_a.init({}) == true); BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING)); BOOST_TEST(node_a.cnt == 1); node_a.cnt = 0; co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { BOOST_TEST(co_await node_a.start({}) == true); BOOST_TEST(node_a.cnt == 1); }, detached); BOOST_TEST(co_await node_a.start({}) == true); BOOST_TEST((node_a.get_state() == type_a::state_type::RUNNING)); BOOST_TEST(node_a.cnt == 1); node_a.cnt = 0; co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { co_await node_a.stop(); BOOST_TEST(node_a.cnt == 1); }, detached); co_await node_a.stop(); BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING)); BOOST_TEST(node_a.cnt == 1); node_a.cnt = 0; co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { co_await node_a.reset(); BOOST_TEST(node_a.cnt == 1); }, detached); co_await node_a.reset(); BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL)); BOOST_TEST(node_a.cnt == 1); node_a.cnt = 0; co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { co_await coro_sleep(50ms); co_await node_a.reset(); co_return; }, detached); co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { BOOST_TEST(co_await node_a.init({}) == false); BOOST_TEST(node_a.cnt == 1); }, detached); BOOST_TEST(co_await node_a.init({}) == false); BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL)); BOOST_TEST(node_a.cnt == 1); co_await node_a.init({}); node_a.cnt = 0; co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { co_await coro_sleep(50ms); co_await node_a.stop(); co_return; }, detached); co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable { BOOST_TEST(co_await node_a.start({}) == false); BOOST_TEST(node_a.cnt == 1); }, detached); BOOST_TEST(co_await node_a.start({}) == false); BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING)); BOOST_TEST(node_a.cnt == 1); } BOOST_AUTO_TEST_CASE(test_tristate_obj) { initialize({}); co_spawn(*global_context, test_tristate_obj_1(), detached); co_spawn(*global_context, test_tristate_obj_2(), detached); co_spawn(*global_context, test_tristate_obj_3(), detached); global_context->run(); }