From 032a35e495505fff83724b0daeaacd0b2ce1212d Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 15 Jul 2021 18:44:38 -0700 Subject: [PATCH] fix Windows unity build Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Tests/test_Main.cpp | 6 +- .../ComponentEntityEditorPlugin/dllmain.cpp | 7 - Code/Editor/QtViewPaneManager.h | 4 - .../UI/Docking/DockWidgetUtils.cpp | 1 + .../Code/Source/Converters/FIR-Weights.cpp | 5 + .../Code/Source/Converters/FIR-Weights.h | 6 +- Gems/Atom/RHI/Code/Tests/AllocatorTests.cpp | 4 +- Gems/Atom/RHI/Code/Tests/BufferTests.cpp | 4 +- Gems/Atom/RHI/Code/Tests/FrameGraphTests.cpp | 4 +- .../RHI/Code/Tests/FrameSchedulerTests.cpp | 4 +- .../RHI/Code/Tests/IndirectBufferTests.cpp | 4 +- .../RHI/Code/Tests/PipelineStateTests.cpp | 4 +- Gems/Atom/RHI/Code/Tests/Query.cpp | 1 + Gems/Atom/RHI/Code/Tests/QueryTests.cpp | 4 +- .../Platform/Windows/RHI/DX12_Windows.h | 2 + .../Builders/CopyDependencyBuilderTest.cpp | 2000 +++++++++-------- .../Code/Tests/Builders/LevelBuilderTest.cpp | 646 +++--- .../Tests/Builders/MaterialBuilderTests.cpp | 419 ++-- .../Code/Tests/Builders/SliceBuilderTests.cpp | 1159 +++++----- 19 files changed, 2143 insertions(+), 2141 deletions(-) diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/Tests/test_Main.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/Tests/test_Main.cpp index ccff4f8b1a..8a14cd3e04 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/Tests/test_Main.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/Tests/test_Main.cpp @@ -10,8 +10,6 @@ #include -using namespace AZ; - // Handle asserts class ToolsFrameworkHook : public AZ::Test::ITestEnvironment @@ -19,12 +17,12 @@ class ToolsFrameworkHook public: void SetupEnvironment() override { - AllocatorInstance::Create(); + AZ::AllocatorInstance::Create(); } void TeardownEnvironment() override { - AllocatorInstance::Destroy(); + AZ::AllocatorInstance::Destroy(); } }; diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/dllmain.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/dllmain.cpp index aac4de5491..bcaf1cdbc6 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/dllmain.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/dllmain.cpp @@ -5,13 +5,6 @@ * */ -// All plugins suffer from the following warning: -// warning C4273: 'GetIEditor' : inconsistent dll linkage -// GetIEditor() is forward-declared using EDITOR_CORE_API, which without EDITOR_CORE set, -// results in dllimport rather than dllexport. This define ensure it's consistently and -// properly defined for export. -#define EDITOR_CORE - #include #include diff --git a/Code/Editor/QtViewPaneManager.h b/Code/Editor/QtViewPaneManager.h index 2b3412aad6..b0524cd531 100644 --- a/Code/Editor/QtViewPaneManager.h +++ b/Code/Editor/QtViewPaneManager.h @@ -7,10 +7,6 @@ #pragma once -#if !defined(Q_MOC_RUN) -#include "Include/EditorCoreAPI.h" -#endif - #if !defined(Q_MOC_RUN) #include "Include/EditorCoreAPI.h" #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Docking/DockWidgetUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Docking/DockWidgetUtils.cpp index 2978fbf487..5bb7ba81da 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Docking/DockWidgetUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Docking/DockWidgetUtils.cpp @@ -5,6 +5,7 @@ * */ +#include #include AZ_PUSH_DISABLE_WARNING(4251 4244 4458, "-Wunknown-warning-option") // 4251: 'QTextStream::d_ptr': class 'QScopedPointer>' needs to have dll-interface to be used by clients of class 'QTextStream' diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.cpp index 77a25cbb46..607644a490 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.cpp @@ -14,6 +14,11 @@ namespace ImageProcessingAtom { + float round(float x) + { + return ((x) >= 0) ? floor((x) + 0.5) : ceil((x)-0.5); + } + void calculateFilterRange(unsigned int srcFactor, int& srcFirst, int& srcLast, unsigned int dstFactor, int dstFirst, int dstLast, double blurFactor, class IWindowFunction* windowFunction) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.h index abb53093f5..22ad6f13d0 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.h @@ -22,11 +22,7 @@ namespace ImageProcessingAtom inline DataType minimum(const DataType& ths, const DataType& tht) { return (ths < tht ? ths : tht); } template inline DataType maximum(const DataType& ths, const DataType& tht) { return (ths > tht ? ths : tht); } - - #ifndef round - #define round(x) ((x) >= 0) ? floor((x) + 0.5) : ceil((x) - 0.5) - #endif - + /* #################################################################################################################### */ diff --git a/Gems/Atom/RHI/Code/Tests/AllocatorTests.cpp b/Gems/Atom/RHI/Code/Tests/AllocatorTests.cpp index c2b25cf9d6..8c7e7f3db0 100644 --- a/Gems/Atom/RHI/Code/Tests/AllocatorTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/AllocatorTests.cpp @@ -12,12 +12,12 @@ #include #include -using namespace AZ; - #define PRINTF(...) do { UnitTest::ColoredPrintf(UnitTest::COLOR_GREEN, "[ ] "); UnitTest::ColoredPrintf(UnitTest::COLOR_YELLOW, __VA_ARGS__); } while(0) namespace UnitTest { + using namespace AZ; + class AllocatorTest : public RHITestFixture { diff --git a/Gems/Atom/RHI/Code/Tests/BufferTests.cpp b/Gems/Atom/RHI/Code/Tests/BufferTests.cpp index d9e7116d1d..49cd815428 100644 --- a/Gems/Atom/RHI/Code/Tests/BufferTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/BufferTests.cpp @@ -9,10 +9,10 @@ #include #include -using namespace AZ; - namespace UnitTest { + using namespace AZ; + class BufferTests : public RHITestFixture { diff --git a/Gems/Atom/RHI/Code/Tests/FrameGraphTests.cpp b/Gems/Atom/RHI/Code/Tests/FrameGraphTests.cpp index 097b0f6477..3e78513f7f 100644 --- a/Gems/Atom/RHI/Code/Tests/FrameGraphTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/FrameGraphTests.cpp @@ -15,10 +15,10 @@ #include #include -using namespace AZ; - namespace UnitTest { + using namespace AZ; + class FrameGraphTests : public RHITestFixture { diff --git a/Gems/Atom/RHI/Code/Tests/FrameSchedulerTests.cpp b/Gems/Atom/RHI/Code/Tests/FrameSchedulerTests.cpp index 269e4e73c6..5da0cb0a3d 100644 --- a/Gems/Atom/RHI/Code/Tests/FrameSchedulerTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/FrameSchedulerTests.cpp @@ -12,10 +12,10 @@ #include #include -using namespace AZ; - namespace UnitTest { + using namespace AZ; + struct ImportedImage { RHI::AttachmentId m_id; diff --git a/Gems/Atom/RHI/Code/Tests/IndirectBufferTests.cpp b/Gems/Atom/RHI/Code/Tests/IndirectBufferTests.cpp index b63e9dc5e3..c9d88b5b91 100644 --- a/Gems/Atom/RHI/Code/Tests/IndirectBufferTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/IndirectBufferTests.cpp @@ -18,10 +18,10 @@ #include #include -using namespace AZ; - namespace UnitTest { + using namespace AZ; + class IndirectBufferTests : public RHITestFixture { diff --git a/Gems/Atom/RHI/Code/Tests/PipelineStateTests.cpp b/Gems/Atom/RHI/Code/Tests/PipelineStateTests.cpp index 712efca658..3dfaca954a 100644 --- a/Gems/Atom/RHI/Code/Tests/PipelineStateTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/PipelineStateTests.cpp @@ -16,10 +16,10 @@ #include -using namespace AZ; - namespace UnitTest { + using namespace AZ; + class PipelineStateTests : public RHITestFixture { diff --git a/Gems/Atom/RHI/Code/Tests/Query.cpp b/Gems/Atom/RHI/Code/Tests/Query.cpp index e6b3619544..aab895a2be 100644 --- a/Gems/Atom/RHI/Code/Tests/Query.cpp +++ b/Gems/Atom/RHI/Code/Tests/Query.cpp @@ -9,6 +9,7 @@ namespace UnitTest { using namespace AZ; + RHI::ResultCode Query::BeginInternal([[maybe_unused]] RHI::CommandList& commandList, [[maybe_unused]] RHI::QueryControlFlags flags) { return RHI::ResultCode::Success; diff --git a/Gems/Atom/RHI/Code/Tests/QueryTests.cpp b/Gems/Atom/RHI/Code/Tests/QueryTests.cpp index 1b01750468..233e8973c3 100644 --- a/Gems/Atom/RHI/Code/Tests/QueryTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/QueryTests.cpp @@ -11,10 +11,10 @@ #include #include -using namespace AZ; - namespace UnitTest { + using namespace AZ; + class QueryTests : public RHITestFixture { diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h index fd88b08f04..b5452e7bb5 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h @@ -7,6 +7,8 @@ #pragma once +#include + #if !defined(AZ_DX12_REFCOUNTED) #error "Incorrect include of DX12_Windows.h, please include DX12.h instead of this header" #endif diff --git a/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp b/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp index bba5310d51..8779f92eeb 100644 --- a/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp +++ b/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp @@ -26,1082 +26,1086 @@ #include #include -using namespace CopyDependencyBuilder; -using namespace AZ; -using namespace AssetBuilderSDK; - -class CopyDependencyBuilderTest - : public ::testing::Test - , public UnitTest::TraceBusRedirector - , private AzToolsFramework::AssetSystemRequestBus::Handler +namespace UnitTest { -protected: - void SetUp() override + using namespace CopyDependencyBuilder; + using namespace AZ; + using namespace AssetBuilderSDK; + + class CopyDependencyBuilderTest + : public ::testing::Test + , public UnitTest::TraceBusRedirector + , private AzToolsFramework::AssetSystemRequestBus::Handler { - AZ::AllocatorInstance::Create(); - - m_app.reset(aznew AZ::ComponentApplication()); - AZ::ComponentApplication::Descriptor desc; - desc.m_useExistingAllocator = true; - m_app->Create(desc); - - if constexpr (AZ::g_currentPlatform == AZ::PlatformID::PLATFORM_WINDOWS_64) + protected: + void SetUp() override { - m_currentPlatform = "pc"; - } - else - { - m_currentPlatform = AZ::GetPlatformName(AZ::g_currentPlatform); - AZStd::to_lower(m_currentPlatform.begin(), m_currentPlatform.end()); + AZ::AllocatorInstance::Create(); + + m_app.reset(aznew AZ::ComponentApplication()); + AZ::ComponentApplication::Descriptor desc; + desc.m_useExistingAllocator = true; + m_app->Create(desc); + + if constexpr (AZ::g_currentPlatform == AZ::PlatformID::PLATFORM_WINDOWS_64) + { + m_currentPlatform = "pc"; + } + else + { + m_currentPlatform = AZ::GetPlatformName(AZ::g_currentPlatform); + AZStd::to_lower(m_currentPlatform.begin(), m_currentPlatform.end()); + } + + // Startup default local FileIO (hits OSAllocator) if not already setup. + if (AZ::IO::FileIOBase::GetInstance() == nullptr) + { + AZ::IO::FileIOBase::SetInstance(aznew AZ::IO::LocalFileIO()); + } + + const AZStd::string engineRoot = AZ::Test::GetEngineRootPath(); + AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engineRoot.c_str()); + + AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath()); + assetRoot /= "Cache"; + AZ::IO::FileIOBase::GetInstance()->SetAlias("@root@", assetRoot.c_str()); + + SerializeContext* serializeContext; + ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationRequests::GetSerializeContext); + ASSERT_TRUE(serializeContext); + + AzFramework::VersionSearchRule::Reflect(serializeContext); + AzFramework::XmlSchemaAttribute::Reflect(serializeContext); + AzFramework::XmlSchemaElement::Reflect(serializeContext); + AzFramework::MatchingRule::Reflect(serializeContext); + AzFramework::SearchRuleDefinition::Reflect(serializeContext); + AzFramework::DependencySearchRule::Reflect(serializeContext); + AzFramework::XmlSchemaAsset::Reflect(serializeContext); + + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + AzToolsFramework::AssetSystemRequestBus::Handler::BusConnect(); } - // Startup default local FileIO (hits OSAllocator) if not already setup. - if (AZ::IO::FileIOBase::GetInstance() == nullptr) + void TearDown() override { - AZ::IO::FileIOBase::SetInstance(aznew AZ::IO::LocalFileIO()); + AzToolsFramework::AssetSystemRequestBus::Handler::BusDisconnect(); + + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + + delete AZ::IO::FileIOBase::GetInstance(); + AZ::IO::FileIOBase::SetInstance(nullptr); + + m_app->Destroy(); + m_app = nullptr; + + AZ::AllocatorInstance::Destroy(); } - const AZStd::string engineRoot = AZ::Test::GetEngineRootPath(); - AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engineRoot.c_str()); + static constexpr char testFileFolder[] = "@engroot@/Gems/LmbrCentral/Code/Tests/"; - AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath()); - assetRoot /= "Cache"; - AZ::IO::FileIOBase::GetInstance()->SetAlias("@root@", assetRoot.c_str()); + AZStd::string GetFullPath(AZStd::string_view fileName) + { + return AZStd::string::format("%s%.*s", testFileFolder, aznumeric_cast(fileName.size()), fileName.data()); + } - SerializeContext* serializeContext; - ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationRequests::GetSerializeContext); - ASSERT_TRUE(serializeContext); - - AzFramework::VersionSearchRule::Reflect(serializeContext); - AzFramework::XmlSchemaAttribute::Reflect(serializeContext); - AzFramework::XmlSchemaElement::Reflect(serializeContext); - AzFramework::MatchingRule::Reflect(serializeContext); - AzFramework::SearchRuleDefinition::Reflect(serializeContext); - AzFramework::DependencySearchRule::Reflect(serializeContext); - AzFramework::XmlSchemaAsset::Reflect(serializeContext); - - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - - AzToolsFramework::AssetSystemRequestBus::Handler::BusConnect(); - } - - void TearDown() override - { - AzToolsFramework::AssetSystemRequestBus::Handler::BusDisconnect(); - - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - - delete AZ::IO::FileIOBase::GetInstance(); - AZ::IO::FileIOBase::SetInstance(nullptr); - - m_app->Destroy(); - m_app = nullptr; - - AZ::AllocatorInstance::Destroy(); - } - - static constexpr char testFileFolder[] = "@engroot@/Gems/LmbrCentral/Code/Tests/"; - - AZStd::string GetFullPath(AZStd::string_view fileName) - { - return AZStd::string::format("%s%.*s", testFileFolder, aznumeric_cast(fileName.size()), fileName.data()); - } - - void TestFailureCase(CopyDependencyBuilderWorker* worker, AZStd::string_view fileName, bool expectedResult = false) - { - AssetBuilderSDK::ProductPathDependencySet resolvedPaths; - AZStd::vector productDependencies; + void TestFailureCase(CopyDependencyBuilderWorker* worker, AZStd::string_view fileName, bool expectedResult = false) + { + AssetBuilderSDK::ProductPathDependencySet resolvedPaths; + AZStd::vector productDependencies; - AssetBuilderSDK::ProcessJobRequest request; - request.m_fullPath = GetFullPath(fileName); - request.m_sourceFile = fileName; - request.m_platformInfo.m_identifier = m_currentPlatform; + AssetBuilderSDK::ProcessJobRequest request; + request.m_fullPath = GetFullPath(fileName); + request.m_sourceFile = fileName; + request.m_platformInfo.m_identifier = m_currentPlatform; - bool result = worker->ParseProductDependencies(request, productDependencies, resolvedPaths); - ASSERT_EQ(result, expectedResult); - ASSERT_EQ(resolvedPaths.size(), 0); - ASSERT_EQ(productDependencies.size(), 0); - } - - void TestSuccessCase( - CopyDependencyBuilderWorker* worker, - AZStd::string_view fileName, - const AZStd::vector& expectedPathDependencies) - { - AZStd::vector expectedProductDependencies; - TestSuccessCase(worker, fileName, expectedPathDependencies, expectedProductDependencies); - } - - void TestSuccessCase( - CopyDependencyBuilderWorker* worker, - AZStd::string_view fileName, - const AZStd::vector& expectedPathDependencies, - const AZStd::vector& expectedProductDependencies, - const AZStd::string watchFolder = {}) - { - AssetBuilderSDK::ProductPathDependencySet resolvedPaths; - AZStd::vector productDependencies; - size_t referencedFilePathsCount = expectedPathDependencies.size(); - size_t referencedProductDependenciesCount = expectedProductDependencies.size(); - - AssetBuilderSDK::ProductPathDependencySet expectedResolvedPaths; - for (const char* path : expectedPathDependencies) - { - expectedResolvedPaths.emplace(path, AssetBuilderSDK::ProductPathDependencyType::ProductFile); + bool result = worker->ParseProductDependencies(request, productDependencies, resolvedPaths); + ASSERT_EQ(result, expectedResult); + ASSERT_EQ(resolvedPaths.size(), 0); + ASSERT_EQ(productDependencies.size(), 0); } - AssetBuilderSDK::ProcessJobRequest request; - request.m_fullPath = GetFullPath(fileName); - request.m_sourceFile = fileName; - request.m_platformInfo.m_identifier = m_currentPlatform; - request.m_watchFolder = watchFolder; - - bool result = worker->ParseProductDependencies(request, productDependencies, resolvedPaths); - ASSERT_TRUE(result); - ASSERT_EQ(resolvedPaths.size(), referencedFilePathsCount); - ASSERT_EQ(productDependencies.size(), referencedProductDependenciesCount); - if (referencedFilePathsCount > 0) + void TestSuccessCase( + CopyDependencyBuilderWorker* worker, + AZStd::string_view fileName, + const AZStd::vector& expectedPathDependencies) { - for (const AssetBuilderSDK::ProductPathDependency& dependency : expectedResolvedPaths) + AZStd::vector expectedProductDependencies; + TestSuccessCase(worker, fileName, expectedPathDependencies, expectedProductDependencies); + } + + void TestSuccessCase( + CopyDependencyBuilderWorker* worker, + AZStd::string_view fileName, + const AZStd::vector& expectedPathDependencies, + const AZStd::vector& expectedProductDependencies, + const AZStd::string watchFolder = {}) + { + AssetBuilderSDK::ProductPathDependencySet resolvedPaths; + AZStd::vector productDependencies; + size_t referencedFilePathsCount = expectedPathDependencies.size(); + size_t referencedProductDependenciesCount = expectedProductDependencies.size(); + + AssetBuilderSDK::ProductPathDependencySet expectedResolvedPaths; + for (const char* path : expectedPathDependencies) { - ASSERT_TRUE(resolvedPaths.find(dependency) != resolvedPaths.end()) << "Expected path dependency is not found in the process result"; + expectedResolvedPaths.emplace(path, AssetBuilderSDK::ProductPathDependencyType::ProductFile); } - } - if (referencedProductDependenciesCount > 0) - { - for (const AssetBuilderSDK::ProductDependency& dependency : productDependencies) + + AssetBuilderSDK::ProcessJobRequest request; + request.m_fullPath = GetFullPath(fileName); + request.m_sourceFile = fileName; + request.m_platformInfo.m_identifier = m_currentPlatform; + request.m_watchFolder = watchFolder; + + bool result = worker->ParseProductDependencies(request, productDependencies, resolvedPaths); + ASSERT_TRUE(result); + ASSERT_EQ(resolvedPaths.size(), referencedFilePathsCount); + ASSERT_EQ(productDependencies.size(), referencedProductDependenciesCount); + if (referencedFilePathsCount > 0) { - bool expectedDependencyExists = false; - for (const AssetBuilderSDK::ProductDependency& expectedProductDependency : expectedProductDependencies) + for (const AssetBuilderSDK::ProductPathDependency& dependency : expectedResolvedPaths) { - if (expectedProductDependency.m_dependencyId == dependency.m_dependencyId - && expectedProductDependency.m_flags == dependency.m_flags) - { - expectedDependencyExists = true; - break; - } + ASSERT_TRUE(resolvedPaths.find(dependency) != resolvedPaths.end()) << "Expected path dependency is not found in the process result"; } - - ASSERT_TRUE(expectedDependencyExists) << "Expected product dependency is not found in the process result"; } + if (referencedProductDependenciesCount > 0) + { + for (const AssetBuilderSDK::ProductDependency& dependency : productDependencies) + { + bool expectedDependencyExists = false; + for (const AssetBuilderSDK::ProductDependency& expectedProductDependency : expectedProductDependencies) + { + if (expectedProductDependency.m_dependencyId == dependency.m_dependencyId + && expectedProductDependency.m_flags == dependency.m_flags) + { + expectedDependencyExists = true; + break; + } + } + + ASSERT_TRUE(expectedDependencyExists) << "Expected product dependency is not found in the process result"; + } + } + } + + void TestSuccessCase(CopyDependencyBuilderWorker* worker, AZStd::string_view fileName, const char* expectedFile) + { + AZStd::vector expectedFiles; + expectedFiles.push_back(expectedFile); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(worker, fileName, expectedFiles, expectedProductDependencies); + } + + void TestSuccessCaseNoDependencies(CopyDependencyBuilderWorker* worker, AZStd::string_view fileName) + { + AZStd::vector expectedFiles; + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(worker, fileName, expectedFiles, expectedProductDependencies); + } + + ////////////////////////////////////////////////////////////////////////// + // AzToolsFramework::AssetSystem::AssetSystemRequestBus::Handler overrides + const char* GetAbsoluteDevGameFolderPath() override { return ""; } + const char* GetAbsoluteDevRootFolderPath() override { return ""; } + bool GetRelativeProductPathFromFullSourceOrProductPath([[maybe_unused]] const AZStd::string& fullPath, [[maybe_unused]] AZStd::string& relativeProductPath) { return true; } + bool GenerateRelativeSourcePath( + [[maybe_unused]] const AZStd::string& sourcePath, [[maybe_unused]] AZStd::string& relativePath, + [[maybe_unused]] AZStd::string& watchFolder) { return true; } + bool GetFullSourcePathFromRelativeProductPath([[maybe_unused]] const AZStd::string& relPath, [[maybe_unused]] AZStd::string& fullSourcePath) { return true; } + bool GetAssetInfoById([[maybe_unused]] const AZ::Data::AssetId& assetId, [[maybe_unused]] const AZ::Data::AssetType& assetType, [[maybe_unused]] const AZStd::string& platformName, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& rootFilePath) { return true; } + bool GetSourceInfoBySourcePath([[maybe_unused]] const char* sourcePath, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& watchFolder) { return true; } + bool GetSourceInfoBySourceUUID([[maybe_unused]] const AZ::Uuid& sourceUuid, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& watchFolder) { return true; } + bool GetScanFolders([[maybe_unused]] AZStd::vector& scanFolders) { return true; } + bool IsAssetPlatformEnabled([[maybe_unused]] const char* platform) { return true; } + int GetPendingAssetsForPlatform([[maybe_unused]] const char* platform) { return 0; } + bool GetAssetsProducedBySourceUUID([[maybe_unused]] const AZ::Uuid& sourceUuid, [[maybe_unused]] AZStd::vector& productsAssetInfo) { return true; } + bool GetAssetSafeFolders(AZStd::vector& assetSafeFolders) override + { + char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(GetFullPath("Xmls").c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); + assetSafeFolders.emplace_back(resolvedBuffer); + return true; + } + + // When supressing AZ_Errors to count how many occur, + // you need to tell it you expect double the number of errors. + const int SuppressedErrorMultiplier = 2; + + AZStd::unique_ptr m_app; + AZStd::string m_currentPlatform; + }; + + TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_EmptyCfg_NoDependenciesNoErrors) + { + ProductPathDependencySet resolvedPaths; + bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( + "arbitraryFileName", + "", + resolvedPaths); + + ASSERT_TRUE(result); + ASSERT_EQ(resolvedPaths.size(), 0); + } + + struct CfgTestHelper + { + AZStd::string m_command; + ProductPathDependency m_expectedDependency; + }; + + AZStd::string ConstructCfgFromHelpers(const AZStd::vector& helpers) + { + AZStd::string result; + for (const CfgTestHelper& helper : helpers) + { + result += AZStd::string::format("%s=%s\n", helper.m_command.c_str(), helper.m_expectedDependency.m_dependencyPath.c_str()); + } + return result; + } + + TEST_F(CopyDependencyBuilderTest, TestXmlBuilderWorker_VegetationDescriptorProduct_AssetTypeValid) + { + const char vegDescriptorTestName[] = "somefile.vegdescriptorlist"; + AZ::Data::AssetType vegDescriptorListType("{60961B36-E3CA-4877-B197-1462C1363F6E}"); // DescriptorListAsset in Vegetation Gem + + XmlBuilderWorker testBuilder; + + AZ::Data::AssetType parsedAssetType = testBuilder.GetAssetType(vegDescriptorTestName); + ASSERT_EQ(parsedAssetType, vegDescriptorListType); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlBuilderWorker_InvalidExtensionProduct_AssetTypeNull) + { + const char nullTestType[] = "somefile.vegdescriptorlist2"; + AZ::Data::AssetType nullType = AZ::Data::AssetType::CreateNull(); + + XmlBuilderWorker testBuilder; + + AZ::Data::AssetType parsedAssetType = testBuilder.GetAssetType(nullTestType); + ASSERT_EQ(parsedAssetType, nullType); + } + + TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_ValidCommands_CorrectDependencies) + { + // Testing every row of the supported config files and supported extensions won't accomplish + // much besides forcing someone to keep two lists in sync. If these test cases work (source extension, product extensions), then the system works. + AZStd::vector commands = + { + { "game_load_screen_uicanvas_path", { "somefile.uicanvas", ProductPathDependencyType::ProductFile }}, + { "sys_splashscreen", { "arbitraryFile.bmp", ProductPathDependencyType::SourceFile } }, + }; + + ProductPathDependencySet resolvedPaths; + bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( + "arbitraryFileName", + ConstructCfgFromHelpers(commands), + resolvedPaths); + + ASSERT_TRUE(result); + ASSERT_EQ(resolvedPaths.size(), commands.size()); + for (CfgTestHelper& helper : commands) + { + // Paths are stored in lowercase in the database + AZStd::to_lower(helper.m_expectedDependency.m_dependencyPath.begin(), helper.m_expectedDependency.m_dependencyPath.end()); + ProductPathDependencySet::iterator foundFile = resolvedPaths.find(helper.m_expectedDependency); + ASSERT_NE(foundFile, resolvedPaths.end()); } } - void TestSuccessCase(CopyDependencyBuilderWorker* worker, AZStd::string_view fileName, const char* expectedFile) + TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_CommentedCommand_NoDependenciesNoError) { - AZStd::vector expectedFiles; - expectedFiles.push_back(expectedFile); + const AZStd::vector commands = + { + // Test product file types + { "--game_load_screen_uicanvas_path", { "somefile.uicanvas", ProductPathDependencyType::ProductFile }}, + { "--sys_splashscreen", { "arbitraryFile.bmp", ProductPathDependencyType::SourceFile } }, + }; + + ProductPathDependencySet resolvedPaths; + bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( + "arbitraryFileName", + ConstructCfgFromHelpers(commands), + resolvedPaths); + + ASSERT_TRUE(result); + // Both commands were commented out, so there should be no resolved paths. + ASSERT_EQ(resolvedPaths.size(), 0); + } + + TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_ValidCommandInvalidValue_NoDependenciesError) + { + const AZStd::vector commands = + { + { "game_load_screen_uicanvas_path", { "Invalid string with illegal characters!", ProductPathDependencyType::ProductFile }} + }; + + ProductPathDependencySet resolvedPaths; + AZ_TEST_START_ASSERTTEST; + bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( + "arbitraryFileName", + ConstructCfgFromHelpers(commands), + resolvedPaths); + // Expected: 1 error, on the illegal characters in the command's value. + AZ_TEST_STOP_ASSERTTEST(1 * SuppressedErrorMultiplier); + + ASSERT_FALSE(result); + ASSERT_EQ(resolvedPaths.size(), 0); + } + + TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_ValidCommandEmptyValue_NoDependenciesError) + { + const AZStd::vector commands = + { + { "game_load_screen_uicanvas_path", { "", ProductPathDependencyType::ProductFile }} + }; + + ProductPathDependencySet resolvedPaths; + AZ_TEST_START_ASSERTTEST; + bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( + "arbitraryFileName", + ConstructCfgFromHelpers(commands), + resolvedPaths); + // Expected: 1 error, on the empty value. + AZ_TEST_STOP_ASSERTTEST(1 * SuppressedErrorMultiplier); + + ASSERT_FALSE(result); + ASSERT_EQ(resolvedPaths.size(), 0); + } + + TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_UnhandledCommandValidData_NoDependenciesNoError) + { + const AZStd::vector commands = + { + { "command_that_does_not_exist", { "thislookslikea.file", ProductPathDependencyType::ProductFile }} + }; + + ProductPathDependencySet resolvedPaths; + bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( + "arbitraryFileName", + ConstructCfgFromHelpers(commands), + resolvedPaths); + + ASSERT_TRUE(result); + ASSERT_EQ(resolvedPaths.size(), 0); + } + + TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_ValidCommandsInvalidExtension_ErrorNoDependencies) + { + // Testing every row of the supported config files and supported extensions won't accomplish + // much besides forcing someone to keep two lists in sync. If these test cases work (source extension, product extensions), then the system works. + AZStd::vector commands = + { + { "game_load_screen_uicanvas_path", { "somefile.badextension", ProductPathDependencyType::ProductFile }} + }; + + ProductPathDependencySet resolvedPaths; + AZ_TEST_START_ASSERTTEST; + bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( + "arbitraryFileName", + ConstructCfgFromHelpers(commands), + resolvedPaths); + // Expected: 1 error, on the invalid extension. + AZ_TEST_STOP_ASSERTTEST(1 * SuppressedErrorMultiplier); + + ASSERT_FALSE(result); + ASSERT_EQ(resolvedPaths.size(), 0); + } + + TEST_F(CopyDependencyBuilderTest, TestFontfamilyAsset_MultipleDependencies_OutputProductDependencies) + { + // Tests processing a FontFamilyExample.fontfamily file containing multiple dependencies + // Should output 4 dependencies + AZStd::vector expectedPaths = { + "Fonts/fontexample-regular.font", + "Fonts/fontexample-bold.font", + "Fonts/fontexample-italic.font", + "Fonts/fontexample-bolditalic.font" + }; + + AZStd::string fileName = "Fonts/FontFamilyExample.fontfamily"; + + FontBuilderWorker builderWorker; AZStd::vector expectedProductDependencies; - TestSuccessCase(worker, fileName, expectedFiles, expectedProductDependencies); + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); } - void TestSuccessCaseNoDependencies(CopyDependencyBuilderWorker* worker, AZStd::string_view fileName) + TEST_F(CopyDependencyBuilderTest, TestFontAsset_SingleDependency_OutputProductDependency) { - AZStd::vector expectedFiles; + // Tests processing a FontExample.font file containing 1 dependency + // Should output 1 dependency + + AZStd::string fileName = "Fonts/FontExample.font"; + + FontBuilderWorker builderWorker; + + TestSuccessCase(&builderWorker, fileName, "Fonts/FontExample.ttf"); + } + + TEST_F(CopyDependencyBuilderTest, TestFontAsset_NoDependency_OutputNoProductDependencies) + { + // Tests processing a FontExampleNoDependency.font file containing 0 dependency + // Should output 0 dependencies and return true + + AZStd::string fileName = "Fonts/FontExampleNoDependency.font"; + + FontBuilderWorker builderWorker; + TestSuccessCaseNoDependencies(&builderWorker, fileName); + } + + TEST_F(CopyDependencyBuilderTest, TestFontAsset_InvalidFilePath_OutputNoProductDependencies) + { + // Tests passing an invalid file path in + // Should output 0 dependency and return false + + AZStd::string fileName = "Fonts/InvalidPathExample.font"; + + FontBuilderWorker builderWorker; + TestFailureCase(&builderWorker, fileName); + } + + TEST_F(CopyDependencyBuilderTest, TestFontAsset_EmptyFile_OutputNoProductDependencies) + { + // Tests passing an empty file in + // Should output 0 dependency and return false + + AZStd::string fileName = "Fonts/EmptyFontExample.font"; + + FontBuilderWorker builderWorker; + TestFailureCase(&builderWorker, fileName); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_ExcludedSourceFilePath_NoProductDependencies) + { + AZStd::vector expectedPaths; + AZStd::string fileName = "Xmls/ExcludedFilePathExample.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); AZStd::vector expectedProductDependencies; - TestSuccessCase(worker, fileName, expectedFiles, expectedProductDependencies); + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); } - ////////////////////////////////////////////////////////////////////////// - // AzToolsFramework::AssetSystem::AssetSystemRequestBus::Handler overrides - const char* GetAbsoluteDevGameFolderPath() override { return ""; } - const char* GetAbsoluteDevRootFolderPath() override { return ""; } - bool GetRelativeProductPathFromFullSourceOrProductPath([[maybe_unused]] const AZStd::string& fullPath, [[maybe_unused]] AZStd::string& relativeProductPath) { return true; } - bool GenerateRelativeSourcePath( - [[maybe_unused]] const AZStd::string& sourcePath, [[maybe_unused]] AZStd::string& relativePath, - [[maybe_unused]] AZStd::string& watchFolder) { return true; } - bool GetFullSourcePathFromRelativeProductPath([[maybe_unused]] const AZStd::string& relPath, [[maybe_unused]] AZStd::string& fullSourcePath) { return true; } - bool GetAssetInfoById([[maybe_unused]] const AZ::Data::AssetId& assetId, [[maybe_unused]] const AZ::Data::AssetType& assetType, [[maybe_unused]] const AZStd::string& platformName, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& rootFilePath) { return true; } - bool GetSourceInfoBySourcePath([[maybe_unused]] const char* sourcePath, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& watchFolder) { return true; } - bool GetSourceInfoBySourceUUID([[maybe_unused]] const AZ::Uuid& sourceUuid, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& watchFolder) { return true; } - bool GetScanFolders([[maybe_unused]] AZStd::vector& scanFolders) { return true; } - bool IsAssetPlatformEnabled([[maybe_unused]] const char* platform) { return true; } - int GetPendingAssetsForPlatform([[maybe_unused]] const char* platform) { return 0; } - bool GetAssetsProducedBySourceUUID([[maybe_unused]] const AZ::Uuid& sourceUuid, [[maybe_unused]] AZStd::vector& productsAssetInfo) { return true; } - bool GetAssetSafeFolders(AZStd::vector& assetSafeFolders) override + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_InvalidSchemaFormat_NoProductDependencies) { - char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(GetFullPath("Xmls").c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - assetSafeFolders.emplace_back(resolvedBuffer); - return true; + AZStd::vector expectedPaths; + AZStd::string fileName = "Xmls/XmlExample.xml"; + XmlBuilderWorker builderWorker; + AZStd::string fullPath = GetFullPath("Xmls/Schema/Invalid/InvalidFormat"); + builderWorker.AddSchemaFileDirectory(fullPath); + AZ_TEST_START_TRACE_SUPPRESSION; + // The expected result is true because the invalid schema doesn't mean this XML file itself has failed to parse, it may be matched + // by other schemas. + TestFailureCase(&builderWorker, fileName, /*expectedResult*/ true); + // Three errors occur: RapidXML parse error (unexpected end of data), ObjectStream XML parse error and schema file loading error + AZ_TEST_STOP_TRACE_SUPPRESSION(3 * SuppressedErrorMultiplier); } - // When supressing AZ_Errors to count how many occur, - // you need to tell it you expect double the number of errors. - const int SuppressedErrorMultiplier = 2; - - AZStd::unique_ptr m_app; - AZStd::string m_currentPlatform; -}; - -TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_EmptyCfg_NoDependenciesNoErrors) -{ - ProductPathDependencySet resolvedPaths; - bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( - "arbitraryFileName", - "", - resolvedPaths); - - ASSERT_TRUE(result); - ASSERT_EQ(resolvedPaths.size(), 0); -} - -struct CfgTestHelper -{ - AZStd::string m_command; - ProductPathDependency m_expectedDependency; -}; - -AZStd::string ConstructCfgFromHelpers(const AZStd::vector& helpers) -{ - AZStd::string result; - for (const CfgTestHelper& helper : helpers) + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_InvalidSourceFilePath_NoProductDependencies) { - result += AZStd::string::format("%s=%s\n", helper.m_command.c_str(), helper.m_expectedDependency.m_dependencyPath.c_str()); + AZStd::string fileName = "Xmls/InvalidFilePathExample.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); + + AZStd::vector expectedPaths; + AZStd::vector expectedProductDependencies; + AZ_TEST_START_TRACE_SUPPRESSION; + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + // One error occurs: Cannot open the source file + AZ_TEST_STOP_TRACE_SUPPRESSION(1 * SuppressedErrorMultiplier); } - return result; -} -TEST_F(CopyDependencyBuilderTest, TestXmlBuilderWorker_VegetationDescriptorProduct_AssetTypeValid) -{ - const char vegDescriptorTestName[] = "somefile.vegdescriptorlist"; - AZ::Data::AssetType vegDescriptorListType("{60961B36-E3CA-4877-B197-1462C1363F6E}"); // DescriptorListAsset in Vegetation Gem - - XmlBuilderWorker testBuilder; - - AZ::Data::AssetType parsedAssetType = testBuilder.GetAssetType(vegDescriptorTestName); - ASSERT_EQ(parsedAssetType, vegDescriptorListType); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlBuilderWorker_InvalidExtensionProduct_AssetTypeNull) -{ - const char nullTestType[] = "somefile.vegdescriptorlist2"; - AZ::Data::AssetType nullType = AZ::Data::AssetType::CreateNull(); - - XmlBuilderWorker testBuilder; - - AZ::Data::AssetType parsedAssetType = testBuilder.GetAssetType(nullTestType); - ASSERT_EQ(parsedAssetType, nullType); -} - -TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_ValidCommands_CorrectDependencies) -{ - // Testing every row of the supported config files and supported extensions won't accomplish - // much besides forcing someone to keep two lists in sync. If these test cases work (source extension, product extensions), then the system works. - AZStd::vector commands = + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_InvalidSourceFileVersionNumberFormat_NoProductDependencies) { - { "game_load_screen_uicanvas_path", { "somefile.uicanvas", ProductPathDependencyType::ProductFile }}, - { "sys_splashscreen", { "arbitraryFile.bmp", ProductPathDependencyType::SourceFile } }, - }; + AZStd::vector expectedPaths; + AZStd::string fileName = "Xmls/XmlExampleInvalidVersionNumberFormat.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - ProductPathDependencySet resolvedPaths; - bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( - "arbitraryFileName", - ConstructCfgFromHelpers(commands), - resolvedPaths); + AZStd::vector expectedProductDependencies; - ASSERT_TRUE(result); - ASSERT_EQ(resolvedPaths.size(), commands.size()); - for (CfgTestHelper& helper : commands) - { - // Paths are stored in lowercase in the database - AZStd::to_lower(helper.m_expectedDependency.m_dependencyPath.begin(), helper.m_expectedDependency.m_dependencyPath.end()); - ProductPathDependencySet::iterator foundFile = resolvedPaths.find(helper.m_expectedDependency); - ASSERT_NE(foundFile, resolvedPaths.end()); + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); } -} -TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_CommentedCommand_NoDependenciesNoError) -{ - const AZStd::vector commands = + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_NoMatchedSchema_NoProductDependencies) { - // Test product file types - { "--game_load_screen_uicanvas_path", { "somefile.uicanvas", ProductPathDependencyType::ProductFile }}, - { "--sys_splashscreen", { "arbitraryFile.bmp", ProductPathDependencyType::SourceFile } }, - }; + AZStd::vector expectedPaths; + AZStd::string fileName = "Xmls/NoMatchedSchemaExample.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); - ProductPathDependencySet resolvedPaths; - bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( - "arbitraryFileName", - ConstructCfgFromHelpers(commands), - resolvedPaths); + AZStd::vector expectedProductDependencies; - ASSERT_TRUE(result); - // Both commands were commented out, so there should be no resolved paths. - ASSERT_EQ(resolvedPaths.size(), 0); -} + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } -TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_ValidCommandInvalidValue_NoDependenciesError) -{ - const AZStd::vector commands = + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SchemaMissingRules_NoProductDependencies) { - { "game_load_screen_uicanvas_path", { "Invalid string with illegal characters!", ProductPathDependencyType::ProductFile }} - }; + AZStd::vector expectedPaths; + AZStd::string fileName = "Xmls/XmlExample.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/Invalid/MissingRules")); + AZ_TEST_START_TRACE_SUPPRESSION; + TestFailureCase(&builderWorker, fileName, true); + // One error occurs: Matching rules are missing + AZ_TEST_STOP_TRACE_SUPPRESSION(1 * SuppressedErrorMultiplier); + } - ProductPathDependencySet resolvedPaths; - AZ_TEST_START_ASSERTTEST; - bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( - "arbitraryFileName", - ConstructCfgFromHelpers(commands), - resolvedPaths); - // Expected: 1 error, on the illegal characters in the command's value. - AZ_TEST_STOP_ASSERTTEST(1 * SuppressedErrorMultiplier); - - ASSERT_FALSE(result); - ASSERT_EQ(resolvedPaths.size(), 0); -} - -TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_ValidCommandEmptyValue_NoDependenciesError) -{ - const AZStd::vector commands = + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SchemaEmptyAttributeValue_OutputProductDependencies) { - { "game_load_screen_uicanvas_path", { "", ProductPathDependencyType::ProductFile }} - }; + AZStd::vector expectedPaths = { + "dependency2.txt", + "dependency3.txt", + "dependency4.txt", + "dependency5.txt", + "dependency6.txt", + "dependency7.txt" + }; - ProductPathDependencySet resolvedPaths; - AZ_TEST_START_ASSERTTEST; - bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( - "arbitraryFileName", - ConstructCfgFromHelpers(commands), - resolvedPaths); - // Expected: 1 error, on the empty value. - AZ_TEST_STOP_ASSERTTEST(1 * SuppressedErrorMultiplier); + AZStd::string fileName = "Xmls/XmlExampleEmptyAttributeValue.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); - ASSERT_FALSE(result); - ASSERT_EQ(resolvedPaths.size(), 0); -} + AZStd::vector expectedProductDependencies; -TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_UnhandledCommandValidData_NoDependenciesNoError) -{ - const AZStd::vector commands = + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleForSpecificAttribute_OutputProductDependencies) { - { "command_that_does_not_exist", { "thislookslikea.file", ProductPathDependencyType::ProductFile }} - }; + AZStd::vector expectedPaths = { + "dependency1.txt", + "dependency2.txt", + "dependency6.txt", + "dependency7.txt" + }; - ProductPathDependencySet resolvedPaths; - bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( - "arbitraryFileName", - ConstructCfgFromHelpers(commands), - resolvedPaths); + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/SpecificAttribute")); - ASSERT_TRUE(result); - ASSERT_EQ(resolvedPaths.size(), 0); -} + AZStd::vector expectedProductDependencies; -TEST_F(CopyDependencyBuilderTest, TestCfgBuilderWorker_ValidCommandsInvalidExtension_ErrorNoDependencies) -{ - // Testing every row of the supported config files and supported extensions won't accomplish - // much besides forcing someone to keep two lists in sync. If these test cases work (source extension, product extensions), then the system works. - AZStd::vector commands = + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleForSpecificElement_OutputProductDependencies) { - { "game_load_screen_uicanvas_path", { "somefile.badextension", ProductPathDependencyType::ProductFile }} - }; + AZStd::vector expectedPaths = { + "dependency3.txt", + "dependency4.txt", + "dependency5.txt" + }; - ProductPathDependencySet resolvedPaths; - AZ_TEST_START_ASSERTTEST; - bool result = CfgBuilderWorker::ParseProductDependenciesFromCfgContents( - "arbitraryFileName", - ConstructCfgFromHelpers(commands), - resolvedPaths); - // Expected: 1 error, on the invalid extension. - AZ_TEST_STOP_ASSERTTEST(1 * SuppressedErrorMultiplier); + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/SpecificElement")); - ASSERT_FALSE(result); - ASSERT_EQ(resolvedPaths.size(), 0); -} + AZStd::vector expectedProductDependencies; -TEST_F(CopyDependencyBuilderTest, TestFontfamilyAsset_MultipleDependencies_OutputProductDependencies) -{ - // Tests processing a FontFamilyExample.fontfamily file containing multiple dependencies - // Should output 4 dependencies - AZStd::vector expectedPaths = { - "Fonts/fontexample-regular.font", - "Fonts/fontexample-bold.font", - "Fonts/fontexample-italic.font", - "Fonts/fontexample-bolditalic.font" - }; + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } - AZStd::string fileName = "Fonts/FontFamilyExample.fontfamily"; + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleRelativeToXmlRootNode_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "dependency1.txt", + "dependency2.txt" + }; - FontBuilderWorker builderWorker; + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/RelativeToXmlRootNode")); - AZStd::vector expectedProductDependencies; + AZStd::vector expectedProductDependencies; - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } -TEST_F(CopyDependencyBuilderTest, TestFontAsset_SingleDependency_OutputProductDependency) -{ - // Tests processing a FontExample.font file containing 1 dependency - // Should output 1 dependency + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleWithExpectedExtension_OutputProductDependencies) + { + AZStd::string fileName = "Xmls/XmlExampleWithoutExtension.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/ExpectedExtension")); + TestSuccessCase(&builderWorker, fileName, "dependency2.txt"); + } - AZStd::string fileName = "Fonts/FontExample.font"; + // The schema supports different extensions at the same location in the file. + // This matches the behavior of systems like materials referencing textures: They can reference the source (png/tif) or product (dds) + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_MultipleOverlappingOptionalExtensions_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "Extension1.ext1", + "Extension2.ext2" + }; + AZStd::string fileName = "Xmls/XmlExampleMultipleMatchingExtensions.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/MultipleExtensionsSamePath")); - FontBuilderWorker builderWorker; + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleWithOptionalAttribute_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "dependency1.txt", + "dependency2.txt" + }; + + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/OptionalAttribute")); + + AZStd::vector expectedProductDependencies; - TestSuccessCase(&builderWorker, fileName, "Fonts/FontExample.ttf"); -} + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } -TEST_F(CopyDependencyBuilderTest, TestFontAsset_NoDependency_OutputNoProductDependencies) -{ - // Tests processing a FontExampleNoDependency.font file containing 0 dependency - // Should output 0 dependencies and return true - - AZStd::string fileName = "Fonts/FontExampleNoDependency.font"; - - FontBuilderWorker builderWorker; - TestSuccessCaseNoDependencies(&builderWorker, fileName); -} - -TEST_F(CopyDependencyBuilderTest, TestFontAsset_InvalidFilePath_OutputNoProductDependencies) -{ - // Tests passing an invalid file path in - // Should output 0 dependency and return false - - AZStd::string fileName = "Fonts/InvalidPathExample.font"; - - FontBuilderWorker builderWorker; - TestFailureCase(&builderWorker, fileName); -} - -TEST_F(CopyDependencyBuilderTest, TestFontAsset_EmptyFile_OutputNoProductDependencies) -{ - // Tests passing an empty file in - // Should output 0 dependency and return false - - AZStd::string fileName = "Fonts/EmptyFontExample.font"; - - FontBuilderWorker builderWorker; - TestFailureCase(&builderWorker, fileName); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_ExcludedSourceFilePath_NoProductDependencies) -{ - AZStd::vector expectedPaths; - AZStd::string fileName = "Xmls/ExcludedFilePathExample.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_InvalidSchemaFormat_NoProductDependencies) -{ - AZStd::vector expectedPaths; - AZStd::string fileName = "Xmls/XmlExample.xml"; - XmlBuilderWorker builderWorker; - AZStd::string fullPath = GetFullPath("Xmls/Schema/Invalid/InvalidFormat"); - builderWorker.AddSchemaFileDirectory(fullPath); - AZ_TEST_START_TRACE_SUPPRESSION; - // The expected result is true because the invalid schema doesn't mean this XML file itself has failed to parse, it may be matched - // by other schemas. - TestFailureCase(&builderWorker, fileName, /*expectedResult*/ true); - // Three errors occur: RapidXML parse error (unexpected end of data), ObjectStream XML parse error and schema file loading error - AZ_TEST_STOP_TRACE_SUPPRESSION(3 * SuppressedErrorMultiplier); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_InvalidSourceFilePath_NoProductDependencies) -{ - AZStd::string fileName = "Xmls/InvalidFilePathExample.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); - - AZStd::vector expectedPaths; - AZStd::vector expectedProductDependencies; - AZ_TEST_START_TRACE_SUPPRESSION; - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); - // One error occurs: Cannot open the source file - AZ_TEST_STOP_TRACE_SUPPRESSION(1 * SuppressedErrorMultiplier); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_InvalidSourceFileVersionNumberFormat_NoProductDependencies) -{ - AZStd::vector expectedPaths; - AZStd::string fileName = "Xmls/XmlExampleInvalidVersionNumberFormat.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_NoMatchedSchema_NoProductDependencies) -{ - AZStd::vector expectedPaths; - AZStd::string fileName = "Xmls/NoMatchedSchemaExample.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SchemaMissingRules_NoProductDependencies) -{ - AZStd::vector expectedPaths; - AZStd::string fileName = "Xmls/XmlExample.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/Invalid/MissingRules")); - AZ_TEST_START_TRACE_SUPPRESSION; - TestFailureCase(&builderWorker, fileName, true); - // One error occurs: Matching rules are missing - AZ_TEST_STOP_TRACE_SUPPRESSION(1 * SuppressedErrorMultiplier); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SchemaEmptyAttributeValue_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency2.txt", - "dependency3.txt", - "dependency4.txt", - "dependency5.txt", - "dependency6.txt", - "dependency7.txt" - }; - - AZStd::string fileName = "Xmls/XmlExampleEmptyAttributeValue.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleForSpecificAttribute_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency1.txt", - "dependency2.txt", - "dependency6.txt", - "dependency7.txt" - }; - - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/SpecificAttribute")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleForSpecificElement_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency3.txt", - "dependency4.txt", - "dependency5.txt" - }; - - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/SpecificElement")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleRelativeToXmlRootNode_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency1.txt", - "dependency2.txt" - }; - - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/RelativeToXmlRootNode")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleWithExpectedExtension_OutputProductDependencies) -{ - AZStd::string fileName = "Xmls/XmlExampleWithoutExtension.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/ExpectedExtension")); - TestSuccessCase(&builderWorker, fileName, "dependency2.txt"); -} - -// The schema supports different extensions at the same location in the file. -// This matches the behavior of systems like materials referencing textures: They can reference the source (png/tif) or product (dds) -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_MultipleOverlappingOptionalExtensions_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "Extension1.ext1", - "Extension2.ext2" - }; - AZStd::string fileName = "Xmls/XmlExampleMultipleMatchingExtensions.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/MultipleExtensionsSamePath")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleWithOptionalAttribute_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency1.txt", - "dependency2.txt" - }; - - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/OptionalAttribute")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleWithMissingRequiredAttribute_NoProductDependencies) -{ - AZStd::vector expectedPaths; - - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/RequiredAttribute")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleWithOptionalElement_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency1.txt", - "dependency2.txt" - }; - - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/OptionalElement")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleWithMissingRequiredElement_NoProductDependencies) -{ - AZStd::vector expectedPaths; - - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/RequiredElements")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithoutVersionSchemaWithVersionConstraints_NoProductDependencies) -{ - AZStd::vector expectedPaths; - - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithVersionOutOfRangeSchemaWithVersionConstraints_NoProductDependencies) -{ - AZStd::vector expectedPaths; - AZStd::string fileName = "Xmls/XmlExampleVersionOutOfRange.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithVersionSchemaWithVersionConstraints_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency1.txt", - "dependency2.txt", - "dependency3.txt", - "dependency4.txt", - "dependency5.txt", - "dependency6.txt", - "dependency7.txt" - }; - - AZStd::string fileName = "Xmls/XmlExample.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithOneVersionPartSchemaWithVersionConstraints_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency1.txt", - "dependency2.txt", - "dependency3.txt", - "dependency4.txt", - "dependency5.txt", - "dependency6.txt", - "dependency7.txt" - }; - - AZStd::string fileName = "Xmls/XmlExampleWithOneVersionPart.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithTwoVersionPartsSchemaWithVersionConstraints_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency1.txt", - "dependency2.txt", - "dependency3.txt", - "dependency4.txt", - "dependency5.txt", - "dependency6.txt", - "dependency7.txt" - }; - - AZStd::string fileName = "Xmls/XmlExampleWithTwoVersionParts.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithThreeVersionPartsSchemaWithVersionConstraints_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency1.txt", - "dependency2.txt", - "dependency3.txt", - "dependency4.txt", - "dependency5.txt", - "dependency6.txt", - "dependency7.txt" - }; - - AZStd::string fileName = "Xmls/XmlExampleWithThreeVersionParts.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithInvalidVersionPartsCountSchemaWithVersionConstraints_OutputNoProductDependencies) -{ - AZStd::vector expectedPaths; - - AZStd::string fileName = "Xmls/XmlExampleWithInvalidVersionPartsCount.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithInvalidVersionPartsSeparatorSchemaWithVersionConstraints_OutputNoProductDependencies) -{ - AZStd::vector expectedPaths; - - AZStd::string fileName = "Xmls/XmlExampleWithInvalidVersionPartsSeparator.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithVersionSchemaWithoutVersionConstraints_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency1.txt", - "dependency2.txt", - "dependency3.txt", - "dependency4.txt", - "dependency5.txt", - "dependency6.txt", - "dependency7.txt" - }; - - AZStd::string fileName = "Xmls/XmlExample.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithoutVersionSchemaWithoutVersionConstraints_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "dependency1.txt", - "dependency2.txt", - "dependency3.txt", - "dependency4.txt", - "dependency5.txt", - "dependency6.txt", - "dependency7.txt" - }; - - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_CreateJobsWithValidSourceFile_OutputSourceDependencies) -{ - AssetBuilderSDK::CreateJobsRequest request; - AssetBuilderSDK::CreateJobsResponse response; - - request.m_sourceFile = "Tests/Xmls/XmlExampleWithoutVersion.xml"; - request.m_watchFolder = "@root@/../Gems/LmbrCentral/Code/"; - - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); - builderWorker.CreateJobs(request, response); - - ASSERT_TRUE(response.m_sourceFileDependencyList.size() == 1); - AZStd::vector splitedPathList; - AzFramework::StringFunc::Tokenize(response.m_sourceFileDependencyList[0].m_sourceFileDependencyPath.c_str(), splitedPathList, AZStd::string::format("%c%c",AZ_CORRECT_FILESYSTEM_SEPARATOR, AZ_WRONG_FILESYSTEM_SEPARATOR).c_str()); - ASSERT_EQ(splitedPathList.back(), "Schema.xmlschema"); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_ProductPathRelativeToSourceAssetFolder_OutputProductDependencies) -{ - AZStd::string product = GetFullPath("Xmls/dependency1.txt"); - AZStd::vector expectedPaths = { - product.c_str() - }; - - AZStd::string fileName = "Xmls/XmlExample.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/PathRelativeToSourceAssetFolder")); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_ProductPathRelativeToProductAssetFolder_OutputProductDependencies) -{ - AZStd::string product = "Xmls/dependency1.txt"; - AZStd::vector expectedPaths = { - product.c_str() - }; - - AZStd::string fileName = "Xmls/XmlExample.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/PathRelativeToProductAssetFolder")); - - AZStd::vector expectedProductDependencies; - - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies, testFileFolder); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_ProductDependencyWithAssetId_OutputProductDependencies) -{ - AZStd::string product = GetFullPath("Xmls/dependency1.txt"); - AZStd::vector expectedPaths; - - AZ::Data::AssetId expectedAssetId; - expectedAssetId.m_guid = AZ::Uuid("00000000-0000-0000-0000-000000000000"); - expectedAssetId.m_subId = 0; - - AZStd::vector expectedProductDependencies; - expectedProductDependencies.emplace_back(AssetBuilderSDK::ProductDependency(expectedAssetId, {})); - - AZStd::string fileName = "Xmls/XmlExampleWithAssetId.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/ProductDependencyWithAssetId")); - TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_MatchRegexMatches_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "Extension1.ext1" - }; - - AZStd::string fileName = "Xmls/XmlExampleMultipleMatchingExtensions.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/MatchPattern")); - TestSuccessCase(&builderWorker, fileName, expectedPaths); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_MatchRegexNoMatches_NoProductDependencies) -{ - AZStd::string fileName = "Xmls/XmlExample.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/MatchPattern")); - TestSuccessCaseNoDependencies(&builderWorker, fileName); -} - -TEST_F(CopyDependencyBuilderTest, TestXmlAsset_FindAndReplace_OutputProductDependencies) -{ - AZStd::vector expectedPaths = { - "hello.ext1", - "hello.ext2" - }; - - AZStd::string fileName = "Xmls/XmlExampleMultipleMatchingExtensions.xml"; - XmlBuilderWorker builderWorker; - builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FindAndReplace")); - TestSuccessCase(&builderWorker, fileName, expectedPaths); -} - -TEST_F(CopyDependencyBuilderTest, TestSchemaAsset_ValidMatchingRules_OutputReverseSourceDependencies) -{ - AZStd::vector expectedPaths = { - "NoMatchedSchemaExample.xml", - "XmlExample.xml", - "XmlExampleEmptyAttributeValue.xml", - "XmlExampleInvalidVersionNumberFormat.xml", - "XmlExampleMultipleMatchingExtensions.xml", - "XmlExampleVersionOutOfRange.xml", - "XmlExampleWithoutExtension.xml", - "XmlExampleWithoutVersion.xml", - "XmlExampleWithOneVersionPart.xml", - "XmlExampleWithTwoVersionParts.xml", - "XmlExampleWithThreeVersionParts.xml", - "XmlExampleWithInvalidVersionPartsSeparator.xml", - "XmlExampleWithInvalidVersionPartsCount.xml", - "XmlExampleWithAssetId.xml", - }; - - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - SchemaBuilderWorker builderWorker; - AssetBuilderSDK::ProcessJobRequest request; - AssetBuilderSDK::ProcessJobResponse response; - request.m_fullPath = GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured/Schema.xmlschema"); - request.m_sourceFile = "Xmls/Schema/WithoutVersionConstraints/FullFeatured/Schema.xmlschema"; - request.m_platformInfo.m_identifier = m_currentPlatform; - - builderWorker.ProcessJob(request, response); - - ASSERT_TRUE(response.m_sourcesToReprocess.size() == expectedPaths.size()); - for (const AZStd::string& reverseSourceDependency : response.m_sourcesToReprocess) + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleWithMissingRequiredAttribute_NoProductDependencies) { + AZStd::vector expectedPaths; + + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/RequiredAttribute")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleWithOptionalElement_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "dependency1.txt", + "dependency2.txt" + }; + + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/OptionalElement")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_DependencySearchRuleWithMissingRequiredElement_NoProductDependencies) + { + AZStd::vector expectedPaths; + + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/RequiredElements")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithoutVersionSchemaWithVersionConstraints_NoProductDependencies) + { + AZStd::vector expectedPaths; + + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithVersionOutOfRangeSchemaWithVersionConstraints_NoProductDependencies) + { + AZStd::vector expectedPaths; + AZStd::string fileName = "Xmls/XmlExampleVersionOutOfRange.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithVersionSchemaWithVersionConstraints_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "dependency1.txt", + "dependency2.txt", + "dependency3.txt", + "dependency4.txt", + "dependency5.txt", + "dependency6.txt", + "dependency7.txt" + }; + + AZStd::string fileName = "Xmls/XmlExample.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithOneVersionPartSchemaWithVersionConstraints_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "dependency1.txt", + "dependency2.txt", + "dependency3.txt", + "dependency4.txt", + "dependency5.txt", + "dependency6.txt", + "dependency7.txt" + }; + + AZStd::string fileName = "Xmls/XmlExampleWithOneVersionPart.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithTwoVersionPartsSchemaWithVersionConstraints_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "dependency1.txt", + "dependency2.txt", + "dependency3.txt", + "dependency4.txt", + "dependency5.txt", + "dependency6.txt", + "dependency7.txt" + }; + + AZStd::string fileName = "Xmls/XmlExampleWithTwoVersionParts.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithThreeVersionPartsSchemaWithVersionConstraints_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "dependency1.txt", + "dependency2.txt", + "dependency3.txt", + "dependency4.txt", + "dependency5.txt", + "dependency6.txt", + "dependency7.txt" + }; + + AZStd::string fileName = "Xmls/XmlExampleWithThreeVersionParts.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithInvalidVersionPartsCountSchemaWithVersionConstraints_OutputNoProductDependencies) + { + AZStd::vector expectedPaths; + + AZStd::string fileName = "Xmls/XmlExampleWithInvalidVersionPartsCount.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithInvalidVersionPartsSeparatorSchemaWithVersionConstraints_OutputNoProductDependencies) + { + AZStd::vector expectedPaths; + + AZStd::string fileName = "Xmls/XmlExampleWithInvalidVersionPartsSeparator.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithVersionConstraints")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithVersionSchemaWithoutVersionConstraints_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "dependency1.txt", + "dependency2.txt", + "dependency3.txt", + "dependency4.txt", + "dependency5.txt", + "dependency6.txt", + "dependency7.txt" + }; + + AZStd::string fileName = "Xmls/XmlExample.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_SourceFileWithoutVersionSchemaWithoutVersionConstraints_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "dependency1.txt", + "dependency2.txt", + "dependency3.txt", + "dependency4.txt", + "dependency5.txt", + "dependency6.txt", + "dependency7.txt" + }; + + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_CreateJobsWithValidSourceFile_OutputSourceDependencies) + { + AssetBuilderSDK::CreateJobsRequest request; + AssetBuilderSDK::CreateJobsResponse response; + + request.m_sourceFile = "Tests/Xmls/XmlExampleWithoutVersion.xml"; + request.m_watchFolder = "@root@/../Gems/LmbrCentral/Code/"; + + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured")); + builderWorker.CreateJobs(request, response); + + ASSERT_TRUE(response.m_sourceFileDependencyList.size() == 1); AZStd::vector splitedPathList; - AzFramework::StringFunc::Tokenize(reverseSourceDependency.c_str(), splitedPathList, AZStd::string::format("%c%c", AZ_CORRECT_FILESYSTEM_SEPARATOR, AZ_WRONG_FILESYSTEM_SEPARATOR).c_str()); - ASSERT_TRUE(AZStd::find(expectedPaths.begin(), expectedPaths.end(), splitedPathList.back()) != expectedPaths.end()); - + AzFramework::StringFunc::Tokenize(response.m_sourceFileDependencyList[0].m_sourceFileDependencyPath.c_str(), splitedPathList, AZStd::string::format("%c%c",AZ_CORRECT_FILESYSTEM_SEPARATOR, AZ_WRONG_FILESYSTEM_SEPARATOR).c_str()); + ASSERT_EQ(splitedPathList.back(), "Schema.xmlschema"); } -} -TEST_F(CopyDependencyBuilderTest, TestSchemaAsset_InvalidFormat_OutputReverseSourceDependencies) -{ - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - SchemaBuilderWorker builderWorker; - AssetBuilderSDK::ProcessJobRequest request; - AssetBuilderSDK::ProcessJobResponse response; - request.m_fullPath = GetFullPath("Xmls/Schema/Invalid/InvalidFormat/Schema.xmlschema"); - request.m_sourceFile = "Xmls/Schema/Invalid/InvalidFormat/Schema.xmlschema"; - request.m_platformInfo.m_identifier = m_currentPlatform; - - AZ_TEST_START_TRACE_SUPPRESSION; - builderWorker.ProcessJob(request, response); - // Three errors: One from LoadObjectFromFileInPlace, one is from GetReverseSourceDependencies and the other from ProcessJob - AZ_TEST_STOP_TRACE_SUPPRESSION(3 * SuppressedErrorMultiplier); - - ASSERT_TRUE(response.m_sourcesToReprocess.size() == 0); -} - -TEST_F(CopyDependencyBuilderTest, TestSchemaAsset_SchemaMissingRules_OutputReverseSourceDependencies) -{ - AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; - SchemaBuilderWorker builderWorker; - AssetBuilderSDK::ProcessJobRequest request; - AssetBuilderSDK::ProcessJobResponse response; - request.m_fullPath = GetFullPath("Xmls/Schema/Invalid/MissingRules/Schema.xmlschema"); - request.m_sourceFile = "Xmls/Schema/Invalid/MissingRules/Schema.xmlschema"; - request.m_platformInfo.m_identifier = m_currentPlatform; - - AZ_TEST_START_TRACE_SUPPRESSION; - builderWorker.ProcessJob(request, response); - AZ_TEST_STOP_TRACE_SUPPRESSION(SuppressedErrorMultiplier); - - ASSERT_TRUE(response.m_sourcesToReprocess.size() == 0); -} - -TEST_F(CopyDependencyBuilderTest, TestEmfxWorkSpace_ProductDependencies_Valid) -{ - AZStd::set expectedProductPathDependencies = { - "foo.actor", - "foo.motionset", - "foo.animgraph", - }; - - AZStd::vector expectedProductDependencies; - AZStd::string fileName = "EmfxWorkSpace/productdependencies.emfxworkspace"; - EmfxWorkspaceBuilderWorker builderWorker; - AssetBuilderSDK::ProcessJobRequest request; - AssetBuilderSDK::ProcessJobResponse response; - request.m_fullPath = GetFullPath("EmfxWorkSpace/productdependencies.emfxworkspace"); - request.m_sourceFile = "EmfxWorkSpace/productdependencies.emfxworkspace"; - request.m_platformInfo.m_identifier = m_currentPlatform; - - builderWorker.ProcessJob(request, response); - - ASSERT_EQ(response.m_outputProducts.size(), 1); - - ASSERT_EQ(response.m_outputProducts[0].m_pathDependencies.size(), 3); - - for (const auto& productDependenciesPath : response.m_outputProducts[0].m_pathDependencies) + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_ProductPathRelativeToSourceAssetFolder_OutputProductDependencies) { - ASSERT_TRUE(expectedProductPathDependencies.find(productDependenciesPath.m_dependencyPath) != expectedProductPathDependencies.end()); - ASSERT_TRUE(productDependenciesPath.m_dependencyType == ProductPathDependencyType::ProductFile); + AZStd::string product = GetFullPath("Xmls/dependency1.txt"); + AZStd::vector expectedPaths = { + product.c_str() + }; + + AZStd::string fileName = "Xmls/XmlExample.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/PathRelativeToSourceAssetFolder")); } -} - -TEST_F(CopyDependencyBuilderTest, TestEmfxWorkSpace_NoProductDependencies_Valid) -{ - AZStd::vector expectedProductDependencies; - AZStd::string fileName = "EmfxWorkSpace/noproductdependencies.emfxworkspace"; - EmfxWorkspaceBuilderWorker builderWorker; - AssetBuilderSDK::ProcessJobRequest request; - AssetBuilderSDK::ProcessJobResponse response; - request.m_fullPath = GetFullPath("EmfxWorkSpace/noproductdependencies.emfxworkspace"); - request.m_sourceFile = "EmfxWorkSpace/noproductdependencies.emfxworkspace"; - request.m_platformInfo.m_identifier = m_currentPlatform; - - builderWorker.ProcessJob(request, response); - - ASSERT_EQ(response.m_outputProducts.size(), 1); - - ASSERT_EQ(response.m_outputProducts[0].m_pathDependencies.size(), 0); + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_ProductPathRelativeToProductAssetFolder_OutputProductDependencies) + { + AZStd::string product = "Xmls/dependency1.txt"; + AZStd::vector expectedPaths = { + product.c_str() + }; + + AZStd::string fileName = "Xmls/XmlExample.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/PathRelativeToProductAssetFolder")); + + AZStd::vector expectedProductDependencies; + + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies, testFileFolder); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_ProductDependencyWithAssetId_OutputProductDependencies) + { + AZStd::string product = GetFullPath("Xmls/dependency1.txt"); + AZStd::vector expectedPaths; + + AZ::Data::AssetId expectedAssetId; + expectedAssetId.m_guid = AZ::Uuid("00000000-0000-0000-0000-000000000000"); + expectedAssetId.m_subId = 0; + + AZStd::vector expectedProductDependencies; + expectedProductDependencies.emplace_back(AssetBuilderSDK::ProductDependency(expectedAssetId, {})); + + AZStd::string fileName = "Xmls/XmlExampleWithAssetId.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/ProductDependencyWithAssetId")); + TestSuccessCase(&builderWorker, fileName, expectedPaths, expectedProductDependencies); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_MatchRegexMatches_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "Extension1.ext1" + }; + + AZStd::string fileName = "Xmls/XmlExampleMultipleMatchingExtensions.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/MatchPattern")); + TestSuccessCase(&builderWorker, fileName, expectedPaths); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_MatchRegexNoMatches_NoProductDependencies) + { + AZStd::string fileName = "Xmls/XmlExample.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/MatchPattern")); + TestSuccessCaseNoDependencies(&builderWorker, fileName); + } + + TEST_F(CopyDependencyBuilderTest, TestXmlAsset_FindAndReplace_OutputProductDependencies) + { + AZStd::vector expectedPaths = { + "hello.ext1", + "hello.ext2" + }; + + AZStd::string fileName = "Xmls/XmlExampleMultipleMatchingExtensions.xml"; + XmlBuilderWorker builderWorker; + builderWorker.AddSchemaFileDirectory(GetFullPath("Xmls/Schema/WithoutVersionConstraints/FindAndReplace")); + TestSuccessCase(&builderWorker, fileName, expectedPaths); + } + + TEST_F(CopyDependencyBuilderTest, TestSchemaAsset_ValidMatchingRules_OutputReverseSourceDependencies) + { + AZStd::vector expectedPaths = { + "NoMatchedSchemaExample.xml", + "XmlExample.xml", + "XmlExampleEmptyAttributeValue.xml", + "XmlExampleInvalidVersionNumberFormat.xml", + "XmlExampleMultipleMatchingExtensions.xml", + "XmlExampleVersionOutOfRange.xml", + "XmlExampleWithoutExtension.xml", + "XmlExampleWithoutVersion.xml", + "XmlExampleWithOneVersionPart.xml", + "XmlExampleWithTwoVersionParts.xml", + "XmlExampleWithThreeVersionParts.xml", + "XmlExampleWithInvalidVersionPartsSeparator.xml", + "XmlExampleWithInvalidVersionPartsCount.xml", + "XmlExampleWithAssetId.xml", + }; + + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + SchemaBuilderWorker builderWorker; + AssetBuilderSDK::ProcessJobRequest request; + AssetBuilderSDK::ProcessJobResponse response; + request.m_fullPath = GetFullPath("Xmls/Schema/WithoutVersionConstraints/FullFeatured/Schema.xmlschema"); + request.m_sourceFile = "Xmls/Schema/WithoutVersionConstraints/FullFeatured/Schema.xmlschema"; + request.m_platformInfo.m_identifier = m_currentPlatform; + + builderWorker.ProcessJob(request, response); + + ASSERT_TRUE(response.m_sourcesToReprocess.size() == expectedPaths.size()); + for (const AZStd::string& reverseSourceDependency : response.m_sourcesToReprocess) + { + AZStd::vector splitedPathList; + AzFramework::StringFunc::Tokenize(reverseSourceDependency.c_str(), splitedPathList, AZStd::string::format("%c%c", AZ_CORRECT_FILESYSTEM_SEPARATOR, AZ_WRONG_FILESYSTEM_SEPARATOR).c_str()); + ASSERT_TRUE(AZStd::find(expectedPaths.begin(), expectedPaths.end(), splitedPathList.back()) != expectedPaths.end()); + + } + } + + TEST_F(CopyDependencyBuilderTest, TestSchemaAsset_InvalidFormat_OutputReverseSourceDependencies) + { + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + SchemaBuilderWorker builderWorker; + AssetBuilderSDK::ProcessJobRequest request; + AssetBuilderSDK::ProcessJobResponse response; + request.m_fullPath = GetFullPath("Xmls/Schema/Invalid/InvalidFormat/Schema.xmlschema"); + request.m_sourceFile = "Xmls/Schema/Invalid/InvalidFormat/Schema.xmlschema"; + request.m_platformInfo.m_identifier = m_currentPlatform; + + AZ_TEST_START_TRACE_SUPPRESSION; + builderWorker.ProcessJob(request, response); + // Three errors: One from LoadObjectFromFileInPlace, one is from GetReverseSourceDependencies and the other from ProcessJob + AZ_TEST_STOP_TRACE_SUPPRESSION(3 * SuppressedErrorMultiplier); + + ASSERT_TRUE(response.m_sourcesToReprocess.size() == 0); + } + + TEST_F(CopyDependencyBuilderTest, TestSchemaAsset_SchemaMissingRules_OutputReverseSourceDependencies) + { + AZStd::string fileName = "Xmls/XmlExampleWithoutVersion.xml"; + SchemaBuilderWorker builderWorker; + AssetBuilderSDK::ProcessJobRequest request; + AssetBuilderSDK::ProcessJobResponse response; + request.m_fullPath = GetFullPath("Xmls/Schema/Invalid/MissingRules/Schema.xmlschema"); + request.m_sourceFile = "Xmls/Schema/Invalid/MissingRules/Schema.xmlschema"; + request.m_platformInfo.m_identifier = m_currentPlatform; + + AZ_TEST_START_TRACE_SUPPRESSION; + builderWorker.ProcessJob(request, response); + AZ_TEST_STOP_TRACE_SUPPRESSION(SuppressedErrorMultiplier); + + ASSERT_TRUE(response.m_sourcesToReprocess.size() == 0); + } + + TEST_F(CopyDependencyBuilderTest, TestEmfxWorkSpace_ProductDependencies_Valid) + { + AZStd::set expectedProductPathDependencies = { + "foo.actor", + "foo.motionset", + "foo.animgraph", + }; + + AZStd::vector expectedProductDependencies; + AZStd::string fileName = "EmfxWorkSpace/productdependencies.emfxworkspace"; + EmfxWorkspaceBuilderWorker builderWorker; + AssetBuilderSDK::ProcessJobRequest request; + AssetBuilderSDK::ProcessJobResponse response; + request.m_fullPath = GetFullPath("EmfxWorkSpace/productdependencies.emfxworkspace"); + request.m_sourceFile = "EmfxWorkSpace/productdependencies.emfxworkspace"; + request.m_platformInfo.m_identifier = m_currentPlatform; + + builderWorker.ProcessJob(request, response); + + ASSERT_EQ(response.m_outputProducts.size(), 1); + + ASSERT_EQ(response.m_outputProducts[0].m_pathDependencies.size(), 3); + + for (const auto& productDependenciesPath : response.m_outputProducts[0].m_pathDependencies) + { + ASSERT_TRUE(expectedProductPathDependencies.find(productDependenciesPath.m_dependencyPath) != expectedProductPathDependencies.end()); + ASSERT_TRUE(productDependenciesPath.m_dependencyType == ProductPathDependencyType::ProductFile); + } + } + + TEST_F(CopyDependencyBuilderTest, TestEmfxWorkSpace_NoProductDependencies_Valid) + { + AZStd::vector expectedProductDependencies; + AZStd::string fileName = "EmfxWorkSpace/noproductdependencies.emfxworkspace"; + EmfxWorkspaceBuilderWorker builderWorker; + AssetBuilderSDK::ProcessJobRequest request; + AssetBuilderSDK::ProcessJobResponse response; + request.m_fullPath = GetFullPath("EmfxWorkSpace/noproductdependencies.emfxworkspace"); + request.m_sourceFile = "EmfxWorkSpace/noproductdependencies.emfxworkspace"; + request.m_platformInfo.m_identifier = m_currentPlatform; + + builderWorker.ProcessJob(request, response); + + ASSERT_EQ(response.m_outputProducts.size(), 1); + + ASSERT_EQ(response.m_outputProducts[0].m_pathDependencies.size(), 0); + } + } diff --git a/Gems/LmbrCentral/Code/Tests/Builders/LevelBuilderTest.cpp b/Gems/LmbrCentral/Code/Tests/Builders/LevelBuilderTest.cpp index 66a3bdb61b..56052b710e 100644 --- a/Gems/LmbrCentral/Code/Tests/Builders/LevelBuilderTest.cpp +++ b/Gems/LmbrCentral/Code/Tests/Builders/LevelBuilderTest.cpp @@ -19,361 +19,363 @@ #include #include -using namespace LevelBuilder; -using namespace AZ; -using namespace AssetBuilderSDK; - -class MockSimpleAsset +namespace UnitTest { -public: - AZ_TYPE_INFO(MockSimpleAsset, "{A8A04FF5-1D58-450D-8FD4-2641F290B918}"); + using namespace LevelBuilder; + using namespace AZ; + using namespace AssetBuilderSDK; - static const char* GetFileFilter() + class MockSimpleAsset { - return "*.txt;"; - } -}; + public: + AZ_TYPE_INFO(MockSimpleAsset, "{A8A04FF5-1D58-450D-8FD4-2641F290B918}"); -class SecondMockSimpleAsset -{ -public: - AZ_TYPE_INFO(SecondMockSimpleAsset, "{A443123A-FD95-45F6-9767-35B17DA2072F}"); - - static const char* GetFileFilter() - { - return "*.txt;*.txt1;*.txt2"; - } -}; - -class ThirdMockSimpleAsset -{ -public: - AZ_TYPE_INFO(ThirdMockSimpleAsset, "{0298F78B-76EF-47CE-8812-B0BC80060016}"); - - static const char* GetFileFilter() - { - return "txt"; - } -}; - -struct MockSimpleAssetRefComponent - : public AZ::Component -{ - AZ_COMPONENT(MockSimpleAssetRefComponent, "{7A37EE69-707B-435F-8B8C-B347C454DC6B}"); - - static void Reflect(ReflectContext* reflection) - { - SerializeContext* serializeContext = azrtti_cast(reflection); - - AzFramework::SimpleAssetReference::Register(*serializeContext); - AzFramework::SimpleAssetReference::Register(*serializeContext); - AzFramework::SimpleAssetReference::Register(*serializeContext); - - if (serializeContext) + static const char* GetFileFilter() { - serializeContext->Class() - ->Field("asset", &MockSimpleAssetRefComponent::m_asset) - ->Field("secondAsset", &MockSimpleAssetRefComponent::m_secondAsset) - ->Field("thirdAsset", &MockSimpleAssetRefComponent::m_thirdAsset); + return "*.txt;"; } + }; + + class SecondMockSimpleAsset + { + public: + AZ_TYPE_INFO(SecondMockSimpleAsset, "{A443123A-FD95-45F6-9767-35B17DA2072F}"); + + static const char* GetFileFilter() + { + return "*.txt;*.txt1;*.txt2"; + } + }; + + class ThirdMockSimpleAsset + { + public: + AZ_TYPE_INFO(ThirdMockSimpleAsset, "{0298F78B-76EF-47CE-8812-B0BC80060016}"); + + static const char* GetFileFilter() + { + return "txt"; + } + }; + + struct MockSimpleAssetRefComponent + : public AZ::Component + { + AZ_COMPONENT(MockSimpleAssetRefComponent, "{7A37EE69-707B-435F-8B8C-B347C454DC6B}"); + + static void Reflect(ReflectContext* reflection) + { + SerializeContext* serializeContext = azrtti_cast(reflection); + + AzFramework::SimpleAssetReference::Register(*serializeContext); + AzFramework::SimpleAssetReference::Register(*serializeContext); + AzFramework::SimpleAssetReference::Register(*serializeContext); + + if (serializeContext) + { + serializeContext->Class() + ->Field("asset", &MockSimpleAssetRefComponent::m_asset) + ->Field("secondAsset", &MockSimpleAssetRefComponent::m_secondAsset) + ->Field("thirdAsset", &MockSimpleAssetRefComponent::m_thirdAsset); + } + } + + void Activate() override {} + void Deactivate() override {} + + AzFramework::SimpleAssetReference m_asset; + AzFramework::SimpleAssetReference m_secondAsset; + AzFramework::SimpleAssetReference m_thirdAsset; + }; + + class LevelBuilderTest + : public ::testing::Test + , public UnitTest::TraceBusRedirector + { + protected: + void SetUp() override + { + AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get(); + auto projectPathKey = + AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path"; + registry->Set(projectPathKey, "AutomatedTesting"); + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry); + + m_app.Start(m_descriptor); + // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is + // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash + // in the unit tests. + AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + const AZStd::string engineRoot = AZ::Test::GetEngineRootPath(); + AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engineRoot.c_str()); + + AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath()); + assetRoot /= "Cache"; + AZ::IO::FileIOBase::GetInstance()->SetAlias("@root@", assetRoot.c_str()); + + auto* serializeContext = m_app.GetSerializeContext(); + + m_simpleAssetRefDescriptor = MockSimpleAssetRefComponent::CreateDescriptor(); + m_simpleAssetRefDescriptor->Reflect(serializeContext); + } + + void TearDown() override + { + delete m_simpleAssetRefDescriptor; + + m_app.Stop(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + + void TestFailureCase(AZStd::string_view fileName) + { + IO::FileIOStream fileStream; + LevelBuilderWorker worker; + ProductPathDependencySet productDependencies; + + ASSERT_TRUE(OpenTestFile(fileName, fileStream)); + ASSERT_EQ(productDependencies.size(), 0); + } + + AZStd::string GetTestFileAliasedPath(AZStd::string_view fileName) + { + constexpr char testFileFolder[] = "@devroot@/Gems/LmbrCentral/Code/Tests/Levels/"; + return AZStd::string::format("%s%.*s", testFileFolder, aznumeric_cast(fileName.size()), fileName.data()); + } + + + AZStd::string GetTestFileFullPath(AZStd::string_view fileName) + { + AZStd::string aliasedPath = GetTestFileAliasedPath(fileName); + char resolvedPath[AZ_MAX_PATH_LEN]; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(aliasedPath.c_str(), resolvedPath, AZ_MAX_PATH_LEN); + return AZStd::string(resolvedPath); + } + + bool OpenTestFile(AZStd::string_view fileName, IO::FileIOStream& fileStream) + { + AZStd::string aliasedPath = GetTestFileFullPath(fileName); + return fileStream.Open(aliasedPath.c_str(), IO::OpenMode::ModeRead | IO::OpenMode::ModeBinary); + } + + AzToolsFramework::ToolsApplication m_app; + AZ::ComponentApplication::Descriptor m_descriptor; + AZ::ComponentDescriptor* m_simpleAssetRefDescriptor; + }; + + TEST_F(LevelBuilderTest, TestLevelData_EmptyFile) + { + // Tests processing a leveldata.xml file that is empty + // Should output 0 dependencies and return false + + TestFailureCase("leveldata_test3.xml"); } - void Activate() override {} - void Deactivate() override {} - - AzFramework::SimpleAssetReference m_asset; - AzFramework::SimpleAssetReference m_secondAsset; - AzFramework::SimpleAssetReference m_thirdAsset; -}; - -class LevelBuilderTest - : public ::testing::Test - , public UnitTest::TraceBusRedirector -{ -protected: - void SetUp() override + TEST_F(LevelBuilderTest, TestLevelData_NoSurfaceTypes) { - AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get(); - auto projectPathKey = - AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path"; - registry->Set(projectPathKey, "AutomatedTesting"); - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry); - - m_app.Start(m_descriptor); - // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is - // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash - // in the unit tests. - AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); + // Tests processing a leveldata.xml file that contains no surface types + // Should output 0 dependencies and return false - const AZStd::string engineRoot = AZ::Test::GetEngineRootPath(); - AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engineRoot.c_str()); - - AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath()); - assetRoot /= "Cache"; - AZ::IO::FileIOBase::GetInstance()->SetAlias("@root@", assetRoot.c_str()); - - auto* serializeContext = m_app.GetSerializeContext(); - - m_simpleAssetRefDescriptor = MockSimpleAssetRefComponent::CreateDescriptor(); - m_simpleAssetRefDescriptor->Reflect(serializeContext); + TestFailureCase("leveldata_test4.xml"); } - void TearDown() override + TEST_F(LevelBuilderTest, TestLevelData_NoLevelData) { - delete m_simpleAssetRefDescriptor; + // Tests processing a leveldata.xml file that contains no level data + // Should output 0 dependencies and return false - m_app.Stop(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + TestFailureCase("leveldata_test5.xml"); } - void TestFailureCase(AZStd::string_view fileName) + TEST_F(LevelBuilderTest, TestLevelData_NonXMLData) { + // Tests processing a leveldata.xml file that is not an xml file + // Should output 0 dependencies and return false + + TestFailureCase("leveldata_test6.xml"); + } + + TEST_F(LevelBuilderTest, TestLevelData_MalformedXMLData) + { + // Tests processing a leveldata.xml file that contains malformed XML + // Should output 0 dependencies and return false + + TestFailureCase("leveldata_test7.xml"); + } + + ////////////////////////////////////////////////////////////////////////// + + TEST_F(LevelBuilderTest, TestMission_MultipleDependencies) + { + // Tests processing a mission_*.xml file containing multiple dependencies and no Cloud texture + // Should output 3 dependencies + IO::FileIOStream fileStream; + + ASSERT_TRUE(OpenTestFile("mission_mission0_test1.xml", fileStream)); + LevelBuilderWorker worker; ProductPathDependencySet productDependencies; - ASSERT_TRUE(OpenTestFile(fileName, fileStream)); + ASSERT_TRUE(worker.PopulateMissionDependenciesHelper(&fileStream, productDependencies)); + ASSERT_THAT(productDependencies, testing::UnorderedElementsAre( + ProductPathDependency{ "EngineAssets/Materials/Sky/Sky.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, + ProductPathDependency{ "EngineAssets/Materials/Water/Ocean_default.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, + ProductPathDependency{ "Textures/Skys/Night/half_moon.dds", AssetBuilderSDK::ProductPathDependencyType::ProductFile })); + } + + TEST_F(LevelBuilderTest, TestMission_NoSkyBox) + { + // Tests processing a mission_*.xml file with no skybox settings + // Should output 0 dependencies and return false + + TestFailureCase("mission_mission0_test2.xml"); + } + + TEST_F(LevelBuilderTest, TestMission_NoOcean) + { + // Tests processing a mission_*.xml file with no ocean settings + // Should output 0 dependencies and return false + + TestFailureCase("mission_mission0_test3.xml"); + } + + TEST_F(LevelBuilderTest, TestMission_NoMoon) + { + // Tests processing a mission_*.xml file with no moon settings + // Should output 2 dependencies + + IO::FileIOStream fileStream; + + ASSERT_TRUE(OpenTestFile("mission_mission0_test4.xml", fileStream)); + + LevelBuilderWorker worker; + ProductPathDependencySet productDependencies; + + ASSERT_TRUE(worker.PopulateMissionDependenciesHelper(&fileStream, productDependencies)); + ASSERT_THAT(productDependencies, testing::UnorderedElementsAre( + ProductPathDependency{ "EngineAssets/Materials/Sky/Sky.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, + ProductPathDependency{ "EngineAssets/Materials/Water/Ocean_default.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile })); + } + + TEST_F(LevelBuilderTest, TestMission_NoEnvironment) + { + // Tests processing a mission_*.xml file with no environment settings + // Should output 0 dependencies and return false + + TestFailureCase("mission_mission0_test5.xml"); + } + + TEST_F(LevelBuilderTest, TestMission_EmptyFile) + { + // Tests processing an empty mission_*.xml + // Should output 0 dependencies and return false + + TestFailureCase("mission_mission0_test6.xml"); + } + + TEST_F(LevelBuilderTest, TestMission_CloudShadow) + { + // Tests processing a mission_*.xml file with cloud shadow texture set + // Should output 4 dependencies and return true + + using namespace AssetBuilderSDK; + + IO::FileIOStream fileStream; + + ASSERT_TRUE(OpenTestFile("mission_mission0_test7.xml", fileStream)); + + LevelBuilderWorker worker; + ProductPathDependencySet productDependencies; + + ASSERT_TRUE(worker.PopulateMissionDependenciesHelper(&fileStream, productDependencies)); + ASSERT_THAT(productDependencies, testing::UnorderedElementsAre( + ProductPathDependency{ "EngineAssets/Materials/Sky/Sky.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, + ProductPathDependency{ "EngineAssets/Materials/Water/Ocean_default.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, + ProductPathDependency{ "Textures/Skys/Night/half_moon.dds", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, + ProductPathDependency{ "textures/terrain/ftue_megatexture_02.dds", AssetBuilderSDK::ProductPathDependencyType::ProductFile })); + } + + TEST_F(LevelBuilderTest, DynamicSlice_NoAssetReferences_HasNoProductDependencies) + { + LevelBuilderWorker worker; + AZStd::vector productDependencies; + ProductPathDependencySet productPathDependencies; + + AZStd::string filePath(GetTestFileAliasedPath("levelSlice_noAssetReferences.entities_xml")); + ASSERT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.c_str())); + + worker.PopulateLevelSliceDependenciesHelper(filePath, productDependencies, productPathDependencies); ASSERT_EQ(productDependencies.size(), 0); + ASSERT_EQ(productPathDependencies.size(), 0); } - AZStd::string GetTestFileAliasedPath(AZStd::string_view fileName) + TEST_F(LevelBuilderTest, DynamicSlice_HasAssetReference_HasCorrectProductDependency) { - constexpr char testFileFolder[] = "@devroot@/Gems/LmbrCentral/Code/Tests/Levels/"; - return AZStd::string::format("%s%.*s", testFileFolder, aznumeric_cast(fileName.size()), fileName.data()); + LevelBuilderWorker worker; + AZStd::vector productDependencies; + ProductPathDependencySet productPathDependencies; + + AZStd::string filePath(GetTestFileAliasedPath("levelSlice_oneAssetRef.entities_xml")); + ASSERT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.c_str())); + + worker.PopulateLevelSliceDependenciesHelper(filePath, productDependencies, productPathDependencies); + ASSERT_EQ(productPathDependencies.size(), 0); + ASSERT_EQ(productDependencies.size(), 1); + ASSERT_EQ(productDependencies[0].m_dependencyId.m_guid, AZ::Uuid("A8970A25-5043-5519-A927-F180E7D6E8C1")); + ASSERT_EQ(productDependencies[0].m_dependencyId.m_subId, 1); } - - AZStd::string GetTestFileFullPath(AZStd::string_view fileName) + void BuildSliceWithSimpleAssetReference(const AZStd::vector& filePaths, AZStd::vector& productDependencies, ProductPathDependencySet& productPathDependencies) { - AZStd::string aliasedPath = GetTestFileAliasedPath(fileName); - char resolvedPath[AZ_MAX_PATH_LEN]; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(aliasedPath.c_str(), resolvedPath, AZ_MAX_PATH_LEN); - return AZStd::string(resolvedPath); + auto* assetComponent = aznew MockSimpleAssetRefComponent; + + assetComponent->m_asset.SetAssetPath(filePaths[0].c_str()); + assetComponent->m_secondAsset.SetAssetPath(filePaths[1].c_str()); + assetComponent->m_thirdAsset.SetAssetPath(filePaths[2].c_str()); + + auto sliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, AZ::Data::AssetId(AZ::Uuid::CreateRandom(), 0)); + + LevelBuilderWorker worker; + + worker.PopulateLevelSliceDependenciesHelper(sliceAsset, productDependencies, productPathDependencies); } - bool OpenTestFile(AZStd::string_view fileName, IO::FileIOStream& fileStream) + TEST_F(LevelBuilderTest, DynamicSlice_HasPopulatedSimpleAssetReference_HasCorrectProductDependency) { - AZStd::string aliasedPath = GetTestFileFullPath(fileName); - return fileStream.Open(aliasedPath.c_str(), IO::OpenMode::ModeRead | IO::OpenMode::ModeBinary); + AZStd::vector productDependencies; + ProductPathDependencySet productPathDependencies; + AZStd::vector filePaths = { "some/test/path.txt", "", "" }; + BuildSliceWithSimpleAssetReference(filePaths, productDependencies, productPathDependencies); + ASSERT_EQ(productDependencies.size(), 0); + ASSERT_EQ(productPathDependencies.size(), 1); + ASSERT_EQ(productPathDependencies.begin()->m_dependencyPath, filePaths[0]); } - AzToolsFramework::ToolsApplication m_app; - AZ::ComponentApplication::Descriptor m_descriptor; - AZ::ComponentDescriptor* m_simpleAssetRefDescriptor; -}; + TEST_F(LevelBuilderTest, DynamicSlice_HasPopulatedSimpleAssetReferencesNoExtension_HasCorrectProductDependency) + { + AZStd::vector productDependencies; + ProductPathDependencySet productPathDependencies; + AZStd::vector filePaths = { "some/test/path0", "some/test/path1", "some/test/path2" }; + BuildSliceWithSimpleAssetReference(filePaths, productDependencies, productPathDependencies); + ASSERT_EQ(productDependencies.size(), 0); + ASSERT_EQ(productPathDependencies.size(), 3); -TEST_F(LevelBuilderTest, TestLevelData_EmptyFile) -{ - // Tests processing a leveldata.xml file that is empty - // Should output 0 dependencies and return false + ASSERT_THAT(productPathDependencies, testing::UnorderedElementsAre( + ProductPathDependency{ "some/test/path0.txt", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, + ProductPathDependency{ "some/test/path1.txt", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, + ProductPathDependency{ "some/test/path2.txt", AssetBuilderSDK::ProductPathDependencyType::ProductFile })); + } - TestFailureCase("leveldata_test3.xml"); + TEST_F(LevelBuilderTest, DynamicSlice_HasEmptySimpleAssetReference_HasNoProductDependency) + { + AZStd::vector productDependencies; + ProductPathDependencySet productPathDependencies; + AZStd::vector filePaths = { "", "", "" }; + BuildSliceWithSimpleAssetReference(filePaths, productDependencies, productPathDependencies); + ASSERT_EQ(productDependencies.size(), 0); + ASSERT_EQ(productPathDependencies.size(), 0); + } } - -TEST_F(LevelBuilderTest, TestLevelData_NoSurfaceTypes) -{ - // Tests processing a leveldata.xml file that contains no surface types - // Should output 0 dependencies and return false - - TestFailureCase("leveldata_test4.xml"); -} - -TEST_F(LevelBuilderTest, TestLevelData_NoLevelData) -{ - // Tests processing a leveldata.xml file that contains no level data - // Should output 0 dependencies and return false - - TestFailureCase("leveldata_test5.xml"); -} - -TEST_F(LevelBuilderTest, TestLevelData_NonXMLData) -{ - // Tests processing a leveldata.xml file that is not an xml file - // Should output 0 dependencies and return false - - TestFailureCase("leveldata_test6.xml"); -} - -TEST_F(LevelBuilderTest, TestLevelData_MalformedXMLData) -{ - // Tests processing a leveldata.xml file that contains malformed XML - // Should output 0 dependencies and return false - - TestFailureCase("leveldata_test7.xml"); -} - -////////////////////////////////////////////////////////////////////////// - -TEST_F(LevelBuilderTest, TestMission_MultipleDependencies) -{ - // Tests processing a mission_*.xml file containing multiple dependencies and no Cloud texture - // Should output 3 dependencies - - IO::FileIOStream fileStream; - - ASSERT_TRUE(OpenTestFile("mission_mission0_test1.xml", fileStream)); - - LevelBuilderWorker worker; - ProductPathDependencySet productDependencies; - - ASSERT_TRUE(worker.PopulateMissionDependenciesHelper(&fileStream, productDependencies)); - ASSERT_THAT(productDependencies, testing::UnorderedElementsAre( - ProductPathDependency{ "EngineAssets/Materials/Sky/Sky.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile}, - ProductPathDependency{ "EngineAssets/Materials/Water/Ocean_default.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile}, - ProductPathDependency{ "Textures/Skys/Night/half_moon.dds", AssetBuilderSDK::ProductPathDependencyType::ProductFile})); -} - -TEST_F(LevelBuilderTest, TestMission_NoSkyBox) -{ - // Tests processing a mission_*.xml file with no skybox settings - // Should output 0 dependencies and return false - - TestFailureCase("mission_mission0_test2.xml"); -} - -TEST_F(LevelBuilderTest, TestMission_NoOcean) -{ - // Tests processing a mission_*.xml file with no ocean settings - // Should output 0 dependencies and return false - - TestFailureCase("mission_mission0_test3.xml"); -} - -TEST_F(LevelBuilderTest, TestMission_NoMoon) -{ - // Tests processing a mission_*.xml file with no moon settings - // Should output 2 dependencies - - IO::FileIOStream fileStream; - - ASSERT_TRUE(OpenTestFile("mission_mission0_test4.xml", fileStream)); - - LevelBuilderWorker worker; - ProductPathDependencySet productDependencies; - - ASSERT_TRUE(worker.PopulateMissionDependenciesHelper(&fileStream, productDependencies)); - ASSERT_THAT(productDependencies, testing::UnorderedElementsAre( - ProductPathDependency{ "EngineAssets/Materials/Sky/Sky.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, - ProductPathDependency{ "EngineAssets/Materials/Water/Ocean_default.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile })); -} - -TEST_F(LevelBuilderTest, TestMission_NoEnvironment) -{ - // Tests processing a mission_*.xml file with no environment settings - // Should output 0 dependencies and return false - - TestFailureCase("mission_mission0_test5.xml"); -} - -TEST_F(LevelBuilderTest, TestMission_EmptyFile) -{ - // Tests processing an empty mission_*.xml - // Should output 0 dependencies and return false - - TestFailureCase("mission_mission0_test6.xml"); -} - -TEST_F(LevelBuilderTest, TestMission_CloudShadow) -{ - // Tests processing a mission_*.xml file with cloud shadow texture set - // Should output 4 dependencies and return true - - using namespace AssetBuilderSDK; - - IO::FileIOStream fileStream; - - ASSERT_TRUE(OpenTestFile("mission_mission0_test7.xml", fileStream)); - - LevelBuilderWorker worker; - ProductPathDependencySet productDependencies; - - ASSERT_TRUE(worker.PopulateMissionDependenciesHelper(&fileStream, productDependencies)); - ASSERT_THAT(productDependencies, testing::UnorderedElementsAre( - ProductPathDependency{ "EngineAssets/Materials/Sky/Sky.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, - ProductPathDependency{ "EngineAssets/Materials/Water/Ocean_default.mtl", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, - ProductPathDependency{ "Textures/Skys/Night/half_moon.dds", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, - ProductPathDependency{ "textures/terrain/ftue_megatexture_02.dds", AssetBuilderSDK::ProductPathDependencyType::ProductFile })); -} - -TEST_F(LevelBuilderTest, DynamicSlice_NoAssetReferences_HasNoProductDependencies) -{ - LevelBuilderWorker worker; - AZStd::vector productDependencies; - ProductPathDependencySet productPathDependencies; - - AZStd::string filePath(GetTestFileAliasedPath("levelSlice_noAssetReferences.entities_xml")); - ASSERT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.c_str())); - - worker.PopulateLevelSliceDependenciesHelper(filePath, productDependencies, productPathDependencies); - ASSERT_EQ(productDependencies.size(), 0); - ASSERT_EQ(productPathDependencies.size(), 0); -} - -TEST_F(LevelBuilderTest, DynamicSlice_HasAssetReference_HasCorrectProductDependency) -{ - LevelBuilderWorker worker; - AZStd::vector productDependencies; - ProductPathDependencySet productPathDependencies; - - AZStd::string filePath(GetTestFileAliasedPath("levelSlice_oneAssetRef.entities_xml")); - ASSERT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.c_str())); - - worker.PopulateLevelSliceDependenciesHelper(filePath, productDependencies, productPathDependencies); - ASSERT_EQ(productPathDependencies.size(), 0); - ASSERT_EQ(productDependencies.size(), 1); - ASSERT_EQ(productDependencies[0].m_dependencyId.m_guid, AZ::Uuid("A8970A25-5043-5519-A927-F180E7D6E8C1")); - ASSERT_EQ(productDependencies[0].m_dependencyId.m_subId, 1); -} - -void BuildSliceWithSimpleAssetReference(const AZStd::vector& filePaths, AZStd::vector& productDependencies, ProductPathDependencySet& productPathDependencies) -{ - auto* assetComponent = aznew MockSimpleAssetRefComponent; - - assetComponent->m_asset.SetAssetPath(filePaths[0].c_str()); - assetComponent->m_secondAsset.SetAssetPath(filePaths[1].c_str()); - assetComponent->m_thirdAsset.SetAssetPath(filePaths[2].c_str()); - - auto sliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, AZ::Data::AssetId(AZ::Uuid::CreateRandom(), 0)); - - LevelBuilderWorker worker; - - worker.PopulateLevelSliceDependenciesHelper(sliceAsset, productDependencies, productPathDependencies); -} - -TEST_F(LevelBuilderTest, DynamicSlice_HasPopulatedSimpleAssetReference_HasCorrectProductDependency) -{ - AZStd::vector productDependencies; - ProductPathDependencySet productPathDependencies; - AZStd::vector filePaths = { "some/test/path.txt", "", "" }; - BuildSliceWithSimpleAssetReference(filePaths, productDependencies, productPathDependencies); - ASSERT_EQ(productDependencies.size(), 0); - ASSERT_EQ(productPathDependencies.size(), 1); - ASSERT_EQ(productPathDependencies.begin()->m_dependencyPath, filePaths[0]); -} - -TEST_F(LevelBuilderTest, DynamicSlice_HasPopulatedSimpleAssetReferencesNoExtension_HasCorrectProductDependency) -{ - AZStd::vector productDependencies; - ProductPathDependencySet productPathDependencies; - AZStd::vector filePaths = { "some/test/path0", "some/test/path1", "some/test/path2" }; - BuildSliceWithSimpleAssetReference(filePaths, productDependencies, productPathDependencies); - ASSERT_EQ(productDependencies.size(), 0); - ASSERT_EQ(productPathDependencies.size(), 3); - - ASSERT_THAT(productPathDependencies, testing::UnorderedElementsAre( - ProductPathDependency{ "some/test/path0.txt", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, - ProductPathDependency{ "some/test/path1.txt", AssetBuilderSDK::ProductPathDependencyType::ProductFile }, - ProductPathDependency{ "some/test/path2.txt", AssetBuilderSDK::ProductPathDependencyType::ProductFile })); -} - -TEST_F(LevelBuilderTest, DynamicSlice_HasEmptySimpleAssetReference_HasNoProductDependency) -{ - AZStd::vector productDependencies; - ProductPathDependencySet productPathDependencies; - AZStd::vector filePaths = { "", "", "" }; - BuildSliceWithSimpleAssetReference(filePaths, productDependencies, productPathDependencies); - ASSERT_EQ(productDependencies.size(), 0); - ASSERT_EQ(productPathDependencies.size(), 0); -} - diff --git a/Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp b/Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp index 16dd59908d..03211a1c1f 100644 --- a/Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp +++ b/Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp @@ -17,242 +17,245 @@ #include #include -using namespace MaterialBuilder; -using namespace AZ; - -class MaterialBuilderTests - : public UnitTest::AllocatorsTestFixture - , public UnitTest::TraceBusRedirector +namespace UnitTest { -protected: - void SetUp() override + using namespace MaterialBuilder; + using namespace AZ; + + class MaterialBuilderTests + : public UnitTest::AllocatorsTestFixture + , public UnitTest::TraceBusRedirector { - UnitTest::AllocatorsTestFixture::SetUp(); - - m_app.reset(aznew AzToolsFramework::ToolsApplication); - m_app->Start(AZ::ComponentApplication::Descriptor()); - // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is - // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash - // in the unit tests. - AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - - const AZStd::string engineRoot = AZ::Test::GetEngineRootPath(); - AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engineRoot.c_str()); - - AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath()); - assetRoot /= "Cache"; - AZ::IO::FileIOBase::GetInstance()->SetAlias("@root@", assetRoot.c_str()); - AZ::IO::FileIOBase::GetInstance()->SetAlias("@assets@", assetRoot.c_str()); - } - - void TearDown() override - { - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - m_app->Stop(); - m_app.reset(); - - UnitTest::AllocatorsTestFixture::TearDown(); - } - - AZStd::string GetTestFileAliasedPath(AZStd::string_view fileName) - { - constexpr char testFileFolder[] = "@engroot@/Gems/LmbrCentral/Code/Tests/Materials/"; - return AZStd::string::format("%s%.*s", testFileFolder, aznumeric_cast(fileName.size()), fileName.data()); - } - - AZStd::string GetTestFileFullPath(AZStd::string_view fileName) - { - AZStd::string aliasedPath = GetTestFileAliasedPath(fileName); - char resolvedPath[AZ_MAX_PATH_LEN]; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(aliasedPath.c_str(), resolvedPath, AZ_MAX_PATH_LEN); - return AZStd::string(resolvedPath); - } - - void TestFailureCase(AZStd::string_view fileName, [[maybe_unused]] int expectedErrorCount) - { - MaterialBuilderWorker worker; - AZStd::vector resolvedPaths; - - AZStd::string absoluteMatPath = GetTestFileFullPath(fileName); - - AZ_TEST_START_ASSERTTEST; - ASSERT_FALSE(worker.GetResolvedTexturePathsFromMaterial(absoluteMatPath, resolvedPaths)); - AZ_TEST_STOP_ASSERTTEST(expectedErrorCount * 2); // The assert tests double count AZ errors, so just multiply expected count by 2 - ASSERT_EQ(resolvedPaths.size(), 0); - } - - void TestSuccessCase(AZStd::string_view fileName, AZStd::vector& expectedTextures) - { - MaterialBuilderWorker worker; - AZStd::vector resolvedPaths; - size_t texturesInMaterialFile = expectedTextures.size(); - - AZStd::string absoluteMatPath = GetTestFileFullPath(fileName); - ASSERT_TRUE(worker.GetResolvedTexturePathsFromMaterial(absoluteMatPath, resolvedPaths)); - ASSERT_EQ(resolvedPaths.size(), texturesInMaterialFile); - if (texturesInMaterialFile > 0 ) + protected: + void SetUp() override { - ASSERT_THAT(resolvedPaths, testing::ElementsAreArray(expectedTextures)); + UnitTest::AllocatorsTestFixture::SetUp(); - AssetBuilderSDK::ProductPathDependencySet dependencies; - ASSERT_TRUE(worker.PopulateProductDependencyList(resolvedPaths, dependencies)); - ASSERT_EQ(dependencies.size(), texturesInMaterialFile); + m_app.reset(aznew AzToolsFramework::ToolsApplication); + m_app->Start(AZ::ComponentApplication::Descriptor()); + // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is + // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash + // in the unit tests. + AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + const AZStd::string engineRoot = AZ::Test::GetEngineRootPath(); + AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engineRoot.c_str()); + + AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath()); + assetRoot /= "Cache"; + AZ::IO::FileIOBase::GetInstance()->SetAlias("@root@", assetRoot.c_str()); + AZ::IO::FileIOBase::GetInstance()->SetAlias("@assets@", assetRoot.c_str()); } - } - void TestSuccessCase(AZStd::string_view fileName, const char* expectedTexture) + void TearDown() override + { + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + m_app->Stop(); + m_app.reset(); + + UnitTest::AllocatorsTestFixture::TearDown(); + } + + AZStd::string GetTestFileAliasedPath(AZStd::string_view fileName) + { + constexpr char testFileFolder[] = "@engroot@/Gems/LmbrCentral/Code/Tests/Materials/"; + return AZStd::string::format("%s%.*s", testFileFolder, aznumeric_cast(fileName.size()), fileName.data()); + } + + AZStd::string GetTestFileFullPath(AZStd::string_view fileName) + { + AZStd::string aliasedPath = GetTestFileAliasedPath(fileName); + char resolvedPath[AZ_MAX_PATH_LEN]; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(aliasedPath.c_str(), resolvedPath, AZ_MAX_PATH_LEN); + return AZStd::string(resolvedPath); + } + + void TestFailureCase(AZStd::string_view fileName, [[maybe_unused]] int expectedErrorCount) + { + MaterialBuilderWorker worker; + AZStd::vector resolvedPaths; + + AZStd::string absoluteMatPath = GetTestFileFullPath(fileName); + + AZ_TEST_START_ASSERTTEST; + ASSERT_FALSE(worker.GetResolvedTexturePathsFromMaterial(absoluteMatPath, resolvedPaths)); + AZ_TEST_STOP_ASSERTTEST(expectedErrorCount * 2); // The assert tests double count AZ errors, so just multiply expected count by 2 + ASSERT_EQ(resolvedPaths.size(), 0); + } + + void TestSuccessCase(AZStd::string_view fileName, AZStd::vector& expectedTextures) + { + MaterialBuilderWorker worker; + AZStd::vector resolvedPaths; + size_t texturesInMaterialFile = expectedTextures.size(); + + AZStd::string absoluteMatPath = GetTestFileFullPath(fileName); + ASSERT_TRUE(worker.GetResolvedTexturePathsFromMaterial(absoluteMatPath, resolvedPaths)); + ASSERT_EQ(resolvedPaths.size(), texturesInMaterialFile); + if (texturesInMaterialFile > 0) + { + ASSERT_THAT(resolvedPaths, testing::ElementsAreArray(expectedTextures)); + + AssetBuilderSDK::ProductPathDependencySet dependencies; + ASSERT_TRUE(worker.PopulateProductDependencyList(resolvedPaths, dependencies)); + ASSERT_EQ(dependencies.size(), texturesInMaterialFile); + } + } + + void TestSuccessCase(AZStd::string_view fileName, const char* expectedTexture) + { + AZStd::vector expectedTextures; + expectedTextures.push_back(expectedTexture); + TestSuccessCase(fileName, expectedTextures); + } + + void TestSuccessCaseNoDependencies(AZStd::string_view fileName) + { + AZStd::vector expectedTextures; + TestSuccessCase(fileName, expectedTextures); + } + + AZStd::unique_ptr m_app; + }; + + TEST_F(MaterialBuilderTests, MaterialBuilder_EmptyFile_ExpectFailure) { - AZStd::vector expectedTextures; - expectedTextures.push_back(expectedTexture); - TestSuccessCase(fileName, expectedTextures); + // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial, when checking for the size of the file. + TestFailureCase("test_mat1.mtl", 1); } - void TestSuccessCaseNoDependencies(AZStd::string_view fileName) + TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_NoChildren_ExpectFailure) { - AZStd::vector expectedTextures; - TestSuccessCase(fileName, expectedTextures); + // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling + // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when both a Textures node and a + // SubMaterials node are not found. No other AZ_Errors should be generated. + TestFailureCase("test_mat2.mtl", 1); } - AZStd::unique_ptr m_app; -}; + TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTexturesNode_NoDependencies) + { + TestSuccessCaseNoDependencies("test_mat3.mtl"); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_EmptyFile_ExpectFailure) -{ - // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial, when checking for the size of the file. - TestFailureCase("test_mat1.mtl", 1); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptySubMaterialNode_ExpectFailure) + { + // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling + // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when a SubMaterials node is present, + // but has no children Material node. No other AZ_Errors should be generated. + TestFailureCase("test_mat4.mtl", 1); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_NoChildren_ExpectFailure) -{ - // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling - // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when both a Textures node and a - // SubMaterials node are not found. No other AZ_Errors should be generated. - TestFailureCase("test_mat2.mtl", 1); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTextureNode_NoDependencies) + { + TestSuccessCaseNoDependencies("test_mat5.mtl"); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTexturesNode_NoDependencies) -{ - TestSuccessCaseNoDependencies("test_mat3.mtl"); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyMaterialInSubMaterial_ExpectFailure) + { + // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling + // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when a SubMaterials node is present, + // but a child Material node has no child Textures node and no child SubMaterials node. No other AZ_Errors should + // be generated. + TestFailureCase("test_mat6.mtl", 1); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptySubMaterialNode_ExpectFailure) -{ - // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling - // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when a SubMaterials node is present, - // but has no children Material node. No other AZ_Errors should be generated. - TestFailureCase("test_mat4.mtl", 1); -} - -TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTextureNode_NoDependencies) -{ - TestSuccessCaseNoDependencies("test_mat5.mtl"); -} - -TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyMaterialInSubMaterial_ExpectFailure) -{ - // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling - // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when a SubMaterials node is present, - // but a child Material node has no child Textures node and no child SubMaterials node. No other AZ_Errors should - // be generated. - TestFailureCase("test_mat6.mtl", 1); -} - -TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTextureNodeInSubMaterial_NoDependencies) -{ - TestSuccessCaseNoDependencies("test_mat7.mtl"); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTextureNodeInSubMaterial_NoDependencies) + { + TestSuccessCaseNoDependencies("test_mat7.mtl"); + } #if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS // The following test file 'test_mat8.mtl' has a windows-specific absolute path, so this test is only valid on windows -TEST_F(MaterialBuilderTests, MaterialBuilder_TextureAbsolutePath_NoDependencies) -{ - TestSuccessCaseNoDependencies("test_mat8.mtl"); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_TextureAbsolutePath_NoDependencies) + { + TestSuccessCaseNoDependencies("test_mat8.mtl"); + } #endif -TEST_F(MaterialBuilderTests, MaterialBuilder_TextureRuntimeAlias_NoDependencies) -{ - TestSuccessCaseNoDependencies("test_mat9.mtl"); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_TextureRuntimeAlias_NoDependencies) + { + TestSuccessCaseNoDependencies("test_mat9.mtl"); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_TextureRuntimeTexture_NoDependencies) -{ - TestSuccessCaseNoDependencies("test_mat10.mtl"); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_TextureRuntimeTexture_NoDependencies) + { + TestSuccessCaseNoDependencies("test_mat10.mtl"); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_ValidSourceFormat) -{ - // texture referenced is textures/natural/terrain/am_floor_tile_ddn.png - const char* expectedPath = "textures/natural/terrain/am_floor_tile_ddn.dds"; - TestSuccessCase("test_mat11.mtl", expectedPath); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_ValidSourceFormat) + { + // texture referenced is textures/natural/terrain/am_floor_tile_ddn.png + const char* expectedPath = "textures/natural/terrain/am_floor_tile_ddn.dds"; + TestSuccessCase("test_mat11.mtl", expectedPath); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_ValidProductFormat) -{ - // texture referenced is textures/natural/terrain/am_floor_tile_ddn.dds - const char* expectedPath = "textures/natural/terrain/am_floor_tile_ddn.dds"; - TestSuccessCase("test_mat12.mtl", expectedPath); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_ValidProductFormat) + { + // texture referenced is textures/natural/terrain/am_floor_tile_ddn.dds + const char* expectedPath = "textures/natural/terrain/am_floor_tile_ddn.dds"; + TestSuccessCase("test_mat12.mtl", expectedPath); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_InvalidSourceFormat_NoDependenices) -{ - // texture referenced is textures/natural/terrain/am_floor_tile_ddn.txt - TestSuccessCaseNoDependencies("test_mat13.mtl"); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_InvalidSourceFormat_NoDependenices) + { + // texture referenced is textures/natural/terrain/am_floor_tile_ddn.txt + TestSuccessCaseNoDependencies("test_mat13.mtl"); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_TextureAnimSequence) -{ - AZStd::vector expectedPaths = { - "path/to/my/textures/test_anim_sequence_01_texture000.dds", - "path/to/my/textures/test_anim_sequence_01_texture001.dds", - "path/to/my/textures/test_anim_sequence_01_texture002.dds", - "path/to/my/textures/test_anim_sequence_01_texture003.dds", - "path/to/my/textures/test_anim_sequence_01_texture004.dds", - "path/to/my/textures/test_anim_sequence_01_texture005.dds" - }; - TestSuccessCase("test_mat14.mtl", expectedPaths); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_TextureAnimSequence) + { + AZStd::vector expectedPaths = { + "path/to/my/textures/test_anim_sequence_01_texture000.dds", + "path/to/my/textures/test_anim_sequence_01_texture001.dds", + "path/to/my/textures/test_anim_sequence_01_texture002.dds", + "path/to/my/textures/test_anim_sequence_01_texture003.dds", + "path/to/my/textures/test_anim_sequence_01_texture004.dds", + "path/to/my/textures/test_anim_sequence_01_texture005.dds" + }; + TestSuccessCase("test_mat14.mtl", expectedPaths); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialMultipleTexture) -{ - AZStd::vector expectedPaths = { - "engineassets/textures/hex.dds", - "engineassets/textures/hex_ddn.dds" - }; - TestSuccessCase("test_mat15.mtl", expectedPaths); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialMultipleTexture) + { + AZStd::vector expectedPaths = { + "engineassets/textures/hex.dds", + "engineassets/textures/hex_ddn.dds" + }; + TestSuccessCase("test_mat15.mtl", expectedPaths); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_MultipleTextures_OneEmptyTexture) -{ - TestSuccessCase("test_mat16.mtl", "engineassets/textures/hex_ddn.dds"); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_MultipleTextures_OneEmptyTexture) + { + TestSuccessCase("test_mat16.mtl", "engineassets/textures/hex_ddn.dds"); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialMultipleTexture_ResolveLeadingSeparatorsAndAliases) -{ - AZStd::vector expectedPaths = { - "engineassets/textures/hex.dds", // resolved from "/engineassets/textures/hex.dds" - "engineassets/textures/hex_ddn.dds", // resolved from "./engineassets/textures/hex_ddn.dds" - "engineassets/textures/hex_spec.dds" // resolved from "@assets@/engineassets/textures/hex_spec.dds" - }; - TestSuccessCase("test_mat17.mtl", expectedPaths); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialMultipleTexture_ResolveLeadingSeparatorsAndAliases) + { + AZStd::vector expectedPaths = { + "engineassets/textures/hex.dds", // resolved from "/engineassets/textures/hex.dds" + "engineassets/textures/hex_ddn.dds", // resolved from "./engineassets/textures/hex_ddn.dds" + "engineassets/textures/hex_spec.dds" // resolved from "@assets@/engineassets/textures/hex_spec.dds" + }; + TestSuccessCase("test_mat17.mtl", expectedPaths); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_SubMaterialSingleTexture) -{ - AZStd::vector expectedPaths = { - "engineassets/textures/scratch.dds", - "engineassets/textures/perlinnoise2d.dds" - }; - TestSuccessCase("test_mat18.mtl", expectedPaths); -} + TEST_F(MaterialBuilderTests, MaterialBuilder_SubMaterialSingleTexture) + { + AZStd::vector expectedPaths = { + "engineassets/textures/scratch.dds", + "engineassets/textures/perlinnoise2d.dds" + }; + TestSuccessCase("test_mat18.mtl", expectedPaths); + } -TEST_F(MaterialBuilderTests, MaterialBuilder_SubMaterialMultipleTexture) -{ - AZStd::vector expectedPaths = { - "engineassets/textures/scratch.dds", - "engineassets/textures/scratch_ddn.dds", - "engineassets/textures/perlinnoise2d.dds", - "engineassets/textures/perlinnoisenormal_ddn.dds" - }; - TestSuccessCase("test_mat19.mtl", expectedPaths); + TEST_F(MaterialBuilderTests, MaterialBuilder_SubMaterialMultipleTexture) + { + AZStd::vector expectedPaths = { + "engineassets/textures/scratch.dds", + "engineassets/textures/scratch_ddn.dds", + "engineassets/textures/perlinnoise2d.dds", + "engineassets/textures/perlinnoisenormal_ddn.dds" + }; + TestSuccessCase("test_mat19.mtl", expectedPaths); + } } diff --git a/Gems/LmbrCentral/Code/Tests/Builders/SliceBuilderTests.cpp b/Gems/LmbrCentral/Code/Tests/Builders/SliceBuilderTests.cpp index 78be853891..a9059b0072 100644 --- a/Gems/LmbrCentral/Code/Tests/Builders/SliceBuilderTests.cpp +++ b/Gems/LmbrCentral/Code/Tests/Builders/SliceBuilderTests.cpp @@ -24,674 +24,675 @@ #include "AzFramework/Asset/SimpleAsset.h" #include "Tests/AZTestShared/Utils/Utils.h" -using namespace SliceBuilder; - -using namespace AZ; -using namespace UnitTest; - -struct MockAsset - : public AZ::Data::AssetData +namespace UnitTest { - AZ_RTTI(MockAsset, "{6A98A05A-5B8B-455B-BA92-508A7CF76024}", AZ::Data::AssetData); + using namespace SliceBuilder; + using namespace AZ; - static void Reflect(ReflectContext* reflection) + struct MockAsset + : public AZ::Data::AssetData { - SerializeContext* serializeContext = azrtti_cast(reflection); - - if (serializeContext) - { - serializeContext->Class() - ->Field("value", &MockAsset::m_value); - } - } - - int m_value = 0; -}; - -struct MockAssetRefComponent - : public AZ::Component -{ - AZ_COMPONENT(MockAssetRefComponent, "{92A6CEC4-BB83-4BED-B062-8A69302E0C9D}"); - - static void Reflect(ReflectContext* reflection) - { - SerializeContext* serializeContext = azrtti_cast(reflection); - - if (serializeContext) - { - serializeContext->Class() - ->Field("asset", &MockAssetRefComponent::m_asset); - } - } - - void Activate() override {} - void Deactivate() override {} - - Data::Asset m_asset; -}; - -class MockSimpleSliceAsset -{ -public: - AZ_TYPE_INFO(MockSimpleSliceAsset, "{923AE476-3491-49F7-A77C-70C896C1B1FD}"); - - static const char* GetFileFilter() - { - return "*.txt;"; - } -}; - -struct MockSubType -{ - AZ_TYPE_INFO(MockSubType, "{25824223-EE7E-4F44-8181-6D3AC5119BB9}"); - - static void Reflect(ReflectContext* reflection) - { - SerializeContext* serializeContext = azrtti_cast(reflection); - - if (serializeContext) - { - serializeContext->Class() - ->Version(m_version); - } - } - - static int m_version; -}; - -int MockSubType::m_version = 1; - -struct MockComponent : AZ::Component -{ - AZ_COMPONENT(MockComponent, "{0A556691-1658-48B7-9745-5FDBA8E13D11}"); - - static void Reflect(ReflectContext* reflection) - { - SerializeContext* serializeContext = azrtti_cast(reflection); - - if (serializeContext) - { - serializeContext->Class() - ->Field("subdata", &MockComponent::m_subData); - } - } - - void Activate() override {} - void Deactivate() override {} - - MockSubType m_subData{}; -}; - -namespace SliceBuilder -{ - struct MockSimpleSliceAssetRefComponent - : public AZ::Component - { - AZ_COMPONENT(MockSimpleSliceAssetRefComponent, "{C3B2F100-D08C-4912-AC16-57506B190C2F}"); + AZ_RTTI(MockAsset, "{6A98A05A-5B8B-455B-BA92-508A7CF76024}", AZ::Data::AssetData); static void Reflect(ReflectContext* reflection) { SerializeContext* serializeContext = azrtti_cast(reflection); - AzFramework::SimpleAssetReference::Register(*serializeContext); + if (serializeContext) + { + serializeContext->Class() + ->Field("value", &MockAsset::m_value); + } + } + + int m_value = 0; + }; + + struct MockAssetRefComponent + : public AZ::Component + { + AZ_COMPONENT(MockAssetRefComponent, "{92A6CEC4-BB83-4BED-B062-8A69302E0C9D}"); + + static void Reflect(ReflectContext* reflection) + { + SerializeContext* serializeContext = azrtti_cast(reflection); if (serializeContext) { - serializeContext->Class() - ->Field("asset", &MockSimpleSliceAssetRefComponent::m_asset); + serializeContext->Class() + ->Field("asset", &MockAssetRefComponent::m_asset); } } void Activate() override {} void Deactivate() override {} - AzFramework::SimpleAssetReference m_asset; + Data::Asset m_asset; }; -} -struct MockEditorComponent - : public AzToolsFramework::Components::EditorComponentBase -{ - AZ_EDITOR_COMPONENT(MockEditorComponent, "{550BA62B-9A98-4A6E-BF7D-7BC939796CF5}"); - - static void Reflect(ReflectContext* reflection) + class MockSimpleSliceAsset { - SerializeContext* serializeContext = azrtti_cast(reflection); + public: + AZ_TYPE_INFO(MockSimpleSliceAsset, "{923AE476-3491-49F7-A77C-70C896C1B1FD}"); - if (serializeContext) + static const char* GetFileFilter() { - serializeContext->Class() - ->Field("uuid", &MockEditorComponent::m_uuid); + return "*.txt;"; } - } + }; - void BuildGameEntity(AZ::Entity* gameEntity) override + struct MockSubType { - auto* assetComponent = aznew MockAssetRefComponent; - assetComponent->m_asset = Data::AssetManager::Instance().CreateAsset(AZ::Data::AssetId(m_uuid, 0), AZ::Data::AssetLoadBehavior::Default); - - gameEntity->AddComponent(assetComponent); - } + AZ_TYPE_INFO(MockSubType, "{25824223-EE7E-4F44-8181-6D3AC5119BB9}"); - AZ::Uuid m_uuid; -}; - -using namespace AZ::Data; - -class SliceBuilderTest_MockCatalog - : public AssetCatalog - , public AZ::Data::AssetCatalogRequestBus::Handler -{ -private: - AZ::Uuid randomUuid = AZ::Uuid::CreateRandom(); - AZStd::vector m_mockAssetIds; - -public: - AZ_CLASS_ALLOCATOR(SliceBuilderTest_MockCatalog, AZ::SystemAllocator, 0); - - SliceBuilderTest_MockCatalog() - { - AssetCatalogRequestBus::Handler::BusConnect(); - } - - ~SliceBuilderTest_MockCatalog() - { - AssetCatalogRequestBus::Handler::BusDisconnect(); - } - - AssetId GenerateMockAssetId() - { - AssetId assetId = AssetId(AZ::Uuid::CreateRandom(), 0); - m_mockAssetIds.push_back(assetId); - return assetId; - } - - ////////////////////////////////////////////////////////////////////////// - // AssetCatalogRequestBus - AssetInfo GetAssetInfoById(const AssetId& id) override - { - AssetInfo result; - result.m_assetType = AZ::AzTypeInfo::Uuid(); - for (const AssetId& assetId : m_mockAssetIds) + static void Reflect(ReflectContext* reflection) { - if (assetId == id) - { - result.m_assetId = id; - break; - } - } - return result; - } - ////////////////////////////////////////////////////////////////////////// + SerializeContext* serializeContext = azrtti_cast(reflection); - AssetStreamInfo GetStreamInfoForLoad(const AssetId& id, const AssetType& type) override - { - EXPECT_TRUE(type == AzTypeInfo::Uuid()); - AssetStreamInfo info; - info.m_dataOffset = 0; - info.m_streamFlags = IO::OpenMode::ModeRead; - - for (int i = 0; i < m_mockAssetIds.size(); ++i) - { - if (m_mockAssetIds[i] == id) + if (serializeContext) { - info.m_streamName = AZStd::string::format("MockSliceAssetName%d", i); + serializeContext->Class() + ->Version(m_version); } } - if (!info.m_streamName.empty()) + static int m_version; + }; + + int MockSubType::m_version = 1; + + struct MockComponent : AZ::Component + { + AZ_COMPONENT(MockComponent, "{0A556691-1658-48B7-9745-5FDBA8E13D11}"); + + static void Reflect(ReflectContext* reflection) { - // this ensures tha parallel running unit tests do not overlap their files that they use. - AZStd::string fullName = AZStd::string::format("%s%s-%s", GetTestFolderPath().c_str(), randomUuid.ToString().c_str(), info.m_streamName.c_str()); - info.m_streamName = fullName; - info.m_dataLen = static_cast(IO::SystemFile::Length(info.m_streamName.c_str())); - } - else - { - info.m_dataLen = 0; + SerializeContext* serializeContext = azrtti_cast(reflection); + + if (serializeContext) + { + serializeContext->Class() + ->Field("subdata", &MockComponent::m_subData); + } } - return info; + void Activate() override {} + void Deactivate() override {} + + MockSubType m_subData{}; + }; + + namespace SliceBuilder + { + struct MockSimpleSliceAssetRefComponent + : public AZ::Component + { + AZ_COMPONENT(MockSimpleSliceAssetRefComponent, "{C3B2F100-D08C-4912-AC16-57506B190C2F}"); + + static void Reflect(ReflectContext* reflection) + { + SerializeContext* serializeContext = azrtti_cast(reflection); + + AzFramework::SimpleAssetReference::Register(*serializeContext); + + if (serializeContext) + { + serializeContext->Class() + ->Field("asset", &MockSimpleSliceAssetRefComponent::m_asset); + } + } + + void Activate() override {} + void Deactivate() override {} + + AzFramework::SimpleAssetReference m_asset; + }; } - AssetStreamInfo GetStreamInfoForSave(const AssetId& id, const AssetType& type) override + struct MockEditorComponent + : public AzToolsFramework::Components::EditorComponentBase { - AssetStreamInfo info; - info = GetStreamInfoForLoad(id, type); - info.m_streamFlags = IO::OpenMode::ModeWrite; - return info; - } + AZ_EDITOR_COMPONENT(MockEditorComponent, "{550BA62B-9A98-4A6E-BF7D-7BC939796CF5}"); - bool SaveAsset(Asset& asset) - { - volatile bool isDone = false; - volatile bool succeeded = false; - AssetBusCallbacks callbacks; - callbacks.SetCallbacks(nullptr, nullptr, nullptr, - [&isDone, &succeeded](const Asset& /*asset*/, bool isSuccessful, AssetBusCallbacks& /*callbacks*/) + static void Reflect(ReflectContext* reflection) { - isDone = true; - succeeded = isSuccessful; - }, nullptr, nullptr, nullptr); + SerializeContext* serializeContext = azrtti_cast(reflection); - callbacks.BusConnect(asset.GetId()); - asset.Save(); - - while (!isDone) - { - AssetManager::Instance().DispatchEvents(); + if (serializeContext) + { + serializeContext->Class() + ->Field("uuid", &MockEditorComponent::m_uuid); + } } - return succeeded; - } -}; -class DependencyTest - : public AllocatorsFixture - , public ComponentApplicationBus::Handler -{ -public: - - ////////////////////////////////////////////////////////////////////////// - // ComponentApplicationMessages - ComponentApplication* GetApplication() override { return nullptr; } - void RegisterComponentDescriptor(const ComponentDescriptor*) override { } - void UnregisterComponentDescriptor(const ComponentDescriptor*) override { } - void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler&) override { } - void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler&) override { } - void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler&) override { } - void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler&) override { } - void SignalEntityActivated(Entity*) override { } - void SignalEntityDeactivated(Entity*) override { } - bool AddEntity(Entity*) override { return true; } - bool RemoveEntity(Entity*) override { return true; } - bool DeleteEntity(const AZ::EntityId&) override { return true; } - Entity* FindEntity(const AZ::EntityId&) override { return nullptr; } - SerializeContext* GetSerializeContext() override { return m_serializeContext; } - BehaviorContext* GetBehaviorContext() override { return nullptr; } - JsonRegistrationContext* GetJsonRegistrationContext() override { return nullptr; } - const char* GetAppRoot() const override { return nullptr; } - const char* GetEngineRoot() const override { return nullptr; } - const char* GetExecutableFolder() const override { return nullptr; } - Debug::DrillerManager* GetDrillerManager() override { return nullptr; } - void EnumerateEntities(const EntityCallback& /*callback*/) override {} - void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {} - ////////////////////////////////////////////////////////////////////////// - - void SetUp() override - { - AllocatorsFixture::SetUp(); - - AllocatorInstance::Create(); - AllocatorInstance::Create(); - - m_serializeContext = aznew SerializeContext(true, true); - - ComponentApplicationBus::Handler::BusConnect(); - AZ::Interface::Register(this); - - m_sliceDescriptor = SliceComponent::CreateDescriptor(); - m_mockAssetDescriptor = MockAssetRefComponent::CreateDescriptor(); - m_mockSimpleAssetDescriptor = MockSimpleSliceAssetRefComponent::CreateDescriptor(); - - m_sliceDescriptor->Reflect(m_serializeContext); - m_mockAssetDescriptor->Reflect(m_serializeContext); - m_mockSimpleAssetDescriptor->Reflect(m_serializeContext); - - AzFramework::SimpleAssetReferenceBase::Reflect(m_serializeContext); - MockAsset::Reflect(m_serializeContext); - MockEditorComponent::Reflect(m_serializeContext); - Entity::Reflect(m_serializeContext); - DataPatch::Reflect(m_serializeContext); - SliceMetadataInfoComponent::Reflect(m_serializeContext); - AzToolsFramework::Components::EditorComponentBase::Reflect(m_serializeContext); - - // Create database - Data::AssetManager::Descriptor desc; - Data::AssetManager::Create(desc); - Data::AssetManager::Instance().RegisterHandler(aznew SliceAssetHandler(m_serializeContext), AzTypeInfo::Uuid()); - Data::AssetManager::Instance().RegisterHandler(aznew AzFramework::GenericAssetHandler("Mock Asset", "Other", "mockasset"), AZ::AzTypeInfo::Uuid()); - m_catalog.reset(aznew SliceBuilderTest_MockCatalog()); - AssetManager::Instance().RegisterCatalog(m_catalog.get(), AzTypeInfo::Uuid()); - } - - void TearDown() override - { - m_catalog->DisableCatalog(); - AZ::Interface::Unregister(this); - ComponentApplicationBus::Handler::BusDisconnect(); - - Data::AssetManager::Destroy(); - m_catalog.reset(); - delete m_mockSimpleAssetDescriptor; - delete m_mockAssetDescriptor; - delete m_sliceDescriptor; - delete m_serializeContext; - - AllocatorInstance::Destroy(); - AllocatorInstance::Destroy(); - - AllocatorsFixture::TearDown(); - } - - void VerifyDependency(AZ::Data::Asset& sliceAsset, AZ::Data::AssetId mockAssetId) - { - AZ::PlatformTagSet platformTags; - AZ::Data::Asset exportSliceAsset; - - AZStd::shared_ptr assetDataStream = AZStd::make_shared(); - - // Save the slice asset into a memory buffer, then hand ownership of the buffer to assetDataStream + void BuildGameEntity(AZ::Entity* gameEntity) override { + auto* assetComponent = aznew MockAssetRefComponent; + assetComponent->m_asset = Data::AssetManager::Instance().CreateAsset(AZ::Data::AssetId(m_uuid, 0), AZ::Data::AssetLoadBehavior::Default); + + gameEntity->AddComponent(assetComponent); + } + + AZ::Uuid m_uuid; + }; + + using namespace AZ::Data; + + class SliceBuilderTest_MockCatalog + : public AssetCatalog + , public AZ::Data::AssetCatalogRequestBus::Handler + { + private: + AZ::Uuid randomUuid = AZ::Uuid::CreateRandom(); + AZStd::vector m_mockAssetIds; + + public: + AZ_CLASS_ALLOCATOR(SliceBuilderTest_MockCatalog, AZ::SystemAllocator, 0); + + SliceBuilderTest_MockCatalog() + { + AssetCatalogRequestBus::Handler::BusConnect(); + } + + ~SliceBuilderTest_MockCatalog() + { + AssetCatalogRequestBus::Handler::BusDisconnect(); + } + + AssetId GenerateMockAssetId() + { + AssetId assetId = AssetId(AZ::Uuid::CreateRandom(), 0); + m_mockAssetIds.push_back(assetId); + return assetId; + } + + ////////////////////////////////////////////////////////////////////////// + // AssetCatalogRequestBus + AssetInfo GetAssetInfoById(const AssetId& id) override + { + AssetInfo result; + result.m_assetType = AZ::AzTypeInfo::Uuid(); + for (const AssetId& assetId : m_mockAssetIds) + { + if (assetId == id) + { + result.m_assetId = id; + break; + } + } + return result; + } + ////////////////////////////////////////////////////////////////////////// + + AssetStreamInfo GetStreamInfoForLoad(const AssetId& id, const AssetType& type) override + { + EXPECT_TRUE(type == AzTypeInfo::Uuid()); + AssetStreamInfo info; + info.m_dataOffset = 0; + info.m_streamFlags = IO::OpenMode::ModeRead; + + for (int i = 0; i < m_mockAssetIds.size(); ++i) + { + if (m_mockAssetIds[i] == id) + { + info.m_streamName = AZStd::string::format("MockSliceAssetName%d", i); + } + } + + if (!info.m_streamName.empty()) + { + // this ensures tha parallel running unit tests do not overlap their files that they use. + AZStd::string fullName = AZStd::string::format("%s%s-%s", GetTestFolderPath().c_str(), randomUuid.ToString().c_str(), info.m_streamName.c_str()); + info.m_streamName = fullName; + info.m_dataLen = static_cast(IO::SystemFile::Length(info.m_streamName.c_str())); + } + else + { + info.m_dataLen = 0; + } + + return info; + } + + AssetStreamInfo GetStreamInfoForSave(const AssetId& id, const AssetType& type) override + { + AssetStreamInfo info; + info = GetStreamInfoForLoad(id, type); + info.m_streamFlags = IO::OpenMode::ModeWrite; + return info; + } + + bool SaveAsset(Asset& asset) + { + volatile bool isDone = false; + volatile bool succeeded = false; + AssetBusCallbacks callbacks; + callbacks.SetCallbacks(nullptr, nullptr, nullptr, + [&isDone, &succeeded](const Asset& /*asset*/, bool isSuccessful, AssetBusCallbacks& /*callbacks*/) + { + isDone = true; + succeeded = isSuccessful; + }, nullptr, nullptr, nullptr); + + callbacks.BusConnect(asset.GetId()); + asset.Save(); + + while (!isDone) + { + AssetManager::Instance().DispatchEvents(); + } + return succeeded; + } + }; + + class DependencyTest + : public AllocatorsFixture + , public ComponentApplicationBus::Handler + { + public: + + ////////////////////////////////////////////////////////////////////////// + // ComponentApplicationMessages + ComponentApplication* GetApplication() override { return nullptr; } + void RegisterComponentDescriptor(const ComponentDescriptor*) override { } + void UnregisterComponentDescriptor(const ComponentDescriptor*) override { } + void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler&) override { } + void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler&) override { } + void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler&) override { } + void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler&) override { } + void SignalEntityActivated(Entity*) override { } + void SignalEntityDeactivated(Entity*) override { } + bool AddEntity(Entity*) override { return true; } + bool RemoveEntity(Entity*) override { return true; } + bool DeleteEntity(const AZ::EntityId&) override { return true; } + Entity* FindEntity(const AZ::EntityId&) override { return nullptr; } + SerializeContext* GetSerializeContext() override { return m_serializeContext; } + BehaviorContext* GetBehaviorContext() override { return nullptr; } + JsonRegistrationContext* GetJsonRegistrationContext() override { return nullptr; } + const char* GetAppRoot() const override { return nullptr; } + const char* GetEngineRoot() const override { return nullptr; } + const char* GetExecutableFolder() const override { return nullptr; } + Debug::DrillerManager* GetDrillerManager() override { return nullptr; } + void EnumerateEntities(const EntityCallback& /*callback*/) override {} + void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {} + ////////////////////////////////////////////////////////////////////////// + + void SetUp() override + { + AllocatorsFixture::SetUp(); + + AllocatorInstance::Create(); + AllocatorInstance::Create(); + + m_serializeContext = aznew SerializeContext(true, true); + + ComponentApplicationBus::Handler::BusConnect(); + AZ::Interface::Register(this); + + m_sliceDescriptor = SliceComponent::CreateDescriptor(); + m_mockAssetDescriptor = MockAssetRefComponent::CreateDescriptor(); + m_mockSimpleAssetDescriptor = SliceBuilder::MockSimpleSliceAssetRefComponent::CreateDescriptor(); + + m_sliceDescriptor->Reflect(m_serializeContext); + m_mockAssetDescriptor->Reflect(m_serializeContext); + m_mockSimpleAssetDescriptor->Reflect(m_serializeContext); + + AzFramework::SimpleAssetReferenceBase::Reflect(m_serializeContext); + MockAsset::Reflect(m_serializeContext); + MockEditorComponent::Reflect(m_serializeContext); + Entity::Reflect(m_serializeContext); + DataPatch::Reflect(m_serializeContext); + SliceMetadataInfoComponent::Reflect(m_serializeContext); + AzToolsFramework::Components::EditorComponentBase::Reflect(m_serializeContext); + + // Create database + Data::AssetManager::Descriptor desc; + Data::AssetManager::Create(desc); + Data::AssetManager::Instance().RegisterHandler(aznew SliceAssetHandler(m_serializeContext), AzTypeInfo::Uuid()); + Data::AssetManager::Instance().RegisterHandler(aznew AzFramework::GenericAssetHandler("Mock Asset", "Other", "mockasset"), AZ::AzTypeInfo::Uuid()); + m_catalog.reset(aznew SliceBuilderTest_MockCatalog()); + AssetManager::Instance().RegisterCatalog(m_catalog.get(), AzTypeInfo::Uuid()); + } + + void TearDown() override + { + m_catalog->DisableCatalog(); + AZ::Interface::Unregister(this); + ComponentApplicationBus::Handler::BusDisconnect(); + + Data::AssetManager::Destroy(); + m_catalog.reset(); + delete m_mockSimpleAssetDescriptor; + delete m_mockAssetDescriptor; + delete m_sliceDescriptor; + delete m_serializeContext; + + AllocatorInstance::Destroy(); + AllocatorInstance::Destroy(); + + AllocatorsFixture::TearDown(); + } + + void VerifyDependency(AZ::Data::Asset& sliceAsset, AZ::Data::AssetId mockAssetId) + { + AZ::PlatformTagSet platformTags; + AZ::Data::Asset exportSliceAsset; + + AZStd::shared_ptr assetDataStream = AZStd::make_shared(); + + // Save the slice asset into a memory buffer, then hand ownership of the buffer to assetDataStream + { + AZ::SliceAssetHandler assetHandler; + assetHandler.SetSerializeContext(nullptr); + + AZStd::vector charBuffer; + AZ::IO::ByteContainerStream> charStream(&charBuffer); + assetHandler.SaveAssetData(sliceAsset, &charStream); + + assetDataStream->Open(AZStd::move(charBuffer)); + } + + bool result = SliceBuilderWorker::GetCompiledSliceAsset(assetDataStream, "MockAsset.slice", platformTags, exportSliceAsset); + ASSERT_TRUE(result); + + AssetBuilderSDK::JobProduct jobProduct; + ASSERT_TRUE(SliceBuilderWorker::OutputSliceJob(exportSliceAsset, "test.slice", jobProduct)); + + ASSERT_EQ(jobProduct.m_dependencies.size(), 1); + ASSERT_EQ(jobProduct.m_dependencies[0].m_dependencyId, mockAssetId); + } + + void BuildSliceWithSimpleAssetReference( + const char* simpleAssetPath, + AZStd::vector& productDependencies, + AssetBuilderSDK::ProductPathDependencySet& productPathDependencies) + { + auto* assetComponent = aznew SliceBuilder::MockSimpleSliceAssetRefComponent; + + assetComponent->m_asset.SetAssetPath(simpleAssetPath); + + auto sliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, m_catalog->GenerateMockAssetId()); + AZ::SliceAssetHandler assetHandler; assetHandler.SetSerializeContext(nullptr); - AZStd::vector charBuffer; - AZ::IO::ByteContainerStream> charStream(&charBuffer); - assetHandler.SaveAssetData(sliceAsset, &charStream); + AZStd::shared_ptr assetDataStream = AZStd::make_shared(); - assetDataStream->Open(AZStd::move(charBuffer)); + // Save the slice asset into a memory buffer, then hand ownership of the buffer to assetDataStream + { + AZStd::vector charBuffer; + AZ::IO::ByteContainerStream> charStream(&charBuffer); + assetHandler.SaveAssetData(sliceAsset, &charStream); + + assetDataStream->Open(AZStd::move(charBuffer)); + } + + AZ::PlatformTagSet platformTags; + AZ::Data::Asset exportSliceAsset; + + bool result = SliceBuilderWorker::GetCompiledSliceAsset(assetDataStream, "MockAsset.slice", platformTags, exportSliceAsset); + ASSERT_TRUE(result); + + AssetBuilderSDK::JobProduct jobProduct; + ASSERT_TRUE(SliceBuilderWorker::OutputSliceJob(exportSliceAsset, "test.slice", jobProduct)); + + productDependencies = AZStd::move(jobProduct.m_dependencies); + productPathDependencies = AZStd::move(jobProduct.m_pathDependencies); } - bool result = SliceBuilderWorker::GetCompiledSliceAsset(assetDataStream, "MockAsset.slice", platformTags, exportSliceAsset); - ASSERT_TRUE(result); + SerializeContext* m_serializeContext; + ComponentDescriptor* m_sliceDescriptor; + ComponentDescriptor* m_mockAssetDescriptor; + ComponentDescriptor* m_mockSimpleAssetDescriptor; + AZStd::unique_ptr m_catalog; + }; - AssetBuilderSDK::JobProduct jobProduct; - ASSERT_TRUE(SliceBuilderWorker::OutputSliceJob(exportSliceAsset, "test.slice", jobProduct)); - - ASSERT_EQ(jobProduct.m_dependencies.size(), 1); - ASSERT_EQ(jobProduct.m_dependencies[0].m_dependencyId, mockAssetId); - } - - void BuildSliceWithSimpleAssetReference( - const char* simpleAssetPath, - AZStd::vector& productDependencies, - AssetBuilderSDK::ProductPathDependencySet& productPathDependencies) + TEST_F(DependencyTest, SimpleSliceTest) { - auto* assetComponent = aznew MockSimpleSliceAssetRefComponent; + // Test a slice containing a component that references an asset + // Should return a dependency on the asset - assetComponent->m_asset.SetAssetPath(simpleAssetPath); + auto* assetComponent = aznew MockAssetRefComponent; + + AZ::Data::AssetId mockAssetId(AZ::Uuid::CreateRandom(), 0); + assetComponent->m_asset = Data::AssetManager::Instance().CreateAsset(mockAssetId, AZ::Data::AssetLoadBehavior::Default); auto sliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, m_catalog->GenerateMockAssetId()); - AZ::SliceAssetHandler assetHandler; - assetHandler.SetSerializeContext(nullptr); + VerifyDependency(sliceAsset, mockAssetId); + } - AZStd::shared_ptr assetDataStream = AZStd::make_shared(); + TEST_F(DependencyTest, NestedSliceTest) + { + // Test a slice that references another slice, which contains a reference to an asset. + // Should return only a dependency on the asset, and not the inner slice - // Save the slice asset into a memory buffer, then hand ownership of the buffer to assetDataStream + auto* outerSliceEntity = aznew AZ::Entity; + auto* assetComponent = aznew MockAssetRefComponent; + + AZ::Data::AssetId mockAssetId(m_catalog->GenerateMockAssetId()); + assetComponent->m_asset = Data::AssetManager::Instance().CreateAsset(mockAssetId, AZ::Data::AssetLoadBehavior::Default); + + auto innerSliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, m_catalog->GenerateMockAssetId()); + + AZ::Data::AssetId outerSliceAssetId(m_catalog->GenerateMockAssetId()); + auto outerSliceAsset = Data::AssetManager::Instance().CreateAsset(outerSliceAssetId, AZ::Data::AssetLoadBehavior::Default); + + AZ::SliceComponent* outerSlice = outerSliceEntity->CreateComponent(); + outerSlice->SetIsDynamic(true); + outerSliceAsset.Get()->SetData(outerSliceEntity, outerSlice); + outerSlice->AddSlice(innerSliceAsset); + + VerifyDependency(outerSliceAsset, mockAssetId); + } + + TEST_F(DependencyTest, DataPatchTest) + { + // Test a slice that references another slice, with the outer slice being data-patched to have a reference to an asset + // Should return a dependency on the asset, but not the inner slice + + auto* outerSliceEntity = aznew AZ::Entity; + auto* assetComponent = aznew MockAssetRefComponent; + + AZ::Data::AssetId outerSliceAssetId(m_catalog->GenerateMockAssetId()); + auto outerSliceAsset = Data::AssetManager::Instance().CreateAsset(outerSliceAssetId, AZ::Data::AssetLoadBehavior::Default); + + auto innerSliceAsset = AZ::Test::CreateSliceFromComponent(nullptr, m_catalog->GenerateMockAssetId()); + + AZ::SliceComponent* outerSlice = outerSliceEntity->CreateComponent(); + outerSlice->SetIsDynamic(true); + outerSliceAsset.Get()->SetData(outerSliceEntity, outerSlice); + outerSlice->AddSlice(innerSliceAsset); + + outerSlice->Instantiate(); + + auto* sliceRef = outerSlice->GetSlice(innerSliceAsset); + auto& instances = sliceRef->GetInstances(); + + AZ::Data::AssetId mockAssetId(m_catalog->GenerateMockAssetId()); + assetComponent->m_asset = Data::AssetManager::Instance().CreateAsset(mockAssetId, AZ::Data::AssetLoadBehavior::Default); + + for (const AZ::SliceComponent::SliceInstance& i : instances) { - AZStd::vector charBuffer; - AZ::IO::ByteContainerStream> charStream(&charBuffer); - assetHandler.SaveAssetData(sliceAsset, &charStream); + const AZ::SliceComponent::InstantiatedContainer* container = i.GetInstantiated(); + container->m_entities[0]->AddComponent(assetComponent); - assetDataStream->Open(AZStd::move(charBuffer)); + sliceRef->ComputeDataPatch(); } - AZ::PlatformTagSet platformTags; - AZ::Data::Asset exportSliceAsset; + VerifyDependency(outerSliceAsset, mockAssetId); - bool result = SliceBuilderWorker::GetCompiledSliceAsset(assetDataStream, "MockAsset.slice", platformTags, exportSliceAsset); - ASSERT_TRUE(result); - - AssetBuilderSDK::JobProduct jobProduct; - ASSERT_TRUE(SliceBuilderWorker::OutputSliceJob(exportSliceAsset, "test.slice", jobProduct)); - - productDependencies = AZStd::move(jobProduct.m_dependencies); - productPathDependencies = AZStd::move(jobProduct.m_pathDependencies); + delete assetComponent; } - SerializeContext* m_serializeContext; - ComponentDescriptor* m_sliceDescriptor; - ComponentDescriptor* m_mockAssetDescriptor; - ComponentDescriptor* m_mockSimpleAssetDescriptor; - AZStd::unique_ptr m_catalog; -}; - -TEST_F(DependencyTest, SimpleSliceTest) -{ - // Test a slice containing a component that references an asset - // Should return a dependency on the asset - - auto* assetComponent = aznew MockAssetRefComponent; - - AZ::Data::AssetId mockAssetId(AZ::Uuid::CreateRandom(), 0); - assetComponent->m_asset = Data::AssetManager::Instance().CreateAsset(mockAssetId, AZ::Data::AssetLoadBehavior::Default); - - auto sliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, m_catalog->GenerateMockAssetId()); - - VerifyDependency(sliceAsset, mockAssetId); -} - -TEST_F(DependencyTest, NestedSliceTest) -{ - // Test a slice that references another slice, which contains a reference to an asset. - // Should return only a dependency on the asset, and not the inner slice - - auto* outerSliceEntity = aznew AZ::Entity; - auto* assetComponent = aznew MockAssetRefComponent; - - AZ::Data::AssetId mockAssetId(m_catalog->GenerateMockAssetId()); - assetComponent->m_asset = Data::AssetManager::Instance().CreateAsset(mockAssetId, AZ::Data::AssetLoadBehavior::Default); - - auto innerSliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, m_catalog->GenerateMockAssetId()); - - AZ::Data::AssetId outerSliceAssetId(m_catalog->GenerateMockAssetId()); - auto outerSliceAsset = Data::AssetManager::Instance().CreateAsset(outerSliceAssetId, AZ::Data::AssetLoadBehavior::Default); - - AZ::SliceComponent* outerSlice = outerSliceEntity->CreateComponent(); - outerSlice->SetIsDynamic(true); - outerSliceAsset.Get()->SetData(outerSliceEntity, outerSlice); - outerSlice->AddSlice(innerSliceAsset); - - VerifyDependency(outerSliceAsset, mockAssetId); -} - -TEST_F(DependencyTest, DataPatchTest) -{ - // Test a slice that references another slice, with the outer slice being data-patched to have a reference to an asset - // Should return a dependency on the asset, but not the inner slice - - auto* outerSliceEntity = aznew AZ::Entity; - auto* assetComponent = aznew MockAssetRefComponent; - - AZ::Data::AssetId outerSliceAssetId(m_catalog->GenerateMockAssetId()); - auto outerSliceAsset = Data::AssetManager::Instance().CreateAsset(outerSliceAssetId, AZ::Data::AssetLoadBehavior::Default); - - auto innerSliceAsset = AZ::Test::CreateSliceFromComponent(nullptr, m_catalog->GenerateMockAssetId()); - - AZ::SliceComponent* outerSlice = outerSliceEntity->CreateComponent(); - outerSlice->SetIsDynamic(true); - outerSliceAsset.Get()->SetData(outerSliceEntity, outerSlice); - outerSlice->AddSlice(innerSliceAsset); - - outerSlice->Instantiate(); - - auto* sliceRef = outerSlice->GetSlice(innerSliceAsset); - auto& instances = sliceRef->GetInstances(); - - AZ::Data::AssetId mockAssetId(m_catalog->GenerateMockAssetId()); - assetComponent->m_asset = Data::AssetManager::Instance().CreateAsset(mockAssetId, AZ::Data::AssetLoadBehavior::Default); - - for (const AZ::SliceComponent::SliceInstance& i : instances) + TEST_F(DependencyTest, DynamicAssetReferenceTest) { - const AZ::SliceComponent::InstantiatedContainer* container = i.GetInstantiated(); - container->m_entities[0]->AddComponent(assetComponent); + // Test a slice that has a component which synthesizes an asset reference at runtime + // Should return a dependency on the asset - sliceRef->ComputeDataPatch(); + auto* assetComponent = aznew MockEditorComponent; + + AZ::Data::AssetId mockAssetId(AZ::Uuid::CreateRandom(), 0); + assetComponent->m_uuid = mockAssetId.m_guid; + + auto sliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, m_catalog->GenerateMockAssetId()); + + VerifyDependency(sliceAsset, mockAssetId); } - VerifyDependency(outerSliceAsset, mockAssetId); - - delete assetComponent; -} - -TEST_F(DependencyTest, DynamicAssetReferenceTest) -{ - // Test a slice that has a component which synthesizes an asset reference at runtime - // Should return a dependency on the asset - - auto* assetComponent = aznew MockEditorComponent; - - AZ::Data::AssetId mockAssetId(AZ::Uuid::CreateRandom(), 0); - assetComponent->m_uuid = mockAssetId.m_guid; - - auto sliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, m_catalog->GenerateMockAssetId()); - - VerifyDependency(sliceAsset, mockAssetId); -} - -TEST_F(DependencyTest, Slice_HasPopulatedSimpleAssetReference_HasCorrectProductDependency) -{ - // Test a slice containing a component with a simple asset reference - // Should return a path dependency - AZStd::vector productDependencies; - AssetBuilderSDK::ProductPathDependencySet productPathDependencySet; - constexpr char testPath[] = "some/test/path.txt"; - BuildSliceWithSimpleAssetReference(testPath, productDependencies, productPathDependencySet); - - ASSERT_EQ(productDependencies.size(), 0); - ASSERT_EQ(productPathDependencySet.size(), 1); - - auto& dependency = *productPathDependencySet.begin(); - ASSERT_STREQ(dependency.m_dependencyPath.c_str(), testPath); -} - -TEST_F(DependencyTest, Slice_HasEmptySimpleAssetReference_HasNoProductDependency) -{ - // Test a slice containing a component with an empty simple asset reference - // Should not return a path dependency - AZStd::vector productDependencies; - AssetBuilderSDK::ProductPathDependencySet productPathDependencySet; - BuildSliceWithSimpleAssetReference("", productDependencies, productPathDependencySet); - - ASSERT_EQ(productDependencies.size(), 0); - ASSERT_EQ(productPathDependencySet.size(), 0); -} - -struct ServiceTestComponent - : public AZ::Component -{ - AZ_COMPONENT(ServiceTestComponent, "{CBC4FCB6-FFD2-4097-844D-A01B09042DF4}"); - - static void Reflect(ReflectContext* reflection) + TEST_F(DependencyTest, Slice_HasPopulatedSimpleAssetReference_HasCorrectProductDependency) { - SerializeContext* serializeContext = azrtti_cast(reflection); + // Test a slice containing a component with a simple asset reference + // Should return a path dependency + AZStd::vector productDependencies; + AssetBuilderSDK::ProductPathDependencySet productPathDependencySet; + constexpr char testPath[] = "some/test/path.txt"; + BuildSliceWithSimpleAssetReference(testPath, productDependencies, productPathDependencySet); - if (serializeContext) + ASSERT_EQ(productDependencies.size(), 0); + ASSERT_EQ(productPathDependencySet.size(), 1); + + auto& dependency = *productPathDependencySet.begin(); + ASSERT_STREQ(dependency.m_dependencyPath.c_str(), testPath); + } + + TEST_F(DependencyTest, Slice_HasEmptySimpleAssetReference_HasNoProductDependency) + { + // Test a slice containing a component with an empty simple asset reference + // Should not return a path dependency + AZStd::vector productDependencies; + AssetBuilderSDK::ProductPathDependencySet productPathDependencySet; + BuildSliceWithSimpleAssetReference("", productDependencies, productPathDependencySet); + + ASSERT_EQ(productDependencies.size(), 0); + ASSERT_EQ(productPathDependencySet.size(), 0); + } + + struct ServiceTestComponent + : public AZ::Component + { + AZ_COMPONENT(ServiceTestComponent, "{CBC4FCB6-FFD2-4097-844D-A01B09042DF4}"); + + static void Reflect(ReflectContext* reflection) { - serializeContext->Class() - ->Field("field", &ServiceTestComponent::m_field); + SerializeContext* serializeContext = azrtti_cast(reflection); + + if (serializeContext) + { + serializeContext->Class() + ->Field("field", &ServiceTestComponent::m_field); + } + } + + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + if (m_enableServiceDependency) + { + required.push_back(AZ_CRC("SomeService", 0x657d5763)); + } + } + + void Activate() override {} + void Deactivate() override {} + + int m_field{}; + + static bool m_enableServiceDependency; + }; + + bool ServiceTestComponent::m_enableServiceDependency = false; + + TEST_F(DependencyTest, SliceFingerprint_ChangesWhenComponentServicesChange) + { + using namespace AzToolsFramework::Fingerprinting; + + AZStd::unique_ptr descriptor(ServiceTestComponent::CreateDescriptor()); + descriptor->Reflect(m_serializeContext); + + auto* assetComponent = aznew ServiceTestComponent; + auto sliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, m_catalog->GenerateMockAssetId()); + SliceComponent* sourcePrefab = sliceAsset.Get() ? sliceAsset.Get()->GetComponent() : nullptr; + + TypeFingerprint fingerprintNoService, fingerprintWithService; + + { + TypeFingerprinter fingerprinter(*m_serializeContext); + fingerprintNoService = fingerprinter.GenerateFingerprintForAllTypesInObject(sourcePrefab); + } + + ServiceTestComponent::m_enableServiceDependency = true; + + { + TypeFingerprinter fingerprinter(*m_serializeContext); + fingerprintWithService = fingerprinter.GenerateFingerprintForAllTypesInObject(sourcePrefab); + } + + ASSERT_NE(fingerprintNoService, fingerprintWithService); + + ServiceTestComponent::m_enableServiceDependency = false; + + { + // Check again to make sure the fingerprint is stable + TypeFingerprinter fingerprinter(*m_serializeContext); + TypeFingerprint fingerprintNoServiceDoubleCheck = fingerprinter.GenerateFingerprintForAllTypesInObject(sourcePrefab); + + ASSERT_EQ(fingerprintNoService, fingerprintNoServiceDoubleCheck); } } - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + struct BuilderRegisterListener : AssetBuilderSDK::AssetBuilderBus::Handler { - if (m_enableServiceDependency) + BuilderRegisterListener() { - required.push_back(AZ_CRC("SomeService", 0x657d5763)); + BusConnect(); } - } - void Activate() override {} - void Deactivate() override {} + ~BuilderRegisterListener() + { + BusDisconnect(); + } - int m_field{}; - static bool m_enableServiceDependency; -}; + void RegisterBuilderInformation(const AssetBuilderSDK::AssetBuilderDesc& desc) override + { + m_desc = desc; + } -bool ServiceTestComponent::m_enableServiceDependency = false; - -TEST_F(DependencyTest, SliceFingerprint_ChangesWhenComponentServicesChange) -{ - using namespace AzToolsFramework::Fingerprinting; - - AZStd::unique_ptr descriptor(ServiceTestComponent::CreateDescriptor()); - descriptor->Reflect(m_serializeContext); - - auto* assetComponent = aznew ServiceTestComponent; - auto sliceAsset = AZ::Test::CreateSliceFromComponent(assetComponent, m_catalog->GenerateMockAssetId()); - SliceComponent* sourcePrefab = sliceAsset.Get() ? sliceAsset.Get()->GetComponent() : nullptr; - - TypeFingerprint fingerprintNoService, fingerprintWithService; + AssetBuilderSDK::AssetBuilderDesc m_desc; + }; + TEST_F(DependencyTest, SliceBuilderFingerprint_ChangesWhenNestedTypeChanges) { - TypeFingerprinter fingerprinter(*m_serializeContext); - fingerprintNoService = fingerprinter.GenerateFingerprintForAllTypesInObject(sourcePrefab); - } + BuilderRegisterListener listener; + AZStd::string fingerprintA, fingerprintB; - ServiceTestComponent::m_enableServiceDependency = true; + auto* descriptor = MockComponent::CreateDescriptor(); - { - TypeFingerprinter fingerprinter(*m_serializeContext); - fingerprintWithService = fingerprinter.GenerateFingerprintForAllTypesInObject(sourcePrefab); - } + descriptor->Reflect(m_serializeContext); + MockSubType::Reflect(m_serializeContext); - ASSERT_NE(fingerprintNoService, fingerprintWithService); + { + BuilderPluginComponent builder; + builder.Activate(); + fingerprintA = listener.m_desc.m_analysisFingerprint; + } - ServiceTestComponent::m_enableServiceDependency = false; + // Unreflect the sub type, change the version, and reflect again + m_serializeContext->EnableRemoveReflection(); + MockSubType::Reflect(m_serializeContext); + m_serializeContext->DisableRemoveReflection(); - { - // Check again to make sure the fingerprint is stable - TypeFingerprinter fingerprinter(*m_serializeContext); - TypeFingerprint fingerprintNoServiceDoubleCheck = fingerprinter.GenerateFingerprintForAllTypesInObject(sourcePrefab); + MockSubType::m_version = 2; + MockSubType::Reflect(m_serializeContext); - ASSERT_EQ(fingerprintNoService, fingerprintNoServiceDoubleCheck); + { + BuilderPluginComponent builder; + builder.Activate(); + fingerprintB = listener.m_desc.m_analysisFingerprint; + } + + delete descriptor; + + EXPECT_STRNE(fingerprintA.c_str(), fingerprintB.c_str()); } } - -struct BuilderRegisterListener : AssetBuilderSDK::AssetBuilderBus::Handler -{ - BuilderRegisterListener() - { - BusConnect(); - } - - ~BuilderRegisterListener() - { - BusDisconnect(); - } - - - void RegisterBuilderInformation(const AssetBuilderSDK::AssetBuilderDesc& desc) override - { - m_desc = desc; - } - - AssetBuilderSDK::AssetBuilderDesc m_desc; -}; - -TEST_F(DependencyTest, SliceBuilderFingerprint_ChangesWhenNestedTypeChanges) -{ - BuilderRegisterListener listener; - AZStd::string fingerprintA, fingerprintB; - - auto* descriptor = MockComponent::CreateDescriptor(); - - descriptor->Reflect(m_serializeContext); - MockSubType::Reflect(m_serializeContext); - - { - BuilderPluginComponent builder; - builder.Activate(); - fingerprintA = listener.m_desc.m_analysisFingerprint; - } - - // Unreflect the sub type, change the version, and reflect again - m_serializeContext->EnableRemoveReflection(); - MockSubType::Reflect(m_serializeContext); - m_serializeContext->DisableRemoveReflection(); - - MockSubType::m_version = 2; - MockSubType::Reflect(m_serializeContext); - - { - BuilderPluginComponent builder; - builder.Activate(); - fingerprintB = listener.m_desc.m_analysisFingerprint; - } - - delete descriptor; - - EXPECT_STRNE(fingerprintA.c_str(), fingerprintB.c_str()); -}