AssetDatabaseTest.cpp 133 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667
  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/std/smart_ptr/unique_ptr.h>
  9. #include <AzToolsFramework/API/AssetDatabaseBus.h>
  10. #include <AzCore/std/sort.h>
  11. #include <native/tests/AssetProcessorTest.h>
  12. #include <native/tests/MockAssetDatabaseRequestsHandler.h>
  13. #include <native/AssetDatabase/AssetDatabase.h>
  14. #include <AzToolsFramework/AssetDatabase/PathOrUuid.h>
  15. namespace UnitTests
  16. {
  17. using namespace testing;
  18. using namespace AssetProcessor;
  19. using namespace AzToolsFramework::AssetDatabase;
  20. using AzToolsFramework::AssetDatabase::ProductDatabaseEntry;
  21. using AzToolsFramework::AssetDatabase::ScanFolderDatabaseEntry;
  22. using AzToolsFramework::AssetDatabase::SourceDatabaseEntry;
  23. using AzToolsFramework::AssetDatabase::SourceFileDependencyEntry;
  24. using AzToolsFramework::AssetDatabase::SourceFileDependencyEntryContainer;
  25. using AzToolsFramework::AssetDatabase::JobDatabaseEntry;
  26. using AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer;
  27. using AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry;
  28. using AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer;
  29. using AzToolsFramework::AssetDatabase::AssetDatabaseConnection;
  30. using AzToolsFramework::AssetDatabase::FileDatabaseEntry;
  31. using AzToolsFramework::AssetDatabase::StatDatabaseEntry;
  32. using AzToolsFramework::AssetDatabase::StatDatabaseEntryContainer;
  33. class AssetDatabaseTest : public AssetProcessorTest
  34. {
  35. public:
  36. void SetUp() override
  37. {
  38. AssetProcessorTest::SetUp();
  39. m_data.reset(new StaticData());
  40. m_data->m_databaseLocationListener.m_assetDatabasePath = ":memory:"; // this special string causes SQLITE to open the database in memory and not touch disk at all.
  41. // Initialize the database:
  42. m_data->m_connection.ClearData(); // this is expected to reset/clear/reopen
  43. }
  44. void TearDown() override
  45. {
  46. m_data.reset();
  47. AssetProcessorTest::TearDown();
  48. }
  49. // COVERAGE TEST
  50. // For each of these coverage tests we'll start with the same kind of database, one with
  51. // SCAN FOLDER: rootportkey
  52. // SOURCE: somefile.tif
  53. // JOB: "some job key" runkey: 1 "pc" SUCCEEDED
  54. // Product: "someproduct1.dds" subid: 1
  55. // Product: "someproduct2.dds" subid: 2
  56. // SOURCE: otherfile.tif
  57. // JOB: "some other job key" runkey: 2 "osx" FAILED
  58. // Product: "someproduct3.dds" subid: 3
  59. // Product: "someproduct4.dds" subid: 4
  60. void CreateCoverageTestData()
  61. {
  62. m_data->m_scanFolder = { "c:/O3DE/dev", "dev", "rootportkey" };
  63. ASSERT_TRUE(m_data->m_connection.SetScanFolder(m_data->m_scanFolder));
  64. m_data->m_sourceFile1 = { m_data->m_scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "AnalysisFingerprint1"};
  65. m_data->m_sourceFile2 = { m_data->m_scanFolder.m_scanFolderID, "otherfile.tif", AZ::Uuid::CreateRandom(), "AnalysisFingerprint2"};
  66. ASSERT_TRUE(m_data->m_connection.SetSource(m_data->m_sourceFile1));
  67. ASSERT_TRUE(m_data->m_connection.SetSource(m_data->m_sourceFile2));
  68. m_data->m_job1 = { m_data->m_sourceFile1.m_sourceID, "some job key", 123, "pc", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, 1 };
  69. m_data->m_job2 = { m_data->m_sourceFile2.m_sourceID, "some other job key", 345, "osx", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Failed, 2 };
  70. ASSERT_TRUE(m_data->m_connection.SetJob(m_data->m_job1));
  71. ASSERT_TRUE(m_data->m_connection.SetJob(m_data->m_job2));
  72. m_data->m_product1 = { m_data->m_job1.m_jobID, 1, "someproduct1.dds", AZ::Data::AssetType::CreateRandom() };
  73. m_data->m_product2 = { m_data->m_job1.m_jobID, 2, "someproduct2.dds", AZ::Data::AssetType::CreateRandom() };
  74. m_data->m_product3 = { m_data->m_job2.m_jobID, 3, "someproduct3.dds", AZ::Data::AssetType::CreateRandom() };
  75. m_data->m_product4 = { m_data->m_job2.m_jobID, 4, "someproduct4.dds", AZ::Data::AssetType::CreateRandom() };
  76. ASSERT_TRUE(m_data->m_connection.SetProduct(m_data->m_product1));
  77. ASSERT_TRUE(m_data->m_connection.SetProduct(m_data->m_product2));
  78. ASSERT_TRUE(m_data->m_connection.SetProduct(m_data->m_product3));
  79. ASSERT_TRUE(m_data->m_connection.SetProduct(m_data->m_product4));
  80. }
  81. /******************************************** Create and insert Stat entry ********************************************/
  82. //! Returns the first stat entry to be inserted into Stats table. Users can specify the prefix of the StatName
  83. StatDatabaseEntry GetFirstStatEntry(const AZStd::string& namePrefix = "")
  84. {
  85. return StatDatabaseEntry{ namePrefix + "a", 10, 100 };
  86. }
  87. //! Step statEntry to the next inserted entry, which increments the name's last character by 1 in ASCII order, increment 20 in StatValue, and increment
  88. //! 300 in LastLogTime. For example, if statEntry was passed in as (StatName=b, StatValue=30, LastLogTime=400), it will become
  89. //! (StatName=c, StatValue=50, LastLogTime=700) after the invocation.
  90. void StepStatEntry(StatDatabaseEntry& statEntry)
  91. {
  92. statEntry.m_statName.back()++;
  93. statEntry.m_statValue = statEntry.m_statValue + 20;
  94. statEntry.m_lastLogTime = statEntry.m_lastLogTime + 300;
  95. }
  96. //! Insert _StatCount_ stat entries into Stats table, starting with first entry given by GetFirstStatEntry().
  97. void InsertStatsTestData(const unsigned int StatCount, const AZStd::string& namePrefix = "")
  98. {
  99. StatDatabaseEntry statEntry = GetFirstStatEntry(namePrefix);
  100. for (unsigned int i = 0; i < StatCount; ++i)
  101. {
  102. ASSERT_TRUE(m_data->m_connection.ReplaceStat(statEntry));
  103. StepStatEntry(statEntry);
  104. }
  105. }
  106. protected:
  107. void SetAndCheckMissingDependency(
  108. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& updatedMissingDependency,
  109. const AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& originalMissingDependency);
  110. struct StaticData
  111. {
  112. // these variables are created during SetUp() and destroyed during TearDown() and thus are always available during tests using this fixture:
  113. AZStd::string m_databaseLocation;
  114. AssetProcessor::MockAssetDatabaseRequestsHandler m_databaseLocationListener;
  115. AssetProcessor::AssetDatabaseConnection m_connection;
  116. // The following database entry variables are initialized only when you call coverage test data CreateCoverageTestData().
  117. // Tests which don't need or want a pre-made database should not call CreateCoverageTestData() but note that in that case
  118. // these entries will be empty and their identifiers will be -1.
  119. ScanFolderDatabaseEntry m_scanFolder;
  120. SourceDatabaseEntry m_sourceFile1;
  121. SourceDatabaseEntry m_sourceFile2;
  122. JobDatabaseEntry m_job1;
  123. JobDatabaseEntry m_job2;
  124. ProductDatabaseEntry m_product1;
  125. ProductDatabaseEntry m_product2;
  126. ProductDatabaseEntry m_product3;
  127. ProductDatabaseEntry m_product4;
  128. };
  129. // we store the above data in a unique_ptr so that its memory can be cleared during TearDown() in one call, before we destroy the memory
  130. // allocator, reducing the chance of missing or forgetting to destroy one in the future.
  131. AZStd::unique_ptr<StaticData> m_data;
  132. };
  133. TEST_F(AssetDatabaseTest, UpdateJob_Succeeds)
  134. {
  135. using namespace AzToolsFramework::AssetDatabase;
  136. CreateCoverageTestData();
  137. m_data->m_job1.m_warningCount = 11;
  138. m_data->m_job1.m_errorCount = 22;
  139. ASSERT_TRUE(m_data->m_connection.SetJob(m_data->m_job1));
  140. JobDatabaseEntryContainer jobs;
  141. ASSERT_TRUE(m_data->m_connection.GetJobsBySourceID(m_data->m_job1.m_sourcePK, jobs));
  142. ASSERT_EQ(jobs.size(), 1);
  143. ASSERT_EQ(m_data->m_job1, jobs[0]);
  144. }
  145. TEST_F(AssetDatabaseTest, GetProducts_WithEmptyDatabase_Fails_ReturnsNoProducts)
  146. {
  147. ProductDatabaseEntryContainer products;
  148. EXPECT_FALSE(m_data->m_connection.GetProducts(products));
  149. EXPECT_EQ(products.size(), 0);
  150. }
  151. TEST_F(AssetDatabaseTest, GetProductByProductID_NotFound_Fails_ReturnsNoProducts)
  152. {
  153. AzToolsFramework::AssetDatabase::ProductDatabaseEntry product;
  154. EXPECT_FALSE(m_data->m_connection.GetProductByProductID(3443, product));
  155. EXPECT_EQ(product, AzToolsFramework::AssetDatabase::ProductDatabaseEntry());
  156. }
  157. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_NotFound_Fails_ReturnsNoProducts)
  158. {
  159. ProductDatabaseEntryContainer products;
  160. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("none", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, products));
  161. EXPECT_EQ(products.size(), 0);
  162. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("none", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, products));
  163. EXPECT_EQ(products.size(), 0);
  164. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("none", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::EndsWith, products));
  165. EXPECT_EQ(products.size(), 0);
  166. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("none", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Matches, products));
  167. EXPECT_EQ(products.size(), 0);
  168. }
  169. TEST_F(AssetDatabaseTest, GetProductsBySourceID_NotFound_Fails_ReturnsNoProducts)
  170. {
  171. ProductDatabaseEntryContainer products;
  172. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(25654, products));
  173. EXPECT_EQ(products.size(), 0);
  174. }
  175. TEST_F(AssetDatabaseTest, SetProduct_InvalidProductID_Fails)
  176. {
  177. // trying to "overwrite" a product that does not exist should fail and emit error.
  178. AZ::Data::AssetType validAssetType1 = AZ::Data::AssetType::CreateRandom();
  179. ProductDatabaseEntry product { 123213, 234234, 1, "SomeProduct1.dds", validAssetType1 };
  180. m_errorAbsorber->Clear();
  181. EXPECT_FALSE(m_data->m_connection.SetProduct(product));
  182. EXPECT_GT(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  183. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  184. // make sure it didn't actually touch the db as a side effect:
  185. ProductDatabaseEntryContainer products;
  186. EXPECT_FALSE(m_data->m_connection.GetProducts(products));
  187. EXPECT_EQ(products.size(), 0);
  188. }
  189. TEST_F(AssetDatabaseTest, SetProduct_InvalidJobPK_Fails)
  190. {
  191. AZ::Data::AssetType validAssetType1 = AZ::Data::AssetType::CreateRandom();
  192. // -1 means insert a new product, but the JobPK is an enforced FK constraint, so this should fail since there
  193. // won't be a Job with the PK of 234234.
  194. ProductDatabaseEntry product{ AzToolsFramework::AssetDatabase::InvalidEntryId, 234234, 1, "SomeProduct1.dds", validAssetType1 };
  195. m_errorAbsorber->Clear();
  196. EXPECT_FALSE(m_data->m_connection.SetProduct(product));
  197. EXPECT_GT(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  198. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  199. // make sure it didn't actually touch the db as a side effect:
  200. ProductDatabaseEntryContainer products;
  201. EXPECT_FALSE(m_data->m_connection.GetProducts(products));
  202. EXPECT_EQ(products.size(), 0);
  203. }
  204. // if we give it a valid command and a -1 product, we expect it to succeed without assert or warning
  205. // and we expect it to tell us (by filling in the entry) what the new PK is.
  206. TEST_F(AssetDatabaseTest, SetProduct_AutoPK_Succeeds)
  207. {
  208. AZ::Data::AssetType validAssetType1 = AZ::Data::AssetType::CreateRandom();
  209. // to add a product legitimately you have to have a full chain of primary keys, chain is:
  210. // ScanFolder --> Source --> job --> product.
  211. // we'll create all of those first (except product) before starting the product test.
  212. //add a scanfolder. None of this has to exist in real disk, this is a db test only.
  213. ScanFolderDatabaseEntry scanFolder{ "c:/O3DE/dev", "dev", "rootportkey" };
  214. EXPECT_TRUE(m_data->m_connection.SetScanFolder(scanFolder));
  215. ASSERT_NE(scanFolder.m_scanFolderID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  216. SourceDatabaseEntry sourceEntry {scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "fingerprint1"};
  217. EXPECT_TRUE(m_data->m_connection.SetSource(sourceEntry));
  218. ASSERT_NE(sourceEntry.m_sourceID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  219. JobDatabaseEntry jobEntry{ sourceEntry.m_sourceID, "some job key", 123, "pc", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, 1 };
  220. EXPECT_TRUE(m_data->m_connection.SetJob(jobEntry));
  221. ASSERT_NE(jobEntry.m_jobID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  222. // --- set up complete --- perform the test!
  223. AZStd::bitset<64> flags;
  224. flags.set(static_cast<int>(AssetBuilderSDK::ProductOutputFlags::IntermediateAsset | AssetBuilderSDK::ProductOutputFlags::ProductAsset));
  225. ProductDatabaseEntry product{ AzToolsFramework::AssetDatabase::InvalidEntryId, jobEntry.m_jobID, 1, "SomeProduct1.dds", validAssetType1,
  226. AZ::Uuid::CreateNull(), 0, flags};
  227. m_errorAbsorber->Clear();
  228. EXPECT_TRUE(m_data->m_connection.SetProduct(product));
  229. ASSERT_NE(product.m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  230. EXPECT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0);
  231. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  232. // read it back from the DB and make sure its identical to what was written
  233. ProductDatabaseEntry productFromDB;
  234. EXPECT_TRUE(m_data->m_connection.GetProductByProductID(product.m_productID, productFromDB));
  235. ASSERT_EQ(product, productFromDB);
  236. }
  237. // update an existing job by giving it a specific PK of a known existing item.
  238. TEST_F(AssetDatabaseTest, SetProduct_SpecificPK_Succeeds_DifferentSubID)
  239. {
  240. AZ::Data::AssetType validAssetType1 = AZ::Data::AssetType::CreateRandom();
  241. // to add a product legitimately you have to have a full chain of primary keys, chain is:
  242. // ScanFolder --> Source --> job --> product.
  243. // we'll create all of those first (except product) before starting the product test.
  244. ScanFolderDatabaseEntry scanFolder{ "c:/O3DE/dev", "dev", "rootportkey" };
  245. ASSERT_TRUE(m_data->m_connection.SetScanFolder(scanFolder));
  246. SourceDatabaseEntry sourceEntry{ scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "fingerprint1" };
  247. ASSERT_TRUE(m_data->m_connection.SetSource(sourceEntry));
  248. // two different job entries.
  249. JobDatabaseEntry jobEntry{ sourceEntry.m_sourceID, "some job key", 123, "pc", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, 1 };
  250. JobDatabaseEntry jobEntry2{ sourceEntry.m_sourceID, "some job key 2", 345, "pc", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, 2 };
  251. ASSERT_TRUE(m_data->m_connection.SetJob(jobEntry));
  252. ASSERT_TRUE(m_data->m_connection.SetJob(jobEntry2));
  253. AZStd::bitset<64> flags;
  254. flags.set(static_cast<int>(AssetBuilderSDK::ProductOutputFlags::ProductAsset));
  255. ProductDatabaseEntry product{ AzToolsFramework::AssetDatabase::InvalidEntryId, jobEntry.m_jobID, 1, "SomeProduct1.dds", validAssetType1,
  256. AZ::Uuid::CreateNull(), 0, flags};
  257. ASSERT_TRUE(m_data->m_connection.SetProduct(product));
  258. // --- set up complete --- perform the test!
  259. // update all the fields of that product and then write it to the db.
  260. ProductDatabaseEntry newProductData = product; // copy first
  261. // now change all the fields:
  262. newProductData.m_assetType = AZ::Uuid::CreateRandom();
  263. newProductData.m_productName = "different name.dds";
  264. newProductData.m_subID = 2;
  265. newProductData.m_jobPK = jobEntry2.m_jobID; // move it to the other job, too!
  266. newProductData.m_flags.set(static_cast<int>(AssetBuilderSDK::ProductOutputFlags::IntermediateAsset));
  267. // update the product
  268. EXPECT_TRUE(m_data->m_connection.SetProduct(newProductData));
  269. ASSERT_NE(newProductData.m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  270. // it should not have entered a new product but instead overwritten the old one.
  271. ASSERT_EQ(product.m_productID, newProductData.m_productID);
  272. // read it back from DB and verify:
  273. ProductDatabaseEntry productFromDB;
  274. EXPECT_TRUE(m_data->m_connection.GetProductByProductID(newProductData.m_productID, productFromDB));
  275. ASSERT_EQ(newProductData, productFromDB);
  276. ProductDatabaseEntryContainer products;
  277. EXPECT_TRUE(m_data->m_connection.GetProducts(products));
  278. EXPECT_EQ(products.size(), 1);
  279. }
  280. // update an existing job by giving it a subID and JobID which is enough to uniquely identify a product (since products may not have the same subid from the same job).
  281. // this is actually a very common case (same job id, same subID)
  282. TEST_F(AssetDatabaseTest, SetProduct_SpecificPK_Succeeds_SameSubID_SameJobID)
  283. {
  284. ScanFolderDatabaseEntry scanFolder{ "c:/O3DE/dev", "dev", "rootportkey"};
  285. ASSERT_TRUE(m_data->m_connection.SetScanFolder(scanFolder));
  286. SourceDatabaseEntry sourceEntry{ scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "fingerprint1" };
  287. ASSERT_TRUE(m_data->m_connection.SetSource(sourceEntry));
  288. JobDatabaseEntry jobEntry{ sourceEntry.m_sourceID, "some job key", 123, "pc", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, 1 };
  289. ASSERT_TRUE(m_data->m_connection.SetJob(jobEntry));
  290. ProductDatabaseEntry product{ AzToolsFramework::AssetDatabase::InvalidEntryId, jobEntry.m_jobID, 1, "SomeProduct1.dds", AZ::Data::AssetType::CreateRandom() };
  291. ASSERT_TRUE(m_data->m_connection.SetProduct(product));
  292. // --- set up complete --- perform the test!
  293. // update all the fields of that product and then write it to the db.
  294. ProductDatabaseEntry newProductData = product; // copy first
  295. // now change all the fields:
  296. newProductData.m_assetType = AZ::Uuid::CreateRandom();
  297. newProductData.m_productName = "different name.dds";
  298. newProductData.m_productID = AzToolsFramework::AssetDatabase::InvalidEntryId; // wipe out the product ID, so that we can make sure it returns it.
  299. // we don't change the subID here or the job ID.
  300. // update the product
  301. EXPECT_TRUE(m_data->m_connection.SetProduct(newProductData));
  302. ASSERT_NE(newProductData.m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  303. // it should not have entered a new product but instead overwritten the old one.
  304. EXPECT_EQ(product.m_productID, newProductData.m_productID);
  305. // read it back from DB and verify:
  306. ProductDatabaseEntry productFromDB;
  307. EXPECT_TRUE(m_data->m_connection.GetProductByProductID(newProductData.m_productID, productFromDB));
  308. EXPECT_EQ(newProductData, productFromDB);
  309. ProductDatabaseEntryContainer products;
  310. EXPECT_TRUE(m_data->m_connection.GetProducts(products));
  311. EXPECT_EQ(products.size(), 1);
  312. }
  313. TEST_F(AssetDatabaseTest, GetProductsByJobID_InvalidID_NotFound_ReturnsFalse)
  314. {
  315. CreateCoverageTestData();
  316. ProductDatabaseEntryContainer resultProducts;
  317. EXPECT_FALSE(m_data->m_connection.GetProductsByJobID(-1, resultProducts));
  318. EXPECT_EQ(resultProducts.size(), 0);
  319. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  320. }
  321. TEST_F(AssetDatabaseTest, GetProductsByJobID_Valid_ReturnsTrue_FindsProducts)
  322. {
  323. CreateCoverageTestData();
  324. ProductDatabaseEntryContainer resultProducts;
  325. EXPECT_TRUE(m_data->m_connection.GetProductsByJobID(m_data->m_job1.m_jobID, resultProducts));
  326. EXPECT_EQ(resultProducts.size(), 2); // should have found the first two products.
  327. // since there is no ordering, we just have to find both of them:
  328. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  329. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  330. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  331. }
  332. TEST_F(AssetDatabaseTest, GetProductByJobIDSubId_InvalidID_NotFound_ReturnsFalse)
  333. {
  334. CreateCoverageTestData();
  335. ProductDatabaseEntry resultProduct;
  336. EXPECT_FALSE(m_data->m_connection.GetProductByJobIDSubId(m_data->m_job1.m_jobID, aznumeric_caster(-1), resultProduct));
  337. EXPECT_FALSE(m_data->m_connection.GetProductByJobIDSubId(-1, m_data->m_product1.m_subID, resultProduct));
  338. EXPECT_FALSE(m_data->m_connection.GetProductByJobIDSubId(-1, aznumeric_caster(-1), resultProduct));
  339. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  340. }
  341. TEST_F(AssetDatabaseTest, GetProductByJobIDSubId_ValidID_Found_ReturnsTrue)
  342. {
  343. CreateCoverageTestData();
  344. ProductDatabaseEntry resultProduct;
  345. EXPECT_TRUE(m_data->m_connection.GetProductByJobIDSubId(m_data->m_job1.m_jobID, m_data->m_product1.m_subID, resultProduct));
  346. EXPECT_EQ(resultProduct, m_data->m_product1);
  347. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  348. }
  349. TEST_F(AssetDatabaseTest, GetProductBySourceGuidSubId_InvalidInputs_ProductNotFound)
  350. {
  351. CreateCoverageTestData();
  352. ProductDatabaseEntry resultProduct;
  353. AZ::Uuid invalidGuid = AZ::Uuid::CreateNull();
  354. AZ::s32 invalidSubId = -1;
  355. EXPECT_FALSE(m_data->m_connection.GetProductBySourceGuidSubId(invalidGuid, m_data->m_product1.m_subID, resultProduct));
  356. EXPECT_FALSE(m_data->m_connection.GetProductBySourceGuidSubId(m_data->m_sourceFile1.m_sourceGuid, invalidSubId, resultProduct));
  357. EXPECT_FALSE(m_data->m_connection.GetProductBySourceGuidSubId(invalidGuid, invalidSubId, resultProduct));
  358. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0);
  359. }
  360. TEST_F(AssetDatabaseTest, GetProductBySourceGuidSubId_ValidInputs_ProductFound)
  361. {
  362. CreateCoverageTestData();
  363. ProductDatabaseEntry resultProduct;
  364. EXPECT_TRUE(m_data->m_connection.GetProductBySourceGuidSubId(m_data->m_sourceFile1.m_sourceGuid, m_data->m_product1.m_subID, resultProduct));
  365. EXPECT_EQ(resultProduct, m_data->m_product1);
  366. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0);
  367. }
  368. // --------------------------------------------------------------------------------------------------------------------
  369. // ------------------------------------------ GetProductsByProductName ------------------------------------------------
  370. // --------------------------------------------------------------------------------------------------------------------
  371. TEST_F(AssetDatabaseTest, GetProductsByProductName_EmptyString_NoResults)
  372. {
  373. CreateCoverageTestData();
  374. ProductDatabaseEntryContainer resultProducts;
  375. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName(QString(), resultProducts));
  376. EXPECT_EQ(resultProducts.size(), 0);
  377. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  378. }
  379. TEST_F(AssetDatabaseTest, GetProductsByProductName_NotFound_NoResult)
  380. {
  381. CreateCoverageTestData();
  382. ProductDatabaseEntryContainer resultProducts;
  383. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("akdsuhuksahdsak", resultProducts));
  384. EXPECT_EQ(resultProducts.size(), 0);
  385. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  386. }
  387. TEST_F(AssetDatabaseTest, GetProductsByProductName_CorrectName_ReturnsCorrectResult)
  388. {
  389. CreateCoverageTestData();
  390. ProductDatabaseEntryContainer resultProducts;
  391. EXPECT_TRUE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts));
  392. EXPECT_EQ(resultProducts.size(), 1);
  393. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  394. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  395. }
  396. // tests all of the filters (beside name) to make sure they all function as expected.
  397. TEST_F(AssetDatabaseTest, GetProductsByProductName_FilterTest_BuilderGUID)
  398. {
  399. CreateCoverageTestData();
  400. ProductDatabaseEntryContainer resultProducts;
  401. // give it a random builder guid. This should make it not match any products:
  402. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateRandom()));
  403. EXPECT_EQ(resultProducts.size(), 0);
  404. // give it a correct builder guid but the wrong builder. Job2's builder actually built product4.
  405. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, m_data->m_job1.m_builderGuid));
  406. EXPECT_EQ(resultProducts.size(), 0);
  407. // give it correct data
  408. EXPECT_TRUE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, m_data->m_job2.m_builderGuid));
  409. EXPECT_EQ(resultProducts.size(), 1);
  410. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  411. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  412. }
  413. TEST_F(AssetDatabaseTest, GetProductsByProductName_FilterTest_JobKey)
  414. {
  415. CreateCoverageTestData();
  416. ProductDatabaseEntryContainer resultProducts;
  417. // give it a random job key that is not going to match the existing job keys. This should make it not match any products:
  418. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), "no matcher"));
  419. EXPECT_EQ(resultProducts.size(), 0);
  420. // give it a correct job key but not one that output that product.
  421. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job1.m_jobKey.c_str())));
  422. EXPECT_EQ(resultProducts.size(), 0);
  423. // give it correct data
  424. EXPECT_TRUE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job2.m_jobKey.c_str())));
  425. EXPECT_EQ(resultProducts.size(), 1);
  426. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  427. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  428. }
  429. TEST_F(AssetDatabaseTest, GetProductsByProductName_FilterTest_Platform)
  430. {
  431. CreateCoverageTestData();
  432. ProductDatabaseEntryContainer resultProducts;
  433. // give it a platform that is not going to match the existing job platforms. This should make it not match any products:
  434. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(), "badplatform"));
  435. EXPECT_EQ(resultProducts.size(), 0);
  436. // give it a correct platform but not one that output that product.
  437. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(), "pc")); // its actually osx
  438. EXPECT_EQ(resultProducts.size(), 0);
  439. // give it correct data
  440. EXPECT_TRUE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(), "osx"));
  441. EXPECT_EQ(resultProducts.size(), 1);
  442. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  443. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  444. }
  445. TEST_F(AssetDatabaseTest, GetProductsByProductName_FilterTest_Status)
  446. {
  447. CreateCoverageTestData();
  448. ProductDatabaseEntryContainer resultProducts;
  449. // give it a correct status but not one that output that product.
  450. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed)); // its actually failed
  451. EXPECT_EQ(resultProducts.size(), 0);
  452. // give it correct data
  453. EXPECT_TRUE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Failed));
  454. EXPECT_EQ(resultProducts.size(), 1);
  455. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  456. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  457. }
  458. // --------------------------------------------------------------------------------------------------------------------
  459. // ------------------------------------------ GetProductsLikeProductName ----------------------------------------------
  460. // --------------------------------------------------------------------------------------------------------------------
  461. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_EmptyString_NoResults)
  462. {
  463. CreateCoverageTestData();
  464. ProductDatabaseEntryContainer resultProducts;
  465. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName(QString(), AssetDatabaseConnection::StartsWith, resultProducts));
  466. EXPECT_EQ(resultProducts.size(), 0);
  467. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  468. }
  469. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_NotFound_NoResult)
  470. {
  471. CreateCoverageTestData();
  472. ProductDatabaseEntryContainer resultProducts;
  473. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("akdsuhuksahdsak", AssetDatabaseConnection::StartsWith, resultProducts));
  474. EXPECT_EQ(resultProducts.size(), 0);
  475. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  476. }
  477. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_CorrectName_StartsWith_ReturnsCorrectResult)
  478. {
  479. CreateCoverageTestData();
  480. ProductDatabaseEntryContainer resultProducts;
  481. EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts));
  482. EXPECT_EQ(resultProducts.size(), 1);
  483. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  484. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  485. }
  486. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_CorrectName_EndsWith_ReturnsCorrectResult)
  487. {
  488. CreateCoverageTestData();
  489. ProductDatabaseEntryContainer resultProducts;
  490. EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("product4.dds", AssetDatabaseConnection::EndsWith, resultProducts));
  491. EXPECT_EQ(resultProducts.size(), 1);
  492. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  493. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  494. }
  495. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_CorrectName_Matches_ReturnsCorrectResult)
  496. {
  497. CreateCoverageTestData();
  498. ProductDatabaseEntryContainer resultProducts;
  499. EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("product4", AssetDatabaseConnection::Matches, resultProducts));
  500. EXPECT_EQ(resultProducts.size(), 1);
  501. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  502. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  503. }
  504. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_CorrectName_StartsWith_ReturnsMany)
  505. {
  506. CreateCoverageTestData();
  507. ProductDatabaseEntryContainer resultProducts;
  508. // a very broad search that matches all products.
  509. EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct", AssetDatabaseConnection::StartsWith, resultProducts));
  510. EXPECT_EQ(resultProducts.size(), 4);
  511. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  512. }
  513. // tests all of the filters (beside name) to make sure they all function as expected.
  514. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_FilterTest_BuilderGUID)
  515. {
  516. CreateCoverageTestData();
  517. ProductDatabaseEntryContainer resultProducts;
  518. // give it a random builder guid. This should make it not match any products:
  519. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateRandom()));
  520. EXPECT_EQ(resultProducts.size(), 0);
  521. // give it a correct builder guid but the wrong builder. Job2's builder actually built product4.
  522. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, m_data->m_job1.m_builderGuid));
  523. EXPECT_EQ(resultProducts.size(), 0);
  524. // give it correct data
  525. EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, m_data->m_job2.m_builderGuid));
  526. EXPECT_EQ(resultProducts.size(), 1);
  527. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  528. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  529. }
  530. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_FilterTest_JobKey)
  531. {
  532. CreateCoverageTestData();
  533. ProductDatabaseEntryContainer resultProducts;
  534. // give it a random job key that is not going to match the existing job keys. This should make it not match any products:
  535. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), "no matcher"));
  536. EXPECT_EQ(resultProducts.size(), 0);
  537. // give it a correct job key but not one that output that product.
  538. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job1.m_jobKey.c_str())));
  539. EXPECT_EQ(resultProducts.size(), 0);
  540. // give it correct data
  541. EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job2.m_jobKey.c_str())));
  542. EXPECT_EQ(resultProducts.size(), 1);
  543. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  544. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  545. }
  546. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_FilterTest_Platform)
  547. {
  548. CreateCoverageTestData();
  549. ProductDatabaseEntryContainer resultProducts;
  550. // give it a platform that is not going to match the existing job platforms. This should make it not match any products:
  551. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "badplatform"));
  552. EXPECT_EQ(resultProducts.size(), 0);
  553. // give it a correct platform but not one that output that product.
  554. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "pc")); // its actually osx
  555. EXPECT_EQ(resultProducts.size(), 0);
  556. // give it correct data
  557. EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "osx"));
  558. EXPECT_EQ(resultProducts.size(), 1);
  559. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  560. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  561. }
  562. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_FilterTest_Status)
  563. {
  564. CreateCoverageTestData();
  565. ProductDatabaseEntryContainer resultProducts;
  566. // give it a correct status but not one that output that product.
  567. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed)); // its actually failed
  568. EXPECT_EQ(resultProducts.size(), 0);
  569. // give it correct data
  570. EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Failed));
  571. EXPECT_EQ(resultProducts.size(), 1);
  572. EXPECT_EQ(resultProducts[0], m_data->m_product4);
  573. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  574. }
  575. // --------------------------------------------------------------------------------------------------------------------
  576. // --------------------------------------------- GetProductsBySourceID ------------------------------------------------
  577. // --------------------------------------------------------------------------------------------------------------------
  578. TEST_F(AssetDatabaseTest, GetProductsBySourceID_NotFound_NoResult)
  579. {
  580. CreateCoverageTestData();
  581. ProductDatabaseEntryContainer resultProducts;
  582. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(-1, resultProducts));
  583. EXPECT_EQ(resultProducts.size(), 0);
  584. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  585. }
  586. TEST_F(AssetDatabaseTest, GetProductsBySourceID_CorrectID_ReturnsCorrectResult)
  587. {
  588. CreateCoverageTestData();
  589. ProductDatabaseEntryContainer resultProducts;
  590. EXPECT_TRUE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts));
  591. EXPECT_EQ(resultProducts.size(), 2);
  592. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  593. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  594. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  595. }
  596. // tests all of the filters (beside name) to make sure they all function as expected.
  597. TEST_F(AssetDatabaseTest, GetProductsBySourceID_FilterTest_BuilderGUID)
  598. {
  599. CreateCoverageTestData();
  600. ProductDatabaseEntryContainer resultProducts;
  601. // give it a random builder guid. This should make it not match any products:
  602. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateRandom()));
  603. EXPECT_EQ(resultProducts.size(), 0);
  604. // give it a valid data, but the wrong one. Note that job2 was the one that built the other files, not the sourcefile1.
  605. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, m_data->m_job2.m_builderGuid));
  606. EXPECT_EQ(resultProducts.size(), 0);
  607. // give it correct data
  608. EXPECT_TRUE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, m_data->m_job1.m_builderGuid));
  609. EXPECT_EQ(resultProducts.size(), 2);
  610. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  611. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  612. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  613. }
  614. TEST_F(AssetDatabaseTest, GetProductsBySourceID_FilterTest_JobKey)
  615. {
  616. CreateCoverageTestData();
  617. ProductDatabaseEntryContainer resultProducts;
  618. // give it invalid data that won't match anything
  619. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), "no matcher"));
  620. EXPECT_EQ(resultProducts.size(), 0);
  621. // give it a valid data, but the wrong one:
  622. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job2.m_jobKey.c_str())));
  623. EXPECT_EQ(resultProducts.size(), 0);
  624. // give it correct data
  625. EXPECT_TRUE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job1.m_jobKey.c_str())));
  626. EXPECT_EQ(resultProducts.size(), 2);
  627. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  628. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  629. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  630. }
  631. TEST_F(AssetDatabaseTest, GetProductsBySourceID_FilterTest_Platform)
  632. {
  633. CreateCoverageTestData();
  634. ProductDatabaseEntryContainer resultProducts;
  635. // give it invalid data that won't match anything
  636. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(), "badplatform"));
  637. EXPECT_EQ(resultProducts.size(), 0);
  638. // give it a valid data, but the wrong one:
  639. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(), "osx")); // its actually pc
  640. EXPECT_EQ(resultProducts.size(), 0);
  641. // give it correct data
  642. EXPECT_TRUE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(), "pc"));
  643. EXPECT_EQ(resultProducts.size(), 2);
  644. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  645. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  646. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  647. }
  648. TEST_F(AssetDatabaseTest, GetProductsBySourceID_FilterTest_Status)
  649. {
  650. CreateCoverageTestData();
  651. ProductDatabaseEntryContainer resultProducts;
  652. // give it a valid data, but the wrong one:
  653. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Failed)); // its actually completed
  654. EXPECT_EQ(resultProducts.size(), 0);
  655. // give it correct data
  656. EXPECT_TRUE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed));
  657. EXPECT_EQ(resultProducts.size(), 2);
  658. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  659. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  660. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  661. }
  662. // --------------------------------------------------------------------------------------------------------------------
  663. // -------------------------------------------- GetProductsBySourceName -----------------------------------------------
  664. // --------------------------------------------------------------------------------------------------------------------
  665. TEST_F(AssetDatabaseTest, GetProductsBySourceName_EmptyString_NoResult)
  666. {
  667. CreateCoverageTestData();
  668. ProductDatabaseEntryContainer resultProducts;
  669. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName(QString(), resultProducts));
  670. EXPECT_EQ(resultProducts.size(), 0);
  671. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  672. }
  673. TEST_F(AssetDatabaseTest, GetProductsBySourceName_NotFound_NoResult)
  674. {
  675. CreateCoverageTestData();
  676. ProductDatabaseEntryContainer resultProducts;
  677. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("blahrga", resultProducts));
  678. EXPECT_EQ(resultProducts.size(), 0);
  679. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  680. }
  681. TEST_F(AssetDatabaseTest, GetProductsBySourceName_CorrectName_ReturnsCorrectResult)
  682. {
  683. CreateCoverageTestData();
  684. ProductDatabaseEntryContainer resultProducts;
  685. EXPECT_TRUE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts)); // this is source1, which results in product1 and product2 via job1
  686. EXPECT_EQ(resultProducts.size(), 2);
  687. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  688. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  689. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  690. }
  691. // tests all of the filters (beside name) to make sure they all function as expected.
  692. TEST_F(AssetDatabaseTest, GetProductsBySourceName_FilterTest_BuilderGUID)
  693. {
  694. CreateCoverageTestData();
  695. ProductDatabaseEntryContainer resultProducts;
  696. // give it a random builder guid. This should make it not match any products:
  697. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateRandom()));
  698. EXPECT_EQ(resultProducts.size(), 0);
  699. // give it a valid data, but the wrong one. Note that job2 was the one that built the other files, not the sourcefile1.
  700. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, m_data->m_job2.m_builderGuid));
  701. EXPECT_EQ(resultProducts.size(), 0);
  702. // give it correct data
  703. EXPECT_TRUE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, m_data->m_job1.m_builderGuid));
  704. EXPECT_EQ(resultProducts.size(), 2);
  705. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  706. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  707. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  708. }
  709. TEST_F(AssetDatabaseTest, GetProductsBySourceName_FilterTest_JobKey)
  710. {
  711. CreateCoverageTestData();
  712. ProductDatabaseEntryContainer resultProducts;
  713. // give it invalid data that won't match anything
  714. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), "no matcher"));
  715. EXPECT_EQ(resultProducts.size(), 0);
  716. // give it a valid data, but the wrong one:
  717. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job2.m_jobKey.c_str())));
  718. EXPECT_EQ(resultProducts.size(), 0);
  719. // give it correct data
  720. EXPECT_TRUE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job1.m_jobKey.c_str())));
  721. EXPECT_EQ(resultProducts.size(), 2);
  722. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  723. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  724. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  725. }
  726. TEST_F(AssetDatabaseTest, GetProductsBySourceName_FilterTest_Platform)
  727. {
  728. CreateCoverageTestData();
  729. ProductDatabaseEntryContainer resultProducts;
  730. // give it invalid data that won't match anything
  731. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(), "badplatform"));
  732. EXPECT_EQ(resultProducts.size(), 0);
  733. // give it a valid data, but the wrong one:
  734. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(), "osx")); // its actually pc
  735. EXPECT_EQ(resultProducts.size(), 0);
  736. // give it correct data
  737. EXPECT_TRUE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(), "pc"));
  738. EXPECT_EQ(resultProducts.size(), 2);
  739. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  740. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  741. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  742. }
  743. TEST_F(AssetDatabaseTest, GetProductsBySourceName_FilterTest_Status)
  744. {
  745. CreateCoverageTestData();
  746. ProductDatabaseEntryContainer resultProducts;
  747. // give it a valid data, but the wrong one:
  748. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Failed)); // its actually completed
  749. EXPECT_EQ(resultProducts.size(), 0);
  750. // give it correct data
  751. EXPECT_TRUE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed));
  752. EXPECT_EQ(resultProducts.size(), 2);
  753. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  754. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  755. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  756. }
  757. // --------------------------------------------------------------------------------------------------------------------
  758. // -------------------------------------------- GetProductsLikeSourceName ---------------------------------------------
  759. // --------------------------------------------------------------------------------------------------------------------
  760. TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_EmptyString_NoResult)
  761. {
  762. CreateCoverageTestData();
  763. ProductDatabaseEntryContainer resultProducts;
  764. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName(QString(), AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, resultProducts));
  765. EXPECT_EQ(resultProducts.size(), 0);
  766. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  767. }
  768. TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_NotFound_NoResult)
  769. {
  770. CreateCoverageTestData();
  771. ProductDatabaseEntryContainer resultProducts;
  772. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("blahrga", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, resultProducts));
  773. EXPECT_EQ(resultProducts.size(), 0);
  774. // this matches the end of a legit string, but we are using startswith, so it should NOT MATCH
  775. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("file.tif", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts));
  776. EXPECT_EQ(resultProducts.size(), 0);
  777. // this matches the startswith, but should NOT MATCH, because its asking for things that end with it.
  778. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::EndsWith, resultProducts));
  779. EXPECT_EQ(resultProducts.size(), 0);
  780. // make sure invalid tokens do not crash it or something
  781. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("%%%%%blahrga%%%%%", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Matches, resultProducts));
  782. EXPECT_EQ(resultProducts.size(), 0);
  783. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  784. }
  785. TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_StartsWith_CorrectName_ReturnsCorrectResult)
  786. {
  787. CreateCoverageTestData();
  788. ProductDatabaseEntryContainer resultProducts;
  789. EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts)); // this is source1, which results in product1 and product2 via job1
  790. EXPECT_EQ(resultProducts.size(), 2);
  791. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  792. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  793. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  794. }
  795. TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_EndsWith_CorrectName_ReturnsCorrectResult)
  796. {
  797. CreateCoverageTestData();
  798. ProductDatabaseEntryContainer resultProducts;
  799. EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("omefile.tif", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::EndsWith, resultProducts)); // this is source1, which results in product1 and product2 via job1
  800. EXPECT_EQ(resultProducts.size(), 2);
  801. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  802. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  803. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  804. }
  805. TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_Matches_CorrectName_ReturnsCorrectResult)
  806. {
  807. CreateCoverageTestData();
  808. ProductDatabaseEntryContainer resultProducts;
  809. EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("omefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Matches, resultProducts)); // this is source1, which results in product1 and product2 via job1
  810. EXPECT_EQ(resultProducts.size(), 2);
  811. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  812. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  813. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  814. }
  815. // tests all of the filters (beside name) to make sure they all function as expected.
  816. TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_FilterTest_BuilderGUID)
  817. {
  818. CreateCoverageTestData();
  819. ProductDatabaseEntryContainer resultProducts;
  820. // give it a random builder guid. This should make it not match any products:
  821. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateRandom()));
  822. EXPECT_EQ(resultProducts.size(), 0);
  823. // give it a valid data, but the wrong one. Note that job2 was the one that built the other files, not the sourcefile1.
  824. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, m_data->m_job2.m_builderGuid));
  825. EXPECT_EQ(resultProducts.size(), 0);
  826. // give it correct data
  827. EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, m_data->m_job1.m_builderGuid));
  828. EXPECT_EQ(resultProducts.size(), 2);
  829. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  830. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  831. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  832. }
  833. TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_FilterTest_JobKey)
  834. {
  835. CreateCoverageTestData();
  836. ProductDatabaseEntryContainer resultProducts;
  837. // give it invalid data that won't match anything
  838. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), "no matcher"));
  839. EXPECT_EQ(resultProducts.size(), 0);
  840. // give it a valid data, but the wrong one:
  841. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job2.m_jobKey.c_str())));
  842. EXPECT_EQ(resultProducts.size(), 0);
  843. // give it correct data
  844. EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job1.m_jobKey.c_str())));
  845. EXPECT_EQ(resultProducts.size(), 2);
  846. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  847. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  848. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  849. }
  850. TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_FilterTest_Platform)
  851. {
  852. CreateCoverageTestData();
  853. ProductDatabaseEntryContainer resultProducts;
  854. // give it invalid data that won't match anything
  855. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "badplatform"));
  856. EXPECT_EQ(resultProducts.size(), 0);
  857. // give it a valid data, but the wrong one:
  858. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "osx")); // its actually pc
  859. EXPECT_EQ(resultProducts.size(), 0);
  860. // give it correct data
  861. EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "pc"));
  862. EXPECT_EQ(resultProducts.size(), 2);
  863. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  864. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  865. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  866. }
  867. TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_FilterTest_Status)
  868. {
  869. CreateCoverageTestData();
  870. ProductDatabaseEntryContainer resultProducts;
  871. // give it a valid data, but the wrong one:
  872. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Failed)); // its actually completed
  873. EXPECT_EQ(resultProducts.size(), 0);
  874. // give it correct data
  875. EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed));
  876. EXPECT_EQ(resultProducts.size(), 2);
  877. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  878. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  879. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  880. }
  881. // --------------------------------------------------------------------------------------------------------------------
  882. // -------------------------------------------------- SetProducts ----------------------------------------------------
  883. // --------------------------------------------------------------------------------------------------------------------
  884. TEST_F(AssetDatabaseTest, SetProducts_EmptyList_Fails)
  885. {
  886. CreateCoverageTestData();
  887. ProductDatabaseEntryContainer requestProducts;
  888. EXPECT_FALSE(m_data->m_connection.SetProducts(requestProducts));
  889. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  890. }
  891. TEST_F(AssetDatabaseTest, SetProducts_UpdatesProductIDs)
  892. {
  893. CreateCoverageTestData();
  894. ProductDatabaseEntryContainer requestProducts;
  895. ProductDatabaseEntryContainer resultProducts;
  896. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  897. size_t priorProductCount = resultProducts.size();
  898. requestProducts.push_back({ m_data->m_job1.m_jobID, 5, "someproduct5.dds", AZ::Data::AssetType::CreateRandom() });
  899. requestProducts.push_back({ m_data->m_job1.m_jobID, 6, "someproduct6.dds", AZ::Data::AssetType::CreateRandom() });
  900. EXPECT_TRUE(m_data->m_connection.SetProducts(requestProducts));
  901. resultProducts.clear();
  902. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  903. size_t newProductCount = resultProducts.size();
  904. EXPECT_NE(requestProducts[0].m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  905. EXPECT_NE(requestProducts[1].m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  906. EXPECT_EQ(newProductCount, priorProductCount + 2);
  907. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  908. }
  909. // --------------------------------------------------------------------------------------------------------------------
  910. // ---------------------------------------------- RemoveProduct(s) ---------------------------------------------------
  911. // --------------------------------------------------------------------------------------------------------------------
  912. TEST_F(AssetDatabaseTest, RemoveProduct_InvalidID_Fails_DoesNotCorruptDB)
  913. {
  914. CreateCoverageTestData();
  915. ProductDatabaseEntryContainer resultProducts;
  916. resultProducts.clear();
  917. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  918. size_t priorProductCount = resultProducts.size();
  919. EXPECT_FALSE(m_data->m_connection.RemoveProduct(-1));
  920. resultProducts.clear();
  921. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  922. size_t newProductCount = resultProducts.size();
  923. EXPECT_EQ(newProductCount, priorProductCount);
  924. }
  925. TEST_F(AssetDatabaseTest, RemoveProducts_EmptyList_Fails_DoesNotCorruptDB)
  926. {
  927. CreateCoverageTestData();
  928. ProductDatabaseEntryContainer resultProducts;
  929. resultProducts.clear();
  930. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  931. size_t priorProductCount = resultProducts.size();
  932. resultProducts.clear();
  933. EXPECT_FALSE(m_data->m_connection.RemoveProducts(resultProducts));
  934. resultProducts.clear();
  935. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  936. size_t newProductCount = resultProducts.size();
  937. EXPECT_EQ(newProductCount, priorProductCount);
  938. }
  939. TEST_F(AssetDatabaseTest, RemoveProducts_InvalidProductIDs_Fails_DoesNotCorruptDB)
  940. {
  941. CreateCoverageTestData();
  942. ProductDatabaseEntryContainer resultProducts;
  943. resultProducts.clear();
  944. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  945. size_t priorProductCount = resultProducts.size();
  946. resultProducts.clear();
  947. resultProducts.push_back({ -1, m_data->m_job1.m_jobID, 5, "someproduct5.dds", AZ::Data::AssetType::CreateRandom() });
  948. resultProducts.push_back({ -2, m_data->m_job1.m_jobID, 6, "someproduct5.dds", AZ::Data::AssetType::CreateRandom() });
  949. resultProducts.push_back({ -3, m_data->m_job1.m_jobID, 7, "someproduct5.dds", AZ::Data::AssetType::CreateRandom() });
  950. EXPECT_FALSE(m_data->m_connection.RemoveProducts(resultProducts));
  951. resultProducts.clear();
  952. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  953. size_t newProductCount = resultProducts.size();
  954. EXPECT_EQ(newProductCount, priorProductCount);
  955. }
  956. TEST_F(AssetDatabaseTest, RemoveProduct_CorrectProduct_OnlyRemovesThatProduct)
  957. {
  958. CreateCoverageTestData();
  959. ProductDatabaseEntryContainer resultProducts;
  960. resultProducts.clear();
  961. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  962. size_t priorProductCount = resultProducts.size();
  963. EXPECT_TRUE(m_data->m_connection.RemoveProduct(m_data->m_product1.m_productID));
  964. resultProducts.clear();
  965. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  966. size_t newProductCount = resultProducts.size();
  967. EXPECT_EQ(newProductCount, priorProductCount - 1);
  968. // make sure they're all there except that one.
  969. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  970. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  971. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end());
  972. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end());
  973. }
  974. TEST_F(AssetDatabaseTest, RemoveProducts_CorrectProduct_OnlyRemovesThoseProducts)
  975. {
  976. CreateCoverageTestData();
  977. ProductDatabaseEntryContainer resultProducts;
  978. resultProducts.clear();
  979. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  980. size_t priorProductCount = resultProducts.size();
  981. resultProducts.clear();
  982. resultProducts.push_back(m_data->m_product1);
  983. resultProducts.push_back(m_data->m_product3);
  984. EXPECT_TRUE(m_data->m_connection.RemoveProducts(resultProducts));
  985. // its also supposed to clear their ids:
  986. EXPECT_EQ(resultProducts[0].m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  987. EXPECT_EQ(resultProducts[1].m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  988. resultProducts.clear();
  989. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  990. size_t newProductCount = resultProducts.size();
  991. EXPECT_EQ(newProductCount, priorProductCount - 2);
  992. // make sure they're all there except those two - (1 and 3) which should be 'eq' to end().
  993. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  994. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  995. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end());
  996. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end());
  997. }
  998. // --------------------------------------------------------------------------------------------------------------------
  999. // ---------------------------------------------- RemoveProductsByJobID ---------------------------------------------------
  1000. // --------------------------------------------------------------------------------------------------------------------
  1001. TEST_F(AssetDatabaseTest, RemoveProductsByJobID_InvalidID_Fails_DoesNotCorruptDB)
  1002. {
  1003. CreateCoverageTestData();
  1004. ProductDatabaseEntryContainer resultProducts;
  1005. resultProducts.clear();
  1006. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1007. size_t priorProductCount = resultProducts.size();
  1008. EXPECT_FALSE(m_data->m_connection.RemoveProductsByJobID(-1));
  1009. resultProducts.clear();
  1010. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1011. size_t newProductCount = resultProducts.size();
  1012. EXPECT_EQ(newProductCount, priorProductCount);
  1013. }
  1014. TEST_F(AssetDatabaseTest, RemoveProductsByJobID_ValidID_OnlyRemovesTheMatchingProducts)
  1015. {
  1016. CreateCoverageTestData();
  1017. ProductDatabaseEntryContainer resultProducts;
  1018. resultProducts.clear();
  1019. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1020. size_t priorProductCount = resultProducts.size();
  1021. EXPECT_TRUE(m_data->m_connection.RemoveProductsByJobID(m_data->m_job1.m_jobID));
  1022. resultProducts.clear();
  1023. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1024. size_t newProductCount = resultProducts.size();
  1025. EXPECT_EQ(newProductCount, priorProductCount - 2);
  1026. // both products that belong to the first job should be gone.
  1027. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  1028. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  1029. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end());
  1030. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end());
  1031. }
  1032. // --------------------------------------------------------------------------------------------------------------------
  1033. // ------------------------------------------ RemoveProductsBySourceID ------------------------------------------------
  1034. // --------------------------------------------------------------------------------------------------------------------
  1035. TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_InvalidSourceID_NoResults)
  1036. {
  1037. CreateCoverageTestData();
  1038. ProductDatabaseEntryContainer resultProducts;
  1039. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1040. size_t priorProductCount = resultProducts.size();
  1041. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(-1));
  1042. resultProducts.clear();
  1043. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1044. size_t newProductCount = resultProducts.size();
  1045. EXPECT_EQ(newProductCount, priorProductCount);
  1046. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1047. }
  1048. TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_Valid_OnlyRemovesTheCorrectOnes)
  1049. {
  1050. CreateCoverageTestData();
  1051. ProductDatabaseEntryContainer resultProducts;
  1052. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1053. size_t priorProductCount = resultProducts.size();
  1054. EXPECT_TRUE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID));
  1055. resultProducts.clear();
  1056. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1057. size_t newProductCount = resultProducts.size();
  1058. EXPECT_EQ(newProductCount, priorProductCount - 2);
  1059. // both products that belong to the first source should be gone - but only those!
  1060. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  1061. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  1062. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end());
  1063. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end());
  1064. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1065. }
  1066. // tests all of the filters (beside name) to make sure they all function as expected.
  1067. TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_FilterTest_BuilderGUID)
  1068. {
  1069. CreateCoverageTestData();
  1070. ProductDatabaseEntryContainer resultProducts;
  1071. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1072. size_t priorProductCount = resultProducts.size();
  1073. // give it a non-matching builder UUID - it should not delete anything despite the product sourceId being correct.
  1074. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateRandom()));
  1075. resultProducts.clear();
  1076. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1077. size_t newProductCount = resultProducts.size();
  1078. EXPECT_EQ(newProductCount, priorProductCount);
  1079. // give it a correct data but the wrong builder (a valid, but wrong one)
  1080. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, m_data->m_job2.m_builderGuid));
  1081. resultProducts.clear();
  1082. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1083. newProductCount = resultProducts.size();
  1084. EXPECT_EQ(newProductCount, priorProductCount);
  1085. // give it correct data, it should delete the first two products:
  1086. EXPECT_TRUE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, m_data->m_job1.m_builderGuid));
  1087. resultProducts.clear();
  1088. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1089. newProductCount = resultProducts.size();
  1090. EXPECT_EQ(newProductCount, priorProductCount - 2);
  1091. // both products that belong to the first source should be gone - but only those!
  1092. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  1093. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  1094. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end());
  1095. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end());
  1096. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1097. }
  1098. TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_FilterTest_JobKey)
  1099. {
  1100. CreateCoverageTestData();
  1101. ProductDatabaseEntryContainer resultProducts;
  1102. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1103. size_t priorProductCount = resultProducts.size();
  1104. // give it a non-matching job key - it should not delete anything despite the product sourceId being correct.
  1105. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), "random key that wont match"));
  1106. resultProducts.clear();
  1107. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1108. size_t newProductCount = resultProducts.size();
  1109. EXPECT_EQ(newProductCount, priorProductCount);
  1110. // give it a correct data but the wrong builder (a valid, but wrong one)
  1111. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), m_data->m_job2.m_jobKey.c_str())); // job2 is not the one that did sourcefile1
  1112. resultProducts.clear();
  1113. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1114. newProductCount = resultProducts.size();
  1115. EXPECT_EQ(newProductCount, priorProductCount);
  1116. // give it correct data, it should delete the first two products:
  1117. EXPECT_TRUE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), m_data->m_job1.m_jobKey.c_str()));
  1118. resultProducts.clear();
  1119. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1120. newProductCount = resultProducts.size();
  1121. EXPECT_EQ(newProductCount, priorProductCount - 2);
  1122. // both products that belong to the first source should be gone - but only those!
  1123. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  1124. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  1125. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end());
  1126. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end());
  1127. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1128. }
  1129. TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_FilterTest_Platform)
  1130. {
  1131. CreateCoverageTestData();
  1132. ProductDatabaseEntryContainer resultProducts;
  1133. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1134. size_t priorProductCount = resultProducts.size();
  1135. // give it a non-matching job key - it should not delete anything despite the product sourceId being correct.
  1136. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), QString(), "no such platform"));
  1137. resultProducts.clear();
  1138. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1139. size_t newProductCount = resultProducts.size();
  1140. EXPECT_EQ(newProductCount, priorProductCount);
  1141. // give it a correct data but the wrong builder (a valid, but wrong one)
  1142. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), QString(), "osx")); // its actually PC
  1143. resultProducts.clear();
  1144. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1145. newProductCount = resultProducts.size();
  1146. EXPECT_EQ(newProductCount, priorProductCount);
  1147. // give it correct data, it should delete the first two products:
  1148. EXPECT_TRUE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), QString(), "pc"));
  1149. resultProducts.clear();
  1150. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1151. newProductCount = resultProducts.size();
  1152. EXPECT_EQ(newProductCount, priorProductCount - 2);
  1153. // both products that belong to the first source should be gone - but only those!
  1154. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  1155. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  1156. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end());
  1157. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end());
  1158. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1159. }
  1160. TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_FilterTest_Status)
  1161. {
  1162. CreateCoverageTestData();
  1163. ProductDatabaseEntryContainer resultProducts;
  1164. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1165. size_t priorProductCount = resultProducts.size();
  1166. // give it a correct status but not one that output that product.
  1167. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Failed));
  1168. resultProducts.clear();
  1169. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1170. size_t newProductCount = resultProducts.size();
  1171. EXPECT_EQ(newProductCount, priorProductCount);
  1172. // give it correct data
  1173. EXPECT_TRUE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed));
  1174. resultProducts.clear();
  1175. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1176. newProductCount = resultProducts.size();
  1177. EXPECT_EQ(newProductCount, priorProductCount - 2);
  1178. // both products that belong to the first source should be gone - but only those!
  1179. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end());
  1180. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end());
  1181. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end());
  1182. EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end());
  1183. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1184. }
  1185. TEST_F(AssetDatabaseTest, SetProductDependencies_CorrectnessTest)
  1186. {
  1187. CreateCoverageTestData();
  1188. ProductDatabaseEntryContainer resultProducts;
  1189. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1190. EXPECT_GT(resultProducts.size(), 0);
  1191. ProductDependencyDatabaseEntryContainer productDependencies;
  1192. AZStd::bitset<64> dependencyFlags = 0xFAA0FEEE;
  1193. AZStd::string pathDep = "unresolved/dependency.txt";
  1194. AZStd::string platform = "somePlatform";
  1195. productDependencies.reserve(200);
  1196. // make 100 product dependencies on the first productID
  1197. for (AZ::u32 productIndex = 0; productIndex < 100; ++productIndex)
  1198. {
  1199. ProductDependencyDatabaseEntry entry(resultProducts[0].m_productID, m_data->m_sourceFile1.m_sourceGuid, productIndex, dependencyFlags, platform, true, pathDep);
  1200. productDependencies.emplace_back(AZStd::move(entry));
  1201. }
  1202. // make 100 product dependencies on the second productID
  1203. for (AZ::u32 productIndex = 0; productIndex < 100; ++productIndex)
  1204. {
  1205. ProductDependencyDatabaseEntry entry(resultProducts[1].m_productID, m_data->m_sourceFile2.m_sourceGuid, productIndex, dependencyFlags, platform, true, pathDep);
  1206. productDependencies.emplace_back(AZStd::move(entry));
  1207. }
  1208. // do a bulk insert:
  1209. EXPECT_TRUE(m_data->m_connection.SetProductDependencies(productDependencies));
  1210. // now, read all the data back and verify each field:
  1211. productDependencies.clear();
  1212. // searching for the first product should only result in the first 100 results:
  1213. EXPECT_TRUE(m_data->m_connection.GetProductDependenciesByProductID(resultProducts[0].m_productID, productDependencies));
  1214. EXPECT_EQ(productDependencies.size(), 100);
  1215. for (AZ::u32 productIndex = 0; productIndex < 100; ++productIndex)
  1216. {
  1217. EXPECT_NE(productDependencies[productIndex].m_productDependencyID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1218. EXPECT_EQ(productDependencies[productIndex].m_productPK, resultProducts[0].m_productID);
  1219. EXPECT_EQ(productDependencies[productIndex].m_dependencySourceGuid, m_data->m_sourceFile1.m_sourceGuid);
  1220. EXPECT_EQ(productDependencies[productIndex].m_dependencySubID, productIndex);
  1221. EXPECT_EQ(productDependencies[productIndex].m_dependencyFlags, dependencyFlags);
  1222. EXPECT_EQ(productDependencies[productIndex].m_platform, platform);
  1223. EXPECT_EQ(productDependencies[productIndex].m_unresolvedPath, pathDep);
  1224. }
  1225. productDependencies.clear();
  1226. // searching for the second product should only result in the second 100 results:
  1227. EXPECT_TRUE(m_data->m_connection.GetProductDependenciesByProductID(resultProducts[1].m_productID, productDependencies));
  1228. EXPECT_EQ(productDependencies.size(), 100);
  1229. for (AZ::u32 productIndex = 0; productIndex < 100; ++productIndex)
  1230. {
  1231. EXPECT_NE(productDependencies[productIndex].m_productDependencyID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1232. EXPECT_EQ(productDependencies[productIndex].m_productPK, resultProducts[1].m_productID);
  1233. EXPECT_EQ(productDependencies[productIndex].m_dependencySourceGuid, m_data->m_sourceFile2.m_sourceGuid);
  1234. EXPECT_EQ(productDependencies[productIndex].m_dependencySubID, productIndex);
  1235. EXPECT_EQ(productDependencies[productIndex].m_dependencyFlags, dependencyFlags);
  1236. EXPECT_EQ(productDependencies[productIndex].m_platform, platform);
  1237. EXPECT_EQ(productDependencies[productIndex].m_unresolvedPath, pathDep);
  1238. }
  1239. // now, we replace the dependencies of the first product with fewer results, with different data:
  1240. productDependencies.clear();
  1241. for (AZ::u32 productIndex = 0; productIndex < 50; ++productIndex)
  1242. {
  1243. ProductDependencyDatabaseEntry entry(resultProducts[0].m_productID, m_data->m_sourceFile2.m_sourceGuid, productIndex, dependencyFlags, platform, true);
  1244. productDependencies.emplace_back(AZStd::move(entry));
  1245. }
  1246. EXPECT_TRUE(m_data->m_connection.SetProductDependencies(productDependencies));
  1247. // searching for the first product should only result in 50 results, which proves that the original 100 were replaced with the new entries:
  1248. productDependencies.clear();
  1249. EXPECT_TRUE(m_data->m_connection.GetProductDependenciesByProductID(resultProducts[0].m_productID, productDependencies));
  1250. EXPECT_EQ(productDependencies.size(), 50);
  1251. for (AZ::u32 productIndex = 0; productIndex < 50; ++productIndex)
  1252. {
  1253. EXPECT_NE(productDependencies[productIndex].m_productDependencyID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1254. EXPECT_EQ(productDependencies[productIndex].m_productPK, resultProducts[0].m_productID);
  1255. EXPECT_EQ(productDependencies[productIndex].m_dependencySourceGuid, m_data->m_sourceFile2.m_sourceGuid); // here we verify that the field has changed.
  1256. EXPECT_EQ(productDependencies[productIndex].m_dependencySubID, productIndex);
  1257. EXPECT_EQ(productDependencies[productIndex].m_dependencyFlags, dependencyFlags);
  1258. EXPECT_EQ(productDependencies[productIndex].m_platform, platform);
  1259. EXPECT_EQ(productDependencies[productIndex].m_unresolvedPath, ""); // verify that no path is set if it was not specified in the entry
  1260. }
  1261. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1262. }
  1263. TEST_F(AssetDatabaseTest, AddLargeNumberOfDependencies_PerformanceTest)
  1264. {
  1265. CreateCoverageTestData();
  1266. ProductDatabaseEntryContainer resultProducts;
  1267. EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts));
  1268. EXPECT_GT(resultProducts.size(), 0);
  1269. ProductDependencyDatabaseEntryContainer productDependencies;
  1270. AZStd::bitset<64> dependencyFlags;
  1271. AZStd::string platform;
  1272. productDependencies.reserve(20000);
  1273. for (AZ::u32 productIndex = 0; productIndex < 20000; ++productIndex)
  1274. {
  1275. ProductDependencyDatabaseEntry entry(resultProducts[0].m_productID, m_data->m_sourceFile1.m_sourceGuid, productIndex, dependencyFlags, platform, true);
  1276. productDependencies.emplace_back(AZStd::move(entry));
  1277. }
  1278. EXPECT_TRUE(m_data->m_connection.SetProductDependencies(productDependencies));
  1279. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1280. }
  1281. TEST_F(AssetDatabaseTest, MissingDependencyTable_WriteAndReadMissingDependencyByDependencyId_ResultsMatch)
  1282. {
  1283. CreateCoverageTestData();
  1284. // Use a non-zero sub ID to verify it writes and reads correctly.
  1285. AZ::Data::AssetId assetId(AZ::Uuid::CreateString("{12209A94-AF18-44BB-8A62-96F35291B2E1}"), 3);
  1286. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry writeMissingDependency(
  1287. // The product ID is a link to another table, it will fail to write this entry if this is invalid.
  1288. m_data->m_product1.m_productID,
  1289. "Scanner Name",
  1290. "1.0.0",
  1291. "Source File Fingerprint",
  1292. assetId.m_guid,
  1293. assetId.m_subId,
  1294. "Source String",
  1295. "last Scan Time",
  1296. 0);
  1297. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(writeMissingDependency));
  1298. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry readMissingDependency;
  1299. EXPECT_TRUE(m_data->m_connection.GetMissingProductDependencyByMissingProductDependencyId(
  1300. writeMissingDependency.m_missingProductDependencyId,
  1301. readMissingDependency));
  1302. EXPECT_EQ(writeMissingDependency, readMissingDependency);
  1303. }
  1304. TEST_F(AssetDatabaseTest, MissingDependencyTable_UpdateExistingMissingDependencyByDependencyId_ResultsMatch)
  1305. {
  1306. CreateCoverageTestData();
  1307. // Use a non-zero sub ID to verify it writes and reads correctly.
  1308. AZ::Data::AssetId assetId(AZ::Uuid::CreateString("{32C32642-5832-4997-A478-F288C734425D}"), 6);
  1309. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry originalMissingDependency(
  1310. // The product ID is a link to another table, it will fail to write this entry if this is invalid.
  1311. m_data->m_product3.m_productID,
  1312. "Scanner Name",
  1313. "1.0.0",
  1314. "Source File Fingerprint",
  1315. assetId.m_guid,
  1316. assetId.m_subId,
  1317. "Source String",
  1318. "last Scan Time",
  1319. 0);
  1320. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(originalMissingDependency));
  1321. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry readMissingDependency;
  1322. EXPECT_TRUE(m_data->m_connection.GetMissingProductDependencyByMissingProductDependencyId(
  1323. originalMissingDependency.m_missingProductDependencyId,
  1324. readMissingDependency));
  1325. EXPECT_EQ(originalMissingDependency, readMissingDependency);
  1326. // Test each field separately.
  1327. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry updatedMissingDependency(originalMissingDependency);
  1328. updatedMissingDependency.m_productPK = m_data->m_product1.m_productID;
  1329. SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency);
  1330. updatedMissingDependency.m_scannerId = "Different Scanner Name";
  1331. SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency);
  1332. updatedMissingDependency.m_scannerVersion = "Different Scanner Version";
  1333. SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency);
  1334. updatedMissingDependency.m_sourceFileFingerprint = "Different Fingerprint";
  1335. SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency);
  1336. updatedMissingDependency.m_dependencySourceGuid = AZ::Uuid::CreateString("{6C3ED7B4-E6F1-4163-9141-54F5DC1D9C35}");
  1337. SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency);
  1338. updatedMissingDependency.m_dependencySubId = 3;
  1339. SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency);
  1340. updatedMissingDependency.m_missingDependencyString = "Different Source String";
  1341. SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency);
  1342. updatedMissingDependency.m_lastScanTime = "Different Scan Time";
  1343. SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency);
  1344. updatedMissingDependency.m_scanTimeSecondsSinceEpoch = 1;
  1345. SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency);
  1346. }
  1347. void AssetDatabaseTest::SetAndCheckMissingDependency(
  1348. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& updatedMissingDependency,
  1349. const AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& originalMissingDependency)
  1350. {
  1351. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(updatedMissingDependency));
  1352. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry readMissingDependency;
  1353. EXPECT_TRUE(m_data->m_connection.GetMissingProductDependencyByMissingProductDependencyId(
  1354. originalMissingDependency.m_missingProductDependencyId,
  1355. readMissingDependency));
  1356. EXPECT_EQ(updatedMissingDependency, readMissingDependency);
  1357. // MissingProductDependencyDatabaseEntry doesn't override the != operator
  1358. EXPECT_FALSE(readMissingDependency == originalMissingDependency);
  1359. }
  1360. TEST_F(AssetDatabaseTest, MissingDependencyTable_WriteAndReadMissingDependenciesByProductId_ResultsMatch)
  1361. {
  1362. CreateCoverageTestData();
  1363. AZStd::vector<AZ::Data::AssetId> assetIds;
  1364. assetIds.push_back(AZ::Data::AssetId(AZ::Uuid::CreateString("{FDAC3A8C-26D1-47D9-88B0-647BCED826DB}"), 10));
  1365. assetIds.push_back(AZ::Data::AssetId(AZ::Uuid::CreateString("{261E8996-7309-4D18-986F-EC6EDE910A70}"), 20));
  1366. assetIds.push_back(AZ::Data::AssetId(AZ::Uuid::CreateString("{2FA88E3A-D6E4-4192-B865-4DDD61AE7492}"), 30));
  1367. // The product ID is a link to another table, it will fail to write this entry if this is invalid.
  1368. AZ::s64 productPK = m_data->m_product2.m_productID;
  1369. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntryContainer writeMissingDependencies;
  1370. writeMissingDependencies.push_back(AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry(
  1371. productPK,
  1372. "Scanner 0",
  1373. "0.0.0",
  1374. "Fingerprint 0",
  1375. assetIds[0].m_guid,
  1376. assetIds[0].m_subId,
  1377. "Source String 0",
  1378. "last Scan Time 0",
  1379. 0));
  1380. writeMissingDependencies.push_back(AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry(
  1381. productPK,
  1382. "Scanner 1",
  1383. "1.1.1",
  1384. "Fingerprint 1",
  1385. assetIds[1].m_guid,
  1386. assetIds[1].m_subId,
  1387. "Source String 1",
  1388. "last Scan Time 1",
  1389. 1));
  1390. writeMissingDependencies.push_back(AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry(
  1391. productPK,
  1392. "Scanner 2",
  1393. "2.2.2",
  1394. "Fingerprint 2",
  1395. assetIds[2].m_guid,
  1396. assetIds[2].m_subId,
  1397. "Source String 2",
  1398. "last Scan Time 2",
  1399. 2));
  1400. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(writeMissingDependencies[0]));
  1401. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(writeMissingDependencies[1]));
  1402. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(writeMissingDependencies[2]));
  1403. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntryContainer readMissingDependencies;
  1404. EXPECT_TRUE(m_data->m_connection.GetMissingProductDependenciesByProductId(productPK, readMissingDependencies));
  1405. EXPECT_EQ(readMissingDependencies.size(), writeMissingDependencies.size());
  1406. for (int dependencyIndex = 0; dependencyIndex < writeMissingDependencies.size(); ++dependencyIndex)
  1407. {
  1408. EXPECT_EQ(readMissingDependencies[dependencyIndex], writeMissingDependencies[dependencyIndex]);
  1409. }
  1410. }
  1411. TEST_F(AssetDatabaseTest, MissingDependencyTable_WriteAndDeleteMissingDependencyByDependencyId_MissingDependencyRecordDeleted)
  1412. {
  1413. CreateCoverageTestData();
  1414. // Use a non-zero sub ID to verify it writes and reads correctly.
  1415. AZ::Data::AssetId assetId(AZ::Uuid::CreateString("{12209A94-AF18-44BB-8A62-96F35291B2E1}"), 3);
  1416. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry writeMissingDependency(
  1417. // The product ID is a link to another table, it will fail to write this entry if this is invalid.
  1418. m_data->m_product1.m_productID,
  1419. "Scanner Name",
  1420. "1.0.0",
  1421. "Source File Fingerprint",
  1422. assetId.m_guid,
  1423. assetId.m_subId,
  1424. "Source String",
  1425. "last Scan Time",
  1426. 0);
  1427. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(writeMissingDependency));
  1428. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry readMissingDependency;
  1429. EXPECT_TRUE(m_data->m_connection.GetMissingProductDependencyByMissingProductDependencyId(
  1430. writeMissingDependency.m_missingProductDependencyId,
  1431. readMissingDependency));
  1432. // Verify that it was written to the DB before erasing it.
  1433. EXPECT_EQ(writeMissingDependency, readMissingDependency);
  1434. EXPECT_TRUE(m_data->m_connection.DeleteMissingProductDependencyByProductId(writeMissingDependency.m_missingProductDependencyId));
  1435. EXPECT_FALSE(m_data->m_connection.GetMissingProductDependencyByMissingProductDependencyId(
  1436. writeMissingDependency.m_missingProductDependencyId,
  1437. readMissingDependency));
  1438. }
  1439. // Verify that clearing missing product dependencies by product ID clears every missing dependency for that product ID.
  1440. TEST_F(AssetDatabaseTest, MissingDependencyTable_DeleteMultipleMissingDependenciesForOneProduct_MissingDependencyRecordsDeleted)
  1441. {
  1442. CreateCoverageTestData();
  1443. // Use a non-zero sub ID to verify it writes and reads correctly.
  1444. AZ::Data::AssetId assetId(AZ::Uuid::CreateString("{12209A94-AF18-44BB-8A62-96F35291B2E1}"), 3);
  1445. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry firstMissingDependency(
  1446. // The product ID is a link to another table, it will fail to write this entry if this is invalid.
  1447. m_data->m_product1.m_productID,
  1448. "Scanner Name",
  1449. "1.0.0",
  1450. "Source File Fingerprint",
  1451. assetId.m_guid,
  1452. assetId.m_subId,
  1453. "Source String",
  1454. "last Scan Time",
  1455. 0);
  1456. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(firstMissingDependency));
  1457. AZ::Data::AssetId secondMissingAssetId(AZ::Uuid::CreateString("{12209A94-FFFF-FFFF-8A62-96F35291B2E1}"), 4);
  1458. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry secondMissingDependency(
  1459. // Use the same product ID as the first missing dependency
  1460. m_data->m_product1.m_productID,
  1461. "Scanner Name 2",
  1462. "1.0.0",
  1463. "Source File Fingerprint",
  1464. secondMissingAssetId.m_guid,
  1465. secondMissingAssetId.m_subId,
  1466. "Source String",
  1467. "last Scan Time",
  1468. 0);
  1469. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(secondMissingDependency));
  1470. AZStd::unordered_set<AZ::s64> expectedMissingDependencies;
  1471. expectedMissingDependencies.insert(firstMissingDependency.m_missingProductDependencyId);
  1472. expectedMissingDependencies.insert(secondMissingDependency.m_missingProductDependencyId);
  1473. // Tests can't be ran inside the lambda, so cache results and check after.
  1474. bool foundUnexpectedDependency = false;
  1475. m_data->m_connection.QueryMissingProductDependencyByProductId(
  1476. m_data->m_product1.m_productID,
  1477. [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& entry)
  1478. {
  1479. if (expectedMissingDependencies.find(entry.m_missingProductDependencyId) == expectedMissingDependencies.end())
  1480. {
  1481. foundUnexpectedDependency = true;
  1482. }
  1483. else
  1484. {
  1485. expectedMissingDependencies.erase(entry.m_missingProductDependencyId);
  1486. }
  1487. return true;
  1488. });
  1489. EXPECT_FALSE(foundUnexpectedDependency);
  1490. EXPECT_EQ(expectedMissingDependencies.size(), 0);
  1491. EXPECT_TRUE(m_data->m_connection.DeleteMissingProductDependencyByProductId(m_data->m_product1.m_productID));
  1492. foundUnexpectedDependency = false;
  1493. m_data->m_connection.QueryMissingProductDependencyByProductId(
  1494. m_data->m_product1.m_productID,
  1495. [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& /*entry*/)
  1496. {
  1497. // No dependencies should be found for this product.
  1498. foundUnexpectedDependency = true;
  1499. return false;
  1500. });
  1501. EXPECT_FALSE(foundUnexpectedDependency);
  1502. }
  1503. // Verify that clearing missing dependencies for one product ID does not clear it for another product ID.
  1504. TEST_F(AssetDatabaseTest, MissingDependencyTable_DeleteMissingDependenciesForOneProduct_MissingDependenciesNotDeletedForOtherProduct)
  1505. {
  1506. CreateCoverageTestData();
  1507. // Use a non-zero sub ID to verify it writes and reads correctly.
  1508. AZ::Data::AssetId assetId(AZ::Uuid::CreateString("{12209A94-AF18-44BB-8A62-96F35291B2E1}"), 3);
  1509. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry firstMissingDependency(
  1510. // The product ID is a link to another table, it will fail to write this entry if this is invalid.
  1511. m_data->m_product1.m_productID,
  1512. "Scanner Name",
  1513. "1.0.0",
  1514. "Source File Fingerprint",
  1515. assetId.m_guid,
  1516. assetId.m_subId,
  1517. "Source String",
  1518. "last Scan Time",
  1519. 0);
  1520. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(firstMissingDependency));
  1521. AZ::Data::AssetId secondMissingAssetId(AZ::Uuid::CreateString("{12209A94-FFFF-FFFF-8A62-96F35291B2E1}"), 4);
  1522. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry secondMissingDependency(
  1523. // Use the same product ID as the first missing dependency
  1524. m_data->m_product3.m_productID,
  1525. "Scanner Name 2",
  1526. "1.0.0",
  1527. "Source File Fingerprint",
  1528. secondMissingAssetId.m_guid,
  1529. secondMissingAssetId.m_subId,
  1530. "Source String",
  1531. "last Scan Time",
  1532. 0);
  1533. EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(secondMissingDependency));
  1534. // Verify both missing dependencies are set.
  1535. size_t dependenciesFound = 0;
  1536. m_data->m_connection.QueryMissingProductDependencyByProductId(
  1537. m_data->m_product1.m_productID,
  1538. [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& /*entry*/)
  1539. {
  1540. ++dependenciesFound;
  1541. return true;
  1542. });
  1543. EXPECT_EQ(dependenciesFound, 1);
  1544. dependenciesFound = 0;
  1545. m_data->m_connection.QueryMissingProductDependencyByProductId(
  1546. m_data->m_product3.m_productID,
  1547. [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& /*entry*/)
  1548. {
  1549. ++dependenciesFound;
  1550. return true;
  1551. });
  1552. EXPECT_EQ(dependenciesFound, 1);
  1553. // Delete the first product's missing dependencies.
  1554. EXPECT_TRUE(m_data->m_connection.DeleteMissingProductDependencyByProductId(m_data->m_product1.m_productID));
  1555. // Verify the first product's missing dependency is gone.
  1556. dependenciesFound = 0;
  1557. m_data->m_connection.QueryMissingProductDependencyByProductId(
  1558. m_data->m_product1.m_productID,
  1559. [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& /*entry*/)
  1560. {
  1561. ++dependenciesFound;
  1562. return false;
  1563. });
  1564. // No dependencies should be found for this product.
  1565. EXPECT_EQ(dependenciesFound, 0);
  1566. // Verify the second product's missing dependency is still there.
  1567. dependenciesFound = 0;
  1568. m_data->m_connection.QueryMissingProductDependencyByProductId(
  1569. m_data->m_product3.m_productID,
  1570. [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& /*entry*/)
  1571. {
  1572. ++dependenciesFound;
  1573. return true;
  1574. });
  1575. EXPECT_EQ(dependenciesFound, 1);
  1576. }
  1577. TEST_F(AssetDatabaseTest, AddLargeNumberOfSourceDependencies_PerformanceTest)
  1578. {
  1579. CreateCoverageTestData();
  1580. SourceFileDependencyEntryContainer resultSourceDependencies;
  1581. resultSourceDependencies.reserve(20000);
  1582. AZ::Uuid builderGuid = AZ::Uuid::CreateRandom();
  1583. // emit 20,000 source dependencies for the same origin file:
  1584. AZ::Uuid originUuid{ "{3C1C9062-7246-443A-A6DF-A001D31B941A}" };
  1585. for (AZ::u32 sourceIndex = 0; sourceIndex < 20000; ++sourceIndex)
  1586. {
  1587. AZStd::string dependentFile = AZStd::string::format("otherfile%i.txt", sourceIndex);
  1588. SourceFileDependencyEntry entry(builderGuid, originUuid, PathOrUuid(dependentFile), SourceFileDependencyEntry::DEP_SourceToSource, true, "");
  1589. resultSourceDependencies.emplace_back(AZStd::move(entry));
  1590. }
  1591. EXPECT_TRUE(m_data->m_connection.SetSourceFileDependencies(resultSourceDependencies));
  1592. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1593. // read them back
  1594. resultSourceDependencies.clear();
  1595. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid, originUuid, SourceFileDependencyEntry::DEP_SourceToSource, resultSourceDependencies));
  1596. EXPECT_EQ(resultSourceDependencies.size(), 20000);
  1597. }
  1598. TEST_F(AssetDatabaseTest, SourceFileDependencies_CorrectnessTest)
  1599. {
  1600. CreateCoverageTestData();
  1601. AZ::Uuid builderGuid1 = AZ::Uuid::CreateRandom();
  1602. AZ::Uuid builderGuid2 = AZ::Uuid::CreateRandom();
  1603. AZ::Uuid file1Uuid{ "{5AA73EF6-5E14-41F3-B458-4FA19D495696}" };
  1604. AZ::Uuid file2Uuid{ "{A3FF1BD5-7D6F-4241-8398-1DC6239AD97A}" };
  1605. AZ::Uuid file1DependsOn1Uuid{ "{33338E41-985A-40DF-A1CC-87BDBC17EC7A}" };
  1606. SourceFileDependencyEntryContainer entries;
  1607. // add the two different kinds of dependencies.
  1608. entries.push_back(SourceFileDependencyEntry(builderGuid1, file1Uuid, PathOrUuid("file1dependson1.txt"), SourceFileDependencyEntry::DEP_SourceToSource, true, ""));
  1609. entries.push_back(SourceFileDependencyEntry(builderGuid2, file1Uuid, PathOrUuid("file1dependson2.txt"), SourceFileDependencyEntry::DEP_SourceToSource, true, ""));
  1610. entries.push_back(SourceFileDependencyEntry(builderGuid1, file1Uuid, PathOrUuid("file1dependson1job.txt"), SourceFileDependencyEntry::DEP_JobToJob, true, ""));
  1611. entries.push_back(SourceFileDependencyEntry(builderGuid2, file1Uuid, PathOrUuid("file1dependson2job.txt"), SourceFileDependencyEntry::DEP_JobToJob, true, ""));
  1612. entries.push_back(SourceFileDependencyEntry(builderGuid1, file2Uuid, PathOrUuid("file2dependson1.txt"), SourceFileDependencyEntry::DEP_SourceToSource, true, ""));
  1613. entries.push_back(SourceFileDependencyEntry(builderGuid1, file2Uuid, PathOrUuid("file2dependson1job.txt"), SourceFileDependencyEntry::DEP_JobToJob, true, ""));
  1614. ASSERT_TRUE(m_data->m_connection.SetSourceFileDependencies(entries));
  1615. SourceFileDependencyEntryContainer resultEntries;
  1616. AZStd::string searchFor;
  1617. auto SearchPredicate = [&searchFor](const SourceFileDependencyEntry& element)
  1618. {
  1619. return element.m_dependsOnSource.GetPath() == searchFor;
  1620. };
  1621. AZ::Uuid searchUuid;
  1622. auto SearchPredicateReverse = [&searchUuid](const SourceFileDependencyEntry& element)
  1623. {
  1624. return element.m_sourceGuid == searchUuid;
  1625. };
  1626. // ask for only the source-to-source dependencies of file1.txt for builder1
  1627. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid1, file1Uuid, SourceFileDependencyEntry::DEP_SourceToSource, resultEntries));
  1628. EXPECT_EQ(resultEntries.size(), 1);
  1629. searchFor = "file1dependson1.txt";
  1630. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end());
  1631. resultEntries.clear();
  1632. // ask for only the source-to-source dependencies of file1.txt for builder2
  1633. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid2, file1Uuid, SourceFileDependencyEntry::DEP_SourceToSource, resultEntries));
  1634. EXPECT_EQ(resultEntries.size(), 1);
  1635. searchFor = "file1dependson2.txt";
  1636. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end());
  1637. resultEntries.clear();
  1638. // ask for the source-to-source dependencies of file1.txt for ANY builder, we shiould get both.
  1639. EXPECT_TRUE(m_data->m_connection.GetDependsOnSourceBySource(file1Uuid, SourceFileDependencyEntry::DEP_SourceToSource, resultEntries));
  1640. EXPECT_EQ(resultEntries.size(), 2);
  1641. searchFor = "file1dependson1.txt";
  1642. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end());
  1643. searchFor = "file1dependson2.txt";
  1644. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end());
  1645. resultEntries.clear();
  1646. // now ask for the job-to-job dependencies for builder 1
  1647. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid1, file1Uuid, SourceFileDependencyEntry::DEP_JobToJob, resultEntries));
  1648. EXPECT_EQ(resultEntries.size(), 1);
  1649. searchFor = "file1dependson1job.txt";
  1650. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end());
  1651. resultEntries.clear();
  1652. // now ask for the job-to-job dependencies for builder 2
  1653. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid2, file1Uuid, SourceFileDependencyEntry::DEP_JobToJob, resultEntries));
  1654. EXPECT_EQ(resultEntries.size(), 1);
  1655. searchFor = "file1dependson2job.txt";
  1656. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end());
  1657. resultEntries.clear();
  1658. // now ask for the job-to-job dependencies for any builder
  1659. EXPECT_TRUE(m_data->m_connection.GetDependsOnSourceBySource(file1Uuid, SourceFileDependencyEntry::DEP_JobToJob, resultEntries));
  1660. EXPECT_EQ(resultEntries.size(), 2);
  1661. searchFor = "file1dependson1job.txt";
  1662. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end());
  1663. searchFor = "file1dependson2job.txt";
  1664. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end());
  1665. resultEntries.clear();
  1666. // now ask for the reverse dependencies - we should find one source-to-source
  1667. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByDependsOnSource(file1DependsOn1Uuid, "file1dependson1.txt", "c:/root/file1dependson1.txt", SourceFileDependencyEntry::DEP_SourceToSource, resultEntries));
  1668. EXPECT_EQ(resultEntries.size(), 1);
  1669. searchUuid = file1Uuid;
  1670. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicateReverse), resultEntries.end());
  1671. resultEntries.clear();
  1672. // now ask for the reverse dependencies - we should find no job-to-job for this:
  1673. EXPECT_FALSE(m_data->m_connection.GetSourceFileDependenciesByDependsOnSource(file1DependsOn1Uuid, "file1dependson1.txt", "c:/root/file1dependson1.txt", SourceFileDependencyEntry::DEP_JobToJob, resultEntries));
  1674. EXPECT_EQ(resultEntries.size(), 0);
  1675. resultEntries.clear();
  1676. // now ask for the reverse dependencies - we should find one 'any' type.
  1677. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByDependsOnSource(file1DependsOn1Uuid, "file1dependson1.txt", "c:/root/file1dependson1.txt", SourceFileDependencyEntry::DEP_Any, resultEntries));
  1678. EXPECT_EQ(resultEntries.size(), 1);
  1679. searchUuid = file1Uuid;
  1680. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicateReverse), resultEntries.end());
  1681. resultEntries.clear();
  1682. // now try the other file - remember the ID for later
  1683. ASSERT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid1, file2Uuid, SourceFileDependencyEntry::DEP_SourceToSource, resultEntries));
  1684. EXPECT_EQ(resultEntries.size(), 1);
  1685. searchFor = "file2dependson1.txt";
  1686. EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end());
  1687. AZ::s64 entryIdSource = resultEntries[0].m_sourceDependencyID;
  1688. resultEntries.clear();
  1689. // and with Job-to-job dependencies
  1690. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid1, file2Uuid, SourceFileDependencyEntry::DEP_JobToJob, resultEntries));
  1691. ASSERT_EQ(resultEntries.size(), 1);
  1692. EXPECT_EQ(resultEntries[0].m_builderGuid, builderGuid1);
  1693. EXPECT_EQ(resultEntries[0].m_sourceGuid, file2Uuid);
  1694. EXPECT_NE(resultEntries[0].m_sourceDependencyID, AzToolsFramework::AssetDatabase::InvalidEntryId);
  1695. EXPECT_STREQ(resultEntries[0].m_dependsOnSource.GetPath().c_str(), "file2dependson1job.txt");
  1696. EXPECT_EQ(resultEntries[0].m_typeOfDependency, SourceFileDependencyEntry::DEP_JobToJob);
  1697. AZ::s64 entryIdJob = resultEntries[0].m_sourceDependencyID;
  1698. resultEntries.clear();
  1699. SourceFileDependencyEntry resultValue;
  1700. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdSource, resultValue));
  1701. EXPECT_EQ(resultValue.m_sourceDependencyID, entryIdSource);
  1702. EXPECT_EQ(resultValue.m_typeOfDependency, SourceFileDependencyEntry::DEP_SourceToSource);
  1703. EXPECT_EQ(resultValue.m_sourceGuid, file2Uuid);
  1704. EXPECT_STREQ(resultValue.m_dependsOnSource.GetPath().c_str(), "file2dependson1.txt");
  1705. EXPECT_EQ(resultValue.m_builderGuid, builderGuid1);
  1706. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdJob, resultValue));
  1707. EXPECT_EQ(resultValue.m_sourceDependencyID, entryIdJob);
  1708. EXPECT_EQ(resultValue.m_typeOfDependency, SourceFileDependencyEntry::DEP_JobToJob);
  1709. EXPECT_EQ(resultValue.m_sourceGuid, file2Uuid);
  1710. EXPECT_STREQ(resultValue.m_dependsOnSource.GetPath().c_str(), "file2dependson1job.txt");
  1711. EXPECT_EQ(resultValue.m_builderGuid, builderGuid1);
  1712. // removal of source
  1713. m_data->m_connection.RemoveSourceFileDependency(entryIdSource);
  1714. EXPECT_FALSE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdSource, resultValue));
  1715. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdJob, resultValue));
  1716. // removeal of job
  1717. m_data->m_connection.RemoveSourceFileDependency(entryIdJob);
  1718. EXPECT_FALSE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdSource, resultValue));
  1719. EXPECT_FALSE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdJob, resultValue));
  1720. }
  1721. TEST_F(AssetDatabaseTest, UpdateNonExistentFile_Fails)
  1722. {
  1723. CreateCoverageTestData();
  1724. ASSERT_FALSE(m_data->m_connection.UpdateFileModTimeAndHashByFileNameAndScanFolderId("testfile.txt", m_data->m_scanFolder.m_scanFolderID, 1234, 1111));
  1725. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1726. }
  1727. TEST_F(AssetDatabaseTest, UpdateExistingFile_Succeeds)
  1728. {
  1729. CreateCoverageTestData();
  1730. FileDatabaseEntry entry;
  1731. entry.m_fileName = "testfile.txt";
  1732. entry.m_scanFolderPK = m_data->m_scanFolder.m_scanFolderID;
  1733. bool entryAlreadyExists;
  1734. ASSERT_TRUE(m_data->m_connection.InsertFile(entry, entryAlreadyExists));
  1735. ASSERT_FALSE(entryAlreadyExists);
  1736. ASSERT_TRUE(m_data->m_connection.UpdateFileModTimeAndHashByFileNameAndScanFolderId("testfile.txt", m_data->m_scanFolder.m_scanFolderID, 1234, 1111));
  1737. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this
  1738. }
  1739. TEST_F(AssetDatabaseTest, GetSourceBySourceName_InvalidInput_SourceNotFound)
  1740. {
  1741. CreateCoverageTestData();
  1742. SourceDatabaseEntry resultSource;
  1743. EXPECT_FALSE(m_data->m_connection.GetSourceBySourceNameScanFolderId("non_existent", m_data->m_scanFolder.m_scanFolderID, resultSource));
  1744. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0);
  1745. }
  1746. TEST_F(AssetDatabaseTest, GetSourceBySourceName_ValidInput_SourceFound)
  1747. {
  1748. CreateCoverageTestData();
  1749. SourceDatabaseEntry resultSource;
  1750. EXPECT_TRUE(m_data->m_connection.GetSourceBySourceNameScanFolderId("somefile.tif", m_data->m_scanFolder.m_scanFolderID, resultSource));
  1751. EXPECT_EQ(resultSource.m_sourceGuid, m_data->m_sourceFile1.m_sourceGuid);
  1752. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0);
  1753. }
  1754. TEST_F(AssetDatabaseTest, GetDirectReverseProductDependenciesBySourceGuidSubID_InvalidInput_ProductsNotFound)
  1755. {
  1756. CreateCoverageTestData();
  1757. ProductDependencyDatabaseEntry productDependency;
  1758. productDependency.m_productPK = m_data->m_product1.m_productID;
  1759. productDependency.m_dependencySourceGuid = m_data->m_sourceFile1.m_sourceGuid;
  1760. productDependency.m_dependencySubID = m_data->m_product1.m_subID;
  1761. ASSERT_TRUE(m_data->m_connection.SetProductDependency(productDependency));
  1762. ProductDatabaseEntryContainer resultProducts;
  1763. AZ::Uuid invalidGuid = AZ::Uuid::CreateNull();
  1764. AZ::s32 invalidSubId = -1;
  1765. EXPECT_FALSE(m_data->m_connection.GetDirectReverseProductDependenciesBySourceGuidSubId(invalidGuid, m_data->m_product1.m_subID, resultProducts));
  1766. EXPECT_FALSE(m_data->m_connection.GetDirectReverseProductDependenciesBySourceGuidSubId(m_data->m_sourceFile1.m_sourceGuid, invalidSubId, resultProducts));
  1767. EXPECT_FALSE(m_data->m_connection.GetDirectReverseProductDependenciesBySourceGuidSubId(invalidGuid, invalidSubId, resultProducts));
  1768. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0);
  1769. }
  1770. TEST_F(AssetDatabaseTest, GetDirectReverseProductDependenciesBySourceGuidSubID_ValidInput_ProductsFound)
  1771. {
  1772. CreateCoverageTestData();
  1773. ProductDependencyDatabaseEntry productDependency;
  1774. productDependency.m_productPK = m_data->m_product1.m_productID;
  1775. productDependency.m_dependencySourceGuid = m_data->m_sourceFile1.m_sourceGuid;
  1776. productDependency.m_dependencySubID = m_data->m_product1.m_subID;
  1777. ASSERT_TRUE(m_data->m_connection.SetProductDependency(productDependency));
  1778. ProductDatabaseEntryContainer resultProducts;
  1779. EXPECT_TRUE(m_data->m_connection.GetDirectReverseProductDependenciesBySourceGuidSubId(m_data->m_sourceFile1.m_sourceGuid, m_data->m_product1.m_subID, resultProducts));
  1780. ASSERT_EQ(resultProducts.size(), 1);
  1781. EXPECT_EQ(resultProducts[0], m_data->m_product1);
  1782. EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0);
  1783. }
  1784. TEST_F(AssetDatabaseTest, QueryProductDependenciesUnresolvedAdvanced_HandlesLargeSearch_Success)
  1785. {
  1786. CreateCoverageTestData();
  1787. constexpr int NumTestPaths = 10000;
  1788. AZStd::vector<AZStd::string> searchPaths;
  1789. searchPaths.reserve(NumTestPaths);
  1790. for (int i = 0; i < NumTestPaths; ++i)
  1791. {
  1792. searchPaths.emplace_back(AZStd::string::format("%d.txt", i));
  1793. }
  1794. ProductDependencyDatabaseEntry dependency1(m_data->m_product1.m_productID, AZ::Uuid::CreateNull(), 0, 0, "pc", false, "*.txt");
  1795. ProductDependencyDatabaseEntry dependency2(
  1796. m_data->m_product1.m_productID, AZ::Uuid::CreateNull(), 0, 0, "pc", false, "default.xml");
  1797. m_data->m_connection.SetProductDependency(dependency1);
  1798. m_data->m_connection.SetProductDependency(dependency2);
  1799. AZStd::vector<AZStd::string> matches;
  1800. matches.reserve(NumTestPaths);
  1801. ASSERT_TRUE(m_data->m_connection.QueryProductDependenciesUnresolvedAdvanced(
  1802. searchPaths,
  1803. [&matches](AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry& /*entry*/, const AZStd::string& path)
  1804. {
  1805. matches.push_back(path);
  1806. return true;
  1807. }));
  1808. ASSERT_EQ(matches.size(), searchPaths.size());
  1809. // Check the first few results match
  1810. for (int i = 0; i < 10 && i < NumTestPaths; ++i)
  1811. {
  1812. ASSERT_STREQ(matches[i].c_str(), searchPaths[i].c_str());
  1813. }
  1814. matches.clear();
  1815. searchPaths.clear();
  1816. searchPaths.push_back("default.xml");
  1817. // Run the query again to make sure a) we can b) we don't get any extra results and c) we can query for exact (non wildcard) matches
  1818. ASSERT_TRUE(m_data->m_connection.QueryProductDependenciesUnresolvedAdvanced(
  1819. searchPaths,
  1820. [&matches](AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry& /*entry*/, const AZStd::string& path)
  1821. {
  1822. matches.push_back(path);
  1823. return true;
  1824. }));
  1825. ASSERT_THAT(matches, testing::ElementsAreArray(searchPaths));
  1826. }
  1827. TEST_F(AssetDatabaseTest, QueryCombined_Succeeds)
  1828. {
  1829. // This test specifically checks that the legacy subIds returned by QueryCombined are correctly matched to only the one product that they're associated with
  1830. using namespace AzToolsFramework::AssetDatabase;
  1831. CreateCoverageTestData();
  1832. auto subIds = { 123, 134, 155, 166, 177 };
  1833. AZStd::vector<LegacySubIDsEntry> createdLegacySubIds;
  1834. for(int subId : subIds)
  1835. {
  1836. LegacySubIDsEntry subIdEntry;
  1837. subIdEntry.m_productPK = m_data->m_product1.m_productID;
  1838. subIdEntry.m_subID = subId;
  1839. ASSERT_TRUE(m_data->m_connection.CreateOrUpdateLegacySubID(subIdEntry));
  1840. createdLegacySubIds.push_back(subIdEntry);
  1841. }
  1842. AZStd::vector<CombinedDatabaseEntry> results;
  1843. auto databaseQueryCallback = [&](AzToolsFramework::AssetDatabase::CombinedDatabaseEntry& combined) -> bool
  1844. {
  1845. results.push_back(combined);
  1846. return true;
  1847. };
  1848. ASSERT_TRUE(m_data->m_connection.QueryCombined(databaseQueryCallback, AZ::Uuid::CreateNull(), nullptr, nullptr, AzToolsFramework::AssetSystem::JobStatus::Any, /*includeLegacyIds*/ true));
  1849. bool foundProductWithLegacyIds = false;
  1850. for(const auto& combined : results)
  1851. {
  1852. if (combined.m_productID == m_data->m_product1.m_productID)
  1853. {
  1854. foundProductWithLegacyIds = true;
  1855. ASSERT_THAT(combined.m_legacySubIDs, testing::UnorderedElementsAreArray(createdLegacySubIds));
  1856. }
  1857. else
  1858. {
  1859. ASSERT_EQ(combined.m_legacySubIDs.size(), 0);
  1860. }
  1861. }
  1862. ASSERT_TRUE(foundProductWithLegacyIds);
  1863. }
  1864. TEST_F(AssetDatabaseTest, InsertFile_Existing_ReturnsExisting)
  1865. {
  1866. CreateCoverageTestData();
  1867. using namespace AzToolsFramework::AssetDatabase;
  1868. FileDatabaseEntry fileEntry;
  1869. fileEntry.m_fileName = "blah";
  1870. fileEntry.m_scanFolderPK = m_data->m_scanFolder.m_scanFolderID;
  1871. bool entryAlreadyExists = false;
  1872. ASSERT_TRUE(m_data->m_connection.InsertFile(fileEntry, entryAlreadyExists));
  1873. ASSERT_FALSE(entryAlreadyExists);
  1874. fileEntry.m_fileID = InvalidEntryId; // InsertFile will update the Id, we want to test without a specified Id
  1875. ASSERT_TRUE(m_data->m_connection.InsertFile(fileEntry, entryAlreadyExists));
  1876. ASSERT_TRUE(entryAlreadyExists);
  1877. // Test one more time, with the Id set to a specific entry now
  1878. ASSERT_NE(fileEntry.m_fileID, InvalidEntryId);
  1879. ASSERT_TRUE(m_data->m_connection.InsertFile(fileEntry, entryAlreadyExists));
  1880. ASSERT_TRUE(entryAlreadyExists);
  1881. }
  1882. TEST_F(AssetDatabaseTest, StatDatabaseEntryEquality)
  1883. {
  1884. // two entries are the same if m_statName, m_statValue, and m_lastLogTime are same.
  1885. using namespace AzToolsFramework::AssetDatabase;
  1886. StatDatabaseEntry entry1, entry2;
  1887. entry1.m_statName = "EqTest";
  1888. entry1.m_statValue = 17632;
  1889. entry1.m_lastLogTime = 54689213;
  1890. entry2.m_statName = "EqTest";
  1891. entry2.m_statValue = 17632;
  1892. entry2.m_lastLogTime = 54689213;
  1893. EXPECT_EQ(entry1, entry2);
  1894. entry2.m_statName = "Helloworld";
  1895. EXPECT_NE(entry1, entry2);
  1896. entry2.m_statName = "EqTest";
  1897. entry2.m_statValue = 81245;
  1898. EXPECT_NE(entry1, entry2);
  1899. entry2.m_statValue = 17632;
  1900. entry2.m_lastLogTime = 12345678;
  1901. EXPECT_NE(entry1, entry2);
  1902. }
  1903. TEST_F(AssetDatabaseTest, ReplaceStat_CreateIfNotExist)
  1904. {
  1905. // create entry if StatName is not seen
  1906. CreateCoverageTestData();
  1907. using namespace AzToolsFramework::AssetDatabase;
  1908. StatDatabaseEntry statEntry;
  1909. StatDatabaseEntryContainer statContainer;
  1910. statEntry.m_statName = "testJob_createIfNotExist";
  1911. statEntry.m_statValue = 1853;
  1912. statEntry.m_lastLogTime = m_data->m_job1.m_lastLogTime;
  1913. //! Ensure the Stats table is empty
  1914. size_t entryCount = 0;
  1915. m_data->m_connection.QueryStatsTable(
  1916. [&entryCount]([[maybe_unused]] StatDatabaseEntry& stat)
  1917. {
  1918. ++entryCount;
  1919. return true;
  1920. });
  1921. EXPECT_EQ(entryCount, 0);
  1922. //! Insert a stat and read the stat. Stat read and stat written should be the same.
  1923. EXPECT_TRUE(m_data->m_connection.ReplaceStat(statEntry));
  1924. m_data->m_connection.GetStatByStatName(statEntry.m_statName.c_str(), statContainer);
  1925. EXPECT_EQ(statContainer.size(), 1);
  1926. EXPECT_EQ(statContainer.at(0), statEntry);
  1927. statContainer.clear();
  1928. //! Ensure one element is added.
  1929. entryCount = 0;
  1930. m_data->m_connection.QueryStatsTable(
  1931. [&entryCount]([[maybe_unused]] StatDatabaseEntry& stat)
  1932. {
  1933. ++entryCount;
  1934. return true;
  1935. });
  1936. EXPECT_EQ(entryCount, 1);
  1937. }
  1938. TEST_F(AssetDatabaseTest, ReplaceStat_UpdateIfExist)
  1939. {
  1940. // replace the entry if the StatName is in the asset database
  1941. CreateCoverageTestData();
  1942. using namespace AzToolsFramework::AssetDatabase;
  1943. StatDatabaseEntry statEntry;
  1944. StatDatabaseEntryContainer statContainer;
  1945. statEntry.m_statName = "testJob_updateIfExist";
  1946. statEntry.m_statValue = 8432;
  1947. statEntry.m_lastLogTime = m_data->m_job1.m_lastLogTime;
  1948. //! Ensure the Stats table is empty
  1949. size_t entryCount = 0;
  1950. m_data->m_connection.QueryStatsTable(
  1951. [&entryCount]([[maybe_unused]] StatDatabaseEntry& stat)
  1952. {
  1953. ++entryCount;
  1954. return true;
  1955. });
  1956. EXPECT_EQ(entryCount, 0);
  1957. //! Insert a stat
  1958. EXPECT_TRUE(m_data->m_connection.ReplaceStat(statEntry));
  1959. //! Insert a stat with the same StatName. The old one should be replaced.
  1960. StatDatabaseEntry secondStatEntry;
  1961. secondStatEntry.m_statName = statEntry.m_statName;
  1962. secondStatEntry.m_statValue = 16384;
  1963. secondStatEntry.m_lastLogTime = 23570;
  1964. EXPECT_TRUE(m_data->m_connection.ReplaceStat(secondStatEntry));
  1965. m_data->m_connection.GetStatByStatName(statEntry.m_statName.c_str(), statContainer);
  1966. ASSERT_EQ(statContainer.size(), 1);
  1967. ASSERT_NE(statContainer.at(0), statEntry);
  1968. ASSERT_EQ(statContainer.at(0), secondStatEntry);
  1969. //! Ensure the element is replaced, not added.
  1970. entryCount = 0;
  1971. m_data->m_connection.QueryStatsTable(
  1972. [&entryCount]([[maybe_unused]] StatDatabaseEntry& stat)
  1973. {
  1974. ++entryCount;
  1975. return true;
  1976. });
  1977. ASSERT_EQ(entryCount, 1);
  1978. }
  1979. TEST_F(AssetDatabaseTest, QueryStatsTable)
  1980. {
  1981. const unsigned int StatCount = 10;
  1982. InsertStatsTestData(StatCount);
  1983. StatDatabaseEntryContainer statContainer;
  1984. auto getAllStats = [&statContainer](StatDatabaseEntry& stat)
  1985. {
  1986. statContainer.push_back(stat);
  1987. return true;
  1988. };
  1989. ASSERT_TRUE(m_data->m_connection.QueryStatsTable(getAllStats));
  1990. ASSERT_TRUE(statContainer.size() == StatCount);
  1991. // check the items are identical to what we inserted
  1992. AZStd::sort(
  1993. statContainer.begin(),
  1994. statContainer.end(),
  1995. [](const StatDatabaseEntry& lhs, const StatDatabaseEntry& rhs)
  1996. {
  1997. return lhs.m_statName != rhs.m_statName ? lhs.m_statName < rhs.m_statName
  1998. : lhs.m_statValue != rhs.m_statValue ? lhs.m_statValue < rhs.m_statValue
  1999. : lhs.m_lastLogTime < rhs.m_lastLogTime;
  2000. });
  2001. StatDatabaseEntry statEntry = GetFirstStatEntry();
  2002. for (unsigned int i = 0; i < StatCount; ++i)
  2003. {
  2004. EXPECT_EQ(statEntry, statContainer[i]);
  2005. StepStatEntry(statEntry);
  2006. }
  2007. }
  2008. TEST_F(AssetDatabaseTest, GetStatByStatName)
  2009. {
  2010. const unsigned int StatCount = 10;
  2011. InsertStatsTestData(StatCount);
  2012. StatDatabaseEntry statEntry = GetFirstStatEntry();
  2013. for (unsigned int i = 0; i < StatCount; ++i)
  2014. {
  2015. StatDatabaseEntryContainer statContainer;
  2016. ASSERT_TRUE(m_data->m_connection.GetStatByStatName(statEntry.m_statName.c_str(), statContainer));
  2017. ASSERT_EQ(statContainer.size(), 1);
  2018. EXPECT_EQ(statContainer[0], statEntry);
  2019. StepStatEntry(statEntry);
  2020. }
  2021. }
  2022. TEST_F(AssetDatabaseTest, GetStatLikeStatName)
  2023. {
  2024. const unsigned int StatCountPerPrefix = 5;
  2025. AZStd::array<AZStd::string, 4> prefixes{ "Apple_", "Banana_", "Orange_", "Grape_" };
  2026. for (const auto& prefix : prefixes)
  2027. {
  2028. InsertStatsTestData(StatCountPerPrefix, prefix);
  2029. }
  2030. //! Make sure we insert right number of entries
  2031. {
  2032. unsigned int entryCount{ 0 };
  2033. auto countAllStats = [&entryCount]([[maybe_unused]] StatDatabaseEntry& stat)
  2034. {
  2035. ++entryCount;
  2036. return true;
  2037. };
  2038. ASSERT_TRUE(m_data->m_connection.QueryStatsTable(countAllStats));
  2039. ASSERT_EQ(entryCount, StatCountPerPrefix * prefixes.size());
  2040. }
  2041. //! Query StatName like prefixes
  2042. for (const auto& prefix : prefixes)
  2043. {
  2044. StatDatabaseEntryContainer container;
  2045. EXPECT_TRUE(m_data->m_connection.GetStatLikeStatName((prefix + "%").c_str(), container));
  2046. EXPECT_EQ(container.size(), StatCountPerPrefix);
  2047. }
  2048. //! Query StatName like suffixes
  2049. char query[] = "%a";
  2050. for (unsigned int i = 0; i < StatCountPerPrefix; ++i, ++query[1])
  2051. {
  2052. StatDatabaseEntryContainer container;
  2053. EXPECT_TRUE(m_data->m_connection.GetStatLikeStatName(query, container));
  2054. EXPECT_EQ(container.size(), prefixes.size());
  2055. }
  2056. }
  2057. class QueryLoggingTraceHandler : public AZ::Debug::TraceMessageBus::Handler
  2058. {
  2059. public:
  2060. QueryLoggingTraceHandler()
  2061. {
  2062. BusConnect();
  2063. }
  2064. ~QueryLoggingTraceHandler()
  2065. {
  2066. BusDisconnect();
  2067. }
  2068. bool OnPrintf(const char* /*window*/, const char* message) override
  2069. {
  2070. if (m_expectedMessage.compare(message) == 0)
  2071. {
  2072. m_expectedMessageFound = true;
  2073. }
  2074. return false; // Return false so it also prints out to the log.
  2075. }
  2076. AZStd::string m_expectedMessage;
  2077. bool m_expectedMessageFound = false;
  2078. private:
  2079. };
  2080. TEST_F(AssetDatabaseTest, LoggingEnabled_InsertFile_LogMessageMatches)
  2081. {
  2082. using namespace AzToolsFramework::AssetDatabase;
  2083. CreateCoverageTestData();
  2084. QueryLoggingTraceHandler queryLoggingTraceHandler;
  2085. queryLoggingTraceHandler.m_expectedMessage =
  2086. "SELECT * FROM Files WHERE ScanFolderPK = :scanfolderpk AND FileName = :filename; = Params :scanfolderpk = `1`, :filename = `blah`\n";
  2087. m_data->m_connection.SetQueryLogging(true);
  2088. FileDatabaseEntry fileEntry;
  2089. fileEntry.m_fileName = "blah";
  2090. fileEntry.m_scanFolderPK = m_data->m_scanFolder.m_scanFolderID;
  2091. bool entryAlreadyExists = false;
  2092. ASSERT_TRUE(m_data->m_connection.InsertFile(fileEntry, entryAlreadyExists));
  2093. m_data->m_connection.SetQueryLogging(false);
  2094. ASSERT_TRUE(queryLoggingTraceHandler.m_expectedMessageFound);
  2095. }
  2096. } // end namespace UnitTests