/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include #include #include #include #include #include #include #include namespace UnitTests { using namespace testing; using ::testing::NiceMock; using namespace AssetProcessor; using AzToolsFramework::AssetDatabase::ProductDatabaseEntry; using AzToolsFramework::AssetDatabase::ScanFolderDatabaseEntry; using AzToolsFramework::AssetDatabase::SourceDatabaseEntry; using AzToolsFramework::AssetDatabase::SourceFileDependencyEntry; using AzToolsFramework::AssetDatabase::SourceFileDependencyEntryContainer; using AzToolsFramework::AssetDatabase::JobDatabaseEntry; using AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer; using AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry; using AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer; using AzToolsFramework::AssetDatabase::AssetDatabaseConnection; using AzToolsFramework::AssetDatabase::FileDatabaseEntry; class MockDatabaseLocationListener : public AzToolsFramework::AssetDatabase::AssetDatabaseRequests::Bus::Handler { public: MOCK_METHOD1(GetAssetDatabaseLocation, bool(AZStd::string&)); }; class AssetDatabaseTest : public AssetProcessorTest { public: void SetUp() override { AssetProcessorTest::SetUp(); m_data.reset(new StaticData()); m_data->m_databaseLocation = ":memory:"; // this special string causes SQLITE to open the database in memory and not touch disk at all. m_data->m_databaseLocationListener.BusConnect(); ON_CALL(m_data->m_databaseLocationListener, GetAssetDatabaseLocation(_)) .WillByDefault( DoAll( // set the 0th argument ref (string) to the database location and return true. SetArgReferee<0>(":memory:"), Return(true))); // Initialize the database: m_data->m_connection.ClearData(); // this is expected to reset/clear/reopen } void TearDown() override { m_data->m_databaseLocationListener.BusDisconnect(); m_data.reset(); AssetProcessorTest::TearDown(); } // COVERAGE TEST // For each of these coverage tests we'll start with the same kind of database, one with // SCAN FOLDER: rootportkey // SOURCE: somefile.tif // JOB: "some job key" runkey: 1 "pc" SUCCEEDED // Product: "someproduct1.dds" subid: 1 // Product: "someproduct2.dds" subid: 2 // SOURCE: otherfile.tif // JOB: "some other job key" runkey: 2 "osx" FAILED // Product: "someproduct3.dds" subid: 3 // Product: "someproduct4.dds" subid: 4 void CreateCoverageTestData() { m_data->m_scanFolder = { "c:/lumberyard/dev", "dev", "rootportkey", "" }; ASSERT_TRUE(m_data->m_connection.SetScanFolder(m_data->m_scanFolder)); m_data->m_sourceFile1 = { m_data->m_scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "AnalysisFingerprint1"}; m_data->m_sourceFile2 = { m_data->m_scanFolder.m_scanFolderID, "otherfile.tif", AZ::Uuid::CreateRandom(), "AnalysisFingerprint2"}; ASSERT_TRUE(m_data->m_connection.SetSource(m_data->m_sourceFile1)); ASSERT_TRUE(m_data->m_connection.SetSource(m_data->m_sourceFile2)); m_data->m_job1 = { m_data->m_sourceFile1.m_sourceID, "some job key", 123, "pc", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, 1 }; m_data->m_job2 = { m_data->m_sourceFile2.m_sourceID, "some other job key", 345, "osx", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Failed, 2 }; ASSERT_TRUE(m_data->m_connection.SetJob(m_data->m_job1)); ASSERT_TRUE(m_data->m_connection.SetJob(m_data->m_job2)); m_data->m_product1 = { m_data->m_job1.m_jobID, 1, "someproduct1.dds", AZ::Data::AssetType::CreateRandom() }; m_data->m_product2 = { m_data->m_job1.m_jobID, 2, "someproduct2.dds", AZ::Data::AssetType::CreateRandom() }; m_data->m_product3 = { m_data->m_job2.m_jobID, 3, "someproduct3.dds", AZ::Data::AssetType::CreateRandom() }; m_data->m_product4 = { m_data->m_job2.m_jobID, 4, "someproduct4.dds", AZ::Data::AssetType::CreateRandom() }; ASSERT_TRUE(m_data->m_connection.SetProduct(m_data->m_product1)); ASSERT_TRUE(m_data->m_connection.SetProduct(m_data->m_product2)); ASSERT_TRUE(m_data->m_connection.SetProduct(m_data->m_product3)); ASSERT_TRUE(m_data->m_connection.SetProduct(m_data->m_product4)); } protected: void SetAndCheckMissingDependency( AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& updatedMissingDependency, const AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& originalMissingDependency); struct StaticData { // these variables are created during SetUp() and destroyed during TearDown() and thus are always available during tests using this fixture: AZStd::string m_databaseLocation; NiceMock m_databaseLocationListener; AssetProcessor::AssetDatabaseConnection m_connection; // The following database entry variables are initialized only when you call coverage test data CreateCoverageTestData(). // Tests which don't need or want a pre-made database should not call CreateCoverageTestData() but note that in that case // these entries will be empty and their identifiers will be -1. ScanFolderDatabaseEntry m_scanFolder; SourceDatabaseEntry m_sourceFile1; SourceDatabaseEntry m_sourceFile2; JobDatabaseEntry m_job1; JobDatabaseEntry m_job2; ProductDatabaseEntry m_product1; ProductDatabaseEntry m_product2; ProductDatabaseEntry m_product3; ProductDatabaseEntry m_product4; }; // 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 // allocator, reducing the chance of missing or forgetting to destroy one in the future. AZStd::unique_ptr m_data; }; TEST_F(AssetDatabaseTest, UpdateJob_Succeeds) { using namespace AzToolsFramework::AssetDatabase; CreateCoverageTestData(); m_data->m_job1.m_warningCount = 11; m_data->m_job1.m_errorCount = 22; ASSERT_TRUE(m_data->m_connection.SetJob(m_data->m_job1)); JobDatabaseEntryContainer jobs; ASSERT_TRUE(m_data->m_connection.GetJobsBySourceID(m_data->m_job1.m_sourcePK, jobs)); ASSERT_EQ(jobs.size(), 1); ASSERT_EQ(m_data->m_job1, jobs[0]); } TEST_F(AssetDatabaseTest, GetProducts_WithEmptyDatabase_Fails_ReturnsNoProducts) { ProductDatabaseEntryContainer products; EXPECT_FALSE(m_data->m_connection.GetProducts(products)); EXPECT_EQ(products.size(), 0); } TEST_F(AssetDatabaseTest, GetProductByProductID_NotFound_Fails_ReturnsNoProducts) { AzToolsFramework::AssetDatabase::ProductDatabaseEntry product; EXPECT_FALSE(m_data->m_connection.GetProductByProductID(3443, product)); EXPECT_EQ(product, AzToolsFramework::AssetDatabase::ProductDatabaseEntry()); } TEST_F(AssetDatabaseTest, GetProductsLikeProductName_NotFound_Fails_ReturnsNoProducts) { ProductDatabaseEntryContainer products; EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("none", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, products)); EXPECT_EQ(products.size(), 0); EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("none", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, products)); EXPECT_EQ(products.size(), 0); EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("none", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::EndsWith, products)); EXPECT_EQ(products.size(), 0); EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("none", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Matches, products)); EXPECT_EQ(products.size(), 0); } TEST_F(AssetDatabaseTest, GetProductsBySourceID_NotFound_Fails_ReturnsNoProducts) { ProductDatabaseEntryContainer products; EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(25654, products)); EXPECT_EQ(products.size(), 0); } TEST_F(AssetDatabaseTest, SetProduct_InvalidProductID_Fails) { // trying to "overwrite" a product that does not exist should fail and emit error. AZ::Data::AssetType validAssetType1 = AZ::Data::AssetType::CreateRandom(); ProductDatabaseEntry product { 123213, 234234, 1, "SomeProduct1.dds", validAssetType1 }; m_errorAbsorber->Clear(); EXPECT_FALSE(m_data->m_connection.SetProduct(product)); EXPECT_GT(m_errorAbsorber->m_numErrorsAbsorbed, 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this // make sure it didn't actually touch the db as a side effect: ProductDatabaseEntryContainer products; EXPECT_FALSE(m_data->m_connection.GetProducts(products)); EXPECT_EQ(products.size(), 0); } TEST_F(AssetDatabaseTest, SetProduct_InvalidJobPK_Fails) { AZ::Data::AssetType validAssetType1 = AZ::Data::AssetType::CreateRandom(); // -1 means insert a new product, but the JobPK is an enforced FK constraint, so this should fail since there // won't be a Job with the PK of 234234. ProductDatabaseEntry product{ AzToolsFramework::AssetDatabase::InvalidEntryId, 234234, 1, "SomeProduct1.dds", validAssetType1 }; m_errorAbsorber->Clear(); EXPECT_FALSE(m_data->m_connection.SetProduct(product)); EXPECT_GT(m_errorAbsorber->m_numErrorsAbsorbed, 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this // make sure it didn't actually touch the db as a side effect: ProductDatabaseEntryContainer products; EXPECT_FALSE(m_data->m_connection.GetProducts(products)); EXPECT_EQ(products.size(), 0); } // if we give it a valid command and a -1 product, we expect it to succeed without assert or warning // and we expect it to tell us (by filling in the entry) what the new PK is. TEST_F(AssetDatabaseTest, SetProduct_AutoPK_Succeeds) { AZ::Data::AssetType validAssetType1 = AZ::Data::AssetType::CreateRandom(); // to add a product legitimately you have to have a full chain of primary keys, chain is: // ScanFolder --> Source --> job --> product. // we'll create all of those first (except product) before starting the product test. //add a scanfolder. None of this has to exist in real disk, this is a db test only. ScanFolderDatabaseEntry scanFolder {"c:/lumberyard/dev", "dev", "rootportkey", ""}; EXPECT_TRUE(m_data->m_connection.SetScanFolder(scanFolder)); ASSERT_NE(scanFolder.m_scanFolderID, AzToolsFramework::AssetDatabase::InvalidEntryId); SourceDatabaseEntry sourceEntry {scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "fingerprint1"}; EXPECT_TRUE(m_data->m_connection.SetSource(sourceEntry)); ASSERT_NE(sourceEntry.m_sourceID, AzToolsFramework::AssetDatabase::InvalidEntryId); JobDatabaseEntry jobEntry{ sourceEntry.m_sourceID, "some job key", 123, "pc", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, 1 }; EXPECT_TRUE(m_data->m_connection.SetJob(jobEntry)); ASSERT_NE(jobEntry.m_jobID, AzToolsFramework::AssetDatabase::InvalidEntryId); // --- set up complete --- perform the test! ProductDatabaseEntry product{ AzToolsFramework::AssetDatabase::InvalidEntryId, jobEntry.m_jobID, 1, "SomeProduct1.dds", validAssetType1 }; m_errorAbsorber->Clear(); EXPECT_TRUE(m_data->m_connection.SetProduct(product)); ASSERT_NE(product.m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId); EXPECT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this // read it back from the DB and make sure its identical to what was written ProductDatabaseEntry productFromDB; EXPECT_TRUE(m_data->m_connection.GetProductByProductID(product.m_productID, productFromDB)); ASSERT_EQ(product, productFromDB); } // update an existing job by giving it a specific PK of a known existing item. TEST_F(AssetDatabaseTest, SetProduct_SpecificPK_Succeeds_DifferentSubID) { AZ::Data::AssetType validAssetType1 = AZ::Data::AssetType::CreateRandom(); // to add a product legitimately you have to have a full chain of primary keys, chain is: // ScanFolder --> Source --> job --> product. // we'll create all of those first (except product) before starting the product test. ScanFolderDatabaseEntry scanFolder{ "c:/lumberyard/dev", "dev", "rootportkey", "" }; ASSERT_TRUE(m_data->m_connection.SetScanFolder(scanFolder)); SourceDatabaseEntry sourceEntry{ scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "fingerprint1" }; ASSERT_TRUE(m_data->m_connection.SetSource(sourceEntry)); // two different job entries. JobDatabaseEntry jobEntry{ sourceEntry.m_sourceID, "some job key", 123, "pc", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, 1 }; JobDatabaseEntry jobEntry2{ sourceEntry.m_sourceID, "some job key 2", 345, "pc", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, 2 }; ASSERT_TRUE(m_data->m_connection.SetJob(jobEntry)); ASSERT_TRUE(m_data->m_connection.SetJob(jobEntry2)); ProductDatabaseEntry product{ AzToolsFramework::AssetDatabase::InvalidEntryId, jobEntry.m_jobID, 1, "SomeProduct1.dds", validAssetType1 }; ASSERT_TRUE(m_data->m_connection.SetProduct(product)); // --- set up complete --- perform the test! // update all the fields of that product and then write it to the db. ProductDatabaseEntry newProductData = product; // copy first // now change all the fields: newProductData.m_assetType = AZ::Uuid::CreateRandom(); newProductData.m_productName = "different name.dds"; newProductData.m_subID = 2; newProductData.m_jobPK = jobEntry2.m_jobID; // move it to the other job, too! // update the product EXPECT_TRUE(m_data->m_connection.SetProduct(newProductData)); ASSERT_NE(newProductData.m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId); // it should not have entered a new product but instead overwritten the old one. ASSERT_EQ(product.m_productID, newProductData.m_productID); // read it back from DB and verify: ProductDatabaseEntry productFromDB; EXPECT_TRUE(m_data->m_connection.GetProductByProductID(newProductData.m_productID, productFromDB)); ASSERT_EQ(newProductData, productFromDB); ProductDatabaseEntryContainer products; EXPECT_TRUE(m_data->m_connection.GetProducts(products)); EXPECT_EQ(products.size(), 1); } // 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). // this is actually a very common case (same job id, same subID) TEST_F(AssetDatabaseTest, SetProduct_SpecificPK_Succeeds_SameSubID_SameJobID) { ScanFolderDatabaseEntry scanFolder{ "c:/lumberyard/dev", "dev", "rootportkey", "" }; ASSERT_TRUE(m_data->m_connection.SetScanFolder(scanFolder)); SourceDatabaseEntry sourceEntry{ scanFolder.m_scanFolderID, "somefile.tif", AZ::Uuid::CreateRandom(), "fingerprint1" }; ASSERT_TRUE(m_data->m_connection.SetSource(sourceEntry)); JobDatabaseEntry jobEntry{ sourceEntry.m_sourceID, "some job key", 123, "pc", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, 1 }; ASSERT_TRUE(m_data->m_connection.SetJob(jobEntry)); ProductDatabaseEntry product{ AzToolsFramework::AssetDatabase::InvalidEntryId, jobEntry.m_jobID, 1, "SomeProduct1.dds", AZ::Data::AssetType::CreateRandom() }; ASSERT_TRUE(m_data->m_connection.SetProduct(product)); // --- set up complete --- perform the test! // update all the fields of that product and then write it to the db. ProductDatabaseEntry newProductData = product; // copy first // now change all the fields: newProductData.m_assetType = AZ::Uuid::CreateRandom(); newProductData.m_productName = "different name.dds"; newProductData.m_productID = AzToolsFramework::AssetDatabase::InvalidEntryId; // wipe out the product ID, so that we can make sure it returns it. // we don't change the subID here or the job ID. // update the product EXPECT_TRUE(m_data->m_connection.SetProduct(newProductData)); ASSERT_NE(newProductData.m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId); // it should not have entered a new product but instead overwritten the old one. EXPECT_EQ(product.m_productID, newProductData.m_productID); // read it back from DB and verify: ProductDatabaseEntry productFromDB; EXPECT_TRUE(m_data->m_connection.GetProductByProductID(newProductData.m_productID, productFromDB)); EXPECT_EQ(newProductData, productFromDB); ProductDatabaseEntryContainer products; EXPECT_TRUE(m_data->m_connection.GetProducts(products)); EXPECT_EQ(products.size(), 1); } TEST_F(AssetDatabaseTest, GetProductsByJobID_InvalidID_NotFound_ReturnsFalse) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_FALSE(m_data->m_connection.GetProductsByJobID(-1, resultProducts)); EXPECT_EQ(resultProducts.size(), 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsByJobID_Valid_ReturnsTrue_FindsProducts) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProductsByJobID(m_data->m_job1.m_jobID, resultProducts)); EXPECT_EQ(resultProducts.size(), 2); // should have found the first two products. // since there is no ordering, we just have to find both of them: EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductByJobIDSubId_InvalidID_NotFound_ReturnsFalse) { CreateCoverageTestData(); ProductDatabaseEntry resultProduct; EXPECT_FALSE(m_data->m_connection.GetProductByJobIDSubId(m_data->m_job1.m_jobID, aznumeric_caster(-1), resultProduct)); EXPECT_FALSE(m_data->m_connection.GetProductByJobIDSubId(-1, m_data->m_product1.m_subID, resultProduct)); EXPECT_FALSE(m_data->m_connection.GetProductByJobIDSubId(-1, aznumeric_caster(-1), resultProduct)); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductByJobIDSubId_ValidID_Found_ReturnsTrue) { CreateCoverageTestData(); ProductDatabaseEntry resultProduct; EXPECT_TRUE(m_data->m_connection.GetProductByJobIDSubId(m_data->m_job1.m_jobID, m_data->m_product1.m_subID, resultProduct)); EXPECT_EQ(resultProduct, m_data->m_product1); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductBySourceGuidSubId_InvalidInputs_ProductNotFound) { CreateCoverageTestData(); ProductDatabaseEntry resultProduct; AZ::Uuid invalidGuid = AZ::Uuid::CreateNull(); AZ::s32 invalidSubId = -1; EXPECT_FALSE(m_data->m_connection.GetProductBySourceGuidSubId(invalidGuid, m_data->m_product1.m_subID, resultProduct)); EXPECT_FALSE(m_data->m_connection.GetProductBySourceGuidSubId(m_data->m_sourceFile1.m_sourceGuid, invalidSubId, resultProduct)); EXPECT_FALSE(m_data->m_connection.GetProductBySourceGuidSubId(invalidGuid, invalidSubId, resultProduct)); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); } TEST_F(AssetDatabaseTest, GetProductBySourceGuidSubId_ValidInputs_ProductFound) { CreateCoverageTestData(); ProductDatabaseEntry resultProduct; EXPECT_TRUE(m_data->m_connection.GetProductBySourceGuidSubId(m_data->m_sourceFile1.m_sourceGuid, m_data->m_product1.m_subID, resultProduct)); EXPECT_EQ(resultProduct, m_data->m_product1); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); } // -------------------------------------------------------------------------------------------------------------------- // ------------------------------------------ GetProductsByProductName ------------------------------------------------ // -------------------------------------------------------------------------------------------------------------------- TEST_F(AssetDatabaseTest, GetProductsByProductName_EmptyString_NoResults) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_FALSE(m_data->m_connection.GetProductsByProductName(QString(), resultProducts)); EXPECT_EQ(resultProducts.size(), 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsByProductName_NotFound_NoResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("akdsuhuksahdsak", resultProducts)); EXPECT_EQ(resultProducts.size(), 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsByProductName_CorrectName_ReturnsCorrectResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts)); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // tests all of the filters (beside name) to make sure they all function as expected. TEST_F(AssetDatabaseTest, GetProductsByProductName_FilterTest_BuilderGUID) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a random builder guid. This should make it not match any products: EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateRandom())); EXPECT_EQ(resultProducts.size(), 0); // give it a correct builder guid but the wrong builder. Job2's builder actually built product4. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, m_data->m_job1.m_builderGuid)); EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, m_data->m_job2.m_builderGuid)); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsByProductName_FilterTest_JobKey) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a random job key that is not going to match the existing job keys. This should make it not match any products: EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), "no matcher")); EXPECT_EQ(resultProducts.size(), 0); // give it a correct job key but not one that output that product. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job1.m_jobKey.c_str()))); EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job2.m_jobKey.c_str()))); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsByProductName_FilterTest_Platform) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a platform that is not going to match the existing job platforms. This should make it not match any products: EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(), "badplatform")); EXPECT_EQ(resultProducts.size(), 0); // give it a correct platform but not one that output that product. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(), "pc")); // its actually osx EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(), "osx")); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsByProductName_FilterTest_Status) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a correct status but not one that output that product. EXPECT_FALSE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed)); // its actually failed EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsByProductName("someproduct4.dds", resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Failed)); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // -------------------------------------------------------------------------------------------------------------------- // ------------------------------------------ GetProductsLikeProductName ---------------------------------------------- // -------------------------------------------------------------------------------------------------------------------- TEST_F(AssetDatabaseTest, GetProductsLikeProductName_EmptyString_NoResults) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName(QString(), AssetDatabaseConnection::StartsWith, resultProducts)); EXPECT_EQ(resultProducts.size(), 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeProductName_NotFound_NoResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("akdsuhuksahdsak", AssetDatabaseConnection::StartsWith, resultProducts)); EXPECT_EQ(resultProducts.size(), 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeProductName_CorrectName_StartsWith_ReturnsCorrectResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts)); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeProductName_CorrectName_EndsWith_ReturnsCorrectResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("product4.dds", AssetDatabaseConnection::EndsWith, resultProducts)); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeProductName_CorrectName_Matches_ReturnsCorrectResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("product4", AssetDatabaseConnection::Matches, resultProducts)); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeProductName_CorrectName_StartsWith_ReturnsMany) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // a very broad search that matches all products. EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct", AssetDatabaseConnection::StartsWith, resultProducts)); EXPECT_EQ(resultProducts.size(), 4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // tests all of the filters (beside name) to make sure they all function as expected. TEST_F(AssetDatabaseTest, GetProductsLikeProductName_FilterTest_BuilderGUID) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a random builder guid. This should make it not match any products: EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateRandom())); EXPECT_EQ(resultProducts.size(), 0); // give it a correct builder guid but the wrong builder. Job2's builder actually built product4. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, m_data->m_job1.m_builderGuid)); EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, m_data->m_job2.m_builderGuid)); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeProductName_FilterTest_JobKey) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a random job key that is not going to match the existing job keys. This should make it not match any products: EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), "no matcher")); EXPECT_EQ(resultProducts.size(), 0); // give it a correct job key but not one that output that product. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job1.m_jobKey.c_str()))); EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job2.m_jobKey.c_str()))); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeProductName_FilterTest_Platform) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a platform that is not going to match the existing job platforms. This should make it not match any products: EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "badplatform")); EXPECT_EQ(resultProducts.size(), 0); // give it a correct platform but not one that output that product. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "pc")); // its actually osx EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "osx")); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeProductName_FilterTest_Status) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a correct status but not one that output that product. EXPECT_FALSE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed)); // its actually failed EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsLikeProductName("someproduct4", AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Failed)); EXPECT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product4); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------- GetProductsBySourceID ------------------------------------------------ // -------------------------------------------------------------------------------------------------------------------- TEST_F(AssetDatabaseTest, GetProductsBySourceID_NotFound_NoResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(-1, resultProducts)); EXPECT_EQ(resultProducts.size(), 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsBySourceID_CorrectID_ReturnsCorrectResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts)); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // tests all of the filters (beside name) to make sure they all function as expected. TEST_F(AssetDatabaseTest, GetProductsBySourceID_FilterTest_BuilderGUID) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a random builder guid. This should make it not match any products: EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateRandom())); EXPECT_EQ(resultProducts.size(), 0); // give it a valid data, but the wrong one. Note that job2 was the one that built the other files, not the sourcefile1. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, m_data->m_job2.m_builderGuid)); EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, m_data->m_job1.m_builderGuid)); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsBySourceID_FilterTest_JobKey) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it invalid data that won't match anything EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), "no matcher")); EXPECT_EQ(resultProducts.size(), 0); // give it a valid data, but the wrong one: 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()))); EXPECT_EQ(resultProducts.size(), 0); // give it correct data 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()))); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsBySourceID_FilterTest_Platform) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it invalid data that won't match anything EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(), "badplatform")); EXPECT_EQ(resultProducts.size(), 0); // give it a valid data, but the wrong one: EXPECT_FALSE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(), "osx")); // its actually pc EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(), "pc")); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsBySourceID_FilterTest_Status) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a valid data, but the wrong one: 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 EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsBySourceID(m_data->m_sourceFile1.m_sourceID, resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed)); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // -------------------------------------------------------------------------------------------------------------------- // -------------------------------------------- GetProductsBySourceName ----------------------------------------------- // -------------------------------------------------------------------------------------------------------------------- TEST_F(AssetDatabaseTest, GetProductsBySourceName_EmptyString_NoResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName(QString(), resultProducts)); EXPECT_EQ(resultProducts.size(), 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsBySourceName_NotFound_NoResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("blahrga", resultProducts)); EXPECT_EQ(resultProducts.size(), 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsBySourceName_CorrectName_ReturnsCorrectResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts)); // this is source1, which results in product1 and product2 via job1 EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // tests all of the filters (beside name) to make sure they all function as expected. TEST_F(AssetDatabaseTest, GetProductsBySourceName_FilterTest_BuilderGUID) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a random builder guid. This should make it not match any products: EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateRandom())); EXPECT_EQ(resultProducts.size(), 0); // give it a valid data, but the wrong one. Note that job2 was the one that built the other files, not the sourcefile1. EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, m_data->m_job2.m_builderGuid)); EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, m_data->m_job1.m_builderGuid)); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsBySourceName_FilterTest_JobKey) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it invalid data that won't match anything EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), "no matcher")); EXPECT_EQ(resultProducts.size(), 0); // give it a valid data, but the wrong one: EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job2.m_jobKey.c_str()))); EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(m_data->m_job1.m_jobKey.c_str()))); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsBySourceName_FilterTest_Platform) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it invalid data that won't match anything EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(), "badplatform")); EXPECT_EQ(resultProducts.size(), 0); // give it a valid data, but the wrong one: EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(), "osx")); // its actually pc EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(), "pc")); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsBySourceName_FilterTest_Status) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a valid data, but the wrong one: EXPECT_FALSE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Failed)); // its actually completed EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsBySourceName("somefile.tif", resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed)); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // -------------------------------------------------------------------------------------------------------------------- // -------------------------------------------- GetProductsLikeSourceName --------------------------------------------- // -------------------------------------------------------------------------------------------------------------------- TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_EmptyString_NoResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName(QString(), AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, resultProducts)); EXPECT_EQ(resultProducts.size(), 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_NotFound_NoResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("blahrga", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Raw, resultProducts)); EXPECT_EQ(resultProducts.size(), 0); // this matches the end of a legit string, but we are using startswith, so it should NOT MATCH EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("file.tif", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts)); EXPECT_EQ(resultProducts.size(), 0); // this matches the startswith, but should NOT MATCH, because its asking for things that end with it. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::EndsWith, resultProducts)); EXPECT_EQ(resultProducts.size(), 0); // make sure invalid tokens do not crash it or something EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("%%%%%blahrga%%%%%", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Matches, resultProducts)); EXPECT_EQ(resultProducts.size(), 0); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_StartsWith_CorrectName_ReturnsCorrectResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts)); // this is source1, which results in product1 and product2 via job1 EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_EndsWith_CorrectName_ReturnsCorrectResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; 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 EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_Matches_CorrectName_ReturnsCorrectResult) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("omefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::Matches, resultProducts)); // this is source1, which results in product1 and product2 via job1 EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // tests all of the filters (beside name) to make sure they all function as expected. TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_FilterTest_BuilderGUID) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a random builder guid. This should make it not match any products: EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateRandom())); EXPECT_EQ(resultProducts.size(), 0); // give it a valid data, but the wrong one. Note that job2 was the one that built the other files, not the sourcefile1. EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, m_data->m_job2.m_builderGuid)); EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, m_data->m_job1.m_builderGuid)); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_FilterTest_JobKey) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it invalid data that won't match anything EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), "no matcher")); EXPECT_EQ(resultProducts.size(), 0); // give it a valid data, but the wrong one: 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()))); EXPECT_EQ(resultProducts.size(), 0); // give it correct data 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()))); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_FilterTest_Platform) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it invalid data that won't match anything EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "badplatform")); EXPECT_EQ(resultProducts.size(), 0); // give it a valid data, but the wrong one: EXPECT_FALSE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "osx")); // its actually pc EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), "pc")); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetProductsLikeSourceName_FilterTest_Status) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; // give it a valid data, but the wrong one: 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 EXPECT_EQ(resultProducts.size(), 0); // give it correct data EXPECT_TRUE(m_data->m_connection.GetProductsLikeSourceName("somefile", AzToolsFramework::AssetDatabase::AssetDatabaseConnection::StartsWith, resultProducts, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed)); EXPECT_EQ(resultProducts.size(), 2); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // -------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------- SetProducts ---------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------- TEST_F(AssetDatabaseTest, SetProducts_EmptyList_Fails) { CreateCoverageTestData(); ProductDatabaseEntryContainer requestProducts; EXPECT_FALSE(m_data->m_connection.SetProducts(requestProducts)); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, SetProducts_UpdatesProductIDs) { CreateCoverageTestData(); ProductDatabaseEntryContainer requestProducts; ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); requestProducts.push_back({ m_data->m_job1.m_jobID, 5, "someproduct5.dds", AZ::Data::AssetType::CreateRandom() }); requestProducts.push_back({ m_data->m_job1.m_jobID, 6, "someproduct6.dds", AZ::Data::AssetType::CreateRandom() }); EXPECT_TRUE(m_data->m_connection.SetProducts(requestProducts)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_NE(requestProducts[0].m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId); EXPECT_NE(requestProducts[1].m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId); EXPECT_EQ(newProductCount, priorProductCount + 2); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // -------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------- RemoveProduct(s) --------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------- TEST_F(AssetDatabaseTest, RemoveProduct_InvalidID_Fails_DoesNotCorruptDB) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); EXPECT_FALSE(m_data->m_connection.RemoveProduct(-1)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); } TEST_F(AssetDatabaseTest, RemoveProducts_EmptyList_Fails_DoesNotCorruptDB) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); resultProducts.clear(); EXPECT_FALSE(m_data->m_connection.RemoveProducts(resultProducts)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); } TEST_F(AssetDatabaseTest, RemoveProducts_InvalidProductIDs_Fails_DoesNotCorruptDB) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); resultProducts.clear(); resultProducts.push_back({ -1, m_data->m_job1.m_jobID, 5, "someproduct5.dds", AZ::Data::AssetType::CreateRandom() }); resultProducts.push_back({ -2, m_data->m_job1.m_jobID, 6, "someproduct5.dds", AZ::Data::AssetType::CreateRandom() }); resultProducts.push_back({ -3, m_data->m_job1.m_jobID, 7, "someproduct5.dds", AZ::Data::AssetType::CreateRandom() }); EXPECT_FALSE(m_data->m_connection.RemoveProducts(resultProducts)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); } TEST_F(AssetDatabaseTest, RemoveProduct_CorrectProduct_OnlyRemovesThatProduct) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); EXPECT_TRUE(m_data->m_connection.RemoveProduct(m_data->m_product1.m_productID)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount - 1); // make sure they're all there except that one. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end()); } TEST_F(AssetDatabaseTest, RemoveProducts_CorrectProduct_OnlyRemovesThoseProducts) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); resultProducts.clear(); resultProducts.push_back(m_data->m_product1); resultProducts.push_back(m_data->m_product3); EXPECT_TRUE(m_data->m_connection.RemoveProducts(resultProducts)); // its also supposed to clear their ids: EXPECT_EQ(resultProducts[0].m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId); EXPECT_EQ(resultProducts[1].m_productID, AzToolsFramework::AssetDatabase::InvalidEntryId); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount - 2); // make sure they're all there except those two - (1 and 3) which should be 'eq' to end(). EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end()); } // -------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------- RemoveProductsByJobID --------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------- TEST_F(AssetDatabaseTest, RemoveProductsByJobID_InvalidID_Fails_DoesNotCorruptDB) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); EXPECT_FALSE(m_data->m_connection.RemoveProductsByJobID(-1)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); } TEST_F(AssetDatabaseTest, RemoveProductsByJobID_ValidID_OnlyRemovesTheMatchingProducts) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); EXPECT_TRUE(m_data->m_connection.RemoveProductsByJobID(m_data->m_job1.m_jobID)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount - 2); // both products that belong to the first job should be gone. EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end()); } // -------------------------------------------------------------------------------------------------------------------- // ------------------------------------------ RemoveProductsBySourceID ------------------------------------------------ // -------------------------------------------------------------------------------------------------------------------- TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_InvalidSourceID_NoResults) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(-1)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_Valid_OnlyRemovesTheCorrectOnes) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); EXPECT_TRUE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount - 2); // both products that belong to the first source should be gone - but only those! EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } // tests all of the filters (beside name) to make sure they all function as expected. TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_FilterTest_BuilderGUID) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); // give it a non-matching builder UUID - it should not delete anything despite the product sourceId being correct. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateRandom())); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); // give it a correct data but the wrong builder (a valid, but wrong one) EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, m_data->m_job2.m_builderGuid)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); // give it correct data, it should delete the first two products: EXPECT_TRUE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, m_data->m_job1.m_builderGuid)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount - 2); // both products that belong to the first source should be gone - but only those! EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_FilterTest_JobKey) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); // give it a non-matching job key - it should not delete anything despite the product sourceId being correct. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), "random key that wont match")); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); // give it a correct data but the wrong builder (a valid, but wrong one) 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 resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); // give it correct data, it should delete the first two products: EXPECT_TRUE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), m_data->m_job1.m_jobKey.c_str())); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount - 2); // both products that belong to the first source should be gone - but only those! EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_FilterTest_Platform) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); // give it a non-matching job key - it should not delete anything despite the product sourceId being correct. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), QString(), "no such platform")); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); // give it a correct data but the wrong builder (a valid, but wrong one) EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), QString(), "osx")); // its actually PC resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); // give it correct data, it should delete the first two products: EXPECT_TRUE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), QString(), "pc")); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount - 2); // both products that belong to the first source should be gone - but only those! EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, RemoveProductsBySourceID_FilterTest_Status) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t priorProductCount = resultProducts.size(); // give it a correct status but not one that output that product. EXPECT_FALSE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Failed)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); size_t newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount); // give it correct data EXPECT_TRUE(m_data->m_connection.RemoveProductsBySourceID(m_data->m_sourceFile1.m_sourceID, AZ::Uuid::CreateNull(), QString(), QString(), AzToolsFramework::AssetSystem::JobStatus::Completed)); resultProducts.clear(); EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); newProductCount = resultProducts.size(); EXPECT_EQ(newProductCount, priorProductCount - 2); // both products that belong to the first source should be gone - but only those! EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product1), resultProducts.end()); EXPECT_EQ(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product2), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product3), resultProducts.end()); EXPECT_NE(AZStd::find(resultProducts.begin(), resultProducts.end(), m_data->m_product4), resultProducts.end()); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, SetProductDependencies_CorrectnessTest) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); EXPECT_GT(resultProducts.size(), 0); ProductDependencyDatabaseEntryContainer productDependencies; AZStd::bitset<64> dependencyFlags = 0xFAA0FEEE; AZStd::string pathDep = "unresolved/dependency.txt"; AZStd::string platform = "somePlatform"; productDependencies.reserve(200); // make 100 product dependencies on the first productID for (AZ::u32 productIndex = 0; productIndex < 100; ++productIndex) { ProductDependencyDatabaseEntry entry(resultProducts[0].m_productID, m_data->m_sourceFile1.m_sourceGuid, productIndex, dependencyFlags, platform, true, pathDep); productDependencies.emplace_back(AZStd::move(entry)); } // make 100 product dependencies on the second productID for (AZ::u32 productIndex = 0; productIndex < 100; ++productIndex) { ProductDependencyDatabaseEntry entry(resultProducts[1].m_productID, m_data->m_sourceFile2.m_sourceGuid, productIndex, dependencyFlags, platform, true, pathDep); productDependencies.emplace_back(AZStd::move(entry)); } // do a bulk insert: EXPECT_TRUE(m_data->m_connection.SetProductDependencies(productDependencies)); // now, read all the data back and verify each field: productDependencies.clear(); // searching for the first product should only result in the first 100 results: EXPECT_TRUE(m_data->m_connection.GetProductDependenciesByProductID(resultProducts[0].m_productID, productDependencies)); EXPECT_EQ(productDependencies.size(), 100); for (AZ::u32 productIndex = 0; productIndex < 100; ++productIndex) { EXPECT_NE(productDependencies[productIndex].m_productDependencyID, AzToolsFramework::AssetDatabase::InvalidEntryId); EXPECT_EQ(productDependencies[productIndex].m_productPK, resultProducts[0].m_productID); EXPECT_EQ(productDependencies[productIndex].m_dependencySourceGuid, m_data->m_sourceFile1.m_sourceGuid); EXPECT_EQ(productDependencies[productIndex].m_dependencySubID, productIndex); EXPECT_EQ(productDependencies[productIndex].m_dependencyFlags, dependencyFlags); EXPECT_EQ(productDependencies[productIndex].m_platform, platform); EXPECT_EQ(productDependencies[productIndex].m_unresolvedPath, pathDep); } productDependencies.clear(); // searching for the second product should only result in the second 100 results: EXPECT_TRUE(m_data->m_connection.GetProductDependenciesByProductID(resultProducts[1].m_productID, productDependencies)); EXPECT_EQ(productDependencies.size(), 100); for (AZ::u32 productIndex = 0; productIndex < 100; ++productIndex) { EXPECT_NE(productDependencies[productIndex].m_productDependencyID, AzToolsFramework::AssetDatabase::InvalidEntryId); EXPECT_EQ(productDependencies[productIndex].m_productPK, resultProducts[1].m_productID); EXPECT_EQ(productDependencies[productIndex].m_dependencySourceGuid, m_data->m_sourceFile2.m_sourceGuid); EXPECT_EQ(productDependencies[productIndex].m_dependencySubID, productIndex); EXPECT_EQ(productDependencies[productIndex].m_dependencyFlags, dependencyFlags); EXPECT_EQ(productDependencies[productIndex].m_platform, platform); EXPECT_EQ(productDependencies[productIndex].m_unresolvedPath, pathDep); } // now, we replace the dependencies of the first product with fewer results, with different data: productDependencies.clear(); for (AZ::u32 productIndex = 0; productIndex < 50; ++productIndex) { ProductDependencyDatabaseEntry entry(resultProducts[0].m_productID, m_data->m_sourceFile2.m_sourceGuid, productIndex, dependencyFlags, platform, true); productDependencies.emplace_back(AZStd::move(entry)); } EXPECT_TRUE(m_data->m_connection.SetProductDependencies(productDependencies)); // searching for the first product should only result in 50 results, which proves that the original 100 were replaced with the new entries: productDependencies.clear(); EXPECT_TRUE(m_data->m_connection.GetProductDependenciesByProductID(resultProducts[0].m_productID, productDependencies)); EXPECT_EQ(productDependencies.size(), 50); for (AZ::u32 productIndex = 0; productIndex < 50; ++productIndex) { EXPECT_NE(productDependencies[productIndex].m_productDependencyID, AzToolsFramework::AssetDatabase::InvalidEntryId); EXPECT_EQ(productDependencies[productIndex].m_productPK, resultProducts[0].m_productID); EXPECT_EQ(productDependencies[productIndex].m_dependencySourceGuid, m_data->m_sourceFile2.m_sourceGuid); // here we verify that the field has changed. EXPECT_EQ(productDependencies[productIndex].m_dependencySubID, productIndex); EXPECT_EQ(productDependencies[productIndex].m_dependencyFlags, dependencyFlags); EXPECT_EQ(productDependencies[productIndex].m_platform, platform); EXPECT_EQ(productDependencies[productIndex].m_unresolvedPath, ""); // verify that no path is set if it was not specified in the entry } EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, AddLargeNumberOfDependencies_PerformanceTest) { CreateCoverageTestData(); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetProducts(resultProducts)); EXPECT_GT(resultProducts.size(), 0); ProductDependencyDatabaseEntryContainer productDependencies; AZStd::bitset<64> dependencyFlags; AZStd::string platform; productDependencies.reserve(20000); for (AZ::u32 productIndex = 0; productIndex < 20000; ++productIndex) { ProductDependencyDatabaseEntry entry(resultProducts[0].m_productID, m_data->m_sourceFile1.m_sourceGuid, productIndex, dependencyFlags, platform, true); productDependencies.emplace_back(AZStd::move(entry)); } EXPECT_TRUE(m_data->m_connection.SetProductDependencies(productDependencies)); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, MissingDependencyTable_WriteAndReadMissingDependencyByDependencyId_ResultsMatch) { CreateCoverageTestData(); // Use a non-zero sub ID to verify it writes and reads correctly. AZ::Data::AssetId assetId(AZ::Uuid::CreateString("{12209A94-AF18-44BB-8A62-96F35291B2E1}"), 3); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry writeMissingDependency( // The product ID is a link to another table, it will fail to write this entry if this is invalid. m_data->m_product1.m_productID, "Scanner Name", "1.0.0", "Source File Fingerprint", assetId.m_guid, assetId.m_subId, "Source String", "last Scan Time", 0); EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(writeMissingDependency)); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry readMissingDependency; EXPECT_TRUE(m_data->m_connection.GetMissingProductDependencyByMissingProductDependencyId( writeMissingDependency.m_missingProductDependencyId, readMissingDependency)); EXPECT_EQ(writeMissingDependency, readMissingDependency); } TEST_F(AssetDatabaseTest, MissingDependencyTable_UpdateExistingMissingDependencyByDependencyId_ResultsMatch) { CreateCoverageTestData(); // Use a non-zero sub ID to verify it writes and reads correctly. AZ::Data::AssetId assetId(AZ::Uuid::CreateString("{32C32642-5832-4997-A478-F288C734425D}"), 6); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry originalMissingDependency( // The product ID is a link to another table, it will fail to write this entry if this is invalid. m_data->m_product3.m_productID, "Scanner Name", "1.0.0", "Source File Fingerprint", assetId.m_guid, assetId.m_subId, "Source String", "last Scan Time", 0); EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(originalMissingDependency)); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry readMissingDependency; EXPECT_TRUE(m_data->m_connection.GetMissingProductDependencyByMissingProductDependencyId( originalMissingDependency.m_missingProductDependencyId, readMissingDependency)); EXPECT_EQ(originalMissingDependency, readMissingDependency); // Test each field separately. AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry updatedMissingDependency(originalMissingDependency); updatedMissingDependency.m_productPK = m_data->m_product1.m_productID; SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency); updatedMissingDependency.m_scannerId = "Different Scanner Name"; SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency); updatedMissingDependency.m_scannerVersion = "Different Scanner Version"; SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency); updatedMissingDependency.m_sourceFileFingerprint = "Different Fingerprint"; SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency); updatedMissingDependency.m_dependencySourceGuid = AZ::Uuid::CreateString("{6C3ED7B4-E6F1-4163-9141-54F5DC1D9C35}"); SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency); updatedMissingDependency.m_dependencySubId = 3; SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency); updatedMissingDependency.m_missingDependencyString = "Different Source String"; SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency); updatedMissingDependency.m_lastScanTime = "Different Scan Time"; SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency); updatedMissingDependency.m_scanTimeSecondsSinceEpoch = 1; SetAndCheckMissingDependency(updatedMissingDependency, originalMissingDependency); } void AssetDatabaseTest::SetAndCheckMissingDependency( AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& updatedMissingDependency, const AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& originalMissingDependency) { EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(updatedMissingDependency)); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry readMissingDependency; EXPECT_TRUE(m_data->m_connection.GetMissingProductDependencyByMissingProductDependencyId( originalMissingDependency.m_missingProductDependencyId, readMissingDependency)); EXPECT_EQ(updatedMissingDependency, readMissingDependency); // MissingProductDependencyDatabaseEntry doesn't override the != operator EXPECT_FALSE(readMissingDependency == originalMissingDependency); } TEST_F(AssetDatabaseTest, MissingDependencyTable_WriteAndReadMissingDependenciesByProductId_ResultsMatch) { CreateCoverageTestData(); AZStd::vector assetIds; assetIds.push_back(AZ::Data::AssetId(AZ::Uuid::CreateString("{FDAC3A8C-26D1-47D9-88B0-647BCED826DB}"), 10)); assetIds.push_back(AZ::Data::AssetId(AZ::Uuid::CreateString("{261E8996-7309-4D18-986F-EC6EDE910A70}"), 20)); assetIds.push_back(AZ::Data::AssetId(AZ::Uuid::CreateString("{2FA88E3A-D6E4-4192-B865-4DDD61AE7492}"), 30)); // The product ID is a link to another table, it will fail to write this entry if this is invalid. AZ::s64 productPK = m_data->m_product2.m_productID; AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntryContainer writeMissingDependencies; writeMissingDependencies.push_back(AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry( productPK, "Scanner 0", "0.0.0", "Fingerprint 0", assetIds[0].m_guid, assetIds[0].m_subId, "Source String 0", "last Scan Time 0", 0)); writeMissingDependencies.push_back(AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry( productPK, "Scanner 1", "1.1.1", "Fingerprint 1", assetIds[1].m_guid, assetIds[1].m_subId, "Source String 1", "last Scan Time 1", 1)); writeMissingDependencies.push_back(AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry( productPK, "Scanner 2", "2.2.2", "Fingerprint 2", assetIds[2].m_guid, assetIds[2].m_subId, "Source String 2", "last Scan Time 2", 2)); EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(writeMissingDependencies[0])); EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(writeMissingDependencies[1])); EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(writeMissingDependencies[2])); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntryContainer readMissingDependencies; EXPECT_TRUE(m_data->m_connection.GetMissingProductDependenciesByProductId(productPK, readMissingDependencies)); EXPECT_EQ(readMissingDependencies.size(), writeMissingDependencies.size()); for (int dependencyIndex = 0; dependencyIndex < writeMissingDependencies.size(); ++dependencyIndex) { EXPECT_EQ(readMissingDependencies[dependencyIndex], writeMissingDependencies[dependencyIndex]); } } TEST_F(AssetDatabaseTest, MissingDependencyTable_WriteAndDeleteMissingDependencyByDependencyId_MissingDependencyRecordDeleted) { CreateCoverageTestData(); // Use a non-zero sub ID to verify it writes and reads correctly. AZ::Data::AssetId assetId(AZ::Uuid::CreateString("{12209A94-AF18-44BB-8A62-96F35291B2E1}"), 3); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry writeMissingDependency( // The product ID is a link to another table, it will fail to write this entry if this is invalid. m_data->m_product1.m_productID, "Scanner Name", "1.0.0", "Source File Fingerprint", assetId.m_guid, assetId.m_subId, "Source String", "last Scan Time", 0); EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(writeMissingDependency)); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry readMissingDependency; EXPECT_TRUE(m_data->m_connection.GetMissingProductDependencyByMissingProductDependencyId( writeMissingDependency.m_missingProductDependencyId, readMissingDependency)); // Verify that it was written to the DB before erasing it. EXPECT_EQ(writeMissingDependency, readMissingDependency); EXPECT_TRUE(m_data->m_connection.DeleteMissingProductDependencyByProductId(writeMissingDependency.m_missingProductDependencyId)); EXPECT_FALSE(m_data->m_connection.GetMissingProductDependencyByMissingProductDependencyId( writeMissingDependency.m_missingProductDependencyId, readMissingDependency)); } // Verify that clearing missing product dependencies by product ID clears every missing dependency for that product ID. TEST_F(AssetDatabaseTest, MissingDependencyTable_DeleteMultipleMissingDependenciesForOneProduct_MissingDependencyRecordsDeleted) { CreateCoverageTestData(); // Use a non-zero sub ID to verify it writes and reads correctly. AZ::Data::AssetId assetId(AZ::Uuid::CreateString("{12209A94-AF18-44BB-8A62-96F35291B2E1}"), 3); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry firstMissingDependency( // The product ID is a link to another table, it will fail to write this entry if this is invalid. m_data->m_product1.m_productID, "Scanner Name", "1.0.0", "Source File Fingerprint", assetId.m_guid, assetId.m_subId, "Source String", "last Scan Time", 0); EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(firstMissingDependency)); AZ::Data::AssetId secondMissingAssetId(AZ::Uuid::CreateString("{12209A94-FFFF-FFFF-8A62-96F35291B2E1}"), 4); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry secondMissingDependency( // Use the same product ID as the first missing dependency m_data->m_product1.m_productID, "Scanner Name 2", "1.0.0", "Source File Fingerprint", secondMissingAssetId.m_guid, secondMissingAssetId.m_subId, "Source String", "last Scan Time", 0); EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(secondMissingDependency)); AZStd::unordered_set expectedMissingDependencies; expectedMissingDependencies.insert(firstMissingDependency.m_missingProductDependencyId); expectedMissingDependencies.insert(secondMissingDependency.m_missingProductDependencyId); // Tests can't be ran inside the lambda, so cache results and check after. bool foundUnexpectedDependency = false; m_data->m_connection.QueryMissingProductDependencyByProductId( m_data->m_product1.m_productID, [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& entry) { if (expectedMissingDependencies.find(entry.m_missingProductDependencyId) == expectedMissingDependencies.end()) { foundUnexpectedDependency = true; } else { expectedMissingDependencies.erase(entry.m_missingProductDependencyId); } return true; }); EXPECT_FALSE(foundUnexpectedDependency); EXPECT_EQ(expectedMissingDependencies.size(), 0); EXPECT_TRUE(m_data->m_connection.DeleteMissingProductDependencyByProductId(m_data->m_product1.m_productID)); foundUnexpectedDependency = false; m_data->m_connection.QueryMissingProductDependencyByProductId( m_data->m_product1.m_productID, [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& /*entry*/) { // No dependencies should be found for this product. foundUnexpectedDependency = true; return false; }); EXPECT_FALSE(foundUnexpectedDependency); } // Verify that clearing missing dependencies for one product ID does not clear it for another product ID. TEST_F(AssetDatabaseTest, MissingDependencyTable_DeleteMissingDependenciesForOneProduct_MissingDependenciesNotDeletedForOtherProduct) { CreateCoverageTestData(); // Use a non-zero sub ID to verify it writes and reads correctly. AZ::Data::AssetId assetId(AZ::Uuid::CreateString("{12209A94-AF18-44BB-8A62-96F35291B2E1}"), 3); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry firstMissingDependency( // The product ID is a link to another table, it will fail to write this entry if this is invalid. m_data->m_product1.m_productID, "Scanner Name", "1.0.0", "Source File Fingerprint", assetId.m_guid, assetId.m_subId, "Source String", "last Scan Time", 0); EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(firstMissingDependency)); AZ::Data::AssetId secondMissingAssetId(AZ::Uuid::CreateString("{12209A94-FFFF-FFFF-8A62-96F35291B2E1}"), 4); AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry secondMissingDependency( // Use the same product ID as the first missing dependency m_data->m_product3.m_productID, "Scanner Name 2", "1.0.0", "Source File Fingerprint", secondMissingAssetId.m_guid, secondMissingAssetId.m_subId, "Source String", "last Scan Time", 0); EXPECT_TRUE(m_data->m_connection.SetMissingProductDependency(secondMissingDependency)); // Verify both missing dependencies are set. size_t dependenciesFound = 0; m_data->m_connection.QueryMissingProductDependencyByProductId( m_data->m_product1.m_productID, [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& /*entry*/) { ++dependenciesFound; return true; }); EXPECT_EQ(dependenciesFound, 1); dependenciesFound = 0; m_data->m_connection.QueryMissingProductDependencyByProductId( m_data->m_product3.m_productID, [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& /*entry*/) { ++dependenciesFound; return true; }); EXPECT_EQ(dependenciesFound, 1); // Delete the first product's missing dependencies. EXPECT_TRUE(m_data->m_connection.DeleteMissingProductDependencyByProductId(m_data->m_product1.m_productID)); // Verify the first product's missing dependency is gone. dependenciesFound = 0; m_data->m_connection.QueryMissingProductDependencyByProductId( m_data->m_product1.m_productID, [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& /*entry*/) { ++dependenciesFound; return false; }); // No dependencies should be found for this product. EXPECT_EQ(dependenciesFound, 0); // Verify the second product's missing dependency is still there. dependenciesFound = 0; m_data->m_connection.QueryMissingProductDependencyByProductId( m_data->m_product3.m_productID, [&](AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& /*entry*/) { ++dependenciesFound; return true; }); EXPECT_EQ(dependenciesFound, 1); } TEST_F(AssetDatabaseTest, AddLargeNumberOfSourceDependencies_PerformanceTest) { CreateCoverageTestData(); SourceFileDependencyEntryContainer resultSourceDependencies; resultSourceDependencies.reserve(20000); AZ::Uuid builderGuid = AZ::Uuid::CreateRandom(); // emit 20,000 source dependencies for the same origin file: AZStd::string originFile("myfile.txt"); for (AZ::u32 sourceIndex = 0; sourceIndex < 20000; ++sourceIndex) { AZStd::string dependentFile = AZStd::string::format("otherfile%i.txt", sourceIndex); SourceFileDependencyEntry entry(builderGuid, originFile.c_str(), dependentFile.c_str(), SourceFileDependencyEntry::DEP_SourceToSource, true); resultSourceDependencies.emplace_back(AZStd::move(entry)); } EXPECT_TRUE(m_data->m_connection.SetSourceFileDependencies(resultSourceDependencies)); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this // read them back resultSourceDependencies.clear(); EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid, originFile.c_str(), SourceFileDependencyEntry::DEP_SourceToSource, resultSourceDependencies)); EXPECT_EQ(resultSourceDependencies.size(), 20000); } TEST_F(AssetDatabaseTest, SourceFileDependencies_CorrectnessTest) { CreateCoverageTestData(); AZ::Uuid builderGuid1 = AZ::Uuid::CreateRandom(); AZ::Uuid builderGuid2 = AZ::Uuid::CreateRandom(); SourceFileDependencyEntryContainer entries; // add the two different kinds of dependencies. entries.push_back(SourceFileDependencyEntry(builderGuid1, "file1.txt", "file1dependson1.txt", SourceFileDependencyEntry::DEP_SourceToSource, true)); entries.push_back(SourceFileDependencyEntry(builderGuid2, "file1.txt", "file1dependson2.txt", SourceFileDependencyEntry::DEP_SourceToSource, true)); entries.push_back(SourceFileDependencyEntry(builderGuid1, "file1.txt", "file1dependson1job.txt", SourceFileDependencyEntry::DEP_JobToJob, true)); entries.push_back(SourceFileDependencyEntry(builderGuid2, "file1.txt", "file1dependson2job.txt", SourceFileDependencyEntry::DEP_JobToJob, true)); entries.push_back(SourceFileDependencyEntry(builderGuid1, "file2.txt", "file2dependson1.txt", SourceFileDependencyEntry::DEP_SourceToSource, true)); entries.push_back(SourceFileDependencyEntry(builderGuid1, "file2.txt", "file2dependson1job.txt", SourceFileDependencyEntry::DEP_JobToJob, true)); ASSERT_TRUE(m_data->m_connection.SetSourceFileDependencies(entries)); SourceFileDependencyEntryContainer resultEntries; AZStd::string searchFor; auto SearchPredicate = [&searchFor](const SourceFileDependencyEntry& element) { return element.m_dependsOnSource == searchFor; }; auto SearchPredicateReverse = [&searchFor](const SourceFileDependencyEntry& element) { return element.m_source == searchFor; }; // ask for only the source-to-source dependencies of file1.txt for builder1 EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid1, "file1.txt", SourceFileDependencyEntry::DEP_SourceToSource, resultEntries)); EXPECT_EQ(resultEntries.size(), 1); searchFor = "file1dependson1.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end()); resultEntries.clear(); // ask for only the source-to-source dependencies of file1.txt for builder2 EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid2, "file1.txt", SourceFileDependencyEntry::DEP_SourceToSource, resultEntries)); EXPECT_EQ(resultEntries.size(), 1); searchFor = "file1dependson2.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end()); resultEntries.clear(); // ask for the source-to-source dependencies of file1.txt for ANY builder, we shiould get both. EXPECT_TRUE(m_data->m_connection.GetDependsOnSourceBySource("file1.txt", SourceFileDependencyEntry::DEP_SourceToSource, resultEntries)); EXPECT_EQ(resultEntries.size(), 2); searchFor = "file1dependson1.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end()); searchFor = "file1dependson2.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end()); resultEntries.clear(); // now ask for the job-to-job dependencies for builder 1 EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid1, "file1.txt", SourceFileDependencyEntry::DEP_JobToJob, resultEntries)); EXPECT_EQ(resultEntries.size(), 1); searchFor = "file1dependson1job.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end()); resultEntries.clear(); // now ask for the job-to-job dependencies for builder 2 EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid2, "file1.txt", SourceFileDependencyEntry::DEP_JobToJob, resultEntries)); EXPECT_EQ(resultEntries.size(), 1); searchFor = "file1dependson2job.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end()); resultEntries.clear(); // now ask for the job-to-job dependencies for any builder EXPECT_TRUE(m_data->m_connection.GetDependsOnSourceBySource( "file1.txt", SourceFileDependencyEntry::DEP_JobToJob, resultEntries)); EXPECT_EQ(resultEntries.size(), 2); searchFor = "file1dependson1job.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end()); searchFor = "file1dependson2job.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end()); resultEntries.clear(); // now ask for the reverse dependencies - we should find one source-to-source EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByDependsOnSource("file1dependson1.txt", SourceFileDependencyEntry::DEP_SourceToSource, resultEntries)); EXPECT_EQ(resultEntries.size(), 1); searchFor = "file1.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicateReverse), resultEntries.end()); resultEntries.clear(); // now ask for the reverse dependencies - we should find no job-to-job for this: EXPECT_FALSE(m_data->m_connection.GetSourceFileDependenciesByDependsOnSource("file1dependson1.txt", SourceFileDependencyEntry::DEP_JobToJob, resultEntries)); EXPECT_EQ(resultEntries.size(), 0); resultEntries.clear(); // now ask for the reverse dependencies - we should find one 'any' type. EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByDependsOnSource("file1dependson1.txt", SourceFileDependencyEntry::DEP_Any, resultEntries)); EXPECT_EQ(resultEntries.size(), 1); searchFor = "file1.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicateReverse), resultEntries.end()); resultEntries.clear(); // now try the other file - remember the ID for later ASSERT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid1, "file2.txt", SourceFileDependencyEntry::DEP_SourceToSource, resultEntries)); EXPECT_EQ(resultEntries.size(), 1); searchFor = "file2dependson1.txt"; EXPECT_NE(AZStd::find_if(resultEntries.begin(), resultEntries.end(), SearchPredicate), resultEntries.end()); AZ::s64 entryIdSource = resultEntries[0].m_sourceDependencyID; resultEntries.clear(); // and with Job-to-job dependencies EXPECT_TRUE(m_data->m_connection.GetSourceFileDependenciesByBuilderGUIDAndSource(builderGuid1, "file2.txt", SourceFileDependencyEntry::DEP_JobToJob, resultEntries)); ASSERT_EQ(resultEntries.size(), 1); EXPECT_EQ(resultEntries[0].m_builderGuid, builderGuid1); EXPECT_STREQ(resultEntries[0].m_source.c_str(), "file2.txt"); EXPECT_NE(resultEntries[0].m_sourceDependencyID, AzToolsFramework::AssetDatabase::InvalidEntryId); EXPECT_STREQ(resultEntries[0].m_dependsOnSource.c_str(), "file2dependson1job.txt"); EXPECT_EQ(resultEntries[0].m_typeOfDependency, SourceFileDependencyEntry::DEP_JobToJob); AZ::s64 entryIdJob = resultEntries[0].m_sourceDependencyID; resultEntries.clear(); SourceFileDependencyEntry resultValue; EXPECT_TRUE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdSource, resultValue)); EXPECT_EQ(resultValue.m_sourceDependencyID, entryIdSource); EXPECT_EQ(resultValue.m_typeOfDependency, SourceFileDependencyEntry::DEP_SourceToSource); EXPECT_STREQ(resultValue.m_source.c_str(), "file2.txt"); EXPECT_STREQ(resultValue.m_dependsOnSource.c_str(), "file2dependson1.txt"); EXPECT_EQ(resultValue.m_builderGuid, builderGuid1); EXPECT_TRUE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdJob, resultValue)); EXPECT_EQ(resultValue.m_sourceDependencyID, entryIdJob); EXPECT_EQ(resultValue.m_typeOfDependency, SourceFileDependencyEntry::DEP_JobToJob); EXPECT_STREQ(resultValue.m_source.c_str(), "file2.txt"); EXPECT_STREQ(resultValue.m_dependsOnSource.c_str(), "file2dependson1job.txt"); EXPECT_EQ(resultValue.m_builderGuid, builderGuid1); // removal of source m_data->m_connection.RemoveSourceFileDependency(entryIdSource); EXPECT_FALSE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdSource, resultValue)); EXPECT_TRUE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdJob, resultValue)); // removeal of job m_data->m_connection.RemoveSourceFileDependency(entryIdJob); EXPECT_FALSE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdSource, resultValue)); EXPECT_FALSE(m_data->m_connection.GetSourceFileDependencyBySourceDependencyId(entryIdJob, resultValue)); } TEST_F(AssetDatabaseTest, UpdateNonExistentFile_Fails) { CreateCoverageTestData(); ASSERT_FALSE(m_data->m_connection.UpdateFileModTimeAndHashByFileNameAndScanFolderId("testfile.txt", m_data->m_scanFolder.m_scanFolderID, 1234, 1111)); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, UpdateExistingFile_Succeeds) { CreateCoverageTestData(); FileDatabaseEntry entry; entry.m_fileName = "testfile.txt"; entry.m_scanFolderPK = m_data->m_scanFolder.m_scanFolderID; bool entryAlreadyExists; ASSERT_TRUE(m_data->m_connection.InsertFile(entry, entryAlreadyExists)); ASSERT_FALSE(entryAlreadyExists); ASSERT_TRUE(m_data->m_connection.UpdateFileModTimeAndHashByFileNameAndScanFolderId("testfile.txt", m_data->m_scanFolder.m_scanFolderID, 1234, 1111)); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); // not allowed to assert on this } TEST_F(AssetDatabaseTest, GetSourceBySourceName_InvalidInput_SourceNotFound) { CreateCoverageTestData(); SourceDatabaseEntry resultSource; EXPECT_FALSE(m_data->m_connection.GetSourceBySourceName("non_existent", resultSource)); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); } TEST_F(AssetDatabaseTest, GetSourceBySourceName_ValidInput_SourceFound) { CreateCoverageTestData(); SourceDatabaseEntry resultSource; EXPECT_TRUE(m_data->m_connection.GetSourceBySourceName("somefile.tif", resultSource)); EXPECT_EQ(resultSource.m_sourceGuid, m_data->m_sourceFile1.m_sourceGuid); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); } TEST_F(AssetDatabaseTest, GetDirectReverseProductDependenciesBySourceGuidSubID_InvalidInput_ProductsNotFound) { CreateCoverageTestData(); ProductDependencyDatabaseEntry productDependency; productDependency.m_productPK = m_data->m_product1.m_productID; productDependency.m_dependencySourceGuid = m_data->m_sourceFile1.m_sourceGuid; productDependency.m_dependencySubID = m_data->m_product1.m_subID; ASSERT_TRUE(m_data->m_connection.SetProductDependency(productDependency)); ProductDatabaseEntryContainer resultProducts; AZ::Uuid invalidGuid = AZ::Uuid::CreateNull(); AZ::s32 invalidSubId = -1; EXPECT_FALSE(m_data->m_connection.GetDirectReverseProductDependenciesBySourceGuidSubId(invalidGuid, m_data->m_product1.m_subID, resultProducts)); EXPECT_FALSE(m_data->m_connection.GetDirectReverseProductDependenciesBySourceGuidSubId(m_data->m_sourceFile1.m_sourceGuid, invalidSubId, resultProducts)); EXPECT_FALSE(m_data->m_connection.GetDirectReverseProductDependenciesBySourceGuidSubId(invalidGuid, invalidSubId, resultProducts)); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); } TEST_F(AssetDatabaseTest, GetDirectReverseProductDependenciesBySourceGuidSubID_ValidInput_ProductsFound) { CreateCoverageTestData(); ProductDependencyDatabaseEntry productDependency; productDependency.m_productPK = m_data->m_product1.m_productID; productDependency.m_dependencySourceGuid = m_data->m_sourceFile1.m_sourceGuid; productDependency.m_dependencySubID = m_data->m_product1.m_subID; ASSERT_TRUE(m_data->m_connection.SetProductDependency(productDependency)); ProductDatabaseEntryContainer resultProducts; EXPECT_TRUE(m_data->m_connection.GetDirectReverseProductDependenciesBySourceGuidSubId(m_data->m_sourceFile1.m_sourceGuid, m_data->m_product1.m_subID, resultProducts)); ASSERT_EQ(resultProducts.size(), 1); EXPECT_EQ(resultProducts[0], m_data->m_product1); EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); } TEST_F(AssetDatabaseTest, QueryProductDependenciesUnresolvedAdvanced_HandlesLargeSearch_Success) { CreateCoverageTestData(); constexpr int NumTestPaths = 10000; AZStd::vector searchPaths; searchPaths.reserve(NumTestPaths); for (int i = 0; i < NumTestPaths; ++i) { searchPaths.emplace_back(AZStd::string::format("%d.txt", i)); } ProductDependencyDatabaseEntry dependency1(m_data->m_product1.m_productID, AZ::Uuid::CreateNull(), 0, 0, "pc", false, "*.txt"); ProductDependencyDatabaseEntry dependency2(m_data->m_product1.m_productID, AZ::Uuid::CreateNull(), 0, 0, "pc", false, "default.xml"); m_data->m_connection.SetProductDependency(dependency1); m_data->m_connection.SetProductDependency(dependency2); AZStd::vector matches; matches.reserve(NumTestPaths); ASSERT_TRUE(m_data->m_connection.QueryProductDependenciesUnresolvedAdvanced(searchPaths, [&matches](AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry& /*entry*/, const AZStd::string& path) { matches.push_back(path); return true; })); ASSERT_EQ(matches.size(), searchPaths.size()); // Check the first few results match for(int i = 0; i < 10 && i < NumTestPaths; ++i) { ASSERT_STREQ(matches[i].c_str(), searchPaths[i].c_str()); } matches.clear(); searchPaths.clear(); searchPaths.push_back("default.xml"); // 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 ASSERT_TRUE(m_data->m_connection.QueryProductDependenciesUnresolvedAdvanced(searchPaths, [&matches](AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry& /*entry*/, const AZStd::string& path) { matches.push_back(path); return true; })); ASSERT_THAT(matches, testing::ElementsAreArray(searchPaths)); } TEST_F(AssetDatabaseTest, QueryCombined_Succeeds) { // This test specifically checks that the legacy subIds returned by QueryCombined are correctly matched to only the one product that they're associated with using namespace AzToolsFramework::AssetDatabase; CreateCoverageTestData(); auto subIds = { 123, 134, 155, 166, 177 }; AZStd::vector createdLegacySubIds; for(int subId : subIds) { LegacySubIDsEntry subIdEntry; subIdEntry.m_productPK = m_data->m_product1.m_productID; subIdEntry.m_subID = subId; ASSERT_TRUE(m_data->m_connection.CreateOrUpdateLegacySubID(subIdEntry)); createdLegacySubIds.push_back(subIdEntry); } AZStd::vector results; auto databaseQueryCallback = [&](AzToolsFramework::AssetDatabase::CombinedDatabaseEntry& combined) -> bool { results.push_back(combined); return true; }; ASSERT_TRUE(m_data->m_connection.QueryCombined(databaseQueryCallback, AZ::Uuid::CreateNull(), nullptr, nullptr, AzToolsFramework::AssetSystem::JobStatus::Any, /*includeLegacyIds*/ true)); bool foundProductWithLegacyIds = false; for(const auto& combined : results) { if (combined.m_productID == m_data->m_product1.m_productID) { foundProductWithLegacyIds = true; ASSERT_THAT(combined.m_legacySubIDs, testing::UnorderedElementsAreArray(createdLegacySubIds)); } else { ASSERT_EQ(combined.m_legacySubIDs.size(), 0); } } ASSERT_TRUE(foundProductWithLegacyIds); } TEST_F(AssetDatabaseTest, InsertFile_Existing_ReturnsExisting) { CreateCoverageTestData(); using namespace AzToolsFramework::AssetDatabase; FileDatabaseEntry fileEntry; fileEntry.m_fileName = "blah"; fileEntry.m_scanFolderPK = m_data->m_scanFolder.m_scanFolderID; bool entryAlreadyExists = false; ASSERT_TRUE(m_data->m_connection.InsertFile(fileEntry, entryAlreadyExists)); ASSERT_FALSE(entryAlreadyExists); fileEntry.m_fileID = InvalidEntryId; // InsertFile will update the Id, we want to test without a specified Id ASSERT_TRUE(m_data->m_connection.InsertFile(fileEntry, entryAlreadyExists)); ASSERT_TRUE(entryAlreadyExists); // Test one more time, with the Id set to a specific entry now ASSERT_NE(fileEntry.m_fileID, InvalidEntryId); ASSERT_TRUE(m_data->m_connection.InsertFile(fileEntry, entryAlreadyExists)); ASSERT_TRUE(entryAlreadyExists); } class QueryLoggingTraceHandler : public AZ::Debug::TraceMessageBus::Handler { public: QueryLoggingTraceHandler() { BusConnect(); } ~QueryLoggingTraceHandler() { BusDisconnect(); } bool OnPrintf(const char* /*window*/, const char* message) override { if (m_expectedMessage.compare(message) == 0) { m_expectedMessageFound = true; } return false; // Return false so it also prints out to the log. } AZStd::string m_expectedMessage; bool m_expectedMessageFound = false; private: }; TEST_F(AssetDatabaseTest, LoggingEnabled_InsertFile_LogMessageMatches) { using namespace AzToolsFramework::AssetDatabase; CreateCoverageTestData(); QueryLoggingTraceHandler queryLoggingTraceHandler; queryLoggingTraceHandler.m_expectedMessage = "SELECT * FROM Files WHERE ScanFolderPK = :scanfolderpk AND FileName = :filename; = Params :scanfolderpk = `1`, :filename = `blah`\n"; m_data->m_connection.SetQueryLogging(true); FileDatabaseEntry fileEntry; fileEntry.m_fileName = "blah"; fileEntry.m_scanFolderPK = m_data->m_scanFolder.m_scanFolderID; bool entryAlreadyExists = false; ASSERT_TRUE(m_data->m_connection.InsertFile(fileEntry, entryAlreadyExists)); m_data->m_connection.SetQueryLogging(false); ASSERT_TRUE(queryLoggingTraceHandler.m_expectedMessageFound); } } // end namespace UnitTests