From e0f8b3d3ca774ff9448b83c72ec00487beb864a6 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 7 Jan 2025 00:02:38 +0100 Subject: [PATCH] chore: add abstraction for opening output files to be able to mock it --- src/Linker/ZoneCreation/ZoneCreator.cpp | 5 +- src/ObjCommon/SearchPath/IOutputPath.h | 18 +++++++ .../SearchPath/OutputPathFilesystem.cpp | 27 ++++++++++ .../SearchPath/OutputPathFilesystem.h | 16 ++++++ src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp | 6 +-- src/ObjCompiling/Game/IW3/ObjCompilerIW3.h | 4 +- src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp | 6 +-- src/ObjCompiling/Game/IW4/ObjCompilerIW4.h | 4 +- src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp | 6 +-- src/ObjCompiling/Game/IW5/ObjCompilerIW5.h | 4 +- src/ObjCompiling/Game/T5/ObjCompilerT5.cpp | 6 +-- src/ObjCompiling/Game/T5/ObjCompilerT5.h | 4 +- src/ObjCompiling/Game/T6/ObjCompilerT6.cpp | 6 +-- src/ObjCompiling/Game/T6/ObjCompilerT6.h | 4 +- src/ObjCompiling/IObjCompiler.h | 10 ++-- src/ObjCompiling/Image/IPak/IPakCreator.cpp | 11 ++--- src/ObjCompiling/Image/IPak/IPakCreator.h | 8 +-- .../Image/ImageIPakPostProcessor.cpp | 2 +- .../Image/ImageIPakPostProcessor.h | 11 ++--- .../Image/ImageIwdPostProcessor.cpp | 2 +- .../Image/ImageIwdPostProcessor.h | 11 ++--- src/ObjCompiling/Iwd/IwdCreator.cpp | 14 +++--- src/ObjCompiling/Iwd/IwdCreator.h | 8 +-- .../SearchPath/MockOutputPath.cpp | 49 +++++++++++++++++++ .../SearchPath/MockOutputPath.h | 28 +++++++++++ 25 files changed, 202 insertions(+), 68 deletions(-) create mode 100644 src/ObjCommon/SearchPath/IOutputPath.h create mode 100644 src/ObjCommon/SearchPath/OutputPathFilesystem.cpp create mode 100644 src/ObjCommon/SearchPath/OutputPathFilesystem.h create mode 100644 test/ObjCommonTestUtils/SearchPath/MockOutputPath.cpp create mode 100644 test/ObjCommonTestUtils/SearchPath/MockOutputPath.h diff --git a/src/Linker/ZoneCreation/ZoneCreator.cpp b/src/Linker/ZoneCreation/ZoneCreator.cpp index 21bc80f0..29f35ed1 100644 --- a/src/Linker/ZoneCreation/ZoneCreator.cpp +++ b/src/Linker/ZoneCreation/ZoneCreator.cpp @@ -3,6 +3,7 @@ #include "Gdt/GdtLookup.h" #include "IObjCompiler.h" #include "IObjLoader.h" +#include "SearchPath/OutputPathFilesystem.h" #include @@ -67,8 +68,10 @@ namespace zone_creator ZoneDefinitionContext zoneDefinitionContext(*context.m_definition); AssetCreationContext creationContext(*zone, &creatorCollection, &ignoredAssetLookup); + OutputPathFilesystem outDir(context.m_out_dir); + OutputPathFilesystem cacheDir(context.m_cache_dir); objCompiler->ConfigureCreatorCollection( - creatorCollection, *zone, zoneDefinitionContext, *context.m_asset_search_path, lookup, creationContext, context.m_out_dir, context.m_cache_dir); + creatorCollection, *zone, zoneDefinitionContext, *context.m_asset_search_path, lookup, creationContext, outDir, cacheDir); objLoader->ConfigureCreatorCollection(creatorCollection, *zone, *context.m_asset_search_path, lookup); for (const auto& assetEntry : context.m_definition->m_assets) diff --git a/src/ObjCommon/SearchPath/IOutputPath.h b/src/ObjCommon/SearchPath/IOutputPath.h new file mode 100644 index 00000000..4073a12c --- /dev/null +++ b/src/ObjCommon/SearchPath/IOutputPath.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include + +class IOutputPath +{ +public: + IOutputPath() = default; + virtual ~IOutputPath() = default; + IOutputPath(const IOutputPath& other) = default; + IOutputPath(IOutputPath&& other) noexcept = default; + IOutputPath& operator=(const IOutputPath& other) = default; + IOutputPath& operator=(IOutputPath&& other) noexcept = default; + + virtual std::unique_ptr Open(const std::string& fileName) = 0; +}; diff --git a/src/ObjCommon/SearchPath/OutputPathFilesystem.cpp b/src/ObjCommon/SearchPath/OutputPathFilesystem.cpp new file mode 100644 index 00000000..c0954f94 --- /dev/null +++ b/src/ObjCommon/SearchPath/OutputPathFilesystem.cpp @@ -0,0 +1,27 @@ +#include "OutputPathFilesystem.h" + +#include + +namespace fs = std::filesystem; + +OutputPathFilesystem::OutputPathFilesystem(const fs::path& path) + : m_path(fs::canonical(path)) +{ +} + +std::unique_ptr OutputPathFilesystem::Open(const std::string& fileName) +{ + const auto fullNewPath = fs::canonical(m_path / fileName); + + if (!fullNewPath.string().starts_with(m_path.string())) + return nullptr; + + const auto containingDirectory = fullNewPath.parent_path(); + fs::create_directories(containingDirectory); + + std::ofstream stream(fullNewPath, std::ios::binary | std::ios::out); + if (!stream.is_open()) + return nullptr; + + return std::make_unique(std::move(stream)); +} diff --git a/src/ObjCommon/SearchPath/OutputPathFilesystem.h b/src/ObjCommon/SearchPath/OutputPathFilesystem.h new file mode 100644 index 00000000..827783f5 --- /dev/null +++ b/src/ObjCommon/SearchPath/OutputPathFilesystem.h @@ -0,0 +1,16 @@ +#pragma once + +#include "IOutputPath.h" + +#include + +class OutputPathFilesystem final : public IOutputPath +{ +public: + explicit OutputPathFilesystem(const std::filesystem::path& path); + + std::unique_ptr Open(const std::string& fileName) override; + +private: + std::filesystem::path m_path; +}; diff --git a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp index b3914ae8..d1be036d 100644 --- a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp +++ b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp @@ -22,7 +22,7 @@ namespace const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const fs::path& outDir) + IOutputPath& outDir) { auto& memory = *zone.GetMemory(); @@ -37,8 +37,8 @@ void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const fs::path& outDir, - const fs::path& cacheDir) const + IOutputPath& outDir, + IOutputPath& cacheDir) const { ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); } diff --git a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h index 771821a7..677d3256 100644 --- a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h +++ b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h @@ -13,7 +13,7 @@ namespace IW3 ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir, - const std::filesystem::path& cacheDir) const override; + IOutputPath& outDir, + IOutputPath& cacheDir) const override; }; } // namespace IW3 diff --git a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp index 12f8e839..d1b3e766 100644 --- a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp +++ b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp @@ -22,7 +22,7 @@ namespace const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const fs::path& outDir) + IOutputPath& outDir) { auto& memory = *zone.GetMemory(); @@ -37,8 +37,8 @@ void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const fs::path& outDir, - const fs::path& cacheDir) const + IOutputPath& outDir, + IOutputPath& cacheDir) const { ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); } diff --git a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h index 522b3c51..ce83806e 100644 --- a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h +++ b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h @@ -13,7 +13,7 @@ namespace IW4 ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir, - const std::filesystem::path& cacheDir) const override; + IOutputPath& outDir, + IOutputPath& cacheDir) const override; }; } // namespace IW4 diff --git a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp index dbfc20d0..b04f4aeb 100644 --- a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp +++ b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp @@ -22,7 +22,7 @@ namespace const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const fs::path& outDir) + IOutputPath& outDir) { auto& memory = *zone.GetMemory(); @@ -37,8 +37,8 @@ void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const fs::path& outDir, - const fs::path& cacheDir) const + IOutputPath& outDir, + IOutputPath& cacheDir) const { ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); } diff --git a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h index 80805f77..8fc6a101 100644 --- a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h +++ b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h @@ -13,7 +13,7 @@ namespace IW5 ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir, - const std::filesystem::path& cacheDir) const override; + IOutputPath& outDir, + IOutputPath& cacheDir) const override; }; } // namespace IW5 diff --git a/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp index 5fb02146..da94980a 100644 --- a/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp +++ b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp @@ -22,7 +22,7 @@ namespace const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const fs::path& outDir) + IOutputPath& outDir) { auto& memory = *zone.GetMemory(); @@ -37,8 +37,8 @@ void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const fs::path& outDir, - const fs::path& cacheDir) const + IOutputPath& outDir, + IOutputPath& cacheDir) const { ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); } diff --git a/src/ObjCompiling/Game/T5/ObjCompilerT5.h b/src/ObjCompiling/Game/T5/ObjCompilerT5.h index bd216b7c..fd31c8c3 100644 --- a/src/ObjCompiling/Game/T5/ObjCompilerT5.h +++ b/src/ObjCompiling/Game/T5/ObjCompilerT5.h @@ -13,7 +13,7 @@ namespace T5 ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir, - const std::filesystem::path& cacheDir) const override; + IOutputPath& outDir, + IOutputPath& cacheDir) const override; }; } // namespace T5 diff --git a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp index 9be2a476..bc59cf06 100644 --- a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp +++ b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp @@ -28,7 +28,7 @@ namespace const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const fs::path& outDir) + IOutputPath& outDir) { auto& memory = *zone.GetMemory(); @@ -46,8 +46,8 @@ void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const fs::path& outDir, - const fs::path& cacheDir) const + IOutputPath& outDir, + IOutputPath& cacheDir) const { ConfigureCompilers(collection, zone, zoneDefinition, searchPath, zoneStates); ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); diff --git a/src/ObjCompiling/Game/T6/ObjCompilerT6.h b/src/ObjCompiling/Game/T6/ObjCompilerT6.h index 73d30655..5e935b02 100644 --- a/src/ObjCompiling/Game/T6/ObjCompilerT6.h +++ b/src/ObjCompiling/Game/T6/ObjCompilerT6.h @@ -13,7 +13,7 @@ namespace T6 ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir, - const std::filesystem::path& cacheDir) const override; + IOutputPath& outDir, + IOutputPath& cacheDir) const override; }; } // namespace T6 diff --git a/src/ObjCompiling/IObjCompiler.h b/src/ObjCompiling/IObjCompiler.h index 26bac9ba..8f7e32fd 100644 --- a/src/ObjCompiling/IObjCompiler.h +++ b/src/ObjCompiling/IObjCompiler.h @@ -4,14 +4,10 @@ #include "Asset/IZoneAssetCreationState.h" #include "Asset/ZoneDefinitionContext.h" #include "Gdt/IGdtQueryable.h" +#include "SearchPath/IOutputPath.h" #include "SearchPath/ISearchPath.h" -#include "Zone/Definition/ZoneDefinition.h" #include "Zone/Zone.h" -#include -#include -#include - class IObjCompiler { public: @@ -28,8 +24,8 @@ public: ISearchPath& searchPath, IGdtQueryable& gdt, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir, - const std::filesystem::path& cacheDir) const = 0; + IOutputPath& outDir, + IOutputPath& cacheDir) const = 0; static const IObjCompiler* GetObjCompilerForGame(GameId game); }; diff --git a/src/ObjCompiling/Image/IPak/IPakCreator.cpp b/src/ObjCompiling/Image/IPak/IPakCreator.cpp index d18c127c..9ad4435c 100644 --- a/src/ObjCompiling/Image/IPak/IPakCreator.cpp +++ b/src/ObjCompiling/Image/IPak/IPakCreator.cpp @@ -379,17 +379,16 @@ void IPakToCreate::AddImage(std::string imageName) m_image_names.emplace_back(std::move(imageName)); } -void IPakToCreate::Build(ISearchPath& searchPath, const std::filesystem::path& outPath) +void IPakToCreate::Build(ISearchPath& searchPath, IOutputPath& outPath) { - auto filePath = outPath / std::format("{}.ipak", m_name); - std::ofstream file(filePath, std::ios::out | std::ios::binary); - if (!file.is_open()) + const auto file = outPath.Open(std::format("{}.ipak", m_name)); + if (!file) { std::cerr << std::format("Failed to open file for ipak {}\n", m_name); return; } - IPakWriter writer(file, searchPath, m_image_names); + IPakWriter writer(*file, searchPath, m_image_names); writer.Write(); std::cout << std::format("Created ipak {} with {} entries\n", m_name, m_image_names.size()); @@ -421,7 +420,7 @@ IPakToCreate* IPakCreator::GetOrAddIPak(const std::string& ipakName) return result; } -void IPakCreator::Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath) +void IPakCreator::Finalize(ISearchPath& searchPath, IOutputPath& outPath) { for (const auto& ipakToCreate : m_ipaks) ipakToCreate->Build(searchPath, outPath); diff --git a/src/ObjCompiling/Image/IPak/IPakCreator.h b/src/ObjCompiling/Image/IPak/IPakCreator.h index 6b9a7565..1218d63c 100644 --- a/src/ObjCompiling/Image/IPak/IPakCreator.h +++ b/src/ObjCompiling/Image/IPak/IPakCreator.h @@ -2,9 +2,9 @@ #include "Asset/IZoneAssetCreationState.h" #include "KeyValuePairs/KeyValuePairsCreator.h" +#include "SearchPath/IOutputPath.h" #include "SearchPath/ISearchPath.h" -#include #include #include #include @@ -15,14 +15,14 @@ public: explicit IPakToCreate(std::string name); void AddImage(std::string imageName); - void Build(ISearchPath& searchPath, const std::filesystem::path& outPath); + void Build(ISearchPath& searchPath, IOutputPath& outPath); private: std::string m_name; std::vector m_image_names; }; -class IPakCreator : public IZoneAssetCreationState +class IPakCreator final : public IZoneAssetCreationState { public: IPakCreator(); @@ -30,7 +30,7 @@ public: void Inject(ZoneAssetCreationInjection& inject) override; IPakToCreate* GetOrAddIPak(const std::string& ipakName); - void Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath); + void Finalize(ISearchPath& searchPath, IOutputPath& outPath); private: KeyValuePairsCreator* m_kvp_creator; diff --git a/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp b/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp index 81932859..09a66139 100644 --- a/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp +++ b/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp @@ -8,7 +8,7 @@ AbstractImageIPakPostProcessor::AbstractImageIPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir) + IOutputPath& outDir) : m_zone_definition(zoneDefinition), m_search_path(searchPath), m_ipak_creator(zoneStates.GetZoneAssetCreationState()), diff --git a/src/ObjCompiling/Image/ImageIPakPostProcessor.h b/src/ObjCompiling/Image/ImageIPakPostProcessor.h index 2c99ee60..675b79cf 100644 --- a/src/ObjCompiling/Image/ImageIPakPostProcessor.h +++ b/src/ObjCompiling/Image/ImageIPakPostProcessor.h @@ -3,8 +3,7 @@ #include "Asset/IAssetPostProcessor.h" #include "Asset/ZoneDefinitionContext.h" #include "Image/IPak/IPakCreator.h" - -#include +#include "SearchPath/IOutputPath.h" class AbstractImageIPakPostProcessor : public IAssetPostProcessor { @@ -12,7 +11,7 @@ public: AbstractImageIPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir); + IOutputPath& outDir); static bool AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition); @@ -25,7 +24,7 @@ private: const ZoneDefinitionContext& m_zone_definition; ISearchPath& m_search_path; IPakCreator& m_ipak_creator; - const std::filesystem::path& m_out_dir; + IOutputPath& m_out_dir; unsigned m_obj_container_index; IPakToCreate* m_current_ipak; @@ -41,7 +40,7 @@ public: ImageIPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir) + IOutputPath& outDir) : AbstractImageIPakPostProcessor(zoneDefinition, searchPath, zoneStates, outDir) { } @@ -49,5 +48,5 @@ public: [[nodiscard]] asset_type_t GetHandlingAssetType() const override { return AssetType::EnumEntry; - }; + } }; diff --git a/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp b/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp index 47eed997..586fa9c0 100644 --- a/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp +++ b/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp @@ -9,7 +9,7 @@ AbstractImageIwdPostProcessor::AbstractImageIwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir) + IOutputPath& outDir) : m_zone_definition(zoneDefinition), m_search_path(searchPath), m_iwd_creator(zoneStates.GetZoneAssetCreationState()), diff --git a/src/ObjCompiling/Image/ImageIwdPostProcessor.h b/src/ObjCompiling/Image/ImageIwdPostProcessor.h index 12c53828..8225c29f 100644 --- a/src/ObjCompiling/Image/ImageIwdPostProcessor.h +++ b/src/ObjCompiling/Image/ImageIwdPostProcessor.h @@ -3,8 +3,7 @@ #include "Asset/IAssetPostProcessor.h" #include "Asset/ZoneDefinitionContext.h" #include "Iwd/IwdCreator.h" - -#include +#include "SearchPath/IOutputPath.h" class AbstractImageIwdPostProcessor : public IAssetPostProcessor { @@ -12,7 +11,7 @@ public: AbstractImageIwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir); + IOutputPath& outDir); static bool AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition); @@ -25,7 +24,7 @@ private: const ZoneDefinitionContext& m_zone_definition; ISearchPath& m_search_path; IwdCreator& m_iwd_creator; - const std::filesystem::path& m_out_dir; + IOutputPath& m_out_dir; unsigned m_obj_container_index; IwdToCreate* m_current_iwd; @@ -41,7 +40,7 @@ public: ImageIwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, - const std::filesystem::path& outDir) + IOutputPath& outDir) : AbstractImageIwdPostProcessor(zoneDefinition, searchPath, zoneStates, outDir) { } @@ -49,5 +48,5 @@ public: [[nodiscard]] asset_type_t GetHandlingAssetType() const override { return AssetType::EnumEntry; - }; + } }; diff --git a/src/ObjCompiling/Iwd/IwdCreator.cpp b/src/ObjCompiling/Iwd/IwdCreator.cpp index f995c32b..9d4932fe 100644 --- a/src/ObjCompiling/Iwd/IwdCreator.cpp +++ b/src/ObjCompiling/Iwd/IwdCreator.cpp @@ -18,19 +18,19 @@ void IwdToCreate::AddFile(std::string filePath) m_file_paths.emplace_back(std::move(filePath)); } -void IwdToCreate::Build(ISearchPath& searchPath, const std::filesystem::path& outPath) +void IwdToCreate::Build(ISearchPath& searchPath, IOutputPath& outPath) { - auto filePath = outPath / std::format("{}.iwd", m_name); - std::ofstream file(filePath, std::ios::out | std::ios::binary); - if (!file.is_open()) + const auto fileName = std::format("{}.iwd", m_name); + const auto file = outPath.Open(fileName); + if (!file) { std::cerr << std::format("Failed to open file for iwd {}\n", m_name); return; } - auto functions = FileToZlibWrapper::CreateFunctions32ForFile(&file); + auto functions = FileToZlibWrapper::CreateFunctions32ForFile(file.get()); - auto zipFile = zipOpen2(filePath.string().c_str(), APPEND_STATUS_CREATE, nullptr, &functions); + const auto zipFile = zipOpen2(fileName.c_str(), APPEND_STATUS_CREATE, nullptr, &functions); if (!zipFile) { std::cerr << std::format("Failed to open file as zip for iwd {}\n", m_name); @@ -92,7 +92,7 @@ IwdToCreate* IwdCreator::GetOrAddIwd(const std::string& iwdName) return result; } -void IwdCreator::Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath) +void IwdCreator::Finalize(ISearchPath& searchPath, IOutputPath& outPath) { std::cout << std::format("Writing {} iwd files to disk\n", m_iwds.size()); for (const auto& iwdToCreate : m_iwds) diff --git a/src/ObjCompiling/Iwd/IwdCreator.h b/src/ObjCompiling/Iwd/IwdCreator.h index 43b31fe0..2b73be50 100644 --- a/src/ObjCompiling/Iwd/IwdCreator.h +++ b/src/ObjCompiling/Iwd/IwdCreator.h @@ -1,9 +1,9 @@ #pragma once #include "Asset/IZoneAssetCreationState.h" +#include "SearchPath/IOutputPath.h" #include "SearchPath/ISearchPath.h" -#include #include #include #include @@ -14,18 +14,18 @@ public: explicit IwdToCreate(std::string name); void AddFile(std::string filePath); - void Build(ISearchPath& searchPath, const std::filesystem::path& outPath); + void Build(ISearchPath& searchPath, IOutputPath& outPath); private: std::string m_name; std::vector m_file_paths; }; -class IwdCreator : public IZoneAssetCreationState +class IwdCreator final : public IZoneAssetCreationState { public: IwdToCreate* GetOrAddIwd(const std::string& iwdName); - void Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath); + void Finalize(ISearchPath& searchPath, IOutputPath& outPath); private: std::unordered_map m_iwd_lookup; diff --git a/test/ObjCommonTestUtils/SearchPath/MockOutputPath.cpp b/test/ObjCommonTestUtils/SearchPath/MockOutputPath.cpp new file mode 100644 index 00000000..6f4c457a --- /dev/null +++ b/test/ObjCommonTestUtils/SearchPath/MockOutputPath.cpp @@ -0,0 +1,49 @@ +#include "MockOutputPath.h" + +#include + +namespace +{ + class MockFileWrapper final : public std::ostringstream + { + public: + MockFileWrapper(std::string name, std::vector& files) + : m_name(std::move(name)), + m_files(files) + { + } + + ~MockFileWrapper() override + { + m_files.emplace_back(std::move(m_name), str()); + } + + private: + std::string m_name; + std::vector& m_files; + }; +} // namespace + +MockOutputFile::MockOutputFile() = default; + +MockOutputFile::MockOutputFile(std::string name, std::string data) + : m_name(std::move(name)), + m_data(std::move(data)) +{ +} + +std::unique_ptr MockOutputPath::Open(const std::string& fileName) +{ + return std::make_unique(fileName, m_files); +} + +const MockOutputFile* MockOutputPath::GetMockedFile(const std::string& name) const +{ + for (const auto& file : m_files) + { + if (file.m_name == name) + return &file; + } + + return nullptr; +} diff --git a/test/ObjCommonTestUtils/SearchPath/MockOutputPath.h b/test/ObjCommonTestUtils/SearchPath/MockOutputPath.h new file mode 100644 index 00000000..092916b0 --- /dev/null +++ b/test/ObjCommonTestUtils/SearchPath/MockOutputPath.h @@ -0,0 +1,28 @@ +#pragma once + +#include "SearchPath/IOutputPath.h" + +#include +#include +#include + +class MockOutputFile +{ +public: + std::string m_name; + std::string m_data; + + MockOutputFile(); + MockOutputFile(std::string name, std::string data); +}; + +class MockOutputPath final : public IOutputPath +{ +public: + std::unique_ptr Open(const std::string& fileName) override; + + [[nodiscard]] const MockOutputFile* GetMockedFile(const std::string& name) const; + +private: + std::vector m_files; +};