1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2002-2006 Marcin Kalicinski
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)
8 // For more information, see www.boost.org
9 // ----------------------------------------------------------------------------
11 // Intentionally no include guards (to be included more than once)
13 #if !defined(CHTYPE) || !defined(T) || !defined(PTREE) || !defined(NOCASE) || !defined(WIDECHAR)
14 # error No character type specified
17 void test_debug(PTREE *)
21 BOOST_TEST(PTREE::debug_get_instances_count() == 0);
27 BOOST_TEST(PTREE::debug_get_instances_count() == 2);
30 PTREE *pt3 = new PTREE;
31 BOOST_TEST(PTREE::debug_get_instances_count() == 3);
34 pt1.push_back(std::make_pair(T("key"), *pt3));
35 BOOST_TEST(PTREE::debug_get_instances_count() == 4);
38 pt2.push_back(std::make_pair(T("key"), *pt3));
39 BOOST_TEST(PTREE::debug_get_instances_count() == 5);
43 BOOST_TEST(PTREE::debug_get_instances_count() == 4);
47 BOOST_TEST(PTREE::debug_get_instances_count() == 3);
51 BOOST_TEST(PTREE::debug_get_instances_count() == 2);
56 BOOST_TEST(PTREE::debug_get_instances_count() == 0);
60 void test_constructor_destructor_assignment(PTREE *)
65 // Test constructor from string
67 BOOST_TEST(pt1.data() == T("data"));
68 //BOOST_TEST(PTREE::debug_get_instances_count() == 1);
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_TEST(PTREE::debug_get_instances_count() == 5);
77 // Make a copy using copy constructor
78 PTREE *pt2 = new PTREE(pt1);
79 BOOST_TEST(*pt2 == pt1);
80 //BOOST_TEST(PTREE::debug_get_instances_count() == 10);
82 // Make a copy using = operator
83 PTREE *pt3 = new PTREE;
85 BOOST_TEST(*pt3 == *pt2);
86 //BOOST_TEST(PTREE::debug_get_instances_count() == 15);
88 // Test self assignment
90 BOOST_TEST(pt1 == *pt2);
91 BOOST_TEST(pt1 == *pt3);
92 //BOOST_TEST(PTREE::debug_get_instances_count() == 15);
96 //BOOST_TEST(PTREE::debug_get_instances_count() == 10);
100 //BOOST_TEST(PTREE::debug_get_instances_count() == 5);
105 //BOOST_TEST(PTREE::debug_get_instances_count() == 0);
109 void test_insertion(PTREE *)
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());
124 // Check instance count
125 //BOOST_TEST(PTREE::debug_get_instances_count() == 11);
128 BOOST_TEST(pt.get(T("key1"), T("")) == T("data1"));
129 BOOST_TEST(pt.get(T("key2"), T("")) == T("data2"));
130 BOOST_TEST(pt.get(T("key1.key3"), T("")) == T("data3"));
131 BOOST_TEST(pt.get(T("key1.key4"), T("")) == T("data4"));
132 BOOST_TEST(pt.get(T("key2.key3"), T("")) == T("data3"));
133 BOOST_TEST(pt.get(T("key2.key4"), T("")) == T("data4"));
136 PTREE::iterator it = it2;
137 ++it; BOOST_TEST(it == it1);
138 ++it; BOOST_TEST(it == pt.end());
140 ++it; BOOST_TEST(it == it3);
141 ++it; BOOST_TEST(it == it1->second.end());
145 void test_erasing(PTREE *)
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());
160 // Check instance count
161 //BOOST_TEST(PTREE::debug_get_instances_count() == 11);
164 PTREE::iterator it = it1->second.erase(it1->second.begin(), it1->second.end());
165 BOOST_TEST(it == it1->second.end());
166 //BOOST_TEST(PTREE::debug_get_instances_count() == 9);
169 PTREE::size_type n = pt.erase(T("key1"));
171 //BOOST_TEST(PTREE::debug_get_instances_count() == 8);
173 // Test multiple erase
174 n = it2->second.erase(T("key"));
176 //BOOST_TEST(PTREE::debug_get_instances_count() == 6);
178 // Test one more erase
179 n = pt.erase(T("key2"));
181 //BOOST_TEST(PTREE::debug_get_instances_count() == 5);
185 void test_clear(PTREE *)
190 pt.push_back(std::make_pair(T("key"), PTREE(T("data"))));
192 // Check instance count
193 //BOOST_TEST(PTREE::debug_get_instances_count() == 2);
197 BOOST_TEST(pt.empty());
198 BOOST_TEST(pt.data().empty());
199 //BOOST_TEST(PTREE::debug_get_instances_count() == 1);
203 void test_pushpop(PTREE *)
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));
217 // Check instance count
218 //BOOST_TEST(PTREE::debug_get_instances_count() == 9);
221 PTREE::iterator it = pt.begin();
222 BOOST_TEST(it->first == T("key1")); ++it;
223 BOOST_TEST(it->first == T("key2")); ++it;
224 BOOST_TEST(it->first == T("key3")); ++it;
225 BOOST_TEST(it->first == T("key4")); ++it;
226 BOOST_TEST(it == pt.end());
230 //BOOST_TEST(PTREE::debug_get_instances_count() == 8);
231 BOOST_TEST(pt.front().second.data() == T("data1"));
232 BOOST_TEST(pt.back().second.data() == T("data3"));
234 //BOOST_TEST(PTREE::debug_get_instances_count() == 7);
235 BOOST_TEST(pt.front().second.data() == T("data2"));
236 BOOST_TEST(pt.back().second.data() == T("data3"));
238 //BOOST_TEST(PTREE::debug_get_instances_count() == 6);
239 BOOST_TEST(pt.front().second.data() == T("data2"));
240 BOOST_TEST(pt.back().second.data() == T("data2"));
242 //BOOST_TEST(PTREE::debug_get_instances_count() == 5);
243 BOOST_TEST(pt.empty());
247 void test_container_iteration(PTREE *)
252 pt.put(T("key3"), T(""));
253 pt.put(T("key1"), T(""));
254 pt.put(T("key4"), T(""));
255 pt.put(T("key2"), T(""));
259 PTREE::iterator it = pt.begin();
260 BOOST_TEST(it->first == T("key3")); ++it;
261 BOOST_TEST(it->first == T("key1")); ++it;
262 BOOST_TEST(it->first == T("key4")); ++it;
263 BOOST_TEST(it->first == T("key2")); ++it;
264 BOOST_TEST(it == pt.end());
269 PTREE::const_iterator it = pt.begin();
270 BOOST_TEST(it->first == T("key3")); ++it;
271 BOOST_TEST(it->first == T("key1")); ++it;
272 BOOST_TEST(it->first == T("key4")); ++it;
273 BOOST_TEST(it->first == T("key2")); ++it;
274 BOOST_TEST(it == pt.end());
279 PTREE::reverse_iterator it = pt.rbegin();
280 BOOST_TEST(it->first == T("key2")); ++it;
281 BOOST_TEST(it->first == T("key4")); ++it;
282 BOOST_TEST(it->first == T("key1")); ++it;
283 BOOST_TEST(it->first == T("key3")); ++it;
284 BOOST_TEST(it == pt.rend());
287 // const_reverse_iterator
289 PTREE::const_reverse_iterator it = pt.rbegin();
290 BOOST_TEST(it->first == T("key2")); ++it;
291 BOOST_TEST(it->first == T("key4")); ++it;
292 BOOST_TEST(it->first == T("key1")); ++it;
293 BOOST_TEST(it->first == T("key3")); ++it;
294 BOOST_TEST(it == PTREE::const_reverse_iterator(pt.rend()));
299 void test_swap(PTREE *)
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(""));
311 //BOOST_TEST(PTREE::debug_get_instances_count() == 6);
312 BOOST_TEST(pt1.size() == 2);
313 BOOST_TEST(pt1.get_child(T("key1")).size() == 2);
314 BOOST_TEST(pt2.size() == 0);
316 // Swap using member function
320 //BOOST_TEST(PTREE::debug_get_instances_count() == 6);
321 BOOST_TEST(pt2.size() == 2);
322 BOOST_TEST(pt2.get_child(T("key1")).size() == 2);
323 BOOST_TEST(pt1.size() == 0);
325 // Swap using free function
329 //BOOST_TEST(PTREE::debug_get_instances_count() == 6);
330 BOOST_TEST(pt1.size() == 2);
331 BOOST_TEST(pt1.get_child(T("key1")).size() == 2);
332 BOOST_TEST(pt2.size() == 0);
334 // Swap using std algorithm
338 //BOOST_TEST(PTREE::debug_get_instances_count() == 6);
339 BOOST_TEST(pt2.size() == 2);
340 BOOST_TEST(pt2.get_child(T("key1")).size() == 2);
341 BOOST_TEST(pt1.size() == 0);
345 void test_sort_reverse(PTREE *)
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(""));
363 PTREE::iterator it = pt.begin();
364 BOOST_TEST(it->first == T("key3")); ++it;
365 BOOST_TEST(it->first == T("key4")); ++it;
366 BOOST_TEST(it->first == T("key1")); ++it;
367 BOOST_TEST(it->first == T("key2")); ++it;
368 BOOST_TEST(it == pt.end());
370 // Check sequence using find to check if index is ok
372 PTREE::iterator it = pt.begin();
373 BOOST_TEST(it == pt.to_iterator(pt.find(T("key3")))); ++it;
374 BOOST_TEST(it == pt.to_iterator(pt.find(T("key4")))); ++it;
375 BOOST_TEST(it == pt.to_iterator(pt.find(T("key1")))); ++it;
376 BOOST_TEST(it == pt.to_iterator(pt.find(T("key2")))); ++it;
377 BOOST_TEST(it == pt.end());
381 pt.sort(SortPred<PTREE>());
385 PTREE::iterator it = pt.begin();
386 BOOST_TEST(it->first == T("key1")); ++it;
387 BOOST_TEST(it->first == T("key2")); ++it;
388 BOOST_TEST(it->first == T("key3")); ++it;
389 BOOST_TEST(it->first == T("key4")); ++it;
390 BOOST_TEST(it == pt.end());
392 // Check sequence (using find to check if index is ok)
394 PTREE::iterator it = pt.begin();
395 BOOST_TEST(it == pt.to_iterator(pt.find(T("key1")))); ++it;
396 BOOST_TEST(it == pt.to_iterator(pt.find(T("key2")))); ++it;
397 BOOST_TEST(it == pt.to_iterator(pt.find(T("key3")))); ++it;
398 BOOST_TEST(it == pt.to_iterator(pt.find(T("key4")))); ++it;
399 BOOST_TEST(it == pt.end());
403 pt.sort(SortPredRev<PTREE>());
407 PTREE::iterator it = pt.begin();
408 BOOST_TEST(it->first == T("key4")); ++it;
409 BOOST_TEST(it->first == T("key3")); ++it;
410 BOOST_TEST(it->first == T("key2")); ++it;
411 BOOST_TEST(it->first == T("key1")); ++it;
412 BOOST_TEST(it == pt.end());
414 // Check sequence (using find to check if index is ok)
416 PTREE::iterator it = pt.begin();
417 BOOST_TEST(it == pt.to_iterator(pt.find(T("key4")))); ++it;
418 BOOST_TEST(it == pt.to_iterator(pt.find(T("key3")))); ++it;
419 BOOST_TEST(it == pt.to_iterator(pt.find(T("key2")))); ++it;
420 BOOST_TEST(it == pt.to_iterator(pt.find(T("key1")))); ++it;
421 BOOST_TEST(it == pt.end());
426 void test_case(PTREE *)
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"));
436 // Check findings depending on traits type
438 //BOOST_TEST(PTREE::debug_get_instances_count() == 7);
439 BOOST_TEST(pt.get(T("key1"), T("")) == T("data1"));
440 BOOST_TEST(pt.get(T("key2"), T("")) == T(""));
441 BOOST_TEST(pt.get(T("key1.key3"), T("")) == T(""));
442 BOOST_TEST(pt.get(T("KEY1.key4"), T("")) == T("data4"));
444 //BOOST_TEST(PTREE::debug_get_instances_count() == 5);
445 BOOST_TEST(pt.get(T("key1"), T("1")) == pt.get(T("KEY1"), T("2")));
446 BOOST_TEST(pt.get(T("key2"), T("1")) == pt.get(T("KEY2"), T("2")));
447 BOOST_TEST(pt.get(T("key1.key3"), T("1")) == pt.get(T("KEY1.KEY3"), T("2")));
448 BOOST_TEST(pt.get(T("key1.key4"), T("1")) == pt.get(T("KEY1.KEY4"), T("2")));
451 // Do more insertions
452 pt.push_back(PTREE::value_type(T("key1"), PTREE()));
453 pt.push_back(PTREE::value_type(T("key1"), PTREE()));
457 BOOST_TEST(pt.count(T("key1")) == 3);
458 BOOST_TEST(pt.count(T("KEY1")) == 1);
459 BOOST_TEST(pt.count(T("key2")) == 0);
460 BOOST_TEST(pt.count(T("KEY2")) == 1);
461 BOOST_TEST(pt.count(T("key3")) == 0);
462 BOOST_TEST(pt.count(T("KEY3")) == 0);
464 BOOST_TEST(pt.count(T("key1")) == 3);
465 BOOST_TEST(pt.count(T("KEY1")) == 3);
466 BOOST_TEST(pt.count(T("key2")) == 1);
467 BOOST_TEST(pt.count(T("KEY2")) == 1);
468 BOOST_TEST(pt.count(T("key3")) == 0);
469 BOOST_TEST(pt.count(T("KEY3")) == 0);
474 void test_comparison(PTREE *)
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"));
488 BOOST_TEST(pt1 == pt2);
489 BOOST_TEST(pt2 == pt1);
490 BOOST_TEST(!(pt1 != pt2));
491 BOOST_TEST(!(pt2 != pt1));
494 // Test originals with modified case
500 pt1.put(T("KEY2"), T("data4"));
501 BOOST_TEST(pt1 == pt2);
502 BOOST_TEST(pt2 == pt1);
503 BOOST_TEST(!(pt1 != pt2));
504 BOOST_TEST(!(pt2 != pt1));
508 // Test modified copies (both modified the same way)
512 pt1.put(T("key1.key5"), T("."));
513 pt2.put(T("key1.key5"), T("."));
514 BOOST_TEST(pt1 == pt2);
515 BOOST_TEST(pt2 == pt1);
516 BOOST_TEST(!(pt1 != pt2));
517 BOOST_TEST(!(pt2 != pt1));
520 // Test modified copies (modified root data)
526 BOOST_TEST(!(pt1 == pt2));
527 BOOST_TEST(!(pt2 == pt1));
528 BOOST_TEST(pt1 != pt2);
529 BOOST_TEST(pt2 != pt1);
532 // Test modified copies (added subkeys with different data)
536 pt1.put(T("key1.key5"), T("a"));
537 pt2.put(T("key1.key5"), T("b"));
538 BOOST_TEST(!(pt1 == pt2));
539 BOOST_TEST(!(pt2 == pt1));
540 BOOST_TEST(pt1 != pt2);
541 BOOST_TEST(pt2 != pt1);
544 // Test modified copies (added subkeys with different keys)
548 pt1.put(T("key1.key5"), T(""));
549 pt2.put(T("key1.key6"), T(""));
550 BOOST_TEST(!(pt1 == pt2));
551 BOOST_TEST(!(pt2 == pt1));
552 BOOST_TEST(pt1 != pt2);
553 BOOST_TEST(pt2 != pt1);
556 // Test modified copies (added subkey to only one copy)
560 pt1.put(T("key1.key5"), T(""));
561 BOOST_TEST(!(pt1 == pt2));
562 BOOST_TEST(!(pt2 == pt1));
563 BOOST_TEST(pt1 != pt2);
564 BOOST_TEST(pt2 != pt1);
569 void test_front_back(PTREE *)
574 pt.put(T("key1"), T(""));
575 pt.put(T("key2"), T(""));
577 // Check front and back
578 BOOST_TEST(pt.front().first == T("key1"));
579 BOOST_TEST(pt.back().first == T("key2"));
583 void test_get_put(PTREE *)
586 typedef std::basic_string<CHTYPE> str_t;
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;
598 // Do insertions via put
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);
607 // Check instances count
608 //BOOST_TEST(PTREE::debug_get_instances_count() == 17);
610 // Check if const char * version returns std::string
611 BOOST_TEST(typeid(pt.get_value(T(""))) == typeid(str_t));
613 // Do extractions via get (throwing version)
614 BOOST_TEST(pt.get<int>(T("k1")) == 1);
615 BOOST_TEST(pt.get<long>(T("k1")) == 1);
616 BOOST_TEST(pt.get<double>(T("k2.k")) == 2.5);
617 BOOST_TEST(pt.get<float>(T("k2.k")) == 2.5f);
618 BOOST_TEST(pt.get<str_t>(T("k3.k.k")) == str_t(T("ala ma kota")));
619 BOOST_TEST(pt.get<CHTYPE>(T("k4.k.k.k")) == CHTYPE('c'));
620 BOOST_TEST(pt.get<bool>(T("k5.k.k.k.f")) == false);
621 BOOST_TEST(pt.get<bool>(T("k5.k.k.k.t")) == true);
623 // Do extractions via get (default value version)
624 BOOST_TEST(pt.get(T("k1"), 0) == 1);
625 BOOST_TEST(pt.get(T("k1"), 0L) == 1);
626 BOOST_TEST(pt.get(T("k2.k"), 0.0) == 2.5);
627 BOOST_TEST(pt.get(T("k2.k"), 0.0f) == 2.5f);
628 BOOST_TEST(pt.get(T("k3.k.k"), str_t()) == str_t(T("ala ma kota")));
629 BOOST_TEST(pt.get(T("k3.k.k"), T("")) == T("ala ma kota"));
630 BOOST_TEST(pt.get(T("k4.k.k.k"), CHTYPE('\0')) == CHTYPE('c'));
631 BOOST_TEST(pt.get(T("k5.k.k.k.f"), true) == false);
632 BOOST_TEST(pt.get(T("k5.k.k.k.t"), false) == true);
634 // Do extractions via get (optional version)
635 opt_int = pt.get_optional<int>(T("k1"));
636 BOOST_TEST(opt_int && *opt_int == 1);
637 opt_long = pt.get_optional<long>(T("k1"));
638 BOOST_TEST(opt_long && *opt_long == 1);
639 opt_double = pt.get_optional<double>(T("k2.k"));
640 BOOST_TEST(opt_double && *opt_double == 2.5);
641 opt_float = pt.get_optional<float>(T("k2.k"));
642 BOOST_TEST(opt_float && *opt_float == 2.5f);
643 opt_string = pt.get_optional<str_t>(T("k3.k.k"));
644 BOOST_TEST(opt_string && *opt_string == str_t(T("ala ma kota")));
645 opt_char = pt.get_optional<CHTYPE>(T("k4.k.k.k"));
646 BOOST_TEST(opt_char && *opt_char == CHTYPE('c'));
647 opt_bool = pt.get_optional<bool>(T("k5.k.k.k.f"));
648 BOOST_TEST(opt_bool && *opt_bool == false);
649 opt_bool = pt.get_optional<bool>(T("k5.k.k.k.t"));
650 BOOST_TEST(opt_bool && *opt_bool == true);
652 // Do insertions via put_value
653 pt1.put_value(short(1));
655 pt3.put_value(str_t(T("ala ma kota")));
656 pt4.put_value(CHTYPE('c'));
657 pt5.put_value(false);
660 // Do extractions via get_value (throwing version)
661 BOOST_TEST(pt1.get_value<int>() == 1);
662 BOOST_TEST(pt1.get_value<long>() == 1);
663 BOOST_TEST(pt2.get_value<double>() == 2.5);
664 BOOST_TEST(pt2.get_value<float>() == 2.5f);
665 BOOST_TEST(pt3.get_value<str_t>() == str_t(T("ala ma kota")));
666 BOOST_TEST(pt4.get_value<CHTYPE>() == CHTYPE('c'));
667 BOOST_TEST(pt5.get_value<bool>() == false);
668 BOOST_TEST(pt6.get_value<bool>() == true);
670 // Do extractions via get_value (default value version)
671 BOOST_TEST(pt1.get_value(0) == 1);
672 BOOST_TEST(pt1.get_value(0L) == 1);
673 BOOST_TEST(pt2.get_value(0.0) == 2.5);
674 BOOST_TEST(pt2.get_value(0.0f) == 2.5f);
675 BOOST_TEST(pt3.get_value(str_t()) == str_t(T("ala ma kota")));
676 BOOST_TEST(pt3.get_value(T("")) == T("ala ma kota"));
677 BOOST_TEST(pt4.get_value(CHTYPE('\0')) == CHTYPE('c'));
678 BOOST_TEST(pt5.get_value(true) == false);
679 BOOST_TEST(pt6.get_value(false) == true);
681 // Do extractions via get_value (optional version)
682 opt_int = pt1.get_value_optional<int>();
683 BOOST_TEST(opt_int && *opt_int == 1);
684 opt_long = pt1.get_value_optional<long>();
685 BOOST_TEST(opt_long && *opt_long == 1);
686 opt_double = pt2.get_value_optional<double>();
687 BOOST_TEST(opt_double && *opt_double == 2.5);
688 opt_float = pt2.get_value_optional<float>();
689 BOOST_TEST(opt_float && *opt_float == 2.5f);
690 opt_string = pt3.get_value_optional<str_t>();
691 BOOST_TEST(opt_string && *opt_string == str_t(T("ala ma kota")));
692 opt_char = pt4.get_value_optional<CHTYPE>();
693 BOOST_TEST(opt_char && *opt_char == CHTYPE('c'));
694 opt_bool = pt5.get_value_optional<bool>();
695 BOOST_TEST(opt_bool && *opt_bool == false);
696 opt_bool = pt6.get_value_optional<bool>();
697 BOOST_TEST(opt_bool && *opt_bool == true);
699 // Do incorrect extractions (throwing version)
702 pt.get<int>(T("k2.k.bogus.path"));
703 BOOST_ERROR("No required exception thrown");
705 catch (boost::property_tree::ptree_bad_path &) { }
708 BOOST_ERROR("Wrong exception type thrown");
712 pt.get<int>(T("k2.k"));
713 BOOST_ERROR("No required exception thrown");
715 catch (boost::property_tree::ptree_bad_data &) { }
718 BOOST_ERROR("Wrong exception type thrown");
721 // Do incorrect extractions (default value version)
722 BOOST_TEST(pt.get(T("k2.k"), -7) == -7);
723 BOOST_TEST(pt.get(T("k3.k.k"), -7) == -7);
724 BOOST_TEST(pt.get(T("k4.k.k.k"), -7) == -7);
726 // Do incorrect extractions (optional version)
727 BOOST_TEST(!pt.get_optional<int>(T("k2.k")));
728 BOOST_TEST(!pt.get_optional<int>(T("k3.k.k")));
729 BOOST_TEST(!pt.get_optional<int>(T("k4.k.k.k")));
731 // Test multiple puts with the same key
735 BOOST_TEST(pt.get<int>(T("key")) == 1);
736 BOOST_TEST(pt.size() == 1);
738 BOOST_TEST(pt.get<int>(T("key")) == 2);
739 BOOST_TEST(pt.size() == 1);
740 pt.put(T("key.key.key"), 1);
741 PTREE &child = pt.get_child(T("key.key"));
742 BOOST_TEST(pt.get<int>(T("key.key.key")) == 1);
743 BOOST_TEST(child.size() == 1);
744 BOOST_TEST(child.count(T("key")) == 1);
745 pt.put(T("key.key.key"), 2);
746 BOOST_TEST(pt.get<int>(T("key.key.key")) == 2);
747 BOOST_TEST(child.size() == 1);
748 BOOST_TEST(child.count(T("key")) == 1);
751 // Test multiple puts with the same key
755 BOOST_TEST(pt.get<int>(T("key")) == 1);
756 BOOST_TEST(pt.size() == 1);
758 BOOST_TEST(pt.get<int>(T("key")) == 2);
759 BOOST_TEST(pt.size() == 1);
760 pt.put(T("key.key.key"), 1);
761 PTREE &child = pt.get_child(T("key.key"));
762 BOOST_TEST(child.size() == 1);
763 BOOST_TEST(child.count(T("key")) == 1);
764 pt.add(T("key.key.key"), 2);
765 BOOST_TEST(child.size() == 2);
766 BOOST_TEST(child.count(T("key")) == 2);
769 // Test that put does not destroy children
772 pt.put(T("key1"), 1);
773 pt.put(T("key1.key2"), 2);
774 BOOST_TEST(pt.get<int>(T("key1"), 0) == 1);
775 BOOST_TEST(pt.get<int>(T("key1.key2"), 0) == 2);
776 pt.put(T("key1"), 2);
777 BOOST_TEST(pt.get<int>(T("key1"), 0) == 2);
778 BOOST_TEST(pt.get<int>(T("key1.key2"), 0) == 2);
781 // Test that get of single character that is whitespace works
784 pt.put_value(T(' '));
785 CHTYPE ch = pt.get_value<CHTYPE>();
786 BOOST_TEST(ch == T(' '));
789 // Test that get of non-char value with trailing and leading whitespace works
792 pt.put_value(T(" \t\n99 \t\n"));
793 BOOST_TEST(pt.get_value<int>(0) == 99);
798 void test_get_child_put_child(PTREE *)
800 PTREE pt(T("ala ma kota"));
802 // Do insertions via put_child
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);
809 // Const references to test const versions of methods
810 const PTREE &cpt1 = pt1, &cpt2 = pt2;
812 // Do correct extractions via get_child (throwing version)
813 BOOST_TEST(pt1.get_child(T("k1")).empty());
814 BOOST_TEST(pt1.get_child(T("k2.k")).empty());
815 BOOST_TEST(pt2.get_child(T("k1")) == pt);
816 BOOST_TEST(pt2.get_child(T("k2.k")) == pt);
817 BOOST_TEST(cpt1.get_child(T("k1")).empty());
818 BOOST_TEST(cpt1.get_child(T("k2.k")).empty());
819 BOOST_TEST(cpt2.get_child(T("k1")) == pt);
820 BOOST_TEST(cpt2.get_child(T("k2.k")) == pt);
822 // Do correct extractions via get_child (default value version)
823 BOOST_TEST(pt1.get_child(T("k1"), PTREE(T("def"))) != PTREE(T("def")));
824 BOOST_TEST(pt1.get_child(T("k2.k"), PTREE(T("def"))) != PTREE(T("def")));
825 BOOST_TEST(pt2.get_child(T("k1"), PTREE(T("def"))) == pt);
826 BOOST_TEST(pt2.get_child(T("k2.k"), PTREE(T("def"))) == pt);
827 BOOST_TEST(cpt1.get_child(T("k1"), PTREE(T("def"))) != PTREE(T("def")));
828 BOOST_TEST(cpt1.get_child(T("k2.k"), PTREE(T("def"))) != PTREE(T("def")));
829 BOOST_TEST(cpt2.get_child(T("k1"), PTREE(T("def"))) == pt);
830 BOOST_TEST(cpt2.get_child(T("k2.k"), PTREE(T("def"))) == pt);
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"));
837 opt = pt1.get_child_optional(T("k2.k"));
839 opt = pt2.get_child_optional(T("k1"));
840 BOOST_TEST(opt && *opt == pt);
841 opt = pt2.get_child_optional(T("k2.k"));
842 BOOST_TEST(opt && *opt == pt);
843 copt = cpt1.get_child_optional(T("k1"));
845 copt = cpt1.get_child_optional(T("k2.k"));
847 copt = cpt2.get_child_optional(T("k1"));
848 BOOST_TEST(copt && *copt == pt);
849 copt = cpt2.get_child_optional(T("k2.k"));
850 BOOST_TEST(copt && *copt == pt);
852 // Do incorrect extractions via get_child (throwing version)
855 pt.get_child(T("k2.k.bogus.path"));
856 BOOST_ERROR("No required exception thrown");
858 catch (boost::property_tree::ptree_bad_path &) { }
861 BOOST_ERROR("Wrong exception type thrown");
864 // Do incorrect extractions via get_child (default value version)
865 BOOST_TEST(&pt.get_child(T("k2.k.bogus.path"), pt3) == &pt3);
867 // Do incorrect extractions via get_child (optional version)
868 BOOST_TEST(!pt.get_child_optional(T("k2.k.bogus.path")));
870 // Test multiple puts with the same key
872 PTREE pt, tmp1(T("data1")), tmp2(T("data2"));
873 pt.put_child(T("key"), tmp1);
874 BOOST_TEST(pt.get_child(T("key")) == tmp1);
875 BOOST_TEST(pt.size() == 1);
876 pt.put_child(T("key"), tmp2);
877 BOOST_TEST(pt.get_child(T("key")) == tmp2);
878 BOOST_TEST(pt.size() == 1);
879 pt.put_child(T("key.key.key"), tmp1);
880 PTREE &child = pt.get_child(T("key.key"));
881 BOOST_TEST(child.size() == 1);
882 pt.put_child(T("key.key.key"), tmp2);
883 BOOST_TEST(child.size() == 1);
886 // Test multiple adds with the same key
888 PTREE pt, tmp1(T("data1")), tmp2(T("data2"));
889 pt.add_child(T("key"), tmp1);
890 BOOST_TEST(pt.size() == 1);
891 pt.add_child(T("key"), tmp2);
892 BOOST_TEST(pt.size() == 2);
893 BOOST_TEST(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_TEST(child.size() == 1);
897 BOOST_TEST(child.count(T("key")) == 1);
898 pt.add_child(T("key.key.key"), tmp2);
899 BOOST_TEST(child.size() == 2);
900 BOOST_TEST(child.count(T("key")) == 2);
903 // Test assigning child to tree
906 pt.put(T("foo.bar"), T("baz"));
907 pt = pt.get_child(T("foo"));
908 BOOST_TEST(pt.size() == 1);
909 BOOST_TEST(pt.get< std::basic_string<CHTYPE> >(T("bar")) == T("baz"));
914 void test_equal_range(PTREE *)
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());
924 BOOST_TEST(boost::distance(pt.equal_range(T("k1"))) == 3);
925 BOOST_TEST(boost::distance(pt.equal_range(T("k2"))) == 2);
926 BOOST_TEST(boost::distance(pt.equal_range(T("k3"))) == 1);
929 void test_path_separator(PTREE *)
932 typedef PTREE::path_type path;
934 // Check instances count
935 //BOOST_TEST(PTREE::debug_get_instances_count() == 0);
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"));
946 // Check instances count
947 //BOOST_TEST(PTREE::debug_get_instances_count() == 13);
949 // Do correct extractions
950 BOOST_TEST(pt.get(T("key1"), 0) == 1);
951 BOOST_TEST(pt.get(T("key2.key"), 0) == 2);
952 BOOST_TEST(pt.get(T("key3.key.key"), 0) == 3);
953 BOOST_TEST(pt.get(path(T("key4"), CHTYPE('/')), 0) == 4);
954 BOOST_TEST(pt.get(path(T("key5/key"), CHTYPE('/')), 0) == 5);
955 BOOST_TEST(pt.get(path(T("key6/key/key"), CHTYPE('/')), 0) == 6);
957 // Do incorrect extractions
958 BOOST_TEST(pt.get(T("key2/key"), 0) == 0);
959 BOOST_TEST(pt.get(T("key3/key/key"), 0) == 0);
960 BOOST_TEST(pt.get(path(T("key5.key"), CHTYPE('/')), 0) == 0);
961 BOOST_TEST(pt.get(path(T("key6.key.key"), CHTYPE('/')), 0) == 0);
965 void test_path(PTREE *)
968 typedef PTREE::path_type path;
972 pt.put(T("key1.key2.key3"), 1);
977 p /= T("key1"); p /= T("key2"); p /= T("key3");
978 BOOST_TEST(pt.get<int>(p, 0) == 1);
985 BOOST_TEST(pt.get<int>(p, 0) == 1);
991 path p1(T("key1.key2"));
995 BOOST_TEST(pt.get<int>(p, 0) == 1);
1000 path p = path(T("key1")) / T("key2.key3");
1001 BOOST_TEST(pt.get<int>(p, 0) == 1);
1006 path p = T("key1.key2") / path(T("key3"));
1007 BOOST_TEST(pt.get<int>(p, 0) == 1);
1012 void test_precision(PTREE *)
1015 typedef double real;
1017 // Quite precise PI value
1018 real pi = real(3.1415926535897932384626433832795028841971);
1023 real pi2 = pt.get_value<real>();
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_TEST(error < 100);
1034 void test_locale(PTREE *)
1036 typedef boost::property_tree::translator_between<
1037 std::basic_string<CHTYPE>, double>::type translator;
1041 // Write strings in english and french locales
1043 #ifdef BOOST_WINDOWS
1044 std::locale loc_english("english");
1045 std::locale loc_french("french");
1047 std::locale loc_english("en_GB");
1048 std::locale loc_french("fr_FR");
1050 pt.put(T("english"), 1.234, translator(loc_english));
1051 pt.put(T("french"), 1.234, translator(loc_french));
1054 BOOST_TEST(pt.get<PTREE::data_type>(T("english")) == T("1.234"));
1055 BOOST_TEST(pt.get<PTREE::data_type>(T("french")) == T("1,234"));
1058 catch (boost::property_tree::ptree_error &)
1062 catch (std::runtime_error &e)
1064 std::cerr << "Required locale not supported by the platform. "
1065 "Skipping locale tests (caught std::runtime_error with message " <<
1071 void test_custom_data_type(PTREE *)
1074 typedef std::basic_string<CHTYPE> Str;
1075 typedef PTREE::key_compare Comp;
1077 // Property_tree with boost::any as data type
1078 typedef boost::property_tree::basic_ptree<Str, boost::any, Comp> my_ptree;
1081 // Put/get int value
1082 pt.put(T("int value"), 3);
1083 int int_value = pt.get<int>(T("int value"));
1084 BOOST_TEST(int_value == 3);
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_TEST(string_value == T("foo bar"));
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_TEST(list_value.size() == 5);
1096 BOOST_TEST(list_value.front() == 1);
1097 BOOST_TEST(list_value.back() == 5);
1101 void test_empty_size_max_size(PTREE *)
1105 BOOST_TEST(pt.max_size());
1106 BOOST_TEST(pt.empty());
1107 BOOST_TEST(pt.size() == 0);
1109 pt.put(T("test1"), 1);
1110 BOOST_TEST(pt.max_size());
1111 BOOST_TEST(!pt.empty());
1112 BOOST_TEST(pt.size() == 1);
1114 pt.put(T("test2"), 2);
1115 BOOST_TEST(pt.max_size());
1116 BOOST_TEST(!pt.empty());
1117 BOOST_TEST(pt.size() == 2);
1121 void test_ptree_bad_path(PTREE *)
1128 pt.get<int>(T("non.existent.path"));
1130 catch (boost::property_tree::ptree_bad_path &e)
1132 PTREE::path_type path = e.path<PTREE::path_type>();
1133 std::string what = e.what();
1134 BOOST_TEST(what.find("non.existent.path") != std::string::npos);
1138 BOOST_ERROR("No required exception thrown");
1142 void test_ptree_bad_data(PTREE *)
1146 pt.put_value("non convertible to int");
1150 pt.get_value<int>();
1152 catch (boost::property_tree::ptree_bad_data &e)
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
1158 //BOOST_TEST(what.find("non convertible to int") != std::string::npos);
1162 BOOST_ERROR("No required exception thrown");
1165 void test_serialization(PTREE *)
1168 // Prepare test tree
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')));
1179 // Endforce const for input
1180 const PTREE &pt1 = pt;
1182 // Test text archives
1184 std::stringstream stream;
1185 boost::archive::text_oarchive oa(stream);
1187 boost::archive::text_iarchive ia(stream);
1190 BOOST_TEST(pt1 == pt2);
1193 // Test binary archives
1195 std::stringstream stream;
1196 boost::archive::binary_oarchive oa(stream);
1198 boost::archive::binary_iarchive ia(stream);
1201 BOOST_TEST(pt1 == pt2);
1204 // Test XML archives
1206 std::stringstream stream;
1209 boost::archive::xml_oarchive oa(stream);
1210 oa & boost::serialization::make_nvp("pt", pt1);
1216 boost::archive::xml_iarchive ia(stream);
1217 ia & boost::serialization::make_nvp("pt", pt2);
1220 BOOST_TEST(pt1 == pt2);
1225 void test_bool(PTREE *)
1228 // Prepare test tree
1230 pt.put(T("bool.false.1"), false);
1231 pt.put(T("bool.false.2"), T("0"));
1232 pt.put(T("bool.true.1"), true);
1233 pt.put(T("bool.true.2"), 1);
1234 pt.put(T("bool.invalid.1"), T(""));
1235 pt.put(T("bool.invalid.2"), T("tt"));
1236 pt.put(T("bool.invalid.3"), T("ff"));
1237 pt.put(T("bool.invalid.4"), T("2"));
1238 pt.put(T("bool.invalid.5"), T("-1"));
1241 for (PTREE::iterator it = pt.get_child(T("bool.false")).begin(); it != pt.get_child(T("bool.false")).end(); ++it)
1242 BOOST_TEST(it->second.get_value<bool>() == false);
1245 for (PTREE::iterator it = pt.get_child(T("bool.true")).begin(); it != pt.get_child(T("bool.true")).end(); ++it)
1246 BOOST_TEST(it->second.get_value<bool>() == true);
1249 for (PTREE::iterator it = pt.get_child(T("bool.invalid")).begin(); it != pt.get_child(T("bool.invalid")).end(); ++it)
1251 BOOST_TEST(it->second.get_value<bool>(false) == false);
1252 BOOST_TEST(it->second.get_value<bool>(true) == true);
1257 void test_char(PTREE *)
1259 typedef signed char schar;
1260 typedef unsigned char uchar;
1262 // Prepare test tree
1265 pt.put(T("char"), char('A'));
1267 pt.put(T("signed char"), static_cast<schar>('A'));
1268 pt.put(T("unsigned char"), static_cast<uchar>('A'));
1269 pt.put(T("signed char min"), (std::numeric_limits<schar>::min)());
1270 pt.put(T("signed char max"), (std::numeric_limits<schar>::max)());
1271 pt.put(T("signed char underflow"),
1272 static_cast<int>((std::numeric_limits<schar>::min)()) - 1);
1273 pt.put(T("signed char overflow"),
1274 static_cast<int>((std::numeric_limits<schar>::max)()) + 1);
1275 pt.put(T("unsigned char min"), (std::numeric_limits<uchar>::min)());
1276 pt.put(T("unsigned char max"), (std::numeric_limits<uchar>::max)());
1277 pt.put(T("unsigned char overflow"),
1278 static_cast<unsigned>((std::numeric_limits<uchar>::max)()) + 1);
1280 // Verify normal conversions
1282 BOOST_TEST(pt.get<char>(T("char")) == 'A');
1284 BOOST_TEST(pt.get<schar>(T("signed char")) == static_cast<schar>('A'));
1285 BOOST_TEST(pt.get<uchar>(T("unsigned char")) == static_cast<uchar>('A'));
1287 // Verify that numbers are saved for signed and unsigned char
1288 BOOST_TEST(pt.get<int>(T("signed char")) == int('A'));
1289 BOOST_TEST(pt.get<int>(T("unsigned char")) == int('A'));
1292 BOOST_TEST(pt.get<schar>(T("signed char min")) ==
1293 (std::numeric_limits<schar>::min)());
1294 BOOST_TEST(pt.get<schar>(T("signed char max")) ==
1295 (std::numeric_limits<schar>::max)());
1296 BOOST_TEST(pt.get<uchar>(T("unsigned char min")) ==
1297 (std::numeric_limits<uchar>::min)());
1298 BOOST_TEST(pt.get<uchar>(T("unsigned char max")) ==
1299 (std::numeric_limits<uchar>::max)());
1301 // Check that out-of-range throws.
1303 pt.get<schar>(T("signed char underflow"));
1304 BOOST_ERROR("expected ptree_bad_data, but nothing was thrown");
1305 } catch (boost::property_tree::ptree_bad_data&) {
1307 BOOST_ERROR("expected ptree_bad_data, but something else was thrown");
1310 pt.get<schar>(T("signed char overflow"));
1311 BOOST_ERROR("expected ptree_bad_data, but nothing was thrown");
1312 } catch (boost::property_tree::ptree_bad_data&) {
1314 BOOST_ERROR("expected ptree_bad_data, but something else was thrown");
1317 pt.get<uchar>(T("unsigned char overflow"));
1318 BOOST_ERROR("expected ptree_bad_data, but nothing was thrown");
1319 } catch (boost::property_tree::ptree_bad_data&) {
1321 BOOST_ERROR("expected ptree_bad_data, but something else was thrown");
1325 void test_float(PTREE*)
1327 const double difficult = -183.12345000098765e-10;
1329 pt.put(T("num"), difficult);
1330 double result = pt.get<double>(T("num"));
1332 BOOST_TEST(!(result < difficult || result > difficult));
1335 void test_sort(PTREE *)
1338 pt.put(T("one"), T("v1"));
1339 pt.put(T("two"), T("v2"));
1340 pt.put(T("three"), T("v3"));
1341 pt.put(T("four"), T("v4"));
1345 PTREE::iterator it = pt.begin();
1346 BOOST_TEST(std::distance(it, pt.end()) == 4);
1347 BOOST_TEST(it->first == T("four"));
1348 BOOST_TEST(it->second.data() == T("v4"));
1350 BOOST_TEST(it->first == T("one"));
1351 BOOST_TEST(it->second.data() == T("v1"));
1353 BOOST_TEST(it->first == T("three"));
1354 BOOST_TEST(it->second.data() == T("v3"));
1356 BOOST_TEST(it->first == T("two"));
1357 BOOST_TEST(it->second.data() == T("v2"));
1360 void test_leaks(PTREE *)
1362 //BOOST_TEST(PTREE::debug_get_instances_count() == 0);