fix: make sure kvps are in a deterministic order

This commit is contained in:
Jan 2025-01-05 10:08:21 +00:00
parent 67fb11506c
commit cacccf64e1
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
3 changed files with 121 additions and 1 deletions

View File

@ -1,7 +1,9 @@
#include "KeyValuePairsCreator.h"
#include <algorithm>
#include <format>
#include <iostream>
#include <ranges>
CommonKeyValuePair::CommonKeyValuePair(std::string keyStr, std::string value)
: m_key_str(std::move(keyStr)),
@ -49,6 +51,23 @@ void KeyValuePairsCreator::Finalize(const ZoneDefinition& zoneDefinition)
}
}
}
std::ranges::sort(m_key_value_pairs,
[](const CommonKeyValuePair& v0, const CommonKeyValuePair& v1)
{
if (v0.m_key_str.has_value())
{
if (!v1.m_key_str.has_value())
return true;
return *v0.m_key_str < *v1.m_key_str;
}
if (!v1.m_key_hash.has_value())
return false;
return *v0.m_key_hash < *v1.m_key_hash;
});
}
std::vector<CommonKeyValuePair> KeyValuePairsCreator::GetFinalKeyValuePairs()

View File

@ -18,7 +18,7 @@ public:
std::string m_value;
};
class KeyValuePairsCreator : public IZoneAssetCreationState
class KeyValuePairsCreator final : public IZoneAssetCreationState
{
public:
void AddKeyValuePair(CommonKeyValuePair keyValuePair);

View File

@ -0,0 +1,101 @@
#include "KeyValuePairs/KeyValuePairsCreator.h"
#include "Utils/TestMemoryManager.h"
#include <catch2/catch_test_macros.hpp>
#include <catch2/generators/catch_generators.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>
#include <memory>
using namespace std::string_literals;
namespace test::keyvaluepairs
{
TEST_CASE("KeyValuePairsCreator: ZoneDefinition with no properties produces no KeyValuePairs", "[keyvaluepairs]")
{
KeyValuePairsCreator sut;
ZoneDefinition zoneDefinition;
sut.Finalize(zoneDefinition);
const auto kvps = sut.GetFinalKeyValuePairs();
REQUIRE(kvps.empty());
}
TEST_CASE("KeyValuePairsCreator: ZoneDefinition with unrelated properties produce no KeyValuePairs", "[keyvaluepairs]")
{
KeyValuePairsCreator sut;
ZoneDefinition zoneDefinition;
zoneDefinition.m_properties.AddProperty("linker.test", "yes");
sut.Finalize(zoneDefinition);
const auto kvps = sut.GetFinalKeyValuePairs();
REQUIRE(kvps.empty());
}
TEST_CASE("KeyValuePairsCreator: ZoneDefinition with level properties produce KeyValuePairs", "[keyvaluepairs]")
{
KeyValuePairsCreator sut;
ZoneDefinition zoneDefinition;
zoneDefinition.m_properties.AddProperty("linker.test", "yes");
zoneDefinition.m_properties.AddProperty("level.random", "lemao");
sut.Finalize(zoneDefinition);
const auto kvps = sut.GetFinalKeyValuePairs();
REQUIRE(kvps.size() == 1);
REQUIRE(kvps[0].m_key_str);
REQUIRE(!kvps[0].m_key_hash);
REQUIRE(*kvps[0].m_key_str == "random");
REQUIRE(kvps[0].m_value == "lemao");
}
TEST_CASE("KeyValuePairsCreator: ZoneDefinition can have level properties with hash", "[keyvaluepairs]")
{
KeyValuePairsCreator sut;
ZoneDefinition zoneDefinition;
zoneDefinition.m_properties.AddProperty("level.@D34DB33F", "yes");
zoneDefinition.m_properties.AddProperty("level.@112233", "no");
zoneDefinition.m_properties.AddProperty("level.@0", "maybe");
sut.Finalize(zoneDefinition);
const auto kvps = sut.GetFinalKeyValuePairs();
REQUIRE(kvps.size() == 3);
REQUIRE(*kvps[0].m_key_hash == 0);
REQUIRE(kvps[0].m_value == "maybe");
REQUIRE(*kvps[1].m_key_hash == 0x112233);
REQUIRE(kvps[1].m_value == "no");
REQUIRE(*kvps[2].m_key_hash == 0xD34DB33F);
REQUIRE(kvps[2].m_value == "yes");
}
TEST_CASE("KeyValuePairsCreator: ZoneDefinition can have level properties with name and/or hash", "[keyvaluepairs]")
{
KeyValuePairsCreator sut;
ZoneDefinition zoneDefinition;
zoneDefinition.m_properties.AddProperty("level.ipak_read", "asdf");
zoneDefinition.m_properties.AddProperty("level.hello_world", "foo");
zoneDefinition.m_properties.AddProperty("level.@D34DB33F", "yes");
zoneDefinition.m_properties.AddProperty("level.@112233", "no");
sut.Finalize(zoneDefinition);
const auto kvps = sut.GetFinalKeyValuePairs();
REQUIRE(kvps.size() == 4);
REQUIRE(*kvps[0].m_key_str == "hello_world");
REQUIRE(kvps[0].m_value == "foo");
REQUIRE(*kvps[1].m_key_str == "ipak_read");
REQUIRE(kvps[1].m_value == "asdf");
REQUIRE(*kvps[2].m_key_hash == 0x112233);
REQUIRE(kvps[2].m_value == "no");
REQUIRE(*kvps[3].m_key_hash == 0xD34DB33F);
REQUIRE(kvps[3].m_value == "yes");
}
} // namespace test::keyvaluepairs