Path: blob/main/contrib/kyua/utils/config/tree_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/tree.ipp"2930#include <atf-c++.hpp>3132#include "utils/config/nodes.ipp"33#include "utils/format/macros.hpp"34#include "utils/text/operations.ipp"3536namespace config = utils::config;37namespace text = utils::text;383940namespace {414243/// Simple wrapper around an integer value without default constructors.44///45/// The purpose of this type is to have a simple class without default46/// constructors to validate that we can use it as a leaf of a tree.47class int_wrapper {48/// The wrapped integer value.49int _value;5051public:52/// Constructs a new wrapped integer.53///54/// \param value_ The value to store in the object.55explicit int_wrapper(int value_) :56_value(value_)57{58}5960/// \return The integer value stored by the object.61int62value(void) const63{64return _value;65}66};676869/// Custom tree leaf type for an object without defualt constructors.70class wrapped_int_node : public config::typed_leaf_node< int_wrapper > {71public:72/// Copies the node.73///74/// \return A dynamically-allocated node.75virtual base_node*76deep_copy(void) const77{78std::unique_ptr< wrapped_int_node > new_node(new wrapped_int_node());79new_node->_value = _value;80return new_node.release();81}8283/// Pushes the node's value onto the Lua stack.84///85/// \param state The Lua state onto which to push the value.86void87push_lua(lutok::state& state) const88{89state.push_integer(90config::typed_leaf_node< int_wrapper >::value().value());91}9293/// Sets the value of the node from an entry in the Lua stack.94///95/// \param state The Lua state from which to get the value.96/// \param value_index The stack index in which the value resides.97void98set_lua(lutok::state& state, const int value_index)99{100ATF_REQUIRE(state.is_number(value_index));101int_wrapper new_value(state.to_integer(value_index));102config::typed_leaf_node< int_wrapper >::set(new_value);103}104105/// Sets the value of the node from a raw string representation.106///107/// \param raw_value The value to set the node to.108void109set_string(const std::string& raw_value)110{111int_wrapper new_value(text::to_type< int >(raw_value));112config::typed_leaf_node< int_wrapper >::set(new_value);113}114115/// Converts the contents of the node to a string.116///117/// \return A string representation of the value held by the node.118std::string119to_string(void) const120{121return F("%s") %122config::typed_leaf_node< int_wrapper >::value().value();123}124};125126127} // anonymous namespace128129130ATF_TEST_CASE_WITHOUT_HEAD(define_set_lookup__one_level);131ATF_TEST_CASE_BODY(define_set_lookup__one_level)132{133config::tree tree;134135tree.define< config::int_node >("var1");136tree.define< config::string_node >("var2");137tree.define< config::bool_node >("var3");138139tree.set< config::int_node >("var1", 42);140tree.set< config::string_node >("var2", "hello");141tree.set< config::bool_node >("var3", false);142143ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("var1"));144ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("var2"));145ATF_REQUIRE(!tree.lookup< config::bool_node >("var3"));146}147148149ATF_TEST_CASE_WITHOUT_HEAD(define_set_lookup__multiple_levels);150ATF_TEST_CASE_BODY(define_set_lookup__multiple_levels)151{152config::tree tree;153154tree.define< config::int_node >("foo.bar.1");155tree.define< config::string_node >("foo.bar.2");156tree.define< config::bool_node >("foo.3");157tree.define_dynamic("sub.tree");158159tree.set< config::int_node >("foo.bar.1", 42);160tree.set< config::string_node >("foo.bar.2", "hello");161tree.set< config::bool_node >("foo.3", true);162tree.set< config::string_node >("sub.tree.1", "bye");163tree.set< config::int_node >("sub.tree.2", 4);164tree.set< config::int_node >("sub.tree.3.4", 123);165166ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("foo.bar.1"));167ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("foo.bar.2"));168ATF_REQUIRE(tree.lookup< config::bool_node >("foo.3"));169ATF_REQUIRE_EQ(4, tree.lookup< config::int_node >("sub.tree.2"));170ATF_REQUIRE_EQ(123, tree.lookup< config::int_node >("sub.tree.3.4"));171}172173174ATF_TEST_CASE_WITHOUT_HEAD(deep_copy__empty);175ATF_TEST_CASE_BODY(deep_copy__empty)176{177config::tree tree1;178config::tree tree2 = tree1.deep_copy();179180tree1.define< config::bool_node >("var1");181// This would crash if the copy shared the internal data.182tree2.define< config::int_node >("var1");183}184185186ATF_TEST_CASE_WITHOUT_HEAD(deep_copy__some);187ATF_TEST_CASE_BODY(deep_copy__some)188{189config::tree tree1;190tree1.define< config::bool_node >("this.is.a.var");191tree1.set< config::bool_node >("this.is.a.var", true);192tree1.define< config::int_node >("this.is.another.var");193tree1.set< config::int_node >("this.is.another.var", 34);194tree1.define< config::int_node >("and.another");195tree1.set< config::int_node >("and.another", 123);196197config::tree tree2 = tree1.deep_copy();198tree2.set< config::bool_node >("this.is.a.var", false);199tree2.set< config::int_node >("this.is.another.var", 43);200201ATF_REQUIRE( tree1.lookup< config::bool_node >("this.is.a.var"));202ATF_REQUIRE(!tree2.lookup< config::bool_node >("this.is.a.var"));203204ATF_REQUIRE_EQ(34, tree1.lookup< config::int_node >("this.is.another.var"));205ATF_REQUIRE_EQ(43, tree2.lookup< config::int_node >("this.is.another.var"));206207ATF_REQUIRE_EQ(123, tree1.lookup< config::int_node >("and.another"));208ATF_REQUIRE_EQ(123, tree2.lookup< config::int_node >("and.another"));209}210211212ATF_TEST_CASE_WITHOUT_HEAD(combine__empty);213ATF_TEST_CASE_BODY(combine__empty)214{215const config::tree t1, t2;216const config::tree combined = t1.combine(t2);217218const config::tree expected;219ATF_REQUIRE(expected == combined);220}221222223static void224init_tree_for_combine_test(config::tree& tree)225{226tree.define< config::int_node >("int-node");227tree.define< config::string_node >("string-node");228tree.define< config::int_node >("unused.node");229tree.define< config::int_node >("deeper.int.node");230tree.define_dynamic("deeper.dynamic");231}232233234ATF_TEST_CASE_WITHOUT_HEAD(combine__same_layout__no_overrides);235ATF_TEST_CASE_BODY(combine__same_layout__no_overrides)236{237config::tree t1, t2;238init_tree_for_combine_test(t1);239init_tree_for_combine_test(t2);240t1.set< config::int_node >("int-node", 3);241t1.set< config::string_node >("string-node", "foo");242t1.set< config::int_node >("deeper.int.node", 15);243t1.set_string("deeper.dynamic.first", "value1");244t1.set_string("deeper.dynamic.second", "value2");245const config::tree combined = t1.combine(t2);246247ATF_REQUIRE(t1 == combined);248}249250251ATF_TEST_CASE_WITHOUT_HEAD(combine__same_layout__no_base);252ATF_TEST_CASE_BODY(combine__same_layout__no_base)253{254config::tree t1, t2;255init_tree_for_combine_test(t1);256init_tree_for_combine_test(t2);257t2.set< config::int_node >("int-node", 3);258t2.set< config::string_node >("string-node", "foo");259t2.set< config::int_node >("deeper.int.node", 15);260t2.set_string("deeper.dynamic.first", "value1");261t2.set_string("deeper.dynamic.second", "value2");262const config::tree combined = t1.combine(t2);263264ATF_REQUIRE(t2 == combined);265}266267268ATF_TEST_CASE_WITHOUT_HEAD(combine__same_layout__mix);269ATF_TEST_CASE_BODY(combine__same_layout__mix)270{271config::tree t1, t2;272init_tree_for_combine_test(t1);273init_tree_for_combine_test(t2);274t1.set< config::int_node >("int-node", 3);275t2.set< config::int_node >("int-node", 5);276t1.set< config::string_node >("string-node", "foo");277t2.set< config::int_node >("deeper.int.node", 15);278t1.set_string("deeper.dynamic.first", "value1");279t1.set_string("deeper.dynamic.second", "value2.1");280t2.set_string("deeper.dynamic.second", "value2.2");281t2.set_string("deeper.dynamic.third", "value3");282const config::tree combined = t1.combine(t2);283284config::tree expected;285init_tree_for_combine_test(expected);286expected.set< config::int_node >("int-node", 5);287expected.set< config::string_node >("string-node", "foo");288expected.set< config::int_node >("deeper.int.node", 15);289expected.set_string("deeper.dynamic.first", "value1");290expected.set_string("deeper.dynamic.second", "value2.2");291expected.set_string("deeper.dynamic.third", "value3");292ATF_REQUIRE(expected == combined);293}294295296ATF_TEST_CASE_WITHOUT_HEAD(combine__different_layout);297ATF_TEST_CASE_BODY(combine__different_layout)298{299config::tree t1;300t1.define< config::int_node >("common.base1");301t1.define< config::int_node >("common.base2");302t1.define_dynamic("dynamic.base");303t1.define< config::int_node >("unset.base");304305config::tree t2;306t2.define< config::int_node >("common.base2");307t2.define< config::int_node >("common.base3");308t2.define_dynamic("dynamic.other");309t2.define< config::int_node >("unset.other");310311t1.set< config::int_node >("common.base1", 1);312t1.set< config::int_node >("common.base2", 2);313t1.set_string("dynamic.base.first", "foo");314t1.set_string("dynamic.base.second", "bar");315316t2.set< config::int_node >("common.base2", 4);317t2.set< config::int_node >("common.base3", 3);318t2.set_string("dynamic.other.first", "FOO");319t2.set_string("dynamic.other.second", "BAR");320321config::tree combined = t1.combine(t2);322323config::tree expected;324expected.define< config::int_node >("common.base1");325expected.define< config::int_node >("common.base2");326expected.define< config::int_node >("common.base3");327expected.define_dynamic("dynamic.base");328expected.define_dynamic("dynamic.other");329expected.define< config::int_node >("unset.base");330expected.define< config::int_node >("unset.other");331332expected.set< config::int_node >("common.base1", 1);333expected.set< config::int_node >("common.base2", 4);334expected.set< config::int_node >("common.base3", 3);335expected.set_string("dynamic.base.first", "foo");336expected.set_string("dynamic.base.second", "bar");337expected.set_string("dynamic.other.first", "FOO");338expected.set_string("dynamic.other.second", "BAR");339340ATF_REQUIRE(expected == combined);341342// The combined tree should have respected existing but unset nodes. Check343// that these calls do not crash.344combined.set< config::int_node >("unset.base", 5);345combined.set< config::int_node >("unset.other", 5);346}347348349ATF_TEST_CASE_WITHOUT_HEAD(combine__dynamic_wins);350ATF_TEST_CASE_BODY(combine__dynamic_wins)351{352config::tree t1;353t1.define< config::int_node >("inner.leaf1");354t1.set< config::int_node >("inner.leaf1", 3);355356config::tree t2;357t2.define_dynamic("inner");358t2.set_string("inner.leaf2", "4");359360config::tree combined = t1.combine(t2);361362config::tree expected;363expected.define_dynamic("inner");364expected.set_string("inner.leaf1", "3");365expected.set_string("inner.leaf2", "4");366367ATF_REQUIRE(expected == combined);368369// The combined inner node should have become dynamic so this call should370// not fail.371combined.set_string("inner.leaf3", "5");372}373374375ATF_TEST_CASE_WITHOUT_HEAD(combine__inner_leaf_mismatch);376ATF_TEST_CASE_BODY(combine__inner_leaf_mismatch)377{378config::tree t1;379t1.define< config::int_node >("top.foo.bar");380381config::tree t2;382t2.define< config::int_node >("top.foo");383384ATF_REQUIRE_THROW_RE(config::bad_combination_error,385"'top.foo' is an inner node in the base tree but a "386"leaf node in the overrides tree",387t1.combine(t2));388389ATF_REQUIRE_THROW_RE(config::bad_combination_error,390"'top.foo' is a leaf node in the base tree but an "391"inner node in the overrides tree",392t2.combine(t1));393}394395396ATF_TEST_CASE_WITHOUT_HEAD(lookup__invalid_key);397ATF_TEST_CASE_BODY(lookup__invalid_key)398{399config::tree tree;400401ATF_REQUIRE_THROW(config::invalid_key_error,402tree.lookup< config::int_node >("."));403}404405406ATF_TEST_CASE_WITHOUT_HEAD(lookup__unknown_key);407ATF_TEST_CASE_BODY(lookup__unknown_key)408{409config::tree tree;410411tree.define< config::int_node >("foo.bar");412tree.define< config::int_node >("a.b.c");413tree.define_dynamic("a.d");414tree.set< config::int_node >("a.b.c", 123);415tree.set< config::int_node >("a.d.100", 0);416417ATF_REQUIRE_THROW(config::unknown_key_error,418tree.lookup< config::int_node >("abc"));419420ATF_REQUIRE_THROW(config::unknown_key_error,421tree.lookup< config::int_node >("foo"));422ATF_REQUIRE_THROW(config::unknown_key_error,423tree.lookup< config::int_node >("foo.bar"));424ATF_REQUIRE_THROW(config::unknown_key_error,425tree.lookup< config::int_node >("foo.bar.baz"));426427ATF_REQUIRE_THROW(config::unknown_key_error,428tree.lookup< config::int_node >("a"));429ATF_REQUIRE_THROW(config::unknown_key_error,430tree.lookup< config::int_node >("a.b"));431ATF_REQUIRE_THROW(config::unknown_key_error,432tree.lookup< config::int_node >("a.c"));433(void)tree.lookup< config::int_node >("a.b.c");434ATF_REQUIRE_THROW(config::unknown_key_error,435tree.lookup< config::int_node >("a.b.c.d"));436ATF_REQUIRE_THROW(config::unknown_key_error,437tree.lookup< config::int_node >("a.d"));438(void)tree.lookup< config::int_node >("a.d.100");439ATF_REQUIRE_THROW(config::unknown_key_error,440tree.lookup< config::int_node >("a.d.101"));441ATF_REQUIRE_THROW(config::unknown_key_error,442tree.lookup< config::int_node >("a.d.100.3"));443ATF_REQUIRE_THROW(config::unknown_key_error,444tree.lookup< config::int_node >("a.d.e"));445}446447448ATF_TEST_CASE_WITHOUT_HEAD(is_set__one_level);449ATF_TEST_CASE_BODY(is_set__one_level)450{451config::tree tree;452453tree.define< config::int_node >("var1");454tree.define< config::string_node >("var2");455tree.define< config::bool_node >("var3");456457tree.set< config::int_node >("var1", 42);458tree.set< config::bool_node >("var3", false);459460ATF_REQUIRE( tree.is_set("var1"));461ATF_REQUIRE(!tree.is_set("var2"));462ATF_REQUIRE( tree.is_set("var3"));463}464465466ATF_TEST_CASE_WITHOUT_HEAD(is_set__multiple_levels);467ATF_TEST_CASE_BODY(is_set__multiple_levels)468{469config::tree tree;470471tree.define< config::int_node >("a.b.var1");472tree.define< config::string_node >("a.b.var2");473tree.define< config::bool_node >("e.var3");474475tree.set< config::int_node >("a.b.var1", 42);476tree.set< config::bool_node >("e.var3", false);477478ATF_REQUIRE(!tree.is_set("a"));479ATF_REQUIRE(!tree.is_set("a.b"));480ATF_REQUIRE( tree.is_set("a.b.var1"));481ATF_REQUIRE(!tree.is_set("a.b.var1.trailing"));482483ATF_REQUIRE(!tree.is_set("a"));484ATF_REQUIRE(!tree.is_set("a.b"));485ATF_REQUIRE(!tree.is_set("a.b.var2"));486ATF_REQUIRE(!tree.is_set("a.b.var2.trailing"));487488ATF_REQUIRE(!tree.is_set("e"));489ATF_REQUIRE( tree.is_set("e.var3"));490ATF_REQUIRE(!tree.is_set("e.var3.trailing"));491}492493494ATF_TEST_CASE_WITHOUT_HEAD(is_set__invalid_key);495ATF_TEST_CASE_BODY(is_set__invalid_key)496{497config::tree tree;498499ATF_REQUIRE_THROW(config::invalid_key_error, tree.is_set(".abc"));500}501502503ATF_TEST_CASE_WITHOUT_HEAD(set__invalid_key);504ATF_TEST_CASE_BODY(set__invalid_key)505{506config::tree tree;507508ATF_REQUIRE_THROW(config::invalid_key_error,509tree.set< config::int_node >("foo.", 54));510}511512513ATF_TEST_CASE_WITHOUT_HEAD(set__invalid_key_value);514ATF_TEST_CASE_BODY(set__invalid_key_value)515{516config::tree tree;517518tree.define< config::int_node >("foo.bar");519tree.define_dynamic("a.d");520521ATF_REQUIRE_THROW(config::invalid_key_value,522tree.set< config::int_node >("foo", 3));523ATF_REQUIRE_THROW(config::invalid_key_value,524tree.set< config::int_node >("a", -10));525}526527528ATF_TEST_CASE_WITHOUT_HEAD(set__unknown_key);529ATF_TEST_CASE_BODY(set__unknown_key)530{531config::tree tree;532533tree.define< config::int_node >("foo.bar");534tree.define< config::int_node >("a.b.c");535tree.define_dynamic("a.d");536tree.set< config::int_node >("a.b.c", 123);537tree.set< config::string_node >("a.d.3", "foo");538539ATF_REQUIRE_THROW(config::unknown_key_error,540tree.set< config::int_node >("abc", 2));541542tree.set< config::int_node >("foo.bar", 15);543ATF_REQUIRE_THROW(config::unknown_key_error,544tree.set< config::int_node >("foo.bar.baz", 0));545546ATF_REQUIRE_THROW(config::unknown_key_error,547tree.set< config::int_node >("a.c", 100));548tree.set< config::int_node >("a.b.c", -3);549ATF_REQUIRE_THROW(config::unknown_key_error,550tree.set< config::int_node >("a.b.c.d", 82));551tree.set< config::string_node >("a.d.3", "bar");552tree.set< config::string_node >("a.d.4", "bar");553ATF_REQUIRE_THROW(config::unknown_key_error,554tree.set< config::int_node >("a.d.4.5", 82));555tree.set< config::int_node >("a.d.5.6", 82);556}557558559ATF_TEST_CASE_WITHOUT_HEAD(set__unknown_key_not_strict);560ATF_TEST_CASE_BODY(set__unknown_key_not_strict)561{562config::tree tree(false);563564tree.define< config::int_node >("foo.bar");565tree.define< config::int_node >("a.b.c");566tree.define_dynamic("a.d");567tree.set< config::int_node >("a.b.c", 123);568tree.set< config::string_node >("a.d.3", "foo");569570tree.set< config::int_node >("abc", 2);571ATF_REQUIRE(!tree.is_set("abc"));572573tree.set< config::int_node >("foo.bar", 15);574tree.set< config::int_node >("foo.bar.baz", 0);575ATF_REQUIRE(!tree.is_set("foo.bar.baz"));576577tree.set< config::int_node >("a.c", 100);578ATF_REQUIRE(!tree.is_set("a.c"));579}580581582ATF_TEST_CASE_WITHOUT_HEAD(push_lua__ok);583ATF_TEST_CASE_BODY(push_lua__ok)584{585config::tree tree;586587tree.define< config::int_node >("top.integer");588tree.define< wrapped_int_node >("top.custom");589tree.define_dynamic("dynamic");590tree.set< config::int_node >("top.integer", 5);591tree.set< wrapped_int_node >("top.custom", int_wrapper(10));592tree.set_string("dynamic.first", "foo");593594lutok::state state;595tree.push_lua("top.integer", state);596tree.push_lua("top.custom", state);597tree.push_lua("dynamic.first", state);598ATF_REQUIRE(state.is_number(-3));599ATF_REQUIRE_EQ(5, state.to_integer(-3));600ATF_REQUIRE(state.is_number(-2));601ATF_REQUIRE_EQ(10, state.to_integer(-2));602ATF_REQUIRE(state.is_string(-1));603ATF_REQUIRE_EQ("foo", state.to_string(-1));604state.pop(3);605}606607608ATF_TEST_CASE_WITHOUT_HEAD(set_lua__ok);609ATF_TEST_CASE_BODY(set_lua__ok)610{611config::tree tree;612613tree.define< config::int_node >("top.integer");614tree.define< wrapped_int_node >("top.custom");615tree.define_dynamic("dynamic");616617{618lutok::state state;619state.push_integer(5);620state.push_integer(10);621state.push_string("foo");622tree.set_lua("top.integer", state, -3);623tree.set_lua("top.custom", state, -2);624tree.set_lua("dynamic.first", state, -1);625state.pop(3);626}627628ATF_REQUIRE_EQ(5, tree.lookup< config::int_node >("top.integer"));629ATF_REQUIRE_EQ(10, tree.lookup< wrapped_int_node >("top.custom").value());630ATF_REQUIRE_EQ("foo", tree.lookup< config::string_node >("dynamic.first"));631}632633634ATF_TEST_CASE_WITHOUT_HEAD(lookup_rw);635ATF_TEST_CASE_BODY(lookup_rw)636{637config::tree tree;638639tree.define< config::int_node >("var1");640tree.define< config::bool_node >("var3");641642tree.set< config::int_node >("var1", 42);643tree.set< config::bool_node >("var3", false);644645tree.lookup_rw< config::int_node >("var1") += 10;646ATF_REQUIRE_EQ(52, tree.lookup< config::int_node >("var1"));647ATF_REQUIRE(!tree.lookup< config::bool_node >("var3"));648}649650651ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__ok);652ATF_TEST_CASE_BODY(lookup_string__ok)653{654config::tree tree;655656tree.define< config::int_node >("var1");657tree.define< config::string_node >("b.var2");658tree.define< config::bool_node >("c.d.var3");659660tree.set< config::int_node >("var1", 42);661tree.set< config::string_node >("b.var2", "hello");662tree.set< config::bool_node >("c.d.var3", false);663664ATF_REQUIRE_EQ("42", tree.lookup_string("var1"));665ATF_REQUIRE_EQ("hello", tree.lookup_string("b.var2"));666ATF_REQUIRE_EQ("false", tree.lookup_string("c.d.var3"));667}668669670ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__invalid_key);671ATF_TEST_CASE_BODY(lookup_string__invalid_key)672{673config::tree tree;674675ATF_REQUIRE_THROW(config::invalid_key_error, tree.lookup_string(""));676}677678679ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__unknown_key);680ATF_TEST_CASE_BODY(lookup_string__unknown_key)681{682config::tree tree;683684tree.define< config::int_node >("a.b.c");685686ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup_string("a.b"));687ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup_string("a.b.c.d"));688}689690691ATF_TEST_CASE_WITHOUT_HEAD(set_string__ok);692ATF_TEST_CASE_BODY(set_string__ok)693{694config::tree tree;695696tree.define< config::int_node >("foo.bar.1");697tree.define< config::string_node >("foo.bar.2");698tree.define_dynamic("sub.tree");699700tree.set_string("foo.bar.1", "42");701tree.set_string("foo.bar.2", "hello");702tree.set_string("sub.tree.2", "15");703tree.set_string("sub.tree.3.4", "bye");704705ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("foo.bar.1"));706ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("foo.bar.2"));707ATF_REQUIRE_EQ("15", tree.lookup< config::string_node >("sub.tree.2"));708ATF_REQUIRE_EQ("bye", tree.lookup< config::string_node >("sub.tree.3.4"));709}710711712ATF_TEST_CASE_WITHOUT_HEAD(set_string__invalid_key);713ATF_TEST_CASE_BODY(set_string__invalid_key)714{715config::tree tree;716717ATF_REQUIRE_THROW(config::invalid_key_error, tree.set_string(".", "foo"));718}719720721ATF_TEST_CASE_WITHOUT_HEAD(set_string__invalid_key_value);722ATF_TEST_CASE_BODY(set_string__invalid_key_value)723{724config::tree tree;725726tree.define< config::int_node >("foo.bar");727728ATF_REQUIRE_THROW(config::invalid_key_value,729tree.set_string("foo", "abc"));730ATF_REQUIRE_THROW(config::invalid_key_value,731tree.set_string("foo.bar", " -3"));732ATF_REQUIRE_THROW(config::invalid_key_value,733tree.set_string("foo.bar", "3 "));734}735736737ATF_TEST_CASE_WITHOUT_HEAD(set_string__unknown_key);738ATF_TEST_CASE_BODY(set_string__unknown_key)739{740config::tree tree;741742tree.define< config::int_node >("foo.bar");743tree.define< config::int_node >("a.b.c");744tree.define_dynamic("a.d");745tree.set_string("a.b.c", "123");746tree.set_string("a.d.3", "foo");747748ATF_REQUIRE_THROW(config::unknown_key_error, tree.set_string("abc", "2"));749750tree.set_string("foo.bar", "15");751ATF_REQUIRE_THROW(config::unknown_key_error,752tree.set_string("foo.bar.baz", "0"));753754ATF_REQUIRE_THROW(config::unknown_key_error,755tree.set_string("a.c", "100"));756tree.set_string("a.b.c", "-3");757ATF_REQUIRE_THROW(config::unknown_key_error,758tree.set_string("a.b.c.d", "82"));759tree.set_string("a.d.3", "bar");760tree.set_string("a.d.4", "bar");761ATF_REQUIRE_THROW(config::unknown_key_error,762tree.set_string("a.d.4.5", "82"));763tree.set_string("a.d.5.6", "82");764}765766767ATF_TEST_CASE_WITHOUT_HEAD(set_string__unknown_key_not_strict);768ATF_TEST_CASE_BODY(set_string__unknown_key_not_strict)769{770config::tree tree(false);771772tree.define< config::int_node >("foo.bar");773tree.define< config::int_node >("a.b.c");774tree.define_dynamic("a.d");775tree.set_string("a.b.c", "123");776tree.set_string("a.d.3", "foo");777778tree.set_string("abc", "2");779ATF_REQUIRE(!tree.is_set("abc"));780781tree.set_string("foo.bar", "15");782tree.set_string("foo.bar.baz", "0");783ATF_REQUIRE(!tree.is_set("foo.bar.baz"));784785tree.set_string("a.c", "100");786ATF_REQUIRE(!tree.is_set("a.c"));787}788789790ATF_TEST_CASE_WITHOUT_HEAD(all_properties__none);791ATF_TEST_CASE_BODY(all_properties__none)792{793const config::tree tree;794ATF_REQUIRE(tree.all_properties().empty());795}796797798ATF_TEST_CASE_WITHOUT_HEAD(all_properties__all_set);799ATF_TEST_CASE_BODY(all_properties__all_set)800{801config::tree tree;802803tree.define< config::int_node >("plain");804tree.set< config::int_node >("plain", 1234);805806tree.define< config::int_node >("static.first");807tree.set< config::int_node >("static.first", -3);808tree.define< config::string_node >("static.second");809tree.set< config::string_node >("static.second", "some text");810811tree.define_dynamic("dynamic");812tree.set< config::string_node >("dynamic.first", "hello");813tree.set< config::string_node >("dynamic.second", "bye");814815config::properties_map exp_properties;816exp_properties["plain"] = "1234";817exp_properties["static.first"] = "-3";818exp_properties["static.second"] = "some text";819exp_properties["dynamic.first"] = "hello";820exp_properties["dynamic.second"] = "bye";821822const config::properties_map properties = tree.all_properties();823ATF_REQUIRE(exp_properties == properties);824}825826827ATF_TEST_CASE_WITHOUT_HEAD(all_properties__some_unset);828ATF_TEST_CASE_BODY(all_properties__some_unset)829{830config::tree tree;831832tree.define< config::int_node >("static.first");833tree.set< config::int_node >("static.first", -3);834tree.define< config::string_node >("static.second");835836tree.define_dynamic("dynamic");837838config::properties_map exp_properties;839exp_properties["static.first"] = "-3";840841const config::properties_map properties = tree.all_properties();842ATF_REQUIRE(exp_properties == properties);843}844845846ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__inner);847ATF_TEST_CASE_BODY(all_properties__subtree__inner)848{849config::tree tree;850851tree.define< config::int_node >("root.a.b.c.first");852tree.define< config::int_node >("root.a.b.c.second");853tree.define< config::int_node >("root.a.d.first");854855tree.set< config::int_node >("root.a.b.c.first", 1);856tree.set< config::int_node >("root.a.b.c.second", 2);857tree.set< config::int_node >("root.a.d.first", 3);858859{860config::properties_map exp_properties;861exp_properties["root.a.b.c.first"] = "1";862exp_properties["root.a.b.c.second"] = "2";863exp_properties["root.a.d.first"] = "3";864ATF_REQUIRE(exp_properties == tree.all_properties("root"));865ATF_REQUIRE(exp_properties == tree.all_properties("root.a"));866}867868{869config::properties_map exp_properties;870exp_properties["root.a.b.c.first"] = "1";871exp_properties["root.a.b.c.second"] = "2";872ATF_REQUIRE(exp_properties == tree.all_properties("root.a.b"));873ATF_REQUIRE(exp_properties == tree.all_properties("root.a.b.c"));874}875876{877config::properties_map exp_properties;878exp_properties["root.a.d.first"] = "3";879ATF_REQUIRE(exp_properties == tree.all_properties("root.a.d"));880}881}882883884ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__leaf);885ATF_TEST_CASE_BODY(all_properties__subtree__leaf)886{887config::tree tree;888889tree.define< config::int_node >("root.a.b.c.first");890tree.set< config::int_node >("root.a.b.c.first", 1);891ATF_REQUIRE_THROW_RE(config::value_error, "Cannot export.*leaf",892tree.all_properties("root.a.b.c.first"));893}894895896ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__strip_key);897ATF_TEST_CASE_BODY(all_properties__subtree__strip_key)898{899config::tree tree;900901tree.define< config::int_node >("root.a.b.c.first");902tree.define< config::int_node >("root.a.b.c.second");903tree.define< config::int_node >("root.a.d.first");904905tree.set< config::int_node >("root.a.b.c.first", 1);906tree.set< config::int_node >("root.a.b.c.second", 2);907tree.set< config::int_node >("root.a.d.first", 3);908909config::properties_map exp_properties;910exp_properties["b.c.first"] = "1";911exp_properties["b.c.second"] = "2";912exp_properties["d.first"] = "3";913ATF_REQUIRE(exp_properties == tree.all_properties("root.a", true));914}915916917ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__invalid_key);918ATF_TEST_CASE_BODY(all_properties__subtree__invalid_key)919{920config::tree tree;921922ATF_REQUIRE_THROW(config::invalid_key_error, tree.all_properties("."));923}924925926ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__unknown_key);927ATF_TEST_CASE_BODY(all_properties__subtree__unknown_key)928{929config::tree tree;930931tree.define< config::int_node >("root.a.b.c.first");932tree.set< config::int_node >("root.a.b.c.first", 1);933tree.define< config::int_node >("root.a.b.c.unset");934935ATF_REQUIRE_THROW(config::unknown_key_error,936tree.all_properties("root.a.b.c.first.foo"));937ATF_REQUIRE_THROW_RE(config::value_error, "Cannot export.*leaf",938tree.all_properties("root.a.b.c.unset"));939}940941942ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__empty);943ATF_TEST_CASE_BODY(operators_eq_and_ne__empty)944{945config::tree t1;946config::tree t2;947ATF_REQUIRE( t1 == t2);948ATF_REQUIRE(!(t1 != t2));949}950951952ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__shallow_copy);953ATF_TEST_CASE_BODY(operators_eq_and_ne__shallow_copy)954{955config::tree t1;956t1.define< config::int_node >("root.a.b.c.first");957t1.set< config::int_node >("root.a.b.c.first", 1);958config::tree t2 = t1;959ATF_REQUIRE( t1 == t2);960ATF_REQUIRE(!(t1 != t2));961}962963964ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__deep_copy);965ATF_TEST_CASE_BODY(operators_eq_and_ne__deep_copy)966{967config::tree t1;968t1.define< config::int_node >("root.a.b.c.first");969t1.set< config::int_node >("root.a.b.c.first", 1);970config::tree t2 = t1.deep_copy();971ATF_REQUIRE( t1 == t2);972ATF_REQUIRE(!(t1 != t2));973}974975976ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__some_contents);977ATF_TEST_CASE_BODY(operators_eq_and_ne__some_contents)978{979config::tree t1, t2;980981t1.define< config::int_node >("root.a.b.c.first");982t1.set< config::int_node >("root.a.b.c.first", 1);983ATF_REQUIRE(!(t1 == t2));984ATF_REQUIRE( t1 != t2);985986t2.define< config::int_node >("root.a.b.c.first");987t2.set< config::int_node >("root.a.b.c.first", 1);988ATF_REQUIRE( t1 == t2);989ATF_REQUIRE(!(t1 != t2));990991t1.set< config::int_node >("root.a.b.c.first", 2);992ATF_REQUIRE(!(t1 == t2));993ATF_REQUIRE( t1 != t2);994995t2.set< config::int_node >("root.a.b.c.first", 2);996ATF_REQUIRE( t1 == t2);997ATF_REQUIRE(!(t1 != t2));998999t1.define< config::string_node >("another.key");1000t1.set< config::string_node >("another.key", "some text");1001ATF_REQUIRE(!(t1 == t2));1002ATF_REQUIRE( t1 != t2);10031004t2.define< config::string_node >("another.key");1005t2.set< config::string_node >("another.key", "some text");1006ATF_REQUIRE( t1 == t2);1007ATF_REQUIRE(!(t1 != t2));1008}100910101011ATF_TEST_CASE_WITHOUT_HEAD(custom_leaf__no_default_ctor);1012ATF_TEST_CASE_BODY(custom_leaf__no_default_ctor)1013{1014config::tree tree;10151016tree.define< wrapped_int_node >("test1");1017tree.define< wrapped_int_node >("test2");1018tree.set< wrapped_int_node >("test1", int_wrapper(5));1019tree.set< wrapped_int_node >("test2", int_wrapper(10));1020const int_wrapper& test1 = tree.lookup< wrapped_int_node >("test1");1021ATF_REQUIRE_EQ(5, test1.value());1022const int_wrapper& test2 = tree.lookup< wrapped_int_node >("test2");1023ATF_REQUIRE_EQ(10, test2.value());1024}102510261027ATF_INIT_TEST_CASES(tcs)1028{1029ATF_ADD_TEST_CASE(tcs, define_set_lookup__one_level);1030ATF_ADD_TEST_CASE(tcs, define_set_lookup__multiple_levels);10311032ATF_ADD_TEST_CASE(tcs, deep_copy__empty);1033ATF_ADD_TEST_CASE(tcs, deep_copy__some);10341035ATF_ADD_TEST_CASE(tcs, combine__empty);1036ATF_ADD_TEST_CASE(tcs, combine__same_layout__no_overrides);1037ATF_ADD_TEST_CASE(tcs, combine__same_layout__no_base);1038ATF_ADD_TEST_CASE(tcs, combine__same_layout__mix);1039ATF_ADD_TEST_CASE(tcs, combine__different_layout);1040ATF_ADD_TEST_CASE(tcs, combine__dynamic_wins);1041ATF_ADD_TEST_CASE(tcs, combine__inner_leaf_mismatch);10421043ATF_ADD_TEST_CASE(tcs, lookup__invalid_key);1044ATF_ADD_TEST_CASE(tcs, lookup__unknown_key);10451046ATF_ADD_TEST_CASE(tcs, is_set__one_level);1047ATF_ADD_TEST_CASE(tcs, is_set__multiple_levels);1048ATF_ADD_TEST_CASE(tcs, is_set__invalid_key);10491050ATF_ADD_TEST_CASE(tcs, set__invalid_key);1051ATF_ADD_TEST_CASE(tcs, set__invalid_key_value);1052ATF_ADD_TEST_CASE(tcs, set__unknown_key);1053ATF_ADD_TEST_CASE(tcs, set__unknown_key_not_strict);10541055ATF_ADD_TEST_CASE(tcs, push_lua__ok);1056ATF_ADD_TEST_CASE(tcs, set_lua__ok);10571058ATF_ADD_TEST_CASE(tcs, lookup_rw);10591060ATF_ADD_TEST_CASE(tcs, lookup_string__ok);1061ATF_ADD_TEST_CASE(tcs, lookup_string__invalid_key);1062ATF_ADD_TEST_CASE(tcs, lookup_string__unknown_key);10631064ATF_ADD_TEST_CASE(tcs, set_string__ok);1065ATF_ADD_TEST_CASE(tcs, set_string__invalid_key);1066ATF_ADD_TEST_CASE(tcs, set_string__invalid_key_value);1067ATF_ADD_TEST_CASE(tcs, set_string__unknown_key);1068ATF_ADD_TEST_CASE(tcs, set_string__unknown_key_not_strict);10691070ATF_ADD_TEST_CASE(tcs, all_properties__none);1071ATF_ADD_TEST_CASE(tcs, all_properties__all_set);1072ATF_ADD_TEST_CASE(tcs, all_properties__some_unset);1073ATF_ADD_TEST_CASE(tcs, all_properties__subtree__inner);1074ATF_ADD_TEST_CASE(tcs, all_properties__subtree__leaf);1075ATF_ADD_TEST_CASE(tcs, all_properties__subtree__strip_key);1076ATF_ADD_TEST_CASE(tcs, all_properties__subtree__invalid_key);1077ATF_ADD_TEST_CASE(tcs, all_properties__subtree__unknown_key);10781079ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__empty);1080ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__shallow_copy);1081ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__deep_copy);1082ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__some_contents);10831084ATF_ADD_TEST_CASE(tcs, custom_leaf__no_default_ctor);1085}108610871088