Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ set(TEST_SOURCES
ts-roundtrip.cpp
ts-snippets.cpp
ts-utf8.cpp
ts-numeric.cpp
ts-boolean.cpp
ts-sections.cpp
ts-deletion.cpp
ts-edgecases.cpp
ts-multiline.cpp
ts-casesensitivity.cpp
)

# ts-wchar.cpp uses wchar_t which is primarily for Windows
Expand Down
252 changes: 252 additions & 0 deletions tests/ts-boolean.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
#include "../SimpleIni.h"
#include "gtest/gtest.h"

class TestBoolean : public ::testing::Test {
protected:
void SetUp() override;
protected:
CSimpleIniA ini;
};

void TestBoolean::SetUp() {
ini.SetUnicode();
}

// Test GetBoolValue with all recognized TRUE values
TEST_F(TestBoolean, TestGetBoolValueTrue) {
std::string input =
"[bools]\n"
"true1 = true\n"
"true2 = t\n"
"true3 = yes\n"
"true4 = y\n"
"true5 = 1\n"
"true6 = on\n";

SI_Error rc = ini.LoadData(input);
ASSERT_EQ(rc, SI_OK);

ASSERT_TRUE(ini.GetBoolValue("bools", "true1", false));
ASSERT_TRUE(ini.GetBoolValue("bools", "true2", false));
ASSERT_TRUE(ini.GetBoolValue("bools", "true3", false));
ASSERT_TRUE(ini.GetBoolValue("bools", "true4", false));
ASSERT_TRUE(ini.GetBoolValue("bools", "true5", false));
ASSERT_TRUE(ini.GetBoolValue("bools", "true6", false));
}

// Test GetBoolValue with all recognized FALSE values
TEST_F(TestBoolean, TestGetBoolValueFalse) {
std::string input =
"[bools]\n"
"false1 = false\n"
"false2 = f\n"
"false3 = no\n"
"false4 = n\n"
"false5 = 0\n"
"false6 = off\n";

SI_Error rc = ini.LoadData(input);
ASSERT_EQ(rc, SI_OK);

ASSERT_FALSE(ini.GetBoolValue("bools", "false1", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "false2", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "false3", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "false4", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "false5", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "false6", true));
}

// Test GetBoolValue with case variations
TEST_F(TestBoolean, TestGetBoolValueCaseInsensitive) {
std::string input =
"[bools]\n"
"upper = TRUE\n"
"mixed = YeS\n"
"lower = false\n"
"caps = NO\n";

SI_Error rc = ini.LoadData(input);
ASSERT_EQ(rc, SI_OK);

ASSERT_TRUE(ini.GetBoolValue("bools", "upper", false));
ASSERT_TRUE(ini.GetBoolValue("bools", "mixed", false));
ASSERT_FALSE(ini.GetBoolValue("bools", "lower", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "caps", true));
}

// Test GetBoolValue with unrecognized values (should return default)
TEST_F(TestBoolean, TestGetBoolValueUnrecognized) {
std::string input =
"[bools]\n"
"invalid1 = maybe\n"
"invalid2 = 2\n"
"invalid3 = \n"
"invalid4 = enabled\n";

SI_Error rc = ini.LoadData(input);
ASSERT_EQ(rc, SI_OK);

// Unrecognized values should return default
ASSERT_TRUE(ini.GetBoolValue("bools", "invalid1", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "invalid1", false));

ASSERT_TRUE(ini.GetBoolValue("bools", "invalid2", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "invalid2", false));

ASSERT_TRUE(ini.GetBoolValue("bools", "invalid3", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "invalid3", false));

ASSERT_TRUE(ini.GetBoolValue("bools", "invalid4", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "invalid4", false));
}

// Test GetBoolValue with missing key
TEST_F(TestBoolean, TestGetBoolValueMissing) {
std::string input = "[bools]\n";

SI_Error rc = ini.LoadData(input);
ASSERT_EQ(rc, SI_OK);

ASSERT_TRUE(ini.GetBoolValue("bools", "missing", true));
ASSERT_FALSE(ini.GetBoolValue("bools", "missing", false));

ASSERT_TRUE(ini.GetBoolValue("missing_section", "key", true));
ASSERT_FALSE(ini.GetBoolValue("missing_section", "key", false));
}

