3 // Copyright (C) 2009, 2010 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the terms
7 // of the GNU General Public License as published by the Free Software
8 // Foundation; either version 3, or (at your option) any later
11 // This library is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING3. If not see
18 // <http://www.gnu.org/licenses/>.
20 #ifndef _GLIBCXX_EXCEPTION_SAFETY_H
21 #define _GLIBCXX_EXCEPTION_SAFETY_H
23 #include <testsuite_container_traits.h>
24 #include <ext/throw_allocator.h>
26 // Container requirement testing.
29 // Base class for exception testing, contains utilities.
32 typedef std::size_t size_type
;
33 typedef std::uniform_int_distribution
<size_type
> distribution_type
;
34 typedef std::mt19937 engine_type
;
36 // Return randomly generated integer on range [0, __max_size].
38 generate(size_type __max_size
)
40 // Make the generator static...
41 const engine_type engine
;
42 const distribution_type distribution
;
43 static auto generator
= std::bind(distribution
, engine
,
44 std::placeholders::_1
);
46 // ... but set the range for this particular invocation here.
47 const typename
distribution_type::param_type
p(0, __max_size
);
48 size_type random
= generator(p
);
49 if (random
< distribution
.min() || random
> distribution
.max())
51 std::string
__s("setup_base::generate");
53 __s
+= "random number generated is: ";
55 __builtin_sprintf(buf
, "%lu", (unsigned long)random
);
58 __builtin_sprintf(buf
, "%lu", (unsigned long)distribution
.min());
61 __builtin_sprintf(buf
, "%lu", (unsigned long)distribution
.max());
64 std::__throw_out_of_range(__s
.c_str());
69 // Given an instantiating type, return a unique value.
70 template<typename _Tp
>
71 struct generate_unique
73 typedef _Tp value_type
;
77 static value_type __ret
;
83 // Partial specialization for pair.
84 template<typename _Tp1
, typename _Tp2
>
85 struct generate_unique
<std::pair
<const _Tp1
, _Tp2
>>
87 typedef _Tp1 first_type
;
88 typedef _Tp2 second_type
;
89 typedef std::pair
<const _Tp1
, _Tp2
> pair_type
;
93 static first_type _S_1
;
94 static second_type _S_2
;
97 return pair_type(_S_1
, _S_2
);
101 // Partial specialization for throw_value
102 template<typename _Cond
>
103 struct generate_unique
<__gnu_cxx::throw_value_base
<_Cond
>>
105 typedef __gnu_cxx::throw_value_base
<_Cond
> value_type
;
107 operator value_type()
109 static size_t _S_i(0);
110 return value_type(_S_i
++);
115 // Construct container of size n directly. _Tp == container type.
116 template<typename _Tp
>
117 struct make_container_base
121 make_container_base() = default;
122 make_container_base(const size_type n
): _M_container(n
) { }
124 operator _Tp
&() { return _M_container
; }
127 // Construct container of size n, via multiple insertions. For
128 // associated and unordered types, unique value_type elements are
130 template<typename _Tp
, bool = traits
<_Tp
>::is_mapped::value
>
131 struct make_insert_container_base
132 : public make_container_base
<_Tp
>
134 using make_container_base
<_Tp
>::_M_container
;
135 typedef typename
_Tp::value_type value_type
;
137 make_insert_container_base(const size_type n
)
139 for (size_type i
= 0; i
< n
; ++i
)
141 value_type v
= generate_unique
<value_type
>();
142 _M_container
.insert(v
);
144 assert(_M_container
.size() == n
);
148 template<typename _Tp
>
149 struct make_insert_container_base
<_Tp
, false>
150 : public make_container_base
<_Tp
>
152 using make_container_base
<_Tp
>::_M_container
;
153 typedef typename
_Tp::value_type value_type
;
155 make_insert_container_base(const size_type n
)
157 for (size_type i
= 0; i
< n
; ++i
)
159 value_type v
= generate_unique
<value_type
>();
160 _M_container
.insert(_M_container
.end(), v
);
162 assert(_M_container
.size() == n
);
166 template<typename _Tp
, bool = traits
<_Tp
>::has_size_type_constructor::value
>
167 struct make_container_n
;
169 // Specialization for non-associative types that have a constructor with
171 template<typename _Tp
>
172 struct make_container_n
<_Tp
, true>
173 : public make_container_base
<_Tp
>
175 make_container_n(const size_type n
) : make_container_base
<_Tp
>(n
) { }
178 template<typename _Tp
>
179 struct make_container_n
<_Tp
, false>
180 : public make_insert_container_base
<_Tp
>
182 make_container_n(const size_type n
)
183 : make_insert_container_base
<_Tp
>(n
) { }
187 // Randomly size and populate a given container reference.
188 // NB: Responsibility for turning off exceptions lies with caller.
189 template<typename _Tp
, bool = traits
<_Tp
>::is_allocator_aware::value
>
192 typedef _Tp container_type
;
193 typedef typename
container_type::allocator_type allocator_type
;
194 typedef typename
container_type::value_type value_type
;
196 populate(_Tp
& __container
)
198 const allocator_type a
= __container
.get_allocator();
200 // Size test container.
201 const size_type max_elements
= 100;
202 size_type n
= generate(max_elements
);
204 // Construct new container.
205 make_container_n
<container_type
> made(n
);
206 container_type
& tmp
= made
;
207 std::swap(tmp
, __container
);
211 // Partial specialization, empty.
212 template<typename _Tp
>
213 struct populate
<_Tp
, false>
218 // Compare two containers for equivalence.
219 // Right now, that means size.
220 // Returns true if equal, throws if not.
221 template<typename _Tp
>
223 compare(const _Tp
& __control
, const _Tp
& __test
)
225 // Make sure test container is in a consistent state, as
226 // compared to the control container.
227 // NB: Should be equivalent to __test != __control, but
228 // computed without equivalence operators
229 const size_type szt
= std::distance(__test
.begin(), __test
.end());
230 const size_type szc
= std::distance(__control
.begin(),
232 bool __equal_size
= szt
== szc
;
234 // Should test iterator validity before and after exception.
235 bool __equal_it
= std::equal(__test
.begin(), __test
.end(),
238 if (!__equal_size
|| !__equal_it
)
239 throw std::logic_error("setup_base::compare containers not equal");
246 // Containing structure holding functors.
247 struct functor_base
: public setup_base
249 // Abstract the erase function.
250 template<typename _Tp
>
253 typedef typename
_Tp::iterator iterator
;
255 iterator (_Tp::* _F_erase_point
)(iterator
);
256 iterator (_Tp::* _F_erase_range
)(iterator
, iterator
);
259 : _F_erase_point(&_Tp::erase
), _F_erase_range(&_Tp::erase
) { }
262 // Specialization, as forward_list has erase_after.
263 template<typename _Tp1
, typename _Tp2
>
264 struct erase_base
<std::forward_list
<_Tp1
, _Tp2
>>
266 typedef std::forward_list
<_Tp1
, _Tp2
> container_type
;
267 typedef typename
container_type::iterator iterator
;
268 typedef typename
container_type::const_iterator const_iterator
;
270 iterator (container_type::* _F_erase_point
)(const_iterator
);
271 iterator (container_type::* _F_erase_range
)(const_iterator
,
275 : _F_erase_point(&container_type::erase_after
),
276 _F_erase_range(&container_type::erase_after
) { }
279 // Specializations for the unordered containers.
280 template<typename _Tp1
, typename _Tp2
, typename _Tp3
,
281 typename _Tp4
, typename _Tp5
>
282 struct erase_base
<std::unordered_map
<_Tp1
, _Tp2
, _Tp3
, _Tp4
, _Tp5
>>
284 typedef std::unordered_map
<_Tp1
, _Tp2
, _Tp3
, _Tp4
, _Tp5
>
286 typedef typename
container_type::iterator iterator
;
287 typedef typename
container_type::const_iterator const_iterator
;
289 iterator (container_type::* _F_erase_point
)(const_iterator
);
290 iterator (container_type::* _F_erase_range
)(const_iterator
,
294 : _F_erase_point(&container_type::erase
),
295 _F_erase_range(&container_type::erase
) { }
298 template<typename _Tp1
, typename _Tp2
, typename _Tp3
,
299 typename _Tp4
, typename _Tp5
>
300 struct erase_base
<std::unordered_multimap
<_Tp1
, _Tp2
, _Tp3
,
303 typedef std::unordered_multimap
<_Tp1
, _Tp2
, _Tp3
, _Tp4
, _Tp5
>
305 typedef typename
container_type::iterator iterator
;
306 typedef typename
container_type::const_iterator const_iterator
;
308 iterator (container_type::* _F_erase_point
)(const_iterator
);
309 iterator (container_type::* _F_erase_range
)(const_iterator
,
313 : _F_erase_point(&container_type::erase
),
314 _F_erase_range(&container_type::erase
) { }
317 template<typename _Tp1
, typename _Tp2
, typename _Tp3
, typename _Tp4
>
318 struct erase_base
<std::unordered_set
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>>
320 typedef std::unordered_set
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>
322 typedef typename
container_type::iterator iterator
;
323 typedef typename
container_type::const_iterator const_iterator
;
325 iterator (container_type::* _F_erase_point
)(const_iterator
);
326 iterator (container_type::* _F_erase_range
)(const_iterator
,
330 : _F_erase_point(&container_type::erase
),
331 _F_erase_range(&container_type::erase
) { }
334 template<typename _Tp1
, typename _Tp2
, typename _Tp3
, typename _Tp4
>
335 struct erase_base
<std::unordered_multiset
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>>
337 typedef std::unordered_multiset
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>
339 typedef typename
container_type::iterator iterator
;
340 typedef typename
container_type::const_iterator const_iterator
;
342 iterator (container_type::* _F_erase_point
)(const_iterator
);
343 iterator (container_type::* _F_erase_range
)(const_iterator
,
347 : _F_erase_point(&container_type::erase
),
348 _F_erase_range(&container_type::erase
) { }
351 template<typename _Tp
,
352 bool = traits
<_Tp
>::has_erase::value
,
353 bool = traits
<_Tp
>::has_erase_after::value
>
356 // Specialization for most containers.
357 template<typename _Tp
>
358 struct erase_point
<_Tp
, true, false> : public erase_base
<_Tp
>
360 using erase_base
<_Tp
>::_F_erase_point
;
363 operator()(_Tp
& __container
)
367 // NB: Should be equivalent to size() member function, but
368 // computed with begin() and end().
369 const size_type sz
= std::distance(__container
.begin(),
372 // NB: Lowest common denominator: use forward iterator operations.
373 auto i
= __container
.begin();
374 std::advance(i
, generate(sz
));
376 // Makes it easier to think of this as __container.erase(i)
377 (__container
.*_F_erase_point
)(i
);
379 catch(const __gnu_cxx::forced_error
&)
384 // Specialization for forward_list.
385 template<typename _Tp
>
386 struct erase_point
<_Tp
, false, true> : public erase_base
<_Tp
>
388 using erase_base
<_Tp
>::_F_erase_point
;
391 operator()(_Tp
& __container
)
395 // NB: Should be equivalent to size() member function, but
396 // computed with begin() and end().
397 const size_type sz
= std::distance(__container
.begin(),
400 // NB: Lowest common denominator: use forward iterator operations.
401 auto i
= __container
.before_begin();
402 std::advance(i
, generate(sz
));
404 // Makes it easier to think of this as __container.erase(i)
405 (__container
.*_F_erase_point
)(i
);
407 catch(const __gnu_cxx::forced_error
&)
412 // Specialization, empty.
413 template<typename _Tp
>
414 struct erase_point
<_Tp
, false, false>
421 template<typename _Tp
,
422 bool = traits
<_Tp
>::has_erase::value
,
423 bool = traits
<_Tp
>::has_erase_after::value
>
426 // Specialization for most containers.
427 template<typename _Tp
>
428 struct erase_range
<_Tp
, true, false> : public erase_base
<_Tp
>
430 using erase_base
<_Tp
>::_F_erase_range
;
433 operator()(_Tp
& __container
)
437 const size_type sz
= std::distance(__container
.begin(),
439 size_type s1
= generate(sz
);
440 size_type s2
= generate(sz
);
441 auto i1
= __container
.begin();
442 auto i2
= __container
.begin();
443 std::advance(i1
, std::min(s1
, s2
));
444 std::advance(i2
, std::max(s1
, s2
));
446 // Makes it easier to think of this as __container.erase(i1, i2).
447 (__container
.*_F_erase_range
)(i1
, i2
);
449 catch(const __gnu_cxx::forced_error
&)
454 // Specialization for forward_list.
455 template<typename _Tp
>
456 struct erase_range
<_Tp
, false, true> : public erase_base
<_Tp
>
458 using erase_base
<_Tp
>::_F_erase_range
;
461 operator()(_Tp
& __container
)
465 const size_type sz
= std::distance(__container
.begin(),
467 size_type s1
= generate(sz
);
468 size_type s2
= generate(sz
);
469 auto i1
= __container
.before_begin();
470 auto i2
= __container
.before_begin();
471 std::advance(i1
, std::min(s1
, s2
));
472 std::advance(i2
, std::max(s1
, s2
));
474 // Makes it easier to think of this as __container.erase(i1, i2).
475 (__container
.*_F_erase_range
)(i1
, i2
);
477 catch(const __gnu_cxx::forced_error
&)
482 // Specialization, empty.
483 template<typename _Tp
>
484 struct erase_range
<_Tp
, false, false>
491 template<typename _Tp
, bool = traits
<_Tp
>::has_push_pop::value
>
495 operator()(_Tp
& __container
)
499 __container
.pop_front();
501 catch(const __gnu_cxx::forced_error
&)
506 // Specialization, empty.
507 template<typename _Tp
>
508 struct pop_front
<_Tp
, false>
515 template<typename _Tp
, bool = traits
<_Tp
>::has_push_pop::value
516 && traits
<_Tp
>::is_reversible::value
>
520 operator()(_Tp
& __container
)
524 __container
.pop_back();
526 catch(const __gnu_cxx::forced_error
&)
531 // Specialization, empty.
532 template<typename _Tp
>
533 struct pop_back
<_Tp
, false>
540 template<typename _Tp
, bool = traits
<_Tp
>::has_push_pop::value
>
543 typedef _Tp container_type
;
544 typedef typename
container_type::value_type value_type
;
547 operator()(_Tp
& __test
)
551 const value_type cv
= generate_unique
<value_type
>();
552 __test
.push_front(cv
);
554 catch(const __gnu_cxx::forced_error
&)
558 // Assumes containers start out equivalent.
560 operator()(_Tp
& __control
, _Tp
& __test
)
564 const value_type cv
= generate_unique
<value_type
>();
565 __test
.push_front(cv
);
567 catch(const __gnu_cxx::forced_error
&)
572 // Specialization, empty.
573 template<typename _Tp
>
574 struct push_front
<_Tp
, false>
580 operator()(_Tp
&, _Tp
&) { }
584 template<typename _Tp
, bool = traits
<_Tp
>::has_push_pop::value
585 && traits
<_Tp
>::is_reversible::value
>
588 typedef _Tp container_type
;
589 typedef typename
container_type::value_type value_type
;
592 operator()(_Tp
& __test
)
596 const value_type cv
= generate_unique
<value_type
>();
597 __test
.push_back(cv
);
599 catch(const __gnu_cxx::forced_error
&)
603 // Assumes containers start out equivalent.
605 operator()(_Tp
& __control
, _Tp
& __test
)
609 const value_type cv
= generate_unique
<value_type
>();
610 __test
.push_back(cv
);
612 catch(const __gnu_cxx::forced_error
&)
617 // Specialization, empty.
618 template<typename _Tp
>
619 struct push_back
<_Tp
, false>
625 operator()(_Tp
&, _Tp
&) { }
629 // Abstract the insert function into two parts:
630 // 1, insert_base_functions == holds function pointer
631 // 2, insert_base == links function pointer to class insert method
632 template<typename _Tp
>
635 typedef typename
_Tp::iterator iterator
;
636 typedef typename
_Tp::value_type value_type
;
638 iterator (_Tp::* _F_insert_point
)(iterator
, const value_type
&);
640 insert_base() : _F_insert_point(&_Tp::insert
) { }
643 // Specialization, as string insertion has a different signature.
644 template<typename _Tp1
, typename _Tp2
, typename _Tp3
>
645 struct insert_base
<std::basic_string
<_Tp1
, _Tp2
, _Tp3
>>
647 typedef std::basic_string
<_Tp1
, _Tp2
, _Tp3
> container_type
;
648 typedef typename
container_type::iterator iterator
;
649 typedef typename
container_type::value_type value_type
;
651 iterator (container_type::* _F_insert_point
)(iterator
, value_type
);
653 insert_base() : _F_insert_point(&container_type::insert
) { }
656 template<typename _Tp1
, typename _Tp2
, typename _Tp3
,
657 template <typename
, typename
, typename
> class _Tp4
>
658 struct insert_base
<__gnu_cxx::__versa_string
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>>
660 typedef __gnu_cxx::__versa_string
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>
662 typedef typename
container_type::iterator iterator
;
663 typedef typename
container_type::value_type value_type
;
665 iterator (container_type::* _F_insert_point
)(iterator
, value_type
);
667 insert_base() : _F_insert_point(&container_type::insert
) { }
670 // Specialization, as forward_list insertion has a different signature.
671 template<typename _Tp1
, typename _Tp2
>
672 struct insert_base
<std::forward_list
<_Tp1
, _Tp2
>>
674 typedef std::forward_list
<_Tp1
, _Tp2
> container_type
;
675 typedef typename
container_type::iterator iterator
;
676 typedef typename
container_type::const_iterator const_iterator
;
677 typedef typename
container_type::value_type value_type
;
679 iterator (container_type::* _F_insert_point
)(const_iterator
,
682 insert_base() : _F_insert_point(&container_type::insert_after
) { }
685 // Likewise for the unordered containers.
686 template<typename _Tp1
, typename _Tp2
, typename _Tp3
,
687 typename _Tp4
, typename _Tp5
>
688 struct insert_base
<std::unordered_map
<_Tp1
, _Tp2
, _Tp3
, _Tp4
, _Tp5
>>
690 typedef std::unordered_map
<_Tp1
, _Tp2
, _Tp3
, _Tp4
, _Tp5
>
692 typedef typename
container_type::iterator iterator
;
693 typedef typename
container_type::const_iterator const_iterator
;
694 typedef typename
container_type::value_type value_type
;
696 iterator (container_type::* _F_insert_point
)(const_iterator
,
699 insert_base() : _F_insert_point(&container_type::insert
) { }
702 template<typename _Tp1
, typename _Tp2
, typename _Tp3
,
703 typename _Tp4
, typename _Tp5
>
704 struct insert_base
<std::unordered_multimap
<_Tp1
, _Tp2
, _Tp3
,
707 typedef std::unordered_multimap
<_Tp1
, _Tp2
, _Tp3
, _Tp4
, _Tp5
>
709 typedef typename
container_type::iterator iterator
;
710 typedef typename
container_type::const_iterator const_iterator
;
711 typedef typename
container_type::value_type value_type
;
713 iterator (container_type::* _F_insert_point
)(const_iterator
,
716 insert_base() : _F_insert_point(&container_type::insert
) { }
719 template<typename _Tp1
, typename _Tp2
, typename _Tp3
, typename _Tp4
>
720 struct insert_base
<std::unordered_set
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>>
722 typedef std::unordered_set
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>
724 typedef typename
container_type::iterator iterator
;
725 typedef typename
container_type::const_iterator const_iterator
;
726 typedef typename
container_type::value_type value_type
;
728 iterator (container_type::* _F_insert_point
)(const_iterator
,
731 insert_base() : _F_insert_point(&container_type::insert
) { }
734 template<typename _Tp1
, typename _Tp2
, typename _Tp3
, typename _Tp4
>
735 struct insert_base
<std::unordered_multiset
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>>
737 typedef std::unordered_multiset
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>
739 typedef typename
container_type::iterator iterator
;
740 typedef typename
container_type::const_iterator const_iterator
;
741 typedef typename
container_type::value_type value_type
;
743 iterator (container_type::* _F_insert_point
)(const_iterator
,
746 insert_base() : _F_insert_point(&container_type::insert
) { }
749 template<typename _Tp
,
750 bool = traits
<_Tp
>::has_insert::value
,
751 bool = traits
<_Tp
>::has_insert_after::value
>
754 // Specialization for most containers.
755 template<typename _Tp
>
756 struct insert_point
<_Tp
, true, false> : public insert_base
<_Tp
>
758 typedef _Tp container_type
;
759 typedef typename
container_type::value_type value_type
;
760 using insert_base
<_Tp
>::_F_insert_point
;
763 operator()(_Tp
& __test
)
767 const value_type cv
= generate_unique
<value_type
>();
768 const size_type sz
= std::distance(__test
.begin(), __test
.end());
769 size_type s
= generate(sz
);
770 auto i
= __test
.begin();
772 (__test
.*_F_insert_point
)(i
, cv
);
774 catch(const __gnu_cxx::forced_error
&)
778 // Assumes containers start out equivalent.
780 operator()(_Tp
& __control
, _Tp
& __test
)
784 const value_type cv
= generate_unique
<value_type
>();
785 const size_type sz
= std::distance(__test
.begin(), __test
.end());
786 size_type s
= generate(sz
);
787 auto i
= __test
.begin();
789 (__test
.*_F_insert_point
)(i
, cv
);
791 catch(const __gnu_cxx::forced_error
&)
796 // Specialization for forward_list.
797 template<typename _Tp
>
798 struct insert_point
<_Tp
, false, true> : public insert_base
<_Tp
>
800 typedef _Tp container_type
;
801 typedef typename
container_type::value_type value_type
;
802 using insert_base
<_Tp
>::_F_insert_point
;
805 operator()(_Tp
& __test
)
809 const value_type cv
= generate_unique
<value_type
>();
810 const size_type sz
= std::distance(__test
.begin(), __test
.end());
811 size_type s
= generate(sz
);
812 auto i
= __test
.before_begin();
814 (__test
.*_F_insert_point
)(i
, cv
);
816 catch(const __gnu_cxx::forced_error
&)
820 // Assumes containers start out equivalent.
822 operator()(_Tp
& __control
, _Tp
& __test
)
826 const value_type cv
= generate_unique
<value_type
>();
827 const size_type sz
= std::distance(__test
.begin(), __test
.end());
828 size_type s
= generate(sz
);
829 auto i
= __test
.before_begin();
831 (__test
.*_F_insert_point
)(i
, cv
);
833 catch(const __gnu_cxx::forced_error
&)
838 // Specialization, empty.
839 template<typename _Tp
>
840 struct insert_point
<_Tp
, false, false>
846 operator()(_Tp
&, _Tp
&) { }
850 template<typename _Tp
, bool = traits
<_Tp
>::is_associative::value
851 || traits
<_Tp
>::is_unordered::value
>
855 operator()(_Tp
& __container
)
861 catch(const __gnu_cxx::forced_error
&)
866 // Specialization, empty.
867 template<typename _Tp
>
868 struct clear
<_Tp
, false>
875 template<typename _Tp
, bool = traits
<_Tp
>::is_unordered::value
>
879 operator()(_Tp
& __test
)
883 size_type s
= generate(__test
.bucket_count());
886 catch(const __gnu_cxx::forced_error
&)
891 operator()(_Tp
& __control
, _Tp
& __test
)
895 size_type s
= generate(__test
.bucket_count());
898 catch(const __gnu_cxx::forced_error
&)
900 // Also check hash status.
902 if (__control
.load_factor() != __test
.load_factor())
904 if (__control
.max_load_factor() != __test
.max_load_factor())
906 if (__control
.bucket_count() != __test
.bucket_count())
908 if (__control
.max_bucket_count() != __test
.max_bucket_count())
914 std::string
__s("setup_base::rehash "
915 "containers not equal");
918 __s
+= "\t\t\tcontrol : test";
920 __s
+= "load_factor\t\t";
921 __builtin_sprintf(buf
, "%lu", __control
.load_factor());
924 __builtin_sprintf(buf
, "%lu", __test
.load_factor());
928 __s
+= "max_load_factor\t\t";
929 __builtin_sprintf(buf
, "%lu", __control
.max_load_factor());
932 __builtin_sprintf(buf
, "%lu", __test
.max_load_factor());
936 __s
+= "bucket_count\t\t";
937 __builtin_sprintf(buf
, "%lu", __control
.bucket_count());
940 __builtin_sprintf(buf
, "%lu", __test
.bucket_count());
944 __s
+= "max_bucket_count\t";
945 __builtin_sprintf(buf
, "%lu", __control
.max_bucket_count());
948 __builtin_sprintf(buf
, "%lu", __test
.max_bucket_count());
952 std::__throw_logic_error(__s
.c_str());
958 // Specialization, empty.
959 template<typename _Tp
>
960 struct rehash
<_Tp
, false>
966 operator()(_Tp
&, _Tp
&) { }
970 template<typename _Tp
>
976 operator()(_Tp
& __container
)
980 __container
.swap(_M_other
);
982 catch(const __gnu_cxx::forced_error
&)
988 template<typename _Tp
>
989 struct iterator_operations
991 typedef _Tp container_type
;
992 typedef typename
container_type::iterator iterator
;
995 operator()(_Tp
& __container
)
1000 iterator i
= __container
.begin();
1001 iterator
__attribute__((unused
)) icopy(i
);
1002 iterator
__attribute__((unused
)) iassign
= i
;
1004 catch(const __gnu_cxx::forced_error
&)
1010 template<typename _Tp
>
1011 struct const_iterator_operations
1013 typedef _Tp container_type
;
1014 typedef typename
container_type::const_iterator const_iterator
;
1017 operator()(_Tp
& __container
)
1022 const_iterator i
= __container
.begin();
1023 const_iterator
__attribute__((unused
)) icopy(i
);
1024 const_iterator
__attribute__((unused
)) iassign
= i
;
1026 catch(const __gnu_cxx::forced_error
&)
1032 // Base class for exception tests.
1033 template<typename _Tp
>
1034 struct test_base
: public functor_base
1036 typedef _Tp container_type
;
1038 typedef functor_base base_type
;
1039 typedef populate
<container_type
> populate
;
1040 typedef make_container_n
<container_type
> make_container_n
;
1042 typedef clear
<container_type
> clear
;
1043 typedef erase_point
<container_type
> erase_point
;
1044 typedef erase_range
<container_type
> erase_range
;
1045 typedef insert_point
<container_type
> insert_point
;
1046 typedef pop_front
<container_type
> pop_front
;
1047 typedef pop_back
<container_type
> pop_back
;
1048 typedef push_front
<container_type
> push_front
;
1049 typedef push_back
<container_type
> push_back
;
1050 typedef rehash
<container_type
> rehash
;
1051 typedef swap
<container_type
> swap
;
1052 typedef iterator_operations
<container_type
> iterator_ops
;
1053 typedef const_iterator_operations
<container_type
> const_iterator_ops
;
1055 using base_type::compare
;
1059 erase_point _M_erasep
;
1060 erase_range _M_eraser
;
1061 insert_point _M_insertp
;
1064 push_front _M_pushf
;
1069 iterator_ops _M_iops
;
1070 const_iterator_ops _M_ciops
;
1074 // Run through all member functions for basic exception safety
1075 // guarantee: no resource leaks when exceptions are thrown.
1077 // Types of resources checked: memory.
1079 // For each member function, use throw_value and throw_allocator as
1080 // value_type and allocator_type to force potential exception safety
1084 // _Tp::value_type is __gnu_cxx::throw_value_*
1085 // _Tp::allocator_type is __gnu_cxx::throw_allocator_*
1086 // And that the _Cond template parameter for them both is
1087 // __gnu_cxx::limit_condition.
1088 template<typename _Tp
>
1089 struct basic_safety
: public test_base
<_Tp
>
1091 typedef _Tp container_type
;
1092 typedef test_base
<container_type
> base_type
;
1093 typedef typename
base_type::populate populate
;
1094 typedef std::function
<void(container_type
&)> function_type
;
1095 typedef __gnu_cxx::limit_condition condition_type
;
1097 using base_type::generate
;
1099 container_type _M_container
;
1100 std::vector
<function_type
> _M_functions
;
1102 basic_safety() { run(); }
1108 condition_type::never_adjustor off
;
1110 // Construct containers.
1111 populate
p1(_M_container
);
1112 populate
p2(base_type::_M_swap
._M_other
);
1114 // Construct list of member functions to exercise.
1115 _M_functions
.push_back(function_type(base_type::_M_iops
));
1116 _M_functions
.push_back(function_type(base_type::_M_ciops
));
1118 _M_functions
.push_back(function_type(base_type::_M_erasep
));
1119 _M_functions
.push_back(function_type(base_type::_M_eraser
));
1120 _M_functions
.push_back(function_type(base_type::_M_insertp
));
1121 _M_functions
.push_back(function_type(base_type::_M_popf
));
1122 _M_functions
.push_back(function_type(base_type::_M_popb
));
1123 _M_functions
.push_back(function_type(base_type::_M_pushf
));
1124 _M_functions
.push_back(function_type(base_type::_M_pushb
));
1125 _M_functions
.push_back(function_type(base_type::_M_rehash
));
1126 _M_functions
.push_back(function_type(base_type::_M_swap
));
1129 _M_functions
.push_back(function_type(base_type::_M_clear
));
1132 for (auto i
= _M_functions
.begin(); i
!= _M_functions
.end(); ++i
)
1134 function_type
& f
= *i
;
1135 run_steps_to_limit(f
);
1139 template<typename _Funct
>
1141 run_steps_to_limit(const _Funct
& __f
)
1145 auto a
= _M_container
.get_allocator();
1149 // Use the current step as an allocator label.
1154 condition_type::limit_adjustor
limit(i
);
1157 // If we get here, done.
1160 catch(const __gnu_cxx::forced_error
&)
1162 // Check this step for allocations.
1163 // NB: Will throw std::logic_error if allocations.
1164 a
.check_allocated(i
);
1166 // Check memory allocated with operator new.
1174 std::cout
<< __f
.target_type().name() << std::endl
;
1175 std::cout
<< "end count " << i
<< std::endl
;
1180 // Run through all member functions with a no throw requirement, sudden death.
1181 // all: member functions erase, pop_back, pop_front, swap
1182 // iterator copy ctor, assignment operator
1183 // unordered and associative: clear
1184 // NB: Assumes _Tp::allocator_type is __gnu_cxx::throw_allocator_random.
1185 template<typename _Tp
>
1186 struct generation_prohibited
: public test_base
<_Tp
>
1188 typedef _Tp container_type
;
1189 typedef test_base
<container_type
> base_type
;
1190 typedef typename
base_type::populate populate
;
1191 typedef __gnu_cxx::random_condition condition_type
;
1193 container_type _M_container
;
1195 generation_prohibited() { run(); }
1200 // Furthermore, assumes that the test functor will throw
1201 // forced_exception via throw_allocator, that all errors are
1202 // propagated and in error. Sudden death!
1206 condition_type::never_adjustor off
;
1207 populate
p1(_M_container
);
1208 populate
p2(base_type::_M_swap
._M_other
);
1213 condition_type::always_adjustor on
;
1215 // NB: Vector and deque are special, erase can throw if the copy
1216 // constructor or assignment operator of value_type throws.
1217 if (!traits
<container_type
>::has_throwing_erase::value
)
1219 _M_erasep(_M_container
);
1220 _M_eraser(_M_container
);
1223 _M_popf(_M_container
);
1224 _M_popb(_M_container
);
1226 _M_iops(_M_container
);
1227 _M_ciops(_M_container
);
1229 _M_swap(_M_container
);
1232 _M_clear(_M_container
);
1238 // Test strong exception guarantee.
1239 // Run through all member functions with a roll-back, consistent
1240 // coherent requirement.
1241 // all: member functions insert of a single element, push_back, push_front
1242 // unordered: rehash
1243 template<typename _Tp
>
1244 struct propagation_consistent
: public test_base
<_Tp
>
1246 typedef _Tp container_type
;
1247 typedef test_base
<container_type
> base_type
;
1248 typedef typename
base_type::populate populate
;
1249 typedef std::function
<void(container_type
&)> function_type
;
1250 typedef __gnu_cxx::limit_condition condition_type
;
1252 using base_type::compare
;
1254 container_type _M_container_test
;
1255 container_type _M_container_control
;
1256 std::vector
<function_type
> _M_functions
;
1258 propagation_consistent() { run(); }
1262 { _M_container_test
= _M_container_control
; }
1269 condition_type::never_adjustor off
;
1271 // Construct containers.
1272 populate
p(_M_container_control
);
1275 // Construct list of member functions to exercise.
1276 _M_functions
.push_back(function_type(base_type::_M_pushf
));
1277 _M_functions
.push_back(function_type(base_type::_M_pushb
));
1278 _M_functions
.push_back(function_type(base_type::_M_insertp
));
1279 _M_functions
.push_back(function_type(base_type::_M_rehash
));
1282 for (auto i
= _M_functions
.begin(); i
!= _M_functions
.end(); ++i
)
1284 function_type
& f
= *i
;
1285 run_steps_to_limit(f
);
1289 template<typename _Funct
>
1291 run_steps_to_limit(const _Funct
& __f
)
1302 condition_type::limit_adjustor
limit(i
);
1303 __f(_M_container_test
);
1305 // If we get here, done.
1308 catch(const __gnu_cxx::forced_error
&)
1310 compare(_M_container_control
, _M_container_test
);
1317 std::cout
<< __f
.target_type().name() << std::endl
;
1318 std::cout
<< "end count " << i
<< std::endl
;
1322 } // namespace __gnu_test