diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/AudioTest.cpp | 161 | ||||
-rw-r--r-- | src/test/CMakeLists.txt | 7 | ||||
-rw-r--r-- | src/test/CollisionTest.cpp | 1 | ||||
-rw-r--r-- | src/test/ECSTest.cpp | 79 | ||||
-rw-r--r-- | src/test/EventTest.cpp | 107 | ||||
-rw-r--r-- | src/test/InputTest.cpp | 4 | ||||
-rw-r--r-- | src/test/LoopManagerTest.cpp | 76 | ||||
-rw-r--r-- | src/test/LoopTimerTest.cpp | 78 | ||||
-rw-r--r-- | src/test/ParticleTest.cpp | 4 | ||||
-rw-r--r-- | src/test/Profiling.cpp | 45 | ||||
-rw-r--r-- | src/test/RenderSystemTest.cpp | 36 | ||||
-rw-r--r-- | src/test/ResourceManagerTest.cpp | 84 | ||||
-rw-r--r-- | src/test/SaveManagerTest.cpp | 40 | ||||
-rw-r--r-- | src/test/ScriptECSTest.cpp | 41 | ||||
-rw-r--r-- | src/test/ScriptEventTest.cpp | 2 | ||||
-rw-r--r-- | src/test/ScriptSaveManagerTest.cpp | 35 | ||||
-rw-r--r-- | src/test/ScriptSceneTest.cpp | 2 | ||||
-rw-r--r-- | src/test/ScriptTest.cpp | 2 | ||||
-rw-r--r-- | src/test/ScriptTest.h | 5 | ||||
-rw-r--r-- | src/test/Vector2Test.cpp | 148 | ||||
-rw-r--r-- | src/test/main.cpp | 14 |
21 files changed, 842 insertions, 129 deletions
diff --git a/src/test/AudioTest.cpp b/src/test/AudioTest.cpp new file mode 100644 index 0000000..48bba1b --- /dev/null +++ b/src/test/AudioTest.cpp @@ -0,0 +1,161 @@ +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <crepe/api/AudioSource.h> +#include <crepe/api/GameObject.h> +#include <crepe/manager/ComponentManager.h> +#include <crepe/manager/ResourceManager.h> +#include <crepe/system/AudioSystem.h> + +using namespace std; +using namespace std::chrono_literals; +using namespace crepe; +using namespace testing; + +class AudioTest : public Test { +private: + class TestSoundContext : public SoundContext { + public: + MOCK_METHOD(SoundHandle, play, (Sound & resource), (override)); + MOCK_METHOD(void, stop, (const SoundHandle &), (override)); + MOCK_METHOD(void, set_volume, (const SoundHandle &, float), (override)); + MOCK_METHOD(void, set_loop, (const SoundHandle &, bool), (override)); + }; + + class TestAudioSystem : public AudioSystem { + public: + using AudioSystem::AudioSystem; + StrictMock<TestSoundContext> context; + virtual SoundContext & get_context() { return this->context; } + }; + +private: + Mediator mediator; + ComponentManager component_manager{mediator}; + ResourceManager resource_manager{mediator}; + +public: + TestAudioSystem system{mediator}; + TestSoundContext & context = system.context; + +private: + GameObject entity = component_manager.new_object("name"); + +public: + AudioSource & component = entity.add_component<AudioSource>("mwe/audio/bgm.ogg"); +}; + +TEST_F(AudioTest, Default) { + EXPECT_CALL(context, play(_)).Times(0); + EXPECT_CALL(context, stop(_)).Times(0); + EXPECT_CALL(context, set_volume(_, _)).Times(0); + EXPECT_CALL(context, set_loop(_, _)).Times(0); + system.update(); +} + +TEST_F(AudioTest, Play) { + system.update(); + + { + InSequence seq; + + EXPECT_CALL(context, play(_)).Times(0); + component.play(); + } + + { + InSequence seq; + + EXPECT_CALL(context, play(_)).Times(1); + system.update(); + } +} + +TEST_F(AudioTest, Stop) { + system.update(); + + { + InSequence seq; + + EXPECT_CALL(context, stop(_)).Times(0); + component.stop(); + } + + { + InSequence seq; + + EXPECT_CALL(context, stop(_)).Times(1); + system.update(); + } +} + +TEST_F(AudioTest, Volume) { + system.update(); + + { + InSequence seq; + + EXPECT_CALL(context, set_volume(_, _)).Times(0); + component.volume += 0.2; + } + + { + InSequence seq; + + EXPECT_CALL(context, set_volume(_, component.volume)).Times(1); + system.update(); + } +} + +TEST_F(AudioTest, Looping) { + system.update(); + + { + InSequence seq; + + EXPECT_CALL(context, set_loop(_, _)).Times(0); + component.loop = !component.loop; + } + + { + InSequence seq; + + EXPECT_CALL(context, set_loop(_, component.loop)).Times(1); + system.update(); + } +} + +TEST_F(AudioTest, StopOnDeactivate) { + system.update(); + + { + InSequence seq; + + EXPECT_CALL(context, stop(_)).Times(1); + component.active = false; + system.update(); + } +} + +TEST_F(AudioTest, PlayOnActive) { + component.active = false; + component.play_on_awake = true; + system.update(); + + { + InSequence seq; + + EXPECT_CALL(context, play(_)).Times(1); + component.active = true; + system.update(); + } +} + +TEST_F(AudioTest, PlayImmediately) { + component.play_on_awake = false; + component.play(); + + EXPECT_CALL(context, play(_)).Times(1); + + system.update(); +} diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index c9cbac5..11b4ca9 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -4,7 +4,9 @@ target_sources(test_main PUBLIC PhysicsTest.cpp ScriptTest.cpp ParticleTest.cpp + AudioTest.cpp AssetTest.cpp + ResourceManagerTest.cpp OptionalRefTest.cpp RenderSystemTest.cpp EventTest.cpp @@ -13,8 +15,13 @@ target_sources(test_main PUBLIC ValueBrokerTest.cpp DBTest.cpp Vector2Test.cpp + LoopManagerTest.cpp + LoopTimerTest.cpp InputTest.cpp ScriptEventTest.cpp ScriptSceneTest.cpp Profiling.cpp + SaveManagerTest.cpp + ScriptSaveManagerTest.cpp + ScriptECSTest.cpp ) diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp index dd45eb6..5dbc670 100644 --- a/src/test/CollisionTest.cpp +++ b/src/test/CollisionTest.cpp @@ -50,6 +50,7 @@ public: class CollisionTest : public Test { public: Mediator m; + EventManager event_mgr{m}; ComponentManager mgr{m}; CollisionSystem collision_sys{m}; ScriptSystem script_sys{m}; diff --git a/src/test/ECSTest.cpp b/src/test/ECSTest.cpp index 3e6c61c..af2b7b0 100644 --- a/src/test/ECSTest.cpp +++ b/src/test/ECSTest.cpp @@ -1,6 +1,7 @@ #include <gtest/gtest.h> #define protected public +#define private public #include <crepe/api/GameObject.h> #include <crepe/api/Metadata.h> @@ -16,6 +17,10 @@ class ECSTest : public ::testing::Test { public: ComponentManager mgr{m}; + + class TestComponent : public Component { + using Component::Component; + }; }; TEST_F(ECSTest, createGameObject) { @@ -387,3 +392,77 @@ TEST_F(ECSTest, resetPersistent) { EXPECT_EQ(metadata.size(), 0); EXPECT_EQ(transform.size(), 0); } + +TEST_F(ECSTest, IDByName) { + GameObject foo = mgr.new_object("foo"); + GameObject bar = mgr.new_object("bar"); + + { + auto objects = mgr.get_objects_by_name(""); + EXPECT_EQ(objects.size(), 0); + } + + { + auto objects = mgr.get_objects_by_name("foo"); + EXPECT_EQ(objects.size(), 1); + EXPECT_TRUE(objects.contains(foo.id)); + } +} + +TEST_F(ECSTest, IDByTag) { + GameObject foo = mgr.new_object("foo", "common tag"); + GameObject bar = mgr.new_object("bar", "common tag"); + + { + auto objects = mgr.get_objects_by_tag(""); + EXPECT_EQ(objects.size(), 0); + } + + { + auto objects = mgr.get_objects_by_tag("common tag"); + EXPECT_EQ(objects.size(), 2); + EXPECT_TRUE(objects.contains(foo.id)); + EXPECT_TRUE(objects.contains(bar.id)); + } +} + +TEST_F(ECSTest, ComponentsByName) { + GameObject foo = mgr.new_object("foo"); + foo.add_component<TestComponent>(); + GameObject bar = mgr.new_object("bar"); + bar.add_component<TestComponent>(); + bar.add_component<TestComponent>(); + + { + auto objects = mgr.get_components_by_name<TestComponent>(""); + EXPECT_EQ(objects.size(), 0); + } + + { + auto objects = mgr.get_components_by_name<TestComponent>("foo"); + EXPECT_EQ(objects.size(), 1); + } + + { + auto objects = mgr.get_components_by_name<TestComponent>("bar"); + EXPECT_EQ(objects.size(), 2); + } +} + +TEST_F(ECSTest, ComponentsByTag) { + GameObject foo = mgr.new_object("foo", "common tag"); + foo.add_component<TestComponent>(); + GameObject bar = mgr.new_object("bar", "common tag"); + bar.add_component<TestComponent>(); + bar.add_component<TestComponent>(); + + { + auto objects = mgr.get_components_by_tag<TestComponent>(""); + EXPECT_EQ(objects.size(), 0); + } + + { + auto objects = mgr.get_components_by_tag<TestComponent>("common tag"); + EXPECT_EQ(objects.size(), 3); + } +} diff --git a/src/test/EventTest.cpp b/src/test/EventTest.cpp index ef7fc10..f57a6de 100644 --- a/src/test/EventTest.cpp +++ b/src/test/EventTest.cpp @@ -1,56 +1,41 @@ -#include <gmock/gmock.h> -#include <gtest/gtest.h> - #include <crepe/api/Event.h> -#include <crepe/api/IKeyListener.h> -#include <crepe/api/IMouseListener.h> #include <crepe/manager/EventManager.h> - +#include <crepe/manager/Mediator.h> +#include <gmock/gmock.h> +#include <gtest/gtest.h> using namespace std; using namespace std::chrono_literals; using namespace crepe; class EventManagerTest : public ::testing::Test { protected: + Mediator mediator; + EventManager event_mgr{mediator}; void SetUp() override { // Clear any existing subscriptions or events before each test - EventManager::get_instance().clear(); + event_mgr.clear(); } void TearDown() override { // Ensure cleanup after each test - EventManager::get_instance().clear(); + event_mgr.clear(); } }; -class MockKeyListener : public IKeyListener { -public: - MOCK_METHOD(bool, on_key_pressed, (const KeyPressEvent & event), (override)); - MOCK_METHOD(bool, on_key_released, (const KeyReleaseEvent & event), (override)); -}; - -class MockMouseListener : public IMouseListener { -public: - MOCK_METHOD(bool, on_mouse_clicked, (const MouseClickEvent & event), (override)); - MOCK_METHOD(bool, on_mouse_pressed, (const MousePressEvent & event), (override)); - MOCK_METHOD(bool, on_mouse_released, (const MouseReleaseEvent & event), (override)); - MOCK_METHOD(bool, on_mouse_moved, (const MouseMoveEvent & event), (override)); -}; - TEST_F(EventManagerTest, EventSubscription) { EventHandler<KeyPressEvent> key_handler = [](const KeyPressEvent & e) { return true; }; // Subscribe to KeyPressEvent - EventManager::get_instance().subscribe<KeyPressEvent>(key_handler, 1); + event_mgr.subscribe<KeyPressEvent>(key_handler, 1); // Verify subscription (not directly verifiable; test by triggering event) - EventManager::get_instance().trigger_event<KeyPressEvent>( + event_mgr.trigger_event<KeyPressEvent>( KeyPressEvent{ .repeat = true, .key = Keycode::A, }, 1); - EventManager::get_instance().trigger_event<KeyPressEvent>( + event_mgr.trigger_event<KeyPressEvent>( KeyPressEvent{ .repeat = true, .key = Keycode::A, @@ -68,8 +53,7 @@ TEST_F(EventManagerTest, EventManagerTest_trigger_all_channels) { EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); return false; }; - EventManager::get_instance().subscribe<MouseClickEvent>(mouse_handler, - EventManager::CHANNEL_ALL); + event_mgr.subscribe<MouseClickEvent>(mouse_handler, EventManager::CHANNEL_ALL); MouseClickEvent click_event{.mouse_pos = {100, 200}, .button = MouseButton::LEFT_MOUSE}; EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, @@ -87,18 +71,17 @@ TEST_F(EventManagerTest, EventManagerTest_trigger_one_channel) { EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); return false; }; - EventManager::get_instance().subscribe<MouseClickEvent>(mouse_handler, test_channel); + event_mgr.subscribe<MouseClickEvent>(mouse_handler, test_channel); MouseClickEvent click_event{.mouse_pos = {100, 200}, .button = MouseButton::LEFT_MOUSE}; EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); EXPECT_FALSE(triggered); - EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, test_channel); + event_mgr.trigger_event<MouseClickEvent>(click_event, test_channel); } TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { - EventManager & event_manager = EventManager::get_instance(); // Flags to track handler calls bool triggered_true = false; @@ -127,7 +110,7 @@ TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { event_manager.subscribe<MouseClickEvent>(mouse_handler_false, EventManager::CHANNEL_ALL); // Trigger event - event_manager.trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); + event_mgr.trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); // Check that only the true handler was triggered EXPECT_TRUE(triggered_true); @@ -136,12 +119,12 @@ TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { // Reset and clear triggered_true = false; triggered_false = false; - event_manager.clear(); - event_manager.subscribe<MouseClickEvent>(mouse_handler_false, EventManager::CHANNEL_ALL); - event_manager.subscribe<MouseClickEvent>(mouse_handler_true, EventManager::CHANNEL_ALL); + event_mgr.clear(); + event_mgr.subscribe<MouseClickEvent>(mouse_handler_false, EventManager::CHANNEL_ALL); + event_mgr.subscribe<MouseClickEvent>(mouse_handler_true, EventManager::CHANNEL_ALL); // Trigger event again - event_manager.trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); + event_mgr.trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); // Check that both handlers were triggered EXPECT_TRUE(triggered_true); @@ -149,47 +132,37 @@ TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { } TEST_F(EventManagerTest, EventManagerTest_queue_dispatch) { - EventManager & event_manager = EventManager::get_instance(); bool triggered1 = false; bool triggered2 = false; int test_channel = 1; - - // Adjusted to use KeyPressEvent with repeat as the first variable - EventHandler<KeyPressEvent> key_handler1 = [&](const KeyPressEvent & e) { + EventHandler<MouseClickEvent> mouse_handler1 = [&](const MouseClickEvent & e) { triggered1 = true; - EXPECT_EQ(e.repeat, false); // Expecting repeat to be false - EXPECT_EQ(e.key, Keycode::A); // Adjust expected key code + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); return false; // Allows propagation }; - - EventHandler<KeyPressEvent> key_handler2 = [&](const KeyPressEvent & e) { + EventHandler<MouseClickEvent> mouse_handler2 = [&](const MouseClickEvent & e) { triggered2 = true; - EXPECT_EQ(e.repeat, false); // Expecting repeat to be false - EXPECT_EQ(e.key, Keycode::A); // Adjust expected key code + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); return false; // Allows propagation }; + event_mgr.subscribe<MouseClickEvent>(mouse_handler1); + event_mgr.subscribe<MouseClickEvent>(mouse_handler2, test_channel); - // Subscribe handlers to KeyPressEvent - event_manager.subscribe<KeyPressEvent>(key_handler1); - event_manager.subscribe<KeyPressEvent>(key_handler2, test_channel); - - // Queue a KeyPressEvent instead of KeyDownEvent - event_manager.queue_event<KeyPressEvent>(KeyPressEvent{ - .repeat = false, .key = Keycode::A}); // Adjust event with repeat flag first - - event_manager.queue_event<KeyPressEvent>( - KeyPressEvent{.repeat = false, - .key = Keycode::A}, // Adjust event for second subscription + event_mgr.queue_event<MouseClickEvent>( + MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}); + event_mgr.queue_event<MouseClickEvent>( + MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}, test_channel); - - event_manager.dispatch_events(); - + event_mgr.dispatch_events(); EXPECT_TRUE(triggered1); EXPECT_TRUE(triggered2); } TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { - EventManager & event_manager = EventManager::get_instance(); // Flags to track if handlers are triggered bool triggered1 = false; @@ -212,15 +185,15 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { return false; // Allows propagation }; // Subscribe handlers - subscription_t handler1_id = event_manager.subscribe<MouseClickEvent>(mouse_handler1); - subscription_t handler2_id = event_manager.subscribe<MouseClickEvent>(mouse_handler2); + subscription_t handler1_id = event_mgr.subscribe<MouseClickEvent>(mouse_handler1); + subscription_t handler2_id = event_mgr.subscribe<MouseClickEvent>(mouse_handler2); // Queue events event_manager.queue_event<MouseClickEvent>( MouseClickEvent{.mouse_pos = {100, 200}, .button = MouseButton::LEFT_MOUSE}); // Dispatch events - both handlers should be triggered - event_manager.dispatch_events(); + event_mgr.dispatch_events(); EXPECT_TRUE(triggered1); // Handler 1 should be triggered EXPECT_TRUE(triggered2); // Handler 2 should be triggered @@ -229,14 +202,14 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { triggered2 = false; // Unsubscribe handler1 - event_manager.unsubscribe(handler1_id); + event_mgr.unsubscribe(handler1_id); // Queue the same event again event_manager.queue_event<MouseClickEvent>( MouseClickEvent{.mouse_pos = {100, 200}, .button = MouseButton::LEFT_MOUSE}); // Dispatch events - only handler 2 should be triggered, handler 1 should NOT - event_manager.dispatch_events(); + event_mgr.dispatch_events(); EXPECT_FALSE(triggered1); // Handler 1 should NOT be triggered EXPECT_TRUE(triggered2); // Handler 2 should be triggered @@ -244,14 +217,14 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { triggered2 = false; // Unsubscribe handler2 - event_manager.unsubscribe(handler2_id); + event_mgr.unsubscribe(handler2_id); // Queue the event again event_manager.queue_event<MouseClickEvent>( MouseClickEvent{.mouse_pos = {100, 200}, .button = MouseButton::LEFT_MOUSE}); // Dispatch events - no handler should be triggered - event_manager.dispatch_events(); + event_mgr.dispatch_events(); EXPECT_FALSE(triggered1); // Handler 1 should NOT be triggered EXPECT_FALSE(triggered2); // Handler 2 should NOT be triggered } diff --git a/src/test/InputTest.cpp b/src/test/InputTest.cpp index a7058b2..a6e60b5 100644 --- a/src/test/InputTest.cpp +++ b/src/test/InputTest.cpp @@ -24,10 +24,10 @@ class InputTest : public ::testing::Test { public: Mediator mediator; ComponentManager mgr{mediator}; + SDLContext sdl_context{mediator}; InputSystem input_system{mediator}; - - EventManager & event_manager = EventManager::get_instance(); + EventManager event_manager{mediator}; //GameObject camera; protected: diff --git a/src/test/LoopManagerTest.cpp b/src/test/LoopManagerTest.cpp new file mode 100644 index 0000000..af89d64 --- /dev/null +++ b/src/test/LoopManagerTest.cpp @@ -0,0 +1,76 @@ +#include <chrono> +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <thread> +#define private public +#define protected public +#include <crepe/api/LoopManager.h> +#include <crepe/manager/EventManager.h> +#include <crepe/manager/LoopTimerManager.h> +using namespace std::chrono; +using namespace crepe; + +class LoopManagerTest : public ::testing::Test { +protected: + class TestGameLoop : public crepe::LoopManager { + public: + MOCK_METHOD(void, fixed_update, (), (override)); + MOCK_METHOD(void, frame_update, (), (override)); + }; + + TestGameLoop test_loop; + void SetUp() override {} +}; + +TEST_F(LoopManagerTest, FixedUpdate) { + // Arrange + test_loop.loop_timer.set_target_framerate(60); + + // Set expectations for the mock calls + EXPECT_CALL(test_loop, frame_update).Times(::testing::Between(55, 65)); + EXPECT_CALL(test_loop, fixed_update).Times(::testing::Between(48, 52)); + + // Start the loop in a separate thread + std::thread loop_thread([&]() { test_loop.start(); }); + + // Let the loop run for exactly 1 second + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // Stop the game loop + test_loop.game_running = false; + // Wait for the loop thread to finish + loop_thread.join(); + + // Test finished +} +TEST_F(LoopManagerTest, ScaledFixedUpdate) { + // Arrange + test_loop.loop_timer.set_target_framerate(60); + + // Set expectations for the mock calls + EXPECT_CALL(test_loop, frame_update).Times(::testing::Between(55, 65)); + EXPECT_CALL(test_loop, fixed_update).Times(::testing::Between(48, 52)); + + // Start the loop in a separate thread + std::thread loop_thread([&]() { test_loop.start(); }); + + // Let the loop run for exactly 1 second + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // Stop the game loop + test_loop.game_running = false; + // Wait for the loop thread to finish + loop_thread.join(); + + // Test finished +} +TEST_F(LoopManagerTest, ShutDown) { + // Arrange + test_loop.loop_timer.set_target_framerate(60); + // Start the loop in a separate thread + std::thread loop_thread([&]() { test_loop.start(); }); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + test_loop.event_manager.trigger_event<ShutDownEvent>(ShutDownEvent{}); + // Wait for the loop thread to finish + loop_thread.join(); +} diff --git a/src/test/LoopTimerTest.cpp b/src/test/LoopTimerTest.cpp new file mode 100644 index 0000000..5e1eccf --- /dev/null +++ b/src/test/LoopTimerTest.cpp @@ -0,0 +1,78 @@ +#include <chrono> +#include <gtest/gtest.h> +#include <thread> +#define private public +#define protected public +#include <crepe/manager/LoopTimerManager.h> +#include <crepe/manager/Mediator.h> +using namespace std::chrono; +using namespace crepe; + +class LoopTimerTest : public ::testing::Test { +protected: + Mediator mediator; + LoopTimerManager loop_timer{mediator}; + + void SetUp() override { loop_timer.start(); } +}; + +TEST_F(LoopTimerTest, EnforcesTargetFrameRate) { + // Set the target FPS to 60 (which gives a target time per frame of ~16.67 ms) + loop_timer.set_target_framerate(60); + + auto start_time = steady_clock::now(); + loop_timer.enforce_frame_rate(); + + auto elapsed_time = steady_clock::now() - start_time; + auto elapsed_ms = duration_cast<milliseconds>(elapsed_time).count(); + + // For 60 FPS, the target frame time is around 16.67ms + ASSERT_NEAR(elapsed_ms, 16.7, 1); +} + +TEST_F(LoopTimerTest, SetTargetFps) { + // Set the target FPS to 120 + loop_timer.set_target_framerate(120); + + // Calculate the expected frame time (~8.33ms per frame) + duration_t expected_frame_time = std::chrono::duration<float>(1.0 / 120.0); + + ASSERT_NEAR(loop_timer.frame_target_time.count(), expected_frame_time.count(), 0.001); +} + +TEST_F(LoopTimerTest, DeltaTimeCalculation) { + // Set the target FPS to 60 (16.67 ms per frame) + loop_timer.set_target_framerate(60); + + auto start_time = steady_clock::now(); + loop_timer.update(); + auto end_time = steady_clock::now(); + + // Check the delta time + duration_t delta_time = loop_timer.get_delta_time(); + + auto elapsed_time = duration_cast<seconds>(end_time - start_time).count(); + + // Assert that delta_time is close to the elapsed time + ASSERT_NEAR(delta_time.count(), elapsed_time, 1); +} + +TEST_F(LoopTimerTest, getCurrentTime) { + // Set the target FPS to 60 (16.67 ms per frame) + loop_timer.set_target_framerate(60); + + auto start_time = steady_clock::now(); + + // Sleep + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + loop_timer.update(); + + auto end_time = steady_clock::now(); + + // Get the elapsed time in seconds as a double + auto elapsed_time + = std::chrono::duration_cast<elapsed_time_t>(end_time - start_time).count(); + + ASSERT_NEAR(loop_timer.get_elapsed_time().count(), elapsed_time, 5); +} diff --git a/src/test/ParticleTest.cpp b/src/test/ParticleTest.cpp index 1409c4f..9112a3f 100644 --- a/src/test/ParticleTest.cpp +++ b/src/test/ParticleTest.cpp @@ -1,10 +1,10 @@ +#include "api/Asset.h" #include <crepe/Particle.h> #include <crepe/api/Config.h> #include <crepe/api/GameObject.h> #include <crepe/api/ParticleEmitter.h> #include <crepe/api/Rigidbody.h> #include <crepe/api/Sprite.h> -#include <crepe/api/Texture.h> #include <crepe/api/Transform.h> #include <crepe/manager/ComponentManager.h> #include <crepe/system/ParticleSystem.h> @@ -30,7 +30,7 @@ public: GameObject game_object = mgr.new_object("", "", vec2{0, 0}, 0, 0); Color color(0, 0, 0, 0); - auto s1 = Texture("asset/texture/img.png"); + auto s1 = Asset("asset/texture/img.png"); Sprite & test_sprite = game_object.add_component<Sprite>( s1, Sprite::Data{ .color = color, diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index c753bca..35f52dc 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -1,9 +1,11 @@ -#include "manager/Mediator.h" -#include "system/ParticleSystem.h" -#include "system/PhysicsSystem.h" -#include "system/RenderSystem.h" #include <chrono> #include <cmath> +#include <crepe/api/Asset.h> +#include <crepe/manager/Mediator.h> +#include <crepe/manager/ResourceManager.h> +#include <crepe/system/ParticleSystem.h> +#include <crepe/system/PhysicsSystem.h> +#include <crepe/system/RenderSystem.h> #include <gtest/gtest.h> #define private public @@ -15,6 +17,7 @@ #include <crepe/api/Rigidbody.h> #include <crepe/api/Script.h> #include <crepe/api/Transform.h> +#include <crepe/facade/SDLContext.h> #include <crepe/manager/ComponentManager.h> #include <crepe/manager/EventManager.h> #include <crepe/system/CollisionSystem.h> @@ -54,6 +57,8 @@ public: const std::chrono::microseconds duration = 16000us; Mediator m; + SDLContext sdl_context{m}; + ResourceManager resman{m}; ComponentManager mgr{m}; // Add system used for profling tests CollisionSystem collision_sys{m}; @@ -167,15 +172,15 @@ TEST_F(DISABLED_ProfilingTest, Profiling_2) { gameobject.add_component<BoxCollider>(vec2{0, 0}, vec2{1, 1}); gameobject.add_component<BehaviorScript>().set_script<TestScript>(); - auto img = Texture("asset/texture/square.png"); Sprite & test_sprite = gameobject.add_component<Sprite>( - img, Sprite::Data{ - .color = {0, 0, 0, 0}, - .flip = {.flip_x = false, .flip_y = false}, - .sorting_in_layer = 1, - .order_in_layer = 1, - .size = {.y = 500}, - }); + Asset{"asset/texture/square.png"}, + Sprite::Data{ + .color = {0, 0, 0, 0}, + .flip = {.flip_x = false, .flip_y = false}, + .sorting_in_layer = 1, + .order_in_layer = 1, + .size = {.y = 500}, + }); } this->game_object_count++; @@ -205,15 +210,15 @@ TEST_F(DISABLED_ProfilingTest, Profiling_3) { }); gameobject.add_component<BoxCollider>(vec2{0, 0}, vec2{1, 1}); gameobject.add_component<BehaviorScript>().set_script<TestScript>(); - auto img = Texture("asset/texture/square.png"); Sprite & test_sprite = gameobject.add_component<Sprite>( - img, Sprite::Data{ - .color = {0, 0, 0, 0}, - .flip = {.flip_x = false, .flip_y = false}, - .sorting_in_layer = 1, - .order_in_layer = 1, - .size = {.y = 500}, - }); + Asset{"asset/texture/square.png"}, + Sprite::Data{ + .color = {0, 0, 0, 0}, + .flip = {.flip_x = false, .flip_y = false}, + .sorting_in_layer = 1, + .order_in_layer = 1, + .size = {.y = 500}, + }); auto & test = gameobject.add_component<ParticleEmitter>(ParticleEmitter::Data{ .max_particles = 10, .emission_rate = 100, diff --git a/src/test/RenderSystemTest.cpp b/src/test/RenderSystemTest.cpp index 205f534..b4519cb 100644 --- a/src/test/RenderSystemTest.cpp +++ b/src/test/RenderSystemTest.cpp @@ -1,3 +1,6 @@ +#include "api/Asset.h" +#include "facade/SDLContext.h" +#include "manager/ResourceManager.h" #include "types.h" #include <functional> #include <gtest/gtest.h> @@ -11,7 +14,6 @@ #include <crepe/api/Color.h> #include <crepe/api/GameObject.h> #include <crepe/api/Sprite.h> -#include <crepe/api/Texture.h> #include <crepe/manager/ComponentManager.h> #include <crepe/system/RenderSystem.h> @@ -25,6 +27,8 @@ class RenderSystemTest : public Test { public: ComponentManager mgr{m}; + SDLContext ctx{m}; + ResourceManager resource_manager{m}; RenderSystem sys{m}; GameObject entity1 = this->mgr.new_object("name"); GameObject entity2 = this->mgr.new_object("name"); @@ -32,10 +36,10 @@ public: GameObject entity4 = this->mgr.new_object("name"); void SetUp() override { - auto s1 = Texture("asset/texture/img.png"); - auto s2 = Texture("asset/texture/img.png"); - auto s3 = Texture("asset/texture/img.png"); - auto s4 = Texture("asset/texture/img.png"); + auto s1 = Asset("asset/texture/img.png"); + auto s2 = Asset("asset/texture/img.png"); + auto s3 = Asset("asset/texture/img.png"); + auto s4 = Asset("asset/texture/img.png"); auto & sprite1 = entity1.add_component<Sprite>(s1, Sprite::Data{ .color = Color(0, 0, 0, 0), @@ -45,7 +49,6 @@ public: .size = {10, 10}, }); - ASSERT_NE(sprite1.texture.texture.get(), nullptr); EXPECT_EQ(sprite1.data.order_in_layer, 5); EXPECT_EQ(sprite1.data.sorting_in_layer, 5); auto & sprite2 @@ -55,7 +58,6 @@ public: .sorting_in_layer = 2, .order_in_layer = 1, }); - ASSERT_NE(sprite2.texture.texture.get(), nullptr); EXPECT_EQ(sprite2.data.sorting_in_layer, 2); EXPECT_EQ(sprite2.data.order_in_layer, 1); @@ -66,7 +68,6 @@ public: .sorting_in_layer = 1, .order_in_layer = 2, }); - ASSERT_NE(sprite3.texture.texture.get(), nullptr); EXPECT_EQ(sprite3.data.sorting_in_layer, 1); EXPECT_EQ(sprite3.data.order_in_layer, 2); @@ -77,27 +78,12 @@ public: .sorting_in_layer = 1, .order_in_layer = 1, }); - ASSERT_NE(sprite4.texture.texture.get(), nullptr); EXPECT_EQ(sprite4.data.sorting_in_layer, 1); EXPECT_EQ(sprite4.data.order_in_layer, 1); } }; -TEST_F(RenderSystemTest, expected_throws) { - GameObject entity1 = this->mgr.new_object("NAME"); - - // no texture img - EXPECT_ANY_THROW({ - auto test = Texture(""); - auto & sprite1 = entity1.add_component<Sprite>( - test, Sprite::Data{ - .color = Color(0, 0, 0, 0), - .flip = Sprite::FlipSettings{false, false}, - .sorting_in_layer = 1, - .order_in_layer = 1, - }); - }); - +TEST_F(RenderSystemTest, NoCamera) { // No camera EXPECT_ANY_THROW({ this->sys.update(); }); } @@ -185,7 +171,7 @@ TEST_F(RenderSystemTest, Color) { Camera::Data{.bg_color = Color::WHITE, .zoom = 1.0f}); auto & sprite = this->mgr.get_components_by_id<Sprite>(entity1.id).front().get(); - ASSERT_NE(sprite.texture.texture.get(), nullptr); + //ASSERT_NE(sprite.texture.texture.get(), nullptr); sprite.data.color = Color::GREEN; EXPECT_EQ(sprite.data.color.r, Color::GREEN.r); diff --git a/src/test/ResourceManagerTest.cpp b/src/test/ResourceManagerTest.cpp new file mode 100644 index 0000000..965eeab --- /dev/null +++ b/src/test/ResourceManagerTest.cpp @@ -0,0 +1,84 @@ +#include "manager/Mediator.h" +#include <gtest/gtest.h> + +#define private public +#define protected public + +#include <crepe/api/GameObject.h> +#include <crepe/manager/ResourceManager.h> +#include <crepe/util/Log.h> + +using namespace std; +using namespace crepe; +using namespace testing; + +class ResourceManagerTest : public Test { + Mediator mediator; + +public: + ResourceManager resource_manager{mediator}; + + class Unrelated : public Resource { + using Resource::Resource; + }; + + Asset asset_a{"asset/texture/img.png"}; + Asset asset_b{"asset/texture/ERROR.png"}; + + class TestResource : public Resource { + public: + static unsigned instances; + + public: + const unsigned instance; + TestResource(const Asset & src, Mediator & mediator) + : Resource(src, mediator), + instance(this->instances++) {} + ~TestResource() { this->instances--; } + bool operator==(const TestResource & other) const { + return this->instance == other.instance; + } + }; + +private: + void SetUp() override { TestResource::instances = 0; } +}; +unsigned ResourceManagerTest::TestResource::instances = 0; + +TEST_F(ResourceManagerTest, Default) { + TestResource & res_1 = resource_manager.get<TestResource>(asset_a); + TestResource & res_2 = resource_manager.get<TestResource>(asset_a); + TestResource & res_3 = resource_manager.get<TestResource>(asset_b); + TestResource & res_4 = resource_manager.get<TestResource>(asset_b); + + ASSERT_EQ(res_1, res_2); + ASSERT_EQ(res_3, res_4); + EXPECT_NE(res_1, res_3); + + EXPECT_EQ(TestResource::instances, 2); + + resource_manager.clear(); +} + +TEST_F(ResourceManagerTest, Persistent) { + resource_manager.set_persistent(asset_a, true); + EXPECT_EQ(TestResource::instances, 0); + + resource_manager.get<TestResource>(asset_a); + resource_manager.get<TestResource>(asset_a); + resource_manager.get<TestResource>(asset_b); + resource_manager.get<TestResource>(asset_b); + EXPECT_EQ(TestResource::instances, 2); + + resource_manager.clear(); + EXPECT_EQ(TestResource::instances, 1); + + resource_manager.clear_all(); + EXPECT_EQ(TestResource::instances, 0); +} + +TEST_F(ResourceManagerTest, UnmatchedType) { + EXPECT_NO_THROW({ resource_manager.get<TestResource>(asset_a); }); + + EXPECT_THROW({ resource_manager.get<Unrelated>(asset_a); }, runtime_error); +} diff --git a/src/test/SaveManagerTest.cpp b/src/test/SaveManagerTest.cpp new file mode 100644 index 0000000..e9b0c29 --- /dev/null +++ b/src/test/SaveManagerTest.cpp @@ -0,0 +1,40 @@ +#include <gtest/gtest.h> + +#include <crepe/ValueBroker.h> +#include <crepe/facade/DB.h> +#include <crepe/manager/SaveManager.h> + +using namespace std; +using namespace crepe; +using namespace testing; + +class SaveManagerTest : public Test { + Mediator m; + class TestSaveManager : public SaveManager { + using SaveManager::SaveManager; + + // in-memory database for testing + DB db{}; + virtual DB & get_db() override { return this->db; } + }; + +public: + TestSaveManager mgr{m}; +}; + +TEST_F(SaveManagerTest, ReadWrite) { + ASSERT_FALSE(mgr.has("foo")); + mgr.set<string>("foo", "bar"); + ASSERT_TRUE(mgr.has("foo")); + + ValueBroker value = mgr.get<string>("foo"); + EXPECT_EQ(value.get(), "bar"); +} + +TEST_F(SaveManagerTest, DefaultValue) { + ValueBroker value = mgr.get<int>("foo", 3); + + ASSERT_EQ(value.get(), 3); + value.set(5); + ASSERT_EQ(value.get(), 5); +} diff --git a/src/test/ScriptECSTest.cpp b/src/test/ScriptECSTest.cpp new file mode 100644 index 0000000..1ec33ba --- /dev/null +++ b/src/test/ScriptECSTest.cpp @@ -0,0 +1,41 @@ +#include <gtest/gtest.h> + +#define protected public + +#include <crepe/api/BehaviorScript.h> +#include <crepe/api/GameObject.h> +#include <crepe/api/Metadata.h> +#include <crepe/api/Script.h> +#include <crepe/manager/ComponentManager.h> +#include <crepe/system/ScriptSystem.h> + +#include "ScriptTest.h" + +using namespace std; +using namespace crepe; +using namespace testing; + +class ScriptECSTest : public ScriptTest { +public: + class TestComponent : public Component { + using Component::Component; + }; +}; + +TEST_F(ScriptECSTest, GetOwnComponent) { + MyScript & script = this->script; + Metadata & metadata = script.get_component<Metadata>(); + + EXPECT_EQ(metadata.name, OBJ_NAME); +} + +TEST_F(ScriptECSTest, GetOwnComponents) { + const unsigned COUNT = 4; + + for (unsigned i = 0; i < COUNT; i++) entity.add_component<TestComponent>(); + + MyScript & script = this->script; + RefVector<TestComponent> components = script.get_components<TestComponent>(); + + EXPECT_EQ(components.size(), COUNT); +} diff --git a/src/test/ScriptEventTest.cpp b/src/test/ScriptEventTest.cpp index 5da31e7..c1b4028 100644 --- a/src/test/ScriptEventTest.cpp +++ b/src/test/ScriptEventTest.cpp @@ -26,7 +26,7 @@ public: class MyEvent : public Event {}; }; -TEST_F(ScriptEventTest, Inactive) { +TEST_F(ScriptEventTest, Default) { BehaviorScript & behaviorscript = this->behaviorscript; MyScript & script = this->script; EventManager & evmgr = this->event_manager; diff --git a/src/test/ScriptSaveManagerTest.cpp b/src/test/ScriptSaveManagerTest.cpp new file mode 100644 index 0000000..64403c4 --- /dev/null +++ b/src/test/ScriptSaveManagerTest.cpp @@ -0,0 +1,35 @@ +#include <gtest/gtest.h> + +// stupid hack to allow access to private/protected members under test +#define private public +#define protected public + +#include <crepe/facade/DB.h> +#include <crepe/manager/SaveManager.h> + +#include "ScriptTest.h" + +using namespace std; +using namespace crepe; +using namespace testing; + +class ScriptSaveManagerTest : public ScriptTest { +public: + class TestSaveManager : public SaveManager { + using SaveManager::SaveManager; + + // in-memory database for testing + DB db{}; + virtual DB & get_db() override { return this->db; } + }; + + TestSaveManager save_mgr{mediator}; +}; + +TEST_F(ScriptSaveManagerTest, GetSaveManager) { + MyScript & script = this->script; + + SaveManager & mgr = script.get_save_manager(); + + EXPECT_EQ(&mgr, &save_mgr); +} diff --git a/src/test/ScriptSceneTest.cpp b/src/test/ScriptSceneTest.cpp index 9ee1e52..2568049 100644 --- a/src/test/ScriptSceneTest.cpp +++ b/src/test/ScriptSceneTest.cpp @@ -18,7 +18,7 @@ public: class MyScene : public Scene {}; }; -TEST_F(ScriptSceneTest, Inactive) { +TEST_F(ScriptSceneTest, Default) { BehaviorScript & behaviorscript = this->behaviorscript; MyScript & script = this->script; diff --git a/src/test/ScriptTest.cpp b/src/test/ScriptTest.cpp index 1d2d6dd..acdae70 100644 --- a/src/test/ScriptTest.cpp +++ b/src/test/ScriptTest.cpp @@ -6,7 +6,6 @@ #define protected public #include "ScriptTest.h" -#include <crepe/api/GameObject.h> using namespace std; using namespace crepe; @@ -14,7 +13,6 @@ using namespace testing; void ScriptTest::SetUp() { auto & mgr = this->component_manager; - GameObject entity = mgr.new_object("name"); BehaviorScript & component = entity.add_component<BehaviorScript>(); this->behaviorscript = component; diff --git a/src/test/ScriptTest.h b/src/test/ScriptTest.h index 1bbfdd3..31fa7c9 100644 --- a/src/test/ScriptTest.h +++ b/src/test/ScriptTest.h @@ -6,15 +6,18 @@ #include <crepe/api/BehaviorScript.h> #include <crepe/api/Script.h> #include <crepe/manager/ComponentManager.h> +#include <crepe/manager/EventManager.h> #include <crepe/system/ScriptSystem.h> - class ScriptTest : public testing::Test { protected: crepe::Mediator mediator; + static constexpr const char * OBJ_NAME = "foo"; public: crepe::ComponentManager component_manager{mediator}; crepe::ScriptSystem system{mediator}; + crepe::EventManager event_mgr{mediator}; + crepe::GameObject entity = component_manager.new_object(OBJ_NAME); class MyScript : public crepe::Script { // NOTE: explicitly stating `public:` is not required on actual scripts diff --git a/src/test/Vector2Test.cpp b/src/test/Vector2Test.cpp index 17bca41..1e21af9 100644 --- a/src/test/Vector2Test.cpp +++ b/src/test/Vector2Test.cpp @@ -382,3 +382,151 @@ TEST_F(Vector2Test, NotEquals) { EXPECT_FALSE(long_vec1 != long_vec1); EXPECT_TRUE(long_vec1 != long_vec2); } + +TEST_F(Vector2Test, Truncate) { + Vector2<int> vec = {3, 4}; + vec.truncate(3); + EXPECT_EQ(vec.x, 0); + EXPECT_EQ(vec.y, 0); + + Vector2<double> vec2 = {3.0, 4.0}; + vec2.truncate(3.0); + EXPECT_FLOAT_EQ(vec2.x, 1.8); + EXPECT_FLOAT_EQ(vec2.y, 2.4); + + Vector2<long> vec3 = {3, 4}; + vec3.truncate(3); + EXPECT_EQ(vec3.x, 0); + EXPECT_EQ(vec3.y, 0); + + Vector2<float> vec4 = {3.0f, 4.0f}; + vec4.truncate(3.0f); + EXPECT_FLOAT_EQ(vec4.x, 1.8f); + EXPECT_FLOAT_EQ(vec4.y, 2.4f); +} + +TEST_F(Vector2Test, Normalize) { + Vector2<int> vec = {3, 4}; + vec.normalize(); + EXPECT_EQ(vec.x, 0); + EXPECT_EQ(vec.y, 0); + + Vector2<double> vec2 = {3.0, 4.0}; + vec2.normalize(); + EXPECT_FLOAT_EQ(vec2.x, 0.6); + EXPECT_FLOAT_EQ(vec2.y, 0.8); + + Vector2<long> vec3 = {3, 4}; + vec3.normalize(); + EXPECT_EQ(vec3.x, 0); + EXPECT_EQ(vec3.y, 0); + + Vector2<float> vec4 = {3.0f, 4.0f}; + vec4.normalize(); + EXPECT_FLOAT_EQ(vec4.x, 0.6f); + EXPECT_FLOAT_EQ(vec4.y, 0.8f); +} + +TEST_F(Vector2Test, Length) { + Vector2<int> vec = {3, 4}; + EXPECT_EQ(vec.length(), 5); + + Vector2<double> vec2 = {3.0, 4.0}; + EXPECT_FLOAT_EQ(vec2.length(), 5.0); + + Vector2<long> vec3 = {3, 4}; + EXPECT_EQ(vec3.length(), 5); + + Vector2<float> vec4 = {3.0f, 4.0f}; + EXPECT_FLOAT_EQ(vec4.length(), 5.0f); +} + +TEST_F(Vector2Test, LengthSquared) { + Vector2<int> vec = {3, 4}; + EXPECT_EQ(vec.length_squared(), 25); + + Vector2<double> vec2 = {3.0, 4.0}; + EXPECT_FLOAT_EQ(vec2.length_squared(), 25.0); + + Vector2<long> vec3 = {3, 4}; + EXPECT_EQ(vec3.length_squared(), 25); + + Vector2<float> vec4 = {3.0f, 4.0f}; + EXPECT_FLOAT_EQ(vec4.length_squared(), 25.0f); +} + +TEST_F(Vector2Test, Dot) { + Vector2<int> vec1 = {3, 4}; + Vector2<int> vec2 = {5, 6}; + EXPECT_EQ(vec1.dot(vec2), 39); + + Vector2<double> vec3 = {3.0, 4.0}; + Vector2<double> vec4 = {5.0, 6.0}; + EXPECT_FLOAT_EQ(vec3.dot(vec4), 39.0); + + Vector2<long> vec5 = {3, 4}; + Vector2<long> vec6 = {5, 6}; + EXPECT_EQ(vec5.dot(vec6), 39); + + Vector2<float> vec7 = {3.0f, 4.0f}; + Vector2<float> vec8 = {5.0f, 6.0f}; + EXPECT_FLOAT_EQ(vec7.dot(vec8), 39.0f); +} + +TEST_F(Vector2Test, Distance) { + Vector2<int> vec1 = {1, 1}; + Vector2<int> vec2 = {4, 5}; + EXPECT_EQ(vec1.distance(vec2), 5); + + Vector2<double> vec3 = {1.0, 1.0}; + Vector2<double> vec4 = {4.0, 5.0}; + EXPECT_FLOAT_EQ(vec3.distance(vec4), 5.0); + + Vector2<long> vec5 = {1, 1}; + Vector2<long> vec6 = {4, 5}; + EXPECT_EQ(vec5.distance(vec6), 5); + + Vector2<float> vec7 = {1.0f, 1.0f}; + Vector2<float> vec8 = {4.0f, 5.0f}; + EXPECT_FLOAT_EQ(vec7.distance(vec8), 5.0f); +} + +TEST_F(Vector2Test, DistanceSquared) { + Vector2<int> vec1 = {3, 4}; + Vector2<int> vec2 = {5, 6}; + EXPECT_EQ(vec1.distance_squared(vec2), 8); + + Vector2<double> vec3 = {3.0, 4.0}; + Vector2<double> vec4 = {5.0, 6.0}; + EXPECT_FLOAT_EQ(vec3.distance_squared(vec4), 8.0); + + Vector2<long> vec5 = {3, 4}; + Vector2<long> vec6 = {5, 6}; + EXPECT_EQ(vec5.distance_squared(vec6), 8); + + Vector2<float> vec7 = {3.0f, 4.0f}; + Vector2<float> vec8 = {5.0f, 6.0f}; + EXPECT_FLOAT_EQ(vec7.distance_squared(vec8), 8.0f); +} + +TEST_F(Vector2Test, Perpendicular) { + Vector2<int> vec = {3, 4}; + Vector2<int> result = vec.perpendicular(); + EXPECT_EQ(result.x, -4); + EXPECT_EQ(result.y, 3); + + Vector2<double> vec2 = {3.0, 4.0}; + Vector2<double> result2 = vec2.perpendicular(); + EXPECT_FLOAT_EQ(result2.x, -4.0); + EXPECT_FLOAT_EQ(result2.y, 3.0); + + Vector2<long> vec3 = {3, 4}; + Vector2<long> result3 = vec3.perpendicular(); + EXPECT_EQ(result3.x, -4); + EXPECT_EQ(result3.y, 3); + + Vector2<float> vec4 = {3.0f, 4.0f}; + Vector2<float> result4 = vec4.perpendicular(); + EXPECT_FLOAT_EQ(result4.x, -4.0f); + EXPECT_FLOAT_EQ(result4.y, 3.0f); +} diff --git a/src/test/main.cpp b/src/test/main.cpp index aece72d..ed2aed5 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -1,9 +1,5 @@ -#include <gtest/gtest.h> - -#define protected public -#define private public - #include <crepe/api/Config.h> +#include <gtest/gtest.h> using namespace crepe; using namespace testing; @@ -11,12 +7,14 @@ using namespace testing; class GlobalConfigReset : public EmptyTestEventListener { public: Config & cfg = Config::get_instance(); - Config cfg_default = Config(); // This function is called before each test void OnTestStart(const TestInfo &) override { - cfg = cfg_default; - cfg.log.level = Log::Level::WARNING; + cfg = { + .log = { + .level = Log::Level::WARNING, + }, + }; } }; |