Files
TrinityCore/tests/common/test-EventMap.cpp
Carbenium 5512eb2f8f tests/EventMap: Test for event past it's execution time
With the switch to std::chrono return type of GetTimeUntilEvent
we don't run into an overflow condition which happend with the previous
uint32 return value if the events scheduled execution time is in the past.
Test for this case.

(cherry picked from commit e877f988d1)
2022-01-24 00:00:47 +01:00

330 lines
7.8 KiB
C++

/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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);
}
}
// TODO: The semantics of this case are not well defined.
// Document them first, check consumers and adapt test
// accordingly.
TEST_CASE("Schedule existing event", "[EventMap][!mayfail]")
{
EventMap eventMap;
eventMap.ScheduleEvent(EVENT_1, 1s);
eventMap.ScheduleEvent(EVENT_1, 1s);
eventMap.Update(1000);
uint32 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("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);
// Timer hasn't ticked yet, so maximum delay is 0ms: 1s (init) + 0s (delay) = 1s
REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 1s);
}
SECTION("With timer update smaller than delay")
{
eventMap.Update(500);
eventMap.DelayEvents(1s);
REQUIRE(eventMap.GetTimeUntilEvent(EVENT_1) == 1s);
}
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());
}