]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/property_tree/test/test_property_tree.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / property_tree / test / test_property_tree.hpp
1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2002-2006 Marcin Kalicinski
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // For more information, see www.boost.org
9 // ----------------------------------------------------------------------------
10
11 // Intentionally no include guards (to be included more than once)
12
13 #if !defined(CHTYPE) || !defined(T) || !defined(PTREE) || !defined(NOCASE) || !defined(WIDECHAR)
14 # error No character type specified
15 #endif
16
17 void test_debug(PTREE *)
18 {
19 #if 0
20 // Check count
21 BOOST_CHECK(PTREE::debug_get_instances_count() == 0);
22
23 {
24
25 // Create ptrees
26 PTREE pt1, pt2;
27 BOOST_CHECK(PTREE::debug_get_instances_count() == 2);
28
29 // Create PTREE
30 PTREE *pt3 = new PTREE;
31 BOOST_CHECK(PTREE::debug_get_instances_count() == 3);
32
33 // Insert
34 pt1.push_back(std::make_pair(T("key"), *pt3));
35 BOOST_CHECK(PTREE::debug_get_instances_count() == 4);
36
37 // Insert
38 pt2.push_back(std::make_pair(T("key"), *pt3));
39 BOOST_CHECK(PTREE::debug_get_instances_count() == 5);
40
41 // Clear
42 pt1.clear();
43 BOOST_CHECK(PTREE::debug_get_instances_count() == 4);
44
45 // Clear
46 pt2.clear();
47 BOOST_CHECK(PTREE::debug_get_instances_count() == 3);
48
49 // Delete
50 delete pt3;
51 BOOST_CHECK(PTREE::debug_get_instances_count() == 2);
52
53 }
54
55 // Check count
56 BOOST_CHECK(PTREE::debug_get_instances_count() == 0);
57 #endif
58 }
59
60 void test_constructor_destructor_assignment(PTREE *)
61 {
62
63 {
64
65 // Test constructor from string
66 PTREE pt1(T("data"));
67 BOOST_CHECK(pt1.data() == T("data"));
68 //BOOST_CHECK(PTREE::debug_get_instances_count() == 1);
69
70 // Do insertions
71 PTREE &tmp1 = pt1.put(T("key1"), T("data1"));
72 PTREE &tmp2 = pt1.put(T("key2"), T("data2"));
73 tmp1.put(T("key3"), T("data3"));
74 tmp2.put(T("key4"), T("data4"));
75 //BOOST_CHECK(PTREE::debug_get_instances_count() == 5);
76
77 // Make a copy using copy constructor
78 PTREE *pt2 = new PTREE(pt1);
79 BOOST_CHECK(*pt2 == pt1);
80 //BOOST_CHECK(PTREE::debug_get_instances_count() == 10);
81
82 // Make a copy using = operator
83 PTREE *pt3 = new PTREE;
84 *pt3 = *pt2;
85 BOOST_CHECK(*pt3 == *pt2);
86 //BOOST_CHECK(PTREE::debug_get_instances_count() == 15);
87
88 // Test self assignment
89 pt1 = pt1;
90 BOOST_CHECK(pt1 == *pt2);
91 BOOST_CHECK(pt1 == *pt3);
92 //BOOST_CHECK(PTREE::debug_get_instances_count() == 15);
93
94 // Destroy
95 delete pt2;
96 //BOOST_CHECK(PTREE::debug_get_instances_count() == 10);
97
98 // Destroy
99 delete pt3;
100 //BOOST_CHECK(PTREE::debug_get_instances_count() == 5);
101
102 }
103
104 // Check count
105 //BOOST_CHECK(PTREE::debug_get_instances_count() == 0);
106
107 }
108
109 void test_insertion(PTREE *)
110 {
111
112 // Do insertions
113 PTREE pt;
114 PTREE tmp1(T("data1"));
115 PTREE tmp2(T("data2"));
116 PTREE tmp3(T("data3"));
117 PTREE tmp4(T("data4"));
118 PTREE::iterator it1 = pt.insert(pt.end(), std::make_pair(T("key1"), tmp1));
119 PTREE::iterator it2 = pt.insert(it1, std::make_pair(T("key2"), tmp2));
120 PTREE::iterator it3 = it1->second.push_back(std::make_pair(T("key3"), tmp3));
121 PTREE::iterator it4 = it1->second.push_front(std::make_pair(T("key4"), tmp4));
122 it2->second.insert(it2->second.end(), it1->second.begin(), it1->second.end());
123
124 // Check instance count
125 //BOOST_CHECK(PTREE::debug_get_instances_count() == 11);
126
127 // Check contents
128 BOOST_CHECK(pt.get(T("key1"), T("")) == T("data1"));
129 BOOST_CHECK(pt.get(T("key2"), T("")) == T("data2"));
130 BOOST_CHECK(pt.get(T("key1.key3"), T("")) == T("data3"));
131 BOOST_CHECK(pt.get(T("key1.key4"), T("")) == T("data4"));
132 BOOST_CHECK(pt.get(T("key2.key3"), T("")) == T("data3"));
133 BOOST_CHECK(pt.get(T("key2.key4"), T("")) == T("data4"));
134
135 // Check sequence
136 PTREE::iterator it = it2;
137 ++it; BOOST_CHECK(it == it1);
138 ++it; BOOST_CHECK(it == pt.end());
139 it = it4;
140 ++it; BOOST_CHECK(it == it3);
141 ++it; BOOST_CHECK(it == it1->second.end());
142
143 }
144
145 void test_erasing(PTREE *)
146 {
147
148 // Do insertions
149 PTREE pt;
150 PTREE tmp1(T("data1"));
151 PTREE tmp2(T("data2"));
152 PTREE tmp3(T("data3"));
153 PTREE tmp4(T("data4"));
154 PTREE::iterator it1 = pt.insert(pt.end(), std::make_pair(T("key1"), tmp1));
155 PTREE::iterator it2 = pt.insert(it1, std::make_pair(T("key2"), tmp2));
156 it1->second.push_back(std::make_pair(T("key"), tmp3));
157 it1->second.push_front(std::make_pair(T("key"), tmp4));
158 it2->second.insert(it2->second.end(), it1->second.begin(), it1->second.end());
159
160 // Check instance count
161 //BOOST_CHECK(PTREE::debug_get_instances_count() == 11);
162
163 // Test range erase
164 PTREE::iterator it = it1->second.erase(it1->second.begin(), it1->second.end());
165 BOOST_CHECK(it == it1->second.end());
166 //BOOST_CHECK(PTREE::debug_get_instances_count() == 9);
167
168 // Test single erase
169 PTREE::size_type n = pt.erase(T("key1"));
170 BOOST_CHECK(n == 1);
171 //BOOST_CHECK(PTREE::debug_get_instances_count() == 8);
172
173 // Test multiple erase
174 n = it2->second.erase(T("key"));
175 BOOST_CHECK(n == 2);
176 //BOOST_CHECK(PTREE::debug_get_instances_count() == 6);
177
178 // Test one more erase
179 n = pt.erase(T("key2"));
180 BOOST_CHECK(n == 1);
181 //BOOST_CHECK(PTREE::debug_get_instances_count() == 5);
182
183 }
184
185 void test_clear(PTREE *)
186 {
187
188 // Do insertions
189 PTREE pt(T("data"));
190 pt.push_back(std::make_pair(T("key"), PTREE(T("data"))));
191
192 // Check instance count
193 //BOOST_CHECK(PTREE::debug_get_instances_count() == 2);
194
195 // Test clear
196 pt.clear();
197 BOOST_CHECK(pt.empty());
198 BOOST_CHECK(pt.data().empty());
199 //BOOST_CHECK(PTREE::debug_get_instances_count() == 1);
200
201 }
202
203 void test_pushpop(PTREE *)
204 {
205
206 // Do insertions
207 PTREE pt;
208 PTREE tmp1(T("data1"));
209 PTREE tmp2(T("data2"));
210 PTREE tmp3(T("data3"));
211 PTREE tmp4(T("data4"));
212 pt.push_back(std::make_pair(T("key3"), tmp3));
213 pt.push_front(std::make_pair(T("key2"), tmp2));
214 pt.push_back(std::make_pair(T("key4"), tmp4));
215 pt.push_front(std::make_pair(T("key1"), tmp1));
216
217 // Check instance count
218 //BOOST_CHECK(PTREE::debug_get_instances_count() == 9);
219
220 // Check sequence
221 PTREE::iterator it = pt.begin();
222 BOOST_CHECK(it->first == T("key1")); ++it;
223 BOOST_CHECK(it->first == T("key2")); ++it;
224 BOOST_CHECK(it->first == T("key3")); ++it;
225 BOOST_CHECK(it->first == T("key4")); ++it;
226 BOOST_CHECK(it == pt.end());
227
228 // Test pops
229 pt.pop_back();
230 //BOOST_CHECK(PTREE::debug_get_instances_count() == 8);
231 BOOST_CHECK(pt.front().second.data() == T("data1"));
232 BOOST_CHECK(pt.back().second.data() == T("data3"));
233 pt.pop_front();
234 //BOOST_CHECK(PTREE::debug_get_instances_count() == 7);
235 BOOST_CHECK(pt.front().second.data() == T("data2"));
236 BOOST_CHECK(pt.back().second.data() == T("data3"));
237 pt.pop_back();
238 //BOOST_CHECK(PTREE::debug_get_instances_count() == 6);
239 BOOST_CHECK(pt.front().second.data() == T("data2"));
240 BOOST_CHECK(pt.back().second.data() == T("data2"));
241 pt.pop_front();
242 //BOOST_CHECK(PTREE::debug_get_instances_count() == 5);
243 BOOST_CHECK(pt.empty());
244
245 }
246
247 void test_container_iteration(PTREE *)
248 {
249
250 // Do insertions
251 PTREE pt;
252 pt.put(T("key3"), T(""));
253 pt.put(T("key1"), T(""));
254 pt.put(T("key4"), T(""));
255 pt.put(T("key2"), T(""));
256
257 // iterator
258 {
259 PTREE::iterator it = pt.begin();
260 BOOST_CHECK(it->first == T("key3")); ++it;
261 BOOST_CHECK(it->first == T("key1")); ++it;
262 BOOST_CHECK(it->first == T("key4")); ++it;
263 BOOST_CHECK(it->first == T("key2")); ++it;
264 BOOST_CHECK(it == pt.end());
265 }
266
267 // const_iterator
268 {
269 PTREE::const_iterator it = pt.begin();
270 BOOST_CHECK(it->first == T("key3")); ++it;
271 BOOST_CHECK(it->first == T("key1")); ++it;
272 BOOST_CHECK(it->first == T("key4")); ++it;
273 BOOST_CHECK(it->first == T("key2")); ++it;
274 BOOST_CHECK(it == pt.end());
275 }
276
277 // reverse_iterator
278 {
279 PTREE::reverse_iterator it = pt.rbegin();
280 BOOST_CHECK(it->first == T("key2")); ++it;
281 BOOST_CHECK(it->first == T("key4")); ++it;
282 BOOST_CHECK(it->first == T("key1")); ++it;
283 BOOST_CHECK(it->first == T("key3")); ++it;
284 BOOST_CHECK(it == pt.rend());
285 }
286
287 // const_reverse_iterator
288 {
289 PTREE::const_reverse_iterator it = pt.rbegin();
290 BOOST_CHECK(it->first == T("key2")); ++it;
291 BOOST_CHECK(it->first == T("key4")); ++it;
292 BOOST_CHECK(it->first == T("key1")); ++it;
293 BOOST_CHECK(it->first == T("key3")); ++it;
294 BOOST_CHECK(it == PTREE::const_reverse_iterator(pt.rend()));
295 }
296
297 }
298
299 void test_swap(PTREE *)
300 {
301
302 PTREE pt1, pt2;
303
304 // Do insertions
305 pt1.put(T("key1"), T(""));
306 pt1.put(T("key2"), T(""));
307 pt1.put(T("key1.key3"), T(""));
308 pt1.put(T("key1.key4"), T(""));
309
310 // Check counts
311 //BOOST_CHECK(PTREE::debug_get_instances_count() == 6);
312 BOOST_CHECK(pt1.size() == 2);
313 BOOST_CHECK(pt1.get_child(T("key1")).size() == 2);
314 BOOST_CHECK(pt2.size() == 0);
315
316 // Swap using member function
317 pt1.swap(pt2);
318
319 // Check counts
320 //BOOST_CHECK(PTREE::debug_get_instances_count() == 6);
321 BOOST_CHECK(pt2.size() == 2);
322 BOOST_CHECK(pt2.get_child(T("key1")).size() == 2);
323 BOOST_CHECK(pt1.size() == 0);
324
325 // Swap using free function
326 swap(pt1, pt2);
327
328 // Check counts
329 //BOOST_CHECK(PTREE::debug_get_instances_count() == 6);
330 BOOST_CHECK(pt1.size() == 2);
331 BOOST_CHECK(pt1.get_child(T("key1")).size() == 2);
332 BOOST_CHECK(pt2.size() == 0);
333
334 // Swap using std algorithm
335 std::swap(pt1, pt2);
336
337 // Check counts
338 //BOOST_CHECK(PTREE::debug_get_instances_count() == 6);
339 BOOST_CHECK(pt2.size() == 2);
340 BOOST_CHECK(pt2.get_child(T("key1")).size() == 2);
341 BOOST_CHECK(pt1.size() == 0);
342
343 }
344
345 void test_sort_reverse(PTREE *)
346 {
347
348 PTREE pt;
349
350 // Do insertions
351 pt.put(T("key2"), T("data2"));
352 pt.put(T("key1"), T("data1"));
353 pt.put(T("key4"), T("data4"));
354 pt.put(T("key3"), T("data3"));
355 pt.put(T("key3.key1"), T(""));
356 pt.put(T("key4.key2"), T(""));
357
358 // Reverse
359 pt.reverse();
360
361 // Check sequence
362 {
363 PTREE::iterator it = pt.begin();
364 BOOST_CHECK(it->first == T("key3")); ++it;
365 BOOST_CHECK(it->first == T("key4")); ++it;
366 BOOST_CHECK(it->first == T("key1")); ++it;
367 BOOST_CHECK(it->first == T("key2")); ++it;
368 BOOST_CHECK(it == pt.end());
369 }
370 // Check sequence using find to check if index is ok
371 {
372 PTREE::iterator it = pt.begin();
373 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key3")))); ++it;
374 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key4")))); ++it;
375 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key1")))); ++it;
376 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key2")))); ++it;
377 BOOST_CHECK(it == pt.end());
378 }
379
380 // Sort
381 pt.sort(SortPred<PTREE>());
382
383 // Check sequence
384 {
385 PTREE::iterator it = pt.begin();
386 BOOST_CHECK(it->first == T("key1")); ++it;
387 BOOST_CHECK(it->first == T("key2")); ++it;
388 BOOST_CHECK(it->first == T("key3")); ++it;
389 BOOST_CHECK(it->first == T("key4")); ++it;
390 BOOST_CHECK(it == pt.end());
391 }
392 // Check sequence (using find to check if index is ok)
393 {
394 PTREE::iterator it = pt.begin();
395 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key1")))); ++it;
396 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key2")))); ++it;
397 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key3")))); ++it;
398 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key4")))); ++it;
399 BOOST_CHECK(it == pt.end());
400 }
401
402 // Sort reverse
403 pt.sort(SortPredRev<PTREE>());
404
405 // Check sequence
406 {
407 PTREE::iterator it = pt.begin();
408 BOOST_CHECK(it->first == T("key4")); ++it;
409 BOOST_CHECK(it->first == T("key3")); ++it;
410 BOOST_CHECK(it->first == T("key2")); ++it;
411 BOOST_CHECK(it->first == T("key1")); ++it;
412 BOOST_CHECK(it == pt.end());
413 }
414 // Check sequence (using find to check if index is ok)
415 {
416 PTREE::iterator it = pt.begin();
417 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key4")))); ++it;
418 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key3")))); ++it;
419 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key2")))); ++it;
420 BOOST_CHECK(it == pt.to_iterator(pt.find(T("key1")))); ++it;
421 BOOST_CHECK(it == pt.end());
422 }
423
424 }
425
426 void test_case(PTREE *)
427 {
428
429 // Do insertions
430 PTREE pt;
431 pt.put(T("key1"), T("data1"));
432 pt.put(T("KEY2"), T("data2"));
433 pt.put(T("kEy1.keY3"), T("data3"));
434 pt.put(T("KEY1.key4"), T("data4"));
435
436 // Check findings depending on traits type
437 #if (NOCASE == 0)
438 //BOOST_CHECK(PTREE::debug_get_instances_count() == 7);
439 BOOST_CHECK(pt.get(T("key1"), T("")) == T("data1"));
440 BOOST_CHECK(pt.get(T("key2"), T("")) == T(""));
441 BOOST_CHECK(pt.get(T("key1.key3"), T("")) == T(""));
442 BOOST_CHECK(pt.get(T("KEY1.key4"), T("")) == T("data4"));
443 #else
444 //BOOST_CHECK(PTREE::debug_get_instances_count() == 5);
445 BOOST_CHECK(pt.get(T("key1"), T("1")) == pt.get(T("KEY1"), T("2")));
446 BOOST_CHECK(pt.get(T("key2"), T("1")) == pt.get(T("KEY2"), T("2")));
447 BOOST_CHECK(pt.get(T("key1.key3"), T("1")) == pt.get(T("KEY1.KEY3"), T("2")));
448 BOOST_CHECK(pt.get(T("key1.key4"), T("1")) == pt.get(T("KEY1.KEY4"), T("2")));
449 #endif
450
451 // Do more insertions
452 pt.push_back(PTREE::value_type(T("key1"), PTREE()));
453 pt.push_back(PTREE::value_type(T("key1"), PTREE()));
454
455 // Test counts
456 #if (NOCASE == 0)
457 BOOST_CHECK(pt.count(T("key1")) == 3);
458 BOOST_CHECK(pt.count(T("KEY1")) == 1);
459 BOOST_CHECK(pt.count(T("key2")) == 0);
460 BOOST_CHECK(pt.count(T("KEY2")) == 1);
461 BOOST_CHECK(pt.count(T("key3")) == 0);
462 BOOST_CHECK(pt.count(T("KEY3")) == 0);
463 #else
464 BOOST_CHECK(pt.count(T("key1")) == 3);
465 BOOST_CHECK(pt.count(T("KEY1")) == 3);
466 BOOST_CHECK(pt.count(T("key2")) == 1);
467 BOOST_CHECK(pt.count(T("KEY2")) == 1);
468 BOOST_CHECK(pt.count(T("key3")) == 0);
469 BOOST_CHECK(pt.count(T("KEY3")) == 0);
470 #endif
471
472 }
473
474 void test_comparison(PTREE *)
475 {
476
477 // Prepare original
478 PTREE pt_orig(T("data"));
479 pt_orig.put(T("key1"), T("data1"));
480 pt_orig.put(T("key1.key3"), T("data2"));
481 pt_orig.put(T("key1.key4"), T("data3"));
482 pt_orig.put(T("key2"), T("data4"));
483
484 // Test originals
485 {
486 PTREE pt1(pt_orig);
487 PTREE pt2(pt_orig);
488 BOOST_CHECK(pt1 == pt2);
489 BOOST_CHECK(pt2 == pt1);
490 BOOST_CHECK(!(pt1 != pt2));
491 BOOST_CHECK(!(pt2 != pt1));
492 }
493
494 // Test originals with modified case
495 #if (NOCASE != 0)
496 {
497 PTREE pt1(pt_orig);
498 PTREE pt2(pt_orig);
499 pt1.pop_back();
500 pt1.put(T("KEY2"), T("data4"));
501 BOOST_CHECK(pt1 == pt2);
502 BOOST_CHECK(pt2 == pt1);
503 BOOST_CHECK(!(pt1 != pt2));
504 BOOST_CHECK(!(pt2 != pt1));
505 }
506 #endif
507
508 // Test modified copies (both modified the same way)
509 {
510 PTREE pt1(pt_orig);
511 PTREE pt2(pt_orig);
512 pt1.put(T("key1.key5"), T("."));
513 pt2.put(T("key1.key5"), T("."));
514 BOOST_CHECK(pt1 == pt2);
515 BOOST_CHECK(pt2 == pt1);
516 BOOST_CHECK(!(pt1 != pt2));
517 BOOST_CHECK(!(pt2 != pt1));
518 }
519
520 // Test modified copies (modified root data)
521 {
522 PTREE pt1(pt_orig);
523 PTREE pt2(pt_orig);
524 pt1.data() = T("a");
525 pt2.data() = T("b");
526 BOOST_CHECK(!(pt1 == pt2));
527 BOOST_CHECK(!(pt2 == pt1));
528 BOOST_CHECK(pt1 != pt2);
529 BOOST_CHECK(pt2 != pt1);
530 }
531
532 // Test modified copies (added subkeys with different data)
533 {
534 PTREE pt1(pt_orig);
535 PTREE pt2(pt_orig);
536 pt1.put(T("key1.key5"), T("a"));
537 pt2.put(T("key1.key5"), T("b"));
538 BOOST_CHECK(!(pt1 == pt2));
539 BOOST_CHECK(!(pt2 == pt1));
540 BOOST_CHECK(pt1 != pt2);
541 BOOST_CHECK(pt2 != pt1);
542 }
543
544 // Test modified copies (added subkeys with different keys)
545 {
546 PTREE pt1(pt_orig);
547 PTREE pt2(pt_orig);
548 pt1.put(T("key1.key5"), T(""));
549 pt2.put(T("key1.key6"), T(""));
550 BOOST_CHECK(!(pt1 == pt2));
551 BOOST_CHECK(!(pt2 == pt1));
552 BOOST_CHECK(pt1 != pt2);
553 BOOST_CHECK(pt2 != pt1);
554 }
555
556 // Test modified copies (added subkey to only one copy)
557 {
558 PTREE pt1(pt_orig);
559 PTREE pt2(pt_orig);
560 pt1.put(T("key1.key5"), T(""));
561 BOOST_CHECK(!(pt1 == pt2));
562 BOOST_CHECK(!(pt2 == pt1));
563 BOOST_CHECK(pt1 != pt2);
564 BOOST_CHECK(pt2 != pt1);
565 }
566
567 }
568
569 void test_front_back(PTREE *)
570 {
571
572 // Do insertions
573 PTREE pt;
574 pt.put(T("key1"), T(""));
575 pt.put(T("key2"), T(""));
576
577 // Check front and back
578 BOOST_CHECK(pt.front().first == T("key1"));
579 BOOST_CHECK(pt.back().first == T("key2"));
580
581 }
582
583 void test_get_put(PTREE *)
584 {
585
586 typedef std::basic_string<CHTYPE> str_t;
587
588 // Temporary storage
589 str_t tmp_string;
590 boost::optional<int> opt_int;
591 boost::optional<long> opt_long;
592 boost::optional<double> opt_double;
593 boost::optional<float> opt_float;
594 boost::optional<str_t> opt_string;
595 boost::optional<CHTYPE> opt_char;
596 boost::optional<bool> opt_bool;
597
598 // Do insertions via put
599 PTREE pt;
600 PTREE &pt1 = pt.put(T("k1"), 1);
601 PTREE &pt2 = pt.put(T("k2.k"), 2.5);
602 PTREE &pt3 = pt.put(T("k3.k.k"), T("ala ma kota"));
603 PTREE &pt4 = pt.put(T("k4.k.k.k"), CHTYPE('c'));
604 PTREE &pt5 = pt.put(T("k5.k.k.k.f"), false);
605 PTREE &pt6 = pt.put(T("k5.k.k.k.t"), true);
606
607 // Check instances count
608 //BOOST_CHECK(PTREE::debug_get_instances_count() == 17);
609
610 // Check if const char * version returns std::string
611 BOOST_CHECK(typeid(pt.get_value(T(""))) == typeid(str_t));
612
613 // Do extractions via get (throwing version)
614 BOOST_CHECK(pt.get<int>(T("k1")) == 1);
615 BOOST_CHECK(pt.get<long>(T("k1")) == 1);
616 BOOST_CHECK(pt.get<double>(T("k2.k")) == 2.5);
617 BOOST_CHECK(pt.get<float>(T("k2.k")) == 2.5f);
618 BOOST_CHECK(pt.get<str_t>(T("k3.k.k")) == str_t(T("ala ma kota")));
619 BOOST_CHECK(pt.get<CHTYPE>(T("k4.k.k.k")) == CHTYPE('c'));
620 BOOST_CHECK(pt.get<bool>(T("k5.k.k.k.f")) == false);
621 BOOST_CHECK(pt.get<bool>(T("k5.k.k.k.t")) == true);
622
623 // Do extractions via get (default value version)
624 BOOST_CHECK(pt.get(T("k1"), 0) == 1);
625 BOOST_CHECK(pt.get(T("k1"), 0L) == 1);
626 BOOST_CHECK(pt.get(T("k2.k"), 0.0) == 2.5);
627 BOOST_CHECK(pt.get(T("k2.k"), 0.0f) == 2.5f);
628 BOOST_CHECK(pt.get(T("k3.k.k"), str_t()) == str_t(T("ala ma kota")));
629 BOOST_CHECK(pt.get(T("k3.k.k"), T("")) == T("ala ma kota"));
630 BOOST_CHECK(pt.get(T("k4.k.k.k"), CHTYPE('\0')) == CHTYPE('c'));
631 BOOST_CHECK(pt.get(T("k5.k.k.k.f"), true) == false);
632 BOOST_CHECK(pt.get(T("k5.k.k.k.t"), false) == true);
633
634 // Do extractions via get (optional version)
635 opt_int = pt.get_optional<int>(T("k1"));
636 BOOST_CHECK(opt_int && *opt_int == 1);
637 opt_long = pt.get_optional<long>(T("k1"));
638 BOOST_CHECK(opt_long && *opt_long == 1);
639 opt_double = pt.get_optional<double>(T("k2.k"));
640 BOOST_CHECK(opt_double && *opt_double == 2.5);
641 opt_float = pt.get_optional<float>(T("k2.k"));
642 BOOST_CHECK(opt_float && *opt_float == 2.5f);
643 opt_string = pt.get_optional<str_t>(T("k3.k.k"));
644 BOOST_CHECK(opt_string && *opt_string == str_t(T("ala ma kota")));
645 opt_char = pt.get_optional<CHTYPE>(T("k4.k.k.k"));
646 BOOST_CHECK(opt_char && *opt_char == CHTYPE('c'));
647 opt_bool = pt.get_optional<bool>(T("k5.k.k.k.f"));
648 BOOST_CHECK(opt_bool && *opt_bool == false);
649 opt_bool = pt.get_optional<bool>(T("k5.k.k.k.t"));
650 BOOST_CHECK(opt_bool && *opt_bool == true);
651
652 // Do insertions via put_value
653 pt1.put_value(short(1));
654 pt2.put_value(2.5f);
655 pt3.put_value(str_t(T("ala ma kota")));
656 pt4.put_value(CHTYPE('c'));
657 pt5.put_value(false);
658 pt6.put_value(true);
659
660 // Do extractions via get_value (throwing version)
661 BOOST_CHECK(pt1.get_value<int>() == 1);
662 BOOST_CHECK(pt1.get_value<long>() == 1);
663 BOOST_CHECK(pt2.get_value<double>() == 2.5);
664 BOOST_CHECK(pt2.get_value<float>() == 2.5f);
665 BOOST_CHECK(pt3.get_value<str_t>() == str_t(T("ala ma kota")));
666 BOOST_CHECK(pt4.get_value<CHTYPE>() == CHTYPE('c'));
667 BOOST_CHECK(pt5.get_value<bool>() == false);
668 BOOST_CHECK(pt6.get_value<bool>() == true);
669
670 // Do extractions via get_value (default value version)
671 BOOST_CHECK(pt1.get_value(0) == 1);
672 BOOST_CHECK(pt1.get_value(0L) == 1);
673 BOOST_CHECK(pt2.get_value(0.0) == 2.5);
674 BOOST_CHECK(pt2.get_value(0.0f) == 2.5f);
675 BOOST_CHECK(pt3.get_value(str_t()) == str_t(T("ala ma kota")));
676 BOOST_CHECK(pt3.get_value(T("")) == T("ala ma kota"));
677 BOOST_CHECK(pt4.get_value(CHTYPE('\0')) == CHTYPE('c'));
678 BOOST_CHECK(pt5.get_value(true) == false);
679 BOOST_CHECK(pt6.get_value(false) == true);
680
681 // Do extractions via get_value (optional version)
682 opt_int = pt1.get_value_optional<int>();
683 BOOST_CHECK(opt_int && *opt_int == 1);
684 opt_long = pt1.get_value_optional<long>();
685 BOOST_CHECK(opt_long && *opt_long == 1);
686 opt_double = pt2.get_value_optional<double>();
687 BOOST_CHECK(opt_double && *opt_double == 2.5);
688 opt_float = pt2.get_value_optional<float>();
689 BOOST_CHECK(opt_float && *opt_float == 2.5f);
690 opt_string = pt3.get_value_optional<str_t>();
691 BOOST_CHECK(opt_string && *opt_string == str_t(T("ala ma kota")));
692 opt_char = pt4.get_value_optional<CHTYPE>();
693 BOOST_CHECK(opt_char && *opt_char == CHTYPE('c'));
694 opt_bool = pt5.get_value_optional<bool>();
695 BOOST_CHECK(opt_bool && *opt_bool == false);
696 opt_bool = pt6.get_value_optional<bool>();
697 BOOST_CHECK(opt_bool && *opt_bool == true);
698
699 // Do incorrect extractions (throwing version)
700 try
701 {
702 pt.get<int>(T("k2.k.bogus.path"));
703 BOOST_ERROR("No required exception thrown");
704 }
705 catch (boost::property_tree::ptree_bad_path &) { }
706 catch (...)
707 {
708 BOOST_ERROR("Wrong exception type thrown");
709 }
710 try
711 {
712 pt.get<int>(T("k2.k"));
713 BOOST_ERROR("No required exception thrown");
714 }
715 catch (boost::property_tree::ptree_bad_data &) { }
716 catch (...)
717 {
718 BOOST_ERROR("Wrong exception type thrown");
719 }
720
721 // Do incorrect extractions (default value version)
722 BOOST_CHECK(pt.get(T("k2.k"), -7) == -7);
723 BOOST_CHECK(pt.get(T("k3.k.k"), -7) == -7);
724 BOOST_CHECK(pt.get(T("k4.k.k.k"), -7) == -7);
725
726 // Do incorrect extractions (optional version)
727 BOOST_CHECK(!pt.get_optional<int>(T("k2.k")));
728 BOOST_CHECK(!pt.get_optional<int>(T("k3.k.k")));
729 BOOST_CHECK(!pt.get_optional<int>(T("k4.k.k.k")));
730
731 // Test multiple puts with the same key
732 {
733 PTREE pt;
734 pt.put(T("key"), 1);
735 BOOST_CHECK(pt.get<int>(T("key")) == 1);
736 BOOST_CHECK(pt.size() == 1);
737 pt.put(T("key"), 2);
738 BOOST_CHECK(pt.get<int>(T("key")) == 2);
739 BOOST_CHECK(pt.size() == 1);
740 pt.put(T("key.key.key"), 1);
741 PTREE &child = pt.get_child(T("key.key"));
742 BOOST_CHECK(pt.get<int>(T("key.key.key")) == 1);
743 BOOST_CHECK(child.size() == 1);
744 BOOST_CHECK(child.count(T("key")) == 1);
745 pt.put(T("key.key.key"), 2);
746 BOOST_CHECK(pt.get<int>(T("key.key.key")) == 2);
747 BOOST_CHECK(child.size() == 1);
748 BOOST_CHECK(child.count(T("key")) == 1);
749 }
750
751 // Test multiple puts with the same key
752 {
753 PTREE pt;
754 pt.put(T("key"), 1);
755 BOOST_CHECK(pt.get<int>(T("key")) == 1);
756 BOOST_CHECK(pt.size() == 1);
757 pt.put(T("key"), 2);
758 BOOST_CHECK(pt.get<int>(T("key")) == 2);
759 BOOST_CHECK(pt.size() == 1);
760 pt.put(T("key.key.key"), 1);
761 PTREE &child = pt.get_child(T("key.key"));
762 BOOST_CHECK(child.size() == 1);
763 BOOST_CHECK(child.count(T("key")) == 1);
764 pt.add(T("key.key.key"), 2);
765 BOOST_CHECK(child.size() == 2);
766 BOOST_CHECK(child.count(T("key")) == 2);
767 }
768
769 // Test that put does not destroy children
770 {
771 PTREE pt;
772 pt.put(T("key1"), 1);
773 pt.put(T("key1.key2"), 2);
774 BOOST_CHECK(pt.get<int>(T("key1"), 0) == 1);
775 BOOST_CHECK(pt.get<int>(T("key1.key2"), 0) == 2);
776 pt.put(T("key1"), 2);
777 BOOST_CHECK(pt.get<int>(T("key1"), 0) == 2);
778 BOOST_CHECK(pt.get<int>(T("key1.key2"), 0) == 2);
779 }
780
781 // Test that get of single character that is whitespace works
782 {
783 PTREE pt;
784 pt.put_value(T(' '));
785 CHTYPE ch = pt.get_value<CHTYPE>();
786 BOOST_CHECK(ch == T(' '));
787 }
788
789 // Test that get of non-char value with trailing and leading whitespace works
790 {
791 PTREE pt;
792 pt.put_value(T(" \t\n99 \t\n"));
793 BOOST_CHECK(pt.get_value<int>(0) == 99);
794 }
795
796 }
797
798 void test_get_child_put_child(PTREE *)
799 {
800 PTREE pt(T("ala ma kota"));
801
802 // Do insertions via put_child
803 PTREE pt1, pt2, pt3;
804 pt1.put_child(T("k1"), PTREE());
805 pt1.put_child(T("k2.k"), PTREE());
806 pt2.put_child(T("k1"), pt);
807 pt2.put_child(T("k2.k"), pt);
808
809 // Const references to test const versions of methods
810 const PTREE &cpt1 = pt1, &cpt2 = pt2;
811
812 // Do correct extractions via get_child (throwing version)
813 BOOST_CHECK(pt1.get_child(T("k1")).empty());
814 BOOST_CHECK(pt1.get_child(T("k2.k")).empty());
815 BOOST_CHECK(pt2.get_child(T("k1")) == pt);
816 BOOST_CHECK(pt2.get_child(T("k2.k")) == pt);
817 BOOST_CHECK(cpt1.get_child(T("k1")).empty());
818 BOOST_CHECK(cpt1.get_child(T("k2.k")).empty());
819 BOOST_CHECK(cpt2.get_child(T("k1")) == pt);
820 BOOST_CHECK(cpt2.get_child(T("k2.k")) == pt);
821
822 // Do correct extractions via get_child (default value version)
823 BOOST_CHECK(pt1.get_child(T("k1"), PTREE(T("def"))) != PTREE(T("def")));
824 BOOST_CHECK(pt1.get_child(T("k2.k"), PTREE(T("def"))) != PTREE(T("def")));
825 BOOST_CHECK(pt2.get_child(T("k1"), PTREE(T("def"))) == pt);
826 BOOST_CHECK(pt2.get_child(T("k2.k"), PTREE(T("def"))) == pt);
827 BOOST_CHECK(cpt1.get_child(T("k1"), PTREE(T("def"))) != PTREE(T("def")));
828 BOOST_CHECK(cpt1.get_child(T("k2.k"), PTREE(T("def"))) != PTREE(T("def")));
829 BOOST_CHECK(cpt2.get_child(T("k1"), PTREE(T("def"))) == pt);
830 BOOST_CHECK(cpt2.get_child(T("k2.k"), PTREE(T("def"))) == pt);
831
832 // Do correct extractions via get_child (optional version)
833 boost::optional<PTREE &> opt;
834 boost::optional<const PTREE &> copt;
835 opt = pt1.get_child_optional(T("k1"));
836 BOOST_CHECK(opt);
837 opt = pt1.get_child_optional(T("k2.k"));
838 BOOST_CHECK(opt);
839 opt = pt2.get_child_optional(T("k1"));
840 BOOST_CHECK(opt && *opt == pt);
841 opt = pt2.get_child_optional(T("k2.k"));
842 BOOST_CHECK(opt && *opt == pt);
843 copt = cpt1.get_child_optional(T("k1"));
844 BOOST_CHECK(copt);
845 copt = cpt1.get_child_optional(T("k2.k"));
846 BOOST_CHECK(copt);
847 copt = cpt2.get_child_optional(T("k1"));
848 BOOST_CHECK(copt && *copt == pt);
849 copt = cpt2.get_child_optional(T("k2.k"));
850 BOOST_CHECK(copt && *copt == pt);
851
852 // Do incorrect extractions via get_child (throwing version)
853 try
854 {
855 pt.get_child(T("k2.k.bogus.path"));
856 BOOST_ERROR("No required exception thrown");
857 }
858 catch (boost::property_tree::ptree_bad_path &) { }
859 catch (...)
860 {
861 BOOST_ERROR("Wrong exception type thrown");
862 }
863
864 // Do incorrect extractions via get_child (default value version)
865 BOOST_CHECK(&pt.get_child(T("k2.k.bogus.path"), pt3) == &pt3);
866
867 // Do incorrect extractions via get_child (optional version)
868 BOOST_CHECK(!pt.get_child_optional(T("k2.k.bogus.path")));
869
870 // Test multiple puts with the same key
871 {
872 PTREE pt, tmp1(T("data1")), tmp2(T("data2"));
873 pt.put_child(T("key"), tmp1);
874 BOOST_CHECK(pt.get_child(T("key")) == tmp1);
875 BOOST_CHECK(pt.size() == 1);
876 pt.put_child(T("key"), tmp2);
877 BOOST_CHECK(pt.get_child(T("key")) == tmp2);
878 BOOST_CHECK(pt.size() == 1);
879 pt.put_child(T("key.key.key"), tmp1);
880 PTREE &child = pt.get_child(T("key.key"));
881 BOOST_CHECK(child.size() == 1);
882 pt.put_child(T("key.key.key"), tmp2);
883 BOOST_CHECK(child.size() == 1);
884 }
885
886 // Test multiple adds with the same key
887 {
888 PTREE pt, tmp1(T("data1")), tmp2(T("data2"));
889 pt.add_child(T("key"), tmp1);
890 BOOST_CHECK(pt.size() == 1);
891 pt.add_child(T("key"), tmp2);
892 BOOST_CHECK(pt.size() == 2);
893 BOOST_CHECK(pt.count(T("key")) == 2);
894 pt.add_child(T("key.key.key"), tmp1);
895 PTREE &child = pt.get_child(T("key.key"));
896 BOOST_CHECK(child.size() == 1);
897 BOOST_CHECK(child.count(T("key")) == 1);
898 pt.add_child(T("key.key.key"), tmp2);
899 BOOST_CHECK(child.size() == 2);
900 BOOST_CHECK(child.count(T("key")) == 2);
901 }
902
903 // Test assigning child to tree
904 {
905 PTREE pt;
906 pt.put(T("foo.bar"), T("baz"));
907 pt = pt.get_child(T("foo"));
908 BOOST_CHECK(pt.size() == 1);
909 BOOST_CHECK(pt.get< std::basic_string<CHTYPE> >(T("bar")) == T("baz"));
910 }
911
912 }
913
914 void test_equal_range(PTREE *)
915 {
916 PTREE pt;
917 pt.add_child(T("k1"), PTREE());
918 pt.add_child(T("k2"), PTREE());
919 pt.add_child(T("k1"), PTREE());
920 pt.add_child(T("k3"), PTREE());
921 pt.add_child(T("k1"), PTREE());
922 pt.add_child(T("k2"), PTREE());
923
924 BOOST_CHECK(boost::distance(pt.equal_range(T("k1"))) == 3);
925 BOOST_CHECK(boost::distance(pt.equal_range(T("k2"))) == 2);
926 BOOST_CHECK(boost::distance(pt.equal_range(T("k3"))) == 1);
927 }
928
929 void test_path_separator(PTREE *)
930 {
931
932 typedef PTREE::path_type path;
933
934 // Check instances count
935 //BOOST_CHECK(PTREE::debug_get_instances_count() == 0);
936
937 // Do insertions
938 PTREE pt;
939 pt.put(T("key1"), T("1"));
940 pt.put(T("key2.key"), T("2"));
941 pt.put(T("key3.key.key"), T("3"));
942 pt.put(path(T("key4"), CHTYPE('/')), T("4"));
943 pt.put(path(T("key5/key"), CHTYPE('/')), T("5"));
944 pt.put(path(T("key6/key/key"), CHTYPE('/')), T("6"));
945
946 // Check instances count
947 //BOOST_CHECK(PTREE::debug_get_instances_count() == 13);
948
949 // Do correct extractions
950 BOOST_CHECK(pt.get(T("key1"), 0) == 1);
951 BOOST_CHECK(pt.get(T("key2.key"), 0) == 2);
952 BOOST_CHECK(pt.get(T("key3.key.key"), 0) == 3);
953 BOOST_CHECK(pt.get(path(T("key4"), CHTYPE('/')), 0) == 4);
954 BOOST_CHECK(pt.get(path(T("key5/key"), CHTYPE('/')), 0) == 5);
955 BOOST_CHECK(pt.get(path(T("key6/key/key"), CHTYPE('/')), 0) == 6);
956
957 // Do incorrect extractions
958 BOOST_CHECK(pt.get(T("key2/key"), 0) == 0);
959 BOOST_CHECK(pt.get(T("key3/key/key"), 0) == 0);
960 BOOST_CHECK(pt.get(path(T("key5.key"), CHTYPE('/')), 0) == 0);
961 BOOST_CHECK(pt.get(path(T("key6.key.key"), CHTYPE('/')), 0) == 0);
962
963 }
964
965 void test_path(PTREE *)
966 {
967
968 typedef PTREE::path_type path;
969
970 // Insert
971 PTREE pt;
972 pt.put(T("key1.key2.key3"), 1);
973
974 // Test operator /=
975 {
976 path p;
977 p /= T("key1"); p /= T("key2"); p /= T("key3");
978 BOOST_CHECK(pt.get<int>(p, 0) == 1);
979 }
980
981 // Test operator /=
982 {
983 path p(T("key1"));
984 p /= T("key2.key3");
985 BOOST_CHECK(pt.get<int>(p, 0) == 1);
986 }
987
988 // Test operator /=
989 {
990 path p;
991 path p1(T("key1.key2"));
992 path p2(T("key3"));
993 p /= p1;
994 p /= p2;
995 BOOST_CHECK(pt.get<int>(p, 0) == 1);
996 }
997
998 // Test operator /
999 {
1000 path p = path(T("key1")) / T("key2.key3");
1001 BOOST_CHECK(pt.get<int>(p, 0) == 1);
1002 }
1003
1004 // Test operator /
1005 {
1006 path p = T("key1.key2") / path(T("key3"));
1007 BOOST_CHECK(pt.get<int>(p, 0) == 1);
1008 }
1009
1010 }
1011
1012 void test_precision(PTREE *)
1013 {
1014
1015 typedef double real;
1016
1017 // Quite precise PI value
1018 real pi = real(3.1415926535897932384626433832795028841971);
1019
1020 // Put and get
1021 PTREE pt;
1022 pt.put_value(pi);
1023 real pi2 = pt.get_value<real>();
1024
1025 // Test if precision is "good enough", i.e. if stream precision increase worked
1026 using namespace std;
1027 real error = abs(pi - pi2) *
1028 pow(real(numeric_limits<real>::radix),
1029 real(numeric_limits<real>::digits));
1030 BOOST_CHECK(error < 100);
1031
1032 }
1033
1034 void test_locale(PTREE *)
1035 {
1036 typedef boost::property_tree::translator_between<
1037 std::basic_string<CHTYPE>, double>::type translator;
1038 try
1039 {
1040
1041 // Write strings in english and french locales
1042 PTREE pt;
1043 #ifdef BOOST_WINDOWS
1044 std::locale loc_english("english");
1045 std::locale loc_french("french");
1046 #else
1047 std::locale loc_english("en_GB");
1048 std::locale loc_french("fr_FR");
1049 #endif
1050 pt.put(T("english"), 1.234, translator(loc_english));
1051 pt.put(T("french"), 1.234, translator(loc_french));
1052
1053 // Test contents
1054 BOOST_CHECK(pt.get<PTREE::data_type>(T("english")) == T("1.234"));
1055 BOOST_CHECK(pt.get<PTREE::data_type>(T("french")) == T("1,234"));
1056
1057 }
1058 catch (boost::property_tree::ptree_error &)
1059 {
1060 throw;
1061 }
1062 catch (std::runtime_error &e)
1063 {
1064 std::cerr << "Required locale not supported by the platform. "
1065 "Skipping locale tests (caught std::runtime_error with message " <<
1066 e.what() << ").\n";
1067 }
1068
1069 }
1070
1071 void test_custom_data_type(PTREE *)
1072 {
1073
1074 typedef std::basic_string<CHTYPE> Str;
1075 typedef PTREE::key_compare Comp;
1076
1077 // Property_tree with boost::any as data type
1078 typedef boost::property_tree::basic_ptree<Str, boost::any, Comp> my_ptree;
1079 my_ptree pt;
1080
1081 // Put/get int value
1082 pt.put(T("int value"), 3);
1083 int int_value = pt.get<int>(T("int value"));
1084 BOOST_CHECK(int_value == 3);
1085
1086 // Put/get string value
1087 pt.put<std::basic_string<CHTYPE> >(T("string value"), T("foo bar"));
1088 std::basic_string<CHTYPE> string_value = pt.get<std::basic_string<CHTYPE> >(T("string value"));
1089 BOOST_CHECK(string_value == T("foo bar"));
1090
1091 // Put/get list<int> value
1092 int list_data[] = { 1, 2, 3, 4, 5 };
1093 pt.put<std::list<int> >(T("list value"), std::list<int>(list_data, list_data + sizeof(list_data) / sizeof(*list_data)));
1094 std::list<int> list_value = pt.get<std::list<int> >(T("list value"));
1095 BOOST_CHECK(list_value.size() == 5);
1096 BOOST_CHECK(list_value.front() == 1);
1097 BOOST_CHECK(list_value.back() == 5);
1098
1099 }
1100
1101 void test_empty_size_max_size(PTREE *)
1102 {
1103
1104 PTREE pt;
1105 BOOST_CHECK(pt.max_size());
1106 BOOST_CHECK(pt.empty());
1107 BOOST_CHECK(pt.size() == 0);
1108
1109 pt.put(T("test1"), 1);
1110 BOOST_CHECK(pt.max_size());
1111 BOOST_CHECK(!pt.empty());
1112 BOOST_CHECK(pt.size() == 1);
1113
1114 pt.put(T("test2"), 2);
1115 BOOST_CHECK(pt.max_size());
1116 BOOST_CHECK(!pt.empty());
1117 BOOST_CHECK(pt.size() == 2);
1118
1119 }
1120
1121 void test_ptree_bad_path(PTREE *)
1122 {
1123
1124 PTREE pt;
1125
1126 try
1127 {
1128 pt.get<int>(T("non.existent.path"));
1129 }
1130 catch (boost::property_tree::ptree_bad_path &e)
1131 {
1132 PTREE::path_type path = e.path<PTREE::path_type>();
1133 std::string what = e.what();
1134 BOOST_CHECK(what.find("non.existent.path") != std::string::npos);
1135 return;
1136 }
1137
1138 BOOST_ERROR("No required exception thrown");
1139
1140 }
1141
1142 void test_ptree_bad_data(PTREE *)
1143 {
1144
1145 PTREE pt;
1146 pt.put_value("non convertible to int");
1147
1148 try
1149 {
1150 pt.get_value<int>();
1151 }
1152 catch (boost::property_tree::ptree_bad_data &e)
1153 {
1154 PTREE::data_type data = e.data<PTREE::data_type>();
1155 std::string what = e.what();
1156 // FIXME: Bring back what translation or make it more clear that it
1157 // doesn't work.
1158 //BOOST_CHECK(what.find("non convertible to int") != std::string::npos);
1159 return;
1160 }
1161
1162 BOOST_ERROR("No required exception thrown");
1163 }
1164
1165 void test_serialization(PTREE *)
1166 {
1167
1168 // Prepare test tree
1169 PTREE pt;
1170 pt.put_value(1);
1171 pt.put(T("key1"), 3);
1172 pt.put(T("key1.key11)"), 3.3);
1173 pt.put(T("key1.key12"), T("foo"));
1174 pt.put(T("key2"), true);
1175 pt.put(T("key2.key21.key211.key2111.key21111"), T("super deep!"));
1176 pt.put_child(T("empty"), PTREE());
1177 pt.put(T("loooooong"), PTREE::data_type(10000, CHTYPE('a')));
1178
1179 // Endforce const for input
1180 const PTREE &pt1 = pt;
1181
1182 // Test text archives
1183 {
1184 std::stringstream stream;
1185 boost::archive::text_oarchive oa(stream);
1186 oa & pt1;
1187 boost::archive::text_iarchive ia(stream);
1188 PTREE pt2;
1189 ia & pt2;
1190 BOOST_CHECK(pt1 == pt2);
1191 }
1192
1193 // Test binary archives
1194 {
1195 std::stringstream stream;
1196 boost::archive::binary_oarchive oa(stream);
1197 oa & pt1;
1198 boost::archive::binary_iarchive ia(stream);
1199 PTREE pt2;
1200 ia & pt2;
1201 BOOST_CHECK(pt1 == pt2);
1202 }
1203
1204 // Test XML archives
1205 {
1206 std::stringstream stream;
1207 boost::archive::xml_oarchive oa(stream);
1208 oa & boost::serialization::make_nvp("pt", pt1);
1209 boost::archive::xml_iarchive ia(stream);
1210 PTREE pt2;
1211 ia & boost::serialization::make_nvp("pt", pt2);
1212 BOOST_CHECK(pt1 == pt2);
1213 }
1214
1215 }
1216
1217 void test_bool(PTREE *)
1218 {
1219
1220 // Prepare test tree
1221 PTREE pt;
1222 pt.put(T("bool.false.1"), false);
1223 pt.put(T("bool.false.2"), T("0"));
1224 pt.put(T("bool.true.1"), true);
1225 pt.put(T("bool.true.2"), 1);
1226 pt.put(T("bool.invalid.1"), T(""));
1227 pt.put(T("bool.invalid.2"), T("tt"));
1228 pt.put(T("bool.invalid.3"), T("ff"));
1229 pt.put(T("bool.invalid.4"), T("2"));
1230 pt.put(T("bool.invalid.5"), T("-1"));
1231
1232 // Test false
1233 for (PTREE::iterator it = pt.get_child(T("bool.false")).begin(); it != pt.get_child(T("bool.false")).end(); ++it)
1234 BOOST_CHECK(it->second.get_value<bool>() == false);
1235
1236 // Test true
1237 for (PTREE::iterator it = pt.get_child(T("bool.true")).begin(); it != pt.get_child(T("bool.true")).end(); ++it)
1238 BOOST_CHECK(it->second.get_value<bool>() == true);
1239
1240 // Test invalid
1241 for (PTREE::iterator it = pt.get_child(T("bool.invalid")).begin(); it != pt.get_child(T("bool.invalid")).end(); ++it)
1242 {
1243 BOOST_CHECK(it->second.get_value<bool>(false) == false);
1244 BOOST_CHECK(it->second.get_value<bool>(true) == true);
1245 }
1246
1247 }
1248
1249 void test_char(PTREE *)
1250 {
1251 typedef signed char schar;
1252 typedef unsigned char uchar;
1253
1254 // Prepare test tree
1255 PTREE pt;
1256 #if WIDECHAR == 0
1257 pt.put(T("char"), char('A'));
1258 #endif
1259 pt.put(T("signed char"), static_cast<schar>('A'));
1260 pt.put(T("unsigned char"), static_cast<uchar>('A'));
1261 pt.put(T("signed char min"), (std::numeric_limits<schar>::min)());
1262 pt.put(T("signed char max"), (std::numeric_limits<schar>::max)());
1263 pt.put(T("signed char underflow"),
1264 static_cast<int>((std::numeric_limits<schar>::min)()) - 1);
1265 pt.put(T("signed char overflow"),
1266 static_cast<int>((std::numeric_limits<schar>::max)()) + 1);
1267 pt.put(T("unsigned char min"), (std::numeric_limits<uchar>::min)());
1268 pt.put(T("unsigned char max"), (std::numeric_limits<uchar>::max)());
1269 pt.put(T("unsigned char overflow"),
1270 static_cast<unsigned>((std::numeric_limits<uchar>::max)()) + 1);
1271
1272 // Verify normal conversions
1273 #if WIDECHAR == 0
1274 BOOST_CHECK(pt.get<char>(T("char")) == 'A');
1275 #endif
1276 BOOST_CHECK(pt.get<schar>(T("signed char")) == static_cast<schar>('A'));
1277 BOOST_CHECK(pt.get<uchar>(T("unsigned char")) == static_cast<uchar>('A'));
1278
1279 // Verify that numbers are saved for signed and unsigned char
1280 BOOST_CHECK(pt.get<int>(T("signed char")) == int('A'));
1281 BOOST_CHECK(pt.get<int>(T("unsigned char")) == int('A'));
1282
1283 // Verify ranges
1284 BOOST_CHECK(pt.get<schar>(T("signed char min")) ==
1285 (std::numeric_limits<schar>::min)());
1286 BOOST_CHECK(pt.get<schar>(T("signed char max")) ==
1287 (std::numeric_limits<schar>::max)());
1288 BOOST_CHECK(pt.get<uchar>(T("unsigned char min")) ==
1289 (std::numeric_limits<uchar>::min)());
1290 BOOST_CHECK(pt.get<uchar>(T("unsigned char max")) ==
1291 (std::numeric_limits<uchar>::max)());
1292
1293 // Check that out-of-range throws.
1294 try {
1295 pt.get<schar>(T("signed char underflow"));
1296 BOOST_ERROR("expected ptree_bad_data, but nothing was thrown");
1297 } catch (boost::property_tree::ptree_bad_data&) {
1298 } catch (...) {
1299 BOOST_ERROR("expected ptree_bad_data, but something else was thrown");
1300 }
1301 try {
1302 pt.get<schar>(T("signed char overflow"));
1303 BOOST_ERROR("expected ptree_bad_data, but nothing was thrown");
1304 } catch (boost::property_tree::ptree_bad_data&) {
1305 } catch (...) {
1306 BOOST_ERROR("expected ptree_bad_data, but something else was thrown");
1307 }
1308 try {
1309 pt.get<uchar>(T("unsigned char overflow"));
1310 BOOST_ERROR("expected ptree_bad_data, but nothing was thrown");
1311 } catch (boost::property_tree::ptree_bad_data&) {
1312 } catch (...) {
1313 BOOST_ERROR("expected ptree_bad_data, but something else was thrown");
1314 }
1315 }
1316
1317 void test_float(PTREE*)
1318 {
1319 const double difficult = -183.12345000098765e-10;
1320 PTREE pt;
1321 pt.put(T("num"), difficult);
1322 double result = pt.get<double>(T("num"));
1323
1324 BOOST_CHECK(!(result < difficult || result > difficult));
1325 }
1326
1327 void test_sort(PTREE *)
1328 {
1329 PTREE pt;
1330 pt.put(T("one"), T("v1"));
1331 pt.put(T("two"), T("v2"));
1332 pt.put(T("three"), T("v3"));
1333 pt.put(T("four"), T("v4"));
1334
1335 pt.sort();
1336
1337 PTREE::iterator it = pt.begin();
1338 BOOST_CHECK(std::distance(it, pt.end()) == 4);
1339 BOOST_CHECK(it->first == T("four"));
1340 BOOST_CHECK(it->second.data() == T("v4"));
1341 ++it;
1342 BOOST_CHECK(it->first == T("one"));
1343 BOOST_CHECK(it->second.data() == T("v1"));
1344 ++it;
1345 BOOST_CHECK(it->first == T("three"));
1346 BOOST_CHECK(it->second.data() == T("v3"));
1347 ++it;
1348 BOOST_CHECK(it->first == T("two"));
1349 BOOST_CHECK(it->second.data() == T("v2"));
1350 }
1351
1352 void test_leaks(PTREE *)
1353 {
1354 //BOOST_CHECK(PTREE::debug_get_instances_count() == 0);
1355 }