ProceduralPrefabSystemComponentTests.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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 <AzCore/IO/FileIO.h>
  9. #include <AzCore/IO/Path/PathReflect.h>
  10. #include <AzCore/Serialization/Json/JsonSystemComponent.h>
  11. #include <AzCore/Serialization/Json/RegistrationContext.h>
  12. #include <AzCore/Settings/SettingsRegistryImpl.h>
  13. #include <AzFramework/IO/LocalFileIO.h>
  14. #include <Prefab/PrefabTestFixture.h>
  15. #include <Prefab/ProceduralPrefabSystemComponent.h>
  16. #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
  17. #include <AZTestShared/Utils/Utils.h>
  18. namespace UnitTest
  19. {
  20. struct ProceduralPrefabSystemComponentTests
  21. : LeakDetectionFixture
  22. , AZ::ComponentApplicationBus::Handler
  23. {
  24. void SetUp() override
  25. {
  26. TestRunner::Instance().m_suppressOutput = false;
  27. TestRunner::Instance().m_suppressPrintf = false;
  28. TestRunner::Instance().m_suppressWarnings = false;
  29. TestRunner::Instance().m_suppressErrors = false;
  30. TestRunner::Instance().m_suppressAsserts = false;
  31. LeakDetectionFixture::SetUp();
  32. AZ::ComponentApplicationBus::Handler::BusConnect();
  33. m_localFileIo = AZStd::make_unique<AZ::IO::LocalFileIO>();
  34. m_prevIoBase = AZ::IO::FileIOBase::GetInstance();
  35. AZ::IO::FileIOBase::SetInstance(nullptr); // Need to clear the previous instance first
  36. AZ::IO::FileIOBase::SetInstance(m_localFileIo.get());
  37. AZ::JsonSystemComponent::Reflect(&m_jsonContext);
  38. m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
  39. AZ::SettingsRegistry::Register(m_settingsRegistry.get());
  40. m_settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath, m_temporaryDirectory.GetDirectory());
  41. m_prefabSystem = PrefabSystemComponent::CreateDescriptor();
  42. m_procSystem = ProceduralPrefabSystemComponent::CreateDescriptor();
  43. m_prefabSystem->Reflect(&m_context);
  44. m_prefabSystem->Reflect(&m_jsonContext);
  45. m_procSystem->Reflect(&m_context);
  46. m_procSystem->Reflect(&m_jsonContext);
  47. AZ::Entity::Reflect(&m_context);
  48. AZ::Entity::Reflect(&m_jsonContext);
  49. AZ::IO::PathReflect(&m_context);
  50. m_systemEntity = AZStd::make_unique<AZ::Entity>();
  51. m_systemEntity->CreateComponent<PrefabSystemComponent>();
  52. m_systemEntity->CreateComponent<ProceduralPrefabSystemComponent>();
  53. m_systemEntity->Init();
  54. m_systemEntity->Activate();
  55. AZ::Data::AssetManager::Create({});
  56. }
  57. void TearDown() override
  58. {
  59. AZ::Data::AssetManager::Destroy();
  60. m_systemEntity->Deactivate();
  61. m_systemEntity = nullptr;
  62. m_jsonContext.EnableRemoveReflection();
  63. AZ::JsonSystemComponent::Reflect(&m_jsonContext);
  64. m_prefabSystem->Reflect(&m_jsonContext);
  65. m_procSystem->Reflect(&m_jsonContext);
  66. AZ::Entity::Reflect(&m_jsonContext);
  67. m_jsonContext.DisableRemoveReflection();
  68. AZ::IO::FileIOBase::SetInstance(nullptr); // Clear the previous instance first
  69. AZ::IO::FileIOBase::SetInstance(m_prevIoBase);
  70. m_prevIoBase = nullptr;
  71. AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
  72. AZ::ComponentApplicationBus::Handler::BusDisconnect();
  73. LeakDetectionFixture::TearDown();
  74. TestRunner::Instance().ResetSuppressionSettingsToDefault();
  75. delete m_procSystem;
  76. m_procSystem = nullptr;
  77. delete m_prefabSystem;
  78. m_prefabSystem = nullptr;
  79. }
  80. // ComponentApplicationBus
  81. AZ::ComponentApplication* GetApplication() override
  82. {
  83. return nullptr;
  84. }
  85. void RegisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
  86. void UnregisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
  87. void RegisterEntityAddedEventHandler(AZ::EntityAddedEvent::Handler&) override { }
  88. void RegisterEntityRemovedEventHandler(AZ::EntityRemovedEvent::Handler&) override { }
  89. void RegisterEntityActivatedEventHandler(AZ::EntityActivatedEvent::Handler&) override { }
  90. void RegisterEntityDeactivatedEventHandler(AZ::EntityDeactivatedEvent::Handler&) override { }
  91. void SignalEntityActivated(AZ::Entity*) override { }
  92. void SignalEntityDeactivated(AZ::Entity*) override { }
  93. bool AddEntity(AZ::Entity*) override
  94. {
  95. return true;
  96. }
  97. bool RemoveEntity(AZ::Entity*) override
  98. {
  99. return true;
  100. }
  101. bool DeleteEntity(const AZ::EntityId&) override
  102. {
  103. return true;
  104. }
  105. AZ::Entity* FindEntity(const AZ::EntityId&) override
  106. {
  107. return nullptr;
  108. }
  109. AZ::SerializeContext* GetSerializeContext() override
  110. {
  111. return &m_context;
  112. }
  113. AZ::BehaviorContext* GetBehaviorContext() override
  114. {
  115. return nullptr;
  116. }
  117. AZ::JsonRegistrationContext* GetJsonRegistrationContext() override
  118. {
  119. return &m_jsonContext;
  120. }
  121. const char* GetEngineRoot() const override
  122. {
  123. return nullptr;
  124. }
  125. const char* GetExecutableFolder() const override
  126. {
  127. return nullptr;
  128. }
  129. void EnumerateEntities(const EntityCallback& /*callback*/) override { }
  130. void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override { }
  131. ////
  132. AZ::ComponentDescriptor* m_prefabSystem{};
  133. AZ::ComponentDescriptor* m_procSystem{};
  134. AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
  135. AZ::SerializeContext m_context;
  136. AZ::JsonRegistrationContext m_jsonContext;
  137. AZStd::unique_ptr<AZ::IO::LocalFileIO> m_localFileIo;
  138. AZ::Test::ScopedAutoTempDirectory m_temporaryDirectory;
  139. AZStd::unique_ptr<AZ::Entity> m_systemEntity;
  140. AZ::IO::FileIOBase* m_prevIoBase{};
  141. };
  142. struct MockCatalog : AZ::Data::AssetCatalogRequestBus::Handler
  143. {
  144. static const inline AZ::Data::AssetId TestId{ AZ::Uuid::CreateRandom(), 1234 };
  145. MockCatalog(AZStd::string testFile)
  146. : m_testFile(AZStd::move(testFile))
  147. {
  148. BusConnect();
  149. }
  150. ~MockCatalog() override
  151. {
  152. BusDisconnect();
  153. }
  154. AZStd::string GetAssetPathById(const AZ::Data::AssetId& assetId) override
  155. {
  156. if (assetId == TestId)
  157. {
  158. return m_testFile;
  159. }
  160. return "InvalidAssetId";
  161. }
  162. AZ::Data::AssetId GetAssetIdByPath(const char* path, const AZ::Data::AssetType&, bool) override
  163. {
  164. AZ::IO::PathView pathView{ AZStd::string_view(path) };
  165. if (AZ::IO::PathView(m_testFile) == pathView)
  166. {
  167. return TestId;
  168. }
  169. AZ_Error("MockCatalog", false, "Requested path %s does not match expected asset path of %s", path, m_testFile.c_str());
  170. ADD_FAILURE();
  171. return {};
  172. }
  173. AZStd::string m_testFile;
  174. };
  175. struct PrefabPublicNotificationsListener : PrefabPublicNotificationBus::Handler
  176. {
  177. PrefabPublicNotificationsListener()
  178. {
  179. BusConnect();
  180. }
  181. ~PrefabPublicNotificationsListener() override
  182. {
  183. BusDisconnect();
  184. }
  185. void OnPrefabInstancePropagationBegin() override
  186. {
  187. m_updated = true;
  188. }
  189. bool m_updated = false;
  190. };
  191. TEST_F(ProceduralPrefabSystemComponentTests, RegisteredPrefabUpdates)
  192. {
  193. const AZStd::string prefabFile = (AZ::IO::Path(m_temporaryDirectory.GetDirectory()) / "test.prefab").Native();
  194. MockCatalog catalog(prefabFile.c_str());
  195. auto proceduralPrefabSystemComponentInterface = AZ::Interface<ProceduralPrefabSystemComponentInterface>::Get();
  196. auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
  197. auto prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
  198. ASSERT_NE(proceduralPrefabSystemComponentInterface, nullptr);
  199. ASSERT_NE(prefabSystemComponentInterface, nullptr);
  200. ASSERT_NE(prefabLoaderInterface, nullptr);
  201. auto entity = aznew AZ::Entity();
  202. AZStd::unique_ptr<Instance> instance = prefabSystemComponentInterface->CreatePrefab({ entity }, {}, prefabFile.c_str());
  203. ASSERT_NE(instance, nullptr);
  204. prefabLoaderInterface->SaveTemplateToFile(instance->GetTemplateId(), prefabFile.c_str());
  205. proceduralPrefabSystemComponentInterface->RegisterProceduralPrefab(prefabFile, instance->GetTemplateId());
  206. AzFramework::AssetCatalogEventBus::Broadcast(&AzFramework::AssetCatalogEventBus::Events::OnCatalogAssetChanged, MockCatalog::TestId);
  207. PrefabPublicNotificationsListener listener;
  208. AZ::SystemTickBus::Broadcast(&AZ::SystemTickBus::Events::OnSystemTick);
  209. EXPECT_TRUE(listener.m_updated);
  210. }
  211. TEST_F(ProceduralPrefabSystemComponentTests, UnregisteredPrefabDoesNotUpdate)
  212. {
  213. PrefabPublicNotificationsListener listener;
  214. const AZStd::string prefabFile = (AZ::IO::Path(m_temporaryDirectory.GetDirectory()) / "test.prefab").Native();
  215. MockCatalog catalog(prefabFile.c_str());
  216. auto proceduralPrefabSystemComponentInterface = AZ::Interface<ProceduralPrefabSystemComponentInterface>::Get();
  217. auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
  218. auto prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
  219. ASSERT_NE(proceduralPrefabSystemComponentInterface, nullptr);
  220. ASSERT_NE(prefabSystemComponentInterface, nullptr);
  221. ASSERT_NE(prefabLoaderInterface, nullptr);
  222. auto entity = aznew AZ::Entity();
  223. AZStd::unique_ptr<Instance> instance = prefabSystemComponentInterface->CreatePrefab({ entity }, {}, prefabFile.c_str());
  224. ASSERT_NE(instance, nullptr);
  225. prefabLoaderInterface->SaveTemplateToFile(instance->GetTemplateId(), prefabFile.c_str());
  226. AzFramework::AssetCatalogEventBus::Broadcast(
  227. &AzFramework::AssetCatalogEventBus::Events::OnCatalogAssetChanged, MockCatalog::TestId);
  228. AZ::SystemTickBus::Broadcast(&AZ::SystemTickBus::Events::OnSystemTick);
  229. EXPECT_FALSE(listener.m_updated);
  230. }
  231. }