// 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 <atf-c++.hpp>
#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);
}