// Copyright 2012 Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of Google Inc. nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "utils/config/tree.ipp" #include #include "utils/config/nodes.ipp" #include "utils/format/macros.hpp" #include "utils/text/operations.ipp" namespace config = utils::config; namespace text = utils::text; namespace { /// Simple wrapper around an integer value without default constructors. /// /// The purpose of this type is to have a simple class without default /// constructors to validate that we can use it as a leaf of a tree. class int_wrapper { /// The wrapped integer value. int _value; public: /// Constructs a new wrapped integer. /// /// \param value_ The value to store in the object. explicit int_wrapper(int value_) : _value(value_) { } /// Gets the integer value stored in the object. int value(void) const { return _value; } }; /// Custom tree leaf type for an object without defualt constructors. class wrapped_int_node : public config::typed_leaf_node< int_wrapper > { public: /// Copies the node. /// /// \return A dynamically-allocated node. virtual base_node* deep_copy(void) const { std::unique_ptr< wrapped_int_node > new_node(new wrapped_int_node()); new_node->_value = _value; return new_node.release(); } /// Pushes the node's value onto the Lua stack. /// /// \param state The Lua state onto which to push the value. void push_lua(lutok::state& state) const { state.push_integer( config::typed_leaf_node< int_wrapper >::value().value()); } /// Sets the value of the node from an entry in the Lua stack. /// /// \param state The Lua state from which to get the value. /// \param value_index The stack index in which the value resides. void set_lua(lutok::state& state, const int value_index) { ATF_REQUIRE(state.is_number(value_index)); int_wrapper new_value(state.to_integer(value_index)); config::typed_leaf_node< int_wrapper >::set(new_value); } /// Sets the value of the node from a raw string representation. /// /// \param raw_value The value to set the node to. void set_string(const std::string& raw_value) { int_wrapper new_value(text::to_type< int >(raw_value)); config::typed_leaf_node< int_wrapper >::set(new_value); } /// Converts the contents of the node to a string. /// /// \return A string representation of the value held by the node. std::string to_string(void) const { return F("%s") % config::typed_leaf_node< int_wrapper >::value().value(); } }; } // anonymous namespace ATF_TEST_CASE_WITHOUT_HEAD(define_set_lookup__one_level); ATF_TEST_CASE_BODY(define_set_lookup__one_level) { config::tree tree; tree.define< config::int_node >("var1"); tree.define< config::string_node >("var2"); tree.define< config::bool_node >("var3"); tree.set< config::int_node >("var1", 42); tree.set< config::string_node >("var2", "hello"); tree.set< config::bool_node >("var3", false); ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("var1")); ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("var2")); ATF_REQUIRE(!tree.lookup< config::bool_node >("var3")); } ATF_TEST_CASE_WITHOUT_HEAD(define_set_lookup__multiple_levels); ATF_TEST_CASE_BODY(define_set_lookup__multiple_levels) { config::tree tree; tree.define< config::int_node >("foo.bar.1"); tree.define< config::string_node >("foo.bar.2"); tree.define< config::bool_node >("foo.3"); tree.define_dynamic("sub.tree"); tree.set< config::int_node >("foo.bar.1", 42); tree.set< config::string_node >("foo.bar.2", "hello"); tree.set< config::bool_node >("foo.3", true); tree.set< config::string_node >("sub.tree.1", "bye"); tree.set< config::int_node >("sub.tree.2", 4); tree.set< config::int_node >("sub.tree.3.4", 123); ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("foo.bar.1")); ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("foo.bar.2")); ATF_REQUIRE(tree.lookup< config::bool_node >("foo.3")); ATF_REQUIRE_EQ(4, tree.lookup< config::int_node >("sub.tree.2")); ATF_REQUIRE_EQ(123, tree.lookup< config::int_node >("sub.tree.3.4")); } ATF_TEST_CASE_WITHOUT_HEAD(deep_copy__empty); ATF_TEST_CASE_BODY(deep_copy__empty) { config::tree tree1; config::tree tree2 = tree1.deep_copy(); tree1.define< config::bool_node >("var1"); // This would crash if the copy shared the internal data. tree2.define< config::int_node >("var1"); } ATF_TEST_CASE_WITHOUT_HEAD(deep_copy__some); ATF_TEST_CASE_BODY(deep_copy__some) { config::tree tree1; tree1.define< config::bool_node >("this.is.a.var"); tree1.set< config::bool_node >("this.is.a.var", true); tree1.define< config::int_node >("this.is.another.var"); tree1.set< config::int_node >("this.is.another.var", 34); tree1.define< config::int_node >("and.another"); tree1.set< config::int_node >("and.another", 123); config::tree tree2 = tree1.deep_copy(); tree2.set< config::bool_node >("this.is.a.var", false); tree2.set< config::int_node >("this.is.another.var", 43); ATF_REQUIRE( tree1.lookup< config::bool_node >("this.is.a.var")); ATF_REQUIRE(!tree2.lookup< config::bool_node >("this.is.a.var")); ATF_REQUIRE_EQ(34, tree1.lookup< config::int_node >("this.is.another.var")); ATF_REQUIRE_EQ(43, tree2.lookup< config::int_node >("this.is.another.var")); ATF_REQUIRE_EQ(123, tree1.lookup< config::int_node >("and.another")); ATF_REQUIRE_EQ(123, tree2.lookup< config::int_node >("and.another")); } ATF_TEST_CASE_WITHOUT_HEAD(lookup__invalid_key); ATF_TEST_CASE_BODY(lookup__invalid_key) { config::tree tree; ATF_REQUIRE_THROW(config::invalid_key_error, tree.lookup< config::int_node >(".")); } ATF_TEST_CASE_WITHOUT_HEAD(lookup__unknown_key); ATF_TEST_CASE_BODY(lookup__unknown_key) { config::tree tree; tree.define< config::int_node >("foo.bar"); tree.define< config::int_node >("a.b.c"); tree.define_dynamic("a.d"); tree.set< config::int_node >("a.b.c", 123); tree.set< config::int_node >("a.d.100", 0); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("abc")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("foo")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("foo.bar")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("foo.bar.baz")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("a")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("a.b")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("a.c")); (void)tree.lookup< config::int_node >("a.b.c"); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("a.b.c.d")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("a.d")); (void)tree.lookup< config::int_node >("a.d.100"); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("a.d.101")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("a.d.100.3")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup< config::int_node >("a.d.e")); } ATF_TEST_CASE_WITHOUT_HEAD(is_set__one_level); ATF_TEST_CASE_BODY(is_set__one_level) { config::tree tree; tree.define< config::int_node >("var1"); tree.define< config::string_node >("var2"); tree.define< config::bool_node >("var3"); tree.set< config::int_node >("var1", 42); tree.set< config::bool_node >("var3", false); ATF_REQUIRE( tree.is_set("var1")); ATF_REQUIRE(!tree.is_set("var2")); ATF_REQUIRE( tree.is_set("var3")); } ATF_TEST_CASE_WITHOUT_HEAD(is_set__multiple_levels); ATF_TEST_CASE_BODY(is_set__multiple_levels) { config::tree tree; tree.define< config::int_node >("a.b.var1"); tree.define< config::string_node >("a.b.var2"); tree.define< config::bool_node >("e.var3"); tree.set< config::int_node >("a.b.var1", 42); tree.set< config::bool_node >("e.var3", false); ATF_REQUIRE(!tree.is_set("a")); ATF_REQUIRE(!tree.is_set("a.b")); ATF_REQUIRE( tree.is_set("a.b.var1")); ATF_REQUIRE(!tree.is_set("a.b.var1.trailing")); ATF_REQUIRE(!tree.is_set("a")); ATF_REQUIRE(!tree.is_set("a.b")); ATF_REQUIRE(!tree.is_set("a.b.var2")); ATF_REQUIRE(!tree.is_set("a.b.var2.trailing")); ATF_REQUIRE(!tree.is_set("e")); ATF_REQUIRE( tree.is_set("e.var3")); ATF_REQUIRE(!tree.is_set("e.var3.trailing")); } ATF_TEST_CASE_WITHOUT_HEAD(is_set__invalid_key); ATF_TEST_CASE_BODY(is_set__invalid_key) { config::tree tree; ATF_REQUIRE_THROW(config::invalid_key_error, tree.is_set(".abc")); } ATF_TEST_CASE_WITHOUT_HEAD(set__invalid_key); ATF_TEST_CASE_BODY(set__invalid_key) { config::tree tree; ATF_REQUIRE_THROW(config::invalid_key_error, tree.set< config::int_node >("foo.", 54)); } ATF_TEST_CASE_WITHOUT_HEAD(set__unknown_key); ATF_TEST_CASE_BODY(set__unknown_key) { config::tree tree; tree.define< config::int_node >("foo.bar"); tree.define< config::int_node >("a.b.c"); tree.define_dynamic("a.d"); tree.set< config::int_node >("a.b.c", 123); tree.set< config::string_node >("a.d.3", "foo"); ATF_REQUIRE_THROW(config::unknown_key_error, tree.set< config::int_node >("abc", 2)); tree.set< config::int_node >("foo.bar", 15); ATF_REQUIRE_THROW(config::unknown_key_error, tree.set< config::int_node >("foo.bar.baz", 0)); ATF_REQUIRE_THROW(config::unknown_key_error, tree.set< config::int_node >("a.c", 100)); tree.set< config::int_node >("a.b.c", -3); ATF_REQUIRE_THROW(config::unknown_key_error, tree.set< config::int_node >("a.b.c.d", 82)); tree.set< config::string_node >("a.d.3", "bar"); tree.set< config::string_node >("a.d.4", "bar"); ATF_REQUIRE_THROW(config::unknown_key_error, tree.set< config::int_node >("a.d.4.5", 82)); tree.set< config::int_node >("a.d.5.6", 82); } ATF_TEST_CASE_WITHOUT_HEAD(set__value_error); ATF_TEST_CASE_BODY(set__value_error) { config::tree tree; tree.define< config::int_node >("foo.bar"); tree.define_dynamic("a.d"); ATF_REQUIRE_THROW(config::value_error, tree.set< config::int_node >("foo", 3)); ATF_REQUIRE_THROW(config::value_error, tree.set< config::int_node >("a", -10)); } ATF_TEST_CASE_WITHOUT_HEAD(push_lua__ok); ATF_TEST_CASE_BODY(push_lua__ok) { config::tree tree; tree.define< config::int_node >("top.integer"); tree.define< wrapped_int_node >("top.custom"); tree.define_dynamic("dynamic"); tree.set< config::int_node >("top.integer", 5); tree.set< wrapped_int_node >("top.custom", int_wrapper(10)); tree.set_string("dynamic.first", "foo"); lutok::state state; tree.push_lua("top.integer", state); tree.push_lua("top.custom", state); tree.push_lua("dynamic.first", state); ATF_REQUIRE(state.is_number(-3)); ATF_REQUIRE_EQ(5, state.to_integer(-3)); ATF_REQUIRE(state.is_number(-2)); ATF_REQUIRE_EQ(10, state.to_integer(-2)); ATF_REQUIRE(state.is_string(-1)); ATF_REQUIRE_EQ("foo", state.to_string(-1)); state.pop(3); } ATF_TEST_CASE_WITHOUT_HEAD(set_lua__ok); ATF_TEST_CASE_BODY(set_lua__ok) { config::tree tree; tree.define< config::int_node >("top.integer"); tree.define< wrapped_int_node >("top.custom"); tree.define_dynamic("dynamic"); { lutok::state state; state.push_integer(5); state.push_integer(10); state.push_string("foo"); tree.set_lua("top.integer", state, -3); tree.set_lua("top.custom", state, -2); tree.set_lua("dynamic.first", state, -1); state.pop(3); } ATF_REQUIRE_EQ(5, tree.lookup< config::int_node >("top.integer")); ATF_REQUIRE_EQ(10, tree.lookup< wrapped_int_node >("top.custom").value()); ATF_REQUIRE_EQ("foo", tree.lookup< config::string_node >("dynamic.first")); } ATF_TEST_CASE_WITHOUT_HEAD(lookup_rw); ATF_TEST_CASE_BODY(lookup_rw) { config::tree tree; tree.define< config::int_node >("var1"); tree.define< config::bool_node >("var3"); tree.set< config::int_node >("var1", 42); tree.set< config::bool_node >("var3", false); tree.lookup_rw< config::int_node >("var1") += 10; ATF_REQUIRE_EQ(52, tree.lookup< config::int_node >("var1")); ATF_REQUIRE(!tree.lookup< config::bool_node >("var3")); } ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__ok); ATF_TEST_CASE_BODY(lookup_string__ok) { config::tree tree; tree.define< config::int_node >("var1"); tree.define< config::string_node >("b.var2"); tree.define< config::bool_node >("c.d.var3"); tree.set< config::int_node >("var1", 42); tree.set< config::string_node >("b.var2", "hello"); tree.set< config::bool_node >("c.d.var3", false); ATF_REQUIRE_EQ("42", tree.lookup_string("var1")); ATF_REQUIRE_EQ("hello", tree.lookup_string("b.var2")); ATF_REQUIRE_EQ("false", tree.lookup_string("c.d.var3")); } ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__invalid_key); ATF_TEST_CASE_BODY(lookup_string__invalid_key) { config::tree tree; ATF_REQUIRE_THROW(config::invalid_key_error, tree.lookup_string("")); } ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__unknown_key); ATF_TEST_CASE_BODY(lookup_string__unknown_key) { config::tree tree; tree.define< config::int_node >("a.b.c"); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup_string("a.b")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup_string("a.b.c.d")); } ATF_TEST_CASE_WITHOUT_HEAD(set_string__ok); ATF_TEST_CASE_BODY(set_string__ok) { config::tree tree; tree.define< config::int_node >("foo.bar.1"); tree.define< config::string_node >("foo.bar.2"); tree.define_dynamic("sub.tree"); tree.set_string("foo.bar.1", "42"); tree.set_string("foo.bar.2", "hello"); tree.set_string("sub.tree.2", "15"); tree.set_string("sub.tree.3.4", "bye"); ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("foo.bar.1")); ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("foo.bar.2")); ATF_REQUIRE_EQ("15", tree.lookup< config::string_node >("sub.tree.2")); ATF_REQUIRE_EQ("bye", tree.lookup< config::string_node >("sub.tree.3.4")); } ATF_TEST_CASE_WITHOUT_HEAD(set_string__invalid_key); ATF_TEST_CASE_BODY(set_string__invalid_key) { config::tree tree; ATF_REQUIRE_THROW(config::invalid_key_error, tree.set_string(".", "foo")); } ATF_TEST_CASE_WITHOUT_HEAD(set_string__unknown_key); ATF_TEST_CASE_BODY(set_string__unknown_key) { config::tree tree; tree.define< config::int_node >("foo.bar"); tree.define< config::int_node >("a.b.c"); tree.define_dynamic("a.d"); tree.set_string("a.b.c", "123"); tree.set_string("a.d.3", "foo"); ATF_REQUIRE_THROW(config::unknown_key_error, tree.set_string("abc", "2")); tree.set_string("foo.bar", "15"); ATF_REQUIRE_THROW(config::unknown_key_error, tree.set_string("foo.bar.baz", "0")); ATF_REQUIRE_THROW(config::unknown_key_error, tree.set_string("a.c", "100")); tree.set_string("a.b.c", "-3"); ATF_REQUIRE_THROW(config::unknown_key_error, tree.set_string("a.b.c.d", "82")); tree.set_string("a.d.3", "bar"); tree.set_string("a.d.4", "bar"); ATF_REQUIRE_THROW(config::unknown_key_error, tree.set_string("a.d.4.5", "82")); tree.set_string("a.d.5.6", "82"); } ATF_TEST_CASE_WITHOUT_HEAD(set_string__value_error); ATF_TEST_CASE_BODY(set_string__value_error) { config::tree tree; tree.define< config::int_node >("foo.bar"); ATF_REQUIRE_THROW(config::value_error, tree.set_string("foo", "abc")); ATF_REQUIRE_THROW(config::value_error, tree.set_string("foo.bar", " -3")); ATF_REQUIRE_THROW(config::value_error, tree.set_string("foo.bar", "3 ")); } ATF_TEST_CASE_WITHOUT_HEAD(all_properties__none); ATF_TEST_CASE_BODY(all_properties__none) { const config::tree tree; ATF_REQUIRE(tree.all_properties().empty()); } ATF_TEST_CASE_WITHOUT_HEAD(all_properties__all_set); ATF_TEST_CASE_BODY(all_properties__all_set) { config::tree tree; tree.define< config::int_node >("plain"); tree.set< config::int_node >("plain", 1234); tree.define< config::int_node >("static.first"); tree.set< config::int_node >("static.first", -3); tree.define< config::string_node >("static.second"); tree.set< config::string_node >("static.second", "some text"); tree.define_dynamic("dynamic"); tree.set< config::string_node >("dynamic.first", "hello"); tree.set< config::string_node >("dynamic.second", "bye"); config::properties_map exp_properties; exp_properties["plain"] = "1234"; exp_properties["static.first"] = "-3"; exp_properties["static.second"] = "some text"; exp_properties["dynamic.first"] = "hello"; exp_properties["dynamic.second"] = "bye"; const config::properties_map properties = tree.all_properties(); ATF_REQUIRE(exp_properties == properties); } ATF_TEST_CASE_WITHOUT_HEAD(all_properties__some_unset); ATF_TEST_CASE_BODY(all_properties__some_unset) { config::tree tree; tree.define< config::int_node >("static.first"); tree.set< config::int_node >("static.first", -3); tree.define< config::string_node >("static.second"); tree.define_dynamic("dynamic"); config::properties_map exp_properties; exp_properties["static.first"] = "-3"; const config::properties_map properties = tree.all_properties(); ATF_REQUIRE(exp_properties == properties); } ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__inner); ATF_TEST_CASE_BODY(all_properties__subtree__inner) { config::tree tree; tree.define< config::int_node >("root.a.b.c.first"); tree.define< config::int_node >("root.a.b.c.second"); tree.define< config::int_node >("root.a.d.first"); tree.set< config::int_node >("root.a.b.c.first", 1); tree.set< config::int_node >("root.a.b.c.second", 2); tree.set< config::int_node >("root.a.d.first", 3); { config::properties_map exp_properties; exp_properties["root.a.b.c.first"] = "1"; exp_properties["root.a.b.c.second"] = "2"; exp_properties["root.a.d.first"] = "3"; ATF_REQUIRE(exp_properties == tree.all_properties("root")); ATF_REQUIRE(exp_properties == tree.all_properties("root.a")); } { config::properties_map exp_properties; exp_properties["root.a.b.c.first"] = "1"; exp_properties["root.a.b.c.second"] = "2"; ATF_REQUIRE(exp_properties == tree.all_properties("root.a.b")); ATF_REQUIRE(exp_properties == tree.all_properties("root.a.b.c")); } { config::properties_map exp_properties; exp_properties["root.a.d.first"] = "3"; ATF_REQUIRE(exp_properties == tree.all_properties("root.a.d")); } } ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__leaf); ATF_TEST_CASE_BODY(all_properties__subtree__leaf) { config::tree tree; tree.define< config::int_node >("root.a.b.c.first"); tree.set< config::int_node >("root.a.b.c.first", 1); ATF_REQUIRE_THROW_RE(config::value_error, "Cannot export.*leaf", tree.all_properties("root.a.b.c.first")); } ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__strip_key); ATF_TEST_CASE_BODY(all_properties__subtree__strip_key) { config::tree tree; tree.define< config::int_node >("root.a.b.c.first"); tree.define< config::int_node >("root.a.b.c.second"); tree.define< config::int_node >("root.a.d.first"); tree.set< config::int_node >("root.a.b.c.first", 1); tree.set< config::int_node >("root.a.b.c.second", 2); tree.set< config::int_node >("root.a.d.first", 3); config::properties_map exp_properties; exp_properties["b.c.first"] = "1"; exp_properties["b.c.second"] = "2"; exp_properties["d.first"] = "3"; ATF_REQUIRE(exp_properties == tree.all_properties("root.a", true)); } ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__invalid_key); ATF_TEST_CASE_BODY(all_properties__subtree__invalid_key) { config::tree tree; ATF_REQUIRE_THROW(config::invalid_key_error, tree.all_properties(".")); } ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__unknown_key); ATF_TEST_CASE_BODY(all_properties__subtree__unknown_key) { config::tree tree; tree.define< config::int_node >("root.a.b.c.first"); tree.set< config::int_node >("root.a.b.c.first", 1); tree.define< config::int_node >("root.a.b.c.unset"); ATF_REQUIRE_THROW(config::unknown_key_error, tree.all_properties("root.a.b.c.first.foo")); ATF_REQUIRE_THROW_RE(config::value_error, "Cannot export.*leaf", tree.all_properties("root.a.b.c.unset")); } ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__empty); ATF_TEST_CASE_BODY(operators_eq_and_ne__empty) { config::tree t1; config::tree t2; ATF_REQUIRE( t1 == t2); ATF_REQUIRE(!(t1 != t2)); } ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__shallow_copy); ATF_TEST_CASE_BODY(operators_eq_and_ne__shallow_copy) { config::tree t1; t1.define< config::int_node >("root.a.b.c.first"); t1.set< config::int_node >("root.a.b.c.first", 1); config::tree t2 = t1; ATF_REQUIRE( t1 == t2); ATF_REQUIRE(!(t1 != t2)); } ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__deep_copy); ATF_TEST_CASE_BODY(operators_eq_and_ne__deep_copy) { config::tree t1; t1.define< config::int_node >("root.a.b.c.first"); t1.set< config::int_node >("root.a.b.c.first", 1); config::tree t2 = t1.deep_copy(); ATF_REQUIRE( t1 == t2); ATF_REQUIRE(!(t1 != t2)); } ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__some_contents); ATF_TEST_CASE_BODY(operators_eq_and_ne__some_contents) { config::tree t1, t2; t1.define< config::int_node >("root.a.b.c.first"); t1.set< config::int_node >("root.a.b.c.first", 1); ATF_REQUIRE(!(t1 == t2)); ATF_REQUIRE( t1 != t2); t2.define< config::int_node >("root.a.b.c.first"); t2.set< config::int_node >("root.a.b.c.first", 1); ATF_REQUIRE( t1 == t2); ATF_REQUIRE(!(t1 != t2)); t1.set< config::int_node >("root.a.b.c.first", 2); ATF_REQUIRE(!(t1 == t2)); ATF_REQUIRE( t1 != t2); t2.set< config::int_node >("root.a.b.c.first", 2); ATF_REQUIRE( t1 == t2); ATF_REQUIRE(!(t1 != t2)); t1.define< config::string_node >("another.key"); t1.set< config::string_node >("another.key", "some text"); ATF_REQUIRE(!(t1 == t2)); ATF_REQUIRE( t1 != t2); t2.define< config::string_node >("another.key"); t2.set< config::string_node >("another.key", "some text"); ATF_REQUIRE( t1 == t2); ATF_REQUIRE(!(t1 != t2)); } ATF_TEST_CASE_WITHOUT_HEAD(custom_leaf__no_default_ctor); ATF_TEST_CASE_BODY(custom_leaf__no_default_ctor) { config::tree tree; tree.define< wrapped_int_node >("test1"); tree.define< wrapped_int_node >("test2"); tree.set< wrapped_int_node >("test1", int_wrapper(5)); tree.set< wrapped_int_node >("test2", int_wrapper(10)); const int_wrapper& test1 = tree.lookup< wrapped_int_node >("test1"); ATF_REQUIRE_EQ(5, test1.value()); const int_wrapper& test2 = tree.lookup< wrapped_int_node >("test2"); ATF_REQUIRE_EQ(10, test2.value()); } ATF_INIT_TEST_CASES(tcs) { ATF_ADD_TEST_CASE(tcs, define_set_lookup__one_level); ATF_ADD_TEST_CASE(tcs, define_set_lookup__multiple_levels); ATF_ADD_TEST_CASE(tcs, deep_copy__empty); ATF_ADD_TEST_CASE(tcs, deep_copy__some); ATF_ADD_TEST_CASE(tcs, lookup__invalid_key); ATF_ADD_TEST_CASE(tcs, lookup__unknown_key); ATF_ADD_TEST_CASE(tcs, is_set__one_level); ATF_ADD_TEST_CASE(tcs, is_set__multiple_levels); ATF_ADD_TEST_CASE(tcs, is_set__invalid_key); ATF_ADD_TEST_CASE(tcs, set__invalid_key); ATF_ADD_TEST_CASE(tcs, set__unknown_key); ATF_ADD_TEST_CASE(tcs, set__value_error); ATF_ADD_TEST_CASE(tcs, push_lua__ok); ATF_ADD_TEST_CASE(tcs, set_lua__ok); ATF_ADD_TEST_CASE(tcs, lookup_rw); ATF_ADD_TEST_CASE(tcs, lookup_string__ok); ATF_ADD_TEST_CASE(tcs, lookup_string__invalid_key); ATF_ADD_TEST_CASE(tcs, lookup_string__unknown_key); ATF_ADD_TEST_CASE(tcs, set_string__ok); ATF_ADD_TEST_CASE(tcs, set_string__invalid_key); ATF_ADD_TEST_CASE(tcs, set_string__unknown_key); ATF_ADD_TEST_CASE(tcs, set_string__value_error); ATF_ADD_TEST_CASE(tcs, all_properties__none); ATF_ADD_TEST_CASE(tcs, all_properties__all_set); ATF_ADD_TEST_CASE(tcs, all_properties__some_unset); ATF_ADD_TEST_CASE(tcs, all_properties__subtree__inner); ATF_ADD_TEST_CASE(tcs, all_properties__subtree__leaf); ATF_ADD_TEST_CASE(tcs, all_properties__subtree__strip_key); ATF_ADD_TEST_CASE(tcs, all_properties__subtree__invalid_key); ATF_ADD_TEST_CASE(tcs, all_properties__subtree__unknown_key); ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__empty); ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__shallow_copy); ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__deep_copy); ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__some_contents); ATF_ADD_TEST_CASE(tcs, custom_leaf__no_default_ctor); }