1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 Copyright (c) 2010 Bryce Lelbach
5
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9
10 #include <boost/config/warning_disable.hpp>
11 #include <boost/detail/lightweight_test.hpp>
12
13 #include <boost/functional/hash.hpp>
14 #include <boost/spirit/include/support_utree.hpp>
15
16 #include <iostream>
17 #include <sstream>
18 #include <cstdlib>
19
check(boost::spirit::utree const & val,std::string expected)20 inline bool check(boost::spirit::utree const& val, std::string expected)
21 {
22 std::stringstream s;
23 s << val;
24 if (s.str() == expected + " ")
25 return true;
26
27 std::cerr << "got result: " << s.str()
28 << ", expected: " << expected << std::endl;
29 return false;
30 }
31
32 struct one_two_three
33 {
operator ()one_two_three34 boost::spirit::utree operator()(boost::spirit::utree) const
35 {
36 return boost::spirit::utree(123);
37 }
38 };
39
40 struct this_
41 {
operator ()this_42 boost::spirit::utree operator()(boost::spirit::utree) const
43 {
44 return boost::spirit::utree(static_cast<int>(boost::hash_value(this)));
45 }
46 };
47
main()48 int main()
49 {
50 using boost::spirit::utree;
51 using boost::spirit::get;
52 using boost::spirit::utf8_symbol_type;
53 using boost::spirit::binary_string_type;
54
55 {
56 // test the size
57 std::cout << "size of utree is: "
58 << sizeof(utree) << " bytes" << std::endl;
59 BOOST_TEST_EQ(sizeof(utree), sizeof(void*[4]));
60 }
61
62 {
63 using boost::spirit::nil;
64
65 utree val(nil);
66 BOOST_TEST(check(val, "<nil>"));
67 }
68
69 {
70 using boost::spirit::empty_list;
71
72 utree val(empty_list);
73 BOOST_TEST(check(val, "( )"));
74 }
75
76 {
77 utree val(true);
78 BOOST_TEST(check(val, "true"));
79 }
80
81 {
82 utree val(123);
83 BOOST_TEST(check(val, "123"));
84 }
85
86 {
87 // single element string
88 utree val('x');
89 BOOST_TEST(check(val, "\"x\""));
90
91 // empty string
92 utree val1("");
93 BOOST_TEST(check(val1, "\"\""));
94 }
95
96 {
97 utree val(123.456);
98 BOOST_TEST(check(val, "123.456"));
99 }
100
101 { // strings
102 utree val("Hello, World");
103 BOOST_TEST(check(val, "\"Hello, World\""));
104 utree val2;
105 val2 = val;
106 BOOST_TEST(check(val2, "\"Hello, World\""));
107 utree val3("Hello, World. Chuckie is back!!!");
108 val = val3;
109 BOOST_TEST(check(val, "\"Hello, World. Chuckie is back!!!\""));
110
111 utree val4("Apple");
112 utree val5("Apple");
113 BOOST_TEST_EQ(val4, val5);
114
115 utree val6("ApplePie");
116 BOOST_TEST(val4 < val6);
117 }
118
119 { // symbols
120 utree val(utf8_symbol_type("Hello, World"));
121 BOOST_TEST(check(val, "Hello, World"));
122 utree val2;
123 val2 = val;
124 BOOST_TEST(check(val2, "Hello, World"));
125 utree val3(utf8_symbol_type("Hello, World. Chuckie is back!!!"));
126 val = val3;
127 BOOST_TEST(check(val, "Hello, World. Chuckie is back!!!"));
128
129 utree val4(utf8_symbol_type("Apple"));
130 utree val5(utf8_symbol_type("Apple"));
131 BOOST_TEST_EQ(val4, val5);
132
133 utree val6(utf8_symbol_type("ApplePie"));
134 BOOST_TEST(val4 < val6);
135 }
136
137 { // binary_strings
138 utree val(binary_string_type("\xDE#\xAD"));
139 BOOST_TEST(check(val, "#de23ad#" /* FIXME?: "#\xDE#\xAD#" */));
140 utree val2;
141 val2 = val;
142 BOOST_TEST(check(val2, "#de23ad#" /* FIXME?: "#\xDE#\xAD#" */));
143 utree val3(binary_string_type("\xDE\xAD\xBE\xEF"));
144 val = val3;
145 BOOST_TEST(check(val, "#deadbeef#" /* FIXME?: "#\xDE\xAD\xBE\xEF#" */));
146
147 utree val4(binary_string_type("\x01"));
148 utree val5(binary_string_type("\x01"));
149 BOOST_TEST_EQ(val4, val5);
150
151 utree val6(binary_string_type("\x01\x02"));
152 BOOST_TEST(val4 < val6);
153 }
154
155 {
156 using boost::spirit::nil;
157
158 utree val;
159 val.push_back(123);
160 val.push_back("Chuckie");
161 BOOST_TEST_EQ(val.size(), 2U);
162 utree val2;
163 val2.push_back(123.456);
164 val2.push_back("Mah Doggie");
165 val.push_back(val2);
166 BOOST_TEST_EQ(val.size(), 3U);
167 BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
168 BOOST_TEST(check(val.front(), "123"));
169
170 utree val3(nil);
171 val3.swap(val);
172 BOOST_TEST_EQ(val3.size(), 3U);
173 BOOST_TEST(check(val, "<nil>"));
174 val3.swap(val);
175 BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
176 val.push_back("another string");
177 BOOST_TEST_EQ(val.size(), 4U);
178 BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"another string\" )"));
179 val.pop_front();
180 BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"another string\" )"));
181 utree::iterator i = val.begin();
182 ++++i;
183 val.insert(i, "Right in the middle");
184 BOOST_TEST_EQ(val.size(), 4U);
185 BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"Right in the middle\" \"another string\" )"));
186 val.pop_back();
187 BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"Right in the middle\" )"));
188 BOOST_TEST_EQ(val.size(), 3U);
189 utree::iterator it = val.end(); --it;
190 val.erase(it);
191 BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
192 BOOST_TEST_EQ(val.size(), 2U);
193
194 val.insert(val.begin(), val2.begin(), val2.end());
195 BOOST_TEST(check(val, "( 123.456 \"Mah Doggie\" \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
196 BOOST_TEST_EQ(val.size(), 4U);
197
198 // Regeression Ticket #6714
199 it = val.insert(val.end(), 111);
200 BOOST_TEST(it != val.begin());
201 BOOST_TEST(it == --val.end());
202 BOOST_TEST(*it == 111);
203
204 val.clear();
205 it = val.insert(val.begin(), 222);
206 BOOST_TEST(it == val.begin());
207 BOOST_TEST(it == --val.end());
208 BOOST_TEST(*it == 222);
209 // Regeression Ticket #6714
210 }
211
212 {
213 utree val;
214 val.insert(val.end(), 123);
215 val.insert(val.end(), "Mia");
216 val.insert(val.end(), "Chuckie");
217 val.insert(val.end(), "Poly");
218 val.insert(val.end(), "Mochi");
219 BOOST_TEST(check(val, "( 123 \"Mia\" \"Chuckie\" \"Poly\" \"Mochi\" )"));
220 }
221
222 {
223 using boost::spirit::nil;
224 using boost::spirit::invalid;
225
226 utree a(nil), b(nil);
227 BOOST_TEST_EQ(a, b);
228 a = 123;
229 BOOST_TEST(a != b);
230 b = 123;
231 BOOST_TEST_EQ(a, b);
232 a = 100.00;
233 BOOST_TEST(a < b);
234
235 b = a = utree(invalid);
236 BOOST_TEST_EQ(a, b);
237 a.push_back(1);
238 a.push_back("two");
239 a.push_back(3.0);
240 b.push_back(1);
241 b.push_back("two");
242 b.push_back(3.0);
243 BOOST_TEST_EQ(a, b);
244 b.push_back(4);
245 BOOST_TEST(a != b);
246 BOOST_TEST(a < b);
247 }
248
249 {
250 using boost::spirit::empty_list;
251
252 utree a(empty_list);
253 a.push_back(0);
254 a.push_back(0);
255 a.push_back(0);
256 a.push_back(0);
257 a.push_back(0);
258 a.push_back(0);
259 a.push_back(0);
260 a.push_back(0);
261 a.push_back(0);
262 a.push_back(0);
263 a.push_back(0);
264 a.push_back(0);
265
266 for (utree::size_type i = 0; i < a.size(); ++i)
267 get(a, i) = int(i + 1);
268
269 BOOST_TEST_EQ(get(a, 0), utree(1));
270 BOOST_TEST_EQ(get(a, 1), utree(2));
271 BOOST_TEST_EQ(get(a, 2), utree(3));
272 BOOST_TEST_EQ(get(a, 3), utree(4));
273 BOOST_TEST_EQ(get(a, 4), utree(5));
274 BOOST_TEST_EQ(get(a, 5), utree(6));
275 BOOST_TEST_EQ(get(a, 6), utree(7));
276 BOOST_TEST_EQ(get(a, 7), utree(8));
277 BOOST_TEST_EQ(get(a, 8), utree(9));
278 BOOST_TEST_EQ(get(a, 9), utree(10));
279 BOOST_TEST_EQ(get(a, 10), utree(11));
280 BOOST_TEST_EQ(get(a, 11), utree(12));
281 }
282
283 {
284 // test empty list
285 utree a;
286 a.push_back(1);
287 a.pop_front();
288 BOOST_TEST(check(a, "( )"));
289
290 // the other way around
291 utree b;
292 b.push_front(1);
293 b.pop_back();
294 BOOST_TEST(check(b, "( )"));
295 }
296
297 { // test references
298 utree val(123);
299 utree ref(boost::ref(val));
300 BOOST_TEST(check(ref, "123"));
301 BOOST_TEST_EQ(ref, utree(123));
302
303 val.clear();
304 val.push_back(1);
305 val.push_back(2);
306 val.push_back(3);
307 val.push_back(4);
308 BOOST_TEST(check(ref, "( 1 2 3 4 )"));
309 BOOST_TEST_EQ(get(ref, 0), utree(1));
310 BOOST_TEST_EQ(get(ref, 1), utree(2));
311 BOOST_TEST_EQ(get(ref, 2), utree(3));
312 BOOST_TEST_EQ(get(ref, 3), utree(4));
313 }
314
315 { // put it in an array
316
317 utree vals[] = {
318 utree(123),
319 utree("Hello, World"),
320 utree(123.456)
321 };
322
323 BOOST_TEST(check(vals[0], "123"));
324 BOOST_TEST(check(vals[1], "\"Hello, World\""));
325 BOOST_TEST(check(vals[2], "123.456"));
326 }
327
328 { // operators
329
330 BOOST_TEST((utree(false) && utree(false)) == utree(false));
331 BOOST_TEST((utree(false) && utree(true)) == utree(false));
332 BOOST_TEST((utree(true) && utree(false)) == utree(false));
333 BOOST_TEST((utree(true) && utree(true)) == utree(true));
334
335 BOOST_TEST((utree(0) && utree(0)) == utree(false));
336 BOOST_TEST((utree(0) && utree(1)) == utree(false));
337 BOOST_TEST((utree(1) && utree(0)) == utree(false));
338 BOOST_TEST((utree(1) && utree(1)) == utree(true));
339
340 BOOST_TEST((utree(false) || utree(false)) == utree(false));
341 BOOST_TEST((utree(false) || utree(true)) == utree(true));
342 BOOST_TEST((utree(true) || utree(false)) == utree(true));
343 BOOST_TEST((utree(true) || utree(true)) == utree(true));
344
345 BOOST_TEST((utree(0) || utree(0)) == utree(false));
346 BOOST_TEST((utree(0) || utree(1)) == utree(true));
347 BOOST_TEST((utree(1) || utree(0)) == utree(true));
348 BOOST_TEST((utree(1) || utree(1)) == utree(true));
349
350 BOOST_TEST((!utree(true)) == utree(false));
351 BOOST_TEST((!utree(false)) == utree(true));
352 BOOST_TEST((!utree(1)) == utree(false));
353 BOOST_TEST((!utree(0)) == utree(true));
354
355 BOOST_TEST((utree(456) + utree(123)) == utree(456 + 123));
356 BOOST_TEST((utree(456) + utree(123.456)) == utree(456 + 123.456));
357 BOOST_TEST((utree(456) - utree(123)) == utree(456 - 123));
358 BOOST_TEST((utree(456) - utree(123.456)) == utree(456 - 123.456));
359 BOOST_TEST((utree(456) * utree(123)) == utree(456 * 123));
360 BOOST_TEST((utree(456) * utree(123.456)) == utree(456 * 123.456));
361 BOOST_TEST((utree(456) / utree(123)) == utree(456 / 123));
362 BOOST_TEST((utree(456) / utree(123.456)) == utree(456 / 123.456));
363 BOOST_TEST((utree(456) % utree(123)) == utree(456 % 123));
364 BOOST_TEST(-utree(456) == utree(-456));
365
366 BOOST_TEST((utree(456) & utree(123)) == utree(456 & 123));
367 BOOST_TEST((utree(456) | utree(123)) == utree(456 | 123));
368 BOOST_TEST((utree(456) ^ utree(123)) == utree(456 ^ 123));
369 BOOST_TEST((utree(456) << utree(3)) == utree(456 << 3));
370 BOOST_TEST((utree(456) >> utree(2)) == utree(456 >> 2));
371 BOOST_TEST(~utree(456) == utree(~456));
372 }
373
374 { // test reference iterator
375 utree val;
376 val.push_back(1);
377 val.push_back(2);
378 val.push_back(3);
379 val.push_back(4);
380 BOOST_TEST(check(val, "( 1 2 3 4 )"));
381
382 utree::ref_iterator b = val.ref_begin();
383 utree::ref_iterator e = val.ref_end();
384
385 utree ref(boost::make_iterator_range(b, e));
386 BOOST_TEST_EQ(get(ref, 0), utree(1));
387 BOOST_TEST_EQ(get(ref, 1), utree(2));
388 BOOST_TEST_EQ(get(ref, 2), utree(3));
389 BOOST_TEST_EQ(get(ref, 3), utree(4));
390 BOOST_TEST(check(ref, "( 1 2 3 4 )"));
391 }
392
393 {
394 // check the tag
395 // TODO: test tags on all utree types
396 utree x;
397 x.tag(123);
398 BOOST_TEST_EQ(x.tag(), 123);
399
400 x = "hello world! my name is bob the builder";
401 x.tag(123);
402 BOOST_TEST_EQ(x.tag(), 123);
403
404 x.tag(456);
405 BOOST_TEST_EQ(x.tag(), 456);
406 BOOST_TEST_EQ(x.size(), 39U);
407 BOOST_TEST(check(x, "\"hello world! my name is bob the builder\""));
408
409 x = "hello";
410 x.tag(456);
411 BOOST_TEST_EQ(x.tag(), 456);
412
413 x.tag(789);
414 BOOST_TEST_EQ(x.tag(), 789);
415 BOOST_TEST_EQ(x.size(), 5U);
416 BOOST_TEST(check(x, "\"hello\""));
417 }
418
419 {
420 // test functions
421 using boost::spirit::stored_function;
422
423 utree f = stored_function<one_two_three>();
424 f.eval(utree());
425 }
426
427 {
428 // test referenced functions
429 using boost::spirit::referenced_function;
430
431 one_two_three f;
432 utree ff = referenced_function<one_two_three>(f);
433 BOOST_TEST_EQ(ff.eval(utree()), f(utree()));
434 }
435
436 {
437 // shallow ranges
438 using boost::spirit::shallow;
439
440 utree val;
441 val.push_back(1);
442 val.push_back(2);
443 val.push_back(3);
444 val.push_back(4);
445
446 utree::iterator i = val.begin(); ++i;
447 utree alias(utree::range(i, val.end()), shallow);
448
449 BOOST_TEST(check(alias, "( 2 3 4 )"));
450 BOOST_TEST_EQ(alias.size(), 3U);
451 BOOST_TEST_EQ(alias.front(), 2);
452 BOOST_TEST_EQ(alias.back(), 4);
453 BOOST_TEST(!alias.empty());
454 BOOST_TEST_EQ(get(alias, 1), 3);
455 }
456
457 {
458 // shallow string ranges
459 using boost::spirit::utf8_string_range_type;
460 using boost::spirit::shallow;
461
462 char const* s = "Hello, World";
463 utree val(utf8_string_range_type(s, s + strlen(s)), shallow);
464 BOOST_TEST(check(val, "\"Hello, World\""));
465
466 utf8_string_range_type r = val.get<utf8_string_range_type>();
467 utf8_string_range_type pf(r.begin()+1, r.end()-1);
468 val = utree(pf, shallow);
469 BOOST_TEST(check(val, "\"ello, Worl\""));
470 }
471
472 {
473 // any pointer
474 using boost::spirit::any_ptr;
475
476 int n = 123;
477 utree up = any_ptr(&n);
478 BOOST_TEST(*up.get<int*>() == 123);
479 }
480
481 // tags
482 {
483 short min = (std::numeric_limits<short>::min)();
484 short max = (std::numeric_limits<short>::max)();
485
486 utree::list_type u;
487 utree u2;
488 bool ok = true;
489
490 for (int t = min ; ok && t <= max ; ++t) {
491 u.tag(t);
492 u2 = u;
493 BOOST_TEST_EQ(t, u.tag());
494 BOOST_TEST_EQ(t, u2.tag());
495 ok = t == u.tag() && t == u2.tag();
496 u2 = utree("12");
497 }
498 }
499
500 return boost::report_errors();
501 }
502