Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/kyua/utils/config/tree_test.cpp
48081 views
1
// Copyright 2012 The Kyua Authors.
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
/// \return The integer value stored by 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(combine__empty);
214
ATF_TEST_CASE_BODY(combine__empty)
215
{
216
const config::tree t1, t2;
217
const config::tree combined = t1.combine(t2);
218
219
const config::tree expected;
220
ATF_REQUIRE(expected == combined);
221
}
222
223
224
static void
225
init_tree_for_combine_test(config::tree& tree)
226
{
227
tree.define< config::int_node >("int-node");
228
tree.define< config::string_node >("string-node");
229
tree.define< config::int_node >("unused.node");
230
tree.define< config::int_node >("deeper.int.node");
231
tree.define_dynamic("deeper.dynamic");
232
}
233
234
235
ATF_TEST_CASE_WITHOUT_HEAD(combine__same_layout__no_overrides);
236
ATF_TEST_CASE_BODY(combine__same_layout__no_overrides)
237
{
238
config::tree t1, t2;
239
init_tree_for_combine_test(t1);
240
init_tree_for_combine_test(t2);
241
t1.set< config::int_node >("int-node", 3);
242
t1.set< config::string_node >("string-node", "foo");
243
t1.set< config::int_node >("deeper.int.node", 15);
244
t1.set_string("deeper.dynamic.first", "value1");
245
t1.set_string("deeper.dynamic.second", "value2");
246
const config::tree combined = t1.combine(t2);
247
248
ATF_REQUIRE(t1 == combined);
249
}
250
251
252
ATF_TEST_CASE_WITHOUT_HEAD(combine__same_layout__no_base);
253
ATF_TEST_CASE_BODY(combine__same_layout__no_base)
254
{
255
config::tree t1, t2;
256
init_tree_for_combine_test(t1);
257
init_tree_for_combine_test(t2);
258
t2.set< config::int_node >("int-node", 3);
259
t2.set< config::string_node >("string-node", "foo");
260
t2.set< config::int_node >("deeper.int.node", 15);
261
t2.set_string("deeper.dynamic.first", "value1");
262
t2.set_string("deeper.dynamic.second", "value2");
263
const config::tree combined = t1.combine(t2);
264
265
ATF_REQUIRE(t2 == combined);
266
}
267
268
269
ATF_TEST_CASE_WITHOUT_HEAD(combine__same_layout__mix);
270
ATF_TEST_CASE_BODY(combine__same_layout__mix)
271
{
272
config::tree t1, t2;
273
init_tree_for_combine_test(t1);
274
init_tree_for_combine_test(t2);
275
t1.set< config::int_node >("int-node", 3);
276
t2.set< config::int_node >("int-node", 5);
277
t1.set< config::string_node >("string-node", "foo");
278
t2.set< config::int_node >("deeper.int.node", 15);
279
t1.set_string("deeper.dynamic.first", "value1");
280
t1.set_string("deeper.dynamic.second", "value2.1");
281
t2.set_string("deeper.dynamic.second", "value2.2");
282
t2.set_string("deeper.dynamic.third", "value3");
283
const config::tree combined = t1.combine(t2);
284
285
config::tree expected;
286
init_tree_for_combine_test(expected);
287
expected.set< config::int_node >("int-node", 5);
288
expected.set< config::string_node >("string-node", "foo");
289
expected.set< config::int_node >("deeper.int.node", 15);
290
expected.set_string("deeper.dynamic.first", "value1");
291
expected.set_string("deeper.dynamic.second", "value2.2");
292
expected.set_string("deeper.dynamic.third", "value3");
293
ATF_REQUIRE(expected == combined);
294
}
295
296
297
ATF_TEST_CASE_WITHOUT_HEAD(combine__different_layout);
298
ATF_TEST_CASE_BODY(combine__different_layout)
299
{
300
config::tree t1;
301
t1.define< config::int_node >("common.base1");
302
t1.define< config::int_node >("common.base2");
303
t1.define_dynamic("dynamic.base");
304
t1.define< config::int_node >("unset.base");
305
306
config::tree t2;
307
t2.define< config::int_node >("common.base2");
308
t2.define< config::int_node >("common.base3");
309
t2.define_dynamic("dynamic.other");
310
t2.define< config::int_node >("unset.other");
311
312
t1.set< config::int_node >("common.base1", 1);
313
t1.set< config::int_node >("common.base2", 2);
314
t1.set_string("dynamic.base.first", "foo");
315
t1.set_string("dynamic.base.second", "bar");
316
317
t2.set< config::int_node >("common.base2", 4);
318
t2.set< config::int_node >("common.base3", 3);
319
t2.set_string("dynamic.other.first", "FOO");
320
t2.set_string("dynamic.other.second", "BAR");
321
322
config::tree combined = t1.combine(t2);
323
324
config::tree expected;
325
expected.define< config::int_node >("common.base1");
326
expected.define< config::int_node >("common.base2");
327
expected.define< config::int_node >("common.base3");
328
expected.define_dynamic("dynamic.base");
329
expected.define_dynamic("dynamic.other");
330
expected.define< config::int_node >("unset.base");
331
expected.define< config::int_node >("unset.other");
332
333
expected.set< config::int_node >("common.base1", 1);
334
expected.set< config::int_node >("common.base2", 4);
335
expected.set< config::int_node >("common.base3", 3);
336
expected.set_string("dynamic.base.first", "foo");
337
expected.set_string("dynamic.base.second", "bar");
338
expected.set_string("dynamic.other.first", "FOO");
339
expected.set_string("dynamic.other.second", "BAR");
340
341
ATF_REQUIRE(expected == combined);
342
343
// The combined tree should have respected existing but unset nodes. Check
344
// that these calls do not crash.
345
combined.set< config::int_node >("unset.base", 5);
346
combined.set< config::int_node >("unset.other", 5);
347
}
348
349
350
ATF_TEST_CASE_WITHOUT_HEAD(combine__dynamic_wins);
351
ATF_TEST_CASE_BODY(combine__dynamic_wins)
352
{
353
config::tree t1;
354
t1.define< config::int_node >("inner.leaf1");
355
t1.set< config::int_node >("inner.leaf1", 3);
356
357
config::tree t2;
358
t2.define_dynamic("inner");
359
t2.set_string("inner.leaf2", "4");
360
361
config::tree combined = t1.combine(t2);
362
363
config::tree expected;
364
expected.define_dynamic("inner");
365
expected.set_string("inner.leaf1", "3");
366
expected.set_string("inner.leaf2", "4");
367
368
ATF_REQUIRE(expected == combined);
369
370
// The combined inner node should have become dynamic so this call should
371
// not fail.
372
combined.set_string("inner.leaf3", "5");
373
}
374
375
376
ATF_TEST_CASE_WITHOUT_HEAD(combine__inner_leaf_mismatch);
377
ATF_TEST_CASE_BODY(combine__inner_leaf_mismatch)
378
{
379
config::tree t1;
380
t1.define< config::int_node >("top.foo.bar");
381
382
config::tree t2;
383
t2.define< config::int_node >("top.foo");
384
385
ATF_REQUIRE_THROW_RE(config::bad_combination_error,
386
"'top.foo' is an inner node in the base tree but a "
387
"leaf node in the overrides tree",
388
t1.combine(t2));
389
390
ATF_REQUIRE_THROW_RE(config::bad_combination_error,
391
"'top.foo' is a leaf node in the base tree but an "
392
"inner node in the overrides tree",
393
t2.combine(t1));
394
}
395
396
397
ATF_TEST_CASE_WITHOUT_HEAD(lookup__invalid_key);
398
ATF_TEST_CASE_BODY(lookup__invalid_key)
399
{
400
config::tree tree;
401
402
ATF_REQUIRE_THROW(config::invalid_key_error,
403
tree.lookup< config::int_node >("."));
404
}
405
406
407
ATF_TEST_CASE_WITHOUT_HEAD(lookup__unknown_key);
408
ATF_TEST_CASE_BODY(lookup__unknown_key)
409
{
410
config::tree tree;
411
412
tree.define< config::int_node >("foo.bar");
413
tree.define< config::int_node >("a.b.c");
414
tree.define_dynamic("a.d");
415
tree.set< config::int_node >("a.b.c", 123);
416
tree.set< config::int_node >("a.d.100", 0);
417
418
ATF_REQUIRE_THROW(config::unknown_key_error,
419
tree.lookup< config::int_node >("abc"));
420
421
ATF_REQUIRE_THROW(config::unknown_key_error,
422
tree.lookup< config::int_node >("foo"));
423
ATF_REQUIRE_THROW(config::unknown_key_error,
424
tree.lookup< config::int_node >("foo.bar"));
425
ATF_REQUIRE_THROW(config::unknown_key_error,
426
tree.lookup< config::int_node >("foo.bar.baz"));
427
428
ATF_REQUIRE_THROW(config::unknown_key_error,
429
tree.lookup< config::int_node >("a"));
430
ATF_REQUIRE_THROW(config::unknown_key_error,
431
tree.lookup< config::int_node >("a.b"));
432
ATF_REQUIRE_THROW(config::unknown_key_error,
433
tree.lookup< config::int_node >("a.c"));
434
(void)tree.lookup< config::int_node >("a.b.c");
435
ATF_REQUIRE_THROW(config::unknown_key_error,
436
tree.lookup< config::int_node >("a.b.c.d"));
437
ATF_REQUIRE_THROW(config::unknown_key_error,
438
tree.lookup< config::int_node >("a.d"));
439
(void)tree.lookup< config::int_node >("a.d.100");
440
ATF_REQUIRE_THROW(config::unknown_key_error,
441
tree.lookup< config::int_node >("a.d.101"));
442
ATF_REQUIRE_THROW(config::unknown_key_error,
443
tree.lookup< config::int_node >("a.d.100.3"));
444
ATF_REQUIRE_THROW(config::unknown_key_error,
445
tree.lookup< config::int_node >("a.d.e"));
446
}
447
448
449
ATF_TEST_CASE_WITHOUT_HEAD(is_set__one_level);
450
ATF_TEST_CASE_BODY(is_set__one_level)
451
{
452
config::tree tree;
453
454
tree.define< config::int_node >("var1");
455
tree.define< config::string_node >("var2");
456
tree.define< config::bool_node >("var3");
457
458
tree.set< config::int_node >("var1", 42);
459
tree.set< config::bool_node >("var3", false);
460
461
ATF_REQUIRE( tree.is_set("var1"));
462
ATF_REQUIRE(!tree.is_set("var2"));
463
ATF_REQUIRE( tree.is_set("var3"));
464
}
465
466
467
ATF_TEST_CASE_WITHOUT_HEAD(is_set__multiple_levels);
468
ATF_TEST_CASE_BODY(is_set__multiple_levels)
469
{
470
config::tree tree;
471
472
tree.define< config::int_node >("a.b.var1");
473
tree.define< config::string_node >("a.b.var2");
474
tree.define< config::bool_node >("e.var3");
475
476
tree.set< config::int_node >("a.b.var1", 42);
477
tree.set< config::bool_node >("e.var3", false);
478
479
ATF_REQUIRE(!tree.is_set("a"));
480
ATF_REQUIRE(!tree.is_set("a.b"));
481
ATF_REQUIRE( tree.is_set("a.b.var1"));
482
ATF_REQUIRE(!tree.is_set("a.b.var1.trailing"));
483
484
ATF_REQUIRE(!tree.is_set("a"));
485
ATF_REQUIRE(!tree.is_set("a.b"));
486
ATF_REQUIRE(!tree.is_set("a.b.var2"));
487
ATF_REQUIRE(!tree.is_set("a.b.var2.trailing"));
488
489
ATF_REQUIRE(!tree.is_set("e"));
490
ATF_REQUIRE( tree.is_set("e.var3"));
491
ATF_REQUIRE(!tree.is_set("e.var3.trailing"));
492
}
493
494
495
ATF_TEST_CASE_WITHOUT_HEAD(is_set__invalid_key);
496
ATF_TEST_CASE_BODY(is_set__invalid_key)
497
{
498
config::tree tree;
499
500
ATF_REQUIRE_THROW(config::invalid_key_error, tree.is_set(".abc"));
501
}
502
503
504
ATF_TEST_CASE_WITHOUT_HEAD(set__invalid_key);
505
ATF_TEST_CASE_BODY(set__invalid_key)
506
{
507
config::tree tree;
508
509
ATF_REQUIRE_THROW(config::invalid_key_error,
510
tree.set< config::int_node >("foo.", 54));
511
}
512
513
514
ATF_TEST_CASE_WITHOUT_HEAD(set__invalid_key_value);
515
ATF_TEST_CASE_BODY(set__invalid_key_value)
516
{
517
config::tree tree;
518
519
tree.define< config::int_node >("foo.bar");
520
tree.define_dynamic("a.d");
521
522
ATF_REQUIRE_THROW(config::invalid_key_value,
523
tree.set< config::int_node >("foo", 3));
524
ATF_REQUIRE_THROW(config::invalid_key_value,
525
tree.set< config::int_node >("a", -10));
526
}
527
528
529
ATF_TEST_CASE_WITHOUT_HEAD(set__unknown_key);
530
ATF_TEST_CASE_BODY(set__unknown_key)
531
{
532
config::tree tree;
533
534
tree.define< config::int_node >("foo.bar");
535
tree.define< config::int_node >("a.b.c");
536
tree.define_dynamic("a.d");
537
tree.set< config::int_node >("a.b.c", 123);
538
tree.set< config::string_node >("a.d.3", "foo");
539
540
ATF_REQUIRE_THROW(config::unknown_key_error,
541
tree.set< config::int_node >("abc", 2));
542
543
tree.set< config::int_node >("foo.bar", 15);
544
ATF_REQUIRE_THROW(config::unknown_key_error,
545
tree.set< config::int_node >("foo.bar.baz", 0));
546
547
ATF_REQUIRE_THROW(config::unknown_key_error,
548
tree.set< config::int_node >("a.c", 100));
549
tree.set< config::int_node >("a.b.c", -3);
550
ATF_REQUIRE_THROW(config::unknown_key_error,
551
tree.set< config::int_node >("a.b.c.d", 82));
552
tree.set< config::string_node >("a.d.3", "bar");
553
tree.set< config::string_node >("a.d.4", "bar");
554
ATF_REQUIRE_THROW(config::unknown_key_error,
555
tree.set< config::int_node >("a.d.4.5", 82));
556
tree.set< config::int_node >("a.d.5.6", 82);
557
}
558
559
560
ATF_TEST_CASE_WITHOUT_HEAD(set__unknown_key_not_strict);
561
ATF_TEST_CASE_BODY(set__unknown_key_not_strict)
562
{
563
config::tree tree(false);
564
565
tree.define< config::int_node >("foo.bar");
566
tree.define< config::int_node >("a.b.c");
567
tree.define_dynamic("a.d");
568
tree.set< config::int_node >("a.b.c", 123);
569
tree.set< config::string_node >("a.d.3", "foo");
570
571
tree.set< config::int_node >("abc", 2);
572
ATF_REQUIRE(!tree.is_set("abc"));
573
574
tree.set< config::int_node >("foo.bar", 15);
575
tree.set< config::int_node >("foo.bar.baz", 0);
576
ATF_REQUIRE(!tree.is_set("foo.bar.baz"));
577
578
tree.set< config::int_node >("a.c", 100);
579
ATF_REQUIRE(!tree.is_set("a.c"));
580
}
581
582
583
ATF_TEST_CASE_WITHOUT_HEAD(push_lua__ok);
584
ATF_TEST_CASE_BODY(push_lua__ok)
585
{
586
config::tree tree;
587
588
tree.define< config::int_node >("top.integer");
589
tree.define< wrapped_int_node >("top.custom");
590
tree.define_dynamic("dynamic");
591
tree.set< config::int_node >("top.integer", 5);
592
tree.set< wrapped_int_node >("top.custom", int_wrapper(10));
593
tree.set_string("dynamic.first", "foo");
594
595
lutok::state state;
596
tree.push_lua("top.integer", state);
597
tree.push_lua("top.custom", state);
598
tree.push_lua("dynamic.first", state);
599
ATF_REQUIRE(state.is_number(-3));
600
ATF_REQUIRE_EQ(5, state.to_integer(-3));
601
ATF_REQUIRE(state.is_number(-2));
602
ATF_REQUIRE_EQ(10, state.to_integer(-2));
603
ATF_REQUIRE(state.is_string(-1));
604
ATF_REQUIRE_EQ("foo", state.to_string(-1));
605
state.pop(3);
606
}
607
608
609
ATF_TEST_CASE_WITHOUT_HEAD(set_lua__ok);
610
ATF_TEST_CASE_BODY(set_lua__ok)
611
{
612
config::tree tree;
613
614
tree.define< config::int_node >("top.integer");
615
tree.define< wrapped_int_node >("top.custom");
616
tree.define_dynamic("dynamic");
617
618
{
619
lutok::state state;
620
state.push_integer(5);
621
state.push_integer(10);
622
state.push_string("foo");
623
tree.set_lua("top.integer", state, -3);
624
tree.set_lua("top.custom", state, -2);
625
tree.set_lua("dynamic.first", state, -1);
626
state.pop(3);
627
}
628
629
ATF_REQUIRE_EQ(5, tree.lookup< config::int_node >("top.integer"));
630
ATF_REQUIRE_EQ(10, tree.lookup< wrapped_int_node >("top.custom").value());
631
ATF_REQUIRE_EQ("foo", tree.lookup< config::string_node >("dynamic.first"));
632
}
633
634
635
ATF_TEST_CASE_WITHOUT_HEAD(lookup_rw);
636
ATF_TEST_CASE_BODY(lookup_rw)
637
{
638
config::tree tree;
639
640
tree.define< config::int_node >("var1");
641
tree.define< config::bool_node >("var3");
642
643
tree.set< config::int_node >("var1", 42);
644
tree.set< config::bool_node >("var3", false);
645
646
tree.lookup_rw< config::int_node >("var1") += 10;
647
ATF_REQUIRE_EQ(52, tree.lookup< config::int_node >("var1"));
648
ATF_REQUIRE(!tree.lookup< config::bool_node >("var3"));
649
}
650
651
652
ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__ok);
653
ATF_TEST_CASE_BODY(lookup_string__ok)
654
{
655
config::tree tree;
656
657
tree.define< config::int_node >("var1");
658
tree.define< config::string_node >("b.var2");
659
tree.define< config::bool_node >("c.d.var3");
660
661
tree.set< config::int_node >("var1", 42);
662
tree.set< config::string_node >("b.var2", "hello");
663
tree.set< config::bool_node >("c.d.var3", false);
664
665
ATF_REQUIRE_EQ("42", tree.lookup_string("var1"));
666
ATF_REQUIRE_EQ("hello", tree.lookup_string("b.var2"));
667
ATF_REQUIRE_EQ("false", tree.lookup_string("c.d.var3"));
668
}
669
670
671
ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__invalid_key);
672
ATF_TEST_CASE_BODY(lookup_string__invalid_key)
673
{
674
config::tree tree;
675
676
ATF_REQUIRE_THROW(config::invalid_key_error, tree.lookup_string(""));
677
}
678
679
680
ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__unknown_key);
681
ATF_TEST_CASE_BODY(lookup_string__unknown_key)
682
{
683
config::tree tree;
684
685
tree.define< config::int_node >("a.b.c");
686
687
ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup_string("a.b"));
688
ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup_string("a.b.c.d"));
689
}
690
691
692
ATF_TEST_CASE_WITHOUT_HEAD(set_string__ok);
693
ATF_TEST_CASE_BODY(set_string__ok)
694
{
695
config::tree tree;
696
697
tree.define< config::int_node >("foo.bar.1");
698
tree.define< config::string_node >("foo.bar.2");
699
tree.define_dynamic("sub.tree");
700
701
tree.set_string("foo.bar.1", "42");
702
tree.set_string("foo.bar.2", "hello");
703
tree.set_string("sub.tree.2", "15");
704
tree.set_string("sub.tree.3.4", "bye");
705
706
ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("foo.bar.1"));
707
ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("foo.bar.2"));
708
ATF_REQUIRE_EQ("15", tree.lookup< config::string_node >("sub.tree.2"));
709
ATF_REQUIRE_EQ("bye", tree.lookup< config::string_node >("sub.tree.3.4"));
710
}
711
712
713
ATF_TEST_CASE_WITHOUT_HEAD(set_string__invalid_key);
714
ATF_TEST_CASE_BODY(set_string__invalid_key)
715
{
716
config::tree tree;
717
718
ATF_REQUIRE_THROW(config::invalid_key_error, tree.set_string(".", "foo"));
719
}
720
721
722
ATF_TEST_CASE_WITHOUT_HEAD(set_string__invalid_key_value);
723
ATF_TEST_CASE_BODY(set_string__invalid_key_value)
724
{
725
config::tree tree;
726
727
tree.define< config::int_node >("foo.bar");
728
729
ATF_REQUIRE_THROW(config::invalid_key_value,
730
tree.set_string("foo", "abc"));
731
ATF_REQUIRE_THROW(config::invalid_key_value,
732
tree.set_string("foo.bar", " -3"));
733
ATF_REQUIRE_THROW(config::invalid_key_value,
734
tree.set_string("foo.bar", "3 "));
735
}
736
737
738
ATF_TEST_CASE_WITHOUT_HEAD(set_string__unknown_key);
739
ATF_TEST_CASE_BODY(set_string__unknown_key)
740
{
741
config::tree tree;
742
743
tree.define< config::int_node >("foo.bar");
744
tree.define< config::int_node >("a.b.c");
745
tree.define_dynamic("a.d");
746
tree.set_string("a.b.c", "123");
747
tree.set_string("a.d.3", "foo");
748
749
ATF_REQUIRE_THROW(config::unknown_key_error, tree.set_string("abc", "2"));
750
751
tree.set_string("foo.bar", "15");
752
ATF_REQUIRE_THROW(config::unknown_key_error,
753
tree.set_string("foo.bar.baz", "0"));
754
755
ATF_REQUIRE_THROW(config::unknown_key_error,
756
tree.set_string("a.c", "100"));
757
tree.set_string("a.b.c", "-3");
758
ATF_REQUIRE_THROW(config::unknown_key_error,
759
tree.set_string("a.b.c.d", "82"));
760
tree.set_string("a.d.3", "bar");
761
tree.set_string("a.d.4", "bar");
762
ATF_REQUIRE_THROW(config::unknown_key_error,
763
tree.set_string("a.d.4.5", "82"));
764
tree.set_string("a.d.5.6", "82");
765
}
766
767
768
ATF_TEST_CASE_WITHOUT_HEAD(set_string__unknown_key_not_strict);
769
ATF_TEST_CASE_BODY(set_string__unknown_key_not_strict)
770
{
771
config::tree tree(false);
772
773
tree.define< config::int_node >("foo.bar");
774
tree.define< config::int_node >("a.b.c");
775
tree.define_dynamic("a.d");
776
tree.set_string("a.b.c", "123");
777
tree.set_string("a.d.3", "foo");
778
779
tree.set_string("abc", "2");
780
ATF_REQUIRE(!tree.is_set("abc"));
781
782
tree.set_string("foo.bar", "15");
783
tree.set_string("foo.bar.baz", "0");
784
ATF_REQUIRE(!tree.is_set("foo.bar.baz"));
785
786
tree.set_string("a.c", "100");
787
ATF_REQUIRE(!tree.is_set("a.c"));
788
}
789
790
791
ATF_TEST_CASE_WITHOUT_HEAD(all_properties__none);
792
ATF_TEST_CASE_BODY(all_properties__none)
793
{
794
const config::tree tree;
795
ATF_REQUIRE(tree.all_properties().empty());
796
}
797
798
799
ATF_TEST_CASE_WITHOUT_HEAD(all_properties__all_set);
800
ATF_TEST_CASE_BODY(all_properties__all_set)
801
{
802
config::tree tree;
803
804
tree.define< config::int_node >("plain");
805
tree.set< config::int_node >("plain", 1234);
806
807
tree.define< config::int_node >("static.first");
808
tree.set< config::int_node >("static.first", -3);
809
tree.define< config::string_node >("static.second");
810
tree.set< config::string_node >("static.second", "some text");
811
812
tree.define_dynamic("dynamic");
813
tree.set< config::string_node >("dynamic.first", "hello");
814
tree.set< config::string_node >("dynamic.second", "bye");
815
816
config::properties_map exp_properties;
817
exp_properties["plain"] = "1234";
818
exp_properties["static.first"] = "-3";
819
exp_properties["static.second"] = "some text";
820
exp_properties["dynamic.first"] = "hello";
821
exp_properties["dynamic.second"] = "bye";
822
823
const config::properties_map properties = tree.all_properties();
824
ATF_REQUIRE(exp_properties == properties);
825
}
826
827
828
ATF_TEST_CASE_WITHOUT_HEAD(all_properties__some_unset);
829
ATF_TEST_CASE_BODY(all_properties__some_unset)
830
{
831
config::tree tree;
832
833
tree.define< config::int_node >("static.first");
834
tree.set< config::int_node >("static.first", -3);
835
tree.define< config::string_node >("static.second");
836
837
tree.define_dynamic("dynamic");
838
839
config::properties_map exp_properties;
840
exp_properties["static.first"] = "-3";
841
842
const config::properties_map properties = tree.all_properties();
843
ATF_REQUIRE(exp_properties == properties);
844
}
845
846
847
ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__inner);
848
ATF_TEST_CASE_BODY(all_properties__subtree__inner)
849
{
850
config::tree tree;
851
852
tree.define< config::int_node >("root.a.b.c.first");
853
tree.define< config::int_node >("root.a.b.c.second");
854
tree.define< config::int_node >("root.a.d.first");
855
856
tree.set< config::int_node >("root.a.b.c.first", 1);
857
tree.set< config::int_node >("root.a.b.c.second", 2);
858
tree.set< config::int_node >("root.a.d.first", 3);
859
860
{
861
config::properties_map exp_properties;
862
exp_properties["root.a.b.c.first"] = "1";
863
exp_properties["root.a.b.c.second"] = "2";
864
exp_properties["root.a.d.first"] = "3";
865
ATF_REQUIRE(exp_properties == tree.all_properties("root"));
866
ATF_REQUIRE(exp_properties == tree.all_properties("root.a"));
867
}
868
869
{
870
config::properties_map exp_properties;
871
exp_properties["root.a.b.c.first"] = "1";
872
exp_properties["root.a.b.c.second"] = "2";
873
ATF_REQUIRE(exp_properties == tree.all_properties("root.a.b"));
874
ATF_REQUIRE(exp_properties == tree.all_properties("root.a.b.c"));
875
}
876
877
{
878
config::properties_map exp_properties;
879
exp_properties["root.a.d.first"] = "3";
880
ATF_REQUIRE(exp_properties == tree.all_properties("root.a.d"));
881
}
882
}
883
884
885
ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__leaf);
886
ATF_TEST_CASE_BODY(all_properties__subtree__leaf)
887
{
888
config::tree tree;
889
890
tree.define< config::int_node >("root.a.b.c.first");
891
tree.set< config::int_node >("root.a.b.c.first", 1);
892
ATF_REQUIRE_THROW_RE(config::value_error, "Cannot export.*leaf",
893
tree.all_properties("root.a.b.c.first"));
894
}
895
896
897
ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__strip_key);
898
ATF_TEST_CASE_BODY(all_properties__subtree__strip_key)
899
{
900
config::tree tree;
901
902
tree.define< config::int_node >("root.a.b.c.first");
903
tree.define< config::int_node >("root.a.b.c.second");
904
tree.define< config::int_node >("root.a.d.first");
905
906
tree.set< config::int_node >("root.a.b.c.first", 1);
907
tree.set< config::int_node >("root.a.b.c.second", 2);
908
tree.set< config::int_node >("root.a.d.first", 3);
909
910
config::properties_map exp_properties;
911
exp_properties["b.c.first"] = "1";
912
exp_properties["b.c.second"] = "2";
913
exp_properties["d.first"] = "3";
914
ATF_REQUIRE(exp_properties == tree.all_properties("root.a", true));
915
}
916
917
918
ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__invalid_key);
919
ATF_TEST_CASE_BODY(all_properties__subtree__invalid_key)
920
{
921
config::tree tree;
922
923
ATF_REQUIRE_THROW(config::invalid_key_error, tree.all_properties("."));
924
}
925
926
927
ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__unknown_key);
928
ATF_TEST_CASE_BODY(all_properties__subtree__unknown_key)
929
{
930
config::tree tree;
931
932
tree.define< config::int_node >("root.a.b.c.first");
933
tree.set< config::int_node >("root.a.b.c.first", 1);
934
tree.define< config::int_node >("root.a.b.c.unset");
935
936
ATF_REQUIRE_THROW(config::unknown_key_error,
937
tree.all_properties("root.a.b.c.first.foo"));
938
ATF_REQUIRE_THROW_RE(config::value_error, "Cannot export.*leaf",
939
tree.all_properties("root.a.b.c.unset"));
940
}
941
942
943
ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__empty);
944
ATF_TEST_CASE_BODY(operators_eq_and_ne__empty)
945
{
946
config::tree t1;
947
config::tree t2;
948
ATF_REQUIRE( t1 == t2);
949
ATF_REQUIRE(!(t1 != t2));
950
}
951
952
953
ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__shallow_copy);
954
ATF_TEST_CASE_BODY(operators_eq_and_ne__shallow_copy)
955
{
956
config::tree t1;
957
t1.define< config::int_node >("root.a.b.c.first");
958
t1.set< config::int_node >("root.a.b.c.first", 1);
959
config::tree t2 = t1;
960
ATF_REQUIRE( t1 == t2);
961
ATF_REQUIRE(!(t1 != t2));
962
}
963
964
965
ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__deep_copy);
966
ATF_TEST_CASE_BODY(operators_eq_and_ne__deep_copy)
967
{
968
config::tree t1;
969
t1.define< config::int_node >("root.a.b.c.first");
970
t1.set< config::int_node >("root.a.b.c.first", 1);
971
config::tree t2 = t1.deep_copy();
972
ATF_REQUIRE( t1 == t2);
973
ATF_REQUIRE(!(t1 != t2));
974
}
975
976
977
ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__some_contents);
978
ATF_TEST_CASE_BODY(operators_eq_and_ne__some_contents)
979
{
980
config::tree t1, t2;
981
982
t1.define< config::int_node >("root.a.b.c.first");
983
t1.set< config::int_node >("root.a.b.c.first", 1);
984
ATF_REQUIRE(!(t1 == t2));
985
ATF_REQUIRE( t1 != t2);
986
987
t2.define< config::int_node >("root.a.b.c.first");
988
t2.set< config::int_node >("root.a.b.c.first", 1);
989
ATF_REQUIRE( t1 == t2);
990
ATF_REQUIRE(!(t1 != t2));
991
992
t1.set< config::int_node >("root.a.b.c.first", 2);
993
ATF_REQUIRE(!(t1 == t2));
994
ATF_REQUIRE( t1 != t2);
995
996
t2.set< config::int_node >("root.a.b.c.first", 2);
997
ATF_REQUIRE( t1 == t2);
998
ATF_REQUIRE(!(t1 != t2));
999
1000
t1.define< config::string_node >("another.key");
1001
t1.set< config::string_node >("another.key", "some text");
1002
ATF_REQUIRE(!(t1 == t2));
1003
ATF_REQUIRE( t1 != t2);
1004
1005
t2.define< config::string_node >("another.key");
1006
t2.set< config::string_node >("another.key", "some text");
1007
ATF_REQUIRE( t1 == t2);
1008
ATF_REQUIRE(!(t1 != t2));
1009
}
1010
1011
1012
ATF_TEST_CASE_WITHOUT_HEAD(custom_leaf__no_default_ctor);
1013
ATF_TEST_CASE_BODY(custom_leaf__no_default_ctor)
1014
{
1015
config::tree tree;
1016
1017
tree.define< wrapped_int_node >("test1");
1018
tree.define< wrapped_int_node >("test2");
1019
tree.set< wrapped_int_node >("test1", int_wrapper(5));
1020
tree.set< wrapped_int_node >("test2", int_wrapper(10));
1021
const int_wrapper& test1 = tree.lookup< wrapped_int_node >("test1");
1022
ATF_REQUIRE_EQ(5, test1.value());
1023
const int_wrapper& test2 = tree.lookup< wrapped_int_node >("test2");
1024
ATF_REQUIRE_EQ(10, test2.value());
1025
}
1026
1027
1028
ATF_INIT_TEST_CASES(tcs)
1029
{
1030
ATF_ADD_TEST_CASE(tcs, define_set_lookup__one_level);
1031
ATF_ADD_TEST_CASE(tcs, define_set_lookup__multiple_levels);
1032
1033
ATF_ADD_TEST_CASE(tcs, deep_copy__empty);
1034
ATF_ADD_TEST_CASE(tcs, deep_copy__some);
1035
1036
ATF_ADD_TEST_CASE(tcs, combine__empty);
1037
ATF_ADD_TEST_CASE(tcs, combine__same_layout__no_overrides);
1038
ATF_ADD_TEST_CASE(tcs, combine__same_layout__no_base);
1039
ATF_ADD_TEST_CASE(tcs, combine__same_layout__mix);
1040
ATF_ADD_TEST_CASE(tcs, combine__different_layout);
1041
ATF_ADD_TEST_CASE(tcs, combine__dynamic_wins);
1042
ATF_ADD_TEST_CASE(tcs, combine__inner_leaf_mismatch);
1043
1044
ATF_ADD_TEST_CASE(tcs, lookup__invalid_key);
1045
ATF_ADD_TEST_CASE(tcs, lookup__unknown_key);
1046
1047
ATF_ADD_TEST_CASE(tcs, is_set__one_level);
1048
ATF_ADD_TEST_CASE(tcs, is_set__multiple_levels);
1049
ATF_ADD_TEST_CASE(tcs, is_set__invalid_key);
1050
1051
ATF_ADD_TEST_CASE(tcs, set__invalid_key);
1052
ATF_ADD_TEST_CASE(tcs, set__invalid_key_value);
1053
ATF_ADD_TEST_CASE(tcs, set__unknown_key);
1054
ATF_ADD_TEST_CASE(tcs, set__unknown_key_not_strict);
1055
1056
ATF_ADD_TEST_CASE(tcs, push_lua__ok);
1057
ATF_ADD_TEST_CASE(tcs, set_lua__ok);
1058
1059
ATF_ADD_TEST_CASE(tcs, lookup_rw);
1060
1061
ATF_ADD_TEST_CASE(tcs, lookup_string__ok);
1062
ATF_ADD_TEST_CASE(tcs, lookup_string__invalid_key);
1063
ATF_ADD_TEST_CASE(tcs, lookup_string__unknown_key);
1064
1065
ATF_ADD_TEST_CASE(tcs, set_string__ok);
1066
ATF_ADD_TEST_CASE(tcs, set_string__invalid_key);
1067
ATF_ADD_TEST_CASE(tcs, set_string__invalid_key_value);
1068
ATF_ADD_TEST_CASE(tcs, set_string__unknown_key);
1069
ATF_ADD_TEST_CASE(tcs, set_string__unknown_key_not_strict);
1070
1071
ATF_ADD_TEST_CASE(tcs, all_properties__none);
1072
ATF_ADD_TEST_CASE(tcs, all_properties__all_set);
1073
ATF_ADD_TEST_CASE(tcs, all_properties__some_unset);
1074
ATF_ADD_TEST_CASE(tcs, all_properties__subtree__inner);
1075
ATF_ADD_TEST_CASE(tcs, all_properties__subtree__leaf);
1076
ATF_ADD_TEST_CASE(tcs, all_properties__subtree__strip_key);
1077
ATF_ADD_TEST_CASE(tcs, all_properties__subtree__invalid_key);
1078
ATF_ADD_TEST_CASE(tcs, all_properties__subtree__unknown_key);
1079
1080
ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__empty);
1081
ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__shallow_copy);
1082
ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__deep_copy);
1083
ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__some_contents);
1084
1085
ATF_ADD_TEST_CASE(tcs, custom_leaf__no_default_ctor);
1086
}
1087
1088