platformconfigurationtests.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  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/Settings/SettingsRegistryMergeUtils.h>
  9. #include "native/tests/platformconfiguration/platformconfigurationtests.h"
  10. #include <AzTest/AzTest.h>
  11. #include <gmock/gmock.h>
  12. const char TestAppRoot[] = "@exefolder@/testdata";
  13. const char EmptyDummyProjectName[] = "EmptyDummyProject";
  14. // make the internal calls public for the purposes of the unit test!
  15. class UnitTestPlatformConfiguration : public AssetProcessor::PlatformConfiguration
  16. {
  17. friend class GTEST_TEST_CLASS_NAME_(PlatformConfigurationUnitTests, Test_GemHandling);
  18. friend class GTEST_TEST_CLASS_NAME_(PlatformConfigurationUnitTests, Test_MetaFileTypes);
  19. friend class GTEST_TEST_CLASS_NAME_(PlatformConfigurationUnitTests, Test_MetaFileTypes_AssetImporterExtensions);
  20. protected:
  21. };
  22. PlatformConfigurationUnitTests::PlatformConfigurationUnitTests()
  23. : m_argc(0)
  24. , m_argv(0)
  25. {
  26. }
  27. void PlatformConfigurationUnitTests::SetUp()
  28. {
  29. using namespace AssetProcessor;
  30. m_qApp = new QCoreApplication(m_argc, m_argv);
  31. AssetProcessorTest::SetUp();
  32. AssetUtilities::ResetAssetRoot();
  33. }
  34. void PlatformConfigurationUnitTests::TearDown()
  35. {
  36. AssetUtilities::ResetAssetRoot();
  37. delete m_qApp;
  38. AssetProcessor::AssetProcessorTest::TearDown();
  39. }
  40. TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_BadPlatform)
  41. {
  42. using namespace AzToolsFramework::AssetSystem;
  43. using namespace AssetProcessor;
  44. const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
  45. const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
  46. auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_badplatform");
  47. ASSERT_TRUE(configRoot);
  48. UnitTestPlatformConfiguration config;
  49. m_errorAbsorber->Clear();
  50. ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
  51. ASSERT_GT(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  52. }
  53. TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_NoPlatform)
  54. {
  55. using namespace AzToolsFramework::AssetSystem;
  56. using namespace AssetProcessor;
  57. const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
  58. const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
  59. auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_noplatform");
  60. ASSERT_TRUE(configRoot);
  61. UnitTestPlatformConfiguration config;
  62. m_errorAbsorber->Clear();
  63. ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
  64. ASSERT_GT(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  65. }
  66. TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_NoScanFolders)
  67. {
  68. using namespace AzToolsFramework::AssetSystem;
  69. using namespace AssetProcessor;
  70. const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
  71. const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
  72. auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_noscans");
  73. ASSERT_TRUE(configRoot);
  74. UnitTestPlatformConfiguration config;
  75. m_errorAbsorber->Clear();
  76. ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
  77. ASSERT_GT(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  78. }
  79. TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_BrokenRecognizers)
  80. {
  81. using namespace AzToolsFramework::AssetSystem;
  82. using namespace AssetProcessor;
  83. const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
  84. const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
  85. auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_recognizers");
  86. ASSERT_TRUE(configRoot);
  87. UnitTestPlatformConfiguration config;
  88. m_errorAbsorber->Clear();
  89. ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
  90. ASSERT_GT(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  91. }
  92. TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Regular_Platforms)
  93. {
  94. using namespace AzToolsFramework::AssetSystem;
  95. using namespace AssetProcessor;
  96. const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
  97. const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
  98. auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
  99. ASSERT_TRUE(configRoot);
  100. UnitTestPlatformConfiguration config;
  101. m_errorAbsorber->Clear();
  102. ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
  103. ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  104. // verify the data.
  105. ASSERT_NE(config.GetPlatformByIdentifier(AzToolsFramework::AssetSystem::GetHostAssetPlatform()), nullptr);
  106. ASSERT_NE(config.GetPlatformByIdentifier("android"), nullptr);
  107. ASSERT_NE(config.GetPlatformByIdentifier("server"), nullptr);
  108. ASSERT_TRUE(config.GetPlatformByIdentifier("android")->HasTag("mobile"));
  109. ASSERT_TRUE(config.GetPlatformByIdentifier("android")->HasTag("renderer"));
  110. ASSERT_TRUE(config.GetPlatformByIdentifier("android")->HasTag("android"));
  111. ASSERT_TRUE(config.GetPlatformByIdentifier("server")->HasTag("server"));
  112. ASSERT_FALSE(config.GetPlatformByIdentifier("android")->HasTag("server"));
  113. ASSERT_FALSE(config.GetPlatformByIdentifier("server")->HasTag("renderer"));
  114. }
  115. TEST_F(PlatformConfigurationUnitTests, TestReadScanFolderRoot_FromSettingsRegistry_Succeeds)
  116. {
  117. auto settingsRegistry = AZ::SettingsRegistry::Get();
  118. ASSERT_NE(nullptr, settingsRegistry);
  119. QTemporaryDir tempEngineRoot;
  120. QDir tempPath(tempEngineRoot.path());
  121. QString testScanFolderSetregPath = tempPath.absoluteFilePath("test.setreg");
  122. UnitTestUtils::CreateDummyFile(testScanFolderSetregPath, QString(R"({ "Amazon":
  123. {
  124. "AssetProcessor":
  125. {
  126. "Settings":
  127. {
  128. "ScanFolder SettingsRegistryTest":
  129. {
  130. "watch": "_TestPath",
  131. "recursive": false,
  132. "order": 20000
  133. }
  134. }
  135. }
  136. }
  137. }\n)"));
  138. EXPECT_TRUE(AssetProcessor::PlatformConfiguration::MergeConfigFileToSettingsRegistry(*settingsRegistry, testScanFolderSetregPath.toUtf8().data()));
  139. AZStd::string watchPath;
  140. bool recurseScanFolder{ true };
  141. AZ::s64 scanOrder{};
  142. EXPECT_TRUE(settingsRegistry->Get(watchPath, AZ::SettingsRegistryInterface::FixedValueString(AssetProcessor::AssetProcessorSettingsKey)
  143. + "/ScanFolder SettingsRegistryTest/watch"));
  144. EXPECT_TRUE(settingsRegistry->Get(recurseScanFolder, AZ::SettingsRegistryInterface::FixedValueString(AssetProcessor::AssetProcessorSettingsKey)
  145. + "/ScanFolder SettingsRegistryTest/recursive"));
  146. EXPECT_TRUE(settingsRegistry->Get(scanOrder, AZ::SettingsRegistryInterface::FixedValueString(AssetProcessor::AssetProcessorSettingsKey)
  147. + "/ScanFolder SettingsRegistryTest/order"));
  148. // These test values come from the <dev_root>/Registry/AssetProcessorPlatformConfig.setreg file
  149. EXPECT_STREQ("_TestPath", watchPath.c_str());
  150. EXPECT_FALSE(recurseScanFolder);
  151. EXPECT_EQ(20000, scanOrder);
  152. }
  153. // a reusable fixture that sets up one host as a pc with a temp path and such.
  154. class PlatformConfigurationUnitTests_OnePCHostFixture : public PlatformConfigurationUnitTests
  155. {
  156. public:
  157. void SetUp() override
  158. {
  159. PlatformConfigurationUnitTests::SetUp();
  160. m_tempEngineRoot.reset(new QTemporaryDir());
  161. m_tempPath = QDir(m_tempEngineRoot->path());
  162. m_config.reset(new UnitTestPlatformConfiguration());
  163. m_config->EnablePlatform({ "pc",{ "desktop", "host" } }, true);
  164. m_config->PopulatePlatformsForScanFolder(m_platforms);
  165. }
  166. void TearDown() override
  167. {
  168. m_platforms.set_capacity(0);
  169. m_tempEngineRoot.reset();
  170. m_config.reset();
  171. PlatformConfigurationUnitTests::TearDown();
  172. }
  173. AZStd::vector<AssetBuilderSDK::PlatformInfo> m_platforms;
  174. AZStd::unique_ptr<UnitTestPlatformConfiguration> m_config;
  175. AZStd::unique_ptr<QTemporaryDir> m_tempEngineRoot = nullptr; // this actually creates the folder in its constructor, so hold off until setup..
  176. QDir m_tempPath;
  177. };
  178. // ensures that when a file in the root (non recursive) folder is searched for, the root is found.
  179. TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetScanFolderForFile_RootFolderFile_IsFound)
  180. {
  181. using namespace AzToolsFramework::AssetSystem;
  182. using namespace AssetProcessor;
  183. m_config->AddScanFolder(ScanFolderInfo(m_tempPath.filePath("scanfolder1"), "ScanFolder1", "sf1", true, false, m_platforms), true); // a root folder that has watched subfolders, not recursive
  184. m_config->AddScanFolder(ScanFolderInfo(m_tempPath.filePath("scanfolder1/Editor"), "Editor", "sf2", false, true, m_platforms), true); // a child folder that exists within that scan folder.
  185. const ScanFolderInfo* info = m_config->GetScanFolderForFile(m_tempPath.filePath("scanfolder1/something.txt"));
  186. ASSERT_TRUE(info);
  187. EXPECT_STREQ(info->ScanPath().toUtf8().constData(), m_tempPath.filePath("scanfolder1").toUtf8().constData());
  188. EXPECT_STREQ(info->GetDisplayName().toUtf8().constData(), "ScanFolder1");
  189. }
  190. // ensures that when a file in a subfolder (recursive) is searched for, the subfolder is found despite it being inside the root, technically.
  191. TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetScanFolderForFile_SubFolderFile_IsFound)
  192. {
  193. using namespace AzToolsFramework::AssetSystem;
  194. using namespace AssetProcessor;
  195. m_config->AddScanFolder(ScanFolderInfo(m_tempPath.filePath("scanfolder1"), "ScanFolder1", "sf1", true, false, m_platforms), true); // a root folder that has watched subfolders, not recursive
  196. m_config->AddScanFolder(ScanFolderInfo(m_tempPath.filePath("scanfolder1/Editor"), "Editor ScanFolder", "sf2", false, true, m_platforms), true); // a child folder that exists within that scan folder.
  197. const ScanFolderInfo* info = m_config->GetScanFolderForFile(m_tempPath.filePath("scanfolder1/Editor/something.txt"));
  198. ASSERT_TRUE(info);
  199. EXPECT_STREQ(info->ScanPath().toUtf8().constData(), m_tempPath.filePath("scanfolder1/Editor").toUtf8().constData());
  200. EXPECT_STREQ(info->GetDisplayName().toUtf8().constData(), "Editor ScanFolder");
  201. }
  202. TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetOverridingFile_ExistsButNotOverridden_ReturnsEmpty)
  203. {
  204. using namespace AzToolsFramework::AssetSystem;
  205. using namespace AssetProcessor;
  206. // create two scan folders, since its order dependent, the ScanFolder1 is the "winner" in tie breakers.
  207. QString scanfolder1Path = m_tempPath.filePath("scanfolder1");
  208. QString scanfolder2Path = m_tempPath.filePath("scanfolder2");
  209. QString caseSensitiveDummyFileName = m_tempPath.absoluteFilePath("scanfolder1/TestCase.tXt");
  210. QString differentCaseDummyFileName = m_tempPath.absoluteFilePath("scanfolder2/testcase.txt");
  211. UnitTestUtils::CreateDummyFile(caseSensitiveDummyFileName, QString("testcase1\n"));
  212. UnitTestUtils::CreateDummyFile(differentCaseDummyFileName, QString("testcase2\n"));
  213. m_config->AddScanFolder(ScanFolderInfo(scanfolder1Path, "ScanFolder1", "sf1", false, true, m_platforms), true);
  214. m_config->AddScanFolder(ScanFolderInfo(scanfolder2Path, "ScanFolder2", "sf2", false, true, m_platforms), true);
  215. // Perform the test by asking it whether the existing real winning file is being overridden by anyone.
  216. QString overrider = m_config->GetOverridingFile("TestCase.tXt", scanfolder1Path);
  217. // note that this should return the emptystring, because there is nothing that OVERRIDES it (ie, its already the winner).
  218. EXPECT_TRUE(overrider.isEmpty());
  219. }
  220. TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetOverridingFile_DoesNotExist_ReturnsEmptyString)
  221. {
  222. using namespace AzToolsFramework::AssetSystem;
  223. using namespace AssetProcessor;
  224. // create two scan folders, since its order dependent, the ScanFolder1 is the "winner" in tie breakers.
  225. QString scanfolder1Path = m_tempPath.filePath("scanfolder1");
  226. QString scanfolder2Path = m_tempPath.filePath("scanfolder2");
  227. m_config->AddScanFolder(ScanFolderInfo(scanfolder1Path, "ScanFolder1", "sf1", false, true, m_platforms), true);
  228. m_config->AddScanFolder(ScanFolderInfo(scanfolder2Path, "ScanFolder2", "sf2", false, true, m_platforms), true);
  229. // Perform the test by asking it whether anyone overrides "testcase" (lowercase) in scanfolder 2.
  230. QString overrider = m_config->GetOverridingFile("doesntExist.txt", scanfolder2Path);
  231. EXPECT_TRUE(overrider.isEmpty());
  232. }
  233. TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, FindFirstMatchingFile_DoesNotExist_ReturnsEmptyString)
  234. {
  235. using namespace AzToolsFramework::AssetSystem;
  236. using namespace AssetProcessor;
  237. // create two scan folders, since its order dependent, the ScanFolder1 is the "winner" in tie breakers.
  238. QString scanfolder1Path = m_tempPath.filePath("scanfolder1");
  239. QString scanfolder2Path = m_tempPath.filePath("scanfolder2");
  240. m_config->AddScanFolder(ScanFolderInfo(scanfolder1Path, "ScanFolder1", "sf1", false, true, m_platforms), true);
  241. m_config->AddScanFolder(ScanFolderInfo(scanfolder2Path, "ScanFolder2", "sf2", false, true, m_platforms), true);
  242. // Perform the test by asking it whether anyone overrides "testcase" (lowercase) in scanfolder 2.
  243. QString foundFile = m_config->FindFirstMatchingFile("doesntExist.txt");
  244. EXPECT_TRUE(foundFile.isEmpty());
  245. }
  246. // note that we do not guarantee that FindFirstMatchingFile always returns the correct case, as it is a super hot path
  247. // function, and the only time case could be incorrect is in the situation where a file with different case overrides
  248. // an underlying file, ie,
  249. // Engine/EngineAssets/Textures/StartScreen.tif
  250. // MyGame/EngineAssets/textures/startscreen.tif <-- would override the above because game has higher / more important priority.
  251. // ensures that exact matches take priority over subfolder matches
  252. TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetScanFolderForFile_SubFolder_ExactMatch_IsFound)
  253. {
  254. using namespace AzToolsFramework::AssetSystem;
  255. using namespace AssetProcessor;
  256. m_config->AddScanFolder(ScanFolderInfo(m_tempPath.filePath("scanfolder1"), "ScanFolder1", "sf1", true, false, m_platforms), true); // a root folder that has watched subfolders, not recursive
  257. m_config->AddScanFolder(ScanFolderInfo(m_tempPath.filePath("scanfolder1/Editor"), "Editor ScanFolder", "sf2", false, true, m_platforms), true); // a child folder that exists within that scan folder.
  258. const ScanFolderInfo* info = m_config->GetScanFolderForFile(m_tempPath.filePath("scanfolder1/Editor"));
  259. ASSERT_TRUE(info);
  260. EXPECT_STREQ(info->ScanPath().toUtf8().constData(), m_tempPath.filePath("scanfolder1/Editor").toUtf8().constData());
  261. EXPECT_STREQ(info->GetDisplayName().toUtf8().constData(), "Editor ScanFolder");
  262. }
  263. TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolder)
  264. {
  265. using namespace AzToolsFramework::AssetSystem;
  266. using namespace AssetProcessor;
  267. const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
  268. const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
  269. auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
  270. ASSERT_TRUE(configRoot);
  271. UnitTestPlatformConfiguration config;
  272. m_errorAbsorber->Clear();
  273. AssetUtilities::ComputeProjectName(EmptyDummyProjectName, true);
  274. ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
  275. ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  276. ASSERT_EQ(config.GetScanFolderCount(), 4); // the two, and then the one that has the same data as prior but different identifier, plus hardcoded intermediates scanfolder
  277. QString scanName = AssetUtilities::ComputeProjectPath(true) + " Scan Folder";
  278. // Scanfolder 0 is the intermediate assets scanfolder, we don't need to check that folder, so start checking at 1
  279. ASSERT_EQ(config.GetScanFolderAt(1).GetDisplayName(), scanName);
  280. ASSERT_EQ(config.GetScanFolderAt(1).RecurseSubFolders(), true);
  281. ASSERT_EQ(config.GetScanFolderAt(1).GetOrder(), 0);
  282. ASSERT_EQ(config.GetScanFolderAt(1).GetPortableKey(), QString("Game"));
  283. ASSERT_EQ(config.GetScanFolderAt(2).GetDisplayName(), QString("FeatureTests"));
  284. ASSERT_EQ(config.GetScanFolderAt(2).RecurseSubFolders(), false);
  285. ASSERT_EQ(config.GetScanFolderAt(2).GetOrder(), 5000);
  286. // this proves that the featuretests name is used instead of the output prefix
  287. ASSERT_EQ(config.GetScanFolderAt(2).GetPortableKey(), QString("FeatureTests"));
  288. ASSERT_EQ(config.GetScanFolderAt(3).GetDisplayName(), QString("FeatureTests2"));
  289. ASSERT_EQ(config.GetScanFolderAt(3).RecurseSubFolders(), false);
  290. ASSERT_EQ(config.GetScanFolderAt(3).GetOrder(), 6000);
  291. // this proves that the featuretests name is used instead of the output prefix
  292. ASSERT_EQ(config.GetScanFolderAt(3).GetPortableKey(), QString("FeatureTests2"));
  293. }
  294. TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolderPlatformSpecific)
  295. {
  296. using namespace AzToolsFramework::AssetSystem;
  297. using namespace AssetProcessor;
  298. const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
  299. const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
  300. auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular_platform_scanfolder");
  301. ASSERT_TRUE(configRoot);
  302. UnitTestPlatformConfiguration config;
  303. m_errorAbsorber->Clear();
  304. ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
  305. ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  306. ASSERT_EQ(config.GetScanFolderCount(), 6); // +1 for hardcoded intermediates scanfolder
  307. // Scanfolder 0 is the intermediate assets folder, so start at 1
  308. ASSERT_EQ(config.GetScanFolderAt(1).GetDisplayName(), QString("gameoutput"));
  309. AZStd::vector<AssetBuilderSDK::PlatformInfo> platforms = config.GetScanFolderAt(1).GetPlatforms();
  310. ASSERT_EQ(platforms.size(), 4);
  311. ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo(AzToolsFramework::AssetSystem::GetHostAssetPlatform(), AZStd::unordered_set<AZStd::string>{})) != platforms.end());
  312. ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("android", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
  313. ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("ios", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
  314. ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("server", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
  315. ASSERT_EQ(config.GetScanFolderAt(2).GetDisplayName(), QString("editoroutput"));
  316. platforms = config.GetScanFolderAt(2).GetPlatforms();
  317. ASSERT_EQ(platforms.size(), 2);
  318. ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo(AzToolsFramework::AssetSystem::GetHostAssetPlatform(), AZStd::unordered_set<AZStd::string>{})) != platforms.end());
  319. ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("android", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
  320. ASSERT_EQ(config.GetScanFolderAt(3).GetDisplayName(), QString("folder1output"));
  321. platforms = config.GetScanFolderAt(3).GetPlatforms();
  322. ASSERT_EQ(platforms.size(), 1);
  323. ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("android", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
  324. ASSERT_EQ(config.GetScanFolderAt(4).GetDisplayName(), QString("folder2output"));
  325. platforms = config.GetScanFolderAt(4).GetPlatforms();
  326. ASSERT_EQ(platforms.size(), 3);
  327. ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo(AzToolsFramework::AssetSystem::GetHostAssetPlatform(), AZStd::unordered_set<AZStd::string>{})) != platforms.end());
  328. ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("ios", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
  329. ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("server", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
  330. ASSERT_EQ(config.GetScanFolderAt(5).GetDisplayName(), QString("folder3output"));
  331. platforms = config.GetScanFolderAt(5).GetPlatforms();
  332. ASSERT_EQ(platforms.size(), 0);
  333. }
  334. TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularExcludes)
  335. {
  336. using namespace AzToolsFramework::AssetSystem;
  337. using namespace AssetProcessor;
  338. const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
  339. const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
  340. auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
  341. ASSERT_TRUE(configRoot);
  342. UnitTestPlatformConfiguration config;
  343. config.AddScanFolder(ScanFolderInfo("blahblah", "Blah ScanFolder", "sf2", true, true), true);
  344. m_errorAbsorber->Clear();
  345. ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
  346. ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  347. ASSERT_TRUE(config.IsFileExcluded("blahblah/$tmp_01.test"));
  348. ASSERT_FALSE(config.IsFileExcluded("blahblah/tmp_01.test"));
  349. ASSERT_TRUE(config.IsFileExcluded("blahblah/Levels/blahblah_hold/whatever.test"));
  350. ASSERT_FALSE(config.IsFileExcluded("blahblah/Levels/blahblahhold/whatever.test"));
  351. }
  352. TEST_F(PlatformConfigurationUnitTests, Test_GemHandling)
  353. {
  354. UnitTestPlatformConfiguration config;
  355. QTemporaryDir tempEngineRoot;
  356. QDir tempPath(tempEngineRoot.path());
  357. AssetUtilities::ResetAssetRoot();
  358. AssetUtilities::ComputeProjectName("AutomatedTesting", true);
  359. QDir computedEngineRoot;
  360. ASSERT_TRUE(AssetUtilities::ComputeAssetRoot(computedEngineRoot, &tempPath));
  361. ASSERT_TRUE(!computedEngineRoot.absolutePath().isEmpty());
  362. ASSERT_TRUE(tempPath.absolutePath() == computedEngineRoot.absolutePath());
  363. // create ONE of the two files - they are optional, but the paths to them should always be checked and generated.
  364. ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("Gems/LyShine/AssetProcessorGemConfig.ini"), ";nothing to see here"));
  365. // note that it is expected that the gems system gives us absolute paths.
  366. AZStd::vector<AzFramework::GemInfo> fakeGems;
  367. fakeGems.emplace_back("LyShine");// true = pretend this is a game gem.
  368. fakeGems.back().m_absoluteSourcePaths.push_back(tempPath.absoluteFilePath("Gems/LyShine").toUtf8().constData());
  369. fakeGems.emplace_back("LmbrCentral");
  370. fakeGems.back().m_absoluteSourcePaths.push_back(tempPath.absoluteFilePath("Gems/LmbrCentral/v2").toUtf8().constData());
  371. // reading gems via the Gems System is already to be tested in the actual Gems API tests.
  372. // to avoid trying to load those DLLs we avoid calling the actual ReadGems function
  373. config.AddGemScanFolders(fakeGems);
  374. QString expectedScanFolder = tempPath.absoluteFilePath("Gems/LyShine/Assets");
  375. AssetUtilities::ResetAssetRoot();
  376. ASSERT_EQ(4, config.GetScanFolderCount());
  377. EXPECT_FALSE(config.GetScanFolderAt(0).IsRoot());
  378. EXPECT_TRUE(config.GetScanFolderAt(0).RecurseSubFolders());
  379. // the first one is a game gem, so its order should be above 1 but below 100.
  380. EXPECT_GE(config.GetScanFolderAt(0).GetOrder(), 100);
  381. EXPECT_EQ(0, config.GetScanFolderAt(0).ScanPath().compare(expectedScanFolder, Qt::CaseInsensitive));
  382. // for each gem, there are currently 2 scan folders:
  383. // The Gem's 'Assets' folder
  384. // The Gem's 'Registry' folder
  385. expectedScanFolder = tempPath.absoluteFilePath("Gems/LmbrCentral/v2/Assets");
  386. EXPECT_FALSE(config.GetScanFolderAt(2).IsRoot() );
  387. EXPECT_TRUE(config.GetScanFolderAt(2).RecurseSubFolders());
  388. EXPECT_GT(config.GetScanFolderAt(2).GetOrder(), config.GetScanFolderAt(0).GetOrder());
  389. EXPECT_EQ(0, config.GetScanFolderAt(2).ScanPath().compare(expectedScanFolder, Qt::CaseInsensitive));
  390. }
  391. TEST_F(PlatformConfigurationUnitTests, Test_MetaFileTypes)
  392. {
  393. UnitTestPlatformConfiguration config;
  394. config.AddMetaDataType("xxxx", "");
  395. config.AddMetaDataType("yyyy", "zzzz");
  396. ASSERT_TRUE(config.MetaDataFileTypesCount() == 2);
  397. ASSERT_TRUE(QString::compare(config.GetMetaDataFileTypeAt(1).first, "yyyy", Qt::CaseInsensitive) == 0);
  398. ASSERT_TRUE(QString::compare(config.GetMetaDataFileTypeAt(1).second, "zzzz", Qt::CaseInsensitive) == 0);
  399. }
  400. TEST_F(PlatformConfigurationUnitTests, ReadCheckServer_FromConfig_Valid)
  401. {
  402. using namespace AzToolsFramework::AssetSystem;
  403. using namespace AssetProcessor;
  404. const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
  405. const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
  406. auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
  407. ASSERT_TRUE(configRoot);
  408. UnitTestPlatformConfiguration config;
  409. m_errorAbsorber->Clear();
  410. ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
  411. ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  412. const AssetProcessor::RecognizerContainer& recogs = config.GetAssetRecognizerContainer();
  413. // verify that check server flag is set to true for i_caf
  414. ASSERT_TRUE(recogs.contains("i_caf"));
  415. ASSERT_TRUE(recogs.at("i_caf").m_checkServer);
  416. }
  417. TEST_F(PlatformConfigurationUnitTests, PlatformConfigFile_IsPresent_Found)
  418. {
  419. UnitTestPlatformConfiguration config;
  420. QTemporaryDir tempEngineRoot;
  421. QDir tempPath(tempEngineRoot.path());
  422. AssetUtilities::ResetAssetRoot();
  423. AssetUtilities::ComputeProjectName("AutomatedTesting", true);
  424. auto settingsRegistry = AZ::SettingsRegistry::Get();
  425. ASSERT_NE(nullptr, settingsRegistry);
  426. settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder, tempPath.absolutePath().toUtf8().constData());
  427. QDir computedEngineRoot;
  428. ASSERT_TRUE(AssetUtilities::ComputeAssetRoot(computedEngineRoot, &tempPath));
  429. ASSERT_TRUE(AssetUtilities::ComputeEngineRoot(computedEngineRoot, &tempPath));
  430. ASSERT_TRUE(!computedEngineRoot.absolutePath().isEmpty());
  431. ASSERT_TRUE(tempPath.absolutePath() == computedEngineRoot.absolutePath());
  432. // create ONE of the two files - they are optional, but the paths to them should always be checked and generated.
  433. QString platformConfigPath{ AssetProcessor::AssetConfigPlatformDir };
  434. platformConfigPath.append("TestPlatform/");
  435. platformConfigPath.append(AssetProcessor::AssetProcessorPlatformConfigFileName);
  436. AZStd::vector<AZ::IO::Path> platformConfigList;
  437. ASSERT_FALSE(config.AddPlatformConfigFilePaths(platformConfigList));
  438. ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath(platformConfigPath), ";nothing to see here"));
  439. ASSERT_TRUE(config.AddPlatformConfigFilePaths(platformConfigList));
  440. ASSERT_EQ(platformConfigList.size(), 1);
  441. }
  442. TEST_F(PlatformConfigurationUnitTests, Test_MetaFileTypes_AssetImporterExtensions)
  443. {
  444. using namespace AssetProcessor;
  445. const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
  446. const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
  447. auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_metadata");
  448. ASSERT_TRUE(configRoot);
  449. UnitTestPlatformConfiguration config;
  450. m_errorAbsorber->Clear();
  451. ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
  452. ASSERT_GT(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  453. ASSERT_TRUE(config.MetaDataFileTypesCount() == 3);
  454. QStringList entriesToTest{ "aaa", "bbb" };
  455. for (int idx = 0; idx < entriesToTest.size(); idx++)
  456. {
  457. // + 1 skip .meta files
  458. ASSERT_EQ(config.GetMetaDataFileTypeAt(idx + 1).first, QString("%1.assetinfo").arg(entriesToTest[idx]));
  459. ASSERT_EQ(config.GetMetaDataFileTypeAt(idx + 1).second, QString("%1").arg(entriesToTest[idx]));
  460. }
  461. }