test_property_tree.hpp 41 KB

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