/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include #include #include #include #include #include class GameStateTest : public UnitTest::AllocatorsTestFixture { protected: void SetUp() override { AllocatorsTestFixture::SetUp(); m_gameStateSystemComponent = AZStd::make_unique(); m_gameStateSystemComponent->GameState::GameStateRequestBus::Handler::BusConnect(); } void TearDown() override { m_gameStateSystemComponent->GameState::GameStateRequestBus::Handler::BusDisconnect(); m_gameStateSystemComponent.reset(); AllocatorsTestFixture::TearDown(); } private: AZStd::unique_ptr m_gameStateSystemComponent; }; class TestGameStateA : public GameState::IGameState { public: AZ_CLASS_ALLOCATOR(TestGameStateA, AZ::SystemAllocator, 0); AZ_RTTI(TestGameStateA, "{81345EC1-3F5F-4F6E-AEC0-49143BE8D133}", IGameState); void OnPushed() override { ASSERT_TRUE(!m_isPushed); m_isPushed = true; } void OnPopped() override { ASSERT_TRUE(m_isPushed); m_isPushed = false; } void OnEnter() override { ASSERT_TRUE(m_isPushed); ASSERT_TRUE(!m_isActive); m_isActive = true; } void OnExit() override { ASSERT_TRUE(m_isPushed); ASSERT_TRUE(m_isActive); m_isActive = false; } private: bool m_isPushed = false; bool m_isActive = false; }; class TestGameStateB : public TestGameStateA { public: AZ_CLASS_ALLOCATOR(TestGameStateB, AZ::SystemAllocator, 0); AZ_RTTI(TestGameStateB, "{DBA86F9F-DEAF-426D-8496-AC9A20256E5D}", TestGameStateA); }; class TestGameStateC : public TestGameStateA { public: AZ_CLASS_ALLOCATOR(TestGameStateC, AZ::SystemAllocator, 0); AZ_RTTI(TestGameStateC, "{F6C6C512-9F19-4B2B-A8B2-A0F0552E27EB}", TestGameStateA); }; class TestGameStateX : public GameState::IGameState { public: AZ_CLASS_ALLOCATOR(TestGameStateX, AZ::SystemAllocator, 0); AZ_RTTI(TestGameStateX, "{FCF63A12-ED21-4432-AB71-F268CC49126E}", IGameState); }; TEST_F(GameStateTest, PushThenPopOneGameState) { // Push A GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop A GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); } TEST_F(GameStateTest, PushThenPopTwoGameStates) { // Push A GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Push B GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop B GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop A GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); } TEST_F(GameStateTest, PopAllGameStates) { // Push A GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Push B GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Push C GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop all game states GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopAllGameStates); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Check the active game state is null AZStd::shared_ptr activeGameState; GameState::GameStateRequestBus::BroadcastResult(activeGameState, &GameState::GameStateRequests::GetActiveGameState); ASSERT_TRUE(activeGameState == nullptr); } TEST_F(GameStateTest, PopActiveGameStateUntilOfType) { // Push A GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Push B GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Push C GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop until C is active (ie. do nothing) ASSERT_TRUE(GameState::GameStateRequests::PopActiveGameStateUntilOfType()); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop until something inheriting from A is active (which C does, so do nothing again) ASSERT_TRUE(GameState::GameStateRequests::PopActiveGameStateUntilOfType()); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop until something inheriting from B is active (which C doesn't) ASSERT_TRUE(GameState::GameStateRequests::PopActiveGameStateUntilOfType()); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop until something inheriting from C is active (C is no longer in the stack) ASSERT_FALSE(GameState::GameStateRequests::PopActiveGameStateUntilOfType()); } TEST_F(GameStateTest, ReplaceActiveGameState) { // Push A GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Replace A with B AZStd::shared_ptr gameStateB = AZStd::make_shared(); GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::ReplaceActiveGameState, gameStateB); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop B GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); } TEST_F(GameStateTest, DoesStackContainGameStateOfType) { // Push A GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); // Push B GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); // Push C GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); // Pop C GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); // Pop B GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); // Pop A GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType()); } TEST_F(GameStateTest, PushSameGameStateTwice) { // Push A AZStd::shared_ptr gameStateA = AZStd::make_shared(); bool result = false; GameState::GameStateRequestBus::BroadcastResult(result, &GameState::GameStateRequests::PushGameState, gameStateA); ASSERT_TRUE(result); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Push same instance of A again GameState::GameStateRequestBus::BroadcastResult(result, &GameState::GameStateRequests::PushGameState, gameStateA); ASSERT_FALSE(result); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop A GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); } TEST_F(GameStateTest, AddGameStateFactoryOverrideWithDerived) { // Override A with B ASSERT_TRUE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType([]() { return AZStd::make_shared(); })); // Push A (overriden by B) GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop A (overriden by B) GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); } TEST_F(GameStateTest, AddGameStateFactoryOverrideWithNotDerived) { // Override A with X ASSERT_FALSE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType([]() { return AZStd::make_shared(); })); // Push A (not overriden by X) GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop A (not overriden by X) GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); } TEST_F(GameStateTest, AddGameStateFactoryOverrideButDontCheck) { // Override A with B ASSERT_TRUE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType([]() { return AZStd::make_shared(); })); // Push A (overriden by B, but don't check for overrides) GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(false); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); } TEST_F(GameStateTest, AddGameStateFactoryOverrideTwice) { // Override A with B ASSERT_TRUE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType([]() { return AZStd::make_shared(); })); // Try override A with C ASSERT_FALSE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType([]() { return AZStd::make_shared(); })); // Try override A with B again ASSERT_FALSE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType([]() { return AZStd::make_shared(); })); } TEST_F(GameStateTest, RemoveGameStateFactoryOverride) { // Override A with B ASSERT_TRUE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType([]() { return AZStd::make_shared(); })); // Push A (overriden by B) GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Remove Override A ASSERT_TRUE(GameState::GameStateRequests::RemoveGameStateFactoryOverrideForType()); ASSERT_FALSE(GameState::GameStateRequests::RemoveGameStateFactoryOverrideForType()); // Push A GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Override A with C ASSERT_TRUE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType([]() { return AZStd::make_shared(); })); // Push A (overriden by C) GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType(); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Remove Override A ASSERT_TRUE(GameState::GameStateRequests::RemoveGameStateFactoryOverrideForType()); ASSERT_FALSE(GameState::GameStateRequests::RemoveGameStateFactoryOverrideForType()); // Pop A (overriden by C) GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop A GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); // Pop A (overriden by B) GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType()); } AZ_UNIT_TEST_HOOK();