Home | History | Annotate | Line # | Download | only in config
      1 // Copyright 2012 Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 // * Redistributions of source code must retain the above copyright
      9 //   notice, this list of conditions and the following disclaimer.
     10 // * Redistributions in binary form must reproduce the above copyright
     11 //   notice, this list of conditions and the following disclaimer in the
     12 //   documentation and/or other materials provided with the distribution.
     13 // * Neither the name of Google Inc. nor the names of its contributors
     14 //   may be used to endorse or promote products derived from this software
     15 //   without specific prior written permission.
     16 //
     17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 
     29 #include "utils/config/tree.ipp"
     30 
     31 #include <atf-c++.hpp>
     32 
     33 #include "utils/config/nodes.ipp"
     34 #include "utils/format/macros.hpp"
     35 #include "utils/text/operations.ipp"
     36 
     37 namespace config = utils::config;
     38 namespace text = utils::text;
     39 
     40 
     41 namespace {
     42 
     43 
     44 /// Simple wrapper around an integer value without default constructors.
     45 ///
     46 /// The purpose of this type is to have a simple class without default
     47 /// constructors to validate that we can use it as a leaf of a tree.
     48 class int_wrapper {
     49     /// The wrapped integer value.
     50     int _value;
     51 
     52 public:
     53     /// Constructs a new wrapped integer.
     54     ///
     55     /// \param value_ The value to store in the object.
     56     explicit int_wrapper(int value_) :
     57         _value(value_)
     58     {
     59     }
     60 
     61     /// Gets the integer value stored in the object.
     62     int
     63     value(void) const
     64     {
     65         return _value;
     66     }
     67 };
     68 
     69 
     70 /// Custom tree leaf type for an object without defualt constructors.
     71 class wrapped_int_node : public config::typed_leaf_node< int_wrapper > {
     72 public:
     73     /// Copies the node.
     74     ///
     75     /// \return A dynamically-allocated node.
     76     virtual base_node*
     77     deep_copy(void) const
     78     {
     79         std::unique_ptr< wrapped_int_node > new_node(new wrapped_int_node());
     80         new_node->_value = _value;
     81         return new_node.release();
     82     }
     83 
     84     /// Pushes the node's value onto the Lua stack.
     85     ///
     86     /// \param state The Lua state onto which to push the value.
     87     void
     88     push_lua(lutok::state& state) const
     89     {
     90         state.push_integer(
     91             config::typed_leaf_node< int_wrapper >::value().value());
     92     }
     93 
     94     /// Sets the value of the node from an entry in the Lua stack.
     95     ///
     96     /// \param state The Lua state from which to get the value.
     97     /// \param value_index The stack index in which the value resides.
     98     void
     99     set_lua(lutok::state& state, const int value_index)
    100     {
    101         ATF_REQUIRE(state.is_number(value_index));
    102         int_wrapper new_value(state.to_integer(value_index));
    103         config::typed_leaf_node< int_wrapper >::set(new_value);
    104     }
    105 
    106     /// Sets the value of the node from a raw string representation.
    107     ///
    108     /// \param raw_value The value to set the node to.
    109     void
    110     set_string(const std::string& raw_value)
    111     {
    112         int_wrapper new_value(text::to_type< int >(raw_value));
    113         config::typed_leaf_node< int_wrapper >::set(new_value);
    114     }
    115 
    116     /// Converts the contents of the node to a string.
    117     ///
    118     /// \return A string representation of the value held by the node.
    119     std::string
    120     to_string(void) const
    121     {
    122         return F("%s") %
    123             config::typed_leaf_node< int_wrapper >::value().value();
    124     }
    125 };
    126 
    127 
    128 }  // anonymous namespace
    129 
    130 
    131 ATF_TEST_CASE_WITHOUT_HEAD(define_set_lookup__one_level);
    132 ATF_TEST_CASE_BODY(define_set_lookup__one_level)
    133 {
    134     config::tree tree;
    135 
    136     tree.define< config::int_node >("var1");
    137     tree.define< config::string_node >("var2");
    138     tree.define< config::bool_node >("var3");
    139 
    140     tree.set< config::int_node >("var1", 42);
    141     tree.set< config::string_node >("var2", "hello");
    142     tree.set< config::bool_node >("var3", false);
    143 
    144     ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("var1"));
    145     ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("var2"));
    146     ATF_REQUIRE(!tree.lookup< config::bool_node >("var3"));
    147 }
    148 
    149 
    150 ATF_TEST_CASE_WITHOUT_HEAD(define_set_lookup__multiple_levels);
    151 ATF_TEST_CASE_BODY(define_set_lookup__multiple_levels)
    152 {
    153     config::tree tree;
    154 
    155     tree.define< config::int_node >("foo.bar.1");
    156     tree.define< config::string_node >("foo.bar.2");
    157     tree.define< config::bool_node >("foo.3");
    158     tree.define_dynamic("sub.tree");
    159 
    160     tree.set< config::int_node >("foo.bar.1", 42);
    161     tree.set< config::string_node >("foo.bar.2", "hello");
    162     tree.set< config::bool_node >("foo.3", true);
    163     tree.set< config::string_node >("sub.tree.1", "bye");
    164     tree.set< config::int_node >("sub.tree.2", 4);
    165     tree.set< config::int_node >("sub.tree.3.4", 123);
    166 
    167     ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("foo.bar.1"));
    168     ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("foo.bar.2"));
    169     ATF_REQUIRE(tree.lookup< config::bool_node >("foo.3"));
    170     ATF_REQUIRE_EQ(4, tree.lookup< config::int_node >("sub.tree.2"));
    171     ATF_REQUIRE_EQ(123, tree.lookup< config::int_node >("sub.tree.3.4"));
    172 }
    173 
    174 
    175 ATF_TEST_CASE_WITHOUT_HEAD(deep_copy__empty);
    176 ATF_TEST_CASE_BODY(deep_copy__empty)
    177 {
    178     config::tree tree1;
    179     config::tree tree2 = tree1.deep_copy();
    180 
    181     tree1.define< config::bool_node >("var1");
    182     // This would crash if the copy shared the internal data.
    183     tree2.define< config::int_node >("var1");
    184 }
    185 
    186 
    187 ATF_TEST_CASE_WITHOUT_HEAD(deep_copy__some);
    188 ATF_TEST_CASE_BODY(deep_copy__some)
    189 {
    190     config::tree tree1;
    191     tree1.define< config::bool_node >("this.is.a.var");
    192     tree1.set< config::bool_node >("this.is.a.var", true);
    193     tree1.define< config::int_node >("this.is.another.var");
    194     tree1.set< config::int_node >("this.is.another.var", 34);
    195     tree1.define< config::int_node >("and.another");
    196     tree1.set< config::int_node >("and.another", 123);
    197 
    198     config::tree tree2 = tree1.deep_copy();
    199     tree2.set< config::bool_node >("this.is.a.var", false);
    200     tree2.set< config::int_node >("this.is.another.var", 43);
    201 
    202     ATF_REQUIRE( tree1.lookup< config::bool_node >("this.is.a.var"));
    203     ATF_REQUIRE(!tree2.lookup< config::bool_node >("this.is.a.var"));
    204 
    205     ATF_REQUIRE_EQ(34, tree1.lookup< config::int_node >("this.is.another.var"));
    206     ATF_REQUIRE_EQ(43, tree2.lookup< config::int_node >("this.is.another.var"));
    207 
    208     ATF_REQUIRE_EQ(123, tree1.lookup< config::int_node >("and.another"));
    209     ATF_REQUIRE_EQ(123, tree2.lookup< config::int_node >("and.another"));
    210 }
    211 
    212 
    213 ATF_TEST_CASE_WITHOUT_HEAD(lookup__invalid_key);
    214 ATF_TEST_CASE_BODY(lookup__invalid_key)
    215 {
    216     config::tree tree;
    217 
    218     ATF_REQUIRE_THROW(config::invalid_key_error,
    219                       tree.lookup< config::int_node >("."));
    220 }
    221 
    222 
    223 ATF_TEST_CASE_WITHOUT_HEAD(lookup__unknown_key);
    224 ATF_TEST_CASE_BODY(lookup__unknown_key)
    225 {
    226     config::tree tree;
    227 
    228     tree.define< config::int_node >("foo.bar");
    229     tree.define< config::int_node >("a.b.c");
    230     tree.define_dynamic("a.d");
    231     tree.set< config::int_node >("a.b.c", 123);
    232     tree.set< config::int_node >("a.d.100", 0);
    233 
    234     ATF_REQUIRE_THROW(config::unknown_key_error,
    235                       tree.lookup< config::int_node >("abc"));
    236 
    237     ATF_REQUIRE_THROW(config::unknown_key_error,
    238                       tree.lookup< config::int_node >("foo"));
    239     ATF_REQUIRE_THROW(config::unknown_key_error,
    240                       tree.lookup< config::int_node >("foo.bar"));
    241     ATF_REQUIRE_THROW(config::unknown_key_error,
    242                       tree.lookup< config::int_node >("foo.bar.baz"));
    243 
    244     ATF_REQUIRE_THROW(config::unknown_key_error,
    245                       tree.lookup< config::int_node >("a"));
    246     ATF_REQUIRE_THROW(config::unknown_key_error,
    247                       tree.lookup< config::int_node >("a.b"));
    248     ATF_REQUIRE_THROW(config::unknown_key_error,
    249                       tree.lookup< config::int_node >("a.c"));
    250     (void)tree.lookup< config::int_node >("a.b.c");
    251     ATF_REQUIRE_THROW(config::unknown_key_error,
    252                       tree.lookup< config::int_node >("a.b.c.d"));
    253     ATF_REQUIRE_THROW(config::unknown_key_error,
    254                       tree.lookup< config::int_node >("a.d"));
    255     (void)tree.lookup< config::int_node >("a.d.100");
    256     ATF_REQUIRE_THROW(config::unknown_key_error,
    257                       tree.lookup< config::int_node >("a.d.101"));
    258     ATF_REQUIRE_THROW(config::unknown_key_error,
    259                       tree.lookup< config::int_node >("a.d.100.3"));
    260     ATF_REQUIRE_THROW(config::unknown_key_error,
    261                       tree.lookup< config::int_node >("a.d.e"));
    262 }
    263 
    264 
    265 ATF_TEST_CASE_WITHOUT_HEAD(is_set__one_level);
    266 ATF_TEST_CASE_BODY(is_set__one_level)
    267 {
    268     config::tree tree;
    269 
    270     tree.define< config::int_node >("var1");
    271     tree.define< config::string_node >("var2");
    272     tree.define< config::bool_node >("var3");
    273 
    274     tree.set< config::int_node >("var1", 42);
    275     tree.set< config::bool_node >("var3", false);
    276 
    277     ATF_REQUIRE( tree.is_set("var1"));
    278     ATF_REQUIRE(!tree.is_set("var2"));
    279     ATF_REQUIRE( tree.is_set("var3"));
    280 }
    281 
    282 
    283 ATF_TEST_CASE_WITHOUT_HEAD(is_set__multiple_levels);
    284 ATF_TEST_CASE_BODY(is_set__multiple_levels)
    285 {
    286     config::tree tree;
    287 
    288     tree.define< config::int_node >("a.b.var1");
    289     tree.define< config::string_node >("a.b.var2");
    290     tree.define< config::bool_node >("e.var3");
    291 
    292     tree.set< config::int_node >("a.b.var1", 42);
    293     tree.set< config::bool_node >("e.var3", false);
    294 
    295     ATF_REQUIRE(!tree.is_set("a"));
    296     ATF_REQUIRE(!tree.is_set("a.b"));
    297     ATF_REQUIRE( tree.is_set("a.b.var1"));
    298     ATF_REQUIRE(!tree.is_set("a.b.var1.trailing"));
    299 
    300     ATF_REQUIRE(!tree.is_set("a"));
    301     ATF_REQUIRE(!tree.is_set("a.b"));
    302     ATF_REQUIRE(!tree.is_set("a.b.var2"));
    303     ATF_REQUIRE(!tree.is_set("a.b.var2.trailing"));
    304 
    305     ATF_REQUIRE(!tree.is_set("e"));
    306     ATF_REQUIRE( tree.is_set("e.var3"));
    307     ATF_REQUIRE(!tree.is_set("e.var3.trailing"));
    308 }
    309 
    310 
    311 ATF_TEST_CASE_WITHOUT_HEAD(is_set__invalid_key);
    312 ATF_TEST_CASE_BODY(is_set__invalid_key)
    313 {
    314     config::tree tree;
    315 
    316     ATF_REQUIRE_THROW(config::invalid_key_error, tree.is_set(".abc"));
    317 }
    318 
    319 
    320 ATF_TEST_CASE_WITHOUT_HEAD(set__invalid_key);
    321 ATF_TEST_CASE_BODY(set__invalid_key)
    322 {
    323     config::tree tree;
    324 
    325     ATF_REQUIRE_THROW(config::invalid_key_error,
    326                       tree.set< config::int_node >("foo.", 54));
    327 }
    328 
    329 
    330 ATF_TEST_CASE_WITHOUT_HEAD(set__unknown_key);
    331 ATF_TEST_CASE_BODY(set__unknown_key)
    332 {
    333     config::tree tree;
    334 
    335     tree.define< config::int_node >("foo.bar");
    336     tree.define< config::int_node >("a.b.c");
    337     tree.define_dynamic("a.d");
    338     tree.set< config::int_node >("a.b.c", 123);
    339     tree.set< config::string_node >("a.d.3", "foo");
    340 
    341     ATF_REQUIRE_THROW(config::unknown_key_error,
    342                       tree.set< config::int_node >("abc", 2));
    343 
    344     tree.set< config::int_node >("foo.bar", 15);
    345     ATF_REQUIRE_THROW(config::unknown_key_error,
    346                       tree.set< config::int_node >("foo.bar.baz", 0));
    347 
    348     ATF_REQUIRE_THROW(config::unknown_key_error,
    349                       tree.set< config::int_node >("a.c", 100));
    350     tree.set< config::int_node >("a.b.c", -3);
    351     ATF_REQUIRE_THROW(config::unknown_key_error,
    352                       tree.set< config::int_node >("a.b.c.d", 82));
    353     tree.set< config::string_node >("a.d.3", "bar");
    354     tree.set< config::string_node >("a.d.4", "bar");
    355     ATF_REQUIRE_THROW(config::unknown_key_error,
    356                       tree.set< config::int_node >("a.d.4.5", 82));
    357     tree.set< config::int_node >("a.d.5.6", 82);
    358 }
    359 
    360 
    361 ATF_TEST_CASE_WITHOUT_HEAD(set__value_error);
    362 ATF_TEST_CASE_BODY(set__value_error)
    363 {
    364     config::tree tree;
    365 
    366     tree.define< config::int_node >("foo.bar");
    367     tree.define_dynamic("a.d");
    368 
    369     ATF_REQUIRE_THROW(config::value_error,
    370                       tree.set< config::int_node >("foo", 3));
    371     ATF_REQUIRE_THROW(config::value_error,
    372                       tree.set< config::int_node >("a", -10));
    373 }
    374 
    375 
    376 ATF_TEST_CASE_WITHOUT_HEAD(push_lua__ok);
    377 ATF_TEST_CASE_BODY(push_lua__ok)
    378 {
    379     config::tree tree;
    380 
    381     tree.define< config::int_node >("top.integer");
    382     tree.define< wrapped_int_node >("top.custom");
    383     tree.define_dynamic("dynamic");
    384     tree.set< config::int_node >("top.integer", 5);
    385     tree.set< wrapped_int_node >("top.custom", int_wrapper(10));
    386     tree.set_string("dynamic.first", "foo");
    387 
    388     lutok::state state;
    389     tree.push_lua("top.integer", state);
    390     tree.push_lua("top.custom", state);
    391     tree.push_lua("dynamic.first", state);
    392     ATF_REQUIRE(state.is_number(-3));
    393     ATF_REQUIRE_EQ(5, state.to_integer(-3));
    394     ATF_REQUIRE(state.is_number(-2));
    395     ATF_REQUIRE_EQ(10, state.to_integer(-2));
    396     ATF_REQUIRE(state.is_string(-1));
    397     ATF_REQUIRE_EQ("foo", state.to_string(-1));
    398     state.pop(3);
    399 }
    400 
    401 
    402 ATF_TEST_CASE_WITHOUT_HEAD(set_lua__ok);
    403 ATF_TEST_CASE_BODY(set_lua__ok)
    404 {
    405     config::tree tree;
    406 
    407     tree.define< config::int_node >("top.integer");
    408     tree.define< wrapped_int_node >("top.custom");
    409     tree.define_dynamic("dynamic");
    410 
    411     {
    412         lutok::state state;
    413         state.push_integer(5);
    414         state.push_integer(10);
    415         state.push_string("foo");
    416         tree.set_lua("top.integer", state, -3);
    417         tree.set_lua("top.custom", state, -2);
    418         tree.set_lua("dynamic.first", state, -1);
    419         state.pop(3);
    420     }
    421 
    422     ATF_REQUIRE_EQ(5, tree.lookup< config::int_node >("top.integer"));
    423     ATF_REQUIRE_EQ(10, tree.lookup< wrapped_int_node >("top.custom").value());
    424     ATF_REQUIRE_EQ("foo", tree.lookup< config::string_node >("dynamic.first"));
    425 }
    426 
    427 
    428 ATF_TEST_CASE_WITHOUT_HEAD(lookup_rw);
    429 ATF_TEST_CASE_BODY(lookup_rw)
    430 {
    431     config::tree tree;
    432 
    433     tree.define< config::int_node >("var1");
    434     tree.define< config::bool_node >("var3");
    435 
    436     tree.set< config::int_node >("var1", 42);
    437     tree.set< config::bool_node >("var3", false);
    438 
    439     tree.lookup_rw< config::int_node >("var1") += 10;
    440     ATF_REQUIRE_EQ(52, tree.lookup< config::int_node >("var1"));
    441     ATF_REQUIRE(!tree.lookup< config::bool_node >("var3"));
    442 }
    443 
    444 
    445 ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__ok);
    446 ATF_TEST_CASE_BODY(lookup_string__ok)
    447 {
    448     config::tree tree;
    449 
    450     tree.define< config::int_node >("var1");
    451     tree.define< config::string_node >("b.var2");
    452     tree.define< config::bool_node >("c.d.var3");
    453 
    454     tree.set< config::int_node >("var1", 42);
    455     tree.set< config::string_node >("b.var2", "hello");
    456     tree.set< config::bool_node >("c.d.var3", false);
    457 
    458     ATF_REQUIRE_EQ("42", tree.lookup_string("var1"));
    459     ATF_REQUIRE_EQ("hello", tree.lookup_string("b.var2"));
    460     ATF_REQUIRE_EQ("false", tree.lookup_string("c.d.var3"));
    461 }
    462 
    463 
    464 ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__invalid_key);
    465 ATF_TEST_CASE_BODY(lookup_string__invalid_key)
    466 {
    467     config::tree tree;
    468 
    469     ATF_REQUIRE_THROW(config::invalid_key_error, tree.lookup_string(""));
    470 }
    471 
    472 
    473 ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__unknown_key);
    474 ATF_TEST_CASE_BODY(lookup_string__unknown_key)
    475 {
    476     config::tree tree;
    477 
    478     tree.define< config::int_node >("a.b.c");
    479 
    480     ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup_string("a.b"));
    481     ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup_string("a.b.c.d"));
    482 }
    483 
    484 
    485 ATF_TEST_CASE_WITHOUT_HEAD(set_string__ok);
    486 ATF_TEST_CASE_BODY(set_string__ok)
    487 {
    488     config::tree tree;
    489 
    490     tree.define< config::int_node >("foo.bar.1");
    491     tree.define< config::string_node >("foo.bar.2");
    492     tree.define_dynamic("sub.tree");
    493 
    494     tree.set_string("foo.bar.1", "42");
    495     tree.set_string("foo.bar.2", "hello");
    496     tree.set_string("sub.tree.2", "15");
    497     tree.set_string("sub.tree.3.4", "bye");
    498 
    499     ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("foo.bar.1"));
    500     ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("foo.bar.2"));
    501     ATF_REQUIRE_EQ("15", tree.lookup< config::string_node >("sub.tree.2"));
    502     ATF_REQUIRE_EQ("bye", tree.lookup< config::string_node >("sub.tree.3.4"));
    503 }
    504 
    505 
    506 ATF_TEST_CASE_WITHOUT_HEAD(set_string__invalid_key);
    507 ATF_TEST_CASE_BODY(set_string__invalid_key)
    508 {
    509     config::tree tree;
    510 
    511     ATF_REQUIRE_THROW(config::invalid_key_error, tree.set_string(".", "foo"));
    512 }
    513 
    514 
    515 ATF_TEST_CASE_WITHOUT_HEAD(set_string__unknown_key);
    516 ATF_TEST_CASE_BODY(set_string__unknown_key)
    517 {
    518     config::tree tree;
    519 
    520     tree.define< config::int_node >("foo.bar");
    521     tree.define< config::int_node >("a.b.c");
    522     tree.define_dynamic("a.d");
    523     tree.set_string("a.b.c", "123");
    524     tree.set_string("a.d.3", "foo");
    525 
    526     ATF_REQUIRE_THROW(config::unknown_key_error, tree.set_string("abc", "2"));
    527 
    528     tree.set_string("foo.bar", "15");
    529     ATF_REQUIRE_THROW(config::unknown_key_error,
    530                       tree.set_string("foo.bar.baz", "0"));
    531 
    532     ATF_REQUIRE_THROW(config::unknown_key_error,
    533                       tree.set_string("a.c", "100"));
    534     tree.set_string("a.b.c", "-3");
    535     ATF_REQUIRE_THROW(config::unknown_key_error,
    536                       tree.set_string("a.b.c.d", "82"));
    537     tree.set_string("a.d.3", "bar");
    538     tree.set_string("a.d.4", "bar");
    539     ATF_REQUIRE_THROW(config::unknown_key_error,
    540                       tree.set_string("a.d.4.5", "82"));
    541     tree.set_string("a.d.5.6", "82");
    542 }
    543 
    544 
    545 ATF_TEST_CASE_WITHOUT_HEAD(set_string__value_error);
    546 ATF_TEST_CASE_BODY(set_string__value_error)
    547 {
    548     config::tree tree;
    549 
    550     tree.define< config::int_node >("foo.bar");
    551 
    552     ATF_REQUIRE_THROW(config::value_error,
    553                       tree.set_string("foo", "abc"));
    554     ATF_REQUIRE_THROW(config::value_error,
    555                       tree.set_string("foo.bar", " -3"));
    556     ATF_REQUIRE_THROW(config::value_error,
    557                       tree.set_string("foo.bar", "3 "));
    558 }
    559 
    560 
    561 ATF_TEST_CASE_WITHOUT_HEAD(all_properties__none);
    562 ATF_TEST_CASE_BODY(all_properties__none)
    563 {
    564     const config::tree tree;
    565     ATF_REQUIRE(tree.all_properties().empty());
    566 }
    567 
    568 
    569 ATF_TEST_CASE_WITHOUT_HEAD(all_properties__all_set);
    570 ATF_TEST_CASE_BODY(all_properties__all_set)
    571 {
    572     config::tree tree;
    573 
    574     tree.define< config::int_node >("plain");
    575     tree.set< config::int_node >("plain", 1234);
    576 
    577     tree.define< config::int_node >("static.first");
    578     tree.set< config::int_node >("static.first", -3);
    579     tree.define< config::string_node >("static.second");
    580     tree.set< config::string_node >("static.second", "some text");
    581 
    582     tree.define_dynamic("dynamic");
    583     tree.set< config::string_node >("dynamic.first", "hello");
    584     tree.set< config::string_node >("dynamic.second", "bye");
    585 
    586     config::properties_map exp_properties;
    587     exp_properties["plain"] = "1234";
    588     exp_properties["static.first"] = "-3";
    589     exp_properties["static.second"] = "some text";
    590     exp_properties["dynamic.first"] = "hello";
    591     exp_properties["dynamic.second"] = "bye";
    592 
    593     const config::properties_map properties = tree.all_properties();
    594     ATF_REQUIRE(exp_properties == properties);
    595 }
    596 
    597 
    598 ATF_TEST_CASE_WITHOUT_HEAD(all_properties__some_unset);
    599 ATF_TEST_CASE_BODY(all_properties__some_unset)
    600 {
    601     config::tree tree;
    602 
    603     tree.define< config::int_node >("static.first");
    604     tree.set< config::int_node >("static.first", -3);
    605     tree.define< config::string_node >("static.second");
    606 
    607     tree.define_dynamic("dynamic");
    608 
    609     config::properties_map exp_properties;
    610     exp_properties["static.first"] = "-3";
    611 
    612     const config::properties_map properties = tree.all_properties();
    613     ATF_REQUIRE(exp_properties == properties);
    614 }
    615 
    616 
    617 ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__inner);
    618 ATF_TEST_CASE_BODY(all_properties__subtree__inner)
    619 {
    620     config::tree tree;
    621 
    622     tree.define< config::int_node >("root.a.b.c.first");
    623     tree.define< config::int_node >("root.a.b.c.second");
    624     tree.define< config::int_node >("root.a.d.first");
    625 
    626     tree.set< config::int_node >("root.a.b.c.first", 1);
    627     tree.set< config::int_node >("root.a.b.c.second", 2);
    628     tree.set< config::int_node >("root.a.d.first", 3);
    629 
    630     {
    631         config::properties_map exp_properties;
    632         exp_properties["root.a.b.c.first"] = "1";
    633         exp_properties["root.a.b.c.second"] = "2";
    634         exp_properties["root.a.d.first"] = "3";
    635         ATF_REQUIRE(exp_properties == tree.all_properties("root"));
    636         ATF_REQUIRE(exp_properties == tree.all_properties("root.a"));
    637     }
    638 
    639     {
    640         config::properties_map exp_properties;
    641         exp_properties["root.a.b.c.first"] = "1";
    642         exp_properties["root.a.b.c.second"] = "2";
    643         ATF_REQUIRE(exp_properties == tree.all_properties("root.a.b"));
    644         ATF_REQUIRE(exp_properties == tree.all_properties("root.a.b.c"));
    645     }
    646 
    647     {
    648         config::properties_map exp_properties;
    649         exp_properties["root.a.d.first"] = "3";
    650         ATF_REQUIRE(exp_properties == tree.all_properties("root.a.d"));
    651     }
    652 }
    653 
    654 
    655 ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__leaf);
    656 ATF_TEST_CASE_BODY(all_properties__subtree__leaf)
    657 {
    658     config::tree tree;
    659 
    660     tree.define< config::int_node >("root.a.b.c.first");
    661     tree.set< config::int_node >("root.a.b.c.first", 1);
    662     ATF_REQUIRE_THROW_RE(config::value_error, "Cannot export.*leaf",
    663                          tree.all_properties("root.a.b.c.first"));
    664 }
    665 
    666 
    667 ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__strip_key);
    668 ATF_TEST_CASE_BODY(all_properties__subtree__strip_key)
    669 {
    670     config::tree tree;
    671 
    672     tree.define< config::int_node >("root.a.b.c.first");
    673     tree.define< config::int_node >("root.a.b.c.second");
    674     tree.define< config::int_node >("root.a.d.first");
    675 
    676     tree.set< config::int_node >("root.a.b.c.first", 1);
    677     tree.set< config::int_node >("root.a.b.c.second", 2);
    678     tree.set< config::int_node >("root.a.d.first", 3);
    679 
    680     config::properties_map exp_properties;
    681     exp_properties["b.c.first"] = "1";
    682     exp_properties["b.c.second"] = "2";
    683     exp_properties["d.first"] = "3";
    684     ATF_REQUIRE(exp_properties == tree.all_properties("root.a", true));
    685 }
    686 
    687 
    688 ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__invalid_key);
    689 ATF_TEST_CASE_BODY(all_properties__subtree__invalid_key)
    690 {
    691     config::tree tree;
    692 
    693     ATF_REQUIRE_THROW(config::invalid_key_error, tree.all_properties("."));
    694 }
    695 
    696 
    697 ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__unknown_key);
    698 ATF_TEST_CASE_BODY(all_properties__subtree__unknown_key)
    699 {
    700     config::tree tree;
    701 
    702     tree.define< config::int_node >("root.a.b.c.first");
    703     tree.set< config::int_node >("root.a.b.c.first", 1);
    704     tree.define< config::int_node >("root.a.b.c.unset");
    705 
    706     ATF_REQUIRE_THROW(config::unknown_key_error,
    707                       tree.all_properties("root.a.b.c.first.foo"));
    708     ATF_REQUIRE_THROW_RE(config::value_error, "Cannot export.*leaf",
    709                          tree.all_properties("root.a.b.c.unset"));
    710 }
    711 
    712 
    713 ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__empty);
    714 ATF_TEST_CASE_BODY(operators_eq_and_ne__empty)
    715 {
    716     config::tree t1;
    717     config::tree t2;
    718     ATF_REQUIRE(  t1 == t2);
    719     ATF_REQUIRE(!(t1 != t2));
    720 }
    721 
    722 
    723 ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__shallow_copy);
    724 ATF_TEST_CASE_BODY(operators_eq_and_ne__shallow_copy)
    725 {
    726     config::tree t1;
    727     t1.define< config::int_node >("root.a.b.c.first");
    728     t1.set< config::int_node >("root.a.b.c.first", 1);
    729     config::tree t2 = t1;
    730     ATF_REQUIRE(  t1 == t2);
    731     ATF_REQUIRE(!(t1 != t2));
    732 }
    733 
    734 
    735 ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__deep_copy);
    736 ATF_TEST_CASE_BODY(operators_eq_and_ne__deep_copy)
    737 {
    738     config::tree t1;
    739     t1.define< config::int_node >("root.a.b.c.first");
    740     t1.set< config::int_node >("root.a.b.c.first", 1);
    741     config::tree t2 = t1.deep_copy();
    742     ATF_REQUIRE(  t1 == t2);
    743     ATF_REQUIRE(!(t1 != t2));
    744 }
    745 
    746 
    747 ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__some_contents);
    748 ATF_TEST_CASE_BODY(operators_eq_and_ne__some_contents)
    749 {
    750     config::tree t1, t2;
    751 
    752     t1.define< config::int_node >("root.a.b.c.first");
    753     t1.set< config::int_node >("root.a.b.c.first", 1);
    754     ATF_REQUIRE(!(t1 == t2));
    755     ATF_REQUIRE(  t1 != t2);
    756 
    757     t2.define< config::int_node >("root.a.b.c.first");
    758     t2.set< config::int_node >("root.a.b.c.first", 1);
    759     ATF_REQUIRE(  t1 == t2);
    760     ATF_REQUIRE(!(t1 != t2));
    761 
    762     t1.set< config::int_node >("root.a.b.c.first", 2);
    763     ATF_REQUIRE(!(t1 == t2));
    764     ATF_REQUIRE(  t1 != t2);
    765 
    766     t2.set< config::int_node >("root.a.b.c.first", 2);
    767     ATF_REQUIRE(  t1 == t2);
    768     ATF_REQUIRE(!(t1 != t2));
    769 
    770     t1.define< config::string_node >("another.key");
    771     t1.set< config::string_node >("another.key", "some text");
    772     ATF_REQUIRE(!(t1 == t2));
    773     ATF_REQUIRE(  t1 != t2);
    774 
    775     t2.define< config::string_node >("another.key");
    776     t2.set< config::string_node >("another.key", "some text");
    777     ATF_REQUIRE(  t1 == t2);
    778     ATF_REQUIRE(!(t1 != t2));
    779 }
    780 
    781 
    782 ATF_TEST_CASE_WITHOUT_HEAD(custom_leaf__no_default_ctor);
    783 ATF_TEST_CASE_BODY(custom_leaf__no_default_ctor)
    784 {
    785     config::tree tree;
    786 
    787     tree.define< wrapped_int_node >("test1");
    788     tree.define< wrapped_int_node >("test2");
    789     tree.set< wrapped_int_node >("test1", int_wrapper(5));
    790     tree.set< wrapped_int_node >("test2", int_wrapper(10));
    791     const int_wrapper& test1 = tree.lookup< wrapped_int_node >("test1");
    792     ATF_REQUIRE_EQ(5, test1.value());
    793     const int_wrapper& test2 = tree.lookup< wrapped_int_node >("test2");
    794     ATF_REQUIRE_EQ(10, test2.value());
    795 }
    796 
    797 
    798 ATF_INIT_TEST_CASES(tcs)
    799 {
    800     ATF_ADD_TEST_CASE(tcs, define_set_lookup__one_level);
    801     ATF_ADD_TEST_CASE(tcs, define_set_lookup__multiple_levels);
    802 
    803     ATF_ADD_TEST_CASE(tcs, deep_copy__empty);
    804     ATF_ADD_TEST_CASE(tcs, deep_copy__some);
    805 
    806     ATF_ADD_TEST_CASE(tcs, lookup__invalid_key);
    807     ATF_ADD_TEST_CASE(tcs, lookup__unknown_key);
    808 
    809     ATF_ADD_TEST_CASE(tcs, is_set__one_level);
    810     ATF_ADD_TEST_CASE(tcs, is_set__multiple_levels);
    811     ATF_ADD_TEST_CASE(tcs, is_set__invalid_key);
    812 
    813     ATF_ADD_TEST_CASE(tcs, set__invalid_key);
    814     ATF_ADD_TEST_CASE(tcs, set__unknown_key);
    815     ATF_ADD_TEST_CASE(tcs, set__value_error);
    816 
    817     ATF_ADD_TEST_CASE(tcs, push_lua__ok);
    818     ATF_ADD_TEST_CASE(tcs, set_lua__ok);
    819 
    820     ATF_ADD_TEST_CASE(tcs, lookup_rw);
    821 
    822     ATF_ADD_TEST_CASE(tcs, lookup_string__ok);
    823     ATF_ADD_TEST_CASE(tcs, lookup_string__invalid_key);
    824     ATF_ADD_TEST_CASE(tcs, lookup_string__unknown_key);
    825 
    826     ATF_ADD_TEST_CASE(tcs, set_string__ok);
    827     ATF_ADD_TEST_CASE(tcs, set_string__invalid_key);
    828     ATF_ADD_TEST_CASE(tcs, set_string__unknown_key);
    829     ATF_ADD_TEST_CASE(tcs, set_string__value_error);
    830 
    831     ATF_ADD_TEST_CASE(tcs, all_properties__none);
    832     ATF_ADD_TEST_CASE(tcs, all_properties__all_set);
    833     ATF_ADD_TEST_CASE(tcs, all_properties__some_unset);
    834     ATF_ADD_TEST_CASE(tcs, all_properties__subtree__inner);
    835     ATF_ADD_TEST_CASE(tcs, all_properties__subtree__leaf);
    836     ATF_ADD_TEST_CASE(tcs, all_properties__subtree__strip_key);
    837     ATF_ADD_TEST_CASE(tcs, all_properties__subtree__invalid_key);
    838     ATF_ADD_TEST_CASE(tcs, all_properties__subtree__unknown_key);
    839 
    840     ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__empty);
    841     ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__shallow_copy);
    842     ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__deep_copy);
    843     ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__some_contents);
    844 
    845     ATF_ADD_TEST_CASE(tcs, custom_leaf__no_default_ctor);
    846 }
    847