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