xref: /netbsd-src/external/bsd/kyua-cli/dist/utils/config/tree_test.cpp (revision 46b85cbbd3d745f264b248ec8702f62b162c7789)
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.
int_wrapper(int value_)56     explicit int_wrapper(int value_) :
57         _value(value_)
58     {
59     }
60 
61     /// Gets the integer value stored in the object.
62     int
value(void) const63     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*
deep_copy(void) const77     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
push_lua(lutok::state & state) const88     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
set_lua(lutok::state & state,const int value_index)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
set_string(const std::string & raw_value)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
to_string(void) const120     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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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 
ATF_INIT_TEST_CASES(tcs)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