// // game_dispatch_test.cxx // engine-test // // Created by Sam Jaffe on 7/10/19. // Copyright © 2019 Sam Jaffe. All rights reserved. // #include #include #include "game/engine/events.hpp" #include "game/engine/game_dispatch.hpp" #include "game/engine/scene.hpp" #include "game/graphics/renderer.hpp" #include "game/util/env.hpp" #include "mock_renderer.h" struct mock_scene : engine::scene { mock_scene(std::shared_ptr game) : engine::scene("mock", {}, game) {} MOCK_METHOD1(update, void(float)); MOCK_METHOD0(render, void()); MOCK_METHOD1(handle_key_event, void(engine::event::key_event)); MOCK_METHOD1(handle_mouse_event, void(engine::event::mouse_event)); }; class GameDispatchTest : public testing::Test { protected: void SetUp() override; void TearDown() override; mock_scene & scene() const { return *scene_; } engine::game_dispatch & game() const { return *dispatch_; } std::shared_ptr renderer_; std::shared_ptr dispatch_; std::shared_ptr scene_; }; void GameDispatchTest::SetUp() { env::resize_screen({{100, 100}}); renderer_.reset(new stub_renderer); dispatch_.reset(new engine::game_dispatch(renderer_)); scene_.reset(new mock_scene(dispatch_)); game().register_scene(scene_); game().activate_scene("mock"); } void GameDispatchTest::TearDown() { scene_.reset(); dispatch_.reset(); renderer_.reset(); } using testing::AnyNumber; using testing::Eq; using testing::Field; using testing::FloatNear; using testing::Ge; using testing::Lt; using testing::_; TEST_F(GameDispatchTest, ManagerIsFetchedFromRenderer) { EXPECT_THAT(&game().graphics_manager(), Eq(renderer_->manager().get())); } // TODO: Set FPS to a much smaller value for testing purposes (e.g. 512fps) TEST_F(GameDispatchTest, UpdateDispatchesToCurrentScene) { EXPECT_CALL(scene(), update(_)).Times(1); game().update(); } TEST_F(GameDispatchTest, UpdateIsCappedInFrequencyByFPSParam) { auto fps60 = 1.0 / 60.0; EXPECT_CALL(scene(), update(Ge(fps60))).Times(AnyNumber()); EXPECT_CALL(scene(), update(Lt(fps60))).Times(0); for (int i = 0; i < 10; i++) { game().update(); } } TEST_F(GameDispatchTest, UpdateHasNoUpperBoundOnTime) { EXPECT_CALL(scene(), update(Ge(0.03))).Times(1); usleep(300000); game().update(); } TEST_F(GameDispatchTest, SetCurrentTimestampOverridesWaiting) { auto fps60 = 1.0 / 60.0; EXPECT_CALL(scene(), update(Ge(0.03))).Times(0); EXPECT_CALL(scene(), update(FloatNear(fps60, 1E-2))).Times(1); usleep(300000); game().set_current_timestamp(); game().update(); } TEST_F(GameDispatchTest, RenderDispatchesToCurrentScene) { EXPECT_CALL(scene(), render()).Times(1); game().render(); } using MouseEventTest = GameDispatchTest; TEST_F(MouseEventTest, DispatchesToCurrentScene) { EXPECT_CALL(scene(), handle_mouse_event(_)).Times(1); game().process_mouse_event({{0.f, 0.f}}, true); } TEST_F(MouseEventTest, TranslatesFrameOfRef) { // TODO: Actually set the local scene size element... auto mouse_pos = &engine::event::mouse_event::current_mouse_position; auto const where = make_vector(5.f, 5.f); EXPECT_CALL(scene(), handle_mouse_event(Field(mouse_pos, where))).Times(1); game().process_mouse_event({{50.f, 50.f}}, true); } using KeyEventTest = GameDispatchTest; TEST_F(KeyEventTest, DoesNotDispatchUnmappedKeys) { EXPECT_CALL(scene(), handle_key_event(_)).Times(0); game().process_key_event('A', true); } TEST_F(KeyEventTest, RemapsKeyWhenForwarding) { // TODO: Properly set this instead of using this garbage const_cast(scene().keys()).emplace('A', 'B'); auto key_value = &engine::event::key_event::key; EXPECT_CALL(scene(), handle_key_event(Field(key_value, 'A'))).Times(0); EXPECT_CALL(scene(), handle_key_event(Field(key_value, 'B'))).Times(1); game().process_key_event('A', true); }