From 8ce3635d39dbdd101ddf180a66c483162df99c04 Mon Sep 17 00:00:00 2001 From: Treeston Date: Sat, 29 Aug 2020 22:03:22 +0200 Subject: UnitTests: Cleanup + StringConvert/ChatCommand tests (PR #25353) --- tests/CMakeLists.txt | 26 ++- tests/common/EventMap.cpp | 386 +++++++++++++++++++++++++++++++++++++++++ tests/common/StringConvert.cpp | 131 ++++++++++++++ tests/common/Timer.cpp | 59 +++++++ tests/common/test-EventMap.cpp | 386 ----------------------------------------- tests/common/test-Timer.cpp | 59 ------- tests/common/test-main.cpp | 20 --- tests/game/ChatCommand.cpp | 64 +++++++ tests/main.cpp | 20 +++ tests/tc_catch2.h | 44 +++++ 10 files changed, 723 insertions(+), 472 deletions(-) create mode 100644 tests/common/EventMap.cpp create mode 100644 tests/common/StringConvert.cpp create mode 100644 tests/common/Timer.cpp delete mode 100644 tests/common/test-EventMap.cpp delete mode 100644 tests/common/test-Timer.cpp delete mode 100644 tests/common/test-main.cpp create mode 100644 tests/game/ChatCommand.cpp create mode 100644 tests/main.cpp create mode 100644 tests/tc_catch2.h (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 40cceb78e1e..a55b7a06523 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,21 +9,33 @@ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. CollectSourceFiles( - ${CMAKE_CURRENT_SOURCE_DIR}/common - COMMON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR} + TEST_SOURCES ) -add_executable(tests-common ${COMMON_SOURCES}) +GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(tests-common +add_executable(tests ${TEST_SOURCES}) + +target_link_libraries(tests PRIVATE trinity-core-interface - common + game Catch2::Catch2) -catch_discover_tests(tests-common) +CollectIncludeDirectories( + ${CMAKE_CURRENT_SOURCE_DIR} + TEST_INCLUDES) + +target_include_directories(tests + PUBLIC + ${TEST_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) + +catch_discover_tests(tests) -set_target_properties(tests-common +set_target_properties(tests PROPERTIES FOLDER "tests") diff --git a/tests/common/EventMap.cpp b/tests/common/EventMap.cpp new file mode 100644 index 00000000000..1f3ff927fef --- /dev/null +++ b/tests/common/EventMap.cpp @@ -0,0 +1,386 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#include "tc_catch2.h" + +#include "EventMap.h" + +enum EVENTS +{ + EVENT_1 = 1, + EVENT_2 = 2, + EVENT_3 = 3 +}; + +enum PHASES +{ + PHASE_1 = 1, + PHASE_2 = 2 +}; + +enum GROUPS +{ + GROUP_1 = 1, + GROUP_2 = 2 +}; + +TEST_CASE("Schedule an event", "[EventMap]") +{ + EventMap eventMap; + + REQUIRE(eventMap.Empty()); + + eventMap.ScheduleEvent(EVENT_1, 1s); + + REQUIRE_FALSE(eventMap.Empty()); + + SECTION("Event has not yet reached its delay") + { + eventMap.Update(100); + uint32 id = eventMap.ExecuteEvent(); + + REQUIRE(id == 0); + REQUIRE_FALSE(eventMap.Empty()); + REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 900ms); + } + + SECTION("Event has reached its delay") + { + eventMap.Update(1000); + uint32 id = eventMap.ExecuteEvent(); + + REQUIRE(id == EVENT_1); + REQUIRE(eventMap.Empty()); + REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == Milliseconds::max()); + } + + SECTION("Event is past it's execution time") + { + eventMap.Update(2000); + + REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == -1s); + } +} + +TEST_CASE("Schedule existing event", "[EventMap]") +{ + EventMap eventMap; + + SECTION("Same time") + { + eventMap.ScheduleEvent(EVENT_1, 1s); + eventMap.ScheduleEvent(EVENT_1, 1s); + + eventMap.Update(1000); + uint32 id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_1); + + id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_1); + + REQUIRE(eventMap.Empty()); + } + + SECTION("Different time") + { + eventMap.ScheduleEvent(EVENT_1, 1s); + eventMap.ScheduleEvent(EVENT_1, 2s); + + eventMap.Update(1000); + uint32 id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_1); + + eventMap.Update(1000); + id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_1); + + REQUIRE(eventMap.Empty()); + } +} + +TEST_CASE("Cancel a scheduled event", "[EventMap]") +{ + EventMap eventMap; + + eventMap.ScheduleEvent(EVENT_1, 1s); + eventMap.ScheduleEvent(EVENT_2, 1s); + + eventMap.CancelEvent(EVENT_1); + REQUIRE_FALSE(eventMap.Empty()); + + eventMap.Update(1000); + uint32 id = eventMap.ExecuteEvent(); + + REQUIRE(id == EVENT_2); + REQUIRE(eventMap.Empty()); +} + +TEST_CASE("Cancel non-existing event", "[EventMap]") +{ + EventMap eventMap; + REQUIRE(eventMap.Empty()); + + eventMap.CancelEvent(EVENT_1); + REQUIRE(eventMap.Empty()); +} + +TEST_CASE("Reschedule an event", "[EventMap]") +{ + EventMap eventMap; + + eventMap.ScheduleEvent(EVENT_1, 1s); + eventMap.RescheduleEvent(EVENT_1, 2s); + + eventMap.Update(1000); + uint32 id = eventMap.ExecuteEvent(); + + REQUIRE(id == 0); + + eventMap.Update(1000); + id = eventMap.ExecuteEvent(); + + REQUIRE(id == EVENT_1); +} + +TEST_CASE("Reschedule a non-scheduled event", "[EventMap]") +{ + EventMap eventMap; + + eventMap.RescheduleEvent(EVENT_1, 2s); + + eventMap.Update(1000); + uint32 id = eventMap.ExecuteEvent(); + + REQUIRE(id == 0); + + eventMap.Update(1000); + id = eventMap.ExecuteEvent(); + + REQUIRE(id == EVENT_1); +} + +TEST_CASE("Repeat an event (empty map)", "[EventMap]") +{ + EventMap eventMap; + + eventMap.Repeat(1s); + eventMap.Update(1s); + + uint32 id = eventMap.ExecuteEvent(); + REQUIRE(id == 0); +} + +TEST_CASE("Repeat an event (populated map)", "[EventMap]") +{ + EventMap eventMap; + eventMap.ScheduleEvent(EVENT_1, 1s); + + SECTION("Scheduled event with delay not reached") + { + eventMap.Update(500ms); + eventMap.Repeat(1s); + + uint32 id = eventMap.ExecuteEvent(); + REQUIRE(id == 0); + } + + SECTION("Scheduled event with delay not reached") + { + eventMap.Update(1s); + eventMap.Repeat(1s); + + uint32 id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_1); + } +} + +TEST_CASE("Schedule event with phase", "[EventMap]") +{ + EventMap eventMap; + REQUIRE(eventMap.Empty()); + + eventMap.ScheduleEvent(EVENT_1, 1s, 0, PHASE_1); + eventMap.ScheduleEvent(EVENT_2, 1s, 0, PHASE_2); + + SECTION("In default phase. Execute all events.") + { + eventMap.Update(1000); + + uint32 id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_1); + REQUIRE_FALSE(eventMap.Empty()); + + id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_2); + REQUIRE(eventMap.Empty()); + } + + SECTION("Execute only events of specified phase") + { + eventMap.SetPhase(PHASE_1); + eventMap.Update(1000); + + uint32 id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_1); + REQUIRE_FALSE(eventMap.Empty()); + + id = eventMap.ExecuteEvent(); + REQUIRE(id == 0); + REQUIRE(eventMap.Empty()); + } + + SECTION("Execute events from multiple phases (1)") + { + eventMap.AddPhase(PHASE_1); + eventMap.AddPhase(PHASE_2); + eventMap.Update(1000); + + uint32 id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_1); + REQUIRE_FALSE(eventMap.Empty()); + + id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_2); + REQUIRE(eventMap.Empty()); + } + + SECTION("Execute events from multiple phases (2)") + { + eventMap.AddPhase(PHASE_1); + eventMap.Update(1000); + + uint32 id = eventMap.ExecuteEvent(); + REQUIRE(id == EVENT_1); + REQUIRE_FALSE(eventMap.Empty()); + + eventMap.RemovePhase(PHASE_2); + id = eventMap.ExecuteEvent(); + REQUIRE(id == 0); + REQUIRE(eventMap.Empty()); + } +} + +TEST_CASE("Phase helper methods", "[EventMap]") +{ + EventMap eventMap; + + eventMap.SetPhase(PHASE_1); + REQUIRE(eventMap.GetPhaseMask() == 0x1); + REQUIRE(eventMap.IsInPhase(PHASE_1)); + REQUIRE_FALSE(eventMap.IsInPhase(PHASE_2)); + + eventMap.AddPhase(PHASE_2); + REQUIRE(eventMap.GetPhaseMask() == 0x3); + REQUIRE(eventMap.IsInPhase(PHASE_1)); + REQUIRE(eventMap.IsInPhase(PHASE_2)); + + eventMap.RemovePhase(PHASE_1); + REQUIRE(eventMap.GetPhaseMask() == 0x2); + REQUIRE_FALSE(eventMap.IsInPhase(PHASE_1)); + REQUIRE(eventMap.IsInPhase(PHASE_2)); +} + +TEST_CASE("Cancel event group", "[EventMap]") +{ + EventMap eventMap; + eventMap.ScheduleEvent(EVENT_2, 1s, GROUP_1); + + SECTION("Only event in group") + { + eventMap.CancelEventGroup(GROUP_1); + REQUIRE(eventMap.Empty()); + } + + SECTION("Group with groupless event") + { + eventMap.ScheduleEvent(EVENT_1, 1s); + + eventMap.CancelEventGroup(GROUP_1); + REQUIRE_FALSE(eventMap.Empty()); + } + + SECTION("Two groups") + { + eventMap.ScheduleEvent(EVENT_1, 1s); + eventMap.ScheduleEvent(EVENT_3, 1s, GROUP_2); + + eventMap.CancelEventGroup(GROUP_1); + REQUIRE_FALSE(eventMap.Empty()); + + eventMap.CancelEventGroup(GROUP_2); + REQUIRE_FALSE(eventMap.Empty()); + } +} + +TEST_CASE("Delay all events", "[EventMap]") +{ + EventMap eventMap; + eventMap.ScheduleEvent(EVENT_1, 1s); + + REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 1s); + + SECTION("Without timer update") + { + eventMap.DelayEvents(1s); + + // 1s (init) + 1s (delay) = 2s + REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 2s); + } + + SECTION("With timer update smaller than delay") + { + eventMap.Update(500); + eventMap.DelayEvents(1s); + + // 1s (init) + 1s (delay) - 500ms (tick) = 1500ms + REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 1500ms); + } + + SECTION("With timer update larger than delay") + { + eventMap.Update(2000); + eventMap.DelayEvents(1s); + + // 1s (init) + 1s (delay) - 2s (tick) = 0s + REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 0s); + } +} + +TEST_CASE("Delay grouped events", "[EventMap]") +{ + EventMap eventMap; + eventMap.ScheduleEvent(EVENT_1, 1s, GROUP_1); + eventMap.ScheduleEvent(EVENT_2, 2s, GROUP_2); + eventMap.ScheduleEvent(EVENT_3, 6s); + + eventMap.Update(2000); + eventMap.DelayEvents(3s, GROUP_1); + + REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 2s); + REQUIRE(eventMap.GetTimeUntilEvent(EVENT_2) == 0s); + REQUIRE(eventMap.GetTimeUntilEvent(EVENT_3) == 4s); +} + +TEST_CASE("Reset map", "[EventMap]") +{ + EventMap eventMap; + eventMap.ScheduleEvent(EVENT_1, 1s); + eventMap.Reset(); + + REQUIRE(eventMap.Empty()); +} diff --git a/tests/common/StringConvert.cpp b/tests/common/StringConvert.cpp new file mode 100644 index 00000000000..d25e28f3d19 --- /dev/null +++ b/tests/common/StringConvert.cpp @@ -0,0 +1,131 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "tc_catch2.h" + +#include "StringConvert.h" + +TEST_CASE("String to uint32", "[StringConvert]") +{ + REQUIRE(Trinity::StringTo("42") == 42); + REQUIRE(Trinity::StringTo("42", 10) == 42); + REQUIRE(Trinity::StringTo(" 42") == std::nullopt); + REQUIRE(Trinity::StringTo("tail42") == std::nullopt); + REQUIRE(Trinity::StringTo("42tail") == std::nullopt); + + REQUIRE(Trinity::StringTo("ff", 16) == 0xff); + REQUIRE(Trinity::StringTo("0xff") == std::nullopt); + REQUIRE(Trinity::StringTo("0xff", 0) == 0xff); + + REQUIRE(Trinity::StringTo("101010", 2) == 0b101010); + REQUIRE(Trinity::StringTo("0b101010") == std::nullopt); + REQUIRE(Trinity::StringTo("0b101010", 0) == 0b101010); + + REQUIRE(Trinity::StringTo("5000000000") == std::nullopt); + REQUIRE(Trinity::StringTo("100000000", 16) == std::nullopt); + REQUIRE(Trinity::StringTo("0x100000000", 0) == std::nullopt); + REQUIRE(Trinity::StringTo("0xffffffff", 0) == 0xffffffff); +} + +TEST_CASE("String to uint64", "[StringConvert]") +{ + REQUIRE(Trinity::StringTo("42") == 42); + REQUIRE(Trinity::StringTo("42", 10) == 42); + REQUIRE(Trinity::StringTo(" 42") == std::nullopt); + REQUIRE(Trinity::StringTo("tail42") == std::nullopt); + REQUIRE(Trinity::StringTo("42tail") == std::nullopt); + REQUIRE(Trinity::StringTo("-1", 0) == std::nullopt); + + REQUIRE(Trinity::StringTo("ff", 16) == 0xff); + REQUIRE(Trinity::StringTo("0xff") == std::nullopt); + REQUIRE(Trinity::StringTo("0xff", 0) == 0xff); + + REQUIRE(Trinity::StringTo("101010", 2) == 0b101010); + REQUIRE(Trinity::StringTo("0b101010") == std::nullopt); + REQUIRE(Trinity::StringTo("0b101010", 0) == 0b101010); + + REQUIRE(Trinity::StringTo("5000000000") == 5000000000ULL); + REQUIRE(Trinity::StringTo("100000000", 16) == 0x100000000ULL); + + REQUIRE(Trinity::StringTo("20000000000000000000") == std::nullopt); + REQUIRE(Trinity::StringTo("10000000000000000", 16) == std::nullopt); + REQUIRE(Trinity::StringTo("0x10000000000000000", 0) == std::nullopt); + REQUIRE(Trinity::StringTo("0xFFFFFFFFFFFFFFFF", 0) == 0xffffffffffffffffULL); +} + +TEST_CASE("String to int32", "[StringConvert]") +{ + REQUIRE(Trinity::StringTo("-42") == -42); + REQUIRE(Trinity::StringTo("42") == 42); + REQUIRE(Trinity::StringTo("+42") == std::nullopt); + REQUIRE(Trinity::StringTo("--42") == std::nullopt); + REQUIRE(Trinity::StringTo("~42") == std::nullopt); + REQUIRE(Trinity::StringTo("42-") == std::nullopt); + + REQUIRE(Trinity::StringTo("-ffff", 16) == -0xffff); + REQUIRE(Trinity::StringTo("ffffffff", 16) == std::nullopt); + REQUIRE(Trinity::StringTo("7fffffff", 16) == 0x7fffffff); +} + +TEST_CASE("String to int64", "[StringConvert]") +{ + REQUIRE(Trinity::StringTo("-42") == -42); + REQUIRE(Trinity::StringTo("42") == 42); + REQUIRE(Trinity::StringTo("+42") == std::nullopt); + REQUIRE(Trinity::StringTo("--42") == std::nullopt); + REQUIRE(Trinity::StringTo("~42") == std::nullopt); + REQUIRE(Trinity::StringTo("42-") == std::nullopt); + + REQUIRE(Trinity::StringTo("-ffff", 16) == -0xffff); + REQUIRE(Trinity::StringTo("ffffffff", 16) == 0xffffffff); + REQUIRE(Trinity::StringTo("7fffffff", 16) == 0x7fffffff); + + REQUIRE(Trinity::StringTo("ffffffffffffffff", 16) == std::nullopt); + REQUIRE(Trinity::StringTo("7fffffffffffffff", 16) == 0x7fffffffffffffffLL); + + REQUIRE(Trinity::StringTo("-8500000000000000", 16) == std::nullopt); +} + +TEST_CASE("String to smaller integer types", "[StringConvert]") +{ + REQUIRE(Trinity::StringTo("0xff", 0) == 0xff); + REQUIRE(Trinity::StringTo("0x1ff", 0) == std::nullopt); + + REQUIRE(Trinity::StringTo("0xff", 0) == std::nullopt); + REQUIRE(Trinity::StringTo("0x7f", 0) == 0x7f); + REQUIRE(Trinity::StringTo("-7f", 16) == -0x7f); + + REQUIRE(Trinity::StringTo("0x1ff", 0) == 0x1ff); + REQUIRE(Trinity::StringTo("0x1ffff", 0) == std::nullopt); + REQUIRE(Trinity::StringTo("-1", 0) == std::nullopt); + + REQUIRE(Trinity::StringTo("0x1ff", 0) == 0x1ff); + REQUIRE(Trinity::StringTo("0xffff", 0) == std::nullopt); + REQUIRE(Trinity::StringTo("0x7fff", 0) == 0x7fff); + REQUIRE(Trinity::StringTo("-1", 0) == -1); +} + +TEST_CASE("Test.String to boolean", "[StringConvert]") +{ + REQUIRE(Trinity::StringTo("true") == true); + REQUIRE(Trinity::StringTo("false") == false); + REQUIRE(Trinity::StringTo("ture") == std::nullopt); + REQUIRE(Trinity::StringTo("true", 10) == std::nullopt); + REQUIRE(Trinity::StringTo("1") == true); + REQUIRE(Trinity::StringTo("1", 10) == true); + REQUIRE(Trinity::StringTo("0", 10) == false); +} diff --git a/tests/common/Timer.cpp b/tests/common/Timer.cpp new file mode 100644 index 00000000000..9117b1338a1 --- /dev/null +++ b/tests/common/Timer.cpp @@ -0,0 +1,59 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#include "tc_catch2.h" + +#include "Timer.h" + +TEST_CASE("TimeTracker: Check if time passed") +{ + TimeTracker tracker(1000 /*ms*/); + REQUIRE_FALSE(tracker.Passed()); + REQUIRE(tracker.GetExpiry() == 1s); + + tracker.Update(500 /*ms*/); + REQUIRE_FALSE(tracker.Passed()); + REQUIRE(tracker.GetExpiry() == 500ms); + + tracker.Update(500 /*ms*/); + REQUIRE(tracker.Passed()); + REQUIRE(tracker.GetExpiry() == 0s); + + tracker.Update(500 /*ms*/); + REQUIRE(tracker.Passed()); + REQUIRE(tracker.GetExpiry() == -500ms); +} + +TEST_CASE("TimeTracker: Reset timer") +{ + TimeTracker tracker(1000 /*ms*/); + REQUIRE_FALSE(tracker.Passed()); + REQUIRE(tracker.GetExpiry() == 1s); + + tracker.Update(1000 /*ms*/); + REQUIRE(tracker.Passed()); + REQUIRE(tracker.GetExpiry() == 0s); + + tracker.Reset(1000 /*ms*/); + REQUIRE_FALSE(tracker.Passed()); + REQUIRE(tracker.GetExpiry() == 1s); + + tracker.Update(1000 /*ms*/); + REQUIRE(tracker.Passed()); + REQUIRE(tracker.GetExpiry() == 0s); +} diff --git a/tests/common/test-EventMap.cpp b/tests/common/test-EventMap.cpp deleted file mode 100644 index 31b27af5daa..00000000000 --- a/tests/common/test-EventMap.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -#include "catch2/catch.hpp" - -#include "EventMap.h" - -enum EVENTS -{ - EVENT_1 = 1, - EVENT_2 = 2, - EVENT_3 = 3 -}; - -enum PHASES -{ - PHASE_1 = 1, - PHASE_2 = 2 -}; - -enum GROUPS -{ - GROUP_1 = 1, - GROUP_2 = 2 -}; - -TEST_CASE("Schedule an event", "[EventMap]") -{ - EventMap eventMap; - - REQUIRE(eventMap.Empty()); - - eventMap.ScheduleEvent(EVENT_1, 1s); - - REQUIRE_FALSE(eventMap.Empty()); - - SECTION("Event has not yet reached its delay") - { - eventMap.Update(100); - uint32 id = eventMap.ExecuteEvent(); - - REQUIRE(id == 0); - REQUIRE_FALSE(eventMap.Empty()); - REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 900ms); - } - - SECTION("Event has reached its delay") - { - eventMap.Update(1000); - uint32 id = eventMap.ExecuteEvent(); - - REQUIRE(id == EVENT_1); - REQUIRE(eventMap.Empty()); - REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == Milliseconds::max()); - } - - SECTION("Event is past it's execution time") - { - eventMap.Update(2000); - - REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == -1s); - } -} - -TEST_CASE("Schedule existing event", "[EventMap]") -{ - EventMap eventMap; - - SECTION("Same time") - { - eventMap.ScheduleEvent(EVENT_1, 1s); - eventMap.ScheduleEvent(EVENT_1, 1s); - - eventMap.Update(1000); - uint32 id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_1); - - id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_1); - - REQUIRE(eventMap.Empty()); - } - - SECTION("Different time") - { - eventMap.ScheduleEvent(EVENT_1, 1s); - eventMap.ScheduleEvent(EVENT_1, 2s); - - eventMap.Update(1000); - uint32 id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_1); - - eventMap.Update(1000); - id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_1); - - REQUIRE(eventMap.Empty()); - } -} - -TEST_CASE("Cancel a scheduled event", "[EventMap]") -{ - EventMap eventMap; - - eventMap.ScheduleEvent(EVENT_1, 1s); - eventMap.ScheduleEvent(EVENT_2, 1s); - - eventMap.CancelEvent(EVENT_1); - REQUIRE_FALSE(eventMap.Empty()); - - eventMap.Update(1000); - uint32 id = eventMap.ExecuteEvent(); - - REQUIRE(id == EVENT_2); - REQUIRE(eventMap.Empty()); -} - -TEST_CASE("Cancel non-existing event", "[EventMap]") -{ - EventMap eventMap; - REQUIRE(eventMap.Empty()); - - eventMap.CancelEvent(EVENT_1); - REQUIRE(eventMap.Empty()); -} - -TEST_CASE("Reschedule an event", "[EventMap]") -{ - EventMap eventMap; - - eventMap.ScheduleEvent(EVENT_1, 1s); - eventMap.RescheduleEvent(EVENT_1, 2s); - - eventMap.Update(1000); - uint32 id = eventMap.ExecuteEvent(); - - REQUIRE(id == 0); - - eventMap.Update(1000); - id = eventMap.ExecuteEvent(); - - REQUIRE(id == EVENT_1); -} - -TEST_CASE("Reschedule a non-scheduled event", "[EventMap]") -{ - EventMap eventMap; - - eventMap.RescheduleEvent(EVENT_1, 2s); - - eventMap.Update(1000); - uint32 id = eventMap.ExecuteEvent(); - - REQUIRE(id == 0); - - eventMap.Update(1000); - id = eventMap.ExecuteEvent(); - - REQUIRE(id == EVENT_1); -} - -TEST_CASE("Repeat an event (empty map)", "[EventMap]") -{ - EventMap eventMap; - - eventMap.Repeat(1s); - eventMap.Update(1s); - - uint32 id = eventMap.ExecuteEvent(); - REQUIRE(id == 0); -} - -TEST_CASE("Repeat an event (populated map)", "[EventMap]") -{ - EventMap eventMap; - eventMap.ScheduleEvent(EVENT_1, 1s); - - SECTION("Scheduled event with delay not reached") - { - eventMap.Update(500ms); - eventMap.Repeat(1s); - - uint32 id = eventMap.ExecuteEvent(); - REQUIRE(id == 0); - } - - SECTION("Scheduled event with delay not reached") - { - eventMap.Update(1s); - eventMap.Repeat(1s); - - uint32 id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_1); - } -} - -TEST_CASE("Schedule event with phase", "[EventMap]") -{ - EventMap eventMap; - REQUIRE(eventMap.Empty()); - - eventMap.ScheduleEvent(EVENT_1, 1s, 0, PHASE_1); - eventMap.ScheduleEvent(EVENT_2, 1s, 0, PHASE_2); - - SECTION("In default phase. Execute all events.") - { - eventMap.Update(1000); - - uint32 id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_1); - REQUIRE_FALSE(eventMap.Empty()); - - id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_2); - REQUIRE(eventMap.Empty()); - } - - SECTION("Execute only events of specified phase") - { - eventMap.SetPhase(PHASE_1); - eventMap.Update(1000); - - uint32 id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_1); - REQUIRE_FALSE(eventMap.Empty()); - - id = eventMap.ExecuteEvent(); - REQUIRE(id == 0); - REQUIRE(eventMap.Empty()); - } - - SECTION("Execute events from multiple phases (1)") - { - eventMap.AddPhase(PHASE_1); - eventMap.AddPhase(PHASE_2); - eventMap.Update(1000); - - uint32 id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_1); - REQUIRE_FALSE(eventMap.Empty()); - - id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_2); - REQUIRE(eventMap.Empty()); - } - - SECTION("Execute events from multiple phases (2)") - { - eventMap.AddPhase(PHASE_1); - eventMap.Update(1000); - - uint32 id = eventMap.ExecuteEvent(); - REQUIRE(id == EVENT_1); - REQUIRE_FALSE(eventMap.Empty()); - - eventMap.RemovePhase(PHASE_2); - id = eventMap.ExecuteEvent(); - REQUIRE(id == 0); - REQUIRE(eventMap.Empty()); - } -} - -TEST_CASE("Phase helper methods", "[EventMap]") -{ - EventMap eventMap; - - eventMap.SetPhase(PHASE_1); - REQUIRE(eventMap.GetPhaseMask() == 0x1); - REQUIRE(eventMap.IsInPhase(PHASE_1)); - REQUIRE_FALSE(eventMap.IsInPhase(PHASE_2)); - - eventMap.AddPhase(PHASE_2); - REQUIRE(eventMap.GetPhaseMask() == 0x3); - REQUIRE(eventMap.IsInPhase(PHASE_1)); - REQUIRE(eventMap.IsInPhase(PHASE_2)); - - eventMap.RemovePhase(PHASE_1); - REQUIRE(eventMap.GetPhaseMask() == 0x2); - REQUIRE_FALSE(eventMap.IsInPhase(PHASE_1)); - REQUIRE(eventMap.IsInPhase(PHASE_2)); -} - -TEST_CASE("Cancel event group", "[EventMap]") -{ - EventMap eventMap; - eventMap.ScheduleEvent(EVENT_2, 1s, GROUP_1); - - SECTION("Only event in group") - { - eventMap.CancelEventGroup(GROUP_1); - REQUIRE(eventMap.Empty()); - } - - SECTION("Group with groupless event") - { - eventMap.ScheduleEvent(EVENT_1, 1s); - - eventMap.CancelEventGroup(GROUP_1); - REQUIRE_FALSE(eventMap.Empty()); - } - - SECTION("Two groups") - { - eventMap.ScheduleEvent(EVENT_1, 1s); - eventMap.ScheduleEvent(EVENT_3, 1s, GROUP_2); - - eventMap.CancelEventGroup(GROUP_1); - REQUIRE_FALSE(eventMap.Empty()); - - eventMap.CancelEventGroup(GROUP_2); - REQUIRE_FALSE(eventMap.Empty()); - } -} - -TEST_CASE("Delay all events", "[EventMap]") -{ - EventMap eventMap; - eventMap.ScheduleEvent(EVENT_1, 1s); - - REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 1s); - - SECTION("Without timer update") - { - eventMap.DelayEvents(1s); - - // 1s (init) + 1s (delay) = 2s - REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 2s); - } - - SECTION("With timer update smaller than delay") - { - eventMap.Update(500); - eventMap.DelayEvents(1s); - - // 1s (init) + 1s (delay) - 500ms (tick) = 1500ms - REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 1500ms); - } - - SECTION("With timer update larger than delay") - { - eventMap.Update(2000); - eventMap.DelayEvents(1s); - - // 1s (init) + 1s (delay) - 2s (tick) = 0s - REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 0s); - } -} - -TEST_CASE("Delay grouped events", "[EventMap]") -{ - EventMap eventMap; - eventMap.ScheduleEvent(EVENT_1, 1s, GROUP_1); - eventMap.ScheduleEvent(EVENT_2, 2s, GROUP_2); - eventMap.ScheduleEvent(EVENT_3, 6s); - - eventMap.Update(2000); - eventMap.DelayEvents(3s, GROUP_1); - - REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 2s); - REQUIRE(eventMap.GetTimeUntilEvent(EVENT_2) == 0s); - REQUIRE(eventMap.GetTimeUntilEvent(EVENT_3) == 4s); -} - -TEST_CASE("Reset map", "[EventMap]") -{ - EventMap eventMap; - eventMap.ScheduleEvent(EVENT_1, 1s); - eventMap.Reset(); - - REQUIRE(eventMap.Empty()); -} diff --git a/tests/common/test-Timer.cpp b/tests/common/test-Timer.cpp deleted file mode 100644 index 76d02d51aa0..00000000000 --- a/tests/common/test-Timer.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -#include "catch2/catch.hpp" - -#include "Timer.h" - -TEST_CASE("TimeTracker: Check if time passed") -{ - TimeTracker tracker(1000 /*ms*/); - REQUIRE_FALSE(tracker.Passed()); - REQUIRE(tracker.GetExpiry() == 1s); - - tracker.Update(500 /*ms*/); - REQUIRE_FALSE(tracker.Passed()); - REQUIRE(tracker.GetExpiry() == 500ms); - - tracker.Update(500 /*ms*/); - REQUIRE(tracker.Passed()); - REQUIRE(tracker.GetExpiry() == 0s); - - tracker.Update(500 /*ms*/); - REQUIRE(tracker.Passed()); - REQUIRE(tracker.GetExpiry() == -500ms); -} - -TEST_CASE("TimeTracker: Reset timer") -{ - TimeTracker tracker(1000 /*ms*/); - REQUIRE_FALSE(tracker.Passed()); - REQUIRE(tracker.GetExpiry() == 1s); - - tracker.Update(1000 /*ms*/); - REQUIRE(tracker.Passed()); - REQUIRE(tracker.GetExpiry() == 0s); - - tracker.Reset(1000 /*ms*/); - REQUIRE_FALSE(tracker.Passed()); - REQUIRE(tracker.GetExpiry() == 1s); - - tracker.Update(1000 /*ms*/); - REQUIRE(tracker.Passed()); - REQUIRE(tracker.GetExpiry() == 0s); -} diff --git a/tests/common/test-main.cpp b/tests/common/test-main.cpp deleted file mode 100644 index 8ed9dd5863b..00000000000 --- a/tests/common/test-main.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - - -#define CATCH_CONFIG_MAIN -#include "catch2/catch.hpp" diff --git a/tests/game/ChatCommand.cpp b/tests/game/ChatCommand.cpp new file mode 100644 index 00000000000..5aab641deba --- /dev/null +++ b/tests/game/ChatCommand.cpp @@ -0,0 +1,64 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "tc_catch2.h" + +#include "ChatCommand.h" + +using namespace Trinity::ChatCommands; +using namespace std::string_view_literals; + +template +static void TestChatCommand(char const* c, F f, Optional expected = true) +{ + bool r = ChatCommand("", 0, false, +f, "")(nullptr, c); + if (expected) + ASSERT(r == *expected); +} + +TEST_CASE("Command return pass-through", "[ChatCommand]") +{ + TestChatCommand("", [](ChatHandler*) { return true; }, true); + TestChatCommand("", [](ChatHandler*) { return false; }, false); +} + +TEST_CASE("Command argument parsing", "[ChatCommand]") +{ + TestChatCommand("42", [](ChatHandler*, uint32 u) + { + REQUIRE(u == 42); + return true; + }); + + TestChatCommand("true", [](ChatHandler*, uint32) { return true; }, false); + + TestChatCommand("1 2 3 4 5 6 7 8 9 10", [](ChatHandler*, std::vector v) + { + REQUIRE(v.size() == 10); + for (size_t i = 0; i < 10; ++i) + REQUIRE(v[i] == (i + 1)); + return true; + }); + + TestChatCommand("|cffff0000|Hplayer:Test|h[Test]|h|r", + [](ChatHandler*, Hyperlink player) + { + REQUIRE("Test"sv == *player); + return true; + } + ); +} diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 00000000000..8ed9dd5863b --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,20 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + + +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" diff --git a/tests/tc_catch2.h b/tests/tc_catch2.h new file mode 100644 index 00000000000..96fcdaf8c9e --- /dev/null +++ b/tests/tc_catch2.h @@ -0,0 +1,44 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef TRINITY_CATCH2_H +#define TRINITY_CATCH2_H + +#include "Optional.h" +#include +#include + +template +std::ostream& operator<<(std::ostream& os, Optional const& value) +{ + os << "Opt"; + if (value) + os << " { " << *value << " }"; + else + os << " ()"; + return os; +} + +inline std::ostream& operator<<(std::ostream& os, std::nullopt_t) +{ + os << ""; + return os; +} + +#include "catch2/catch.hpp" + +#endif -- cgit v1.2.3