3
0

SliceEntityOwnershipTests.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  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 <AzFramework/Entity/SliceEntityOwnershipService.h>
  9. #include "EntityOwnershipServiceTestFixture.h"
  10. #include <AzToolsFramework/Slice/SliceMetadataEntityContextBus.h>
  11. namespace UnitTest
  12. {
  13. class SliceEntityOwnershipTests
  14. : public EntityOwnershipServiceTestFixture
  15. {
  16. public:
  17. void SetUp() override
  18. {
  19. SetUpEntityOwnershipServiceTest();
  20. m_sliceEntityOwnershipService = AZStd::make_unique<AzFramework::SliceEntityOwnershipService>(AZ::Uuid::CreateNull(),
  21. m_app->GetSerializeContext());
  22. m_sliceEntityOwnershipService->Initialize();
  23. m_sliceEntityOwnershipService->SetEntitiesAddedCallback([this](const AzFramework::EntityList& entityList)
  24. {
  25. this->HandleEntitiesAdded(entityList);
  26. });
  27. m_sliceEntityOwnershipService->SetEntitiesRemovedCallback([this](const AzFramework::EntityIdList& entityIds)
  28. {
  29. this->HandleEntitiesRemoved(entityIds);
  30. });
  31. m_sliceEntityOwnershipService->SetValidateEntitiesCallback([this](const AzFramework::EntityList& entityList)
  32. {
  33. return this->ValidateEntities(entityList);
  34. });
  35. }
  36. void TearDown() override
  37. {
  38. m_sliceEntityOwnershipService->SetEntitiesAddedCallback(nullptr);
  39. // In order for the death tests to work, we have to destroy the EOS early. So, don't try to destroy again.
  40. if (m_sliceEntityOwnershipService->IsInitialized())
  41. {
  42. m_sliceEntityOwnershipService->Destroy();
  43. }
  44. m_sliceEntityOwnershipService.reset();
  45. TearDownEntityOwnershipServiceTest();
  46. }
  47. protected:
  48. AZStd::unique_ptr<AzFramework::SliceEntityOwnershipService> m_sliceEntityOwnershipService;
  49. };
  50. using SliceEntityOwnershipDeathTests = SliceEntityOwnershipTests;
  51. TEST_F(SliceEntityOwnershipTests, AddEntity_InitalizedCorrectly_EntityCreated)
  52. {
  53. AZ::Entity* testEntity = aznew AZ::Entity("testEntity");
  54. m_sliceEntityOwnershipService->AddEntity(testEntity);
  55. // Validate that entities-added callback is triggerted.
  56. EXPECT_TRUE(m_entitiesAddedCallbackTriggered);
  57. const AzFramework::EntityList& entitiesUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetNewEntities();
  58. // Validate that there is only one entity under root slice.
  59. EXPECT_EQ(entitiesUnderRootSlice.size(), 1);
  60. EXPECT_EQ(entitiesUnderRootSlice.at(0)->GetName(), "testEntity");
  61. }
  62. TEST_F(SliceEntityOwnershipTests, DestroyEntityById_EntityAdded_EntityDestroyed)
  63. {
  64. AZ::Entity* testEntity = aznew AZ::Entity("testEntity");
  65. m_sliceEntityOwnershipService->AddEntity(testEntity);
  66. AzFramework::EntityList entitiesUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetNewEntities();
  67. // Verify that entity is added
  68. EXPECT_EQ(entitiesUnderRootSlice.size(), 1);
  69. EXPECT_TRUE(m_sliceEntityOwnershipService->DestroyEntityById(testEntity->GetId()));
  70. entitiesUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetNewEntities();
  71. // Verify that entity is destroyed
  72. EXPECT_EQ(entitiesUnderRootSlice.size(), 0);
  73. }
  74. TEST_F(SliceEntityOwnershipTests, GetRootSlice_RootAssetAbsent_ReturnNull)
  75. {
  76. m_sliceEntityOwnershipService->Destroy();
  77. AZ::SliceComponent* rootSlice = nullptr;
  78. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(rootSlice,
  79. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::GetRootSlice);
  80. EXPECT_EQ(rootSlice, nullptr);
  81. }
  82. TEST_F(SliceEntityOwnershipTests, GetRootSlice_RootAssetPresent_ReturnRootSlice)
  83. {
  84. AZ::SliceComponent* rootSlice = nullptr;
  85. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(rootSlice,
  86. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::GetRootSlice);
  87. EXPECT_NE(rootSlice, nullptr);
  88. }
  89. TEST_F(SliceEntityOwnershipTests, Reset_SliceAdded_DestroySliceEntities)
  90. {
  91. AzFramework::EntityList entitiesToAdd = AzFramework::EntityList{ aznew AZ::Entity() };
  92. AddSlice(entitiesToAdd);
  93. size_t slicesCountBeforeReset = GetRootSliceAsset()->GetComponent()->GetSlices().size();
  94. // Verify that slice exists
  95. EXPECT_EQ(slicesCountBeforeReset, 1);
  96. m_sliceEntityOwnershipService->Reset();
  97. size_t slicesCountAfterReset = GetRootSliceAsset()->GetComponent()->GetSlices().size();
  98. // Verify that slices under rootSlice were removed after reset of EntityOwnershipService.
  99. EXPECT_EQ(slicesCountAfterReset, 0);
  100. // Verify that call to destroy entities in the added slice occured.
  101. EXPECT_TRUE(m_entityRemovedCallbackTriggered);
  102. }
  103. TEST_F(SliceEntityOwnershipTests, Reset_SliceInstantiationStarted_StopSliceInstantiation)
  104. {
  105. AddSlice(AzFramework::EntityList{}, true);
  106. m_sliceEntityOwnershipService->Reset();
  107. AZ::TickBus::ExecuteQueuedEvents();
  108. size_t slicesCountUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetSlices().size();
  109. EXPECT_EQ(slicesCountUnderRootSlice, 0);
  110. }
  111. TEST_F(SliceEntityOwnershipTests, Reset_EntityAdded_EntityDestroyedAfterReset)
  112. {
  113. AZ::Entity* testEntity = aznew AZ::Entity("testEntity");
  114. m_sliceEntityOwnershipService->AddEntity(testEntity);
  115. m_sliceEntityOwnershipService->Reset();
  116. const AzFramework::EntityList& entitiesUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetNewEntities();
  117. EXPECT_EQ(entitiesUnderRootSlice.size(), 0);
  118. EXPECT_TRUE(m_entityRemovedCallbackTriggered);
  119. }
  120. TEST_F(SliceEntityOwnershipTests, HandleRootEntityReloadedFromStream_NoRootEntity_FailToLoadEntity)
  121. {
  122. bool rootEntityLoadSuccessful = false;
  123. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(rootEntityLoadSuccessful,
  124. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::HandleRootEntityReloadedFromStream, nullptr, false, nullptr);
  125. EXPECT_FALSE(rootEntityLoadSuccessful);
  126. }
  127. TEST_F(SliceEntityOwnershipTests, HandleRootEntityReloadedFromStream_NoSliceComponent_FailToLoadEntity)
  128. {
  129. AZ::Entity* testEntity = aznew AZ::Entity();
  130. // Suppress the AZ_Error thrown for not creating the root slice.
  131. AZ_TEST_START_TRACE_SUPPRESSION;
  132. bool rootEntityLoadSuccessful = false;
  133. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(rootEntityLoadSuccessful,
  134. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::HandleRootEntityReloadedFromStream, testEntity, false, nullptr);
  135. EXPECT_FALSE(rootEntityLoadSuccessful);
  136. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  137. delete testEntity;
  138. }
  139. TEST_F(SliceEntityOwnershipTests, HandleRootEntityReloadedFromStream_RemapIdsTrue_IdsRemapped)
  140. {
  141. AZ::Entity* rootEntity = aznew AZ::Entity();
  142. AZ::SliceComponent* rootSliceComponent = rootEntity->CreateComponent<AZ::SliceComponent>();
  143. AZ::Entity* testEntity = aznew AZ::Entity();
  144. rootSliceComponent->AddEntity(testEntity);
  145. AZ::SliceComponent::EntityIdToEntityIdMap previousToNewIdMap;
  146. previousToNewIdMap.emplace(testEntity->GetId(), testEntity->GetId());
  147. bool rootEntityLoadSuccessful = false;
  148. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(rootEntityLoadSuccessful,
  149. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::HandleRootEntityReloadedFromStream,
  150. rootEntity, true, &previousToNewIdMap);
  151. EXPECT_TRUE(rootEntityLoadSuccessful);
  152. // Verify that remapping of entityIds is done by comparing the entityIds in previousToNewIdMap
  153. EXPECT_TRUE(previousToNewIdMap.begin()->first != previousToNewIdMap.begin()->second);
  154. }
  155. TEST_F(SliceEntityOwnershipTests, FindLoadedEntityIdMapping_IdsNotRemapped_EntityIdPresent)
  156. {
  157. AZ::Entity* rootEntity = aznew AZ::Entity();
  158. AZ::SliceComponent* rootSliceComponent = rootEntity->CreateComponent<AZ::SliceComponent>();
  159. AZ::Entity* testEntity = aznew AZ::Entity();
  160. rootSliceComponent->AddEntity(testEntity);
  161. bool rootEntityLoadSuccessful = false;
  162. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(rootEntityLoadSuccessful,
  163. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::HandleRootEntityReloadedFromStream, rootEntity, false, nullptr);
  164. EXPECT_TRUE(rootEntityLoadSuccessful);
  165. AZ::EntityId loadedEntityId;
  166. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(loadedEntityId,
  167. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::FindLoadedEntityIdMapping, testEntity->GetId());
  168. // Verify that the entityId in the loadedEntityIdMap is same as the provided entityId, which happens when remapping is not done.
  169. EXPECT_TRUE(loadedEntityId == testEntity->GetId());
  170. }
  171. TEST_F(SliceEntityOwnershipTests, FindLoadedEntityIdMapping_IdsRemapped_EntityIdAbsent)
  172. {
  173. AZ::Entity* rootEntity = aznew AZ::Entity();
  174. AZ::SliceComponent* rootSliceComponent = rootEntity->CreateComponent<AZ::SliceComponent>();
  175. AZ::Entity* testEntity = aznew AZ::Entity();
  176. rootSliceComponent->AddEntity(testEntity);
  177. AZ::SliceComponent::EntityIdToEntityIdMap previousToNewIdMap;
  178. previousToNewIdMap.emplace(testEntity->GetId(), testEntity->GetId());
  179. bool rootEntityLoadSuccessful = false;
  180. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(rootEntityLoadSuccessful,
  181. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::HandleRootEntityReloadedFromStream,
  182. rootEntity, true, &previousToNewIdMap);
  183. EXPECT_TRUE(rootEntityLoadSuccessful);
  184. AZ::EntityId loadedEntityId;
  185. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(loadedEntityId,
  186. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::FindLoadedEntityIdMapping, testEntity->GetId());
  187. // Verify that entityId is not present in the loadedEntityIdMap when remapping is done.
  188. EXPECT_FALSE(loadedEntityId.IsValid());
  189. }
  190. TEST_F(SliceEntityOwnershipTests, OnAssetReady_RootSliceAssetReady_DoNotInstantiate)
  191. {
  192. m_sliceEntityOwnershipService->OnAssetReady(GetRootSliceAsset());
  193. // Verify that validate entities callback is not triggered,
  194. // which will only happen when an attempt to instantiate slice didn't occur.
  195. EXPECT_FALSE(m_validateEntitiesCallbackTriggered);
  196. }
  197. TEST_F(SliceEntityOwnershipTests, OnAssetError_RootSliceAssetError_DoNotClearOtherSliceInstantiations)
  198. {
  199. AddSlice(AzFramework::EntityList{}, true);
  200. m_sliceEntityOwnershipService->OnAssetError(GetRootSliceAsset());
  201. // Try to finish any queued slice instantiations
  202. AZ::TickBus::ExecuteQueuedEvents();
  203. // Verify that slice instantiation was successful.
  204. size_t slicesCountUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetSlices().size();
  205. EXPECT_EQ(slicesCountUnderRootSlice, 1);
  206. }
  207. TEST_F(SliceEntityOwnershipTests, OnAssetError_InstantiatingAssetError_StopSliceInstantiation)
  208. {
  209. AZ::Data::Asset<AZ::SliceAsset> sliceAsset1;
  210. AZ::Data::AssetId sliceAsset1Id = AZ::Data::AssetId(AZ::Uuid::CreateRandom());
  211. sliceAsset1.Create(sliceAsset1Id, false);
  212. AddSlice(AzFramework::EntityList{}, true, sliceAsset1);
  213. AZ::Data::Asset<AZ::SliceAsset> sliceAsset2;
  214. sliceAsset2.Create(AZ::Data::AssetId(AZ::Uuid::CreateRandom()), false);
  215. AddSlice(AzFramework::EntityList{}, true, sliceAsset2);
  216. m_sliceEntityOwnershipService->OnAssetError(sliceAsset2);
  217. // Try to finish any queued slice instantiations
  218. AZ::TickBus::ExecuteQueuedEvents();
  219. AZ::SliceComponent::SliceList& slicesUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetSlices();
  220. // Verify that there is only one slice under root slice
  221. EXPECT_EQ(slicesUnderRootSlice.size(), 1);
  222. // Verify that the slice without the asset error was instantiated
  223. EXPECT_EQ(slicesUnderRootSlice.front().GetSliceAsset().GetId(), sliceAsset1Id);
  224. }
  225. TEST_F(SliceEntityOwnershipTests, InstantiateSlice_InvalidAssetId_ReturnBlankInstantiationTicket)
  226. {
  227. // Set the asset id to null to invalidate it.
  228. AZ_TEST_START_TRACE_SUPPRESSION;
  229. AZ::Data::Asset<AZ::SliceAsset> sliceAssetHolder = AZ::Data::AssetManager::Instance().
  230. CreateAsset<AZ::SliceAsset>(AZ::Data::AssetId{});
  231. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  232. EXPECT_EQ(nullptr, sliceAssetHolder.Get());
  233. AzFramework::SliceInstantiationTicket sliceInstantiationTicket;
  234. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(sliceInstantiationTicket,
  235. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::InstantiateSlice, sliceAssetHolder, nullptr, nullptr);
  236. AZ::TickBus::ExecuteQueuedEvents();
  237. // Verify that there is no request id or context id associated with the sliceInstantiationTicket
  238. EXPECT_EQ(sliceInstantiationTicket.GetContextId(), AZ::Uuid::CreateNull());
  239. EXPECT_EQ(sliceInstantiationTicket.GetRequestId(), 0);
  240. }
  241. TEST_F(SliceEntityOwnershipTests, InstantiateSlice_InstantiateTwoSlices_SlicesInstantiated)
  242. {
  243. // Add 2 slices asynchronously
  244. AddSlice(AzFramework::EntityList{}, true);
  245. AddSlice(AzFramework::EntityList{}, true);
  246. AZ::TickBus::ExecuteQueuedEvents();
  247. size_t slicesCountUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetSlices().size();
  248. EXPECT_EQ(slicesCountUnderRootSlice, 2);
  249. }
  250. TEST_F(SliceEntityOwnershipTests, CloneSliceInstance_InstantiateSlice_SliceCloned)
  251. {
  252. AZ::Entity* testEntity = aznew AZ::Entity("testEntity");
  253. AddSlice(AzFramework::EntityList{ testEntity });
  254. AZ::SliceComponent::EntityIdSet entityIdsInSlice;
  255. GetRootSliceAsset()->GetComponent()->GetEntityIds(entityIdsInSlice);
  256. AZ::SliceComponent* rootSlice = nullptr;
  257. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(rootSlice,
  258. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::GetRootSlice);
  259. AZ::SliceComponent::SliceInstanceAddress sourceSliceInstanceAddress = rootSlice->FindSlice(*entityIdsInSlice.begin());
  260. AZ::SliceComponent::EntityIdToEntityIdMap entityIdToEntityIdMap;
  261. AZ::SliceComponent::SliceInstanceAddress clonedSliceInstanceAddress;
  262. AzFramework::SliceEntityOwnershipServiceRequestBus::BroadcastResult(clonedSliceInstanceAddress,
  263. &AzFramework::SliceEntityOwnershipServiceRequests::CloneSliceInstance, sourceSliceInstanceAddress, entityIdToEntityIdMap);
  264. // Verify that the entity was cloned successfully with the slice
  265. EXPECT_EQ(clonedSliceInstanceAddress.GetInstance()->GetInstantiated()->m_entities.front()->GetName(), "testEntity");
  266. // Verify that the source slice and the cloned slice have the same reference.
  267. EXPECT_EQ(sourceSliceInstanceAddress.GetReference(), clonedSliceInstanceAddress.GetReference());
  268. }
  269. TEST_F(SliceEntityOwnershipTests, InstantiateSlice_EntitiesInvalid_SliceInstantiationFailed)
  270. {
  271. m_areEntitiesValidForContext = false;
  272. AddSlice(AzFramework::EntityList{});
  273. size_t slicesCountUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetSlices().size();
  274. // If entities are invalid, then slice instantiation would fail
  275. EXPECT_EQ(slicesCountUnderRootSlice, 0);
  276. }
  277. TEST_F(SliceEntityOwnershipTests, CancelSliceInstantiation_SetupCorrect_SliceInstantiationCanceled)
  278. {
  279. AzFramework::SliceInstantiationTicket sliceInstantiationTicket = AddSlice(AzFramework::EntityList{}, true);
  280. AzFramework::SliceEntityOwnershipServiceRequestBus::Broadcast(
  281. &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::CancelSliceInstantiation, sliceInstantiationTicket);
  282. // This will try to finish any queued slice instantiations.
  283. AZ::TickBus::ExecuteQueuedEvents();
  284. size_t slicesCountUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetSlices().size();
  285. EXPECT_EQ(slicesCountUnderRootSlice, 0);
  286. }
  287. TEST_F(SliceEntityOwnershipTests, GetOwningSlice_SliceAdded_OwningSliceFetchedCorrectly)
  288. {
  289. AZ::SliceComponent::SliceList& slicesUnderRootSlice = GetRootSliceAsset()->GetComponent()->GetSlices();
  290. AddSlice(AzFramework::EntityList{ aznew AZ::Entity() });
  291. ASSERT_EQ(slicesUnderRootSlice.size(), 1);
  292. AZ::SliceComponent::SliceReference& sliceReference = slicesUnderRootSlice.front();
  293. ASSERT_EQ(sliceReference.GetInstances().size(), 1);
  294. AzFramework::EntityList entitiesOfSlice = sliceReference.GetInstances().begin()->GetInstantiated()->m_entities;
  295. ASSERT_EQ(entitiesOfSlice.size(), 1);
  296. AZ::SliceComponent::SliceInstanceAddress sliceInstanceAddress;
  297. AzFramework::SliceEntityRequestBus::EventResult(sliceInstanceAddress, entitiesOfSlice.front()->GetId(),
  298. &AzFramework::SliceEntityRequestBus::Events::GetOwningSlice);
  299. // Verify that the source slice and the cloned slice have the same slice asset.
  300. EXPECT_EQ(sliceInstanceAddress.GetReference()->GetSliceAsset(), sliceReference.GetSliceAsset());
  301. }
  302. TEST_F(SliceEntityOwnershipTests, GetOwningSlice_LooseEntityAdded_EntityHasNoOwningSlice)
  303. {
  304. AZ::Entity* testEntity = aznew AZ::Entity();
  305. m_sliceEntityOwnershipService->AddEntity(testEntity);
  306. AZ::SliceComponent::SliceInstanceAddress sliceInstanceAddress;
  307. AzFramework::SliceEntityRequestBus::EventResult(sliceInstanceAddress, testEntity->GetId(),
  308. &AzFramework::SliceEntityRequestBus::Events::GetOwningSlice);
  309. // Verify that the loose entity doesn't belong to a slice instance
  310. EXPECT_FALSE(sliceInstanceAddress.IsValid());
  311. }
  312. #if GTEST_HAS_DEATH_TEST
  313. #if AZ_TRAIT_DISABLE_FAILED_DEATH_TESTS
  314. TEST_F(SliceEntityOwnershipDeathTests, DISABLED_AddEntity_RootSliceAssetAbsent_EntityNotCreated)
  315. #else
  316. TEST_F(SliceEntityOwnershipDeathTests, AddEntity_RootSliceAssetAbsent_EntityNotCreated)
  317. #endif // AZ_TRAIT_DISABLE_FAILED_DEATH_TESTS
  318. {
  319. m_sliceEntityOwnershipService->Destroy();
  320. AZ::Entity testEntity = AZ::Entity("testEntity");
  321. EXPECT_DEATH(
  322. {
  323. m_sliceEntityOwnershipService->AddEntity(&testEntity);
  324. }, ".*");
  325. }
  326. #endif // GTEST_HAS_DEATH_TEST
  327. }