fix: fix issue in config manager.

- fix fwrite fread issue in config manager.
- add testbench for config manager.
- change testbench order to get better experience.
This commit is contained in:
yyc12345 2024-07-03 10:14:17 +08:00
parent e2a582e7d2
commit e374575852
3 changed files with 116 additions and 16 deletions

View File

@ -35,7 +35,7 @@ namespace YYCC::ConfigManager {
// fetch version info
uint64_t version_info;
if (std::fread(&version_info, sizeof(version_info), 1u, fs.get()) != sizeof(version_info))
if (std::fread(&version_info, 1u, sizeof(version_info), fs.get()) != sizeof(version_info))
return false;
// check version
// if read version is greater than we expected,
@ -51,19 +51,19 @@ namespace YYCC::ConfigManager {
// try fetch setting name
// fetch name length
size_t name_length;
if (std::fread(&name_length, sizeof(name_length), 1u, fs.get()) != sizeof(name_length)) {
if (std::fread(&name_length, 1u, sizeof(name_length), fs.get()) != sizeof(name_length)) {
// we also check whether reach EOF at there.
if (std::feof(fs.get())) break;
else return false;
}
// fetch name body
name_cache.resize(name_length);
if (std::fread(name_cache.data(), name_length, 1u, fs.get()) != name_length)
if (std::fread(name_cache.data(), 1u, name_length, fs.get()) != name_length)
return false;
// get setting data length
size_t data_length;
if (std::fread(&data_length, sizeof(data_length), 1u, fs.get()) != sizeof(data_length))
if (std::fread(&data_length, 1u, sizeof(data_length), fs.get()) != sizeof(data_length))
return false;
// get matched setting first
@ -71,7 +71,7 @@ namespace YYCC::ConfigManager {
if (found != m_Settings.end()) {
// found. read data for it
found->second->ResizeData(data_length);
if (std::fread(found->second->GetDataPtr(), data_length, 1u, fs.get()) != data_length)
if (std::fread(found->second->GetDataPtr(), 1u, data_length, fs.get()) != data_length)
return false;
// call user defined load function
// if fail to parse, reset to default value
@ -95,7 +95,7 @@ namespace YYCC::ConfigManager {
// write config data
uint64_t version_info = m_VersionIdentifier;
if (std::fwrite(&version_info, sizeof(version_info), 1u, fs.get()) != sizeof(version_info))
if (std::fwrite(&version_info, 1u, sizeof(version_info), fs.get()) != sizeof(version_info))
return false;
// iterate all data for writing
@ -108,19 +108,19 @@ namespace YYCC::ConfigManager {
// write setting name
// write name length
size_t name_length = pair.first.size();
if (std::fwrite(&name_length, sizeof(name_length), 1u, fs.get()) != sizeof(name_length))
if (std::fwrite(&name_length, 1u, sizeof(name_length), fs.get()) != sizeof(name_length))
return false;
// write name body
if (std::fwrite(pair.first.c_str(), name_length, 1u, fs.get()) != name_length)
if (std::fwrite(pair.first.c_str(), 1u, name_length, fs.get()) != name_length)
return false;
// write setting daat
// write data length
size_t data_length = pair.second->GetDataSize();
if (std::fwrite(&data_length, sizeof(data_length), 1u, fs.get()) != sizeof(data_length))
if (std::fwrite(&data_length, 1u, sizeof(data_length), fs.get()) != sizeof(data_length))
return false;
// write data body
if (std::fwrite(pair.second->GetDataPtr(), data_length, 1u, fs.get()) != data_length)
if (std::fwrite(pair.second->GetDataPtr(), 1u, data_length, fs.get()) != data_length)
return false;
}

View File

@ -26,7 +26,7 @@ namespace YYCC::ConfigManager {
namespace ConstrainPresets {
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty>, int> = 0>
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty> && !std::is_enum_v<_Ty> && !std::is_same_v<_Ty, bool>, int> = 0>
Constrain<_Ty> GetNumberRangeConstrain(_Ty min_value, _Ty max_value) {
if (min_value > max_value)
throw std::invalid_argument("invalid min max value for NumberRangeConstrain");
@ -93,7 +93,7 @@ namespace YYCC::ConfigManager {
#pragma region Setting Presets
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty>, int> = 0>
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty> || std::is_enum_v<_Ty>, int> = 0>
class NumberSetting : public AbstractSetting {
public:
NumberSetting(const yycc_char8_t* name, _Ty default_value, Constrain<_Ty> constrain = Constrain<_Ty> {}) :
@ -103,7 +103,7 @@ namespace YYCC::ConfigManager {
_Ty Get() const { return m_Data; }
bool Set(_Ty new_data) {
// validate data
if (m_Constrain.IsValid() && !m_Constrain.m_CheckFct(m_Data))
if (m_Constrain.IsValid() && !m_Constrain.m_CheckFct(new_data))
return false;
// assign data
m_Data = new_data;
@ -189,6 +189,9 @@ namespace YYCC::ConfigManager {
std::memcpy(ptr + sizeof(string_length), m_Data.data(), string_length);
return true;
}
virtual void UserReset() override {
m_Data = m_DefaultData;
}
yycc_u8string m_Data, m_DefaultData;
Constrain<yycc_u8string> m_Constrain;

View File

@ -390,15 +390,112 @@ namespace YYCCTestbench {
}
class TestConfigManager {
public:
enum class TestEnum : int8_t {
Test1, Test2, Test3
};
TestConfigManager() :
m_IntSetting(YYCC_U8("int-setting"), INT32_C(0)),
m_FloatSetting(YYCC_U8("float-setting"), 0.0f),
m_StringSetting(YYCC_U8("string-setting"), YYCC_U8("")),
m_BoolSetting(YYCC_U8("bool-setting"), false),
m_ClampedFloatSetting(YYCC_U8("clamped-float-setting"), 0.0f, YYCC::ConfigManager::ConstrainPresets::GetNumberRangeConstrain<float>(-1.0f, 1.0f)),
m_EnumSetting(YYCC_U8("enum-setting"), TestEnum::Test1),
m_CoreManager(YYCC_U8("test.cfg"), UINT64_C(0), {
&m_IntSetting, &m_FloatSetting, &m_StringSetting, &m_BoolSetting, &m_ClampedFloatSetting, &m_EnumSetting
})
{}
~TestConfigManager() {}
void PrintSettings() {
Console::WriteLine(YYCC_U8("Config Manager Settings:"));
Console::FormatLine(YYCC_U8("\tint-setting: %" PRIi32), m_IntSetting.Get());
Console::FormatLine(YYCC_U8("\tfloat-setting: %f"), m_FloatSetting.Get());
Console::FormatLine(YYCC_U8("\tstring-setting: %s"), m_StringSetting.Get().c_str());
Console::FormatLine(YYCC_U8("\tbool-setting: %s"), m_BoolSetting.Get() ? YYCC_U8("true") : YYCC_U8("false"));
Console::FormatLine(YYCC_U8("\tfloat-setting: %f"), m_ClampedFloatSetting.Get());
Console::FormatLine(YYCC_U8("\tenum-setting: %" PRIi8), static_cast<std::underlying_type_t<TestEnum>>(m_EnumSetting.Get()));
}
YYCC::ConfigManager::NumberSetting<int32_t> m_IntSetting;
YYCC::ConfigManager::NumberSetting<float> m_FloatSetting;
YYCC::ConfigManager::StringSetting m_StringSetting;
YYCC::ConfigManager::NumberSetting<bool> m_BoolSetting;
YYCC::ConfigManager::NumberSetting<float> m_ClampedFloatSetting;
YYCC::ConfigManager::NumberSetting<TestEnum> m_EnumSetting;
YYCC::ConfigManager::CoreManager m_CoreManager;
};
static void ConfigManagerTestbench() {
// init cfg manager
TestConfigManager test;
// test constrain works
Assert(!test.m_ClampedFloatSetting.Set(2.0f), YYCC_U8("YYCC::ConfigManager::Constraint"));
Assert(test.m_ClampedFloatSetting.Get() == 0.0f, YYCC_U8("YYCC::ConfigManager::Constraint"));
// test modify settings
#define TEST_MACRO(member_name, set_val) { \
Assert(test.member_name.Set(set_val), YYCC_U8("YYCC::ConfigManager::AbstractSetting::Set")); \
Assert(test.member_name.Get() == set_val, YYCC_U8("YYCC::ConfigManager::AbstractSetting::Set")); \
}
TEST_MACRO(m_IntSetting, INT32_C(114));
TEST_MACRO(m_FloatSetting, 2.0f);
TEST_MACRO(m_StringSetting, YYCC_U8("fuck"));
TEST_MACRO(m_BoolSetting, true);
TEST_MACRO(m_ClampedFloatSetting, 0.5f);
TEST_MACRO(m_EnumSetting, TestConfigManager::TestEnum::Test2);
#undef TEST_MACRO
// test save
test.PrintSettings();
Assert(test.m_CoreManager.Save(), YYCC_U8("YYCC::ConfigManager::CoreManager::Save"));
// test reset
test.m_CoreManager.Reset();
test.PrintSettings();
Assert(test.m_IntSetting.Get() == INT32_C(0), YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
Assert(test.m_FloatSetting.Get() == 0.0f, YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
Assert(test.m_StringSetting.Get() == YYCC_U8(""), YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
Assert(test.m_BoolSetting.Get() == false, YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
Assert(test.m_ClampedFloatSetting.Get() == 0.0f, YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
Assert(test.m_EnumSetting.Get() == TestConfigManager::TestEnum::Test1, YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
// test load
Assert(test.m_CoreManager.Load(), YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
test.PrintSettings();
Assert(test.m_IntSetting.Get() == INT32_C(114), YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
Assert(test.m_FloatSetting.Get() == 2.0f, YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
Assert(test.m_StringSetting.Get() == YYCC_U8("fuck"), YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
Assert(test.m_BoolSetting.Get() == true, YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
Assert(test.m_ClampedFloatSetting.Get() == 0.5f, YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
Assert(test.m_EnumSetting.Get() == TestConfigManager::TestEnum::Test2, YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
}
}
int main(int argc, char** args) {
//YYCCTestbench::ConsoleTestbench();
// common testbench
// normal
YYCCTestbench::EncodingTestbench();
YYCCTestbench::StringTestbench();
YYCCTestbench::ParserTestbench();
YYCCTestbench::DialogTestbench();
YYCCTestbench::ExceptionTestbench();
YYCCTestbench::WinFctTestbench();
YYCCTestbench::FsPathPatch();
// advanced
YYCCTestbench::ConfigManagerTestbench();
// testbench which may terminal app or ordering input
YYCCTestbench::ConsoleTestbench();
YYCCTestbench::DialogTestbench();
YYCCTestbench::ExceptionTestbench();
}