1/* Boost.MultiIndex test for safe_mode.
2 *
3 * Copyright 2003-2021 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
22using namespace boost::multi_index;
23
24#define TRY_SAFE_MODE \
25try{
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
34template<typename T> void prevent_unused_var_warning(const T&){}
35
36template<typename Policy>
37static 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
239template<typename Policy>
240static 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
260template<typename Policy>
261static 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
286template<typename Policy>
287static 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
293template<typename Policy>
294static 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::inside_range)
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
345template<typename MultiIndexContainer,int N>
346struct 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
352 static index_type& index_from_container(container& c){return get<N>(c);}
353};
354
355template<typename MultiIndexContainer,int N>
356struct 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
367 static iterator insert(index_type& i,const value_type& v)
368 {
369 return i.insert(v).first;
370 }
371
372 static iterator insert(index_type& i,iterator it,const value_type& v)
373 {
374 return i.insert(it,v);
375 }
376
377 static void insert(index_type& i,BOOST_RV_REF(node_type) nh)
378 {
379 i.insert(boost::move(nh));
380 }
381};
382
383template<typename MultiIndexContainer,int N>
384struct 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
395 static iterator insert(index_type& i,const value_type& v)
396 {
397 return i.push_back(v).first;
398 }
399
400 static iterator insert(index_type& i,iterator it,const value_type& v)
401 {
402 return i.insert(it,v).first;
403 }
404
405 static void insert(index_type& i,BOOST_RV_REF(node_type) nh)
406 {
407 i.insert(i.end(),boost::move(nh));
408 }
409};
410
411struct employee_set_policy_base
412{
413 static employee some_value(){return employee(0,"Joe",31,1123);}
414 static employee another_value(){return employee(1,"Robert",27,5601);}
415};
416
417struct employee_set_policy:
418 employee_set_policy_base,
419 key_based_index_policy_base<employee_set,0>
420{};
421
422struct employee_set_by_name_policy:
423 employee_set_policy_base,
424 key_based_index_policy_base<employee_set,1>
425{};
426
427struct employee_set_as_inserted_policy:
428 employee_set_policy_base,
429 non_key_based_index_policy_base<employee_set,3>
430{};
431
432struct employee_set_randomly_policy:
433 employee_set_policy_base,
434 non_key_based_index_policy_base<employee_set,5>
435{};
436
437template<typename IntegralBimap>
438static 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
462void 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

source code of boost/libs/multi_index/test/test_safe_mode.cpp