AssetProcessingStateDataUnitTests.cpp 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591
  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 <native/tests/AssetProcessorTest.h>
  9. #include <native/unittests/AssetProcessorUnitTests.h>
  10. #include <native/unittests/UnitTestUtils.h> // for the assert absorber.
  11. using namespace AzToolsFramework::AssetDatabase;
  12. namespace AssetProcessor
  13. {
  14. namespace Internal
  15. {
  16. auto ScanFoldersContainScanFolderID = [](const ScanFolderDatabaseEntryContainer& scanFolders, AZ::s64 scanFolderID) -> bool
  17. {
  18. for (const auto& scanFolder : scanFolders)
  19. {
  20. if (scanFolder.m_scanFolderID == scanFolderID)
  21. {
  22. return true;
  23. }
  24. }
  25. return false;
  26. };
  27. auto ScanFoldersContainScanPath = [](const ScanFolderDatabaseEntryContainer& scanFolders, const char* scanPath) -> bool
  28. {
  29. for (const auto& scanFolder : scanFolders)
  30. {
  31. if (scanFolder.m_scanFolder == scanPath)
  32. {
  33. return true;
  34. }
  35. }
  36. return false;
  37. };
  38. auto ScanFoldersContainPortableKey = [](const ScanFolderDatabaseEntryContainer& scanFolders, const char* portableKey) -> bool
  39. {
  40. for (const auto& scanFolder : scanFolders)
  41. {
  42. if (scanFolder.m_portableKey == portableKey)
  43. {
  44. return true;
  45. }
  46. }
  47. return false;
  48. };
  49. auto SourcesContainSourceID = [](const SourceDatabaseEntryContainer& sources, AZ::s64 sourceID) -> bool
  50. {
  51. for (const auto& source : sources)
  52. {
  53. if (source.m_sourceID == sourceID)
  54. {
  55. return true;
  56. }
  57. }
  58. return false;
  59. };
  60. auto SourcesContainSourceName = [](const SourceDatabaseEntryContainer& sources, const char* sourceName) -> bool
  61. {
  62. for (const auto& source : sources)
  63. {
  64. if (source.m_sourceName == sourceName)
  65. {
  66. return true;
  67. }
  68. }
  69. return false;
  70. };
  71. auto SourcesContainSourceGuid = [](const SourceDatabaseEntryContainer& sources, AZ::Uuid sourceGuid) -> bool
  72. {
  73. for (const auto& source : sources)
  74. {
  75. if (source.m_sourceGuid == sourceGuid)
  76. {
  77. return true;
  78. }
  79. }
  80. return false;
  81. };
  82. auto JobsContainJobID = [](const JobDatabaseEntryContainer& jobs, AZ::s64 jobId) -> bool
  83. {
  84. for (const auto& job : jobs)
  85. {
  86. if (job.m_jobID == jobId)
  87. {
  88. return true;
  89. }
  90. }
  91. return false;
  92. };
  93. auto JobsContainJobKey = [](const JobDatabaseEntryContainer& jobs, const char* jobKey) -> bool
  94. {
  95. for (const auto& job : jobs)
  96. {
  97. if (job.m_jobKey == jobKey)
  98. {
  99. return true;
  100. }
  101. }
  102. return false;
  103. };
  104. auto JobsContainFingerprint = [](const JobDatabaseEntryContainer& jobs, AZ::u32 fingerprint) -> bool
  105. {
  106. for (const auto& job : jobs)
  107. {
  108. if (job.m_fingerprint == fingerprint)
  109. {
  110. return true;
  111. }
  112. }
  113. return false;
  114. };
  115. auto JobsContainPlatform = [](const JobDatabaseEntryContainer& jobs, const char* platform) -> bool
  116. {
  117. for (const auto& job : jobs)
  118. {
  119. if (job.m_platform == platform)
  120. {
  121. return true;
  122. }
  123. }
  124. return false;
  125. };
  126. auto JobsContainBuilderGuid = [](const JobDatabaseEntryContainer& jobs, AZ::Uuid builderGuid) -> bool
  127. {
  128. for (const auto& job : jobs)
  129. {
  130. if (job.m_builderGuid == builderGuid)
  131. {
  132. return true;
  133. }
  134. }
  135. return false;
  136. };
  137. auto JobsContainStatus = [](const JobDatabaseEntryContainer& jobs, AzToolsFramework::AssetSystem::JobStatus status) -> bool
  138. {
  139. for (const auto& job : jobs)
  140. {
  141. if (job.m_status == status)
  142. {
  143. return true;
  144. }
  145. }
  146. return false;
  147. };
  148. auto JobsContainRunKey = [](const JobDatabaseEntryContainer& jobs, AZ::u64 runKey) -> bool
  149. {
  150. for (const auto& job : jobs)
  151. {
  152. if (job.m_jobRunKey == runKey)
  153. {
  154. return true;
  155. }
  156. }
  157. return false;
  158. };
  159. auto ProductDependenciesContainProductDependencyID = [](const ProductDependencyDatabaseEntryContainer& productDependencies, AZ::s64 productDepdendencyId) -> bool
  160. {
  161. for (const auto& productDependency : productDependencies)
  162. {
  163. if (productDependency.m_productDependencyID == productDepdendencyId)
  164. {
  165. return true;
  166. }
  167. }
  168. return false;
  169. };
  170. auto ProductDependenciesContainProductID = [](const ProductDependencyDatabaseEntryContainer& productDependencies, AZ::s64 productId) -> bool
  171. {
  172. for (const auto& productDependency : productDependencies)
  173. {
  174. if (productDependency.m_productPK == productId)
  175. {
  176. return true;
  177. }
  178. }
  179. return false;
  180. };
  181. auto ProductDependenciesContainDependencySoureGuid = [](const ProductDependencyDatabaseEntryContainer& productDependencies, AZ::Uuid dependencySourceGuid) -> bool
  182. {
  183. for (const auto& productDependency : productDependencies)
  184. {
  185. if (productDependency.m_dependencySourceGuid == dependencySourceGuid)
  186. {
  187. return true;
  188. }
  189. }
  190. return false;
  191. };
  192. auto ProductDependenciesContainDependencySubID = [](const ProductDependencyDatabaseEntryContainer& productDependencies, AZ::u32 dependencySubID) -> bool
  193. {
  194. for (const auto& productDependency : productDependencies)
  195. {
  196. if (productDependency.m_dependencySubID == dependencySubID)
  197. {
  198. return true;
  199. }
  200. }
  201. return false;
  202. };
  203. auto ProductDependenciesContainDependencyFlags = [](const ProductDependencyDatabaseEntryContainer& productDependencies, AZStd::bitset<64> dependencyFlags) -> bool
  204. {
  205. for (const auto& productDependency : productDependencies)
  206. {
  207. if (productDependency.m_dependencyFlags == dependencyFlags)
  208. {
  209. return true;
  210. }
  211. }
  212. return false;
  213. };
  214. auto ProductsContainProductID = [](const ProductDatabaseEntryContainer& products, AZ::s64 productId) -> bool
  215. {
  216. for (const auto& product : products)
  217. {
  218. if (product.m_productID == productId)
  219. {
  220. return true;
  221. }
  222. }
  223. return false;
  224. };
  225. }
  226. class AssetProcessingStateDataUnitTest
  227. : public UnitTest::AssetProcessorUnitTestBase
  228. {
  229. protected:
  230. void SetUp() override
  231. {
  232. UnitTest::AssetProcessorUnitTestBase::SetUp();
  233. EXPECT_TRUE(m_connection.DataExists());
  234. EXPECT_TRUE(m_connection.OpenDatabase());
  235. }
  236. void TearDown() override
  237. {
  238. m_connection.CloseDatabase();
  239. UnitTest::AssetProcessorUnitTestBase::TearDown();
  240. }
  241. void AddDefaultScanFolder()
  242. {
  243. // this isn't a real directory. It just creates an entry in the database, so any string would work.
  244. m_defaultScanFolder = ScanFolderDatabaseEntry("c:/O3DE/dev", "dev", "rootportkey");
  245. EXPECT_TRUE(m_connection.SetScanFolder(m_defaultScanFolder));
  246. EXPECT_NE(m_defaultScanFolder.m_scanFolderID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  247. }
  248. void AddDefaultSource()
  249. {
  250. if (m_defaultScanFolder.m_scanFolderID == AzToolsFramework::AssetDatabase::InvalidEntryId)
  251. {
  252. AddDefaultScanFolder();
  253. }
  254. AZ::Uuid validSourceGuid = AZ::Uuid::CreateRandom();
  255. m_defaultSource = SourceDatabaseEntry(m_defaultScanFolder.m_scanFolderID, "SomeSource.tif", validSourceGuid, "12345");
  256. EXPECT_TRUE(m_connection.SetSource(m_defaultSource));
  257. EXPECT_NE(m_defaultSource.m_sourceID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  258. }
  259. void AddDefaultJob()
  260. {
  261. if (m_defaultSource.m_sourceID == AzToolsFramework::AssetDatabase::InvalidEntryId)
  262. {
  263. AddDefaultSource();
  264. }
  265. AZ::u32 validFingerprint = 0;
  266. AZ::Uuid validBuilderGuid = AZ::Uuid::CreateRandom();
  267. AzToolsFramework::AssetSystem::JobStatus statusQueued = AzToolsFramework::AssetSystem::JobStatus::Queued;
  268. m_defaultJob = JobDatabaseEntry(m_defaultSource.m_sourceID, "jobKey", validFingerprint, "pc", validBuilderGuid, statusQueued, 1);
  269. EXPECT_TRUE(m_connection.SetJob(m_defaultJob));
  270. EXPECT_NE(m_defaultJob.m_jobID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  271. EXPECT_EQ(m_defaultJob.m_jobRunKey, 1);
  272. }
  273. void AddDefaultProduct()
  274. {
  275. if (m_defaultJob.m_jobID == AzToolsFramework::AssetDatabase::InvalidEntryId)
  276. {
  277. AddDefaultJob();
  278. }
  279. AZ::Data::AssetType validAssetType = AZ::Data::AssetType::CreateRandom();
  280. m_defaultProduct = ProductDatabaseEntry(m_defaultJob.m_jobID, 0, "SomeProduct.dds", validAssetType);
  281. EXPECT_TRUE(m_connection.SetProduct(m_defaultProduct));
  282. }
  283. void AddDefaultLegacySubId()
  284. {
  285. if (m_defaultProduct.m_productID == AzToolsFramework::AssetDatabase::InvalidEntryId)
  286. {
  287. AddDefaultProduct();
  288. }
  289. m_defaultLegacyEntry = LegacySubIDsEntry(AzToolsFramework::AssetDatabase::InvalidEntryId, m_defaultProduct.m_productID, 0);
  290. EXPECT_TRUE(m_connection.CreateOrUpdateLegacySubID(m_defaultLegacyEntry));
  291. EXPECT_NE(m_defaultLegacyEntry.m_subIDsEntryID, AzToolsFramework::AssetDatabase::InvalidEntryId); // it should have also updated the PK
  292. }
  293. void CreateProductDependencyTree(SourceDatabaseEntryContainer& sources, ProductDatabaseEntryContainer& products, const AZStd::string& platform = "")
  294. {
  295. /* Create the product dependency tree as below
  296. *
  297. * products[0] -> products[1] -> products[2] -> products[4] -> products[5]
  298. * \
  299. * -> products[3]
  300. */
  301. AddDefaultProduct();
  302. // Add sources
  303. sources.emplace_back(m_defaultSource);
  304. for (int index = 1; index < 6; ++index)
  305. {
  306. AZ::Uuid validSourceGuid = AZ::Uuid::CreateRandom();
  307. sources.emplace_back(SourceDatabaseEntry(m_defaultScanFolder.m_scanFolderID, AZStd::string::format("SomeSource%d.tif", index).c_str(), validSourceGuid, ""));
  308. EXPECT_TRUE(m_connection.SetSource(sources[index]));
  309. }
  310. //Add jobs
  311. JobDatabaseEntryContainer jobs;
  312. jobs.emplace_back(m_defaultJob);
  313. AzToolsFramework::AssetSystem::JobStatus statusCompleted = AzToolsFramework::AssetSystem::JobStatus::Completed;
  314. for (int index = 1; index < 6; ++index)
  315. {
  316. AZ::Uuid validBuilderGuid = AZ::Uuid::CreateRandom();
  317. AZ::u32 validFingerprint = index;
  318. jobs.emplace_back(JobDatabaseEntry(sources[index].m_sourceID, AZStd::string::format("jobkey%d", index).c_str(), validFingerprint, "pc", validBuilderGuid, statusCompleted, index + 1));
  319. EXPECT_TRUE(m_connection.SetJob(jobs[index]));
  320. }
  321. //Add products
  322. products.emplace_back(m_defaultProduct);
  323. for (int index = 1; index < 6; ++index)
  324. {
  325. AZ::Data::AssetType validAssetType = AZ::Data::AssetType::CreateRandom();
  326. products.emplace_back(ProductDatabaseEntry(jobs[index].m_jobID, index, AZStd::string::format("SomeProduct%d.dds", index).c_str(), validAssetType));
  327. EXPECT_TRUE(m_connection.SetProduct(products[index]));
  328. }
  329. //products[0] -> products[1]
  330. ProductDependencyDatabaseEntry productDependency = ProductDependencyDatabaseEntry(products[0].m_productID, sources[1].m_sourceGuid, 1, 0, platform, true);
  331. EXPECT_TRUE(m_connection.SetProductDependency(productDependency));
  332. //products[1] -> products[2]
  333. productDependency = ProductDependencyDatabaseEntry(products[1].m_productID, sources[2].m_sourceGuid, 2, 0, platform, true);
  334. EXPECT_TRUE(m_connection.SetProductDependency(productDependency));
  335. //products[1] -> products[3]
  336. productDependency = ProductDependencyDatabaseEntry(products[1].m_productID, sources[3].m_sourceGuid, 3, 0, platform, true);
  337. EXPECT_TRUE(m_connection.SetProductDependency(productDependency));
  338. //products[2] -> products[4]
  339. productDependency = ProductDependencyDatabaseEntry(products[2].m_productID, sources[4].m_sourceGuid, 4, 0, platform, true);
  340. EXPECT_TRUE(m_connection.SetProductDependency(productDependency));
  341. //products[4] -> products[5]
  342. productDependency = ProductDependencyDatabaseEntry(products[4].m_productID, sources[5].m_sourceGuid, 5, 0, platform, true);
  343. EXPECT_TRUE(m_connection.SetProductDependency(productDependency));
  344. }
  345. void CreateProductDependencyTree(ProductDatabaseEntryContainer& products, const AZStd::string& platform = "")
  346. {
  347. SourceDatabaseEntryContainer sources;
  348. CreateProductDependencyTree(sources, products, platform);
  349. }
  350. void CreateProductDependencyTree(SourceDatabaseEntryContainer& sources, const AZStd::string& platform = "")
  351. {
  352. ProductDatabaseEntryContainer products;
  353. CreateProductDependencyTree(sources, products, platform);
  354. }
  355. AssetProcessor::AssetDatabaseConnection m_connection;
  356. ScanFolderDatabaseEntry m_defaultScanFolder;
  357. SourceDatabaseEntry m_defaultSource;
  358. JobDatabaseEntry m_defaultJob;
  359. ProductDatabaseEntry m_defaultProduct;
  360. LegacySubIDsEntry m_defaultLegacyEntry;
  361. };
  362. TEST_F(AssetProcessingStateDataUnitTest, TestScanFolder_AddScanFolder_Succeeds)
  363. {
  364. // There are no scan folders yet so trying to find one should fail
  365. ScanFolderDatabaseEntry scanFolder;
  366. ScanFolderDatabaseEntryContainer scanFolders;
  367. EXPECT_FALSE(m_connection.GetScanFolders(scanFolders));
  368. EXPECT_FALSE(m_connection.GetScanFolderByScanFolderID(0, scanFolder));
  369. EXPECT_FALSE(m_connection.GetScanFolderBySourceID(0, scanFolder));
  370. EXPECT_FALSE(m_connection.GetScanFolderByProductID(0, scanFolder));
  371. EXPECT_FALSE(m_connection.GetScanFolderByPortableKey("sadfsadfsadfsadfs", scanFolder));
  372. scanFolders.clear();
  373. AddDefaultScanFolder();
  374. // Get all scan folders, there should be one we just added
  375. scanFolders.clear();
  376. EXPECT_TRUE(m_connection.GetScanFolders(scanFolders));
  377. EXPECT_EQ(scanFolders.size(), 1);
  378. EXPECT_TRUE(Internal::ScanFoldersContainScanPath(scanFolders, "c:/O3DE/dev"));
  379. EXPECT_TRUE(Internal::ScanFoldersContainScanFolderID(scanFolders, m_defaultScanFolder.m_scanFolderID));
  380. EXPECT_TRUE(Internal::ScanFoldersContainPortableKey(scanFolders, m_defaultScanFolder.m_portableKey.c_str()));
  381. EXPECT_TRUE(Internal::ScanFoldersContainPortableKey(scanFolders, "rootportkey"));
  382. }
  383. TEST_F(AssetProcessingStateDataUnitTest, TestScanFolder_AddDuplicateScanFolder_GetsSameId)
  384. {
  385. AddDefaultScanFolder();
  386. // Add the same folder again, should not add another because it already exists, so we should get the same id
  387. // not only that, but the path should update.
  388. ScanFolderDatabaseEntry dupeScanFolder("c:/O3DE/dev1", "dev", "rootportkey");
  389. dupeScanFolder.m_scanFolderID = AzToolsFramework::AssetDatabase::InvalidEntryId;
  390. EXPECT_TRUE(m_connection.SetScanFolder(dupeScanFolder));
  391. EXPECT_EQ(dupeScanFolder, m_defaultScanFolder);
  392. EXPECT_EQ(dupeScanFolder.m_portableKey, m_defaultScanFolder.m_portableKey);
  393. EXPECT_EQ(dupeScanFolder.m_scanFolderID, m_defaultScanFolder.m_scanFolderID);
  394. // Get all scan folders, there should only the one we added
  395. ScanFolderDatabaseEntryContainer scanFolders;
  396. EXPECT_TRUE(m_connection.GetScanFolders(scanFolders));
  397. EXPECT_EQ(scanFolders.size(), 1);
  398. EXPECT_TRUE(Internal::ScanFoldersContainScanPath(scanFolders, "c:/O3DE/dev1"));
  399. EXPECT_TRUE(Internal::ScanFoldersContainScanFolderID(scanFolders, m_defaultScanFolder.m_scanFolderID));
  400. EXPECT_TRUE(Internal::ScanFoldersContainPortableKey(scanFolders, m_defaultScanFolder.m_portableKey.c_str()));
  401. EXPECT_TRUE(Internal::ScanFoldersContainPortableKey(scanFolders, "rootportkey"));
  402. }
  403. TEST_F(AssetProcessingStateDataUnitTest, TestScanFolder_RetrieveScanFolderById_Succeeds)
  404. {
  405. AddDefaultScanFolder();
  406. // Retrieve the one we just made by id
  407. ScanFolderDatabaseEntry retrieveScanfolderById;
  408. EXPECT_TRUE(m_connection.GetScanFolderByScanFolderID(m_defaultScanFolder.m_scanFolderID, retrieveScanfolderById));
  409. EXPECT_NE(retrieveScanfolderById.m_scanFolderID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  410. EXPECT_EQ(retrieveScanfolderById.m_scanFolderID, m_defaultScanFolder.m_scanFolderID);
  411. }
  412. TEST_F(AssetProcessingStateDataUnitTest, TestScanFolder_RetrieveScanFolderByPortableKey_Succeeds)
  413. {
  414. AddDefaultScanFolder();
  415. // Retrieve the one we just made by portable key
  416. ScanFolderDatabaseEntry retrieveScanfolderByScanPath;
  417. EXPECT_TRUE(m_connection.GetScanFolderByPortableKey("rootportkey", retrieveScanfolderByScanPath));
  418. EXPECT_NE(retrieveScanfolderByScanPath.m_scanFolderID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  419. EXPECT_EQ(retrieveScanfolderByScanPath.m_scanFolderID, m_defaultScanFolder.m_scanFolderID);
  420. }
  421. TEST_F(AssetProcessingStateDataUnitTest, TestScanFolder_RemoveScanFolderById_Succeeds)
  422. {
  423. AddDefaultScanFolder();
  424. // Add another scan folder
  425. ScanFolderDatabaseEntry gameScanFolderEntry("c:/O3DE/game", "game", "gameportkey");
  426. EXPECT_TRUE(m_connection.SetScanFolder(gameScanFolderEntry));
  427. EXPECT_NE(gameScanFolderEntry.m_scanFolderID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  428. // Get all scan folders, there should be two scan folders we just added
  429. ScanFolderDatabaseEntryContainer scanFolders;
  430. EXPECT_TRUE(m_connection.GetScanFolders(scanFolders));
  431. EXPECT_EQ(scanFolders.size(), 2);
  432. EXPECT_TRUE(Internal::ScanFoldersContainScanPath(scanFolders, "c:/O3DE/dev"));
  433. EXPECT_TRUE(Internal::ScanFoldersContainScanPath(scanFolders, "c:/O3DE/game"));
  434. EXPECT_TRUE(Internal::ScanFoldersContainScanFolderID(scanFolders, m_defaultScanFolder.m_scanFolderID));
  435. EXPECT_TRUE(Internal::ScanFoldersContainScanFolderID(scanFolders, gameScanFolderEntry.m_scanFolderID));
  436. // Remove the game scan folder
  437. EXPECT_TRUE(m_connection.RemoveScanFolder(848475));//should return true even if it doesn't exist, false only means SQL failed
  438. EXPECT_TRUE(m_connection.RemoveScanFolder(gameScanFolderEntry.m_scanFolderID));
  439. // Get all scan folders again, there should now only the first we added
  440. scanFolders.clear();
  441. EXPECT_TRUE(m_connection.GetScanFolders(scanFolders));
  442. EXPECT_EQ(scanFolders.size(), 1);
  443. EXPECT_TRUE(Internal::ScanFoldersContainScanPath(scanFolders, "c:/O3DE/dev"));
  444. EXPECT_TRUE(Internal::ScanFoldersContainScanFolderID(scanFolders, m_defaultScanFolder.m_scanFolderID));
  445. }
  446. TEST_F(AssetProcessingStateDataUnitTest, TestScanFolder_RemoveScanFolderByContainer_Succeeds)
  447. {
  448. AddDefaultScanFolder();
  449. // Add another scan folder
  450. ScanFolderDatabaseEntry gameScanFolderEntry("c:/O3DE/game", "game", "gameportkey");
  451. EXPECT_TRUE(m_connection.SetScanFolder(gameScanFolderEntry));
  452. EXPECT_NE(gameScanFolderEntry.m_scanFolderID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  453. // Get all scan folders, there should only the two we added
  454. ScanFolderDatabaseEntryContainer scanFolders;
  455. EXPECT_TRUE(m_connection.GetScanFolders(scanFolders));
  456. EXPECT_EQ(scanFolders.size(), 2);
  457. EXPECT_TRUE(Internal::ScanFoldersContainScanPath(scanFolders, "c:/O3DE/dev"));
  458. EXPECT_TRUE(Internal::ScanFoldersContainScanPath(scanFolders, "c:/O3DE/game"));
  459. EXPECT_TRUE(Internal::ScanFoldersContainScanFolderID(scanFolders, m_defaultScanFolder.m_scanFolderID));
  460. EXPECT_TRUE(Internal::ScanFoldersContainScanFolderID(scanFolders, gameScanFolderEntry.m_scanFolderID));
  461. // Remove scan folder by using a container
  462. ScanFolderDatabaseEntryContainer tempScanFolderDatabaseEntryContainer; // note that on clang, its illegal to call a non-const function with a temp variable container as the param
  463. EXPECT_TRUE(m_connection.RemoveScanFolders(tempScanFolderDatabaseEntryContainer)); // call with empty
  464. EXPECT_TRUE(m_connection.RemoveScanFolders(scanFolders));
  465. scanFolders.clear();
  466. EXPECT_FALSE(m_connection.GetScanFolders(scanFolders));
  467. }
  468. TEST_F(AssetProcessingStateDataUnitTest, TestSources_AddSource_Succeeds)
  469. {
  470. // There are no sources yet so trying to find one should fail
  471. SourceDatabaseEntry source;
  472. SourceDatabaseEntryContainer sources;
  473. EXPECT_FALSE(m_connection.GetSources(sources));
  474. EXPECT_FALSE(m_connection.GetSourceBySourceID(3443, source));
  475. EXPECT_FALSE(m_connection.GetSourceBySourceGuid(AZ::Uuid::Create(), source));
  476. EXPECT_FALSE(m_connection.GetSourcesLikeSourceName("source", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, sources));
  477. EXPECT_FALSE(m_connection.GetSourcesLikeSourceName("source", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, sources));
  478. EXPECT_FALSE(m_connection.GetSourcesLikeSourceName("source", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::EndsWith, sources));
  479. EXPECT_FALSE(m_connection.GetSourcesLikeSourceName("source", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Matches, sources));
  480. // Trying to add a source without a valid scan folder pk should fail
  481. AZ::Uuid validSourceGuid1 = AZ::Uuid::CreateRandom();
  482. source = SourceDatabaseEntry(234234, "SomeSource.tif", validSourceGuid1, "");
  483. {
  484. UnitTestUtils::AssertAbsorber absorber;
  485. EXPECT_FALSE(m_connection.SetSource(source));
  486. EXPECT_GE(absorber.m_numWarningsAbsorbed, 0);
  487. }
  488. AddDefaultSource();
  489. // Get all sources, there should only the one we added
  490. sources.clear();
  491. EXPECT_TRUE(m_connection.GetSources(sources));
  492. EXPECT_EQ(sources.size(), 1);
  493. EXPECT_EQ(sources[0].m_analysisFingerprint, "12345");
  494. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  495. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  496. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  497. }
  498. TEST_F(AssetProcessingStateDataUnitTest, TestSources_AddDuplicateSource_GetsSameId)
  499. {
  500. AddDefaultSource();
  501. // Add the same source again, should not add another because it already exists, so we should get the same id
  502. SourceDatabaseEntry dupeSource(m_defaultSource);
  503. dupeSource.m_sourceID = AzToolsFramework::AssetDatabase::InvalidEntryId;
  504. EXPECT_TRUE(m_connection.SetSource(dupeSource));
  505. EXPECT_EQ(dupeSource.m_sourceID, m_defaultSource.m_sourceID);
  506. // Get all sources, there should still only the one we added
  507. SourceDatabaseEntryContainer sources;
  508. EXPECT_TRUE(m_connection.GetSources(sources));
  509. EXPECT_EQ(sources.size(), 1);
  510. EXPECT_EQ(sources[0].m_analysisFingerprint, "12345");
  511. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  512. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  513. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  514. }
  515. TEST_F(AssetProcessingStateDataUnitTest, TestSources_ChangeSourceField_Succeeds)
  516. {
  517. AddDefaultSource();
  518. // Make sure that changing a field like fingerprint writes the new field to database but does not
  519. // add a new entry (ie, its just modifying existing data)
  520. SourceDatabaseEntry sourceWithDifferentFingerprint(m_defaultSource);
  521. sourceWithDifferentFingerprint.m_analysisFingerprint = "otherFingerprint";
  522. EXPECT_TRUE(m_connection.SetSource(sourceWithDifferentFingerprint));
  523. EXPECT_EQ(sourceWithDifferentFingerprint.m_sourceID, m_defaultSource.m_sourceID);
  524. SourceDatabaseEntryContainer sources;
  525. EXPECT_TRUE(m_connection.GetSources(sources));
  526. EXPECT_EQ(sources.size(), 1);
  527. EXPECT_EQ(sources[0].m_analysisFingerprint, "otherFingerprint");
  528. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  529. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  530. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  531. }
  532. TEST_F(AssetProcessingStateDataUnitTest, TestSources_ChangeScanFolder_Succeeds)
  533. {
  534. AddDefaultSource();
  535. // Add the same source again, but change the scan folder. This should NOT add a new source - even if we don't know what the sourceID is:
  536. ScanFolderDatabaseEntry scanfolder = ScanFolderDatabaseEntry("c:/O3DE/dev1", "dev1", "devkey");
  537. EXPECT_TRUE(m_connection.SetScanFolder(scanfolder));
  538. SourceDatabaseEntry source(m_defaultSource);
  539. source.m_scanFolderPK = scanfolder.m_scanFolderID;
  540. source.m_analysisFingerprint = "new different fingerprint";
  541. source.m_sourceID = AzToolsFramework::AssetDatabase::InvalidEntryId;
  542. EXPECT_TRUE(m_connection.SetSource(source));
  543. EXPECT_EQ(source.m_sourceID, m_defaultSource.m_sourceID);
  544. // Get all sources, there should still only the one we added
  545. SourceDatabaseEntryContainer sources;
  546. EXPECT_TRUE(m_connection.GetSources(sources));
  547. EXPECT_EQ(sources.size(), 1);
  548. EXPECT_EQ(sources[0].m_analysisFingerprint, "new different fingerprint"); // verify that this column IS updated.
  549. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  550. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  551. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  552. // Add the same source again, but change the scan folder back. This should NOT add a new source - this time we do know what the source ID is!
  553. SourceDatabaseEntry dupeSource(m_defaultSource);
  554. dupeSource.m_scanFolderPK = m_defaultScanFolder.m_scanFolderID; // changing it back here.
  555. EXPECT_TRUE(m_connection.SetSource(dupeSource));
  556. EXPECT_EQ(dupeSource.m_sourceID, m_defaultSource.m_sourceID);
  557. // Get all sources, there should still only the one we added
  558. sources.clear();
  559. EXPECT_TRUE(m_connection.GetSources(sources));
  560. EXPECT_EQ(sources.size(), 1);
  561. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  562. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  563. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  564. // Remove the extra scan folder, make sure it doesn't drop the source since it should now be bound to the original scan folder agian
  565. EXPECT_TRUE(m_connection.RemoveScanFolder(scanfolder.m_scanFolderID));
  566. sources.clear();
  567. EXPECT_TRUE(m_connection.GetSources(sources));
  568. EXPECT_EQ(sources.size(), 1);
  569. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  570. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  571. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  572. }
  573. TEST_F(AssetProcessingStateDataUnitTest, TestSources_RetrieveSourceBySourceId_Succeeds)
  574. {
  575. AddDefaultSource();
  576. SourceDatabaseEntry retrieveSourceBySourceID;
  577. EXPECT_TRUE(m_connection.GetSourceBySourceID(m_defaultSource.m_sourceID, retrieveSourceBySourceID));
  578. EXPECT_NE(retrieveSourceBySourceID.m_sourceID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  579. EXPECT_EQ(retrieveSourceBySourceID.m_sourceID, m_defaultSource.m_sourceID);
  580. EXPECT_EQ(retrieveSourceBySourceID.m_scanFolderPK, m_defaultSource.m_scanFolderPK);
  581. EXPECT_EQ(retrieveSourceBySourceID.m_sourceGuid, m_defaultSource.m_sourceGuid);
  582. EXPECT_EQ(retrieveSourceBySourceID.m_sourceName, m_defaultSource.m_sourceName);
  583. }
  584. TEST_F(AssetProcessingStateDataUnitTest, TestSources_RetrieveSourceBySourceGuid_Succeeds)
  585. {
  586. AddDefaultSource();
  587. // Try retrieving this source by guid
  588. SourceDatabaseEntry retrieveSourceBySourceGuid;
  589. EXPECT_TRUE(m_connection.GetSourceBySourceGuid(m_defaultSource.m_sourceGuid, retrieveSourceBySourceGuid));
  590. EXPECT_NE(retrieveSourceBySourceGuid.m_sourceID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  591. EXPECT_EQ(retrieveSourceBySourceGuid.m_sourceID, m_defaultSource.m_sourceID);
  592. EXPECT_EQ(retrieveSourceBySourceGuid.m_scanFolderPK, m_defaultSource.m_scanFolderPK);
  593. EXPECT_EQ(retrieveSourceBySourceGuid.m_sourceGuid, m_defaultSource.m_sourceGuid);
  594. EXPECT_EQ(retrieveSourceBySourceGuid.m_sourceName, m_defaultSource.m_sourceName);
  595. }
  596. TEST_F(AssetProcessingStateDataUnitTest, TestSources_RetrieveSourceBySourceName_Succeeds)
  597. {
  598. AddDefaultSource();
  599. // Try retrieving this source by source name
  600. SourceDatabaseEntryContainer sources;
  601. EXPECT_FALSE(m_connection.GetSourcesLikeSourceName("Source.tif", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, sources));
  602. sources.clear();
  603. EXPECT_FALSE(m_connection.GetSourcesLikeSourceName("_SomeSource_", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, sources));
  604. sources.clear();
  605. EXPECT_TRUE(m_connection.GetSourcesLikeSourceName("SomeSource%", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, sources));
  606. EXPECT_EQ(sources.size(), 1);
  607. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  608. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  609. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  610. sources.clear();
  611. EXPECT_TRUE(m_connection.GetSourcesLikeSourceName("%SomeSource%", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, sources));
  612. EXPECT_EQ(sources.size(), 1);
  613. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  614. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  615. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  616. sources.clear();
  617. EXPECT_FALSE(m_connection.GetSourcesLikeSourceName("Source", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, sources));
  618. sources.clear();
  619. EXPECT_TRUE(m_connection.GetSourcesLikeSourceName("Some", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, sources));
  620. EXPECT_EQ(sources.size(), 1);
  621. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  622. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  623. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  624. sources.clear();
  625. EXPECT_FALSE(m_connection.GetSourcesLikeSourceName("SomeSource", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::EndsWith, sources));
  626. sources.clear();
  627. EXPECT_TRUE(m_connection.GetSourcesLikeSourceName(".tif", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::EndsWith, sources));
  628. EXPECT_EQ(sources.size(), 1);
  629. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  630. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  631. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  632. sources.clear();
  633. EXPECT_FALSE(m_connection.GetSourcesLikeSourceName("blah", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Matches, sources));
  634. sources.clear();
  635. EXPECT_TRUE(m_connection.GetSourcesLikeSourceName("meSour", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Matches, sources));
  636. EXPECT_EQ(sources.size(), 1);
  637. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  638. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  639. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  640. }
  641. TEST_F(AssetProcessingStateDataUnitTest, TestSources_RemoveSourceById_Succeeds)
  642. {
  643. AddDefaultSource();
  644. // Get all sources, there should still only the one we added
  645. SourceDatabaseEntryContainer sources;
  646. EXPECT_TRUE(m_connection.GetSources(sources));
  647. EXPECT_EQ(sources.size(), 1);
  648. EXPECT_EQ(sources[0].m_analysisFingerprint, "12345");
  649. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  650. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  651. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  652. // Remove a source
  653. EXPECT_TRUE(m_connection.RemoveSource(432234));//should return true even if it doesn't exist, false only if SQL failed
  654. EXPECT_TRUE(m_connection.RemoveSource(m_defaultSource.m_sourceID));
  655. // Get all sources, there shouldn't be any
  656. sources.clear();
  657. EXPECT_FALSE(m_connection.GetSources(sources));
  658. }
  659. TEST_F(AssetProcessingStateDataUnitTest, TestSources_RemoveSourceByContainer_Succeeds)
  660. {
  661. AddDefaultSource();
  662. // Add another source
  663. AZ::Uuid validSourceGuid = AZ::Uuid::CreateRandom();
  664. SourceDatabaseEntry source(m_defaultScanFolder.m_scanFolderID, "SomeSource1.tif", validSourceGuid, "");
  665. EXPECT_TRUE(m_connection.SetSource(source));
  666. // Get all sources, there should only the two we added
  667. SourceDatabaseEntryContainer sources;
  668. EXPECT_TRUE(m_connection.GetSources(sources));
  669. EXPECT_EQ(sources.size(), 2);
  670. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  671. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource1.tif"));
  672. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  673. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  674. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, source.m_sourceID));
  675. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, source.m_sourceGuid));
  676. // Remove source via container
  677. SourceDatabaseEntryContainer tempSourceDatabaseEntryContainer;
  678. EXPECT_TRUE(m_connection.RemoveSources(tempSourceDatabaseEntryContainer)); // try it with an empty one.
  679. EXPECT_TRUE(m_connection.RemoveSources(sources));
  680. // Get all sources, there should none
  681. sources.clear();
  682. EXPECT_FALSE(m_connection.GetSources(sources));
  683. }
  684. TEST_F(AssetProcessingStateDataUnitTest, TestSources_RemoveSourceByScanFolderId_Succeeds)
  685. {
  686. AddDefaultSource();
  687. // Add another source
  688. AZ::Uuid validSourceGuid = AZ::Uuid::CreateRandom();
  689. SourceDatabaseEntry source(m_defaultScanFolder.m_scanFolderID, "SomeSource1.tif", validSourceGuid, "");
  690. EXPECT_TRUE(m_connection.SetSource(source));
  691. // Get all sources, there should only the two we added
  692. SourceDatabaseEntryContainer sources;
  693. EXPECT_TRUE(m_connection.GetSources(sources));
  694. EXPECT_EQ(sources.size(), 2);
  695. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource.tif"));
  696. EXPECT_TRUE(Internal::SourcesContainSourceName(sources, "SomeSource1.tif"));
  697. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, m_defaultSource.m_sourceID));
  698. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, m_defaultSource.m_sourceGuid));
  699. EXPECT_TRUE(Internal::SourcesContainSourceID(sources, source.m_sourceID));
  700. EXPECT_TRUE(Internal::SourcesContainSourceGuid(sources, source.m_sourceGuid));
  701. // Remove the scan folder for these sources, the sources should cascade delete
  702. EXPECT_TRUE(m_connection.RemoveScanFolder(m_defaultScanFolder.m_scanFolderID));
  703. // Get all sources, there should none
  704. sources.clear();
  705. EXPECT_FALSE(m_connection.GetSources(sources));
  706. }
  707. TEST_F(AssetProcessingStateDataUnitTest, TestJobs_AddJob_Succeeds)
  708. {
  709. //there are no jobs yet so trying to find one should fail.
  710. JobDatabaseEntryContainer jobs;
  711. JobDatabaseEntry job;
  712. EXPECT_FALSE(m_connection.GetJobs(jobs));
  713. EXPECT_FALSE(m_connection.GetJobByJobID(3443, job));
  714. EXPECT_FALSE(m_connection.GetJobsBySourceID(3234, jobs));
  715. EXPECT_FALSE(m_connection.GetJobsBySourceName(AssetProcessor::SourceAssetReference("c:/O3DE/dev/none"), jobs));
  716. AddDefaultSource();
  717. // Trying to add a job without a valid source pk should fail:
  718. AZ::u32 validFingerprint1 = 1;
  719. AZ::Uuid validBuilderGuid1 = AZ::Uuid::CreateRandom();
  720. AzToolsFramework::AssetSystem::JobStatus statusQueued = AzToolsFramework::AssetSystem::JobStatus::Queued;
  721. {
  722. UnitTestUtils::AssertAbsorber absorber;
  723. job = JobDatabaseEntry(234234, "jobkey", validFingerprint1, "pc", validBuilderGuid1, statusQueued, 1);
  724. EXPECT_FALSE(m_connection.SetJob(job));
  725. EXPECT_GE(absorber.m_numWarningsAbsorbed, 0);
  726. }
  727. // Trying to add a job with a valid source pk but an invalid job id should fail:
  728. {
  729. UnitTestUtils::AssertAbsorber absorber;
  730. job = JobDatabaseEntry(m_defaultSource.m_sourceID, "jobkey", validFingerprint1, "pc", validBuilderGuid1, statusQueued, 0);
  731. EXPECT_FALSE(m_connection.SetJob(job));
  732. EXPECT_GE(absorber.m_numErrorsAbsorbed, 0);
  733. }
  734. AddDefaultJob();
  735. // Get all jobs, there should only the one we added
  736. jobs.clear();
  737. EXPECT_TRUE(m_connection.GetJobs(jobs));
  738. EXPECT_EQ(jobs.size(), 1);
  739. EXPECT_TRUE(Internal::JobsContainJobID(jobs, m_defaultJob.m_jobID));
  740. EXPECT_TRUE(Internal::JobsContainJobKey(jobs, m_defaultJob.m_jobKey.c_str()));
  741. EXPECT_TRUE(Internal::JobsContainFingerprint(jobs, m_defaultJob.m_fingerprint));
  742. EXPECT_TRUE(Internal::JobsContainPlatform(jobs, m_defaultJob.m_platform.c_str()));
  743. EXPECT_TRUE(Internal::JobsContainBuilderGuid(jobs, m_defaultJob.m_builderGuid));
  744. EXPECT_TRUE(Internal::JobsContainStatus(jobs, m_defaultJob.m_status));
  745. EXPECT_TRUE(Internal::JobsContainRunKey(jobs, m_defaultJob.m_jobRunKey));
  746. }
  747. TEST_F(AssetProcessingStateDataUnitTest, TestJobs_AddDuplicateJob_GetsSameId)
  748. {
  749. AddDefaultJob();
  750. // Add the same job again, should not add another because it already exists, so we should get the same id
  751. JobDatabaseEntry dupeJob(m_defaultJob);
  752. dupeJob.m_jobID = AzToolsFramework::AssetDatabase::InvalidEntryId;
  753. EXPECT_TRUE(m_connection.SetJob(dupeJob));
  754. EXPECT_EQ(dupeJob, m_defaultJob);
  755. // Get all jobs, there should still only the one we added
  756. JobDatabaseEntryContainer jobs;
  757. EXPECT_TRUE(m_connection.GetJobs(jobs));
  758. EXPECT_EQ(jobs.size(), 1);
  759. EXPECT_TRUE(Internal::JobsContainJobID(jobs, m_defaultJob.m_jobID));
  760. EXPECT_TRUE(Internal::JobsContainJobKey(jobs, m_defaultJob.m_jobKey.c_str()));
  761. EXPECT_TRUE(Internal::JobsContainFingerprint(jobs, m_defaultJob.m_fingerprint));
  762. EXPECT_TRUE(Internal::JobsContainPlatform(jobs, m_defaultJob.m_platform.c_str()));
  763. EXPECT_TRUE(Internal::JobsContainBuilderGuid(jobs, m_defaultJob.m_builderGuid));
  764. EXPECT_TRUE(Internal::JobsContainStatus(jobs, m_defaultJob.m_status));
  765. }
  766. TEST_F(AssetProcessingStateDataUnitTest, TestJobs_RetrieveJobByJobId_Succeeds)
  767. {
  768. AddDefaultJob();
  769. // Try retrieving this source by id
  770. EXPECT_TRUE(m_connection.GetJobByJobID(m_defaultJob.m_jobID, m_defaultJob));
  771. EXPECT_NE(m_defaultJob.m_jobID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  772. // Try retrieving jobs by source id
  773. JobDatabaseEntryContainer jobs;
  774. EXPECT_TRUE(m_connection.GetJobsBySourceID(m_defaultSource.m_sourceID, jobs));
  775. EXPECT_EQ(jobs.size(), 1);
  776. EXPECT_TRUE(Internal::JobsContainJobID(jobs, m_defaultJob.m_jobID));
  777. EXPECT_TRUE(Internal::JobsContainJobKey(jobs, m_defaultJob.m_jobKey.c_str()));
  778. EXPECT_TRUE(Internal::JobsContainFingerprint(jobs, m_defaultJob.m_fingerprint));
  779. EXPECT_TRUE(Internal::JobsContainPlatform(jobs, m_defaultJob.m_platform.c_str()));
  780. EXPECT_TRUE(Internal::JobsContainBuilderGuid(jobs, m_defaultJob.m_builderGuid));
  781. EXPECT_TRUE(Internal::JobsContainStatus(jobs, m_defaultJob.m_status));
  782. }
  783. TEST_F(AssetProcessingStateDataUnitTest, TestJobs_RetrieveJobBySourceName_Succeeds)
  784. {
  785. AddDefaultJob();
  786. auto& config = m_appManager->m_platformConfig;
  787. config->AddScanFolder(AssetProcessor::ScanFolderInfo{m_defaultScanFolder.m_scanFolder.c_str(),
  788. m_defaultScanFolder.m_displayName.c_str(), m_defaultScanFolder.m_portableKey.c_str(),
  789. false, true, {} , 0, m_defaultScanFolder.m_scanFolderID});
  790. // Try retrieving jobs by source name
  791. JobDatabaseEntryContainer jobs;
  792. EXPECT_TRUE(m_connection.GetJobsBySourceName(AssetProcessor::SourceAssetReference(
  793. m_defaultSource.m_scanFolderPK, m_defaultSource.m_sourceName.c_str()), jobs));
  794. EXPECT_EQ(jobs.size(), 1);
  795. EXPECT_TRUE(Internal::JobsContainJobID(jobs, m_defaultJob.m_jobID));
  796. EXPECT_TRUE(Internal::JobsContainJobKey(jobs, m_defaultJob.m_jobKey.c_str()));
  797. EXPECT_TRUE(Internal::JobsContainFingerprint(jobs, m_defaultJob.m_fingerprint));
  798. EXPECT_TRUE(Internal::JobsContainPlatform(jobs, m_defaultJob.m_platform.c_str()));
  799. EXPECT_TRUE(Internal::JobsContainBuilderGuid(jobs, m_defaultJob.m_builderGuid));
  800. EXPECT_TRUE(Internal::JobsContainStatus(jobs, m_defaultJob.m_status));
  801. }
  802. TEST_F(AssetProcessingStateDataUnitTest, TestJobs_RemoveJobByJobId_Succeeds)
  803. {
  804. AddDefaultJob();
  805. // Remove a job
  806. EXPECT_TRUE(m_connection.RemoveJob(432234));
  807. EXPECT_TRUE(m_connection.RemoveJob(m_defaultJob.m_jobID));
  808. // Get all jobs, there shouldn't be any
  809. JobDatabaseEntryContainer jobs;
  810. EXPECT_FALSE(m_connection.GetJobs(jobs));
  811. }
  812. TEST_F(AssetProcessingStateDataUnitTest, TestJobs_RemoveJobByContainer_Succeeds)
  813. {
  814. AddDefaultJob();
  815. // Add another source and job
  816. AZ::Uuid validSourceGuid = AZ::Uuid::CreateRandom();
  817. SourceDatabaseEntry source = SourceDatabaseEntry(m_defaultScanFolder.m_scanFolderID, "SomeSource1.tif", validSourceGuid, "");
  818. EXPECT_TRUE(m_connection.SetSource(source));
  819. AZ::u32 validFingerprint = 1;
  820. AZ::u32 validJobRunKey = 1;
  821. AZ::Uuid validBuilderGuid = AZ::Uuid::CreateRandom();
  822. AzToolsFramework::AssetSystem::JobStatus statusQueued = AzToolsFramework::AssetSystem::JobStatus::Queued;
  823. JobDatabaseEntry job(source.m_sourceID, "jobkey1", validFingerprint, "pc", validBuilderGuid, statusQueued, validJobRunKey);
  824. EXPECT_TRUE(m_connection.SetJob(job));
  825. // Get all jobs, there should be 2
  826. JobDatabaseEntryContainer jobs;
  827. EXPECT_TRUE(m_connection.GetJobs(jobs));
  828. EXPECT_EQ(jobs.size(), 2);
  829. EXPECT_TRUE(Internal::JobsContainJobID(jobs, m_defaultJob.m_jobID));
  830. EXPECT_TRUE(Internal::JobsContainJobKey(jobs, m_defaultJob.m_jobKey.c_str()));
  831. EXPECT_TRUE(Internal::JobsContainFingerprint(jobs, m_defaultJob.m_fingerprint));
  832. EXPECT_TRUE(Internal::JobsContainPlatform(jobs, m_defaultJob.m_platform.c_str()));
  833. EXPECT_TRUE(Internal::JobsContainBuilderGuid(jobs, m_defaultJob.m_builderGuid));
  834. EXPECT_TRUE(Internal::JobsContainStatus(jobs, m_defaultJob.m_status));
  835. EXPECT_TRUE(Internal::JobsContainJobID(jobs, job.m_jobID));
  836. EXPECT_TRUE(Internal::JobsContainJobKey(jobs, job.m_jobKey.c_str()));
  837. EXPECT_TRUE(Internal::JobsContainFingerprint(jobs, job.m_fingerprint));
  838. EXPECT_TRUE(Internal::JobsContainPlatform(jobs, job.m_platform.c_str()));
  839. EXPECT_TRUE(Internal::JobsContainBuilderGuid(jobs, job.m_builderGuid));
  840. EXPECT_TRUE(Internal::JobsContainStatus(jobs, job.m_status));
  841. //Remove job via container
  842. JobDatabaseEntryContainer tempJobDatabaseEntryContainer;
  843. EXPECT_TRUE(m_connection.RemoveJobs(tempJobDatabaseEntryContainer)); // make sure it works on an empty container.
  844. EXPECT_TRUE(m_connection.RemoveJobs(jobs));
  845. //get all jobs, there should none
  846. jobs.clear();
  847. EXPECT_FALSE(m_connection.GetJobs(jobs));
  848. }
  849. TEST_F(AssetProcessingStateDataUnitTest, TestJobs_RemoveJobBySource_Succeeds)
  850. {
  851. AddDefaultJob();
  852. // Add another job for the same source
  853. AZ::u32 validFingerprint = 1;
  854. AZ::u32 validJobRunKey = 1;
  855. AZ::Uuid validBuilderGuid = AZ::Uuid::CreateRandom();
  856. AzToolsFramework::AssetSystem::JobStatus statusQueued = AzToolsFramework::AssetSystem::JobStatus::Queued;
  857. JobDatabaseEntry job(m_defaultSource.m_sourceID, "jobkey1", validFingerprint, "pc", validBuilderGuid, statusQueued, validJobRunKey);
  858. EXPECT_TRUE(m_connection.SetJob(job));
  859. // Get all jobs, there should be 2
  860. JobDatabaseEntryContainer jobs;
  861. EXPECT_TRUE(m_connection.GetJobs(jobs));
  862. EXPECT_EQ(jobs.size(), 2);
  863. EXPECT_TRUE(Internal::JobsContainJobID(jobs, m_defaultJob.m_jobID));
  864. EXPECT_TRUE(Internal::JobsContainJobKey(jobs, m_defaultJob.m_jobKey.c_str()));
  865. EXPECT_TRUE(Internal::JobsContainFingerprint(jobs, m_defaultJob.m_fingerprint));
  866. EXPECT_TRUE(Internal::JobsContainPlatform(jobs, m_defaultJob.m_platform.c_str()));
  867. EXPECT_TRUE(Internal::JobsContainBuilderGuid(jobs, m_defaultJob.m_builderGuid));
  868. EXPECT_TRUE(Internal::JobsContainStatus(jobs, m_defaultJob.m_status));
  869. EXPECT_TRUE(Internal::JobsContainJobID(jobs, job.m_jobID));
  870. EXPECT_TRUE(Internal::JobsContainJobKey(jobs, job.m_jobKey.c_str()));
  871. EXPECT_TRUE(Internal::JobsContainFingerprint(jobs, job.m_fingerprint));
  872. EXPECT_TRUE(Internal::JobsContainPlatform(jobs, job.m_platform.c_str()));
  873. EXPECT_TRUE(Internal::JobsContainBuilderGuid(jobs, job.m_builderGuid));
  874. EXPECT_TRUE(Internal::JobsContainStatus(jobs, job.m_status));
  875. // Remove the source for these jobs, the jobs should cascade delete
  876. EXPECT_TRUE(m_connection.RemoveSource(m_defaultSource.m_sourceID));
  877. // Get all jobs, there should none
  878. jobs.clear();
  879. EXPECT_FALSE(m_connection.GetJobs(jobs));
  880. }
  881. TEST_F(AssetProcessingStateDataUnitTest, TestProducts_AddProduct_Succeeds)
  882. {
  883. // There are no scan folders yet so trying to find one should fail
  884. ProductDatabaseEntry product;
  885. ProductDatabaseEntryContainer products;
  886. EXPECT_FALSE(m_connection.GetProducts(products));
  887. EXPECT_EQ(products.size(), 0);
  888. AddDefaultProduct();
  889. // Get all products, there should be one we just added
  890. products.clear();
  891. EXPECT_TRUE(m_connection.GetProducts(products));
  892. EXPECT_EQ(products.size(), 1);
  893. }
  894. TEST_F(AssetProcessingStateDataUnitTest, TestProducts_RemoveProduct_Succeeds)
  895. {
  896. AddDefaultProduct();
  897. // Add another product
  898. AZ::Data::AssetType validAssetType = AZ::Data::AssetType::CreateRandom();
  899. ProductDatabaseEntry product = ProductDatabaseEntry(m_defaultJob.m_jobID, 1, "SomeProduct1.dds", validAssetType);
  900. EXPECT_TRUE(m_connection.SetProduct(product));
  901. // The products should cascade delete
  902. EXPECT_TRUE(m_connection.RemoveSource(m_defaultSource.m_sourceID));
  903. // Get all products, there should none
  904. ProductDatabaseEntryContainer products;
  905. EXPECT_FALSE(m_connection.GetProducts(products));
  906. }
  907. TEST_F(AssetProcessingStateDataUnitTest, TestProducts_AddLegacySubIds_Succeeds)
  908. {
  909. AddDefaultProduct();
  910. // Test invalid insert for non existant legacy subids.
  911. LegacySubIDsEntry legacyEntry(1, m_defaultProduct.m_productID, 0);
  912. {
  913. UnitTestUtils::AssertAbsorber absorber;
  914. EXPECT_FALSE(m_connection.CreateOrUpdateLegacySubID(legacyEntry));
  915. EXPECT_GT(absorber.m_numWarningsAbsorbed, 0);
  916. }
  917. // Test invalid insert for non-existant legacy product FK constraint
  918. legacyEntry = LegacySubIDsEntry(AzToolsFramework::AssetDatabase::InvalidEntryId, 9999, 0);
  919. {
  920. UnitTestUtils::AssertAbsorber absorber;
  921. EXPECT_FALSE(m_connection.CreateOrUpdateLegacySubID(legacyEntry));
  922. EXPECT_GT(absorber.m_numWarningsAbsorbed, 0);
  923. }
  924. // Test valid insert for a product
  925. AddDefaultLegacySubId();
  926. EXPECT_NE(m_defaultLegacyEntry.m_subIDsEntryID, AzToolsFramework::AssetDatabase::InvalidEntryId); // it should have also updated the PK
  927. }
  928. TEST_F(AssetProcessingStateDataUnitTest, TestLegacySubIds_RetrieveLegacySubIds_Succeeds)
  929. {
  930. AddDefaultLegacySubId();
  931. // Insert of another for same product
  932. LegacySubIDsEntry legacyEntry(AzToolsFramework::AssetDatabase::InvalidEntryId, m_defaultProduct.m_productID, 1);
  933. EXPECT_TRUE(m_connection.CreateOrUpdateLegacySubID(legacyEntry));
  934. EXPECT_NE(legacyEntry.m_subIDsEntryID, AzToolsFramework::AssetDatabase::InvalidEntryId); // it should have also updated the PK
  935. EXPECT_NE(legacyEntry.m_subIDsEntryID, m_defaultLegacyEntry.m_subIDsEntryID); // pk should be unique
  936. // Insert of another for different product
  937. ProductDatabaseEntry product(m_defaultJob.m_jobID, 1, "SomeProduct1.dds", m_defaultProduct.m_assetType);
  938. EXPECT_TRUE(m_connection.SetProduct(product));
  939. legacyEntry = LegacySubIDsEntry(AzToolsFramework::AssetDatabase::InvalidEntryId, product.m_productID, 2);
  940. EXPECT_TRUE(m_connection.CreateOrUpdateLegacySubID(legacyEntry));
  941. // Test that the ones inserted can be retrieved.
  942. AZStd::vector<LegacySubIDsEntry> entriesReturned;
  943. auto handler = [&entriesReturned](LegacySubIDsEntry& entry)
  944. {
  945. entriesReturned.push_back(entry);
  946. return true;
  947. };
  948. EXPECT_TRUE(m_connection.QueryLegacySubIdsByProductID(m_defaultProduct.m_productID, handler));
  949. EXPECT_EQ(entriesReturned.size(), 2);
  950. bool foundSubID3 = false;
  951. bool foundSubID4 = false;
  952. for (const LegacySubIDsEntry& entryFound : entriesReturned)
  953. {
  954. EXPECT_NE(entryFound.m_subIDsEntryID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  955. EXPECT_EQ(entryFound.m_productPK, m_defaultProduct.m_productID);
  956. if (entryFound.m_subID == 0)
  957. {
  958. foundSubID3 = true;
  959. }
  960. else if (entryFound.m_subID == 1)
  961. {
  962. foundSubID4 = true;
  963. }
  964. }
  965. EXPECT_TRUE(foundSubID3);
  966. EXPECT_TRUE(foundSubID4);
  967. entriesReturned.clear();
  968. EXPECT_TRUE(m_connection.QueryLegacySubIdsByProductID(product.m_productID, handler));
  969. EXPECT_EQ(entriesReturned.size(), 1);
  970. EXPECT_NE(entriesReturned[0].m_subIDsEntryID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  971. EXPECT_EQ(entriesReturned[0].m_productPK, product.m_productID);
  972. EXPECT_EQ(entriesReturned[0].m_subID, 2);
  973. }
  974. TEST_F(AssetProcessingStateDataUnitTest, TestLegacySubIds_OverrideLegacySubId_Succeeds)
  975. {
  976. AddDefaultLegacySubId();
  977. // Retrieve the current legacy sub IDs entry
  978. AZStd::vector<LegacySubIDsEntry> entriesReturned;
  979. auto handler = [&entriesReturned](LegacySubIDsEntry& entry)
  980. {
  981. entriesReturned.push_back(entry);
  982. return true;
  983. };
  984. EXPECT_TRUE(m_connection.QueryLegacySubIdsByProductID(m_defaultProduct.m_productID, handler));
  985. EXPECT_EQ(entriesReturned.size(), 1);
  986. EXPECT_NE(entriesReturned[0].m_subIDsEntryID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  987. EXPECT_EQ(entriesReturned[0].m_productPK, m_defaultProduct.m_productID);
  988. EXPECT_EQ(entriesReturned[0].m_subID, 0);
  989. // Test UPDATE -> overwrite existing.
  990. entriesReturned[0].m_subID = 1;
  991. EXPECT_TRUE(m_connection.CreateOrUpdateLegacySubID(entriesReturned[0]));
  992. entriesReturned.clear();
  993. EXPECT_TRUE(m_connection.QueryLegacySubIdsByProductID(m_defaultProduct.m_productID, handler));
  994. EXPECT_EQ(entriesReturned.size(), 1);
  995. EXPECT_NE(entriesReturned[0].m_subIDsEntryID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  996. EXPECT_EQ(entriesReturned[0].m_productPK, m_defaultProduct.m_productID);
  997. EXPECT_EQ(entriesReturned[0].m_subID, 1);
  998. }
  999. TEST_F(AssetProcessingStateDataUnitTest, TestLegacySubIds_RemoveLegacySubIdByProductId_Succeeds)
  1000. {
  1001. AddDefaultLegacySubId();
  1002. AZStd::vector<LegacySubIDsEntry> entriesReturned;
  1003. auto handler = [&entriesReturned](LegacySubIDsEntry& entry)
  1004. {
  1005. entriesReturned.push_back(entry);
  1006. return true;
  1007. };
  1008. EXPECT_TRUE(m_connection.RemoveLegacySubIDsByProductID(m_defaultProduct.m_productID));
  1009. entriesReturned.clear();
  1010. EXPECT_TRUE(m_connection.QueryLegacySubIdsByProductID(m_defaultProduct.m_productID, handler));
  1011. EXPECT_TRUE(entriesReturned.empty());
  1012. }
  1013. TEST_F(AssetProcessingStateDataUnitTest, TestLegacySubIds_RemoveLegacySubIdByPK_Succeeds)
  1014. {
  1015. AddDefaultLegacySubId();
  1016. // Add a second legacy sub ID
  1017. LegacySubIDsEntry legacyEntry(AzToolsFramework::AssetDatabase::InvalidEntryId, m_defaultProduct.m_productID, 1);
  1018. EXPECT_TRUE(m_connection.CreateOrUpdateLegacySubID(legacyEntry));
  1019. EXPECT_NE(legacyEntry.m_subIDsEntryID, AzToolsFramework::AssetDatabase::InvalidEntryId); // it should have also updated the PK
  1020. EXPECT_NE(legacyEntry.m_subIDsEntryID, m_defaultLegacyEntry.m_subIDsEntryID); // pk should be unique
  1021. AZStd::vector<LegacySubIDsEntry> entriesReturned;
  1022. auto handler = [&entriesReturned](LegacySubIDsEntry& entry)
  1023. {
  1024. entriesReturned.push_back(entry);
  1025. return true;
  1026. };
  1027. EXPECT_TRUE(m_connection.QueryLegacySubIdsByProductID(m_defaultProduct.m_productID, handler));
  1028. EXPECT_EQ(entriesReturned.size(), 2);
  1029. // Test delete by PK. The prior entries should be here for product1. This also makes sure the above
  1030. // delete statement didn't delete more than it should have.
  1031. AZ::s64 toRemove = entriesReturned[0].m_subIDsEntryID;
  1032. AZ::u32 removingSubID = entriesReturned[0].m_subID;
  1033. EXPECT_TRUE(m_connection.RemoveLegacySubID(toRemove));
  1034. entriesReturned.clear();
  1035. EXPECT_TRUE(m_connection.QueryLegacySubIdsByProductID(m_defaultProduct.m_productID, handler));
  1036. EXPECT_EQ(entriesReturned.size(), 1);
  1037. EXPECT_NE(entriesReturned[0].m_subIDsEntryID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1038. EXPECT_NE(entriesReturned[0].m_subIDsEntryID, toRemove);
  1039. EXPECT_EQ(entriesReturned[0].m_productPK, m_defaultProduct.m_productID);
  1040. EXPECT_NE(entriesReturned[0].m_subID, removingSubID);
  1041. }
  1042. TEST_F(AssetProcessingStateDataUnitTest, TestProductDependency_AddProductDependency_Succeeds)
  1043. {
  1044. AddDefaultProduct();
  1045. // Add a second product
  1046. AZ::Uuid validSourceGuid = AZ::Uuid::CreateRandom();
  1047. SourceDatabaseEntry source = SourceDatabaseEntry(m_defaultScanFolder.m_scanFolderID, "SomeSource1.tif", validSourceGuid, "");
  1048. EXPECT_TRUE(m_connection.SetSource(source));
  1049. AZ::Uuid validBuilderGuid = AZ::Uuid::CreateRandom();
  1050. AZ::u32 validFingerprint = 2;
  1051. AZ::u32 validJobRunKey = 1;
  1052. AzToolsFramework::AssetSystem::JobStatus statusCompleted = AzToolsFramework::AssetSystem::JobStatus::Completed;
  1053. JobDatabaseEntry job = JobDatabaseEntry(source.m_sourceID, "jobkey1", validFingerprint, "pc", validBuilderGuid, statusCompleted, validJobRunKey);
  1054. EXPECT_TRUE(m_connection.SetJob(job));
  1055. AZ::Data::AssetType validAssetType = AZ::Data::AssetType::CreateRandom();
  1056. ProductDatabaseEntry product = ProductDatabaseEntry(job.m_jobID, 1, "SomeProduct1.dds", validAssetType);
  1057. EXPECT_TRUE(m_connection.SetProduct(product));
  1058. // There are no product dependencies yet so trying to find one should fail
  1059. ProductDependencyDatabaseEntry productDependency;
  1060. ProductDatabaseEntryContainer products;
  1061. ProductDependencyDatabaseEntryContainer productDependencies;
  1062. EXPECT_FALSE(m_connection.GetProductDependencies(productDependencies));
  1063. EXPECT_FALSE(m_connection.GetProductDependencyByProductDependencyID(3443, productDependency));
  1064. EXPECT_FALSE(m_connection.GetProductDependenciesByProductID(3443, productDependencies));
  1065. EXPECT_FALSE(m_connection.GetDirectProductDependencies(3443, products));
  1066. EXPECT_FALSE(m_connection.GetAllProductDependencies(3443, products));
  1067. AZStd::string platform;
  1068. // Trying to add a product dependency without a valid product pk should fail
  1069. productDependency = ProductDependencyDatabaseEntry(234234, m_defaultSource.m_sourceGuid, 1, 0, platform, true);
  1070. {
  1071. UnitTestUtils::AssertAbsorber absorber;
  1072. EXPECT_FALSE(m_connection.SetProductDependency(productDependency));
  1073. EXPECT_GE(absorber.m_numWarningsAbsorbed, 0);
  1074. }
  1075. // Setting a valid product pk should allow it to be added
  1076. // Product -> Product2
  1077. productDependency = ProductDependencyDatabaseEntry(m_defaultProduct.m_productID, validSourceGuid, 2, 0, platform, true);
  1078. EXPECT_TRUE(m_connection.SetProductDependency(productDependency));
  1079. EXPECT_NE(productDependency.m_productDependencyID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1080. // Get all product dependencies, there should only the one we added
  1081. productDependencies.clear();
  1082. EXPECT_TRUE(m_connection.GetProductDependencies(productDependencies));
  1083. EXPECT_EQ(productDependencies.size(), 1);
  1084. EXPECT_TRUE(Internal::ProductDependenciesContainProductDependencyID(productDependencies, productDependency.m_productDependencyID));
  1085. EXPECT_TRUE(Internal::ProductDependenciesContainProductID(productDependencies, productDependency.m_productPK));
  1086. EXPECT_TRUE(Internal::ProductDependenciesContainDependencySoureGuid(productDependencies, productDependency.m_dependencySourceGuid));
  1087. EXPECT_TRUE(Internal::ProductDependenciesContainDependencySubID(productDependencies, productDependency.m_dependencySubID));
  1088. EXPECT_TRUE(Internal::ProductDependenciesContainDependencyFlags(productDependencies, productDependency.m_dependencyFlags));
  1089. // Add the same product again, should not add another because it already exists, so we should get the same id
  1090. ProductDependencyDatabaseEntry dupeProductDependency(productDependency);
  1091. dupeProductDependency.m_productDependencyID = AzToolsFramework::AssetDatabase::InvalidEntryId;
  1092. EXPECT_TRUE(m_connection.SetProductDependency(dupeProductDependency));
  1093. EXPECT_EQ(dupeProductDependency, dupeProductDependency);
  1094. EXPECT_EQ(dupeProductDependency, dupeProductDependency);
  1095. // Get all product dependencies, there should still only the one we added
  1096. productDependencies.clear();
  1097. EXPECT_TRUE(m_connection.GetProductDependencies(productDependencies));
  1098. EXPECT_EQ(productDependencies.size(), 1);
  1099. EXPECT_TRUE(Internal::ProductDependenciesContainProductDependencyID(productDependencies, productDependency.m_productDependencyID));
  1100. EXPECT_TRUE(Internal::ProductDependenciesContainProductID(productDependencies, productDependency.m_productPK));
  1101. EXPECT_TRUE(Internal::ProductDependenciesContainDependencySoureGuid(productDependencies, productDependency.m_dependencySourceGuid));
  1102. EXPECT_TRUE(Internal::ProductDependenciesContainDependencySubID(productDependencies, productDependency.m_dependencySubID));
  1103. EXPECT_TRUE(Internal::ProductDependenciesContainDependencyFlags(productDependencies, productDependency.m_dependencyFlags));
  1104. }
  1105. TEST_F(AssetProcessingStateDataUnitTest, TestProductDependency_VerifyProductDependency_Succeeds)
  1106. {
  1107. /* Verify the following product dependency tree
  1108. *
  1109. * products[0] -> products[1] -> products[2] -> products[4] -> products[5]
  1110. * \
  1111. * -> products[3]
  1112. */
  1113. ProductDatabaseEntryContainer products;
  1114. CreateProductDependencyTree(products);
  1115. // Direct Deps
  1116. // products[0] -> products[1]
  1117. ProductDatabaseEntryContainer dependentProducts;
  1118. EXPECT_TRUE(m_connection.GetDirectProductDependencies(products[0].m_productID, dependentProducts));
  1119. EXPECT_EQ(dependentProducts.size(), 1);
  1120. EXPECT_TRUE(Internal::ProductsContainProductID(products, products[1].m_productID));
  1121. // products[1] -> products[2], products[3]
  1122. dependentProducts.clear();
  1123. EXPECT_TRUE(m_connection.GetDirectProductDependencies(products[1].m_productID, dependentProducts));
  1124. EXPECT_EQ(dependentProducts.size(), 2);
  1125. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[2].m_productID));
  1126. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[3].m_productID));
  1127. // products[2] -> products[4]
  1128. dependentProducts.clear();
  1129. EXPECT_TRUE(m_connection.GetDirectProductDependencies(products[2].m_productID, dependentProducts));
  1130. EXPECT_EQ(dependentProducts.size(), 1);
  1131. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[4].m_productID));
  1132. // products[3] ->
  1133. dependentProducts.clear();
  1134. EXPECT_FALSE(m_connection.GetDirectProductDependencies(products[3].m_productID, dependentProducts));
  1135. EXPECT_EQ(dependentProducts.size(), 0);
  1136. // products[4] -> products[5]
  1137. dependentProducts.clear();
  1138. EXPECT_TRUE(m_connection.GetDirectProductDependencies(products[4].m_productID, dependentProducts));
  1139. EXPECT_EQ(dependentProducts.size(), 1);
  1140. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[5].m_productID));
  1141. // products[5] ->
  1142. dependentProducts.clear();
  1143. EXPECT_FALSE(m_connection.GetDirectProductDependencies(products[5].m_productID, dependentProducts));
  1144. EXPECT_EQ(dependentProducts.size(), 0);
  1145. // All Deps
  1146. // products[0] -> products[1], products[2], products[3], products[4], products[5]
  1147. dependentProducts.clear();
  1148. EXPECT_TRUE(m_connection.GetAllProductDependencies(products[0].m_productID, dependentProducts));
  1149. EXPECT_EQ(dependentProducts.size(), 5);
  1150. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[1].m_productID));
  1151. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[2].m_productID));
  1152. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[3].m_productID));
  1153. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[4].m_productID));
  1154. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[5].m_productID));
  1155. // products[1] -> products[2], products[3], products[4], products[5]
  1156. dependentProducts.clear();
  1157. EXPECT_TRUE(m_connection.GetAllProductDependencies(products[1].m_productID, dependentProducts));
  1158. EXPECT_EQ(dependentProducts.size(), 4);
  1159. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[2].m_productID));
  1160. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[3].m_productID));
  1161. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[4].m_productID));
  1162. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[5].m_productID));
  1163. // products[2] -> products[4], products[5]
  1164. dependentProducts.clear();
  1165. EXPECT_TRUE(m_connection.GetAllProductDependencies(products[2].m_productID, dependentProducts));
  1166. EXPECT_EQ(dependentProducts.size(), 2);
  1167. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[4].m_productID));
  1168. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[5].m_productID));
  1169. // products[3] ->
  1170. dependentProducts.clear();
  1171. EXPECT_FALSE(m_connection.GetAllProductDependencies(products[3].m_productID, dependentProducts));
  1172. EXPECT_EQ(dependentProducts.size(), 0);
  1173. // products[4] -> products[5]
  1174. dependentProducts.clear();
  1175. EXPECT_TRUE(m_connection.GetAllProductDependencies(products[4].m_productID, dependentProducts));
  1176. EXPECT_EQ(dependentProducts.size(), 1);
  1177. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[5].m_productID));
  1178. // products[5] ->
  1179. dependentProducts.clear();
  1180. EXPECT_FALSE(m_connection.GetAllProductDependencies(products[5].m_productID, dependentProducts));
  1181. EXPECT_EQ(dependentProducts.size(), 0);
  1182. }
  1183. TEST_F(AssetProcessingStateDataUnitTest, TestProductDependency_VerifyCircularProductDependency_Succeeds)
  1184. {
  1185. /* Verify the following circular dependency tree
  1186. * v-----------------------------------------------------------------------<
  1187. * | |
  1188. * products[0] -> products[1] -> products[2] -> products[4] -> products[6]-^
  1189. * \
  1190. * -> products[3]
  1191. */
  1192. SourceDatabaseEntryContainer sources;
  1193. ProductDatabaseEntryContainer products;
  1194. AZStd::string platform;
  1195. CreateProductDependencyTree(sources, products, platform);
  1196. // products[5] -> products[0] (This creates a circular dependency)
  1197. ProductDependencyDatabaseEntry productDependency(products[5].m_productID, sources[0].m_sourceGuid, 0, 0, platform, true);
  1198. EXPECT_TRUE(m_connection.SetProductDependency(productDependency));
  1199. // products[5] -> products[0]
  1200. ProductDatabaseEntryContainer dependentProducts;
  1201. EXPECT_TRUE(m_connection.GetDirectProductDependencies(products[5].m_productID, dependentProducts));
  1202. EXPECT_EQ(dependentProducts.size(), 1);
  1203. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[0].m_productID));
  1204. // products[2] -> products[4], products[5], products[0], products[1], products[3]
  1205. dependentProducts.clear();
  1206. EXPECT_TRUE(m_connection.GetAllProductDependencies(products[2].m_productID, dependentProducts));
  1207. EXPECT_EQ(dependentProducts.size(), 5);
  1208. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[4].m_productID));
  1209. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[5].m_productID));
  1210. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[0].m_productID));
  1211. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[1].m_productID));
  1212. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[3].m_productID));
  1213. m_connection.RemoveProductDependencyByProductId(products[4].m_productID);
  1214. // products[1] -> products[2], products[3], products[4]
  1215. dependentProducts.clear();
  1216. EXPECT_TRUE(m_connection.GetAllProductDependencies(products[1].m_productID, dependentProducts));
  1217. EXPECT_EQ(dependentProducts.size(), 3);
  1218. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[2].m_productID));
  1219. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[3].m_productID));
  1220. EXPECT_TRUE(Internal::ProductsContainProductID(dependentProducts, products[4].m_productID));
  1221. }
  1222. TEST_F(AssetProcessingStateDataUnitTest, TestProductDependency_RemoveProductDependency_Succeeds)
  1223. {
  1224. SourceDatabaseEntryContainer sources;
  1225. CreateProductDependencyTree(sources);
  1226. // Teardown
  1227. // The product dependencies should cascade delete
  1228. for (int index = 0; index < sources.size(); ++index)
  1229. {
  1230. EXPECT_TRUE(m_connection.RemoveSource(sources[index].m_sourceID));
  1231. }
  1232. ProductDependencyDatabaseEntryContainer productDependencies;
  1233. ProductDatabaseEntryContainer dependentProducts;
  1234. EXPECT_FALSE(m_connection.GetProductDependencies(productDependencies));
  1235. EXPECT_FALSE(m_connection.GetDirectProductDependencies(m_defaultProduct.m_productID, dependentProducts));
  1236. EXPECT_FALSE(m_connection.GetAllProductDependencies(m_defaultProduct.m_productID, dependentProducts));
  1237. }
  1238. TEST_F(AssetProcessingStateDataUnitTest, TestBuilderInfo_SetBuilderInfoTable_Succeeds)
  1239. {
  1240. using BuilderInfoEntry = AzToolsFramework::AssetDatabase::BuilderInfoEntry;
  1241. using BuilderInfoEntryContainer = AzToolsFramework::AssetDatabase::BuilderInfoEntryContainer;
  1242. // empty database should have no builder info:
  1243. BuilderInfoEntryContainer results;
  1244. auto resultGatherer = [&results](BuilderInfoEntry&& element)
  1245. {
  1246. results.push_back(AZStd::move(element));
  1247. return true; // returning false would stop iterating. We want all results, so we return true.
  1248. };
  1249. EXPECT_TRUE(m_connection.QueryBuilderInfoTable(resultGatherer));
  1250. EXPECT_TRUE(results.empty());
  1251. BuilderInfoEntryContainer newEntries;
  1252. newEntries.emplace_back(BuilderInfoEntry(AzToolsFramework::AssetDatabase::InvalidEntryId, AZ::Uuid::CreateString("{648B7B06-27A3-42AC-897D-FA4557C28654}"), "Finger_Print"));
  1253. newEntries.emplace_back(BuilderInfoEntry(AzToolsFramework::AssetDatabase::InvalidEntryId, AZ::Uuid::CreateString("{0B657D45-A5B0-485B-BF34-0E8779F9A482}"), "Finger_Print"));
  1254. EXPECT_TRUE(m_connection.SetBuilderInfoTable(newEntries));
  1255. // make sure each entry has a number assigned:
  1256. EXPECT_NE(newEntries[0].m_builderInfoID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1257. EXPECT_NE(newEntries[1].m_builderInfoID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1258. EXPECT_TRUE(m_connection.QueryBuilderInfoTable(resultGatherer));
  1259. EXPECT_EQ(results.size(), 2);
  1260. EXPECT_NE(results[0].m_builderInfoID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1261. EXPECT_NE(results[1].m_builderInfoID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1262. // they could be in any order, so fix that first:
  1263. bool isInCorrectOrder = (results[0].m_builderInfoID == newEntries[0].m_builderInfoID) && (results[1].m_builderInfoID == newEntries[1].m_builderInfoID);
  1264. bool isInReverseOrder = (results[1].m_builderInfoID == newEntries[0].m_builderInfoID) && (results[0].m_builderInfoID == newEntries[1].m_builderInfoID);
  1265. EXPECT_TRUE(isInCorrectOrder || isInReverseOrder);
  1266. if (isInReverseOrder)
  1267. {
  1268. BuilderInfoEntry temp = results[0];
  1269. results[0] = results[1];
  1270. results[1] = temp;
  1271. }
  1272. for (size_t idx = 0; idx < 2; ++idx)
  1273. {
  1274. EXPECT_EQ(results[idx].m_builderUuid, newEntries[idx].m_builderUuid);
  1275. EXPECT_EQ(results[idx].m_builderInfoID, newEntries[idx].m_builderInfoID);
  1276. EXPECT_EQ(results[idx].m_analysisFingerprint, newEntries[idx].m_analysisFingerprint);
  1277. }
  1278. // now REPLACE the entries with fewer and make sure it actually chops it down and also replaces the fields.
  1279. newEntries.clear();
  1280. results.clear();
  1281. newEntries.emplace_back(BuilderInfoEntry(AzToolsFramework::AssetDatabase::InvalidEntryId, AZ::Uuid::CreateString("{8863194A-BCB2-4A4C-A7D9-4E90D68814D4}"), "Finger_Print2"));
  1282. EXPECT_TRUE(m_connection.SetBuilderInfoTable(newEntries));
  1283. // make sure each entry has a number assigned:
  1284. EXPECT_NE(newEntries[0].m_builderInfoID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1285. EXPECT_TRUE(m_connection.QueryBuilderInfoTable(resultGatherer));
  1286. EXPECT_EQ(results.size(), 1);
  1287. EXPECT_NE(results[0].m_builderInfoID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1288. EXPECT_EQ(results[0].m_builderUuid, newEntries[0].m_builderUuid);
  1289. EXPECT_EQ(results[0].m_builderInfoID, newEntries[0].m_builderInfoID);
  1290. EXPECT_EQ(results[0].m_analysisFingerprint, newEntries[0].m_analysisFingerprint);
  1291. }
  1292. TEST_F(AssetProcessingStateDataUnitTest, TestSourceDependency_VerifySourceDependency_Succeeds)
  1293. {
  1294. using namespace AzToolsFramework::AssetDatabase;
  1295. // A depends on B, which depends on both C and D
  1296. AZ::Uuid aUuid{ "{B3FCF51E-BDB3-430D-B360-E57913725250}" };
  1297. AZ::Uuid bUuid{ "{E040466C-8B26-4ABB-9E7A-2FF9D1660DB6}" };
  1298. SourceFileDependencyEntry newEntry1; // a depends on B
  1299. newEntry1.m_sourceDependencyID = AzToolsFramework::AssetDatabase::InvalidEntryId;
  1300. newEntry1.m_builderGuid = AZ::Uuid::CreateRandom();
  1301. newEntry1.m_sourceGuid = aUuid;
  1302. newEntry1.m_dependsOnSource = PathOrUuid(bUuid);
  1303. SourceFileDependencyEntry newEntry2; // b depends on C
  1304. newEntry2.m_sourceDependencyID = AzToolsFramework::AssetDatabase::InvalidEntryId;
  1305. newEntry2.m_builderGuid = AZ::Uuid::CreateRandom();
  1306. newEntry2.m_sourceGuid = bUuid;
  1307. newEntry2.m_dependsOnSource = PathOrUuid("c.txt");
  1308. SourceFileDependencyEntry newEntry3; // b also depends on D
  1309. newEntry3.m_sourceDependencyID = AzToolsFramework::AssetDatabase::InvalidEntryId;
  1310. newEntry3.m_builderGuid = AZ::Uuid::CreateRandom();
  1311. newEntry3.m_sourceGuid = bUuid;
  1312. newEntry3.m_dependsOnSource = PathOrUuid("d.txt");
  1313. EXPECT_TRUE(m_connection.SetSourceFileDependency(newEntry1));
  1314. EXPECT_TRUE(m_connection.SetSourceFileDependency(newEntry2));
  1315. EXPECT_TRUE(m_connection.SetSourceFileDependency(newEntry3));
  1316. SourceFileDependencyEntryContainer results;
  1317. // what depends on b? a does.
  1318. EXPECT_TRUE(m_connection.GetSourceFileDependenciesByDependsOnSource(bUuid, "b.txt", "unused", SourceFileDependencyEntry::DEP_Any, results));
  1319. EXPECT_EQ(results.size(), 1);
  1320. EXPECT_EQ(results[0].m_sourceGuid, aUuid);
  1321. EXPECT_EQ(results[0].m_builderGuid, newEntry1.m_builderGuid);
  1322. EXPECT_EQ(results[0].m_sourceDependencyID, newEntry1.m_sourceDependencyID);
  1323. // what does B depend on?
  1324. results.clear();
  1325. EXPECT_TRUE(m_connection.GetDependsOnSourceBySource(bUuid, SourceFileDependencyEntry::DEP_Any, results));
  1326. // b depends on 2 things: c and d
  1327. EXPECT_EQ(results.size(), 2);
  1328. EXPECT_EQ(results[0].m_sourceGuid, bUuid); // note that both of these are B, since its B that has the dependency on the others.
  1329. EXPECT_EQ(results[1].m_sourceGuid, bUuid);
  1330. EXPECT_EQ(results[0].m_dependsOnSource.GetPath(), "c.txt");
  1331. EXPECT_EQ(results[1].m_dependsOnSource.GetPath(), "d.txt");
  1332. // what does b depend on, but filtered to only one builder?
  1333. results.clear();
  1334. EXPECT_TRUE(m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(newEntry2.m_builderGuid, bUuid, SourceFileDependencyEntry::DEP_SourceToSource, results));
  1335. // b depends on 1 thing from that builder: c
  1336. EXPECT_EQ(results.size(), 1);
  1337. EXPECT_EQ(results[0].m_sourceGuid, bUuid);
  1338. EXPECT_EQ(results[0].m_dependsOnSource.GetPath(), "c.txt");
  1339. // make sure that we can look these up by ID (a)
  1340. EXPECT_TRUE(m_connection.GetSourceFileDependencyBySourceDependencyId(newEntry1.m_sourceDependencyID, results[0]));
  1341. EXPECT_EQ(results[0].m_sourceGuid, aUuid);
  1342. EXPECT_EQ(results[0].m_builderGuid, newEntry1.m_builderGuid);
  1343. EXPECT_EQ(results[0].m_sourceDependencyID, newEntry1.m_sourceDependencyID);
  1344. // remove D, b now should only depend on C
  1345. results.clear();
  1346. EXPECT_TRUE(m_connection.RemoveSourceFileDependency(newEntry3.m_sourceDependencyID));
  1347. EXPECT_TRUE(m_connection.GetDependsOnSourceBySource(bUuid, SourceFileDependencyEntry::DEP_Any, results));
  1348. EXPECT_EQ(results.size(), 1);
  1349. EXPECT_EQ(results[0].m_dependsOnSource.GetPath(), "c.txt");
  1350. // clean up
  1351. EXPECT_TRUE(m_connection.RemoveSourceFileDependency(newEntry1.m_sourceDependencyID));
  1352. EXPECT_TRUE(m_connection.RemoveSourceFileDependency(newEntry2.m_sourceDependencyID));
  1353. }
  1354. TEST_F(AssetProcessingStateDataUnitTest, TestSourceFingerprint_QuerySourceAnalysisFingerprint_Succeeds)
  1355. {
  1356. using SourceDatabaseEntry = AzToolsFramework::AssetDatabase::SourceDatabaseEntry;
  1357. AddDefaultSource();
  1358. // Add another source
  1359. AZ::Uuid validSourceGuid = AZ::Uuid::CreateRandom();
  1360. SourceDatabaseEntry source(m_defaultScanFolder.m_scanFolderID, "SomeSource1.tif", validSourceGuid, "54321");
  1361. EXPECT_TRUE(m_connection.SetSource(source));
  1362. AZStd::string resultString("garbage");
  1363. // its not a database error to ask for a file that does not exist:
  1364. EXPECT_TRUE(m_connection.QuerySourceAnalysisFingerprint("does not exist", m_defaultScanFolder.m_scanFolderID, resultString));
  1365. // but we do expect it to empty the result:
  1366. EXPECT_TRUE(resultString.empty());
  1367. EXPECT_TRUE(m_connection.QuerySourceAnalysisFingerprint("SomeSource.tif", m_defaultScanFolder.m_scanFolderID, resultString));
  1368. EXPECT_EQ(resultString, "12345");
  1369. EXPECT_TRUE(m_connection.QuerySourceAnalysisFingerprint("SomeSource1.tif", m_defaultScanFolder.m_scanFolderID, resultString));
  1370. EXPECT_EQ(resultString, "54321");
  1371. }
  1372. }