UuidManagerTests.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  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/RTTI/ReflectContext.h>
  9. #include <AzCore/UnitTest/TestTypes.h>
  10. #include <AzToolsFramework/Metadata/MetadataManager.h>
  11. #include <AzCore/Serialization/Json/JsonSystemComponent.h>
  12. #include <AzCore/Serialization/Json/RegistrationContext.h>
  13. #include <AzCore/UnitTest/Mocks/MockFileIOBase.h>
  14. #include <AzCore/Component/ComponentApplication.h>
  15. #include <AzCore/Utils/Utils.h>
  16. #include <native/utilities/UuidManager.h>
  17. #include <AssetManager/SourceAssetReference.h>
  18. #include <tests/UnitTestUtilities.h>
  19. #include <Tests/AZTestShared/Utils/Utils.h>
  20. #include <unittests/UnitTestUtils.h>
  21. namespace UnitTests
  22. {
  23. struct UuidManagerTests
  24. : UnitTest::LeakDetectionFixture
  25. {
  26. void SetUp() override
  27. {
  28. m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
  29. m_jsonRegistrationContext = AZStd::make_unique<AZ::JsonRegistrationContext>();
  30. m_componentApplication = AZStd::make_unique<testing::NiceMock<MockComponentApplication>>();
  31. using namespace testing;
  32. ON_CALL(*m_componentApplication.get(), GetSerializeContext()).WillByDefault(Return(m_serializeContext.get()));
  33. ON_CALL(*m_componentApplication.get(), GetJsonRegistrationContext()).WillByDefault(Return(m_jsonRegistrationContext.get()));
  34. AZ::JsonSystemComponent::Reflect(m_jsonRegistrationContext.get());
  35. AzToolsFramework::UuidUtilComponent::Reflect(m_serializeContext.get());
  36. AzToolsFramework::MetadataManager::Reflect(m_serializeContext.get());
  37. AssetProcessor::UuidManager::Reflect(m_serializeContext.get());
  38. m_uuidInterface = AZ::Interface<AssetProcessor::IUuidRequests>::Get();
  39. ASSERT_TRUE(m_uuidInterface);
  40. // Enable txt files by default for these tests
  41. m_uuidInterface->EnableGenerationForTypes({ ".txt" });
  42. m_pathConversion.AddScanfolder("c:/somepath", "somepath");
  43. m_pathConversion.AddScanfolder("c:/other", "other");
  44. }
  45. void TearDown() override
  46. {
  47. m_jsonRegistrationContext->EnableRemoveReflection();
  48. AZ::JsonSystemComponent::Reflect(m_jsonRegistrationContext.get());
  49. m_jsonRegistrationContext->DisableRemoveReflection();
  50. m_jsonRegistrationContext.reset();
  51. m_serializeContext.reset();
  52. }
  53. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  54. AZStd::unique_ptr<AZ::JsonRegistrationContext> m_jsonRegistrationContext;
  55. MockFileStateCache m_fileStateCache;
  56. AzToolsFramework::UuidUtilComponent m_uuidUtil;
  57. AzToolsFramework::MetadataManager m_metadataManager;
  58. AssetProcessor::UuidManager m_uuidManager;
  59. MockMultiPathConversion m_pathConversion;
  60. MockVirtualFileIO m_virtualFileIO;
  61. AZStd::unique_ptr<testing::NiceMock<MockComponentApplication>> m_componentApplication;
  62. TraceBusErrorChecker m_errorChecker;
  63. AssetProcessor::IUuidRequests* m_uuidInterface{};
  64. };
  65. void MakeFile(AZ::IO::PathView path)
  66. {
  67. ASSERT_TRUE(UnitTestUtils::CreateDummyFileAZ(path));
  68. }
  69. TEST_F(UuidManagerTests, GetUuid_FirstTime_ReturnsRandomUuid)
  70. {
  71. static constexpr const char* TestFile = "c:/somepath/mockfile.txt";
  72. MakeFile(TestFile);
  73. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  74. EXPECT_TRUE(uuid);
  75. // Make sure a metadata file was created
  76. EXPECT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(AZStd::string::format("%s%s", TestFile, AzToolsFramework::MetadataManager::MetadataFileExtension).c_str()));
  77. }
  78. TEST_F(UuidManagerTests, GetUuid_FileDoesNotExist_Fails)
  79. {
  80. static constexpr const char* TestFile = "c:/somepath/mockfile.txt";
  81. m_errorChecker.Begin();
  82. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  83. m_errorChecker.End(1);
  84. EXPECT_FALSE(uuid);
  85. }
  86. TEST_F(UuidManagerTests, GetUuid_ExistingFileDeleted_Fails)
  87. {
  88. static constexpr const char* TestFile = "c:/somepath/mockfile.txt";
  89. MakeFile(TestFile);
  90. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  91. EXPECT_TRUE(uuid);
  92. // Make sure a metadata file was created
  93. EXPECT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(
  94. AZStd::string::format("%s%s", TestFile, AzToolsFramework::MetadataManager::MetadataFileExtension).c_str()));
  95. // Remove the file
  96. AZ::IO::FileIOBase::GetInstance()->Remove(TestFile);
  97. AZ::IO::FileIOBase::GetInstance()->Remove(
  98. (AZStd::string(TestFile) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  99. m_uuidInterface->FileRemoved((AZStd::string(TestFile) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  100. // Check the UUID again, expecting an error
  101. m_errorChecker.Begin();
  102. uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  103. m_errorChecker.End(1);
  104. EXPECT_FALSE(uuid);
  105. }
  106. TEST_F(UuidManagerTests, GetUuidTwice_ReturnsSameUuid)
  107. {
  108. static constexpr const char* TestFile = "c:/somepath/Mockfile.txt";
  109. MakeFile(TestFile);
  110. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  111. ASSERT_TRUE(uuid);
  112. auto uuid2 = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  113. ASSERT_TRUE(uuid2);
  114. EXPECT_EQ(uuid.GetValue(), uuid2.GetValue());
  115. }
  116. TEST_F(UuidManagerTests, GetUuid_DifferentFiles_ReturnsDifferentUuid)
  117. {
  118. static constexpr const char* FileA = "c:/somepath/fileA.txt";
  119. static constexpr const char* FileB = "c:/somepath/fileB.txt";
  120. MakeFile(FileA);
  121. MakeFile(FileB);
  122. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileA));
  123. ASSERT_TRUE(uuid);
  124. auto uuid2 = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileB));
  125. ASSERT_TRUE(uuid2);
  126. EXPECT_NE(uuid.GetValue(), uuid2.GetValue());
  127. }
  128. TEST_F(UuidManagerTests, GetLegacyUuids_UppercaseFileName_ReturnsTwoDifferentUuids)
  129. {
  130. static constexpr const char* TestFile = "c:/somepath/Mockfile.txt";
  131. MakeFile(TestFile);
  132. auto result = m_uuidInterface->GetLegacyUuids(AssetProcessor::SourceAssetReference(TestFile));
  133. ASSERT_TRUE(result);
  134. auto uuids = result.GetValue();
  135. ASSERT_EQ(uuids.size(), 2);
  136. EXPECT_NE(*uuids.begin(), *++uuids.begin());
  137. }
  138. TEST_F(UuidManagerTests, GetLegacyUuids_LowercaseFileName_ReturnsOneUuid)
  139. {
  140. static constexpr const char* TestFile = "c:/somepath/mockfile.txt";
  141. MakeFile(TestFile);
  142. auto result = m_uuidInterface->GetLegacyUuids(AssetProcessor::SourceAssetReference(TestFile));
  143. ASSERT_TRUE(result);
  144. EXPECT_EQ(result.GetValue().size(), 1);
  145. }
  146. TEST_F(UuidManagerTests, GetLegacyUuids_DifferentFromCanonicalUuid)
  147. {
  148. static constexpr const char* TestFile = "c:/somepath/Mockfile.txt";
  149. MakeFile(TestFile);
  150. auto legacyUuids = m_uuidInterface->GetLegacyUuids(AssetProcessor::SourceAssetReference(TestFile));
  151. ASSERT_TRUE(legacyUuids);
  152. ASSERT_EQ(legacyUuids.GetValue().size(), 2);
  153. auto canonicalUuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  154. ASSERT_TRUE(canonicalUuid);
  155. EXPECT_THAT(legacyUuids.GetValue(), ::testing::Not(::testing::Contains(canonicalUuid.GetValue())));
  156. }
  157. TEST_F(UuidManagerTests, MoveFile_UuidRemainsTheSame)
  158. {
  159. static constexpr const char* FileA = "c:/somepath/mockfile.txt";
  160. static constexpr const char* FileB = "c:/somepath/newfile.txt";
  161. MakeFile(FileA);
  162. MakeFile(FileB);
  163. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileA));
  164. // Move the metadata file and signal the old one is removed
  165. AZ::IO::FileIOBase::GetInstance()->Rename(
  166. (AZStd::string(FileA) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str(),
  167. (AZStd::string(FileB) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  168. m_uuidInterface->FileRemoved((AZStd::string(FileA) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  169. auto movedUuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileB));
  170. ASSERT_TRUE(uuid);
  171. ASSERT_TRUE(movedUuid);
  172. EXPECT_EQ(uuid.GetValue(), movedUuid.GetValue());
  173. }
  174. TEST_F(UuidManagerTests, MoveFileWithComplexName_UuidRemainsTheSame)
  175. {
  176. static constexpr const char* FileA = "c:/somepath/mockfile.ext1.ext2.txt";
  177. static constexpr const char* FileB = "c:/somepath/newfile.txt";
  178. MakeFile(FileA);
  179. MakeFile(FileB);
  180. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileA));
  181. // Move the metadata file and signal the old one is removed
  182. AZ::IO::FileIOBase::GetInstance()->Rename(
  183. (AZStd::string(FileA) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str(),
  184. (AZStd::string(FileB) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  185. m_uuidInterface->FileRemoved((AZStd::string(FileA) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  186. auto movedUuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileB));
  187. ASSERT_TRUE(uuid);
  188. ASSERT_TRUE(movedUuid);
  189. EXPECT_EQ(uuid.GetValue(), movedUuid.GetValue());
  190. }
  191. TEST_F(UuidManagerTests, MetadataRemoved_NewUuidAssigned)
  192. {
  193. static constexpr const char* TestFile = "c:/somepath/mockfile.txt";
  194. MakeFile(TestFile);
  195. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  196. // Delete the metadata file and signal its removal
  197. AZ::IO::FileIOBase::GetInstance()->Remove(
  198. (AZStd::string(TestFile) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  199. m_uuidInterface->FileRemoved((AZStd::string(TestFile) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  200. auto movedUuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  201. ASSERT_TRUE(uuid);
  202. ASSERT_TRUE(movedUuid);
  203. EXPECT_NE(uuid.GetValue(), movedUuid.GetValue());
  204. }
  205. TEST_F(UuidManagerTests, MetadataUpdated_NewUuidAssigned)
  206. {
  207. static constexpr const char* FileA = "c:/somepath/mockfile.test.txt";
  208. static constexpr const char* FileB = "c:/somepath/someotherfile.txt";
  209. MakeFile(FileA);
  210. MakeFile(FileB);
  211. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileA));
  212. // Generate another metadata file, its the easiest way to "change" a UUID in the metadata file for this test
  213. m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileB));
  214. AZ::IO::FileIOBase::GetInstance()->Remove(
  215. (AZStd::string(FileA) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  216. // Copy FileB's metadata onto the FileA metadata
  217. AZ::IO::FileIOBase::GetInstance()->Rename(
  218. (AZStd::string(FileB) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str(),
  219. (AZStd::string(FileA) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  220. m_uuidInterface->FileRemoved((AZStd::string(FileB) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  221. m_uuidInterface->FileChanged((AZStd::string(FileA) + AzToolsFramework::MetadataManager::MetadataFileExtension).c_str());
  222. auto newUuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileA));
  223. ASSERT_TRUE(uuid);
  224. ASSERT_TRUE(newUuid);
  225. EXPECT_NE(uuid.GetValue(), newUuid.GetValue());
  226. }
  227. TEST_F(UuidManagerTests, RequestUuid_DisabledType_ReturnsLegacyUuid)
  228. {
  229. static constexpr const char* TestFile = "c:/somepath/mockfile.png";
  230. MakeFile(TestFile);
  231. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  232. auto legacyUuids = m_uuidInterface->GetLegacyUuids(AssetProcessor::SourceAssetReference(TestFile));
  233. ASSERT_TRUE(uuid);
  234. ASSERT_TRUE(legacyUuids);
  235. EXPECT_THAT(legacyUuids.GetValue(), ::testing::Contains(uuid.GetValue()));
  236. // Make sure no metadata file was created
  237. EXPECT_FALSE(AZ::IO::FileIOBase::GetInstance()->Exists(
  238. AZStd::string::format("%s%s", TestFile, AzToolsFramework::MetadataManager::MetadataFileExtension).c_str()));
  239. }
  240. TEST_F(UuidManagerTests, TwoFilesWithSameRelativePath_DisabledType_ReturnsSameUuid)
  241. {
  242. static constexpr AZ::IO::FixedMaxPath FileA = "c:/somepath/folderA/mockfile.png"; // png files are disabled
  243. static constexpr AZ::IO::FixedMaxPath FileB = "c:/somepath/folderB/mockfile.png";
  244. MakeFile(FileA);
  245. MakeFile(FileB);
  246. auto uuidA = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(1, FileA.ParentPath(), FileA.Filename()));
  247. auto uuidB = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(2, FileB.ParentPath(), FileB.Filename()));
  248. ASSERT_TRUE(uuidA);
  249. ASSERT_TRUE(uuidB);
  250. EXPECT_EQ(uuidA.GetValue(), uuidB.GetValue());
  251. }
  252. TEST_F(UuidManagerTests, TwoFilesWithSameRelativePath_EnabledType_ReturnsDifferentUuid)
  253. {
  254. static constexpr AZ::IO::FixedMaxPath FileA = "c:/somepath/folderA/mockfile.txt"; // txt files are enabled
  255. static constexpr AZ::IO::FixedMaxPath FileB = "c:/somepath/folderB/mockfile.txt";
  256. MakeFile(FileA);
  257. MakeFile(FileB);
  258. auto uuidA = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(1, FileA.ParentPath(), FileA.Filename()));
  259. auto uuidB = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(2, FileB.ParentPath(), FileB.Filename()));
  260. ASSERT_TRUE(uuidA);
  261. ASSERT_TRUE(uuidB);
  262. EXPECT_NE(uuidA.GetValue(), uuidB.GetValue());
  263. }
  264. TEST_F(UuidManagerTests, GetUuid_CorruptedFile_Fails)
  265. {
  266. static constexpr AZ::IO::FixedMaxPath TestFile = "c:/somepath/mockfile.txt";
  267. static constexpr AZ::IO::FixedMaxPath MetadataFile = TestFile.Native() + AzToolsFramework::MetadataManager::MetadataFileExtension;
  268. MakeFile(TestFile);
  269. // Generate a metadata file
  270. m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  271. // Read in the metadata file
  272. auto result = AZ::Utils::ReadFile<AZStd::string>(MetadataFile.Native());
  273. ASSERT_TRUE(result.IsSuccess());
  274. auto metadataFileContents = result.GetValue();
  275. // Corrupt the first character of the metadata file and write it back to disk, signalling a file change as well
  276. metadataFileContents.data()[0] = 'A';
  277. AZ::Utils::WriteFile(metadataFileContents, MetadataFile.Native());
  278. m_uuidInterface->FileChanged(MetadataFile);
  279. // Try to read the metadata again, expecting an error
  280. auto uuidRetry = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  281. EXPECT_FALSE(uuidRetry);
  282. }
  283. TEST_F(UuidManagerTests, GetUuid_IncompleteMetadataFile_ReturnsAndUpdates)
  284. {
  285. static constexpr AZ::IO::FixedMaxPath TestFile = "c:/somepath/mockfile.txt";
  286. static constexpr AZ::IO::FixedMaxPath MetadataFile = TestFile.Native() + AzToolsFramework::MetadataManager::MetadataFileExtension;
  287. MakeFile(TestFile);
  288. static constexpr AZ::Uuid testUuid{ "{2EE0C7C2-F21E-4254-A180-174992819254}" };
  289. AZStd::string contents = AZStd::string::format("{\"UUID\": {\"uuid\": \"%s\"}}", testUuid.ToFixedString().c_str());
  290. AZ::Utils::WriteFile(contents, MetadataFile.Native());
  291. auto uuidRetry = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  292. ASSERT_TRUE(uuidRetry);
  293. EXPECT_EQ(uuidRetry.GetValue(), testUuid);
  294. auto legacyIds = m_uuidInterface->GetLegacyUuids(AssetProcessor::SourceAssetReference(TestFile));
  295. ASSERT_TRUE(legacyIds);
  296. EXPECT_EQ(legacyIds.GetValue().size(), 1);
  297. }
  298. TEST_F(UuidManagerTests, GetUuid_MetadataFileNoUuid_Fails)
  299. {
  300. static constexpr AZ::IO::FixedMaxPath TestFile = "c:/somepath/mockfile.txt";
  301. static constexpr AZ::IO::FixedMaxPath MetadataFile = TestFile.Native() + AzToolsFramework::MetadataManager::MetadataFileExtension;
  302. MakeFile(TestFile);
  303. AZStd::string contents = AZStd::string::format("{\"UUID\": {\"originalPath\": \" " AZ_STRING_FORMAT " \"}}", AZ_STRING_ARG(TestFile.Filename().Native()));
  304. AZ::Utils::WriteFile(contents, MetadataFile.Native());
  305. auto uuidRetry = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  306. EXPECT_FALSE(uuidRetry);
  307. }
  308. TEST_F(UuidManagerTests, GetUuid_DuplicateUuids_Fails)
  309. {
  310. static constexpr AZ::IO::FixedMaxPath FileA = "c:/somepath/mockfile.test.txt";
  311. static constexpr AZ::IO::FixedMaxPath FileB = "c:/somepath/someotherfile.txt";
  312. MakeFile(FileA);
  313. MakeFile(FileB);
  314. auto uuidA = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileA));
  315. // Assign the same UUID to FileB (note this doesn't fail)
  316. AZ::Interface<AzToolsFramework::IUuidUtil>::Get()->CreateSourceUuid(FileB, uuidA.GetValue());
  317. auto uuidB = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileB));
  318. EXPECT_FALSE(uuidB);
  319. }
  320. TEST_F(UuidManagerTests, GetUuid_DuplicateUuidsClearedCache_Succeeds)
  321. {
  322. static constexpr AZ::IO::FixedMaxPath FileA = "c:/somepath/mockfile.test.txt";
  323. static constexpr AZ::IO::FixedMaxPath FileB = "c:/somepath/someotherfile.txt";
  324. MakeFile(FileA);
  325. MakeFile(FileB);
  326. auto uuidA = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileA));
  327. // Assign the same UUID to FileB
  328. AZ::Interface<AzToolsFramework::IUuidUtil>::Get()->CreateSourceUuid(FileB, uuidA.GetValue());
  329. // Pretend we deleted FileA so there shouldn't be a conflict anymore
  330. m_uuidInterface->FileRemoved(AzToolsFramework::MetadataManager::ToMetadataPath(FileA.c_str()));
  331. auto uuidB = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(FileB));
  332. ASSERT_TRUE(uuidA);
  333. ASSERT_TRUE(uuidB);
  334. EXPECT_EQ(uuidB.GetValue(), uuidA.GetValue());
  335. }
  336. TEST_F(UuidManagerTests, UpdateCase)
  337. {
  338. static constexpr AZ::IO::FixedMaxPath TestFile = "c:/somepath/mockfile.txt";
  339. static constexpr AZ::IO::FixedMaxPath RenamedFile = "c:/somepath/MockFile.txt";
  340. MakeFile(TestFile);
  341. // Generate the metadata file
  342. auto uuid = m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(TestFile));
  343. EXPECT_TRUE(uuid);
  344. auto* io = AZ::IO::FileIOBase::GetInstance();
  345. // Make sure the metadata file exists (this is not a case sensitive check)
  346. EXPECT_TRUE(io->Exists(AzToolsFramework::MetadataManager::ToMetadataPath(TestFile.c_str()).c_str()));
  347. QString relPath = "mockfile.txt";
  348. relPath += AzToolsFramework::MetadataManager::MetadataFileExtension;
  349. // Verify the case of the metadata file is lowercase to start with
  350. EXPECT_TRUE(AssetUtilities::UpdateToCorrectCase("c:/somepath", relPath));
  351. EXPECT_STREQ(relPath.toUtf8().constData(), (QString("mockfile.txt") + AzToolsFramework::MetadataManager::MetadataFileExtension).toUtf8().constData());
  352. // Rename the source file from lowercase to uppercase and notify about the old file being removed
  353. io->Rename(TestFile.c_str(), RenamedFile.c_str());
  354. m_uuidInterface->FileRemoved(TestFile);
  355. // Request the UUID again, this should automatically update the case of the metadata file
  356. m_uuidInterface->GetUuid(AssetProcessor::SourceAssetReference(RenamedFile));
  357. // Verify the metadata file exists (this is not a case sensitive check)
  358. EXPECT_TRUE(io->Exists(AzToolsFramework::MetadataManager::ToMetadataPath(RenamedFile.c_str()).c_str()));
  359. // Verify the case of the metadata file is actually updated
  360. EXPECT_TRUE(AssetUtilities::UpdateToCorrectCase("c:/somepath", relPath));
  361. EXPECT_STREQ(relPath.toUtf8().constData(), (QString("MockFile.txt") + AzToolsFramework::MetadataManager::MetadataFileExtension).toUtf8().constData());
  362. }
  363. TEST_F(UuidManagerTests, FindFilesByUuid)
  364. {
  365. // Test that FindFilesByUuid correctly returns all files with the same matching (legacy) UUID
  366. using namespace AssetProcessor;
  367. static constexpr AZ::IO::FixedMaxPath FileA = "c:/somepath/mockfile.txt";
  368. static constexpr AZ::IO::FixedMaxPath FileB = "c:/other/MockFile.txt";
  369. static constexpr AZ::IO::FixedMaxPath FileC = "c:/other/notvalid/mockFile.txt"; // throw in a random extra file to make sure only matching files are returned
  370. MakeFile(FileA);
  371. MakeFile(FileB);
  372. MakeFile(FileC);
  373. auto fileALegacy = m_uuidInterface->GetLegacyUuids(SourceAssetReference(FileA));
  374. auto fileBLegacy = m_uuidInterface->GetLegacyUuids(SourceAssetReference(FileB));
  375. ASSERT_TRUE(fileALegacy);
  376. ASSERT_TRUE(fileBLegacy);
  377. auto fileAUuid = *fileALegacy.GetValue().begin();
  378. EXPECT_TRUE(fileBLegacy.GetValue().contains(fileAUuid));
  379. auto files = m_uuidInterface->FindFilesByUuid(fileAUuid);
  380. EXPECT_THAT(files, ::testing::UnorderedElementsAre(FileA, FileB));
  381. auto fileACanonical = m_uuidInterface->GetUuid(SourceAssetReference(FileA));
  382. ASSERT_TRUE(fileACanonical);
  383. EXPECT_THAT(m_uuidInterface->FindFilesByUuid(fileACanonical.GetValue()), ::testing::UnorderedElementsAre(FileA));
  384. }
  385. TEST_F(UuidManagerTests, FindHighestPriorityFileByUuid)
  386. {
  387. // Test that FindHighestPriorityFileByUuid returns the oldest file
  388. using namespace AssetProcessor;
  389. static constexpr AZ::IO::FixedMaxPath FileA = "c:/somepath/fileA.txt";
  390. static constexpr AZ::IO::FixedMaxPath FileB = "c:/somepath/fileB.txt";
  391. static constexpr AZ::IO::FixedMaxPath FileC = "c:/other/fileA.txt";
  392. static constexpr AZ::IO::FixedMaxPath FileD = "c:/other/fileB.txt";
  393. MakeFile(FileA);
  394. MakeFile(FileB);
  395. MakeFile(FileC);
  396. MakeFile(FileD);
  397. auto result = m_uuidInterface->GetUuidDetails(AssetProcessor::SourceAssetReference(FileA));
  398. ASSERT_TRUE(result);
  399. auto uuidDetails = result.GetValue();
  400. // Copy the metadata for FileA but give it a different canonical UUID and an older timestamp
  401. // This is really just meant to duplicate the legacy UUIDs
  402. uuidDetails.m_uuid = AZ::Uuid::CreateRandom();
  403. uuidDetails.m_millisecondsSinceUnixEpoch = uuidDetails.m_millisecondsSinceUnixEpoch - 1;
  404. m_metadataManager.SetValue(FileB, AzToolsFramework::UuidUtilComponent::UuidKey, &uuidDetails, azrtti_typeid<decltype(uuidDetails)>());
  405. // Get UUID manager to load the uuids
  406. m_uuidInterface->GetUuid(SourceAssetReference(FileB));
  407. m_uuidInterface->GetUuid(SourceAssetReference(FileC));
  408. m_uuidInterface->GetUuid(SourceAssetReference(FileD));
  409. auto highestPriority = m_uuidInterface->FindHighestPriorityFileByUuid(*uuidDetails.m_legacyUuids.begin());
  410. ASSERT_TRUE(highestPriority);
  411. EXPECT_EQ(highestPriority.value(), FileB);
  412. }
  413. TEST_F(UuidManagerTests, GetCanonicalUuid)
  414. {
  415. // Test that a legacy UUID is correctly upgraded to the canonical UUID
  416. using namespace AssetProcessor;
  417. static constexpr AZ::IO::FixedMaxPath FileA = "c:/somepath/fileA.txt";
  418. MakeFile(FileA);
  419. auto legacyUuids = m_uuidInterface->GetLegacyUuids(SourceAssetReference(FileA));
  420. ASSERT_TRUE(legacyUuids);
  421. auto canonicalUuid = m_uuidInterface->GetCanonicalUuid(*legacyUuids.GetValue().begin());
  422. ASSERT_TRUE(canonicalUuid);
  423. EXPECT_EQ(m_uuidInterface->GetUuid(SourceAssetReference(FileA)).GetValue(), canonicalUuid.value());
  424. }
  425. }