GameStateTest.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <GameStateSystemComponent.h>
  9. #include <AzTest/AzTest.h>
  10. #include <AzCore/Memory/OSAllocator.h>
  11. #include <AzCore/Memory/SystemAllocator.h>
  12. #include <AzCore/std/smart_ptr/unique_ptr.h>
  13. #include <AzCore/UnitTest/TestTypes.h>
  14. class GameStateTest
  15. : public UnitTest::LeakDetectionFixture
  16. {
  17. protected:
  18. void SetUp() override
  19. {
  20. LeakDetectionFixture::SetUp();
  21. m_gameStateSystemComponent = AZStd::make_unique<GameState::GameStateSystemComponent>();
  22. m_gameStateSystemComponent->GameState::GameStateRequestBus::Handler::BusConnect();
  23. }
  24. void TearDown() override
  25. {
  26. m_gameStateSystemComponent->GameState::GameStateRequestBus::Handler::BusDisconnect();
  27. m_gameStateSystemComponent.reset();
  28. LeakDetectionFixture::TearDown();
  29. }
  30. private:
  31. AZStd::unique_ptr<GameState::GameStateSystemComponent> m_gameStateSystemComponent;
  32. };
  33. class TestGameStateA : public GameState::IGameState
  34. {
  35. public:
  36. AZ_CLASS_ALLOCATOR(TestGameStateA, AZ::SystemAllocator);
  37. AZ_RTTI(TestGameStateA, "{81345EC1-3F5F-4F6E-AEC0-49143BE8D133}", IGameState);
  38. void OnPushed() override
  39. {
  40. ASSERT_TRUE(!m_isPushed);
  41. m_isPushed = true;
  42. }
  43. void OnPopped() override
  44. {
  45. ASSERT_TRUE(m_isPushed);
  46. m_isPushed = false;
  47. }
  48. void OnEnter() override
  49. {
  50. ASSERT_TRUE(m_isPushed);
  51. ASSERT_TRUE(!m_isActive);
  52. m_isActive = true;
  53. }
  54. void OnExit() override
  55. {
  56. ASSERT_TRUE(m_isPushed);
  57. ASSERT_TRUE(m_isActive);
  58. m_isActive = false;
  59. }
  60. private:
  61. bool m_isPushed = false;
  62. bool m_isActive = false;
  63. };
  64. class TestGameStateB : public TestGameStateA
  65. {
  66. public:
  67. AZ_CLASS_ALLOCATOR(TestGameStateB, AZ::SystemAllocator);
  68. AZ_RTTI(TestGameStateB, "{DBA86F9F-DEAF-426D-8496-AC9A20256E5D}", TestGameStateA);
  69. };
  70. class TestGameStateC : public TestGameStateA
  71. {
  72. public:
  73. AZ_CLASS_ALLOCATOR(TestGameStateC, AZ::SystemAllocator);
  74. AZ_RTTI(TestGameStateC, "{F6C6C512-9F19-4B2B-A8B2-A0F0552E27EB}", TestGameStateA);
  75. };
  76. class TestGameStateX : public GameState::IGameState
  77. {
  78. public:
  79. AZ_CLASS_ALLOCATOR(TestGameStateX, AZ::SystemAllocator);
  80. AZ_RTTI(TestGameStateX, "{FCF63A12-ED21-4432-AB71-F268CC49126E}", IGameState);
  81. };
  82. TEST_F(GameStateTest, PushThenPopOneGameState)
  83. {
  84. // Push A
  85. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  86. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  87. // Pop A
  88. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  89. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  90. }
  91. TEST_F(GameStateTest, PushThenPopTwoGameStates)
  92. {
  93. // Push A
  94. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  95. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  96. // Push B
  97. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateB>();
  98. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  99. // Pop B
  100. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  101. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  102. // Pop A
  103. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  104. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  105. }
  106. TEST_F(GameStateTest, PopAllGameStates)
  107. {
  108. // Push A
  109. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  110. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  111. // Push B
  112. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateB>();
  113. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  114. // Push C
  115. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateC>();
  116. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  117. // Pop all game states
  118. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopAllGameStates);
  119. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  120. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  121. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  122. // Check the active game state is null
  123. AZStd::shared_ptr<GameState::IGameState> activeGameState;
  124. GameState::GameStateRequestBus::BroadcastResult(activeGameState, &GameState::GameStateRequests::GetActiveGameState);
  125. ASSERT_TRUE(activeGameState == nullptr);
  126. }
  127. TEST_F(GameStateTest, PopActiveGameStateUntilOfType)
  128. {
  129. // Push A
  130. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  131. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  132. // Push B
  133. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateB>();
  134. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  135. // Push C
  136. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateC>();
  137. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  138. // Pop until C is active (ie. do nothing)
  139. ASSERT_TRUE(GameState::GameStateRequests::PopActiveGameStateUntilOfType<TestGameStateC>());
  140. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  141. // Pop until something inheriting from A is active (which C does, so do nothing again)
  142. ASSERT_TRUE(GameState::GameStateRequests::PopActiveGameStateUntilOfType<TestGameStateA>());
  143. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  144. // Pop until something inheriting from B is active (which C doesn't)
  145. ASSERT_TRUE(GameState::GameStateRequests::PopActiveGameStateUntilOfType<TestGameStateB>());
  146. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  147. // Pop until something inheriting from C is active (C is no longer in the stack)
  148. ASSERT_FALSE(GameState::GameStateRequests::PopActiveGameStateUntilOfType<TestGameStateC>());
  149. }
  150. TEST_F(GameStateTest, ReplaceActiveGameState)
  151. {
  152. // Push A
  153. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  154. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  155. // Replace A with B
  156. AZStd::shared_ptr<GameState::IGameState> gameStateB = AZStd::make_shared<TestGameStateB>();
  157. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::ReplaceActiveGameState, gameStateB);
  158. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  159. // Pop B
  160. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  161. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  162. }
  163. TEST_F(GameStateTest, DoesStackContainGameStateOfType)
  164. {
  165. // Push A
  166. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  167. ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateA>());
  168. ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateB>());
  169. ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateC>());
  170. // Push B
  171. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateB>();
  172. ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateA>());
  173. ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateB>());
  174. ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateC>());
  175. // Push C
  176. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateC>();
  177. ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateA>());
  178. ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateB>());
  179. ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateC>());
  180. // Pop C
  181. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  182. ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateA>());
  183. ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateB>());
  184. ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateC>());
  185. // Pop B
  186. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  187. ASSERT_TRUE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateA>());
  188. ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateB>());
  189. ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateC>());
  190. // Pop A
  191. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  192. ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateA>());
  193. ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateB>());
  194. ASSERT_FALSE(GameState::GameStateRequests::DoesStackContainGameStateOfType<TestGameStateC>());
  195. }
  196. TEST_F(GameStateTest, PushSameGameStateTwice)
  197. {
  198. // Push A
  199. AZStd::shared_ptr<GameState::IGameState> gameStateA = AZStd::make_shared<TestGameStateA>();
  200. bool result = false;
  201. GameState::GameStateRequestBus::BroadcastResult(result, &GameState::GameStateRequests::PushGameState, gameStateA);
  202. ASSERT_TRUE(result);
  203. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  204. // Push same instance of A again
  205. GameState::GameStateRequestBus::BroadcastResult(result, &GameState::GameStateRequests::PushGameState, gameStateA);
  206. ASSERT_FALSE(result);
  207. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  208. // Pop A
  209. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  210. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  211. }
  212. TEST_F(GameStateTest, AddGameStateFactoryOverrideWithDerived)
  213. {
  214. // Override A with B
  215. ASSERT_TRUE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType<TestGameStateA>([]()
  216. {
  217. return AZStd::make_shared<TestGameStateB>();
  218. }));
  219. // Push A (overriden by B)
  220. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  221. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  222. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  223. // Pop A (overriden by B)
  224. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  225. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  226. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  227. }
  228. TEST_F(GameStateTest, AddGameStateFactoryOverrideWithNotDerived)
  229. {
  230. // Override A with X
  231. ASSERT_FALSE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType<TestGameStateA>([]()
  232. {
  233. return AZStd::make_shared<TestGameStateX>();
  234. }));
  235. // Push A (not overriden by X)
  236. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  237. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  238. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateX>());
  239. // Pop A (not overriden by X)
  240. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  241. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  242. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateX>());
  243. }
  244. TEST_F(GameStateTest, AddGameStateFactoryOverrideButDontCheck)
  245. {
  246. // Override A with B
  247. ASSERT_TRUE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType<TestGameStateA>([]()
  248. {
  249. return AZStd::make_shared<TestGameStateB>();
  250. }));
  251. // Push A (overriden by B, but don't check for overrides)
  252. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>(false);
  253. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  254. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  255. }
  256. TEST_F(GameStateTest, AddGameStateFactoryOverrideTwice)
  257. {
  258. // Override A with B
  259. ASSERT_TRUE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType<TestGameStateA>([]()
  260. {
  261. return AZStd::make_shared<TestGameStateB>();
  262. }));
  263. // Try override A with C
  264. ASSERT_FALSE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType<TestGameStateA>([]()
  265. {
  266. return AZStd::make_shared<TestGameStateC>();
  267. }));
  268. // Try override A with B again
  269. ASSERT_FALSE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType<TestGameStateA>([]()
  270. {
  271. return AZStd::make_shared<TestGameStateB>();
  272. }));
  273. }
  274. TEST_F(GameStateTest, RemoveGameStateFactoryOverride)
  275. {
  276. // Override A with B
  277. ASSERT_TRUE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType<TestGameStateA>([]()
  278. {
  279. return AZStd::make_shared<TestGameStateB>();
  280. }));
  281. // Push A (overriden by B)
  282. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  283. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  284. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  285. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  286. // Remove Override A
  287. ASSERT_TRUE(GameState::GameStateRequests::RemoveGameStateFactoryOverrideForType<TestGameStateA>());
  288. ASSERT_FALSE(GameState::GameStateRequests::RemoveGameStateFactoryOverrideForType<TestGameStateA>());
  289. // Push A
  290. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  291. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  292. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  293. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  294. // Override A with C
  295. ASSERT_TRUE(GameState::GameStateRequests::AddGameStateFactoryOverrideForType<TestGameStateA>([]()
  296. {
  297. return AZStd::make_shared<TestGameStateC>();
  298. }));
  299. // Push A (overriden by C)
  300. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<TestGameStateA>();
  301. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  302. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  303. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  304. // Remove Override A
  305. ASSERT_TRUE(GameState::GameStateRequests::RemoveGameStateFactoryOverrideForType<TestGameStateA>());
  306. ASSERT_FALSE(GameState::GameStateRequests::RemoveGameStateFactoryOverrideForType<TestGameStateA>());
  307. // Pop A (overriden by C)
  308. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  309. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  310. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  311. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  312. // Pop A
  313. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  314. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  315. ASSERT_TRUE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  316. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  317. // Pop A (overriden by B)
  318. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  319. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateA>());
  320. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateB>());
  321. ASSERT_FALSE(GameState::GameStateRequests::IsActiveGameStateOfType<TestGameStateC>());
  322. }
  323. AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);