Path: blob/main/contrib/kyua/utils/config/parser_test.cpp
48081 views
// Copyright 2012 The Kyua Authors.1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are5// met:6//7// * Redistributions of source code must retain the above copyright8// notice, this list of conditions and the following disclaimer.9// * Redistributions in binary form must reproduce the above copyright10// notice, this list of conditions and the following disclaimer in the11// documentation and/or other materials provided with the distribution.12// * Neither the name of Google Inc. nor the names of its contributors13// may be used to endorse or promote products derived from this software14// without specific prior written permission.15//16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2728#include "utils/config/parser.hpp"2930#include <stdexcept>3132#include <atf-c++.hpp>3334#include "utils/config/exceptions.hpp"35#include "utils/config/parser.hpp"36#include "utils/config/tree.ipp"37#include "utils/format/macros.hpp"38#include "utils/fs/path.hpp"3940namespace config = utils::config;41namespace fs = utils::fs;424344namespace {454647/// Implementation of a parser for testing purposes.48class mock_parser : public config::parser {49/// Initializes the tree keys before reading the file.50///51/// \param [in,out] tree The tree in which to define the key structure.52/// \param syntax_version The version of the file format as specified in the53/// configuration file.54void55setup(config::tree& tree, const int syntax_version)56{57if (syntax_version == 1) {58// Do nothing on config_tree.59} else if (syntax_version == 2) {60tree.define< config::string_node >("top_string");61tree.define< config::int_node >("inner.int");62tree.define_dynamic("inner.dynamic");63} else {64throw std::runtime_error(F("Unknown syntax version %s") %65syntax_version);66}67}6869public:70/// Initializes a parser.71///72/// \param tree The mock config tree to parse.73mock_parser(config::tree& tree) :74config::parser(tree)75{76}77};787980} // anonymous namespace818283ATF_TEST_CASE_WITHOUT_HEAD(no_keys__ok);84ATF_TEST_CASE_BODY(no_keys__ok)85{86atf::utils::create_file(87"output.lua",88"syntax(2)\n"89"local foo = 'value'\n");9091config::tree tree;92mock_parser(tree).parse(fs::path("output.lua"));93ATF_REQUIRE_THROW(config::unknown_key_error,94tree.lookup< config::string_node >("foo"));95}969798ATF_TEST_CASE_WITHOUT_HEAD(no_keys__unknown_key);99ATF_TEST_CASE_BODY(no_keys__unknown_key)100{101atf::utils::create_file(102"output.lua",103"syntax(2)\n"104"foo = 'value'\n");105106config::tree tree;107ATF_REQUIRE_THROW_RE(config::syntax_error, "foo",108mock_parser(tree).parse(fs::path("output.lua")));109}110111112ATF_TEST_CASE_WITHOUT_HEAD(some_keys__ok);113ATF_TEST_CASE_BODY(some_keys__ok)114{115atf::utils::create_file(116"output.lua",117"syntax(2)\n"118"top_string = 'foo'\n"119"inner.int = 12345\n"120"inner.dynamic.foo = 78\n"121"inner.dynamic.bar = 'some text'\n");122123config::tree tree;124mock_parser(tree).parse(fs::path("output.lua"));125ATF_REQUIRE_EQ("foo", tree.lookup< config::string_node >("top_string"));126ATF_REQUIRE_EQ(12345, tree.lookup< config::int_node >("inner.int"));127ATF_REQUIRE_EQ("78",128tree.lookup< config::string_node >("inner.dynamic.foo"));129ATF_REQUIRE_EQ("some text",130tree.lookup< config::string_node >("inner.dynamic.bar"));131}132133134ATF_TEST_CASE_WITHOUT_HEAD(some_keys__not_strict);135ATF_TEST_CASE_BODY(some_keys__not_strict)136{137atf::utils::create_file(138"output.lua",139"syntax(2)\n"140"top_string = 'foo'\n"141"unknown_string = 'bar'\n"142"top_string = 'baz'\n");143144config::tree tree(false);145mock_parser(tree).parse(fs::path("output.lua"));146ATF_REQUIRE_EQ("baz", tree.lookup< config::string_node >("top_string"));147ATF_REQUIRE(!tree.is_set("unknown_string"));148}149150151ATF_TEST_CASE_WITHOUT_HEAD(some_keys__unknown_key);152ATF_TEST_CASE_BODY(some_keys__unknown_key)153{154atf::utils::create_file(155"output.lua",156"syntax(2)\n"157"top_string2 = 'foo'\n");158config::tree tree1;159ATF_REQUIRE_THROW_RE(config::syntax_error,160"Unknown configuration property 'top_string2'",161mock_parser(tree1).parse(fs::path("output.lua")));162163atf::utils::create_file(164"output.lua",165"syntax(2)\n"166"inner.int2 = 12345\n");167config::tree tree2;168ATF_REQUIRE_THROW_RE(config::syntax_error,169"Unknown configuration property 'inner.int2'",170mock_parser(tree2).parse(fs::path("output.lua")));171}172173174ATF_TEST_CASE_WITHOUT_HEAD(invalid_syntax);175ATF_TEST_CASE_BODY(invalid_syntax)176{177config::tree tree;178179atf::utils::create_file("output.lua", "syntax(56)\n");180ATF_REQUIRE_THROW_RE(config::syntax_error,181"Unknown syntax version 56",182mock_parser(tree).parse(fs::path("output.lua")));183}184185186ATF_TEST_CASE_WITHOUT_HEAD(syntax_deprecated_format);187ATF_TEST_CASE_BODY(syntax_deprecated_format)188{189config::tree tree;190191atf::utils::create_file("output.lua", "syntax('config', 1)\n");192(void)mock_parser(tree).parse(fs::path("output.lua"));193194atf::utils::create_file("output.lua", "syntax('foo', 1)\n");195ATF_REQUIRE_THROW_RE(config::syntax_error, "must be 'config'",196mock_parser(tree).parse(fs::path("output.lua")));197198atf::utils::create_file("output.lua", "syntax('config', 2)\n");199ATF_REQUIRE_THROW_RE(config::syntax_error, "only takes one argument",200mock_parser(tree).parse(fs::path("output.lua")));201}202203204ATF_TEST_CASE_WITHOUT_HEAD(syntax_not_called);205ATF_TEST_CASE_BODY(syntax_not_called)206{207config::tree tree;208tree.define< config::int_node >("var");209210atf::utils::create_file("output.lua", "var = 3\n");211ATF_REQUIRE_THROW_RE(config::syntax_error, "No syntax defined",212mock_parser(tree).parse(fs::path("output.lua")));213214ATF_REQUIRE(!tree.is_set("var"));215}216217218ATF_TEST_CASE_WITHOUT_HEAD(syntax_called_more_than_once);219ATF_TEST_CASE_BODY(syntax_called_more_than_once)220{221config::tree tree;222tree.define< config::int_node >("var");223224atf::utils::create_file(225"output.lua",226"syntax(2)\n"227"var = 3\n"228"syntax(2)\n"229"var = 5\n");230ATF_REQUIRE_THROW_RE(config::syntax_error,231"syntax\\(\\) can only be called once",232mock_parser(tree).parse(fs::path("output.lua")));233234ATF_REQUIRE_EQ(3, tree.lookup< config::int_node >("var"));235}236237238ATF_INIT_TEST_CASES(tcs)239{240ATF_ADD_TEST_CASE(tcs, no_keys__ok);241ATF_ADD_TEST_CASE(tcs, no_keys__unknown_key);242243ATF_ADD_TEST_CASE(tcs, some_keys__ok);244ATF_ADD_TEST_CASE(tcs, some_keys__not_strict);245ATF_ADD_TEST_CASE(tcs, some_keys__unknown_key);246247ATF_ADD_TEST_CASE(tcs, invalid_syntax);248ATF_ADD_TEST_CASE(tcs, syntax_deprecated_format);249ATF_ADD_TEST_CASE(tcs, syntax_not_called);250ATF_ADD_TEST_CASE(tcs, syntax_called_more_than_once);251}252253254