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/nodes.ipp"
30
31#include <atf-c++.hpp>
32
33#include <lutok/state.ipp>
34
35#include "utils/config/exceptions.hpp"
36#include "utils/config/keys.hpp"
37#include "utils/defs.hpp"
38
39namespace config = utils::config;
40
41
42namespace {
43
44
45/// Typed leaf node that specializes the validate() method.
46class validation_node : public config::int_node {
47    /// Checks a given value for validity against a fake value.
48    ///
49    /// \param new_value The value to validate.
50    ///
51    /// \throw value_error If the value is not valid.
52    void
53    validate(const value_type& new_value) const
54    {
55        if (new_value == 12345)
56            throw config::value_error("Custom validate method");
57    }
58};
59
60
61/// Set node that specializes the validate() method.
62class set_validation_node : public config::strings_set_node {
63    /// Checks a given value for validity against a fake value.
64    ///
65    /// \param new_value The value to validate.
66    ///
67    /// \throw value_error If the value is not valid.
68    void
69    validate(const value_type& new_value) const
70    {
71        for (value_type::const_iterator iter = new_value.begin();
72             iter != new_value.end(); ++iter)
73            if (*iter == "throw")
74                throw config::value_error("Custom validate method");
75    }
76};
77
78
79}  // anonymous namespace
80
81
82ATF_TEST_CASE_WITHOUT_HEAD(bool_node__deep_copy);
83ATF_TEST_CASE_BODY(bool_node__deep_copy)
84{
85    config::bool_node node;
86    node.set(true);
87    config::detail::base_node* raw_copy = node.deep_copy();
88    config::bool_node* copy = static_cast< config::bool_node* >(raw_copy);
89    ATF_REQUIRE(copy->value());
90    copy->set(false);
91    ATF_REQUIRE(node.value());
92    ATF_REQUIRE(!copy->value());
93    delete copy;
94}
95
96
97ATF_TEST_CASE_WITHOUT_HEAD(bool_node__is_set_and_set);
98ATF_TEST_CASE_BODY(bool_node__is_set_and_set)
99{
100    config::bool_node node;
101    ATF_REQUIRE(!node.is_set());
102    node.set(false);
103    ATF_REQUIRE( node.is_set());
104}
105
106
107ATF_TEST_CASE_WITHOUT_HEAD(bool_node__value_and_set);
108ATF_TEST_CASE_BODY(bool_node__value_and_set)
109{
110    config::bool_node node;
111    node.set(false);
112    ATF_REQUIRE(!node.value());
113    node.set(true);
114    ATF_REQUIRE( node.value());
115}
116
117
118ATF_TEST_CASE_WITHOUT_HEAD(bool_node__push_lua);
119ATF_TEST_CASE_BODY(bool_node__push_lua)
120{
121    lutok::state state;
122
123    config::bool_node node;
124    node.set(true);
125    node.push_lua(state);
126    ATF_REQUIRE(state.is_boolean(-1));
127    ATF_REQUIRE(state.to_boolean(-1));
128    state.pop(1);
129}
130
131
132ATF_TEST_CASE_WITHOUT_HEAD(bool_node__set_lua__ok);
133ATF_TEST_CASE_BODY(bool_node__set_lua__ok)
134{
135    lutok::state state;
136
137    config::bool_node node;
138    state.push_boolean(false);
139    node.set_lua(state, -1);
140    state.pop(1);
141    ATF_REQUIRE(!node.value());
142}
143
144
145ATF_TEST_CASE_WITHOUT_HEAD(bool_node__set_lua__invalid_value);
146ATF_TEST_CASE_BODY(bool_node__set_lua__invalid_value)
147{
148    lutok::state state;
149
150    config::bool_node node;
151    state.push_string("foo bar");
152    ATF_REQUIRE_THROW(config::value_error, node.set_lua(state, -1));
153    state.pop(1);
154    ATF_REQUIRE(!node.is_set());
155}
156
157
158ATF_TEST_CASE_WITHOUT_HEAD(bool_node__set_string__ok);
159ATF_TEST_CASE_BODY(bool_node__set_string__ok)
160{
161    config::bool_node node;
162    node.set_string("false");
163    ATF_REQUIRE(!node.value());
164    node.set_string("true");
165    ATF_REQUIRE( node.value());
166}
167
168
169ATF_TEST_CASE_WITHOUT_HEAD(bool_node__set_string__invalid_value);
170ATF_TEST_CASE_BODY(bool_node__set_string__invalid_value)
171{
172    config::bool_node node;
173    ATF_REQUIRE_THROW(config::value_error, node.set_string("12345"));
174    ATF_REQUIRE(!node.is_set());
175}
176
177
178ATF_TEST_CASE_WITHOUT_HEAD(bool_node__to_string);
179ATF_TEST_CASE_BODY(bool_node__to_string)
180{
181    config::bool_node node;
182    node.set(false);
183    ATF_REQUIRE_EQ("false", node.to_string());
184    node.set(true);
185    ATF_REQUIRE_EQ("true", node.to_string());
186}
187
188
189ATF_TEST_CASE_WITHOUT_HEAD(int_node__deep_copy);
190ATF_TEST_CASE_BODY(int_node__deep_copy)
191{
192    config::int_node node;
193    node.set(5);
194    config::detail::base_node* raw_copy = node.deep_copy();
195    config::int_node* copy = static_cast< config::int_node* >(raw_copy);
196    ATF_REQUIRE_EQ(5, copy->value());
197    copy->set(10);
198    ATF_REQUIRE_EQ(5, node.value());
199    ATF_REQUIRE_EQ(10, copy->value());
200    delete copy;
201}
202
203
204ATF_TEST_CASE_WITHOUT_HEAD(int_node__is_set_and_set);
205ATF_TEST_CASE_BODY(int_node__is_set_and_set)
206{
207    config::int_node node;
208    ATF_REQUIRE(!node.is_set());
209    node.set(20);
210    ATF_REQUIRE( node.is_set());
211}
212
213
214ATF_TEST_CASE_WITHOUT_HEAD(int_node__value_and_set);
215ATF_TEST_CASE_BODY(int_node__value_and_set)
216{
217    config::int_node node;
218    node.set(20);
219    ATF_REQUIRE_EQ(20, node.value());
220    node.set(0);
221    ATF_REQUIRE_EQ(0, node.value());
222}
223
224
225ATF_TEST_CASE_WITHOUT_HEAD(int_node__push_lua);
226ATF_TEST_CASE_BODY(int_node__push_lua)
227{
228    lutok::state state;
229
230    config::int_node node;
231    node.set(754);
232    node.push_lua(state);
233    ATF_REQUIRE(state.is_number(-1));
234    ATF_REQUIRE_EQ(754, state.to_integer(-1));
235    state.pop(1);
236}
237
238
239ATF_TEST_CASE_WITHOUT_HEAD(int_node__set_lua__ok);
240ATF_TEST_CASE_BODY(int_node__set_lua__ok)
241{
242    lutok::state state;
243
244    config::int_node node;
245    state.push_integer(123);
246    state.push_string("456");
247    node.set_lua(state, -2);
248    ATF_REQUIRE_EQ(123, node.value());
249    node.set_lua(state, -1);
250    ATF_REQUIRE_EQ(456, node.value());
251    state.pop(2);
252}
253
254
255ATF_TEST_CASE_WITHOUT_HEAD(int_node__set_lua__invalid_value);
256ATF_TEST_CASE_BODY(int_node__set_lua__invalid_value)
257{
258    lutok::state state;
259
260    config::int_node node;
261    state.push_boolean(true);
262    ATF_REQUIRE_THROW(config::value_error, node.set_lua(state, -1));
263    state.pop(1);
264    ATF_REQUIRE(!node.is_set());
265}
266
267
268ATF_TEST_CASE_WITHOUT_HEAD(int_node__set_string__ok);
269ATF_TEST_CASE_BODY(int_node__set_string__ok)
270{
271    config::int_node node;
272    node.set_string("178");
273    ATF_REQUIRE_EQ(178, node.value());
274    node.set_string("-123");
275    ATF_REQUIRE_EQ(-123, node.value());
276}
277
278
279ATF_TEST_CASE_WITHOUT_HEAD(int_node__set_string__invalid_value);
280ATF_TEST_CASE_BODY(int_node__set_string__invalid_value)
281{
282    config::int_node node;
283    ATF_REQUIRE_THROW(config::value_error, node.set_string(" 23"));
284    ATF_REQUIRE(!node.is_set());
285}
286
287
288ATF_TEST_CASE_WITHOUT_HEAD(int_node__to_string);
289ATF_TEST_CASE_BODY(int_node__to_string)
290{
291    config::int_node node;
292    node.set(89);
293    ATF_REQUIRE_EQ("89", node.to_string());
294    node.set(-57);
295    ATF_REQUIRE_EQ("-57", node.to_string());
296}
297
298
299ATF_TEST_CASE_WITHOUT_HEAD(string_node__deep_copy);
300ATF_TEST_CASE_BODY(string_node__deep_copy)
301{
302    config::string_node node;
303    node.set("first");
304    config::detail::base_node* raw_copy = node.deep_copy();
305    config::string_node* copy = static_cast< config::string_node* >(raw_copy);
306    ATF_REQUIRE_EQ("first", copy->value());
307    copy->set("second");
308    ATF_REQUIRE_EQ("first", node.value());
309    ATF_REQUIRE_EQ("second", copy->value());
310    delete copy;
311}
312
313
314ATF_TEST_CASE_WITHOUT_HEAD(string_node__is_set_and_set);
315ATF_TEST_CASE_BODY(string_node__is_set_and_set)
316{
317    config::string_node node;
318    ATF_REQUIRE(!node.is_set());
319    node.set("foo");
320    ATF_REQUIRE( node.is_set());
321}
322
323
324ATF_TEST_CASE_WITHOUT_HEAD(string_node__value_and_set);
325ATF_TEST_CASE_BODY(string_node__value_and_set)
326{
327    config::string_node node;
328    node.set("foo");
329    ATF_REQUIRE_EQ("foo", node.value());
330    node.set("");
331    ATF_REQUIRE_EQ("", node.value());
332}
333
334
335ATF_TEST_CASE_WITHOUT_HEAD(string_node__push_lua);
336ATF_TEST_CASE_BODY(string_node__push_lua)
337{
338    lutok::state state;
339
340    config::string_node node;
341    node.set("some message");
342    node.push_lua(state);
343    ATF_REQUIRE(state.is_string(-1));
344    ATF_REQUIRE_EQ("some message", state.to_string(-1));
345    state.pop(1);
346}
347
348
349ATF_TEST_CASE_WITHOUT_HEAD(string_node__set_lua__ok);
350ATF_TEST_CASE_BODY(string_node__set_lua__ok)
351{
352    lutok::state state;
353
354    config::string_node node;
355    state.push_string("text 1");
356    state.push_integer(231);
357    node.set_lua(state, -2);
358    ATF_REQUIRE_EQ("text 1", node.value());
359    node.set_lua(state, -1);
360    ATF_REQUIRE_EQ("231", node.value());
361    state.pop(2);
362}
363
364
365ATF_TEST_CASE_WITHOUT_HEAD(string_node__set_lua__invalid_value);
366ATF_TEST_CASE_BODY(string_node__set_lua__invalid_value)
367{
368    lutok::state state;
369
370    config::bool_node node;
371    state.new_table();
372    ATF_REQUIRE_THROW(config::value_error, node.set_lua(state, -1));
373    state.pop(1);
374    ATF_REQUIRE(!node.is_set());
375}
376
377
378ATF_TEST_CASE_WITHOUT_HEAD(string_node__set_string);
379ATF_TEST_CASE_BODY(string_node__set_string)
380{
381    config::string_node node;
382    node.set_string("abcd efgh");
383    ATF_REQUIRE_EQ("abcd efgh", node.value());
384    node.set_string("  1234  ");
385    ATF_REQUIRE_EQ("  1234  ", node.value());
386}
387
388
389ATF_TEST_CASE_WITHOUT_HEAD(string_node__to_string);
390ATF_TEST_CASE_BODY(string_node__to_string)
391{
392    config::string_node node;
393    node.set("");
394    ATF_REQUIRE_EQ("", node.to_string());
395    node.set("aaa");
396    ATF_REQUIRE_EQ("aaa", node.to_string());
397}
398
399
400ATF_TEST_CASE_WITHOUT_HEAD(strings_set_node__deep_copy);
401ATF_TEST_CASE_BODY(strings_set_node__deep_copy)
402{
403    std::set< std::string > value;
404    config::strings_set_node node;
405    value.insert("foo");
406    node.set(value);
407    config::detail::base_node* raw_copy = node.deep_copy();
408    config::strings_set_node* copy =
409        static_cast< config::strings_set_node* >(raw_copy);
410    value.insert("bar");
411    ATF_REQUIRE_EQ(1, copy->value().size());
412    copy->set(value);
413    ATF_REQUIRE_EQ(1, node.value().size());
414    ATF_REQUIRE_EQ(2, copy->value().size());
415    delete copy;
416}
417
418
419ATF_TEST_CASE_WITHOUT_HEAD(strings_set_node__is_set_and_set);
420ATF_TEST_CASE_BODY(strings_set_node__is_set_and_set)
421{
422    std::set< std::string > value;
423    value.insert("foo");
424
425    config::strings_set_node node;
426    ATF_REQUIRE(!node.is_set());
427    node.set(value);
428    ATF_REQUIRE( node.is_set());
429}
430
431
432ATF_TEST_CASE_WITHOUT_HEAD(strings_set_node__value_and_set);
433ATF_TEST_CASE_BODY(strings_set_node__value_and_set)
434{
435    std::set< std::string > value;
436    value.insert("first");
437
438    config::strings_set_node node;
439    node.set(value);
440    ATF_REQUIRE(value == node.value());
441    value.clear();
442    node.set(value);
443    value.insert("second");
444    ATF_REQUIRE(node.value().empty());
445}
446
447
448ATF_TEST_CASE_WITHOUT_HEAD(strings_set_node__set_string);
449ATF_TEST_CASE_BODY(strings_set_node__set_string)
450{
451    config::strings_set_node node;
452    {
453        std::set< std::string > expected;
454        expected.insert("abcd");
455        expected.insert("efgh");
456
457        node.set_string("abcd efgh");
458        ATF_REQUIRE(expected == node.value());
459    }
460    {
461        std::set< std::string > expected;
462        expected.insert("1234");
463
464        node.set_string("  1234  ");
465        ATF_REQUIRE(expected == node.value());
466    }
467}
468
469
470ATF_TEST_CASE_WITHOUT_HEAD(strings_set_node__to_string);
471ATF_TEST_CASE_BODY(strings_set_node__to_string)
472{
473    std::set< std::string > value;
474    config::strings_set_node node;
475    value.insert("second");
476    value.insert("first");
477    node.set(value);
478    ATF_REQUIRE_EQ("first second", node.to_string());
479}
480
481
482ATF_TEST_CASE_WITHOUT_HEAD(typed_leaf_node__validate_set);
483ATF_TEST_CASE_BODY(typed_leaf_node__validate_set)
484{
485    validation_node node;
486    node.set(1234);
487    ATF_REQUIRE_THROW_RE(config::value_error, "Custom validate method",
488                         node.set(12345));
489}
490
491
492ATF_TEST_CASE_WITHOUT_HEAD(typed_leaf_node__validate_set_string);
493ATF_TEST_CASE_BODY(typed_leaf_node__validate_set_string)
494{
495    validation_node node;
496    node.set_string("1234");
497    ATF_REQUIRE_THROW_RE(config::value_error, "Custom validate method",
498                         node.set_string("12345"));
499}
500
501
502ATF_TEST_CASE_WITHOUT_HEAD(base_set_node__validate_set);
503ATF_TEST_CASE_BODY(base_set_node__validate_set)
504{
505    set_validation_node node;
506    set_validation_node::value_type values;
507    values.insert("foo");
508    values.insert("bar");
509    node.set(values);
510    values.insert("throw");
511    values.insert("baz");
512    ATF_REQUIRE_THROW_RE(config::value_error, "Custom validate method",
513                         node.set(values));
514}
515
516
517ATF_TEST_CASE_WITHOUT_HEAD(base_set_node__validate_set_string);
518ATF_TEST_CASE_BODY(base_set_node__validate_set_string)
519{
520    set_validation_node node;
521    node.set_string("foo bar");
522    ATF_REQUIRE_THROW_RE(config::value_error, "Custom validate method",
523                         node.set_string("foo bar throw baz"));
524}
525
526
527ATF_INIT_TEST_CASES(tcs)
528{
529    ATF_ADD_TEST_CASE(tcs, bool_node__deep_copy);
530    ATF_ADD_TEST_CASE(tcs, bool_node__is_set_and_set);
531    ATF_ADD_TEST_CASE(tcs, bool_node__value_and_set);
532    ATF_ADD_TEST_CASE(tcs, bool_node__push_lua);
533    ATF_ADD_TEST_CASE(tcs, bool_node__set_lua__ok);
534    ATF_ADD_TEST_CASE(tcs, bool_node__set_lua__invalid_value);
535    ATF_ADD_TEST_CASE(tcs, bool_node__set_string__ok);
536    ATF_ADD_TEST_CASE(tcs, bool_node__set_string__invalid_value);
537    ATF_ADD_TEST_CASE(tcs, bool_node__to_string);
538
539    ATF_ADD_TEST_CASE(tcs, int_node__deep_copy);
540    ATF_ADD_TEST_CASE(tcs, int_node__is_set_and_set);
541    ATF_ADD_TEST_CASE(tcs, int_node__value_and_set);
542    ATF_ADD_TEST_CASE(tcs, int_node__push_lua);
543    ATF_ADD_TEST_CASE(tcs, int_node__set_lua__ok);
544    ATF_ADD_TEST_CASE(tcs, int_node__set_lua__invalid_value);
545    ATF_ADD_TEST_CASE(tcs, int_node__set_string__ok);
546    ATF_ADD_TEST_CASE(tcs, int_node__set_string__invalid_value);
547    ATF_ADD_TEST_CASE(tcs, int_node__to_string);
548
549    ATF_ADD_TEST_CASE(tcs, string_node__deep_copy);
550    ATF_ADD_TEST_CASE(tcs, string_node__is_set_and_set);
551    ATF_ADD_TEST_CASE(tcs, string_node__value_and_set);
552    ATF_ADD_TEST_CASE(tcs, string_node__push_lua);
553    ATF_ADD_TEST_CASE(tcs, string_node__set_lua__ok);
554    ATF_ADD_TEST_CASE(tcs, string_node__set_lua__invalid_value);
555    ATF_ADD_TEST_CASE(tcs, string_node__set_string);
556    ATF_ADD_TEST_CASE(tcs, string_node__to_string);
557
558    ATF_ADD_TEST_CASE(tcs, strings_set_node__deep_copy);
559    ATF_ADD_TEST_CASE(tcs, strings_set_node__is_set_and_set);
560    ATF_ADD_TEST_CASE(tcs, strings_set_node__value_and_set);
561    ATF_ADD_TEST_CASE(tcs, strings_set_node__set_string);
562    ATF_ADD_TEST_CASE(tcs, strings_set_node__to_string);
563
564    ATF_ADD_TEST_CASE(tcs, typed_leaf_node__validate_set);
565    ATF_ADD_TEST_CASE(tcs, typed_leaf_node__validate_set_string);
566    ATF_ADD_TEST_CASE(tcs, base_set_node__validate_set);
567    ATF_ADD_TEST_CASE(tcs, base_set_node__validate_set_string);
568}
569