SceneBuilderConfigTests.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  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 <gmock/gmock.h>
  9. #include <AzTest/AzTest.h>
  10. #include <AzCore/Debug/TraceMessageBus.h>
  11. #include <AzCore/IO/FileIO.h>
  12. #include <AzCore/Serialization/Json/JsonSystemComponent.h>
  13. #include <AzCore/Serialization/Json/RegistrationContext.h>
  14. #include <AzCore/Settings/SettingsRegistryImpl.h>
  15. #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
  16. #include <AzCore/UnitTest/Mocks/MockFileIOBase.h>
  17. #include <AzCore/UnitTest/TestTypes.h>
  18. #include <Config/Components/SceneProcessingConfigSystemComponent.h>
  19. #include <Config/SettingsObjects/FileSoftNameSetting.h>
  20. #include <Config/SettingsObjects/NodeSoftNameSetting.h>
  21. #include <SceneAPI/SceneCore/Containers/Scene.h>
  22. class SceneProcessingConfigTest
  23. : public UnitTest::LeakDetectionFixture
  24. , public AZ::Debug::TraceMessageBus::Handler
  25. {
  26. public:
  27. void SetUp() override
  28. {
  29. m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
  30. AZ::SettingsRegistry::Register(m_settingsRegistry.get());
  31. m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
  32. m_registrationContext = AZStd::make_unique<AZ::JsonRegistrationContext>();
  33. m_settingsRegistry->SetContext(m_serializeContext.get());
  34. m_settingsRegistry->SetContext(m_registrationContext.get());
  35. AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get();
  36. auto projectPathKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path";
  37. AZ::IO::FixedMaxPath enginePath;
  38. registry->Get(enginePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
  39. registry->Set(projectPathKey, (enginePath / "AutomatedTesting").Native());
  40. AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry);
  41. m_fileIOMock = AZStd::make_unique<testing::NiceMock<AZ::IO::MockFileIOBase>>();
  42. m_prevFileIO = AZ::IO::FileIOBase::GetInstance();
  43. AZ::IO::FileIOBase::SetInstance(nullptr);
  44. AZ::IO::FileIOBase::SetInstance(m_fileIOMock.get());
  45. ASSERT_EQ(m_fileIOMock.get(), AZ::IO::FileIOBase::GetInstance());
  46. ON_CALL(*m_fileIOMock.get(), ResolvePath(::testing::_, ::testing::_))
  47. .WillByDefault([](AZ::IO::FixedMaxPath& resolvedPath, const AZ::IO::PathView& path) -> bool
  48. {
  49. resolvedPath = AZ::IO::FixedMaxPath("/fake/path") / path.Filename();
  50. return true;
  51. }
  52. );
  53. ON_CALL(*m_fileIOMock.get(), Exists(::testing::_))
  54. .WillByDefault([](const char*) -> bool
  55. {
  56. return true;
  57. }
  58. );
  59. AZ::Debug::TraceMessageBus::Handler::BusConnect();
  60. }
  61. void TearDown() override
  62. {
  63. AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
  64. EXPECT_EQ(m_fileIOMock.get(), AZ::IO::FileIOBase::GetInstance());
  65. AZ::IO::FileIOBase::SetInstance(nullptr);
  66. AZ::IO::FileIOBase::SetInstance(m_prevFileIO);
  67. m_fileIOMock.reset();
  68. AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
  69. m_registrationContext.reset();
  70. m_serializeContext.reset();
  71. m_settingsRegistry.reset();
  72. }
  73. void ReflectTypes()
  74. {
  75. AZ::JsonSystemComponent::Reflect(m_registrationContext.get());
  76. // PatternMatcher is defined in SceneCore. Avoid loading the dynamic-link library in the test by
  77. // just binding the class for serialization.
  78. m_serializeContext->Class<AZ::SceneAPI::SceneCore::PatternMatcher>();
  79. AZ::SceneProcessingConfig::SoftNameSetting::Reflect(m_serializeContext.get());
  80. AZ::SceneProcessingConfig::NodeSoftNameSetting::Reflect(m_serializeContext.get());
  81. AZ::SceneProcessingConfig::FileSoftNameSetting::Reflect(m_serializeContext.get());
  82. }
  83. void RemoveReflectedTypes()
  84. {
  85. m_serializeContext->EnableRemoveReflection();
  86. AZ::SceneProcessingConfig::FileSoftNameSetting::Reflect(m_serializeContext.get());
  87. AZ::SceneProcessingConfig::NodeSoftNameSetting::Reflect(m_serializeContext.get());
  88. AZ::SceneProcessingConfig::SoftNameSetting::Reflect(m_serializeContext.get());
  89. m_serializeContext->Class<AZ::SceneAPI::SceneCore::PatternMatcher>();
  90. m_serializeContext->DisableRemoveReflection();
  91. m_registrationContext->EnableRemoveReflection();
  92. AZ::JsonSystemComponent::Reflect(m_registrationContext.get());
  93. m_registrationContext->DisableRemoveReflection();
  94. }
  95. // AZ::Debug::TraceMessageBus::Handler overrides
  96. bool OnWarning(const char* window, const char* message) override
  97. {
  98. AZ_UNUSED(window);
  99. AZ_UNUSED(message);
  100. ++m_warningsCount;
  101. return true;
  102. }
  103. AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
  104. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  105. AZStd::unique_ptr<AZ::JsonRegistrationContext> m_registrationContext;
  106. AZStd::unique_ptr<::testing::NiceMock<AZ::IO::MockFileIOBase>> m_fileIOMock;
  107. AZ::IO::FileIOBase* m_prevFileIO = nullptr;
  108. int m_warningsCount = 0;
  109. };
  110. TEST_F(SceneProcessingConfigTest, SceneProcessingConfigSystemComponent_EmptySetReg_ReturnsEmptyGetScriptConfigList)
  111. {
  112. AZ::SceneProcessingConfig::SceneProcessingConfigSystemComponent sceneProcessingConfigSystemComponent;
  113. sceneProcessingConfigSystemComponent.Activate();
  114. AZStd::vector<AZ::SceneAPI::Events::ScriptConfig> scriptConfigList;
  115. sceneProcessingConfigSystemComponent.GetScriptConfigList(scriptConfigList);
  116. EXPECT_TRUE(scriptConfigList.empty());
  117. sceneProcessingConfigSystemComponent.Deactivate();
  118. }
  119. TEST_F(SceneProcessingConfigTest, SceneProcessingConfigSystemComponent_ProperlySetup_ReturnsCompleteList)
  120. {
  121. const char* settings = R"JSON(
  122. {
  123. "O3DE": {
  124. "AssetProcessor": {
  125. "SceneBuilder": {
  126. "defaultScripts": {
  127. "fooPattern": "@projectroot@/test_foo.py",
  128. "barPattern": "@projectroot@/test_bar.py",
  129. "badValue": 1
  130. }
  131. }
  132. }
  133. }
  134. }
  135. )JSON";
  136. m_settingsRegistry->MergeSettings(settings, AZ::SettingsRegistryInterface::Format::JsonMergePatch);
  137. AZ::SceneProcessingConfig::SceneProcessingConfigSystemComponent sceneProcessingConfigSystemComponent;
  138. sceneProcessingConfigSystemComponent.Activate();
  139. AZStd::vector<AZ::SceneAPI::Events::ScriptConfig> scriptConfigList;
  140. sceneProcessingConfigSystemComponent.GetScriptConfigList(scriptConfigList);
  141. EXPECT_EQ(scriptConfigList.size(), 2);
  142. sceneProcessingConfigSystemComponent.Deactivate();
  143. }
  144. TEST_F(SceneProcessingConfigTest, SceneProcessingConfigSystemComponent_ScriptConfigEventBus_IsEnabled)
  145. {
  146. const char* settings = R"JSON(
  147. {
  148. "O3DE": {
  149. "AssetProcessor": {
  150. "SceneBuilder": {
  151. "defaultScripts": {
  152. "fooPattern": "@projectroot@/test_foo.py"
  153. }
  154. }
  155. }
  156. }
  157. }
  158. )JSON";
  159. m_settingsRegistry->MergeSettings(settings, AZ::SettingsRegistryInterface::Format::JsonMergePatch);
  160. AZ::SceneProcessingConfig::SceneProcessingConfigSystemComponent sceneProcessingConfigSystemComponent;
  161. sceneProcessingConfigSystemComponent.Activate();
  162. AZStd::vector<AZ::SceneAPI::Events::ScriptConfig> scriptConfigList;
  163. AZ::SceneAPI::Events::ScriptConfigEventBus::Broadcast(
  164. &AZ::SceneAPI::Events::ScriptConfigEventBus::Events::GetScriptConfigList,
  165. scriptConfigList);
  166. EXPECT_EQ(scriptConfigList.size(), 1);
  167. sceneProcessingConfigSystemComponent.Deactivate();
  168. }
  169. TEST_F(SceneProcessingConfigTest, SceneProcessingConfigSystemComponent_ScriptConfigEventBus_MatchesScriptConfig)
  170. {
  171. const char* settings = R"JSON(
  172. {
  173. "O3DE": {
  174. "AssetProcessor": {
  175. "SceneBuilder": {
  176. "defaultScripts": {
  177. "foo*": "@projectroot@/test_foo.py"
  178. }
  179. }
  180. }
  181. }
  182. }
  183. )JSON";
  184. m_settingsRegistry->MergeSettings(settings, AZ::SettingsRegistryInterface::Format::JsonMergePatch);
  185. AZ::SceneProcessingConfig::SceneProcessingConfigSystemComponent sceneProcessingConfigSystemComponent;
  186. sceneProcessingConfigSystemComponent.Activate();
  187. AZStd::optional<AZ::SceneAPI::Events::ScriptConfig> result;
  188. AZ::SceneAPI::Events::ScriptConfigEventBus::BroadcastResult(
  189. result,
  190. &AZ::SceneAPI::Events::ScriptConfigEventBus::Events::MatchesScriptConfig,
  191. "fake/folder/foo_bar.asset");
  192. EXPECT_TRUE(result.has_value());
  193. sceneProcessingConfigSystemComponent.Deactivate();
  194. }
  195. TEST_F(SceneProcessingConfigTest, SceneProcessingConfigSystemComponent_SoftNameSettings_MatchesSettingRegistry)
  196. {
  197. const char* settings = R"JSON(
  198. {
  199. "O3DE": {
  200. "AssetProcessor": {
  201. "SceneBuilder": {
  202. "NodeSoftNameSettings": [
  203. {
  204. "pattern": {
  205. "pattern": "^.*_[Ll][Oo][Dd]_?1(_optimized)?$",
  206. "matcher": 2
  207. },
  208. "virtualType": "LODMesh1",
  209. "includeChildren": true
  210. }
  211. ],
  212. "FileSoftNameSettings": [
  213. {
  214. "pattern": {
  215. "pattern": "_anim",
  216. "matcher": 1
  217. },
  218. "virtualType": "Ignore",
  219. "inclusiveList": false,
  220. "graphTypes": {
  221. "types": [
  222. {
  223. "name": "IAnimationData"
  224. }
  225. ]
  226. }
  227. }
  228. ]
  229. }
  230. }
  231. }
  232. }
  233. )JSON";
  234. m_settingsRegistry->MergeSettings(settings, AZ::SettingsRegistryInterface::Format::JsonMergePatch);
  235. ReflectTypes();
  236. AZ::SceneProcessingConfig::SceneProcessingConfigSystemComponent sceneProcessingConfigSystemComponent;
  237. sceneProcessingConfigSystemComponent.Activate();
  238. const AZStd::vector<AZStd::unique_ptr<AZ::SceneProcessingConfig::SoftNameSetting>>* result = nullptr;
  239. AZ::SceneProcessingConfig::SceneProcessingConfigRequestBus::BroadcastResult(
  240. result,
  241. &AZ::SceneProcessingConfig::SceneProcessingConfigRequests::GetSoftNames);
  242. EXPECT_EQ(result->size(), 2);
  243. EXPECT_EQ(result->at(0)->GetVirtualType(), "LODMesh1");
  244. EXPECT_EQ(result->at(1)->GetVirtualType(), "Ignore");
  245. sceneProcessingConfigSystemComponent.Deactivate();
  246. RemoveReflectedTypes();
  247. }
  248. TEST_F(SceneProcessingConfigTest, SceneProcessingConfigSystemComponent_SoftNameSettings_AddSoftNameSettingsWithDifferentTypeIdAndSameVirtualType)
  249. {
  250. const char* settings = R"JSON(
  251. {
  252. "O3DE": {
  253. "AssetProcessor": {
  254. "SceneBuilder": {
  255. "NodeSoftNameSettings": [
  256. {
  257. "pattern": {
  258. "pattern": "^.*_[Ll][Oo][Dd]_?1(_optimized)?$",
  259. "matcher": 2
  260. },
  261. "virtualType": "Ignore",
  262. "includeChildren": true
  263. }
  264. ],
  265. "FileSoftNameSettings": [
  266. {
  267. "pattern": {
  268. "pattern": "_anim",
  269. "matcher": 1
  270. },
  271. "virtualType": "Ignore",
  272. "inclusiveList": false,
  273. "graphTypes": {
  274. "types": [
  275. {
  276. "name": "IAnimationData"
  277. }
  278. ]
  279. }
  280. }
  281. ]
  282. }
  283. }
  284. }
  285. }
  286. )JSON";
  287. m_settingsRegistry->MergeSettings(settings, AZ::SettingsRegistryInterface::Format::JsonMergePatch);
  288. ReflectTypes();
  289. AZ::SceneProcessingConfig::SceneProcessingConfigSystemComponent sceneProcessingConfigSystemComponent;
  290. sceneProcessingConfigSystemComponent.Activate();
  291. const AZStd::vector<AZStd::unique_ptr<AZ::SceneProcessingConfig::SoftNameSetting>>* result = nullptr;
  292. AZ::SceneProcessingConfig::SceneProcessingConfigRequestBus::BroadcastResult(
  293. result,
  294. &AZ::SceneProcessingConfig::SceneProcessingConfigRequests::GetSoftNames);
  295. EXPECT_EQ(result->size(), 2);
  296. EXPECT_EQ(result->at(0)->GetVirtualType(), "Ignore");
  297. EXPECT_EQ(result->at(1)->GetVirtualType(), "Ignore");
  298. sceneProcessingConfigSystemComponent.Deactivate();
  299. RemoveReflectedTypes();
  300. }
  301. TEST_F(SceneProcessingConfigTest, SceneProcessingConfigSystemComponent_SoftNameSettings_IgnoreSoftNameSettingsWithSameTypeIdAndSameVirtualType)
  302. {
  303. const char* settings = R"JSON(
  304. {
  305. "O3DE": {
  306. "AssetProcessor": {
  307. "SceneBuilder": {
  308. "NodeSoftNameSettings": [
  309. {
  310. "pattern": {
  311. "pattern": "^.*_[Ll][Oo][Dd]_?1(_optimized)?$",
  312. "matcher": 2
  313. },
  314. "virtualType": "LODMesh1",
  315. "includeChildren": true
  316. },
  317. {
  318. "pattern": {
  319. "pattern": "^.*_[Ll][Oo][Dd]_?1(_optimized)?$",
  320. "matcher": 0
  321. },
  322. "virtualType": "LODMesh1",
  323. "includeChildren": true
  324. },
  325. {
  326. "pattern": {
  327. "pattern": "^.*_[Ll][Oo][Dd]_?2(_optimized)?$",
  328. "matcher": 2
  329. },
  330. "virtualType": "LODMesh2",
  331. "includeChildren": true
  332. }
  333. ]
  334. }
  335. }
  336. }
  337. }
  338. )JSON";
  339. m_settingsRegistry->MergeSettings(settings, AZ::SettingsRegistryInterface::Format::JsonMergePatch);
  340. ReflectTypes();
  341. AZ_TEST_START_TRACE_SUPPRESSION;
  342. // Expect to get one error when adding duplicate soft name settings
  343. AZ::SceneProcessingConfig::SceneProcessingConfigSystemComponent sceneProcessingConfigSystemComponent;
  344. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  345. sceneProcessingConfigSystemComponent.Activate();
  346. const AZStd::vector<AZStd::unique_ptr<AZ::SceneProcessingConfig::SoftNameSetting>>* result = nullptr;
  347. AZ::SceneProcessingConfig::SceneProcessingConfigRequestBus::BroadcastResult(
  348. result,
  349. &AZ::SceneProcessingConfig::SceneProcessingConfigRequests::GetSoftNames);
  350. EXPECT_EQ(result->size(), 2);
  351. EXPECT_EQ(result->at(0)->GetVirtualType(), "LODMesh1");
  352. EXPECT_EQ(result->at(1)->GetVirtualType(), "LODMesh2");
  353. sceneProcessingConfigSystemComponent.Deactivate();
  354. RemoveReflectedTypes();
  355. }
  356. TEST_F(SceneProcessingConfigTest, SceneProcessingConfigSystemComponent_SoftNameSettings_WarningWithoutSettingsRegistry)
  357. {
  358. // Expect to get one warning when soft name settings cannot be read from the settings registry
  359. AZ::SceneProcessingConfig::SceneProcessingConfigSystemComponent sceneProcessingConfigSystemComponent;
  360. EXPECT_EQ(m_warningsCount, 1);
  361. sceneProcessingConfigSystemComponent.Activate();
  362. const AZStd::vector<AZStd::unique_ptr<AZ::SceneProcessingConfig::SoftNameSetting>>* result = nullptr;
  363. AZ::SceneProcessingConfig::SceneProcessingConfigRequestBus::BroadcastResult(
  364. result,
  365. &AZ::SceneProcessingConfig::SceneProcessingConfigRequests::GetSoftNames);
  366. EXPECT_EQ(result->size(), 0);
  367. sceneProcessingConfigSystemComponent.Deactivate();
  368. }
  369. TEST_F(SceneProcessingConfigTest, SceneProcessingConfigSystemComponent_SoftNameSettings_NoWarningWithEmptySettingsRegistry)
  370. {
  371. const char* settings = R"JSON(
  372. {
  373. "O3DE": {
  374. "AssetProcessor": {
  375. "SceneBuilder": {
  376. "NodeSoftNameSettings": [
  377. ],
  378. "FileSoftNameSettings": [
  379. ]
  380. }
  381. }
  382. }
  383. }
  384. )JSON";
  385. m_settingsRegistry->MergeSettings(settings, AZ::SettingsRegistryInterface::Format::JsonMergePatch);
  386. ReflectTypes();
  387. AZ::SceneProcessingConfig::SceneProcessingConfigSystemComponent sceneProcessingConfigSystemComponent;
  388. EXPECT_EQ(m_warningsCount, 0);
  389. sceneProcessingConfigSystemComponent.Activate();
  390. const AZStd::vector<AZStd::unique_ptr<AZ::SceneProcessingConfig::SoftNameSetting>>* result = nullptr;
  391. AZ::SceneProcessingConfig::SceneProcessingConfigRequestBus::BroadcastResult(
  392. result,
  393. &AZ::SceneProcessingConfig::SceneProcessingConfigRequests::GetSoftNames);
  394. EXPECT_EQ(result->size(), 0);
  395. sceneProcessingConfigSystemComponent.Deactivate();
  396. RemoveReflectedTypes();
  397. }