feat(unlinker): support ?game? placeholder in output folder (#945)

* feat(unlinker): support ?game? placeholder in output folder

* chore: move unlinking tests to separate project

---------

Co-authored-by: Jan Laupetin <[email protected]>
This commit is contained in:
mo
2026-08-07 20:43:24 +02:00
committed by GitHub
co-authored by Jan Laupetin
parent b2036716dd
commit 6da0f2207e
6 changed files with 122 additions and 5 deletions
+6 -3
View File
@@ -17,8 +17,8 @@ jobs:
build-test-linux:
strategy:
matrix:
build_arch: [x86, x64]
toolset: [gcc, clang]
build_arch: [ x86, x64 ]
toolset: [ gcc, clang ]
include:
- build_arch: x86
gtk_packages: libgtk-4-dev:i386 libwebkitgtk-6.0-dev:i386
@@ -105,13 +105,14 @@ jobs:
./ObjWritingTests
./ParserTests
./SystemTests
./UnlinkingTests
./ZoneCodeGeneratorLibTests
./ZoneCommonTests
build-test-windows:
strategy:
matrix:
build_arch: [x86, x64]
build_arch: [ x86, x64 ]
include:
- build_arch: x86
msbuild_config: Win32
@@ -200,6 +201,8 @@ jobs:
$combinedExitCode = [System.Math]::max($combinedExitCode, $LASTEXITCODE)
./SystemTests
$combinedExitCode = [System.Math]::max($combinedExitCode, $LASTEXITCODE)
./UnlinkingTests
$combinedExitCode = [System.Math]::max($combinedExitCode, $LASTEXITCODE)
./ZoneCodeGeneratorLibTests
$combinedExitCode = [System.Math]::max($combinedExitCode, $LASTEXITCODE)
./ZoneCommonTests
+2
View File
@@ -208,6 +208,7 @@ include "test/ObjWritingTests.lua"
include "test/ParserTestUtils.lua"
include "test/ParserTests.lua"
include "test/SystemTests.lua"
include "test/UnlinkingTests.lua"
include "test/ZoneCodeGeneratorLibTests.lua"
include "test/ZoneCommonTests.lua"
@@ -223,6 +224,7 @@ group "Tests"
ParserTestUtils:project()
ParserTests:project()
SystemTests:project()
UnlinkingTests:project()
ZoneCodeGeneratorLibTests:project()
ZoneCommonTests:project()
group ""
+10 -2
View File
@@ -66,7 +66,9 @@ const CommandLineOption* const OPTION_OUTPUT_FOLDER =
CommandLineOption::Builder::Create()
.WithShortName("o")
.WithLongName("output-folder")
.WithDescription(std::format("Specifies the output folder containing the contents of the unlinked zones. Defaults to \"{}\"", UnlinkerArgs::DEFAULT_OUTPUT_FOLDER))
.WithDescription(std::format("Specifies the output folder containing the contents of the unlinked zones. Supports ?game? and ?zone? placeholders. "
"Defaults to \"{}\"",
UnlinkerArgs::DEFAULT_OUTPUT_FOLDER))
.WithParameter("outputFolderPath")
.Build();
@@ -148,6 +150,7 @@ const CommandLineOption* const COMMAND_LINE_OPTIONS[]{
UnlinkerArgs::UnlinkerArgs()
: m_argument_parser(COMMAND_LINE_OPTIONS, std::extent_v<decltype(COMMAND_LINE_OPTIONS)>),
m_game_pattern(R"(\?game\?)"),
m_zone_pattern(R"(\?zone\?)"),
m_task(ProcessingTask::DUMP),
m_minimal_zone_def(false),
@@ -390,5 +393,10 @@ bool UnlinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldCont
std::string UnlinkerArgs::GetOutputFolderPathForZone(const Zone& zone) const
{
return std::regex_replace(m_output_folder, m_zone_pattern, zone.m_name);
auto outputPath = std::regex_replace(m_output_folder, m_zone_pattern, zone.m_name);
auto gameName = IGame::GetGameById(zone.m_game_id)->GetShortName();
utils::MakeStringLowerCase(gameName);
return std::regex_replace(outputPath, m_game_pattern, gameName);
}
+1
View File
@@ -17,6 +17,7 @@ public:
private:
ArgumentParser m_argument_parser;
std::regex m_game_pattern;
std::regex m_zone_pattern;
/**
+58
View File
@@ -0,0 +1,58 @@
UnlinkingTests = {}
function UnlinkingTests:include(includes)
if includes:handle(self:name()) then
includedirs {
"%{wks.location}/src/Unlinking",
path.join(TestFolder(), "UnlinkingTests")
}
end
end
function UnlinkingTests:link(links)
end
function UnlinkingTests:use()
end
function UnlinkingTests:name()
return "UnlinkingTests"
end
function UnlinkingTests:project()
local folder = TestFolder()
local includes = Includes:create()
local links = Links:create()
project(self:name())
targetdir(TargetDirectoryTest)
location "%{wks.location}/test/%{prj.name}"
kind "ConsoleApp"
language "C++"
files {
path.join(folder, "UnlinkingTests/**.h"),
path.join(folder, "UnlinkingTests/**.cpp")
}
vpaths {
["*"] = {
path.join(folder, "UnlinkingTests")
}
}
self:include(includes)
Catch2Common:include(includes)
ObjCommonTestUtils:include(includes)
Unlinking:include(includes)
catch2:include(includes)
links:linkto(ObjCommonTestUtils)
links:linkto(ParserTestUtils)
links:linkto(Unlinking)
links:linkto(catch2)
links:linkto(Catch2Common)
links:linkall()
end
+45
View File
@@ -0,0 +1,45 @@
#include "UnlinkerArgs.h"
#include <catch2/catch_test_macros.hpp>
#include <type_traits>
namespace
{
TEST_CASE("Unlinker uses the default output folder when none is specified", "[unlinker][arguments]")
{
const char* argStrings[]{
"Unlinker",
"test.ff",
};
UnlinkerArgs args;
bool shouldContinue = true;
REQUIRE(args.ParseArgs(std::extent_v<decltype(argStrings)>, argStrings, shouldContinue));
REQUIRE(shouldContinue);
REQUIRE(args.m_output_folder == UnlinkerArgs::DEFAULT_OUTPUT_FOLDER);
const Zone zone("test_zone", 0, GameId::IW4, GamePlatform::PC);
REQUIRE(args.GetOutputFolderPathForZone(zone) == "zone_dump/zone_raw/test_zone");
}
TEST_CASE("Unlinker output folder remains unchanged without placeholders", "[unlinker][arguments]")
{
UnlinkerArgs args;
args.m_output_folder = "zone_dump/custom";
const Zone zone("test_zone", 0, GameId::IW4, GamePlatform::PC);
REQUIRE(args.GetOutputFolderPathForZone(zone) == "zone_dump/custom");
}
TEST_CASE("Unlinker output folder replaces game and zone placeholders", "[unlinker][arguments]")
{
UnlinkerArgs args;
args.m_output_folder = "zone_dump/?game?/?zone?";
const Zone zone("test_zone", 0, GameId::IW4, GamePlatform::PC);
REQUIRE(args.GetOutputFolderPathForZone(zone) == "zone_dump/iw4/test_zone");
}
} // namespace