• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Boost.MultiIndex test for safe_mode.
2  *
3  * Copyright 2003-2020 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 
11 #include "test_safe_mode.hpp"
12 
13 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
14 #include <boost/move/core.hpp>
15 #include <boost/move/utility_core.hpp>
16 #include "pre_multi_index.hpp"
17 #include "employee.hpp"
18 #include "pair_of_ints.hpp"
19 #include <stdexcept>
20 #include <boost/detail/lightweight_test.hpp>
21 
22 using namespace boost::multi_index;
23 
24 #define TRY_SAFE_MODE \
25 try{
26 
27 #define CATCH_SAFE_MODE(err) \
28   throw std::runtime_error("safe mode violation not detected");\
29 }catch(const safe_mode_exception& e){\
30   if(e.error_code!=(err))throw std::runtime_error(\
31     "safe mode violation not expected");\
32 }
33 
prevent_unused_var_warning(const T &)34 template<typename T> void prevent_unused_var_warning(const T&){}
35 
36 template<typename Policy>
local_test_safe_mode(std::forward_iterator_tag BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE (Policy))37 static void local_test_safe_mode(
38   std::forward_iterator_tag
39   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
40 {
41   typedef typename Policy::container      container;
42   typedef typename Policy::allocator_type allocator_type;
43   typedef typename Policy::index_type     index_type;
44   typedef typename index_type::value_type value_type;
45   typedef typename index_type::iterator   iterator;
46   typedef typename index_type::node_type  node_type;
47 
48   container   c,c2;
49   index_type& i=Policy::index_from_container(c);
50   index_type& i2=Policy::index_from_container(c2);
51   Policy::insert(i,Policy::some_value());
52 
53   TRY_SAFE_MODE
54     iterator it;
55     iterator it2=i.begin();
56     it2=it;
57   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
58 
59   TRY_SAFE_MODE
60     iterator it;
61     value_type e=*it;
62   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
63 
64   TRY_SAFE_MODE
65     iterator it=i.end();
66     value_type e=*it;
67   CATCH_SAFE_MODE(safe_mode::not_dereferenceable_iterator)
68 
69   TRY_SAFE_MODE
70     iterator it=i.end();
71     ++it;
72   CATCH_SAFE_MODE(safe_mode::not_incrementable_iterator)
73 
74   TRY_SAFE_MODE
75     iterator it;
76     iterator it2;
77     bool b=(it==it2);
78     prevent_unused_var_warning(b);
79   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
80 
81   TRY_SAFE_MODE
82     iterator it=i.begin();
83     iterator it2;
84     bool b=(it==it2);
85     prevent_unused_var_warning(b);
86   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
87 
88   TRY_SAFE_MODE
89     iterator it=i.begin();
90     iterator it2=i2.begin();
91     bool b=(it==it2);
92     prevent_unused_var_warning(b);
93   CATCH_SAFE_MODE(safe_mode::not_same_owner)
94 
95   TRY_SAFE_MODE
96     i.erase(i.end(),i.begin());
97   CATCH_SAFE_MODE(safe_mode::invalid_range)
98 
99   TRY_SAFE_MODE
100     iterator it;
101     Policy::insert(i,it,Policy::some_value());
102   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
103 
104   TRY_SAFE_MODE
105     i.erase(i.end());
106   CATCH_SAFE_MODE(safe_mode::not_dereferenceable_iterator)
107 
108   TRY_SAFE_MODE
109     iterator it=i.begin();
110     Policy::insert(i2,it,Policy::some_value());
111   CATCH_SAFE_MODE(safe_mode::not_owner)
112 
113   TRY_SAFE_MODE
114     iterator it=i.begin();
115     iterator it2=i2.end();
116     i2.erase(it,it2);
117   CATCH_SAFE_MODE(safe_mode::not_owner)
118 
119   TRY_SAFE_MODE
120     iterator it=Policy::insert(i,Policy::another_value());
121     i.erase(it);
122     i.erase(it);
123   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
124 
125   TRY_SAFE_MODE
126     container   c3(c);
127     index_type& i3=Policy::index_from_container(c3);
128     iterator it=Policy::insert(i3,Policy::another_value());
129     i3.clear();
130     i3.erase(it);
131   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
132 
133   TRY_SAFE_MODE
134     iterator it;
135     {
136       container   c3;
137       index_type& i3=Policy::index_from_container(c3);
138       it=i3.end();
139     }
140     iterator it2;
141     it2=it;
142   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
143 
144   TRY_SAFE_MODE
145     iterator it;
146     {
147       container   c3;
148       index_type& i3=Policy::index_from_container(c3);
149       it=Policy::insert(i3,Policy::some_value());
150     }
151     value_type e=*it;
152   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
153 
154   TRY_SAFE_MODE
155     iterator it;
156     {
157       container   c3;
158       index_type& i3=Policy::index_from_container(c3);
159       it=Policy::insert(i3,Policy::some_value());
160     }
161     iterator it2;
162     it2=it;
163   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
164 
165   TRY_SAFE_MODE
166     container   c3(c);
167     container   c4;
168     index_type& i3=Policy::index_from_container(c3);
169     index_type& i4=Policy::index_from_container(c4);
170     iterator  it=i3.begin();
171     i3.swap(i4);
172     i3.erase(it);
173   CATCH_SAFE_MODE(safe_mode::not_owner)
174 
175   /* this, unlike the previous case, is indeed correct, test safe mode
176    * gets it right
177    */
178   {
179     container   c3(c);
180     container   c4;
181     index_type& i3=Policy::index_from_container(c3);
182     index_type& i4=Policy::index_from_container(c4);
183     iterator  it=i3.begin();
184     i3.swap(i4);
185     i4.erase(it);
186   }
187 
188   TRY_SAFE_MODE
189     iterator it=i.end();
190     typename container::iterator it2=project<0>(c2,it);
191   CATCH_SAFE_MODE(safe_mode::not_owner)
192 
193   TRY_SAFE_MODE
194     iterator it=Policy::insert(i,Policy::another_value());
195     typename container::iterator it2=project<0>(c,it);
196     i.erase(it);
197     value_type e=*it2;
198   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
199 
200   TRY_SAFE_MODE
201     iterator   it=Policy::insert(i,Policy::another_value());
202     node_type  nh=i.extract(it);
203     value_type e=*it;
204     (void)nh;
205   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
206 
207   TRY_SAFE_MODE
208     iterator    it=Policy::insert(i,Policy::another_value());
209     node_type   nh=i.extract(it);
210     container   c3(c2,allocator_type(-1));
211     index_type& i3=Policy::index_from_container(c3);
212     Policy::insert(i3,boost::move(nh));
213   CATCH_SAFE_MODE(safe_mode::unequal_allocators)
214 
215   /* testcase for bug reported at
216    * http://lists.boost.org/boost-users/2006/02/17230.php
217    */
218   {
219     container c3(c);
220     index_type& i3=Policy::index_from_container(c3);
221     iterator it=i3.end();
222     i3.clear();
223     it=i3.end();
224   }
225 
226   /* testcase for doppelganger bug of that discovered for STLport at
227    * http://lists.boost.org/Archives/boost/2006/04/102740.php
228    */
229   {
230     container c3;
231     index_type& i3=Policy::index_from_container(c3);
232     iterator it=i3.end();
233     i3.clear();
234     iterator it2=it;
235     BOOST_TEST(it2==i3.end());
236   }
237 }
238 
239 template<typename Policy>
local_test_safe_mode(std::bidirectional_iterator_tag BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE (Policy))240 static void local_test_safe_mode(
241   std::bidirectional_iterator_tag
242   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
243 {
244   ::local_test_safe_mode<Policy>(std::forward_iterator_tag());
245 
246   typedef typename Policy::container    container;
247   typedef typename Policy::index_type   index_type;
248   typedef typename index_type::iterator iterator;
249 
250   container   c;
251   index_type& i=Policy::index_from_container(c);
252   Policy::insert(i,Policy::some_value());
253 
254   TRY_SAFE_MODE
255     iterator it=i.begin();
256     --it;
257   CATCH_SAFE_MODE(safe_mode::not_decrementable_iterator)
258 }
259 
260 template<typename Policy>
local_test_safe_mode(std::random_access_iterator_tag BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE (Policy))261 static void local_test_safe_mode(
262   std::random_access_iterator_tag
263   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
264 {
265   ::local_test_safe_mode<Policy>(std::bidirectional_iterator_tag());
266 
267   typedef typename Policy::container    container;
268   typedef typename Policy::index_type   index_type;
269   typedef typename index_type::iterator iterator;
270 
271   container   c;
272   index_type& i=Policy::index_from_container(c);
273   Policy::insert(i,Policy::some_value());
274 
275   TRY_SAFE_MODE
276     iterator it=i.begin();
277     it+=2;
278   CATCH_SAFE_MODE(safe_mode::out_of_bounds)
279 
280   TRY_SAFE_MODE
281     iterator it=i.begin();
282     it-=1;
283   CATCH_SAFE_MODE(safe_mode::out_of_bounds)
284 }
285 
286 template<typename Policy>
local_test_safe_mode()287 static void local_test_safe_mode()
288 {
289   typedef typename Policy::index_type::iterator::iterator_category category;
290   ::local_test_safe_mode<Policy>(category());
291 }
292 
293 template<typename Policy>
local_test_safe_mode_with_rearrange()294 static void local_test_safe_mode_with_rearrange()
295 {
296   ::local_test_safe_mode<Policy>();
297 
298   typedef typename Policy::container    container;
299   typedef typename Policy::index_type   index_type;
300   typedef typename index_type::iterator iterator;
301 
302   container   c;
303   index_type& i=Policy::index_from_container(c);
304   Policy::insert(i,Policy::some_value());
305 
306   TRY_SAFE_MODE
307     iterator it;
308     i.splice(it,i,i.begin(),i.end());
309   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
310 
311   TRY_SAFE_MODE
312     container   c2(c);
313     index_type& i2=Policy::index_from_container(c2);
314     iterator    it2=i2.begin();
315     iterator    it=i.begin();
316     i.splice(it2,i2,it);
317   CATCH_SAFE_MODE(safe_mode::not_owner)
318 
319   TRY_SAFE_MODE
320     i.splice(i.begin(),i,i.begin(),i.end());
321   CATCH_SAFE_MODE(safe_mode::inside_range)
322 
323   TRY_SAFE_MODE
324     i.splice(i.begin(),i,i.end(),i.begin());
325   CATCH_SAFE_MODE(safe_mode::invalid_range)
326 
327   TRY_SAFE_MODE
328     i.splice(i.begin(),i);
329   CATCH_SAFE_MODE(safe_mode::same_container)
330 
331   TRY_SAFE_MODE
332     iterator it;
333     i.relocate(it,i.begin(),i.end());
334   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
335 
336   TRY_SAFE_MODE
337     i.relocate(i.begin(),i.begin(),i.end());
338   CATCH_SAFE_MODE(safe_mode::inside_range)
339 
340   TRY_SAFE_MODE
341     i.relocate(i.begin(),i.end(),i.begin());
342   CATCH_SAFE_MODE(safe_mode::invalid_range)
343 }
344 
345 template<typename MultiIndexContainer,int N>
346 struct index_policy_base
347 {
348   typedef MultiIndexContainer                   container;
349   typedef typename container::allocator_type    allocator_type;
350   typedef typename nth_index<container,N>::type index_type;
351 
index_from_containerindex_policy_base352   static index_type& index_from_container(container& c){return get<N>(c);}
353 };
354 
355 template<typename MultiIndexContainer,int N>
356 struct key_based_index_policy_base:
357   index_policy_base<MultiIndexContainer,N>
358 {
359   typedef index_policy_base<MultiIndexContainer,N> super;
360 
361   typedef typename super::container       container;
362   typedef typename super::index_type      index_type;
363   typedef typename index_type::value_type value_type;
364   typedef typename index_type::iterator   iterator;
365   typedef typename index_type::node_type  node_type;
366 
insertkey_based_index_policy_base367   static iterator insert(index_type& i,const value_type& v)
368   {
369     return i.insert(v).first;
370   }
371 
insertkey_based_index_policy_base372   static iterator insert(index_type& i,iterator it,const value_type& v)
373   {
374     return i.insert(it,v);
375   }
376 
insertkey_based_index_policy_base377   static void insert(index_type& i,BOOST_RV_REF(node_type) nh)
378   {
379     i.insert(boost::move(nh));
380   }
381 };
382 
383 template<typename MultiIndexContainer,int N>
384 struct non_key_based_index_policy_base:
385   index_policy_base<MultiIndexContainer,N>
386 {
387   typedef index_policy_base<MultiIndexContainer,N> super;
388 
389   typedef typename super::container       container;
390   typedef typename super::index_type      index_type;
391   typedef typename index_type::value_type value_type;
392   typedef typename index_type::iterator   iterator;
393   typedef typename index_type::node_type  node_type;
394 
insertnon_key_based_index_policy_base395   static iterator insert(index_type& i,const value_type& v)
396   {
397     return i.push_back(v).first;
398   }
399 
insertnon_key_based_index_policy_base400   static iterator insert(index_type& i,iterator it,const value_type& v)
401   {
402     return i.insert(it,v).first;
403   }
404 
insertnon_key_based_index_policy_base405   static void insert(index_type& i,BOOST_RV_REF(node_type) nh)
406   {
407     i.insert(i.end(),boost::move(nh));
408   }
409 };
410 
411 struct employee_set_policy_base
412 {
some_valueemployee_set_policy_base413   static employee    some_value(){return employee(0,"Joe",31,1123);}
another_valueemployee_set_policy_base414   static employee    another_value(){return employee(1,"Robert",27,5601);}
415 };
416 
417 struct employee_set_policy:
418   employee_set_policy_base,
419   key_based_index_policy_base<employee_set,0>
420 {};
421 
422 struct employee_set_by_name_policy:
423   employee_set_policy_base,
424   key_based_index_policy_base<employee_set,1>
425 {};
426 
427 struct employee_set_as_inserted_policy:
428   employee_set_policy_base,
429   non_key_based_index_policy_base<employee_set,3>
430 {};
431 
432 struct employee_set_randomly_policy:
433   employee_set_policy_base,
434   non_key_based_index_policy_base<employee_set,5>
435 {};
436 
437 template<typename IntegralBimap>
test_integral_bimap()438 static void test_integral_bimap()
439 {
440   typedef typename IntegralBimap::value_type value_type;
441   typedef typename IntegralBimap::iterator   iterator;
442 
443   TRY_SAFE_MODE
444     IntegralBimap bm;
445     iterator it=bm.insert(value_type(0,0)).first;
446     bm.insert(value_type(1,1));
447     bm.modify(it,increment_first);
448     value_type v=*it;
449     prevent_unused_var_warning(v);
450   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
451 
452   TRY_SAFE_MODE
453     IntegralBimap bm;
454     iterator it=bm.insert(value_type(0,0)).first;
455     bm.insert(value_type(1,1));
456     bm.modify(it,increment_second);
457     pair_of_ints v=*it;
458     prevent_unused_var_warning(v);
459   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
460 }
461 
test_safe_mode()462 void test_safe_mode()
463 {
464   local_test_safe_mode<employee_set_policy>();
465   local_test_safe_mode<employee_set_by_name_policy>();
466   local_test_safe_mode_with_rearrange<employee_set_as_inserted_policy>();
467   local_test_safe_mode_with_rearrange<employee_set_randomly_policy>();
468 
469   typedef multi_index_container<
470     pair_of_ints,
471     indexed_by<
472       ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
473       ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
474   > bimap0_type;
475 
476   test_integral_bimap<bimap0_type>();
477 
478   typedef multi_index_container<
479     pair_of_ints,
480     indexed_by<
481       ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
482       hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
483   > bimap1_type;
484 
485   test_integral_bimap<bimap1_type>();
486 
487   typedef multi_index_container<
488     pair_of_ints,
489     indexed_by<
490       hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
491       ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
492   > bimap2_type;
493 
494   test_integral_bimap<bimap2_type>();
495 
496   typedef multi_index_container<
497     pair_of_ints,
498     indexed_by<
499       hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
500       hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
501   > bimap3_type;
502 
503   test_integral_bimap<bimap3_type>();
504 }
505