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