test_safe_mode.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /* Boost.MultiIndex test for safe_mode.
  2. *
  3. * Copyright 2003-2018 Joaquin M Lopez Munoz.
  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. * See http://www.boost.org/libs/multi_index for library home page.
  9. */
  10. #include "test_safe_mode.hpp"
  11. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  12. #include "pre_multi_index.hpp"
  13. #include "employee.hpp"
  14. #include "pair_of_ints.hpp"
  15. #include <stdexcept>
  16. #include <boost/detail/lightweight_test.hpp>
  17. using namespace boost::multi_index;
  18. #define TRY_SAFE_MODE \
  19. try{
  20. #define CATCH_SAFE_MODE(err) \
  21. throw std::runtime_error("safe mode violation not detected");\
  22. }catch(const safe_mode_exception& e){\
  23. if(e.error_code!=(err))throw std::runtime_error(\
  24. "safe mode violation not expected");\
  25. }
  26. template<typename T> void prevent_unused_var_warning(const T&){}
  27. template<typename Policy>
  28. static void local_test_safe_mode(
  29. std::forward_iterator_tag
  30. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
  31. {
  32. typedef typename Policy::container container;
  33. typedef typename Policy::index_type index_type;
  34. typedef typename index_type::value_type value_type;
  35. typedef typename index_type::iterator iterator;
  36. container c,c2;
  37. index_type& i=Policy::index_from_container(c);
  38. index_type& i2=Policy::index_from_container(c2);
  39. Policy::insert(i,Policy::some_value());
  40. TRY_SAFE_MODE
  41. iterator it;
  42. iterator it2=i.begin();
  43. it2=it;
  44. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  45. TRY_SAFE_MODE
  46. iterator it;
  47. value_type e=*it;
  48. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  49. TRY_SAFE_MODE
  50. iterator it=i.end();
  51. value_type e=*it;
  52. CATCH_SAFE_MODE(safe_mode::not_dereferenceable_iterator)
  53. TRY_SAFE_MODE
  54. iterator it=i.end();
  55. ++it;
  56. CATCH_SAFE_MODE(safe_mode::not_incrementable_iterator)
  57. TRY_SAFE_MODE
  58. iterator it;
  59. iterator it2;
  60. bool b=(it==it2);
  61. prevent_unused_var_warning(b);
  62. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  63. TRY_SAFE_MODE
  64. iterator it=i.begin();
  65. iterator it2;
  66. bool b=(it==it2);
  67. prevent_unused_var_warning(b);
  68. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  69. TRY_SAFE_MODE
  70. iterator it=i.begin();
  71. iterator it2=i2.begin();
  72. bool b=(it==it2);
  73. prevent_unused_var_warning(b);
  74. CATCH_SAFE_MODE(safe_mode::not_same_owner)
  75. TRY_SAFE_MODE
  76. i.erase(i.end(),i.begin());
  77. CATCH_SAFE_MODE(safe_mode::invalid_range)
  78. TRY_SAFE_MODE
  79. iterator it;
  80. Policy::insert(i,it,Policy::some_value());
  81. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  82. TRY_SAFE_MODE
  83. i.erase(i.end());
  84. CATCH_SAFE_MODE(safe_mode::not_dereferenceable_iterator)
  85. TRY_SAFE_MODE
  86. iterator it=i.begin();
  87. Policy::insert(i2,it,Policy::some_value());
  88. CATCH_SAFE_MODE(safe_mode::not_owner)
  89. TRY_SAFE_MODE
  90. iterator it=i.begin();
  91. iterator it2=i2.end();
  92. i2.erase(it,it2);
  93. CATCH_SAFE_MODE(safe_mode::not_owner)
  94. TRY_SAFE_MODE
  95. iterator it=Policy::insert(i,Policy::another_value());
  96. i.erase(it);
  97. i.erase(it);
  98. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  99. TRY_SAFE_MODE
  100. container c3(c);
  101. index_type& i3=Policy::index_from_container(c3);
  102. iterator it=Policy::insert(i3,Policy::another_value());
  103. i3.clear();
  104. i3.erase(it);
  105. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  106. TRY_SAFE_MODE
  107. iterator it;
  108. {
  109. container c3;
  110. index_type& i3=Policy::index_from_container(c3);
  111. it=i3.end();
  112. }
  113. iterator it2;
  114. it2=it;
  115. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  116. TRY_SAFE_MODE
  117. iterator it;
  118. {
  119. container c3;
  120. index_type& i3=Policy::index_from_container(c3);
  121. it=Policy::insert(i3,Policy::some_value());
  122. }
  123. value_type e=*it;
  124. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  125. TRY_SAFE_MODE
  126. iterator it;
  127. {
  128. container c3;
  129. index_type& i3=Policy::index_from_container(c3);
  130. it=Policy::insert(i3,Policy::some_value());
  131. }
  132. iterator it2;
  133. it2=it;
  134. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  135. TRY_SAFE_MODE
  136. container c3(c);
  137. container c4;
  138. index_type& i3=Policy::index_from_container(c3);
  139. index_type& i4=Policy::index_from_container(c4);
  140. iterator it=i3.begin();
  141. i3.swap(i4);
  142. i3.erase(it);
  143. CATCH_SAFE_MODE(safe_mode::not_owner)
  144. /* this, unlike the previous case, is indeed correct, test safe mode
  145. * gets it right
  146. */
  147. {
  148. container c3(c);
  149. container c4;
  150. index_type& i3=Policy::index_from_container(c3);
  151. index_type& i4=Policy::index_from_container(c4);
  152. iterator it=i3.begin();
  153. i3.swap(i4);
  154. i4.erase(it);
  155. }
  156. TRY_SAFE_MODE
  157. iterator it=i.end();
  158. typename container::iterator it2=project<0>(c2,it);
  159. CATCH_SAFE_MODE(safe_mode::not_owner)
  160. TRY_SAFE_MODE
  161. iterator it=Policy::insert(i,Policy::another_value());
  162. typename container::iterator it2=project<0>(c,it);
  163. i.erase(it);
  164. value_type e=*it2;
  165. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  166. /* testcase for bug reported at
  167. * http://lists.boost.org/boost-users/2006/02/17230.php
  168. */
  169. {
  170. container c3(c);
  171. index_type& i3=Policy::index_from_container(c3);
  172. iterator it=i3.end();
  173. i3.clear();
  174. it=i3.end();
  175. }
  176. /* testcase for doppelganger bug of that discovered for STLport at
  177. * http://lists.boost.org/Archives/boost/2006/04/102740.php
  178. */
  179. {
  180. container c3;
  181. index_type& i3=Policy::index_from_container(c3);
  182. iterator it=i3.end();
  183. i3.clear();
  184. iterator it2=it;
  185. BOOST_TEST(it2==i3.end());
  186. }
  187. }
  188. template<typename Policy>
  189. static void local_test_safe_mode(
  190. std::bidirectional_iterator_tag
  191. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
  192. {
  193. ::local_test_safe_mode<Policy>(std::forward_iterator_tag());
  194. typedef typename Policy::container container;
  195. typedef typename Policy::index_type index_type;
  196. typedef typename index_type::iterator iterator;
  197. container c;
  198. index_type& i=Policy::index_from_container(c);
  199. Policy::insert(i,Policy::some_value());
  200. TRY_SAFE_MODE
  201. iterator it=i.begin();
  202. --it;
  203. CATCH_SAFE_MODE(safe_mode::not_decrementable_iterator)
  204. }
  205. template<typename Policy>
  206. static void local_test_safe_mode(
  207. std::random_access_iterator_tag
  208. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
  209. {
  210. ::local_test_safe_mode<Policy>(std::bidirectional_iterator_tag());
  211. typedef typename Policy::container container;
  212. typedef typename Policy::index_type index_type;
  213. typedef typename index_type::iterator iterator;
  214. container c;
  215. index_type& i=Policy::index_from_container(c);
  216. Policy::insert(i,Policy::some_value());
  217. TRY_SAFE_MODE
  218. iterator it=i.begin();
  219. it+=2;
  220. CATCH_SAFE_MODE(safe_mode::out_of_bounds)
  221. TRY_SAFE_MODE
  222. iterator it=i.begin();
  223. it-=1;
  224. CATCH_SAFE_MODE(safe_mode::out_of_bounds)
  225. }
  226. template<typename Policy>
  227. static void local_test_safe_mode()
  228. {
  229. typedef typename Policy::index_type::iterator::iterator_category category;
  230. ::local_test_safe_mode<Policy>(category());
  231. }
  232. template<typename Policy>
  233. static void local_test_safe_mode_with_rearrange()
  234. {
  235. ::local_test_safe_mode<Policy>();
  236. typedef typename Policy::container container;
  237. typedef typename Policy::index_type index_type;
  238. typedef typename index_type::iterator iterator;
  239. container c;
  240. index_type& i=Policy::index_from_container(c);
  241. Policy::insert(i,Policy::some_value());
  242. TRY_SAFE_MODE
  243. iterator it;
  244. i.splice(it,i,i.begin(),i.end());
  245. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  246. TRY_SAFE_MODE
  247. container c2(c);
  248. index_type& i2=Policy::index_from_container(c2);
  249. iterator it2=i2.begin();
  250. iterator it=i.begin();
  251. i.splice(it2,i2,it);
  252. CATCH_SAFE_MODE(safe_mode::not_owner)
  253. TRY_SAFE_MODE
  254. i.splice(i.begin(),i,i.begin(),i.end());
  255. CATCH_SAFE_MODE(safe_mode::inside_range)
  256. TRY_SAFE_MODE
  257. i.splice(i.begin(),i,i.end(),i.begin());
  258. CATCH_SAFE_MODE(safe_mode::invalid_range)
  259. TRY_SAFE_MODE
  260. i.splice(i.begin(),i);
  261. CATCH_SAFE_MODE(safe_mode::same_container)
  262. TRY_SAFE_MODE
  263. iterator it;
  264. i.relocate(it,i.begin(),i.end());
  265. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  266. TRY_SAFE_MODE
  267. i.relocate(i.begin(),i.begin(),i.end());
  268. CATCH_SAFE_MODE(safe_mode::inside_range)
  269. TRY_SAFE_MODE
  270. i.relocate(i.begin(),i.end(),i.begin());
  271. CATCH_SAFE_MODE(safe_mode::invalid_range)
  272. }
  273. template<typename MultiIndexContainer,int N>
  274. struct index_policy_base
  275. {
  276. typedef MultiIndexContainer container;
  277. typedef typename nth_index<container,N>::type index_type;
  278. static index_type& index_from_container(container& c){return get<N>(c);}
  279. };
  280. template<typename MultiIndexContainer,int N>
  281. struct key_based_index_policy_base:
  282. index_policy_base<MultiIndexContainer,N>
  283. {
  284. typedef index_policy_base<MultiIndexContainer,N> super;
  285. typedef typename super::container container;
  286. typedef typename super::index_type index_type;
  287. typedef typename index_type::value_type value_type;
  288. typedef typename index_type::iterator iterator;
  289. static iterator insert(index_type& i,const value_type& v)
  290. {
  291. return i.insert(v).first;
  292. }
  293. static iterator insert(index_type& i,iterator it,const value_type& v)
  294. {
  295. return i.insert(it,v);
  296. }
  297. };
  298. template<typename MultiIndexContainer,int N>
  299. struct non_key_based_index_policy_base:
  300. index_policy_base<MultiIndexContainer,N>
  301. {
  302. typedef index_policy_base<MultiIndexContainer,N> super;
  303. typedef typename super::container container;
  304. typedef typename super::index_type index_type;
  305. typedef typename index_type::value_type value_type;
  306. typedef typename index_type::iterator iterator;
  307. static iterator insert(index_type& i,const value_type& v)
  308. {
  309. return i.push_back(v).first;
  310. }
  311. static iterator insert(index_type& i,iterator it,const value_type& v)
  312. {
  313. return i.insert(it,v).first;
  314. }
  315. };
  316. struct employee_set_policy_base
  317. {
  318. static employee some_value(){return employee(0,"Joe",31,1123);}
  319. static employee another_value(){return employee(1,"Robert",27,5601);}
  320. };
  321. struct employee_set_policy:
  322. employee_set_policy_base,
  323. key_based_index_policy_base<employee_set,0>
  324. {};
  325. struct employee_set_by_name_policy:
  326. employee_set_policy_base,
  327. key_based_index_policy_base<employee_set,1>
  328. {};
  329. struct employee_set_as_inserted_policy:
  330. employee_set_policy_base,
  331. non_key_based_index_policy_base<employee_set,3>
  332. {};
  333. struct employee_set_randomly_policy:
  334. employee_set_policy_base,
  335. non_key_based_index_policy_base<employee_set,5>
  336. {};
  337. template<typename IntegralBimap>
  338. static void test_integral_bimap()
  339. {
  340. typedef typename IntegralBimap::value_type value_type;
  341. typedef typename IntegralBimap::iterator iterator;
  342. TRY_SAFE_MODE
  343. IntegralBimap bm;
  344. iterator it=bm.insert(value_type(0,0)).first;
  345. bm.insert(value_type(1,1));
  346. bm.modify(it,increment_first);
  347. value_type v=*it;
  348. prevent_unused_var_warning(v);
  349. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  350. TRY_SAFE_MODE
  351. IntegralBimap bm;
  352. iterator it=bm.insert(value_type(0,0)).first;
  353. bm.insert(value_type(1,1));
  354. bm.modify(it,increment_second);
  355. pair_of_ints v=*it;
  356. prevent_unused_var_warning(v);
  357. CATCH_SAFE_MODE(safe_mode::invalid_iterator)
  358. }
  359. void test_safe_mode()
  360. {
  361. local_test_safe_mode<employee_set_policy>();
  362. local_test_safe_mode<employee_set_by_name_policy>();
  363. local_test_safe_mode_with_rearrange<employee_set_as_inserted_policy>();
  364. local_test_safe_mode_with_rearrange<employee_set_randomly_policy>();
  365. typedef multi_index_container<
  366. pair_of_ints,
  367. indexed_by<
  368. ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
  369. ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
  370. > bimap0_type;
  371. test_integral_bimap<bimap0_type>();
  372. typedef multi_index_container<
  373. pair_of_ints,
  374. indexed_by<
  375. ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
  376. hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
  377. > bimap1_type;
  378. test_integral_bimap<bimap1_type>();
  379. typedef multi_index_container<
  380. pair_of_ints,
  381. indexed_by<
  382. hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
  383. ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
  384. > bimap2_type;
  385. test_integral_bimap<bimap2_type>();
  386. typedef multi_index_container<
  387. pair_of_ints,
  388. indexed_by<
  389. hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
  390. hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
  391. > bimap3_type;
  392. test_integral_bimap<bimap3_type>();
  393. }