The Battle for Wesnoth  1.15.0-dev
test_config.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2018 by Chris Beck <render787@gmail.com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-test"
16 
17 #include <boost/test/unit_test.hpp>
18 #include <cmath>
19 
20 #include "config.hpp"
21 #include "variable_info.hpp"
22 
23 BOOST_AUTO_TEST_SUITE ( test_config )
24 
25 BOOST_AUTO_TEST_CASE ( test_config_attribute_value )
26 {
27  config c;
28  const config& cc = c;
29  int x_int;
30  std::string x_str;
31  long long x_sll;
32  double x_dbl;
33 
34  c["x"] = 1;
35  x_str = c["x"].str();
36  BOOST_CHECK_EQUAL(x_str, "1");
37  x_int = c["x"].to_int();
38  BOOST_CHECK_EQUAL(x_int, 1);
39  x_sll = c["x"].to_long_long();
40  BOOST_CHECK_EQUAL(x_sll, 1ll);
41  x_dbl = c["x"].to_double();
42  BOOST_CHECK_EQUAL(x_dbl, 1.0);
43 
44 
45  c["x"] = 10000000;
46  x_int = c["x"].to_int();
47  BOOST_CHECK_EQUAL(x_int, 10000000);
48  x_str = c["x"].str();
49  BOOST_CHECK_EQUAL(x_str, "10000000");
50  x_sll = c["x"].to_long_long();
51  BOOST_CHECK_EQUAL(x_sll, 10000000ll);
52  x_dbl = c["x"].to_double();
53  BOOST_CHECK_EQUAL(x_dbl, 1e7);
54 
55  c["x"] = "";
56  x_sll = c["x"].to_long_long();
57  BOOST_CHECK_EQUAL(x_sll, 0ll);
58  x_str = c["x"].str();
59  BOOST_CHECK_EQUAL(x_str, "");
60  x_int = c["x"].to_int();
61  BOOST_CHECK_EQUAL(x_int, 0);
62  x_dbl = c["x"].to_double();
63  BOOST_CHECK_EQUAL(x_dbl, 0.0);
64 
65 
66  c["x"] = "0x11";
67  x_int = c["x"].to_int();
68  BOOST_CHECK_EQUAL(x_int, 0);
69  x_str = c["x"].str();
70  BOOST_CHECK_EQUAL(x_str, "0x11");
71  x_sll = c["x"].to_long_long();
72  BOOST_CHECK_EQUAL(x_sll, 0ll);
73  x_dbl = c["x"].to_double();
74  BOOST_CHECK_EQUAL(x_dbl, 0.0);
75 
76 
77  c["x"] = "0xab";
78  x_int = c["x"].to_int();
79  BOOST_CHECK_EQUAL(x_int, 0);
80  x_str = c["x"].str();
81  BOOST_CHECK_EQUAL(x_str, "0xab");
82  x_sll = c["x"].to_long_long();
83  BOOST_CHECK_EQUAL(x_sll, 0ll);
84  x_dbl = c["x"].to_double();
85  BOOST_CHECK_EQUAL(x_dbl, 0.0);
86 
87 
88  c["x"] = "00001111";
89  x_int = c["x"].to_int();
90  BOOST_CHECK_EQUAL(x_int, 1111);
91  x_str = c["x"].str();
92  BOOST_CHECK_EQUAL(x_str, "00001111");
93  x_sll = c["x"].to_long_long();
94  BOOST_CHECK_EQUAL(x_sll, 1111ll);
95  x_dbl = c["x"].to_double();
96  BOOST_CHECK_EQUAL(x_dbl, 1.111e3);
97 
98 
99  c["x"] = "000000";
100  x_int = c["x"].to_int();
101  BOOST_CHECK_EQUAL(x_int, 0);
102  x_str = c["x"].str();
103  BOOST_CHECK_EQUAL(x_str,"000000");
104  x_sll = c["x"].to_long_long();
105  BOOST_CHECK_EQUAL(x_sll, 0ll);
106  x_dbl = c["x"].to_double();
107  BOOST_CHECK_EQUAL(x_dbl, 0.0);
108 
109 
110  c["x"] = "01234567890123456789";
111  x_sll = c["x"].to_long_long();
112  BOOST_CHECK_EQUAL(x_sll,1234567890123456789ll);
113  x_str = c["x"].str();
114  BOOST_CHECK_EQUAL(x_str,"01234567890123456789");
115  x_int = c["x"].to_int();
116  BOOST_CHECK_EQUAL(x_int, 0);
117  x_dbl = c["x"].to_double();
118  BOOST_CHECK_EQUAL(x_dbl, 1.23456789012345678e18);
119 
120 
121  c["x"] = "99999999999999999999";
122  x_sll = c["x"].to_long_long();
123  BOOST_CHECK_EQUAL(x_sll, 0ll);
124  x_str = c["x"].str();
125  BOOST_CHECK_EQUAL(x_str, "99999999999999999999");
126  x_int = c["x"].to_int();
127  BOOST_CHECK_EQUAL(x_int, 0);
128  x_dbl = c["x"].to_double();
129  BOOST_CHECK_EQUAL(x_dbl, 1e20);
130 
131  c["x"] = 1.499;
132  x_sll = c["x"].to_long_long();
133  BOOST_CHECK_EQUAL(x_sll, 1ll);
134  x_str = c["x"].str();
135  BOOST_CHECK_EQUAL(x_str, "1.499");
136  x_int = c["x"].to_int();
137  BOOST_CHECK_EQUAL(x_int, 1);
138  x_dbl = c["x"].to_double();
139  BOOST_CHECK(std::abs(x_dbl - 1.499) < 1e-6);
140 
141 
142  c["x"] = 123456789123ll;
143  x_int = c["x"].to_int();
144  BOOST_CHECK_EQUAL(x_int, -1097262461);
145  x_dbl = c["x"].to_double();
146  BOOST_CHECK_EQUAL(x_dbl, 1.23456789123e11);
147  x_sll = c["x"].to_long_long();
148  BOOST_CHECK_EQUAL(x_sll, 123456789123ll);
149  x_str = c["x"].str();
150  BOOST_CHECK_EQUAL(x_str, "123456789123");
151 
152  // blank != "" test.
153  c.clear();
154  BOOST_CHECK(cc["x"] != "");
155  BOOST_CHECK(cc["x"].empty());
156  BOOST_CHECK(cc["x"].blank());
157 
158  BOOST_CHECK(c["x"] != "");
159  BOOST_CHECK(c["x"].empty());
160  BOOST_CHECK(c["x"].blank());
161 
162  BOOST_CHECK_EQUAL(cc["x"], c["x"]);
163 
164  c["x"] = "";
165  BOOST_CHECK(cc["x"].empty());
166  BOOST_CHECK(cc["x"].empty());
167  BOOST_CHECK(!cc["x"].blank());
168 
169  BOOST_CHECK(c["x"].empty());
170  BOOST_CHECK(c["x"].empty());
171  BOOST_CHECK(!c["x"].blank());
172 
173  BOOST_CHECK_EQUAL(cc["x"], c["x"]);
174 }
175 
176 BOOST_AUTO_TEST_CASE ( test_variable_info )
177 {
178  config c;
179  {
180  variable_access_const access("", c);
181  // We dotn allow empty keys
182  BOOST_CHECK_THROW (access.as_scalar(), invalid_variablename_exception);
183  }
184  {
185  variable_access_const access("some_non_existent.", c);
186  // We dotn allow empty keys
187  BOOST_CHECK_THROW (access.as_scalar(), invalid_variablename_exception);
188  }
189  {
190  variable_access_const access("some_non_existent[0]value", c);
191  // We expect '.' after ']'
192  BOOST_CHECK_THROW (access.as_scalar(), invalid_variablename_exception);
193  }
194  {
195  variable_access_const access("some_non_existent", c);
196  // we return empty be default
197  BOOST_CHECK (!access.exists_as_container());
198  BOOST_CHECK_EQUAL (access.as_container(), config());
199  BOOST_CHECK (!access.exists_as_attribute());
200  BOOST_CHECK_EQUAL (access.as_scalar(), config::attribute_value());
201  }
202  {
203  variable_access_const access("a.b[0].c[1].d.e.f[2]", c);
204  // we return empty be default
205  BOOST_CHECK (!access.exists_as_container());
206  BOOST_CHECK_EQUAL (access.as_container(), config());
207  // Explicit indexes can never be an attribute
208  BOOST_CHECK_THROW (access.as_scalar(), invalid_variablename_exception);
209  }
210  BOOST_CHECK (c.empty());
211  {
212  config c2;
213  variable_access_create access("a.b[0].c[1].d.e.f[2].g", c2);
214  access.as_scalar() = 84;
215  BOOST_CHECK_EQUAL (variable_access_const("a.length", c2).as_scalar(), 1);
216  BOOST_CHECK_EQUAL (variable_access_const("a.b.length", c2).as_scalar(), 1);
217  BOOST_CHECK_EQUAL (variable_access_const("a.b.c.length", c2).as_scalar(), 2);
218  BOOST_CHECK_EQUAL (variable_access_const("a.b.c[1].d.e.f.length", c2).as_scalar(), 3);
219  // we set g as a scalar
220  BOOST_CHECK_EQUAL (variable_access_const("a.b.c[1].d.e.f[2].g.length", c2).as_scalar(), 0);
221  BOOST_CHECK_EQUAL (variable_access_const("a.b.c[1].d.e.f[2].g", c2).as_scalar(), 84);
222  }
223  {
224  config c2;
225  variable_access_throw access("a.b[9].c", c2);
226  BOOST_CHECK_THROW(access.as_scalar(), invalid_variablename_exception);
227  }
228  {
229  const config nonempty {
230  "tag1", config(),
231  "tag1", config {
232  "tag2", config(),
233  "tag2", config(),
234  "tag2", config {
235  "atribute1", 88,
236  "atribute2", "value",
237  },
238  },
239  "tag1", config(),
240  };
241  /** This is the config:
242  [tag1]
243  [/tag1]
244  [tag1]
245  [tag2]
246  [/tag2]
247  [tag2]
248  [/tag2]
249  [tag2]
250  atribute1 = 88
251  atribute2 = "value"
252  [/tag2]
253  [/tag1]
254  [tag1]
255  [/tag1]
256  */
257  BOOST_CHECK_EQUAL (variable_access_const("tag1.length", nonempty).as_scalar(), 3);
258  BOOST_CHECK_EQUAL (variable_access_const("tag1.tag2.length", nonempty).as_scalar(), 0);
259  BOOST_CHECK_EQUAL (variable_access_const("tag1[1].tag2.length", nonempty).as_scalar(), 3);
260  BOOST_CHECK_EQUAL (variable_access_const("tag1[1].tag2[2].atribute1", nonempty).as_scalar().to_int(), 88);
261  int count = 0;
262  for(const config& child : variable_access_const("tag1", nonempty).as_array())
263  {
264  //silences unused variable warning.
265  UNUSED(child);
266  ++count;
267  }
268  BOOST_CHECK_EQUAL (count, 3);
269  count = 0;
270  for(const config& child : variable_access_const("tag1.tag2", nonempty).as_array())
271  {
272  //silences unused variable warning.
273  UNUSED(child);
274  ++count;
275  }
276  BOOST_CHECK_EQUAL (count, 0);
277  count = 0;
278  // explicit indexes as range always return a one element range, whether they exist or not.
279  for(const config& child : variable_access_const("tag1.tag2[5]", nonempty).as_array())
280  {
281  //silences unused variable warning.
282  UNUSED(child);
283  ++count;
284  }
285  BOOST_CHECK_EQUAL (count, 1);
286  }
287 }
288 
289 BOOST_AUTO_TEST_SUITE_END()
bool exists_as_attribute() const
BOOST_AUTO_TEST_CASE(test_config_attribute_value)
Definition: test_config.cpp:25
maybe_const_t< config::attribute_value, V > & as_scalar() const
If instantiated with vi_policy_const, the lifetime of the returned const attribute_value reference mi...
Additional functionality for a non-const variable_info.
maybe_const_t< config, V > & as_container() const
If instantiated with vi_policy_const, the lifetime of the returned const attribute_value reference mi...
void clear()
Definition: config.cpp:865
Definitions for the interface to Wesnoth Markup Language (WML).
variable_info< const variable_info_implementation::vi_policy_const > variable_access_const
Read-only access.
#define UNUSED(x)
Definition: global.hpp:34
Information on a WML variable.
bool exists_as_container() const
#define e
config_attribute_value attribute_value
Variant for storing WML attributes.
Definition: config.hpp:247
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
mock_char c
bool empty() const
Definition: config.cpp:886