diff options
author | 2011-03-20 20:10:06 +0000 | |
---|---|---|
committer | 2011-03-20 20:10:06 +0000 | |
commit | 62ba0191fb7936e9e0555d1442abd49c210567d3 (patch) | |
tree | 4aea466bb9847d5a1cf550df7ab12dabe361b1af | |
parent | 013f8226fc1207c01b568986e2c89163a4c78d8f (diff) | |
download | paludis-62ba0191fb7936e9e0555d1442abd49c210567d3.tar.gz paludis-62ba0191fb7936e9e0555d1442abd49c210567d3.tar.xz |
gtest more
-rw-r--r-- | paludis/util/config_file_TEST.cc | 888 | ||||
-rw-r--r-- | paludis/util/files.m4 | 2 |
2 files changed, 398 insertions, 492 deletions
diff --git a/paludis/util/config_file_TEST.cc b/paludis/util/config_file_TEST.cc index 95ad3c98b..6b20d3272 100644 --- a/paludis/util/config_file_TEST.cc +++ b/paludis/util/config_file_TEST.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh + * Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011 Ciaran McCreesh * * This file is part of the Paludis package manager. Paludis is free software; * you can redistribute it and/or modify it under the terms of the GNU General @@ -25,15 +25,15 @@ #include <paludis/util/map.hh> #include <paludis/util/options.hh> #include <paludis/util/wrapped_forward_iterator.hh> + #include <sstream> -#include <test/test_framework.hh> -#include <test/test_runner.hh> #include <vector> #include <cstdlib> #include <iomanip> #include <unistd.h> -using namespace test; +#include <gtest/gtest.h> + using namespace paludis; namespace @@ -58,494 +58,400 @@ namespace } } -namespace test_cases +TEST(LineConfigFile, Works) { - struct LineConfigFileTest : TestCase - { - LineConfigFileTest() : TestCase("line config file") { } - - void run() - { - std::stringstream s; - s << "one" << std::endl; - s << " two \t " << std::endl; - s << " \t " << std::endl; - s << "" << std::endl; - s << "three" << std::endl; - s << "# blah" << std::endl; - s << " # blah" << std::endl; - s << "#" << std::endl; - s << " # \t " << std::endl; - s << "four four" << std::endl; - s << "five \\" << std::endl; - s << "six" << std::endl; - s << "seven\\" << std::endl; - s << "eight" << std::endl; - s << "nine # ten" << std::endl; - - LineConfigFile f(s, { }); - TEST_CHECK_EQUAL(std::distance(f.begin(), f.end()), 7); - std::vector<std::string> lines; - std::copy(f.begin(), f.end(), std::back_inserter(lines)); - TEST_CHECK_EQUAL(lines.at(0), "one"); - TEST_CHECK_EQUAL(lines.at(1), "two"); - TEST_CHECK_EQUAL(lines.at(2), "three"); - TEST_CHECK_EQUAL(lines.at(3), "four four"); - TEST_CHECK_EQUAL(lines.at(4), "five six"); - TEST_CHECK_EQUAL(lines.at(5), "seveneight"); - TEST_CHECK_EQUAL(lines.at(6), "nine # ten"); - - s.clear(); - s.seekg(0, std::ios::beg); - - LineConfigFile g(s, { lcfo_disallow_comments, lcfo_preserve_whitespace, lcfo_no_skip_blank_lines }); - TEST_CHECK_EQUAL(std::distance(g.begin(), g.end()), 13); - lines.clear(); - std::copy(g.begin(), g.end(), std::back_inserter(lines)); - TEST_CHECK_EQUAL(lines.at(0), "one"); - TEST_CHECK_EQUAL(lines.at(1), " two \t "); - TEST_CHECK_EQUAL(lines.at(2), " \t "); - TEST_CHECK_EQUAL(lines.at(3), ""); - TEST_CHECK_EQUAL(lines.at(4), "three"); - TEST_CHECK_EQUAL(lines.at(5), "# blah"); - TEST_CHECK_EQUAL(lines.at(6), " # blah"); - TEST_CHECK_EQUAL(lines.at(7), "#"); - TEST_CHECK_EQUAL(lines.at(8), " # \t "); - TEST_CHECK_EQUAL(lines.at(9), "four four"); - TEST_CHECK_EQUAL(lines.at(10), "five six"); - TEST_CHECK_EQUAL(lines.at(11), "seveneight"); - TEST_CHECK_EQUAL(lines.at(12), "nine # ten"); - - s.clear(); - s.seekg(0, std::ios::beg); - - LineConfigFile h(s, { lcfo_allow_inline_comments }); - TEST_CHECK_EQUAL(std::distance(f.begin(), f.end()), 7); - lines.clear(); - std::copy(h.begin(), h.end(), std::back_inserter(lines)); - TEST_CHECK_EQUAL(lines.at(0), "one"); - TEST_CHECK_EQUAL(lines.at(1), "two"); - TEST_CHECK_EQUAL(lines.at(2), "three"); - TEST_CHECK_EQUAL(lines.at(3), "four four"); - TEST_CHECK_EQUAL(lines.at(4), "five six"); - TEST_CHECK_EQUAL(lines.at(5), "seveneight"); - TEST_CHECK_EQUAL(lines.at(6), "nine"); - } - } test_line_config_file; - - struct ConfigFileOpenFileTest : TestCase - { - ConfigFileOpenFileTest() : TestCase("config file open file") { } - - void run() - { - FSPath ff("config_file_TEST_dir/config_file"); - TEST_CHECK(ff.stat().is_regular_file()); - LineConfigFile f(ff, { }); - TEST_CHECK_EQUAL(std::distance(f.begin(), f.end()), 1); - TEST_CHECK_EQUAL(*f.begin(), "I am a fish."); - - FSPath ff2("config_file_TEST_dir/not_a_config_file"); - TEST_CHECK(! ff2.stat().exists()); - LineConfigFile * f2(0); - TEST_CHECK_THROWS(f2 = new LineConfigFile(ff2, { }), ConfigFileError); - - if (0 != geteuid()) - { - FSPath ff3("config_file_TEST_dir/unreadable_file"); - TEST_CHECK(ff3.stat().is_regular_file()); - LineConfigFile * f3(0); - TEST_CHECK_THROWS(f3 = new LineConfigFile(ff3, { }), ConfigFileError); - } - } - } test_config_file_open_file; - - struct KeyValueConfigFileTest : TestCase - { - KeyValueConfigFileTest() : TestCase("key value config file") { } - - void run() - { - std::stringstream s; - s << "one=first" << std::endl; - s << "two = second" << std::endl; - s << "three=" << std::endl; - s << "four = \"fourth\" " << std::endl; - s << "five = ''" << std::endl; - KeyValueConfigFile ff(s, { kvcfo_preserve_whitespace }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(ff.get("one"), "first"); - TEST_CHECK_EQUAL(ff.get("two"), "second"); - TEST_CHECK_EQUAL(ff.get("three"), ""); - TEST_CHECK_EQUAL(ff.get("four"), "fourth "); - TEST_CHECK_EQUAL(ff.get("five"), ""); - TEST_CHECK_EQUAL(ff.get("six"), ""); - } - } test_key_value_config_file; - - /** - * \test Test KeyValueConfigFile continuations. - * - */ - struct KeyValueConfigFileContinuationsTest : TestCase - { - KeyValueConfigFileContinuationsTest() : TestCase("key value config file continuations") { } - - void run() - { - std::stringstream s; - s << "one='first" << std::endl; - s << " first " << std::endl; - s << "first'" << std::endl; - KeyValueConfigFile ff(s, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(ff.get("one"), "first\n first \nfirst"); - } - } test_key_value_config_file_continuations; - - /** - * \test Test KeyValueConfigFile variables. - * - */ - struct KeyValueConfigFileVarsTest : TestCase - { - KeyValueConfigFileVarsTest() : TestCase("key value config file with vars") { } - - void run() - { - std::stringstream s; - s << "x=foo" << std::endl; - s << "y = \"${x}\\\\${y}\\$${z}\"" << std::endl; - s << "z = $x$y$z" << std::endl; - KeyValueConfigFile ff(s, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(ff.get("x"), "foo"); - TEST_CHECK_EQUAL(ff.get("y"), "foo\\$"); - TEST_CHECK_EQUAL(ff.get("z"), "foofoo\\$"); - - std::stringstream t; - std::shared_ptr<Map<std::string, std::string> > t_defs(std::make_shared<Map<std::string, std::string>>()); - t_defs->insert("a", "moo"); - t_defs->insert("d", "bar"); - t_defs->insert("e", "baz"); - t << "a=foo" << std::endl; - t << "b=$a" << std::endl; - t << "c=$d" << std::endl; - t << "d=$d" << std::endl; - t << "f = " << std::endl; - t << "g = foo \\" << std::endl; - t << " bar" << std::endl; - KeyValueConfigFile fg(t, { }, - std::bind(&predefined, t_defs, std::placeholders::_1, std::placeholders::_2), - &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(fg.get("a"), "foo"); - TEST_CHECK_EQUAL(fg.get("b"), "foo"); - TEST_CHECK_EQUAL(fg.get("c"), "bar"); - TEST_CHECK_EQUAL(fg.get("d"), "bar"); - TEST_CHECK_EQUAL(fg.get("e"), "baz"); - TEST_CHECK_EQUAL(fg.get("f"), ""); - TEST_CHECK_EQUAL(fg.get("g"), "foo bar"); - } - } test_key_value_config_file_vars; - - struct KeyValueConfigFileDefaultsTest : TestCase - { - KeyValueConfigFileDefaultsTest() : TestCase("key value config file with defaults") { } - - void run() - { - setenv("moo", "cow", 1); - - std::stringstream d_s; - d_s << "foo=oink" << std::endl; - std::shared_ptr<KeyValueConfigFile> d_ff(std::make_shared<KeyValueConfigFile>(d_s, KeyValueConfigFileOptions(), - &predefined_from_env, - &KeyValueConfigFile::no_transformation)); - - std::stringstream s; - s << "x=${foo}" << std::endl; - s << "y=${moo}" << std::endl; - KeyValueConfigFile ff(s, { }, - std::bind(&predefined_from_config_file, std::cref(*d_ff), std::placeholders::_1, std::placeholders::_2), - &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(ff.get("x"), "oink"); - TEST_CHECK_EQUAL(ff.get("y"), "cow"); - } - } test_key_value_config_file_defaults; - - struct KeyValueConfigFileSourceTest : TestCase - { - KeyValueConfigFileSourceTest() : TestCase("key value config file source") { } - - void run() - { - std::stringstream d_s; - d_s << "six=\"llama\"" << std::endl; - d_s << "seven=\"spider\"" << std::endl; - d_s << "source config_file_TEST_dir/sourced_one" << std::endl; - d_s << "eight=\"octopus\"" << std::endl; - KeyValueConfigFile ff(d_s, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(ff.get("one"), "cat"); - TEST_CHECK_EQUAL(ff.get("two"), "dog"); - TEST_CHECK_EQUAL(ff.get("three"), "koala"); - TEST_CHECK_EQUAL(ff.get("four"), "sheep"); - TEST_CHECK_EQUAL(ff.get("five"), "rabbit"); - TEST_CHECK_EQUAL(ff.get("six"), "llama"); - TEST_CHECK_EQUAL(ff.get("seven"), "spider"); - TEST_CHECK_EQUAL(ff.get("eight"), "octopus"); - } - } test_key_value_config_file_source; - - /** - * \test Test KeyValueConfigFile ignore export. - * - */ - struct KeyValueConfigFileIgnoreExportTest : TestCase - { - KeyValueConfigFileIgnoreExportTest() : TestCase("key value config file ignore export") { } - - void run() - { - std::stringstream d_s; - d_s << "export \t foo = \"xyzzy\"" << std::endl; - d_s << "export bar='plugh'" << std::endl; - d_s << "baz = \"plover\"" << std::endl; - d_s << "exportfoo = \"exportxyzzy\"" << std::endl; - KeyValueConfigFile ff(d_s, { kvcfo_ignore_export }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(ff.get("foo"), "xyzzy"); - TEST_CHECK_EQUAL(ff.get("bar"), "plugh"); - TEST_CHECK_EQUAL(ff.get("baz"), "plover"); - TEST_CHECK_EQUAL(ff.get("exportfoo"), "exportxyzzy"); - - std::stringstream d_s2; - d_s2 << "export = 42" << std::endl; - KeyValueConfigFile ff2(d_s2, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(ff2.get("export"), "42"); - } - } test_key_value_config_file_ignore_export; - - /** - * \test Test KeyValueConfigFile errors. - * - */ - struct KeyValueConfigFileErrorsTest : TestCase - { - KeyValueConfigFileErrorsTest() : TestCase("key value config file with errors") { } - - void run() - { - std::stringstream s1; - s1 << "x='" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s1, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - - std::stringstream s2; - s2 << "x='moo\"" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s2, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - - std::stringstream s3; - s3 << "x=${foo" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s3, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - - std::stringstream s4; - s4 << "x=$~" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s4, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - - std::stringstream s5; - s5 << "x=abc\\" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s5, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - - std::stringstream s6; - s6 << "x=$" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s6, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - - std::stringstream s7; - s7 << "x=blah \\" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s7, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - - std::stringstream s8; - s8 << "x=blah \\" << std::endl << "# foo" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s8, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - - std::stringstream s9; - s9 << "x='blah" << std::endl << "blah" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s9, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - - std::stringstream s10; - s10 << "export x=blah" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s10, { }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - - std::stringstream s11; - s11 << "export x = blah" << std::endl; - TEST_CHECK_THROWS(KeyValueConfigFile ff(s11, { kvcfo_ignore_export, kvcfo_disallow_space_around_equals }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); - } - } test_key_value_config_file_errors; - - struct LineConfigFileInlineCommentsTest : TestCase - { - LineConfigFileInlineCommentsTest() : TestCase("line config file inline comments") { } - - void run() - { - std::stringstream s; - s << "one # moo" << std::endl; - s << "tw\\" << std::endl; - s << "o # moo" << std::endl; - s << "" << std::endl; - s << "three #" << std::endl; - s << "#" << std::endl; - s << "four" << std::endl; - s << "five # moo" << std::endl; - - LineConfigFile f(s, { lcfo_allow_inline_comments }); - TEST_CHECK_EQUAL(std::distance(f.begin(), f.end()), 5); - std::vector<std::string> lines; - std::copy(f.begin(), f.end(), std::back_inserter(lines)); - TEST_CHECK_EQUAL(lines.at(0), "one"); - TEST_CHECK_EQUAL(lines.at(1), "two"); - TEST_CHECK_EQUAL(lines.at(2), "three"); - TEST_CHECK_EQUAL(lines.at(3), "four"); - TEST_CHECK_EQUAL(lines.at(4), "five"); - } - } test_line_config_file_inline_comments; - - struct KeyValueConfigFileInlineCommentsTest : TestCase - { - KeyValueConfigFileInlineCommentsTest() : TestCase("key value config inline comments") { } - - void run() - { - std::stringstream d_s; - d_s << "one=\"one\" # foo" << std::endl; - d_s << "two=two # bar" << std::endl; - d_s << "three = \\" << std::endl; - d_s << "three # bar" << std::endl; - d_s << "four = four # foo" << std::endl; - d_s << "five = five # moo" << std::endl; - KeyValueConfigFile ff(d_s, { kvcfo_allow_inline_comments }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(std::distance(ff.begin(), ff.end()), 5); - TEST_CHECK_EQUAL(ff.get("one"), "one"); - TEST_CHECK_EQUAL(ff.get("two"), "two"); - TEST_CHECK_EQUAL(ff.get("three"), "three"); - TEST_CHECK_EQUAL(ff.get("four"), "four"); - TEST_CHECK_EQUAL(ff.get("five"), "five"); - } - } test_key_value_config_file_inline_comments; - - struct KeyValueConfigFileMultipleAssignsTest : TestCase - { - KeyValueConfigFileMultipleAssignsTest() : TestCase("key value config multiple assigns") { } - - void run() - { - std::stringstream d_s; - d_s << "one=\"one\" two=two" << std::endl; - d_s << "three = \\" << std::endl; - d_s << "three four = \\" << std::endl; - d_s << "\"four\" # one=three" << std::endl; - d_s << "five=five # six=six" << std::endl; - KeyValueConfigFile ff(d_s, { kvcfo_allow_inline_comments, kvcfo_allow_multiple_assigns_per_line, kvcfo_disallow_space_inside_unquoted_values }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(std::distance(ff.begin(), ff.end()), 5); - TEST_CHECK_EQUAL(ff.get("one"), "one"); - TEST_CHECK_EQUAL(ff.get("two"), "two"); - TEST_CHECK_EQUAL(ff.get("three"), "three"); - TEST_CHECK_EQUAL(ff.get("four"), "four"); - TEST_CHECK_EQUAL(ff.get("five"), "five"); - } - } test_key_value_config_file_multiple_assigns; - - struct KeyValueConfigFileSectionsTest : TestCase - { - KeyValueConfigFileSectionsTest() : TestCase("key value config sections") { } - - void run() - { - std::stringstream d_s; - d_s << "a = b" << std::endl; - d_s << "c = d" << std::endl; - d_s << "[foo]" << std::endl; - d_s << "a = c" << std::endl; - d_s << "[bar bar]" << std::endl; - d_s << "a = d" << std::endl; - d_s << "[var]" << std::endl; - d_s << "b = x" << std::endl; - d_s << "a = ${a} ${b} ${c}" << std::endl; - KeyValueConfigFile ff(d_s, { kvcfo_allow_sections }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(std::distance(ff.begin(), ff.end()), 6); - TEST_CHECK_EQUAL(ff.get("a"), "b"); - TEST_CHECK_EQUAL(ff.get("c"), "d"); - TEST_CHECK_EQUAL(ff.get("foo/a"), "c"); - TEST_CHECK_EQUAL(ff.get("bar/bar/a"), "d"); - TEST_CHECK_EQUAL(ff.get("var/b"), "x"); - TEST_CHECK_EQUAL(ff.get("var/a"), "b x d"); - } - } test_key_value_config_file_sections; - - struct KeyValueConfigFileFancyAssignsTest : TestCase - { - KeyValueConfigFileFancyAssignsTest() : TestCase("key value config fancy assigns") { } - - void run() - { - std::stringstream d_s; - d_s << "a = A" << std::endl; - d_s << "a ?= X" << std::endl; - d_s << "b ?= B" << std::endl; - KeyValueConfigFile ff(d_s, { kvcfo_allow_sections, kvcfo_allow_fancy_assigns }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(std::distance(ff.begin(), ff.end()), 2); - TEST_CHECK_EQUAL(ff.get("a"), "A"); - TEST_CHECK_EQUAL(ff.get("b"), "B"); - } - } test_key_value_config_file_fancy_assigns; - - struct KeyValueConfigFileEnvVarsTest : TestCase + std::stringstream s; + s << "one" << std::endl; + s << " two \t " << std::endl; + s << " \t " << std::endl; + s << "" << std::endl; + s << "three" << std::endl; + s << "# blah" << std::endl; + s << " # blah" << std::endl; + s << "#" << std::endl; + s << " # \t " << std::endl; + s << "four four" << std::endl; + s << "five \\" << std::endl; + s << "six" << std::endl; + s << "seven\\" << std::endl; + s << "eight" << std::endl; + s << "nine # ten" << std::endl; + + LineConfigFile f(s, { }); + ASSERT_EQ(7, std::distance(f.begin(), f.end())); + std::vector<std::string> lines; + std::copy(f.begin(), f.end(), std::back_inserter(lines)); + EXPECT_EQ("one", lines.at(0)); + EXPECT_EQ("two", lines.at(1)); + EXPECT_EQ("three", lines.at(2)); + EXPECT_EQ("four four", lines.at(3)); + EXPECT_EQ("five six", lines.at(4)); + EXPECT_EQ("seveneight", lines.at(5)); + EXPECT_EQ("nine # ten", lines.at(6)); + + s.clear(); + s.seekg(0, std::ios::beg); + + LineConfigFile g(s, { lcfo_disallow_comments, lcfo_preserve_whitespace, lcfo_no_skip_blank_lines }); + ASSERT_EQ(13, std::distance(g.begin(), g.end())); + lines.clear(); + std::copy(g.begin(), g.end(), std::back_inserter(lines)); + EXPECT_EQ("one", lines.at(0)); + EXPECT_EQ(" two \t ", lines.at(1)); + EXPECT_EQ(" \t ", lines.at(2)); + EXPECT_EQ("", lines.at(3)); + EXPECT_EQ("three", lines.at(4)); + EXPECT_EQ("# blah", lines.at(5)); + EXPECT_EQ(" # blah", lines.at(6)); + EXPECT_EQ("#", lines.at(7)); + EXPECT_EQ(" # \t ", lines.at(8)); + EXPECT_EQ("four four", lines.at(9)); + EXPECT_EQ("five six", lines.at(10)); + EXPECT_EQ("seveneight", lines.at(11)); + EXPECT_EQ("nine # ten", lines.at(12)); + + s.clear(); + s.seekg(0, std::ios::beg); + + LineConfigFile h(s, { lcfo_allow_inline_comments }); + ASSERT_EQ(7, std::distance(f.begin(), f.end())); + lines.clear(); + std::copy(h.begin(), h.end(), std::back_inserter(lines)); + EXPECT_EQ("one", lines.at(0)); + EXPECT_EQ("two", lines.at(1)); + EXPECT_EQ("three", lines.at(2)); + EXPECT_EQ("four four", lines.at(3)); + EXPECT_EQ("five six", lines.at(4)); + EXPECT_EQ("seveneight", lines.at(5)); + EXPECT_EQ("nine", lines.at(6)); +} + +TEST(LineConfigFile, Open) +{ + FSPath ff("config_file_TEST_dir/config_file"); + EXPECT_TRUE(ff.stat().is_regular_file()); + LineConfigFile f(ff, { }); + ASSERT_EQ(1, std::distance(f.begin(), f.end())); + EXPECT_EQ("I am a fish.", *f.begin()); + + FSPath ff2("config_file_TEST_dir/not_a_config_file"); + EXPECT_TRUE(! ff2.stat().exists()); + LineConfigFile * f2(0); + EXPECT_THROW(f2 = new LineConfigFile(ff2, { }), ConfigFileError); + + if (0 != geteuid()) { - KeyValueConfigFileEnvVarsTest() : TestCase("key value config env vars") { } - - void run() - { - ::setenv("A_VAR", "AAAARGH", 1); - ::setenv("B_VAR", "BRRRRGH", 1); - - std::stringstream d_s; - d_s << "a = ${ENV{A_VAR}}" << std::endl; - d_s << "b = ${ENV{B_VAR}}" << std::endl; - KeyValueConfigFile ff(d_s, { kvcfo_allow_env }, - &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); - - TEST_CHECK_EQUAL(std::distance(ff.begin(), ff.end()), 2); - TEST_CHECK_EQUAL(ff.get("a"), "AAAARGH"); - TEST_CHECK_EQUAL(ff.get("b"), "BRRRRGH"); - } - } test_key_value_config_file_env_vars; + FSPath ff3("config_file_TEST_dir/unreadable_file"); + EXPECT_TRUE(ff3.stat().is_regular_file()); + LineConfigFile * f3(0); + EXPECT_THROW(f3 = new LineConfigFile(ff3, { }), ConfigFileError); + } +} + +TEST(KeyValueConfigFile, Works) +{ + std::stringstream s; + s << "one=first" << std::endl; + s << "two = second" << std::endl; + s << "three=" << std::endl; + s << "four = \"fourth\" " << std::endl; + s << "five = ''" << std::endl; + KeyValueConfigFile ff(s, { kvcfo_preserve_whitespace }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + EXPECT_EQ("first", ff.get("one")); + EXPECT_EQ("second", ff.get("two")); + EXPECT_EQ("", ff.get("three")); + EXPECT_EQ("fourth ", ff.get("four")); + EXPECT_EQ("", ff.get("five")); + EXPECT_EQ("", ff.get("six")); +} + +TEST(KeyValueConfigFile, Continuations) +{ + std::stringstream s; + s << "one='first" << std::endl; + s << " first " << std::endl; + s << "first'" << std::endl; + KeyValueConfigFile ff(s, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + EXPECT_EQ("first\n first \nfirst", ff.get("one")); +} + +TEST(KeyValueConfigFile, Variables) +{ + std::stringstream s; + s << "x=foo" << std::endl; + s << "y = \"${x}\\\\${y}\\$${z}\"" << std::endl; + s << "z = $x$y$z" << std::endl; + KeyValueConfigFile ff(s, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + EXPECT_EQ("foo", ff.get("x")); + EXPECT_EQ("foo\\$", ff.get("y")); + EXPECT_EQ("foofoo\\$", ff.get("z")); + + std::stringstream t; + std::shared_ptr<Map<std::string, std::string> > t_defs(std::make_shared<Map<std::string, std::string>>()); + t_defs->insert("a", "moo"); + t_defs->insert("d", "bar"); + t_defs->insert("e", "baz"); + t << "a=foo" << std::endl; + t << "b=$a" << std::endl; + t << "c=$d" << std::endl; + t << "d=$d" << std::endl; + t << "f = " << std::endl; + t << "g = foo \\" << std::endl; + t << " bar" << std::endl; + KeyValueConfigFile fg(t, { }, + std::bind(&predefined, t_defs, std::placeholders::_1, std::placeholders::_2), + &KeyValueConfigFile::no_transformation); + + EXPECT_EQ("foo", fg.get("a")); + EXPECT_EQ("foo", fg.get("b")); + EXPECT_EQ("bar", fg.get("c")); + EXPECT_EQ("bar", fg.get("d")); + EXPECT_EQ("baz", fg.get("e")); + EXPECT_EQ("", fg.get("f")); + EXPECT_EQ("foo bar", fg.get("g")); +} + +TEST(KeyValueConfigFile, Defaults) +{ + setenv("moo", "cow", 1); + + std::stringstream d_s; + d_s << "foo=oink" << std::endl; + std::shared_ptr<KeyValueConfigFile> d_ff(std::make_shared<KeyValueConfigFile>(d_s, KeyValueConfigFileOptions(), + &predefined_from_env, + &KeyValueConfigFile::no_transformation)); + + std::stringstream s; + s << "x=${foo}" << std::endl; + s << "y=${moo}" << std::endl; + KeyValueConfigFile ff(s, { }, + std::bind(&predefined_from_config_file, std::cref(*d_ff), std::placeholders::_1, std::placeholders::_2), + &KeyValueConfigFile::no_transformation); + + EXPECT_EQ("oink", ff.get("x")); + EXPECT_EQ("cow", ff.get("y")); +} + +TEST(KeyValueConfigFile, Source) +{ + std::stringstream d_s; + d_s << "six=\"llama\"" << std::endl; + d_s << "seven=\"spider\"" << std::endl; + d_s << "source config_file_TEST_dir/sourced_one" << std::endl; + d_s << "eight=\"octopus\"" << std::endl; + KeyValueConfigFile ff(d_s, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + EXPECT_EQ("cat", ff.get("one")); + EXPECT_EQ("dog", ff.get("two")); + EXPECT_EQ("koala", ff.get("three")); + EXPECT_EQ("sheep", ff.get("four")); + EXPECT_EQ("rabbit", ff.get("five")); + EXPECT_EQ("llama", ff.get("six")); + EXPECT_EQ("spider", ff.get("seven")); + EXPECT_EQ("octopus", ff.get("eight")); +} + +TEST(KeyValueConfigFile, IgnoreExport) +{ + std::stringstream d_s; + d_s << "export \t foo = \"xyzzy\"" << std::endl; + d_s << "export bar='plugh'" << std::endl; + d_s << "baz = \"plover\"" << std::endl; + d_s << "exportfoo = \"exportxyzzy\"" << std::endl; + KeyValueConfigFile ff(d_s, { kvcfo_ignore_export }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + EXPECT_EQ("xyzzy", ff.get("foo")); + EXPECT_EQ("plugh", ff.get("bar")); + EXPECT_EQ("plover", ff.get("baz")); + EXPECT_EQ("exportxyzzy", ff.get("exportfoo")); + + std::stringstream d_s2; + d_s2 << "export = 42" << std::endl; + KeyValueConfigFile ff2(d_s2, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + EXPECT_EQ("42", ff2.get("export")); +} + +TEST(KeyValueConfigFile, Errors) +{ + std::stringstream s1; + s1 << "x='" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s1, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); + + std::stringstream s2; + s2 << "x='moo\"" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s2, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); + + std::stringstream s3; + s3 << "x=${foo" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s3, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); + + std::stringstream s4; + s4 << "x=$~" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s4, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); + + std::stringstream s5; + s5 << "x=abc\\" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s5, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); + + std::stringstream s6; + s6 << "x=$" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s6, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); + + std::stringstream s7; + s7 << "x=blah \\" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s7, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); + + std::stringstream s8; + s8 << "x=blah \\" << std::endl << "# foo" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s8, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); + + std::stringstream s9; + s9 << "x='blah" << std::endl << "blah" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s9, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); + + std::stringstream s10; + s10 << "export x=blah" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s10, { }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); + + std::stringstream s11; + s11 << "export x = blah" << std::endl; + EXPECT_THROW(KeyValueConfigFile ff(s11, { kvcfo_ignore_export, kvcfo_disallow_space_around_equals }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation), ConfigurationError); +} + +TEST(LineConfigFile, InlineComments) +{ + std::stringstream s; + s << "one # moo" << std::endl; + s << "tw\\" << std::endl; + s << "o # moo" << std::endl; + s << "" << std::endl; + s << "three #" << std::endl; + s << "#" << std::endl; + s << "four" << std::endl; + s << "five # moo" << std::endl; + + LineConfigFile f(s, { lcfo_allow_inline_comments }); + ASSERT_EQ(5, std::distance(f.begin(), f.end())); + std::vector<std::string> lines; + std::copy(f.begin(), f.end(), std::back_inserter(lines)); + EXPECT_EQ("one", lines.at(0)); + EXPECT_EQ("two", lines.at(1)); + EXPECT_EQ("three", lines.at(2)); + EXPECT_EQ("four", lines.at(3)); + EXPECT_EQ("five", lines.at(4)); +} + +TEST(KeyValueConfigFile, InlineComments) +{ + std::stringstream d_s; + d_s << "one=\"one\" # foo" << std::endl; + d_s << "two=two # bar" << std::endl; + d_s << "three = \\" << std::endl; + d_s << "three # bar" << std::endl; + d_s << "four = four # foo" << std::endl; + d_s << "five = five # moo" << std::endl; + KeyValueConfigFile ff(d_s, { kvcfo_allow_inline_comments }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + ASSERT_EQ(5, std::distance(ff.begin(), ff.end())); + EXPECT_EQ("one", ff.get("one")); + EXPECT_EQ("two", ff.get("two")); + EXPECT_EQ("three", ff.get("three")); + EXPECT_EQ("four", ff.get("four")); + EXPECT_EQ("five", ff.get("five")); +} + +TEST(KeyValueConfigFile, MultipleAssigns) +{ + std::stringstream d_s; + d_s << "one=\"one\" two=two" << std::endl; + d_s << "three = \\" << std::endl; + d_s << "three four = \\" << std::endl; + d_s << "\"four\" # one=three" << std::endl; + d_s << "five=five # six=six" << std::endl; + KeyValueConfigFile ff(d_s, { kvcfo_allow_inline_comments, kvcfo_allow_multiple_assigns_per_line, kvcfo_disallow_space_inside_unquoted_values }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + ASSERT_EQ(5, std::distance(ff.begin(), ff.end())); + EXPECT_EQ("one", ff.get("one")); + EXPECT_EQ("two", ff.get("two")); + EXPECT_EQ("three", ff.get("three")); + EXPECT_EQ("four", ff.get("four")); + EXPECT_EQ("five", ff.get("five")); +} + +TEST(KeyValueConfigFile, Sections) +{ + std::stringstream d_s; + d_s << "a = b" << std::endl; + d_s << "c = d" << std::endl; + d_s << "[foo]" << std::endl; + d_s << "a = c" << std::endl; + d_s << "[bar bar]" << std::endl; + d_s << "a = d" << std::endl; + d_s << "[var]" << std::endl; + d_s << "b = x" << std::endl; + d_s << "a = ${a} ${b} ${c}" << std::endl; + KeyValueConfigFile ff(d_s, { kvcfo_allow_sections }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + ASSERT_EQ(6, std::distance(ff.begin(), ff.end())); + EXPECT_EQ("b", ff.get("a")); + EXPECT_EQ("d", ff.get("c")); + EXPECT_EQ("c", ff.get("foo/a")); + EXPECT_EQ("d", ff.get("bar/bar/a")); + EXPECT_EQ("x", ff.get("var/b")); + EXPECT_EQ("b x d", ff.get("var/a")); +} + +TEST(KeyValueConfigFile, FancyAssigns) +{ + std::stringstream d_s; + d_s << "a = A" << std::endl; + d_s << "a ?= X" << std::endl; + d_s << "b ?= B" << std::endl; + KeyValueConfigFile ff(d_s, { kvcfo_allow_sections, kvcfo_allow_fancy_assigns }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + ASSERT_EQ(2, std::distance(ff.begin(), ff.end())); + EXPECT_EQ("A", ff.get("a")); + EXPECT_EQ("B", ff.get("b")); +} + +TEST(KeyValueConfigFile, EnvVars) +{ + ::setenv("A_VAR", "AAAARGH", 1); + ::setenv("B_VAR", "BRRRRGH", 1); + + std::stringstream d_s; + d_s << "a = ${ENV{A_VAR}}" << std::endl; + d_s << "b = ${ENV{B_VAR}}" << std::endl; + KeyValueConfigFile ff(d_s, { kvcfo_allow_env }, + &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation); + + ASSERT_EQ(2, std::distance(ff.begin(), ff.end())); + EXPECT_EQ("AAAARGH", ff.get("a")); + EXPECT_EQ("BRRRRGH", ff.get("b")); } diff --git a/paludis/util/files.m4 b/paludis/util/files.m4 index 31c274344..1dd08367e 100644 --- a/paludis/util/files.m4 +++ b/paludis/util/files.m4 @@ -17,7 +17,7 @@ add(`byte_swap', `hh', `gtest') add(`channel', `hh', `cc') add(`checked_delete', `hh') add(`clone', `hh', `impl') -add(`config_file', `hh', `cc', `fwd', `se', `test', `testscript') +add(`config_file', `hh', `cc', `fwd', `se', `gtest', `testscript') add(`condition_variable', `hh', `cc', `gtest') add(`cookie', `hh', `cc') add(`create_iterator', `hh', `fwd', `impl', `gtest') |