#include "unittest/TestSuite.h" #include "utilities/Atom.h" #include "utilities/EventDispatcher.h" static bool callback1(Atom eventID, void * eventData, void * context) { *(int *) context += *(int *) eventData; TestCase_assert(eventID == Atom_fromString("event1"), "Expected %p \"event1\" but got %p \"%s\"", Atom_fromString("event1"), eventID, eventID); return true; } static bool callback2(Atom eventID, void * eventData, void * context) { *(int *) context += *(int *) eventData; TestCase_assert(eventID == Atom_fromString("event2"), "Expected %p \"event2\" but got %p \"%s\"", Atom_fromString("event2"), eventID, eventID); return false; } static bool callback3(Atom eventID, void * eventData, void * context) { *(int *) context += *(int *) eventData; return false; } static void testCallbacks() { EventDispatcher * dispatcher; int callback1Context = 0, callback2Context = 0; int incrementation = 2; bool handled; Atom event1Atom, event2Atom; dispatcher = EventDispatcher_create(); event1Atom = Atom_fromString("event1"); event2Atom = Atom_fromString("event2"); handled = EventDispatcher_dispatchEvent(dispatcher, event1Atom, &incrementation); TestCase_assert(!handled, "Event handled when no callbacks are registered"); EventDispatcher_registerForEvent(dispatcher, event1Atom, callback1, &callback1Context); handled = EventDispatcher_dispatchEvent(dispatcher, event1Atom, &incrementation); TestCase_assert(handled, "Event not handled when appropriate callback was registered"); TestCase_assert(callback1Context == 2, "Expected 2 but got %d", callback1Context); incrementation = 3; EventDispatcher_dispatchEvent(dispatcher, event2Atom, &incrementation); TestCase_assert(callback1Context == 2, "Callback called for wrong type of event"); EventDispatcher_registerForEvent(dispatcher, event2Atom, callback2, &callback2Context); handled = EventDispatcher_dispatchEvent(dispatcher, event2Atom, &incrementation); TestCase_assert(callback2Context == 3, "Expected 3 but got %d", callback2Context); TestCase_assert(!handled, "Expected false but got true"); EventDispatcher_unregisterForEvent(dispatcher, event1Atom, callback1, NULL); handled = EventDispatcher_dispatchEvent(dispatcher, event1Atom, &incrementation); TestCase_assert(handled, "Event not still handled after unregistering callbacks with the wrong context"); EventDispatcher_unregisterForEvent(dispatcher, event1Atom, callback1, &callback1Context); handled = EventDispatcher_dispatchEvent(dispatcher, event1Atom, &incrementation); TestCase_assert(!handled, "Event still handled after unregistering callbacks"); incrementation = 1; handled = EventDispatcher_dispatchEvent(dispatcher, event2Atom, &incrementation); TestCase_assert(callback2Context == 4, "Expected 4 but got %d", callback2Context); TestCase_assert(!handled, "Expected false but got true"); EventDispatcher_dispose(dispatcher); } struct removeDispatchContext { EventDispatcher * dispatcher; unsigned int callCount1; unsigned int callCount2; unsigned int lastCall; }; static bool removedDispatchCallback(Atom eventID, void * eventData, void * context) { struct removeDispatchContext * contextStruct = context; contextStruct->callCount2++; contextStruct->lastCall = 2; return true; } static bool removeDispatchCallback(Atom eventID, void * eventData, void * context) { struct removeDispatchContext * contextStruct = context; contextStruct->callCount1++; contextStruct->lastCall = 1; EventDispatcher_unregisterForEvent(contextStruct->dispatcher, ATOM("event"), removedDispatchCallback, contextStruct); return true; } static void testRemoveDuringDispatch(void) { Atom eventAtom = ATOM("event"); EventDispatcher * dispatcher = EventDispatcher_create(); struct removeDispatchContext contextStruct = {dispatcher, 0, 0, 0}; EventDispatcher_registerForEvent(dispatcher, eventAtom, removeDispatchCallback, &contextStruct); EventDispatcher_registerForEvent(dispatcher, eventAtom, removedDispatchCallback, &contextStruct); EventDispatcher_dispatchEvent(dispatcher, eventAtom, NULL); TestCase_assertUIntEqual(contextStruct.callCount1, 1); TestCase_assertUIntEqual(contextStruct.callCount2, 1); TestCase_assertUIntEqual(contextStruct.lastCall, 2); EventDispatcher_dispatchEvent(dispatcher, eventAtom, NULL); TestCase_assertUIntEqual(contextStruct.callCount1, 2); TestCase_assertUIntEqual(contextStruct.callCount2, 1); TestCase_assertUIntEqual(contextStruct.lastCall, 1); EventDispatcher_dispose(dispatcher); } static void testUnregisterAll(void) { Atom event1Atom = ATOM("event1"), event2Atom = ATOM("event2"); int eventCount1 = 0, eventCount2 = 0, eventData = 1; EventDispatcher * dispatcher = EventDispatcher_create(); EventDispatcher_registerForEvent(dispatcher, event1Atom, callback1, &eventCount1); EventDispatcher_registerForEvent(dispatcher, event1Atom, callback3, &eventCount2); EventDispatcher_registerForEvent(dispatcher, event2Atom, callback2, &eventCount2); EventDispatcher_dispatchEvent(dispatcher, event1Atom, &eventData); TestCase_assertIntEqual(eventCount1, 1); TestCase_assertIntEqual(eventCount2, 1); EventDispatcher_dispatchEvent(dispatcher, event2Atom, &eventData); TestCase_assertIntEqual(eventCount2, 2); EventDispatcher_unregisterAllForEventID(dispatcher, event1Atom); EventDispatcher_dispatchEvent(dispatcher, event1Atom, &eventData); TestCase_assertIntEqual(eventCount1, 1); TestCase_assertIntEqual(eventCount2, 2); EventDispatcher_dispatchEvent(dispatcher, event2Atom, &eventData); TestCase_assertIntEqual(eventCount2, 3); EventDispatcher_dispose(dispatcher); eventCount1 = eventCount2 = 0; dispatcher = EventDispatcher_create(); EventDispatcher_registerForEvent(dispatcher, event1Atom, callback1, &eventCount1); EventDispatcher_registerForEvent(dispatcher, event1Atom, callback3, &eventCount1); EventDispatcher_registerForEvent(dispatcher, event2Atom, callback3, &eventCount2); EventDispatcher_dispatchEvent(dispatcher, event1Atom, &eventData); TestCase_assertIntEqual(eventCount1, 2); EventDispatcher_dispatchEvent(dispatcher, event2Atom, &eventData); TestCase_assertIntEqual(eventCount2, 1); EventDispatcher_unregisterAllForCallback(dispatcher, callback3); EventDispatcher_dispatchEvent(dispatcher, event1Atom, &eventData); TestCase_assertIntEqual(eventCount1, 3); EventDispatcher_dispatchEvent(dispatcher, event2Atom, &eventData); TestCase_assertIntEqual(eventCount2, 1); EventDispatcher_dispose(dispatcher); eventCount1 = eventCount2 = 0; dispatcher = EventDispatcher_create(); EventDispatcher_registerForEvent(dispatcher, event1Atom, callback3, &eventCount2); EventDispatcher_registerForEvent(dispatcher, event1Atom, callback3, &eventCount1); EventDispatcher_registerForEvent(dispatcher, event2Atom, callback3, &eventCount2); EventDispatcher_dispatchEvent(dispatcher, event1Atom, &eventData); TestCase_assertIntEqual(eventCount1, 1); TestCase_assertIntEqual(eventCount2, 1); EventDispatcher_dispatchEvent(dispatcher, event2Atom, &eventData); TestCase_assertIntEqual(eventCount2, 2); EventDispatcher_unregisterAllForContext(dispatcher, &eventCount2); EventDispatcher_dispatchEvent(dispatcher, event1Atom, &eventData); TestCase_assertIntEqual(eventCount1, 2); TestCase_assertIntEqual(eventCount2, 2); EventDispatcher_dispatchEvent(dispatcher, event2Atom, &eventData); TestCase_assertIntEqual(eventCount2, 2); EventDispatcher_dispose(dispatcher); } TEST_SUITE(EventDispatcherTest, testCallbacks, testRemoveDuringDispatch, testUnregisterAll)