From 3f5499cebc06356ed99159be3fb9676292cf7b8b Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 24 Jul 2024 10:44:13 +0200 Subject: turns: rename domain to core --- core/tests/disposition.cpp | 32 ++++++ core/tests/participant.cpp | 113 +++++++++++++++++++++ core/tests/register_types.cpp | 13 +++ core/tests/turn_order.cpp | 225 +++++++++++++++++++++++++++++++++++++++++ core/tests/turn_order_bugs.cpp | 42 ++++++++ 5 files changed, 425 insertions(+) create mode 100644 core/tests/disposition.cpp create mode 100644 core/tests/participant.cpp create mode 100644 core/tests/register_types.cpp create mode 100644 core/tests/turn_order.cpp create mode 100644 core/tests/turn_order_bugs.cpp (limited to 'core/tests') diff --git a/core/tests/disposition.cpp b/core/tests/disposition.cpp new file mode 100644 index 0000000..3a35741 --- /dev/null +++ b/core/tests/disposition.cpp @@ -0,0 +1,32 @@ +#include "turns/core/disposition.hpp" + +#include +#include + +#include +#include +#include +#include + +#include +#include + +namespace turns::core::tests +{ + + TEST_CASE("to_presentation_name returns the correct string for the current language", "[disposition]") + { + auto [value, name] = GENERATE(std::pair{disposition::neutral, Glib::ustring{_("Neutral")}}, + std::pair{disposition::friendly, Glib::ustring{_("Friendly")}}, + std::pair{disposition::hostile, Glib::ustring{_("Hostile")}}, + std::pair{disposition::secret, Glib::ustring{_("Secret")}}, + std::pair{static_cast(std::numeric_limits>::max()), + Glib::ustring{_("Unknown disposition value")}}); + + SECTION(std::format("the presentation name for '{}' is '{}'", static_cast>(value), name.c_str())) + { + REQUIRE(presentation_name_for(value) == name); + } + } + +} // namespace turns::core::tests \ No newline at end of file diff --git a/core/tests/participant.cpp b/core/tests/participant.cpp new file mode 100644 index 0000000..14fb1ae --- /dev/null +++ b/core/tests/participant.cpp @@ -0,0 +1,113 @@ +#include "turns/core/participant.hpp" +#include "turns/core/disposition.hpp" + +#include + +#include + +#include + +namespace turns::core::tests +{ + + TEST_CASE("A freshly constructed participant") + { + auto constexpr constructed_name = "Vana Thistletop"; + auto constexpr constructed_priority = 17; + auto constexpr constructed_disposition = disposition::friendly; + auto instance = participant{constructed_name, constructed_priority, constructed_disposition}; + + SECTION("can be created") + { + REQUIRE(participant::create(constructed_name, constructed_priority, constructed_disposition)); + } + + SECTION("allows access to its disposition") + { + SECTION("allowing to get it") + { + REQUIRE(instance.disposition() == constructed_disposition); + } + + SECTION("allowing to get it via a constant object") + { + auto const & cref = instance; + REQUIRE(cref.disposition() == constructed_disposition); + } + + SECTION("allowing to set it") + { + instance.disposition() = disposition::hostile; + REQUIRE(instance.disposition() == disposition::hostile); + } + } + + SECTION("allows access to its name") + { + SECTION("allowing to get it") + { + REQUIRE(instance.name() == constructed_name); + } + + SECTION("allowing to get it via a constant object") + { + auto const & cref = instance; + REQUIRE(cref.name() == constructed_name); + } + + SECTION("allowing to set it") + { + instance.name() = "replaced"; + REQUIRE(instance.name() == "replaced"); + } + } + + SECTION("allows access to its priority") + { + SECTION("allowing to get it") + { + REQUIRE(instance.priority() == constructed_priority); + } + + SECTION("allowing to get it via a constant object") + { + auto const & cref = instance; + REQUIRE(cref.priority() == constructed_priority); + } + + SECTION("allowing to set it") + { + instance.priority() = 4; + REQUIRE(instance.priority() == 4); + } + } + + SECTION("can be compared with another participant") + { + auto equivalent_instance = participant{"Equivalent", constructed_priority, constructed_disposition}; + auto lesser_instance = participant{"Lesser", constructed_priority - 1, constructed_disposition}; + auto greater_instance = participant{"Greater", constructed_priority + 1, constructed_disposition}; + + SECTION("yielding std::partial_ordering::equivalent for itself") + { + REQUIRE((instance <=> equivalent_instance) == std::partial_ordering::equivalent); + } + + SECTION("yielding std::partial_ordering::equivalent for an equivalent participant") + { + REQUIRE((instance <=> equivalent_instance) == std::partial_ordering::equivalent); + } + + SECTION("yielding std::partial_ordering::greater for a lesser participant") + { + REQUIRE((instance <=> lesser_instance) == std::partial_ordering::greater); + } + + SECTION("yielding std::partial_ordering::less for a greater participant") + { + REQUIRE((instance <=> greater_instance) == std::partial_ordering::less); + } + } + } + +} // namespace turns::core::tests \ No newline at end of file diff --git a/core/tests/register_types.cpp b/core/tests/register_types.cpp new file mode 100644 index 0000000..2ad0628 --- /dev/null +++ b/core/tests/register_types.cpp @@ -0,0 +1,13 @@ +#include "turns/core/participant.hpp" +#include "turns/core/turn_order.hpp" + +namespace turns::tests +{ + + auto register_types() -> void + { + static_cast(core::participant{}); + static_cast(core::turn_order{}); + } + +} // namespace turns::tests \ No newline at end of file diff --git a/core/tests/turn_order.cpp b/core/tests/turn_order.cpp new file mode 100644 index 0000000..fc779d7 --- /dev/null +++ b/core/tests/turn_order.cpp @@ -0,0 +1,225 @@ +#include "turns/core/turn_order.hpp" + +#include "turns/core/participant.hpp" + +#include + +#include + +namespace turns::core::tests +{ + SCENARIO("Queries on a fresh turn_order instance", "[turn_order]") + { + GIVEN("an empty turn_order") + { + auto instance = turn_order::create(); + + THEN("get_n_items() returns 0") + { + auto str = Gio::ListStore::create(); + REQUIRE(instance->get_n_items() == str->get_n_items()); + } + + THEN("get_type() returns participant::get_type()") + { + REQUIRE(instance->get_item_type() == participant::get_type()); + } + + THEN("get_typed_object(0) returns nullptr") + { + REQUIRE(instance->get_typed_object(0) == nullptr); + } + + THEN("has_next() returns false") + { + REQUIRE_FALSE(instance->has_next()); + } + + THEN("has_previous() returns false") + { + REQUIRE_FALSE(instance->has_previous()); + } + + THEN("is_empty() returns true") + { + REQUIRE(instance->is_empty()); + } + + THEN("is_running() returns false") + { + REQUIRE_FALSE(instance->is_running()); + } + + THEN("round_number() returns invalid_round_number") + { + REQUIRE(instance->round_number() == turn_order::invalid_round_number); + } + } + } + + SCENARIO("Adding participants") + { + auto instance = turn_order::create(); + + GIVEN("a participant has been added to a turn_order") + { + instance->add("Participant #0", 0, disposition::neutral); + + THEN("get_n_items() returns 1") + { + REQUIRE(instance->get_n_items() == 1); + } + + THEN("get_typed_object(0) returns a non-null pointer") + { + REQUIRE(instance->get_typed_object(0) != nullptr); + } + + THEN("has_next() returns true") + { + REQUIRE(instance->has_next()); + } + + THEN("has_previous() returns false") + { + REQUIRE_FALSE(instance->has_previous()); + } + + THEN("is_empty() returns false") + { + REQUIRE_FALSE(instance->is_empty()); + } + + THEN("is_running() returns false") + { + REQUIRE_FALSE(instance->is_running()); + } + + THEN("round_number() returns invalid_round_number") + { + REQUIRE(instance->round_number() == turn_order::invalid_round_number); + } + + WHEN("the turn_order is start()ed") + { + instance->start(); + + THEN("get_n_items() still returns 1") + { + REQUIRE(instance->get_n_items() == 1); + } + + THEN("get_typed_object(0) still returns a non-null pointer") + { + REQUIRE(instance->get_typed_object(0) != nullptr); + } + + THEN("has_next() still returns true") + { + REQUIRE(instance->has_next()); + } + + THEN("has_previous() still returns false") + { + REQUIRE_FALSE(instance->has_previous()); + } + + THEN("is_empty() still returns false") + { + REQUIRE_FALSE(instance->is_empty()); + } + + THEN("is_running() returns true") + { + REQUIRE(instance->is_running()); + } + + THEN("round_number() returns 0") + { + REQUIRE(instance->round_number() == 0); + } + + AND_WHEN("invoking previous()") + { + instance->previous(); + + THEN("get_n_items() still returns 1") + { + REQUIRE(instance->get_n_items() == 1); + } + + THEN("get_typed_object(0) still returns a non-null pointer") + { + REQUIRE(instance->get_typed_object(0) != nullptr); + } + + THEN("has_next() still returns true") + { + REQUIRE(instance->has_next()); + } + + THEN("has_previous() still returns false") + { + REQUIRE_FALSE(instance->has_previous()); + } + + THEN("is_empty() still returns false") + { + REQUIRE_FALSE(instance->is_empty()); + } + + THEN("is_running() returns true") + { + REQUIRE(instance->is_running()); + } + + THEN("round_number() returns 0") + { + REQUIRE(instance->round_number() == 0); + } + } + + AND_WHEN("invoking next()") + { + instance->next(); + + THEN("get_n_items() still returns 1") + { + REQUIRE(instance->get_n_items() == 1); + } + + THEN("get_typed_object(0) still returns a non-null pointer") + { + REQUIRE(instance->get_typed_object(0) != nullptr); + } + + THEN("has_next() still returns true") + { + REQUIRE(instance->has_next()); + } + + THEN("has_previous() returns true") + { + REQUIRE(instance->has_previous()); + } + + THEN("is_empty() still returns false") + { + REQUIRE_FALSE(instance->is_empty()); + } + + THEN("is_running() returns true") + { + REQUIRE(instance->is_running()); + } + + THEN("round_number() returns 1") + { + REQUIRE(instance->round_number() == 1); + } + } + } + } + } + +} // namespace turns::core::tests \ No newline at end of file diff --git a/core/tests/turn_order_bugs.cpp b/core/tests/turn_order_bugs.cpp new file mode 100644 index 0000000..0fa0720 --- /dev/null +++ b/core/tests/turn_order_bugs.cpp @@ -0,0 +1,42 @@ +#include "turns/core/participant.hpp" +#include "turns/core/turn_order.hpp" + +#include + +#include + +namespace turns::core::tests +{ + /** + * Bug description: + * + * After having stepped according to the step pattern below, tt was possible to step backward often enough to underflow the round number: + * - forward + * - backward + * - forward + */ + SCENARIO("Can step back infinitely", "[turn_order][bug]") + { + GIVEN("a non-empty turn_order") + { + auto instance = turn_order::create(); + + instance->add("A", 0, disposition::neutral); + + WHEN("it is started and then stepped forward, backward, forward") + { + instance->start(); + instance->next(); + instance->previous(); + instance->next(); + + THEN("it is not possible to step backwards more than once") + { + instance->previous(); + instance->previous(); + REQUIRE(instance->round_number() == 0); + } + } + } + } +} // namespace turns::core::tests \ No newline at end of file -- cgit v1.2.3