// Test SetBoolValue
TEST_F(TestBoolean, TestSetBoolValue) {
SI_Error rc = ini.SetBoolValue("bools", "value1", true);
ASSERT_EQ(rc, SI_INSERTED);

bool result = ini.GetBoolValue("bools", "value1", false);
ASSERT_TRUE(result);

rc = ini.SetBoolValue("bools", "value2", false);
ASSERT_EQ(rc, SI_INSERTED);

result = ini.GetBoolValue("bools", "value2", true);
ASSERT_FALSE(result);
}

// Test SetBoolValue updates existing value
TEST_F(TestBoolean, TestSetBoolValueUpdate) {
SI_Error rc = ini.SetBoolValue("bools", "toggle", true);
ASSERT_EQ(rc, SI_INSERTED);

ASSERT_TRUE(ini.GetBoolValue("bools", "toggle", false));

rc = ini.SetBoolValue("bools", "toggle", false);
ASSERT_EQ(rc, SI_UPDATED);

ASSERT_FALSE(ini.GetBoolValue("bools", "toggle", true));
}

// Test SetBoolValue output format
TEST_F(TestBoolean, TestSetBoolValueFormat) {
ini.SetBoolValue("bools", "enabled", true);
ini.SetBoolValue("bools", "disabled", false);

std::string output;
SI_Error rc = ini.Save(output);
ASSERT_EQ(rc, SI_OK);

// Should write as "true" and "false"
EXPECT_NE(output.find("enabled = true"), std::string::npos);
EXPECT_NE(output.find("disabled = false"), std::string::npos);
}

// Test GetBoolValue with whitespace
TEST_F(TestBoolean, TestGetBoolValueWhitespace) {
std::string input =
"[bools]\n"
"padded = true \n"
"tabs =\tfalse\t\n";

SI_Error rc = ini.LoadData(input);
ASSERT_EQ(rc, SI_OK);

ASSERT_TRUE(ini.GetBoolValue("bools", "padded", false));
ASSERT_FALSE(ini.GetBoolValue("bools", "tabs", true));
}

// Test boolean with multikey
TEST_F(TestBoolean, TestBooleanMultikey) {
ini.SetMultiKey(true);

std::string input =
"[bools]\n"
"flag = true\n"
"flag = false\n"
"flag = yes\n";

SI_Error rc = ini.LoadData(input);
ASSERT_EQ(rc, SI_OK);

bool hasMultiple = false;
bool result = ini.GetBoolValue("bools", "flag", false, &hasMultiple);
ASSERT_TRUE(result); // First value is true
ASSERT_TRUE(hasMultiple);

// Get all values
CSimpleIniA::TNamesDepend values;
ini.GetAllValues("bools", "flag", values);
ASSERT_EQ(values.size(), 3);
}

// Test SetBoolValue with force replace
TEST_F(TestBoolean, TestSetBoolValueForceReplace) {
ini.SetMultiKey(true);

std::string input =
"[bools]\n"
"value = true\n"
"value = false\n";

SI_Error rc = ini.LoadData(input);
ASSERT_EQ(rc, SI_OK);

// Replace all values
rc = ini.SetBoolValue("bools", "value", true, nullptr, true);
ASSERT_EQ(rc, SI_UPDATED);

// Should only have one value now
bool hasMultiple = false;
bool result = ini.GetBoolValue("bools", "value", false, &hasMultiple);
ASSERT_TRUE(result);
ASSERT_FALSE(hasMultiple);
}

// Test boolean roundtrip
TEST_F(TestBoolean, TestBooleanRoundtrip) {
ini.SetBoolValue("test", "bool1", true);
ini.SetBoolValue("test", "bool2", false);
ini.SetBoolValue("test", "bool3", true);

std::string output;
SI_Error rc = ini.Save(output);
ASSERT_EQ(rc, SI_OK);

// Load it back
CSimpleIniA ini2;
ini2.SetUnicode();
rc = ini2.LoadData(output);
ASSERT_EQ(rc, SI_OK);

ASSERT_TRUE(ini2.GetBoolValue("test", "bool1", false));
ASSERT_FALSE(ini2.GetBoolValue("test", "bool2", true));
ASSERT_TRUE(ini2.GetBoolValue("test", "bool3", false));
}

// Test "of" typo for "off" (documented quirk)
TEST_F(TestBoolean, TestBoolValueOfTypo) {
std::string input =
"[bools]\n"
"typo = of\n";

SI_Error rc = ini.LoadData(input);
ASSERT_EQ(rc, SI_OK);

// "of" is recognized as false (documented quirk)
ASSERT_FALSE(ini.GetBoolValue("bools", "typo", true));
}
Loading