diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/cfg.cc | 190 | ||||
| -rw-r--r-- | test/testdir.cc | 37 | ||||
| -rw-r--r-- | test/testdir.hh | 22 |
3 files changed, 249 insertions, 0 deletions
diff --git a/test/cfg.cc b/test/cfg.cc new file mode 100644 index 0000000..80ebba9 --- /dev/null +++ b/test/cfg.cc @@ -0,0 +1,190 @@ +#include "cfg.hh" + +#include "testdir.hh" +#include "testenv.hh" + +#include <fstream> +#include <gtest/gtest.h> +#include <string> +#include <vector> + +namespace { + +class ConfigTest : public TestEnv { + protected: + void SetUp() override { ASSERT_TRUE(dir_.good()); } + + TestDir dir_; +}; + +} // namespace + +TEST_F(ConfigTest, empty) { + auto does_not_exist = dir_.path() / "does-not-exist"; + std::vector<std::string> errors; + auto cfg = cfg::Config::load(does_not_exist.string(), errors); + ASSERT_TRUE(cfg); + EXPECT_EQ(1, errors.size()); + + EXPECT_FALSE(cfg->has("")); + EXPECT_FALSE(cfg->get("").has_value()); + + EXPECT_FALSE(cfg->has("foo")); + EXPECT_FALSE(cfg->get("foo").has_value()); +} + +TEST_F(ConfigTest, values) { + auto file = dir_.path() / "file"; + { + std::ofstream out(file); + out << "# Comment\n" + << "key=value\n" + << " foo = bar \n" + << "i1 = 12\n" + << "b1 = true\n" + << "b2=FaLSe\n" + << "i2 = -12313\n"; + } + std::vector<std::string> errors; + auto cfg = cfg::Config::load(file.string(), errors); + ASSERT_TRUE(cfg); + EXPECT_EQ(0, errors.size()); + + EXPECT_FALSE(cfg->has("")); + EXPECT_FALSE(cfg->get("").has_value()); + + EXPECT_TRUE(cfg->has("key")); + EXPECT_EQ("value", cfg->get("key").value_or("")); + + EXPECT_TRUE(cfg->has("foo")); + EXPECT_EQ("bar", cfg->get("foo").value_or("")); + EXPECT_FALSE(cfg->get_int64("foo").has_value()); + + EXPECT_TRUE(cfg->has("i1")); + EXPECT_EQ("12", cfg->get("i1").value_or("")); + EXPECT_EQ(12, cfg->get_int64("i1").value_or(0)); + EXPECT_EQ(12, cfg->get_uint64("i1").value_or(0)); + + EXPECT_TRUE(cfg->has("b1")); + EXPECT_EQ("true", cfg->get("b1").value_or("")); + EXPECT_TRUE(cfg->get_bool("b1").value_or(false)); + + EXPECT_TRUE(cfg->has("b2")); + EXPECT_EQ("FaLSe", cfg->get("b2").value_or("")); + EXPECT_FALSE(cfg->get_bool("b2").value_or(true)); + + EXPECT_TRUE(cfg->has("i2")); + EXPECT_EQ("-12313", cfg->get("i2").value_or("")); + EXPECT_EQ(-12313, cfg->get_int64("i2").value_or(0)); + EXPECT_EQ(0, cfg->get_uint64("i2").value_or(0)); +} + +TEST_F(ConfigTest, bools) { + auto file = dir_.path() / "file"; + { + std::ofstream out(file); + out << "key1=True\n" + << "key2=yES\n" + << "key3=false\n" + << "key4=NO\n" + << "key5=ja\n"; + } + std::vector<std::string> errors; + auto cfg = cfg::Config::load(file.string(), errors); + ASSERT_TRUE(cfg); + EXPECT_EQ(0, errors.size()); + + EXPECT_TRUE(cfg->get_bool("key1").value_or(false)); + EXPECT_TRUE(cfg->get_bool("key2").value_or(false)); + EXPECT_FALSE(cfg->get_bool("key3").value_or(true)); + EXPECT_FALSE(cfg->get_bool("key4").value_or(true)); + EXPECT_FALSE(cfg->get_bool("key5").has_value()); +} + +TEST_F(ConfigTest, errors) { + auto file = dir_.path() / "file"; + { + std::ofstream out(file); + out << "bad line\n" + << "key=value\n" + << "key=duplicate\n"; + } + std::vector<std::string> errors; + auto cfg = cfg::Config::load(file.string(), errors); + ASSERT_TRUE(cfg); + EXPECT_EQ(2, errors.size()); +} + +TEST_F(ConfigTest, merge) { + auto dir1 = dir_.path() / "dir1"; + auto dir2 = dir_.path() / "dir2"; + auto dir3 = dir_.path() / "dir3"; + std::filesystem::create_directory(dir1); + std::filesystem::create_directory(dir2); + std::filesystem::create_directory(dir3); + setenv("XDG_CONFIG_HOME", dir1); + setenv("XDG_CONFIG_DIRS", dir2.string() + ":" + dir3.string()); + auto file1 = dir1 / "file"; + auto file2 = dir2 / "file"; + { + std::ofstream out(file2); + out << "key1 = value1\n" + << "key2 = value2\n"; + } + { + std::ofstream out(file1); + out << "key1 = 12\n" + << "key3 = value3"; + } + std::vector<std::string> errors; + auto cfg = cfg::Config::load("file", errors); + ASSERT_TRUE(cfg); + EXPECT_EQ(0, errors.size()); + + EXPECT_FALSE(cfg->has("")); + EXPECT_FALSE(cfg->get("").has_value()); + + EXPECT_TRUE(cfg->has("key1")); + EXPECT_EQ("12", cfg->get("key1").value_or("")); + + EXPECT_TRUE(cfg->has("key2")); + EXPECT_EQ("value2", cfg->get("key2").value_or("")); + + EXPECT_TRUE(cfg->has("key3")); + EXPECT_EQ("value3", cfg->get("key3").value_or("")); +} + +TEST_F(ConfigTest, merge_errors) { + auto dir1 = dir_.path() / "dir1"; + auto dir2 = dir_.path() / "dir2"; + std::filesystem::create_directory(dir1); + std::filesystem::create_directory(dir2); + setenv("XDG_CONFIG_HOME", dir1); + setenv("XDG_CONFIG_DIRS", dir2); + auto file1 = dir1 / "file"; + auto file2 = dir2 / "file"; + { + std::ofstream out(file2); + out << "key1 = value1\n" + << "key2 = value2\n"; + } + { + std::ofstream out(file1); + out << "invalid line"; + } + std::vector<std::string> errors; + auto cfg = cfg::Config::load("file", errors); + ASSERT_TRUE(cfg); + EXPECT_EQ(1, errors.size()); + + EXPECT_FALSE(cfg->has("")); + EXPECT_FALSE(cfg->get("").has_value()); + + EXPECT_TRUE(cfg->has("key1")); + EXPECT_EQ("value1", cfg->get("key1").value_or("")); + + EXPECT_TRUE(cfg->has("key2")); + EXPECT_EQ("value2", cfg->get("key2").value_or("")); + + EXPECT_FALSE(cfg->has("key3")); +} diff --git a/test/testdir.cc b/test/testdir.cc new file mode 100644 index 0000000..d5aef22 --- /dev/null +++ b/test/testdir.cc @@ -0,0 +1,37 @@ +#include "testdir.hh" + +#include <cstdlib> +#include <filesystem> +#include <format> +#include <gtest/gtest.h> +#include <system_error> + +namespace { + +std::filesystem::path mktmpdir() { + std::error_code ec; + auto base = std::filesystem::temp_directory_path(ec); + if (ec) + return {}; + for (int i = 0; i < 10; ++i) { + auto name = std::format( + "{}-{}", + ::testing::UnitTest::GetInstance()->current_test_info()->name(), + rand()); + auto tmpdir = base / name; + if (std::filesystem::exists(tmpdir)) + continue; + if (std::filesystem::create_directory(tmpdir, ec)) + return tmpdir; + } + return {}; +} + +} // namespace + +TestDir::TestDir() : path_(mktmpdir()) {} + +TestDir::~TestDir() { + if (!path_.empty()) + std::filesystem::remove_all(path_); +} diff --git a/test/testdir.hh b/test/testdir.hh new file mode 100644 index 0000000..b59e09a --- /dev/null +++ b/test/testdir.hh @@ -0,0 +1,22 @@ +#ifndef TESTDIR_HH +#define TESTDIR_HH + +#include <filesystem> // IWYU pragma: export + +class TestDir { + public: + TestDir(); + ~TestDir(); + + TestDir(TestDir const&) = delete; + TestDir& operator=(TestDir const&) = delete; + + bool good() const { return !path_.empty(); }; + + std::filesystem::path const& path() const { return path_; }; + + private: + std::filesystem::path path_; +}; + +#endif // TESTDIR_HH |
