mirror of
https://github.com/thunderbrewhq/squall.git
synced 2026-02-04 00:49:08 +00:00
612 lines
22 KiB
C++
612 lines
22 KiB
C++
#include "EventTest.hpp"
|
|
|
|
static void STORMAPI TestBreakEventHandlerSelf(void* data) {
|
|
EventHandlerTest::RegisterCall(10, data);
|
|
|
|
CHECK(SEvtBreakHandlerChain(data) == 1);
|
|
}
|
|
|
|
static void STORMAPI TestBreakEventHandlerOther(void* data) {
|
|
EventHandlerTest::RegisterCall(10, data);
|
|
|
|
CHECK(SEvtBreakHandlerChain(nullptr) == 1);
|
|
}
|
|
|
|
TEST_CASE("SEvtBreakHandlerChain", "[event]") {
|
|
EventHandlerTest test;
|
|
|
|
SECTION("can use nullptr as data") {
|
|
CHECK(SEvtBreakHandlerChain(nullptr) == 1);
|
|
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
CHECK(SEvtDispatch(7357, 1, 0, nullptr) == 0);
|
|
CHECK(SEvtDispatch(7357, 1, 0, nullptr) == 1);
|
|
}
|
|
|
|
SECTION("causes SEvtDispatch to break early if one of many data matches") {
|
|
int data1 = 42, data2 = 1337, data3 = 0xFFFFFFFF;
|
|
|
|
CHECK(SEvtBreakHandlerChain(nullptr) == 1);
|
|
CHECK(SEvtBreakHandlerChain(&data1) == 1);
|
|
CHECK(SEvtBreakHandlerChain(&data2) == 1);
|
|
CHECK(SEvtBreakHandlerChain(&data3) == 1);
|
|
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data2) == 0);
|
|
|
|
// CLEANUP - SEvtDestroy doesn't erase registered breaks, avoid polluting other tests
|
|
CHECK(SEvtDispatch(7357, 1, 0, nullptr) == 0);
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data1) == 0);
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data3) == 0);
|
|
}
|
|
|
|
SECTION("doesn't break SEvtDispatch if no data matches") {
|
|
int data1 = 42, data2 = 1337, data3 = 0xFFFFFFFF;
|
|
|
|
CHECK(SEvtBreakHandlerChain(nullptr) == 1);
|
|
CHECK(SEvtBreakHandlerChain(&data1) == 1);
|
|
CHECK(SEvtBreakHandlerChain(&data2) == 1);
|
|
CHECK(SEvtBreakHandlerChain(&data3) == 1);
|
|
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
CHECK(SEvtDispatch(7357, 1, 0, &test) == 1);
|
|
|
|
// CLEANUP - SEvtDestroy doesn't erase registered breaks, avoid polluting other tests
|
|
CHECK(SEvtDispatch(7357, 1, 0, nullptr) == 0);
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data1) == 0);
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data2) == 0);
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data3) == 0);
|
|
}
|
|
|
|
SECTION("deduplicates multiple same-data breaks") {
|
|
CHECK(SEvtBreakHandlerChain(&test) == 1);
|
|
CHECK(SEvtBreakHandlerChain(&test) == 1);
|
|
CHECK(SEvtBreakHandlerChain(&test) == 1);
|
|
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
CHECK(SEvtDispatch(7357, 1, 0, &test) == 0);
|
|
CHECK(SEvtDispatch(7357, 1, 0, &test) == 1);
|
|
}
|
|
|
|
SECTION("causes a dispatch to stop during handling") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestBreakEventHandlerSelf);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler2);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 2);
|
|
// Calls are reverse order, TestEventHandler1 doesn't get called
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 2, nullptr }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 10, nullptr }));
|
|
}
|
|
|
|
SECTION("doesn't cause a dispatch to stop during handling if data differs") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestBreakEventHandlerOther);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler2);
|
|
|
|
int data = 42;
|
|
CHECK(SEvtDispatch(0, 0, 0, &data) == 1);
|
|
CHECK(test.NumCalls() == 3);
|
|
// Calls are reverse order, TestEventHandler1 doesn't get called
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 2, &data }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 10, &data }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, &data }));
|
|
|
|
// CLEANUP - SEvtDestroy doesn't erase registered breaks, avoid polluting other tests
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 0);
|
|
}
|
|
}
|
|
|
|
#if !defined(WHOA_TEST_STORMDLL)
|
|
TEST_CASE("SEvtDestroy", "[event]") {
|
|
EventHandlerTest test;
|
|
|
|
SECTION("always returns 1") {
|
|
CHECK(SEvtDestroy() == 1);
|
|
}
|
|
|
|
SECTION("destroys all event handlers") {
|
|
SEvtRegisterHandler(1, 1, 1, 0, &TestEventHandler1);
|
|
CHECK(SEvtDispatch(1, 1, 1, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
|
|
CHECK(SEvtDispatch(1, 1, 1, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 2);
|
|
|
|
CHECK(SEvtDestroy() == 1);
|
|
|
|
// Can't increment calls since the handler was destroyed
|
|
CHECK(SEvtDispatch(1, 1, 1, nullptr) == 0);
|
|
CHECK(test.NumCalls() == 2);
|
|
}
|
|
|
|
SECTION("doesn't destroy break data") {
|
|
// not ideal but it's official behaviour
|
|
SEvtBreakHandlerChain(nullptr);
|
|
|
|
CHECK(SEvtDestroy() == 1);
|
|
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler1);
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 0);
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void STORMAPI TestNestedDispatchEventHandler(void* data) {
|
|
EventHandlerTest::RegisterCall(20, data);
|
|
|
|
CHECK(SEvtDispatch(1337, 420, 69, nullptr) == 1);
|
|
}
|
|
|
|
TEST_CASE("SEvtDispatch", "[event]") {
|
|
EventHandlerTest test;
|
|
|
|
SECTION("sends data to an event handler") {
|
|
SEvtRegisterHandler(1337, 42, 5, 0, &TestEventHandler1);
|
|
|
|
int data = 5;
|
|
CHECK(SEvtDispatch(1337, 42, 5, &data) == 1);
|
|
|
|
REQUIRE(test.NumCalls() == 1);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, &data }));
|
|
}
|
|
|
|
SECTION("can use 0 as valid handler ids") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler1);
|
|
|
|
int data = 5;
|
|
CHECK(SEvtDispatch(0, 0, 0, &data) == 1);
|
|
|
|
REQUIRE(test.NumCalls() == 1);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, &data }));
|
|
}
|
|
|
|
SECTION("can pass nullptr to a handler") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 1);
|
|
|
|
REQUIRE(test.NumCalls() == 1);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, nullptr }));
|
|
}
|
|
|
|
SECTION("sends data to multiple event handlers") {
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler2);
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler3);
|
|
|
|
int data = 1;
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data) == 1);
|
|
|
|
REQUIRE(test.NumCalls() == 3);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 3, &data }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 2, &data }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, &data }));
|
|
}
|
|
|
|
SECTION("sends data to multiple event handlers with reverse ordering") {
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler3);
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler2);
|
|
|
|
int data = 1;
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data) == 1);
|
|
|
|
REQUIRE(test.NumCalls() == 3);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 2, &data }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, &data }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 3, &data }));
|
|
}
|
|
|
|
SECTION("sends data to duplicate handlers") {
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
|
|
int data = 1;
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data) == 1);
|
|
|
|
REQUIRE(test.NumCalls() == 3);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, &data }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, &data }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, &data }));
|
|
}
|
|
|
|
SECTION("does nothing if there are no handlers in the type") {
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtDispatch(42, 1, 0, nullptr) == 0);
|
|
CHECK(test.NumCalls() == 0);
|
|
}
|
|
|
|
SECTION("does nothing if there are no handlers that match the subtype") {
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtDispatch(7357, 2, 0, nullptr) == 0);
|
|
CHECK(test.NumCalls() == 0);
|
|
}
|
|
|
|
SECTION("does nothing if there are no handlers that match the id") {
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtDispatch(7357, 1, 1, nullptr) == 0);
|
|
CHECK(test.NumCalls() == 0);
|
|
}
|
|
|
|
SECTION("breaks the next dispatch if data matches any in break chain") {
|
|
int data = 42;
|
|
SEvtBreakHandlerChain(&data);
|
|
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
|
|
// doesn't call because data matches the break chain
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data) == 0);
|
|
CHECK(test.NumCalls() == 0);
|
|
|
|
// calls because the break already occurred
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
}
|
|
|
|
SECTION("calls handlers if data doesn't match any in break chain") {
|
|
int data = 42;
|
|
int data2 = 1337;
|
|
SEvtBreakHandlerChain(&data);
|
|
|
|
SEvtRegisterHandler(7357, 1, 0, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtDispatch(7357, 1, 0, &data2) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
}
|
|
|
|
SECTION("finds the correct handler among many") {
|
|
SEvtRegisterHandler(9000, 0, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(9000, 1, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(9000, 1, 1, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(420, 0, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(420, 1, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(420, 1, 1, 0, &TestEventHandler2);
|
|
SEvtRegisterHandler(420, 1, 2, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(42, 0, 0, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtDispatch(420, 1, 1, nullptr) == 1);
|
|
|
|
CHECK(test.NumCalls() == 1);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({2, nullptr}));
|
|
}
|
|
|
|
SECTION("can use a non-pointer as data") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, reinterpret_cast<void*>(42)) == 1);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({1, reinterpret_cast<void*>(42)}));
|
|
}
|
|
|
|
SECTION("broken handler chain still results in success if at least 1 handler called") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestBreakEventHandlerOther);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
}
|
|
|
|
SECTION("can be called from handlers") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(1337, 420, 69, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler2);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestNestedDispatchEventHandler);
|
|
SEvtRegisterHandler(1337, 420, 69, 0, &TestEventHandler3);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler4);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, &test) == 1);
|
|
CHECK(test.NumCalls() == 6);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 4, &test }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 20, &test }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 3, nullptr }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, nullptr }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 2, &test }));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 1, &test }));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("SEvtPopState", "[event]") {
|
|
EventHandlerTest test;
|
|
|
|
SECTION("fails if there are no handlers") {
|
|
CHECK(SEvtPopState(0, 0) == 0);
|
|
}
|
|
|
|
SECTION("unregisters type if it is already top level") {
|
|
SEvtRegisterHandler(1337, 420, 69, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtPopState(1337, 420) == 1);
|
|
CHECK(SEvtUnregisterType(1337, 420) == 0);
|
|
}
|
|
|
|
SECTION("popped state can receive callbacks again") {
|
|
SEvtRegisterHandler(1337, 420, 69, 0, &TestEventHandler1);
|
|
CHECK(SEvtPushState(1337, 420) == 1);
|
|
|
|
// State is duplicated, remove our duplicated handler
|
|
SEvtUnregisterHandler(1337, 420, 69, &TestEventHandler1);
|
|
|
|
CHECK(SEvtDispatch(1337, 420, 69, nullptr) == 0);
|
|
CHECK(test.NumCalls() == 0);
|
|
|
|
CHECK(SEvtPopState(1337, 420) == 0);
|
|
|
|
CHECK(SEvtDispatch(1337, 420, 69, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
}
|
|
|
|
SECTION("popped state can be unregistered again") {
|
|
SEvtRegisterHandler(1337, 420, 69, 0, &TestEventHandler1);
|
|
CHECK(SEvtPushState(1337, 420) == 1);
|
|
|
|
// Unregisters the duplicated instance
|
|
CHECK(SEvtUnregisterHandler(1337, 420, 69, &TestEventHandler1) == 1);
|
|
|
|
CHECK(SEvtPopState(1337, 420) == 0);
|
|
CHECK(SEvtUnregisterHandler(1337, 420, 69, &TestEventHandler1) == 1);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("SEvtPushState", "[event]") {
|
|
EventHandlerTest test;
|
|
|
|
SECTION("fails if there are no handlers") {
|
|
CHECK(SEvtPushState(0, 0) == 0);
|
|
}
|
|
|
|
SECTION("fails if the type does not match any registered types") {
|
|
SEvtRegisterHandler(0, 0, 1, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(10, 0, 1, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(0, 9, 1, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtPushState(10, 9) == 0);
|
|
}
|
|
|
|
SECTION("succeeds if the handler type exists") {
|
|
SEvtRegisterHandler(0, 0, 1, 0, &TestEventHandler1);
|
|
CHECK(SEvtPushState(0, 0) == 1);
|
|
}
|
|
|
|
SECTION("pushed state duplicates its callbacks") {
|
|
SEvtRegisterHandler(1337, 420, 69, 0, &TestEventHandler1);
|
|
CHECK(SEvtPushState(1337, 420) == 1);
|
|
|
|
CHECK(SEvtDispatch(1337, 420, 69, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
}
|
|
|
|
SECTION("pushed state applies to all ids") {
|
|
SEvtRegisterHandler(0, 0, 9, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(0, 0, 8, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(0, 0, 66, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtPushState(0, 0) == 1);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 9, nullptr) == 1);
|
|
CHECK(SEvtDispatch(0, 0, 8, nullptr) == 1);
|
|
CHECK(SEvtDispatch(0, 0, 66, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 3);
|
|
}
|
|
|
|
SECTION("pushed state can be unregistered") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler2);
|
|
|
|
CHECK(SEvtPushState(0, 0) == 1);
|
|
CHECK(SEvtUnregisterHandler(0, 0, 0, &TestEventHandler1) == 1);
|
|
}
|
|
}
|
|
|
|
static void STORMAPI TestRegisterEventHandler(void* data) {
|
|
EventHandlerTest::RegisterCall(30, data);
|
|
|
|
CHECK(SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler4) == 1);
|
|
}
|
|
|
|
TEST_CASE("SEvtRegisterHandler", "[event]") {
|
|
EventHandlerTest test;
|
|
|
|
SECTION("registers an event handler") {
|
|
CHECK(SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler1) == 1);
|
|
// true if found and removed
|
|
CHECK(SEvtUnregisterHandler(7357, 1, 2, &TestEventHandler1) == 1);
|
|
}
|
|
|
|
SECTION("registers event handlers with different types") {
|
|
CHECK(SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler1) == 1);
|
|
CHECK(SEvtRegisterHandler(69, 1, 2, 0, &TestEventHandler1) == 1);
|
|
|
|
CHECK(SEvtUnregisterHandler(69, 1, 2, &TestEventHandler1) == 1);
|
|
CHECK(SEvtRegisterHandler(777, 1, 2, 0, &TestEventHandler1) == 1);
|
|
|
|
CHECK(SEvtUnregisterHandler(7357, 1, 2, &TestEventHandler1) == 1);
|
|
CHECK(SEvtUnregisterHandler(777, 1, 2, &TestEventHandler1) == 1);
|
|
}
|
|
|
|
SECTION("adds a new handler while being processed") {
|
|
CHECK(SEvtRegisterHandler(0, 0, 0, 0, &TestEventHandler1) == 1);
|
|
CHECK(SEvtRegisterHandler(0, 0, 0, 0, &TestRegisterEventHandler) == 1);
|
|
|
|
SEvtDispatch(0, 0, 0, nullptr);
|
|
CHECK(test.NumCalls() == 2);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({30}));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({1}));
|
|
|
|
SEvtDispatch(0, 0, 0, nullptr);
|
|
CHECK(test.NumCalls() == 3);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({4}));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({30}));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({1}));
|
|
|
|
SEvtDispatch(0, 0, 0, nullptr);
|
|
CHECK(test.NumCalls() == 4);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({4}));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({4}));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({30}));
|
|
CHECK_THAT(test.CallResult(), MatchesCall({1}));
|
|
}
|
|
}
|
|
|
|
static void STORMAPI TestUnregisterEventHandler(void* data) {
|
|
EventHandlerTest::RegisterCall(30, data);
|
|
|
|
CHECK(SEvtUnregisterHandler(0, 0, 0, &TestUnregisterEventHandler) == 1);
|
|
}
|
|
|
|
TEST_CASE("SEvtUnregisterHandler", "[event]") {
|
|
EventHandlerTest test;
|
|
|
|
SECTION("does nothing if handler doesn't exist") {
|
|
CHECK(SEvtUnregisterHandler(7357, 2, 1, &TestEventHandler1) == 0);
|
|
CHECK(SEvtUnregisterHandler(7357, 2, 1, nullptr) == 0);
|
|
}
|
|
|
|
SECTION("removes multiple handler functions if handler is null") {
|
|
SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler2);
|
|
|
|
CHECK(SEvtUnregisterHandler(7357, 1, 2, nullptr) == 1);
|
|
|
|
// Make sure nothing gets called
|
|
CHECK(SEvtDispatch(7357, 1, 2, nullptr) == 0);
|
|
CHECK(test.NumCalls() == 0);
|
|
}
|
|
|
|
SECTION("removes a specific event handler") {
|
|
SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler2);
|
|
|
|
CHECK(SEvtUnregisterHandler(7357, 1, 2, &TestEventHandler1) == 1);
|
|
|
|
// Make sure the other handler wasn't removed by checking if it is called
|
|
CHECK(SEvtDispatch(7357, 1, 2, nullptr) == 1);
|
|
CHECK_THAT(test.CallResult(), MatchesCall({ 2, nullptr }));
|
|
}
|
|
|
|
SECTION("removes nothing if only type differs") {
|
|
SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtUnregisterHandler(42, 1, 2, nullptr) == 0);
|
|
|
|
CHECK(SEvtDispatch(7357, 1, 2, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
}
|
|
|
|
SECTION("removes nothing if only subtype differs") {
|
|
SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtUnregisterHandler(7357, 2, 2, nullptr) == 0);
|
|
|
|
CHECK(SEvtDispatch(7357, 1, 2, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
}
|
|
|
|
SECTION("removes nothing if only id differs") {
|
|
SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtUnregisterHandler(7357, 1, 3, nullptr) == 0);
|
|
|
|
CHECK(SEvtDispatch(7357, 1, 2, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
}
|
|
|
|
SECTION("allows a handler to remove itself while being called") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestUnregisterEventHandler);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 0);
|
|
}
|
|
|
|
SECTION("stops calls once a handler removes itself") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestUnregisterEventHandler);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestUnregisterEventHandler);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestUnregisterEventHandler);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 0);
|
|
}
|
|
}
|
|
|
|
static void STORMAPI TestUnregisterTypeHandler(void* data) {
|
|
EventHandlerTest::RegisterCall(30, data);
|
|
|
|
CHECK(SEvtUnregisterType(0, 0) == 1);
|
|
}
|
|
|
|
TEST_CASE("SEvtUnregisterType", "[event]") {
|
|
EventHandlerTest test;
|
|
|
|
SECTION("removes all event handlers in matching type and subtype") {
|
|
SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler2);
|
|
|
|
CHECK(SEvtUnregisterType(7357, 1) == 1);
|
|
|
|
CHECK(SEvtDispatch(7357, 1, 2, nullptr) == 0);
|
|
CHECK(test.NumCalls() == 0);
|
|
}
|
|
|
|
SECTION("removes nothing if only type matches") {
|
|
SEvtRegisterHandler(7357, 2, 2, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtUnregisterType(7357, 1) == 0);
|
|
|
|
CHECK(SEvtDispatch(7357, 2, 2, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
}
|
|
|
|
SECTION("removes nothing if only subtype matches") {
|
|
SEvtRegisterHandler(7357, 1, 2, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtUnregisterType(42, 1) == 0);
|
|
|
|
CHECK(SEvtDispatch(7357, 1, 2, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
}
|
|
|
|
SECTION("removes only matching handlers among many") {
|
|
SEvtRegisterHandler(123, 1, 2, 0, &TestEventHandler1);
|
|
SEvtRegisterHandler(123, 2, 2, 0, &TestEventHandler2);
|
|
SEvtRegisterHandler(123, 2, 3, 0, &TestEventHandler3);
|
|
SEvtRegisterHandler(123, 1, 1, 0, &TestEventHandler4);
|
|
SEvtRegisterHandler(123, 2, 1, 0, &TestEventHandler1);
|
|
|
|
CHECK(SEvtUnregisterType(123, 2) == 1);
|
|
|
|
CHECK(SEvtDispatch(123, 2, 1, nullptr) == 0);
|
|
CHECK(SEvtDispatch(123, 2, 2, nullptr) == 0);
|
|
CHECK(SEvtDispatch(123, 2, 3, nullptr) == 0);
|
|
|
|
CHECK(SEvtDispatch(123, 1, 1, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
CHECK(SEvtDispatch(123, 1, 2, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 2);
|
|
}
|
|
|
|
SECTION("allows a handler to remove itself while being called") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestUnregisterTypeHandler);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 0);
|
|
}
|
|
|
|
SECTION("stops calls once a handler removes itself") {
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestUnregisterTypeHandler);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestUnregisterTypeHandler);
|
|
SEvtRegisterHandler(0, 0, 0, 0, &TestUnregisterTypeHandler);
|
|
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 1);
|
|
CHECK(test.NumCalls() == 1);
|
|
CHECK(SEvtDispatch(0, 0, 0, nullptr) == 0);
|
|
}
|
|
}
|