diff --git a/tests/tests/dsl/GroupPool.cpp b/tests/tests/dsl/GroupPool.cpp new file mode 100644 index 00000000..09f18cb6 --- /dev/null +++ b/tests/tests/dsl/GroupPool.cpp @@ -0,0 +1,111 @@ +/* + * MIT License + * + * Copyright (c) 2024 NUClear Contributors + * + * This file is part of the NUClear codebase. + * See https://github.com/Fastcode/NUClear for further info. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "test_util/TestBase.hpp" + +namespace { + +/// @brief A vector of events that have happened +std::vector events; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +/// @brief Add an event to the event list +void add_event(const std::string& event) { + static std::mutex events_mutex; + std::lock_guard lock(events_mutex); + events.push_back(event); +} + +struct StartTest {}; +struct Synced {}; +template +struct PoolFinished {}; + +static constexpr int POOL_COUNT = 10; + +class TestReactor : public test_util::TestBase { +public: + template + struct TestPool { + static constexpr int thread_count = 1; + }; + + template + void register_callbacks(NUClear::util::Sequence) { + + NUClear::util::unpack(on, Pool>, Sync>().then([this] { + add_event("Pool Message"); + emit(std::make_unique>()); + })...); + + on>...>().then([this] { + add_event("Finished"); + powerplant.shutdown(); + }); + } + + TestReactor(std::unique_ptr environment) : TestBase(std::move(environment), false) { + + on().then([this] { + add_event("Startup"); + emit(std::make_unique()); + }); + + // Trigger on the start message and emit a message that will be synced + on, Sync>().then([this] { + add_event("Send Synced Message"); + emit(std::make_unique()); + }); + + // Register all the callbacks and a final callback to gather the results + register_callbacks(NUClear::util::GenerateSequence<0, POOL_COUNT>()); + } +}; + +} // namespace + + +TEST_CASE("Test that if a pool has nothing to do because of a sync group it will recover", "[api][pool][group]") { + + NUClear::Configuration config; + config.thread_count = 1; + NUClear::PowerPlant plant(config); + plant.install(); + plant.start(); + + std::vector expected = { + "Startup", + "Send Synced Message", + }; + for (int i = 0; i < POOL_COUNT; ++i) { + expected.push_back("Pool Message"); + } + expected.push_back("Finished"); + + // Make an info print the diff in an easy to read way if we fail + INFO(test_util::diff_string(expected, events)); + + // Check the events fired in order and only those events + REQUIRE(events == expected); +}