From d9a51069366650051e644453f5d3ac90f2ab29b5 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 16:29:48 +0100 Subject: turn examples into unit tests --- src/test/ValueBrokerTest.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/test/ValueBrokerTest.cpp (limited to 'src/test/ValueBrokerTest.cpp') diff --git a/src/test/ValueBrokerTest.cpp b/src/test/ValueBrokerTest.cpp new file mode 100644 index 0000000..10a4654 --- /dev/null +++ b/src/test/ValueBrokerTest.cpp @@ -0,0 +1,64 @@ +#include + +#include +#include + +using namespace std; +using namespace crepe; +using namespace testing; + +class ValueBrokerTest : public Test { +public: + int read_count = 0; + int write_count = 0; + int value = 0; + + ValueBroker broker { + [this](const int & target) -> void { + this->write_count++; + this->value = target; + }, + [this]() -> const int & { + this->read_count++; + return this->value; + }, + }; + Proxy proxy{broker}; + + void SetUp() override { + ASSERT_EQ(read_count, 0); + ASSERT_EQ(write_count, 0); + } +}; + +TEST_F(ValueBrokerTest, BrokerWrite) { + broker.set(0); + EXPECT_EQ(read_count, 0); + EXPECT_EQ(write_count, 1); +} + +TEST_F(ValueBrokerTest, BrokerRead) { + broker.get(); + EXPECT_EQ(read_count, 1); + EXPECT_EQ(write_count, 0); +} + +TEST_F(ValueBrokerTest, ProxyWrite) { + proxy = 0; + EXPECT_EQ(read_count, 0); + EXPECT_EQ(write_count, 1); +} + +void dummy(int) { } +TEST_F(ValueBrokerTest, ProxyRead) { + dummy(proxy); + EXPECT_EQ(read_count, 1); + EXPECT_EQ(write_count, 0); +} + +TEST_F(ValueBrokerTest, ProxyReadWrite) { + proxy = proxy; + ASSERT_EQ(read_count, 1); + ASSERT_EQ(write_count, 1); +} + -- cgit v1.2.3 From 8e72968e294cbc4ac6e9ff09bd94cde1775d735b Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 21:51:30 +0100 Subject: nitpick #34 --- mwe/events/include/event.h | 2 +- src/crepe/api/EventManager.cpp | 54 +++++++++++++++++----------------------- src/crepe/api/EventManager.h | 39 +++++++++++++++++++++-------- src/crepe/api/EventManager.hpp | 36 +++++++++------------------ src/crepe/api/IKeyListener.cpp | 3 ++- src/crepe/api/IKeyListener.h | 4 +-- src/crepe/api/IMouseListener.cpp | 3 ++- src/crepe/api/IMouseListener.h | 2 +- src/crepe/facade/SDLContext.cpp | 3 ++- src/example/CMakeLists.txt | 6 ----- src/test/DBTest.cpp | 3 +-- src/test/ValueBrokerTest.cpp | 5 ++-- 12 files changed, 77 insertions(+), 83 deletions(-) (limited to 'src/test/ValueBrokerTest.cpp') diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index e1b220b..ee1bf52 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -148,7 +148,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent"){}; + ShutDownEvent() : Event("ShutDownEvent") {}; REGISTER_EVENT_TYPE(ShutDownEvent) diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 993db86..20f0dd3 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -1,6 +1,7 @@ #include "EventManager.h" using namespace crepe; +using namespace std; EventManager & EventManager::get_instance() { static EventManager instance; @@ -8,30 +9,23 @@ EventManager & EventManager::get_instance() { } void EventManager::dispatch_events() { - for (auto event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { - std::unique_ptr & event = (*event_it).event; - int channel = (*event_it).channel; - std::type_index event_type = (*event_it).type; - - bool event_handled = false; - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it == this->subscribers.end()) { - continue; - } - std::vector & handlers = handlers_it->second; - - for (auto handler_it = handlers.begin(); handler_it != handlers.end(); ++handler_it) { - // If callback is executed and returns true, remove the event from the queue - if ((*handler_it).callback->exec(*event)) { - event_it = this->events_queue.erase(event_it); - event_handled = true; - break; - } - } + for (auto & event : this->events_queue) { + this->handle_event(event.type, event.channel, *event.event.get()); + } + this->events_queue.clear(); +} - if (!event_handled) { - ++event_it; - } +void EventManager::handle_event(type_index type, event_channel_t channel, const Event & data) { + auto handlers_it = this->subscribers.find(type); + if (handlers_it == this->subscribers.end()) return; + + vector & handlers = handlers_it->second; + for (auto & handler : handlers) { + bool check_channel = handler.channel != CHANNEL_ALL || channel != CHANNEL_ALL; + if (check_channel && handler.channel != channel) continue; + + bool handled = handler.callback->exec(data); + if (handled) return; } } @@ -40,15 +34,13 @@ void EventManager::clear() { this->events_queue.clear(); } -void EventManager::unsubscribe(subscription_t event_id) { +void EventManager::unsubscribe(subscription_t id) { for (auto & [event_type, handlers] : this->subscribers) { - for (auto it = handlers.begin(); it != handlers.end();) { - if (it->id == event_id) { - it = handlers.erase(it); - return; - } else { - ++it; - } + for (auto it = handlers.begin(); it != handlers.end(); it++) { + // find listener with subscription id + if ((*it).id != id) continue; + it = handlers.erase(it); + return; } } } diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index bd9772a..348a04d 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -1,8 +1,6 @@ #pragma once -#include #include -#include #include #include #include @@ -11,8 +9,17 @@ #include "EventHandler.h" namespace crepe { -//! typedef for subscription value -typedef int subscription_t; + +//! Event listener unique ID +typedef size_t subscription_t; + +/** + * \brief Event channel + * + * Events can be sent to a specific channel, which prevents listeners on other channels from + * being called. The default channel is EventManager::CHANNEL_ALL, which calls all listeners. + */ +typedef size_t event_channel_t; /** * \class EventManager @@ -24,7 +31,7 @@ typedef int subscription_t; */ class EventManager { public: - static constexpr int CHANNEL_ALL = -1; + static constexpr const event_channel_t CHANNEL_ALL = -1; /** * \brief Get the singleton instance of the EventManager. @@ -49,7 +56,7 @@ public: */ template subscription_t subscribe(const EventHandler & callback, - int channel = CHANNEL_ALL); + event_channel_t channel = CHANNEL_ALL); /** * \brief Unsubscribe a previously registered callback. @@ -70,7 +77,7 @@ public: * \param channel The channel to trigger the event on (default is CHANNEL_ALL, which triggers on all channels). */ template - void trigger_event(const EventType & event, int channel = CHANNEL_ALL); + void trigger_event(const EventType & event, event_channel_t channel = CHANNEL_ALL); /** * \brief Queue an event for later processing. @@ -82,7 +89,7 @@ public: * \param channel The channel to associate with the event (default is CHANNEL_ALL). */ template - void queue_event(const EventType & event, int channel = CHANNEL_ALL); + void queue_event(const EventType & event, event_channel_t channel = CHANNEL_ALL); /** * \brief Process all queued events. @@ -113,17 +120,29 @@ private: */ struct QueueEntry { std::unique_ptr event; ///< The event instance. - int channel = CHANNEL_ALL; ///< The channel associated with the event. + event_channel_t channel = CHANNEL_ALL; ///< The channel associated with the event. std::type_index type; ///< The type of the event. }; + /** + * \brief Internal event handler + * + * This function processes a single event, and is used to process events both during + * EventManager::dispatch_events and inside EventManager::trigger_event + * + * \param type \c typeid of concrete Event class + * \param channel Event channel + * \param data Event data + */ + void handle_event(std::type_index type, event_channel_t channel, const Event & data); + /** * \struct CallbackEntry * \brief Represents a registered event handler callback. */ struct CallbackEntry { std::unique_ptr callback; ///< The callback function wrapper. - int channel = CHANNEL_ALL; ///< The channel this callback listens to. + event_channel_t channel = CHANNEL_ALL; ///< The channel this callback listens to. subscription_t id = -1; ///< Unique subscription ID. }; diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index b2a94bd..a5f4556 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -1,9 +1,12 @@ +#pragma once + #include "EventManager.h" namespace crepe { template -subscription_t EventManager::subscribe(const EventHandler & callback, int channel) { +subscription_t EventManager::subscribe(const EventHandler & callback, + event_channel_t channel) { subscription_counter++; std::type_index event_type = typeid(EventType); std::unique_ptr> handler @@ -15,34 +18,19 @@ subscription_t EventManager::subscribe(const EventHandler & callback, } template -void EventManager::queue_event(const EventType & event, int channel) { +void EventManager::queue_event(const EventType & event, event_channel_t channel) { static_assert(std::is_base_of::value, "EventType must derive from Event"); - std::type_index event_type = typeid(EventType); - - auto event_ptr = std::make_unique(event); - - this->events_queue.push_back( - QueueEntry{.event = std::move(event_ptr), .channel = channel, .type = event_type}); + this->events_queue.push_back(QueueEntry{ + .event = std::make_unique(event), + .channel = channel, + .type = typeid(EventType), + }); } template -void EventManager::trigger_event(const EventType & event, int channel) { - std::type_index event_type = typeid(EventType); - - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - const std::vector & handlers = handlers_it->second; - - for (const CallbackEntry & handler : handlers) { - if (handler.channel != channel && handler.channel != CHANNEL_ALL) { - continue; - } - if (handler.callback->exec(event)) { - break; - } - } - } +void EventManager::trigger_event(const EventType & event, event_channel_t channel) { + this->handle_event(typeid(EventType), channel, event); } } // namespace crepe diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index 7aefaf7..8642655 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -3,7 +3,8 @@ using namespace crepe; // Constructor with specified channel -IKeyListener::IKeyListener(int channel) : event_manager(EventManager::get_instance()) { +IKeyListener::IKeyListener(event_channel_t channel) + : event_manager(EventManager::get_instance()) { this->press_id = event_manager.subscribe( [this](const KeyPressEvent & event) { return this->on_key_pressed(event); }, channel); this->release_id = event_manager.subscribe( diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 2a89cbc..328a4c2 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -16,7 +16,7 @@ public: * \brief Constructs an IKeyListener with a specified channel. * \param channel The channel ID for event handling. */ - IKeyListener(int channel = EventManager::CHANNEL_ALL); + IKeyListener(event_channel_t channel = EventManager::CHANNEL_ALL); virtual ~IKeyListener(); IKeyListener(const IKeyListener &) = delete; IKeyListener & operator=(const IKeyListener &) = delete; @@ -43,7 +43,7 @@ private: //! Key release event id subscription_t release_id = -1; //! EventManager reference - EventManager & event_manager;; + EventManager & event_manager; }; } // namespace crepe diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 7d38280..989aeb3 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -2,7 +2,8 @@ using namespace crepe; -IMouseListener::IMouseListener(int channel) : event_manager(EventManager::get_instance()) { +IMouseListener::IMouseListener(event_channel_t channel) + : event_manager(EventManager::get_instance()) { this->click_id = event_manager.subscribe( [this](const MouseClickEvent & event) { return this->on_mouse_clicked(event); }, channel); diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 91b33e1..15e1619 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -16,7 +16,7 @@ public: * \brief Constructs an IMouseListener with a specified channel. * \param channel The channel ID for event handling. */ - IMouseListener(int channel = EventManager::CHANNEL_ALL); + IMouseListener(event_channel_t channel = EventManager::CHANNEL_ALL); virtual ~IMouseListener(); IMouseListener & operator=(const IMouseListener &) = delete; IMouseListener(const IMouseListener &) = delete; diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index b8b2bda..00523a6 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -47,7 +47,8 @@ SDLContext::SDLContext() { SDL_Renderer * tmp_renderer = SDL_CreateRenderer(this->game_window.get(), -1, SDL_RENDERER_ACCELERATED); if (!tmp_renderer) { - throw runtime_error(format("SDLContext: SDL_CreateRenderer error: {}", SDL_GetError())); + throw runtime_error( + format("SDLContext: SDL_CreateRenderer error: {}", SDL_GetError())); } this->game_renderer diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index 7b4cc43..560e2bc 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -18,12 +18,6 @@ endfunction() add_example(asset_manager) add_example(savemgr) -add_example(proxy) -add_example(db) -add_example(ecs) -add_example(scene_manager) -add_example(events) -add_example(particles) add_example(rendering_particle) add_example(gameloop) diff --git a/src/test/DBTest.cpp b/src/test/DBTest.cpp index b57eba9..e80814c 100644 --- a/src/test/DBTest.cpp +++ b/src/test/DBTest.cpp @@ -1,5 +1,5 @@ -#include #include +#include using namespace std; using namespace crepe; @@ -26,4 +26,3 @@ TEST_F(DBTest, Has) { db.set("foo", "bar"); EXPECT_EQ(db.has("foo"), true); } - diff --git a/src/test/ValueBrokerTest.cpp b/src/test/ValueBrokerTest.cpp index 10a4654..e6bb058 100644 --- a/src/test/ValueBrokerTest.cpp +++ b/src/test/ValueBrokerTest.cpp @@ -13,7 +13,7 @@ public: int write_count = 0; int value = 0; - ValueBroker broker { + ValueBroker broker{ [this](const int & target) -> void { this->write_count++; this->value = target; @@ -49,7 +49,7 @@ TEST_F(ValueBrokerTest, ProxyWrite) { EXPECT_EQ(write_count, 1); } -void dummy(int) { } +void dummy(int) {} TEST_F(ValueBrokerTest, ProxyRead) { dummy(proxy); EXPECT_EQ(read_count, 1); @@ -61,4 +61,3 @@ TEST_F(ValueBrokerTest, ProxyReadWrite) { ASSERT_EQ(read_count, 1); ASSERT_EQ(write_count, 1); } - -- cgit v1.2.3