]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // (C) Copyright Ion Gaztanaga 2004-2013. Distributed under the Boost | |
4 | // Software License, Version 1.0. (See accompanying file | |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | // See http://www.boost.org/libs/container for documentation. | |
8 | // | |
9 | ////////////////////////////////////////////////////////////////////////////// | |
7c673cae FG |
10 | #include <memory> |
11 | #include <deque> | |
12 | #include <iostream> | |
13 | #include <list> | |
14 | ||
15 | #include <boost/container/deque.hpp> | |
16 | #include <boost/container/allocator.hpp> | |
17 | ||
18 | #include "print_container.hpp" | |
19 | #include "check_equal_containers.hpp" | |
20 | #include "dummy_test_allocator.hpp" | |
21 | #include "movable_int.hpp" | |
22 | #include <boost/move/utility_core.hpp> | |
23 | #include <boost/move/iterator.hpp> | |
24 | #include <boost/container/detail/mpl.hpp> | |
25 | #include <boost/container/detail/type_traits.hpp> | |
26 | #include <string> | |
27 | #include "emplace_test.hpp" | |
28 | #include "propagate_allocator_test.hpp" | |
29 | #include "vector_test.hpp" | |
30 | #include "default_init_test.hpp" | |
31 | #include <boost/core/no_exceptions_support.hpp> | |
32 | #include "../../intrusive/test/iterator_test.hpp" | |
33 | ||
34 | using namespace boost::container; | |
35 | ||
7c673cae FG |
36 | //Function to check if both sets are equal |
37 | template<class V1, class V2> | |
11fdf7f2 | 38 | bool deque_copyable_only(V1 &, V2 &, dtl::false_type) |
7c673cae FG |
39 | { |
40 | return true; | |
41 | } | |
42 | ||
43 | //Function to check if both sets are equal | |
44 | template<class V1, class V2> | |
11fdf7f2 | 45 | bool deque_copyable_only(V1 &cntdeque, V2 &stddeque, dtl::true_type) |
7c673cae FG |
46 | { |
47 | typedef typename V1::value_type IntType; | |
48 | std::size_t size = cntdeque.size(); | |
1e59de90 TL |
49 | stddeque.insert(stddeque.end(), 50u, 1); |
50 | cntdeque.insert(cntdeque.end(), 50u, IntType(1)); | |
7c673cae FG |
51 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
52 | { | |
53 | IntType move_me(1); | |
1e59de90 TL |
54 | stddeque.insert(stddeque.begin()+std::ptrdiff_t(size)/2, 50u, 1); |
55 | cntdeque.insert(cntdeque.begin()+std::ptrdiff_t(size/2), 50u, boost::move(move_me)); | |
7c673cae FG |
56 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
57 | } | |
58 | { | |
59 | IntType move_me(2); | |
60 | cntdeque.assign(cntdeque.size()/2, boost::move(move_me)); | |
61 | stddeque.assign(stddeque.size()/2, 2); | |
62 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
63 | } | |
64 | { | |
65 | IntType move_me(1); | |
66 | stddeque.clear(); | |
67 | cntdeque.clear(); | |
1e59de90 TL |
68 | stddeque.insert(stddeque.begin(), 50u, 1); |
69 | cntdeque.insert(cntdeque.begin(), 50u, boost::move(move_me)); | |
7c673cae | 70 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
1e59de90 TL |
71 | stddeque.insert(stddeque.begin()+20, 50u, 1); |
72 | cntdeque.insert(cntdeque.begin()+20, 50u, boost::move(move_me)); | |
7c673cae | 73 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
1e59de90 TL |
74 | stddeque.insert(stddeque.begin()+20, 20u, 1); |
75 | cntdeque.insert(cntdeque.begin()+20, 20u, boost::move(move_me)); | |
7c673cae FG |
76 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
77 | } | |
78 | { | |
79 | IntType move_me(1); | |
80 | stddeque.clear(); | |
81 | cntdeque.clear(); | |
1e59de90 TL |
82 | stddeque.insert(stddeque.end(), 50u, 1); |
83 | cntdeque.insert(cntdeque.end(), 50u, boost::move(move_me)); | |
7c673cae | 84 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
1e59de90 TL |
85 | stddeque.insert(stddeque.end()-20, 50u, 1); |
86 | cntdeque.insert(cntdeque.end()-20, 50u, boost::move(move_me)); | |
7c673cae | 87 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
1e59de90 TL |
88 | stddeque.insert(stddeque.end()-20, 20u, 1); |
89 | cntdeque.insert(cntdeque.end()-20, 20u, boost::move(move_me)); | |
7c673cae FG |
90 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
91 | } | |
92 | ||
93 | return true; | |
94 | } | |
95 | ||
96 | //Test recursive structures | |
97 | class recursive_deque | |
98 | { | |
99 | public: | |
100 | ||
20effc67 TL |
101 | recursive_deque (const recursive_deque &x) |
102 | : deque_(x.deque_) | |
103 | {} | |
104 | ||
7c673cae FG |
105 | recursive_deque & operator=(const recursive_deque &x) |
106 | { this->deque_ = x.deque_; return *this; } | |
107 | ||
108 | int id_; | |
109 | deque<recursive_deque> deque_; | |
110 | deque<recursive_deque>::iterator it_; | |
111 | deque<recursive_deque>::const_iterator cit_; | |
112 | deque<recursive_deque>::reverse_iterator rit_; | |
113 | deque<recursive_deque>::const_reverse_iterator crit_; | |
114 | }; | |
115 | ||
116 | template<class IntType> | |
117 | bool do_test() | |
118 | { | |
119 | //Test for recursive types | |
120 | { | |
121 | deque<recursive_deque> recursive_deque_deque; | |
122 | } | |
123 | ||
124 | { | |
125 | //Now test move semantics | |
126 | deque<recursive_deque> original; | |
127 | deque<recursive_deque> move_ctor(boost::move(original)); | |
128 | deque<recursive_deque> move_assign; | |
129 | move_assign = boost::move(move_ctor); | |
130 | move_assign.swap(original); | |
131 | } | |
132 | ||
133 | //Alias deque types | |
134 | typedef deque<IntType> MyCntDeque; | |
135 | typedef std::deque<int> MyStdDeque; | |
136 | const int max = 100; | |
137 | { | |
138 | ::boost::movelib::unique_ptr<MyCntDeque> const pcntdeque = ::boost::movelib::make_unique<MyCntDeque>(); | |
139 | ::boost::movelib::unique_ptr<MyStdDeque> const pstddeque = ::boost::movelib::make_unique<MyStdDeque>(); | |
140 | MyCntDeque &cntdeque = *pcntdeque; | |
141 | MyStdDeque &stddeque = *pstddeque; | |
142 | for(int i = 0; i < max*100; ++i){ | |
143 | IntType move_me(i); | |
144 | cntdeque.insert(cntdeque.end(), boost::move(move_me)); | |
145 | stddeque.insert(stddeque.end(), i); | |
146 | } | |
147 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
148 | ||
149 | cntdeque.clear(); | |
150 | stddeque.clear(); | |
151 | ||
152 | for(int i = 0; i < max*100; ++i){ | |
153 | IntType move_me(i); | |
154 | cntdeque.push_back(boost::move(move_me)); | |
155 | stddeque.push_back(i); | |
156 | } | |
157 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
158 | ||
159 | cntdeque.clear(); | |
160 | stddeque.clear(); | |
161 | ||
162 | for(int i = 0; i < max*100; ++i){ | |
163 | IntType move_me(i); | |
164 | cntdeque.push_front(boost::move(move_me)); | |
165 | stddeque.push_front(i); | |
166 | } | |
167 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
168 | ||
169 | typename MyCntDeque::iterator it; | |
170 | typename MyCntDeque::const_iterator cit = it; | |
171 | (void)cit; | |
172 | ||
173 | cntdeque.erase(cntdeque.begin()++); | |
174 | stddeque.erase(stddeque.begin()++); | |
175 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
176 | ||
177 | cntdeque.erase(cntdeque.begin()); | |
178 | stddeque.erase(stddeque.begin()); | |
179 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
180 | ||
181 | { | |
182 | //Initialize values | |
183 | IntType aux_vect[50]; | |
184 | for(int i = 0; i < 50; ++i){ | |
185 | IntType move_me (-1); | |
186 | aux_vect[i] = boost::move(move_me); | |
187 | } | |
188 | int aux_vect2[50]; | |
189 | for(int i = 0; i < 50; ++i){ | |
190 | aux_vect2[i] = -1; | |
191 | } | |
192 | ||
193 | cntdeque.insert(cntdeque.end() | |
194 | ,boost::make_move_iterator(&aux_vect[0]) | |
195 | ,boost::make_move_iterator(aux_vect + 50)); | |
196 | stddeque.insert(stddeque.end(), aux_vect2, aux_vect2 + 50); | |
197 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
198 | ||
199 | for(int i = 0; i < 50; ++i){ | |
200 | IntType move_me (i); | |
201 | aux_vect[i] = boost::move(move_me); | |
202 | } | |
203 | for(int i = 0; i < 50; ++i){ | |
204 | aux_vect2[i] = i; | |
205 | } | |
206 | ||
1e59de90 | 207 | cntdeque.insert(cntdeque.begin()+std::ptrdiff_t(cntdeque.size()) |
7c673cae FG |
208 | ,boost::make_move_iterator(&aux_vect[0]) |
209 | ,boost::make_move_iterator(aux_vect + 50)); | |
1e59de90 | 210 | stddeque.insert(stddeque.begin()+std::ptrdiff_t(stddeque.size()), aux_vect2, aux_vect2 + 50); |
7c673cae FG |
211 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
212 | ||
213 | for(int i = 0, j = static_cast<int>(cntdeque.size()); i < j; ++i){ | |
214 | cntdeque.erase(cntdeque.begin()); | |
215 | stddeque.erase(stddeque.begin()); | |
216 | } | |
217 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
218 | } | |
219 | { | |
220 | IntType aux_vect[50]; | |
221 | for(int i = 0; i < 50; ++i){ | |
222 | IntType move_me(-1); | |
223 | aux_vect[i] = boost::move(move_me); | |
224 | } | |
225 | int aux_vect2[50]; | |
226 | for(int i = 0; i < 50; ++i){ | |
227 | aux_vect2[i] = -1; | |
228 | } | |
229 | cntdeque.insert(cntdeque.begin() | |
230 | ,boost::make_move_iterator(&aux_vect[0]) | |
231 | ,boost::make_move_iterator(aux_vect + 50)); | |
232 | stddeque.insert(stddeque.begin(), aux_vect2, aux_vect2 + 50); | |
233 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
234 | } | |
235 | ||
236 | if(!deque_copyable_only(cntdeque, stddeque | |
11fdf7f2 | 237 | ,dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){ |
7c673cae FG |
238 | return false; |
239 | } | |
240 | ||
241 | cntdeque.erase(cntdeque.begin()); | |
242 | stddeque.erase(stddeque.begin()); | |
243 | ||
244 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
245 | ||
246 | for(int i = 0; i < max; ++i){ | |
247 | IntType move_me(i); | |
248 | cntdeque.insert(cntdeque.begin(), boost::move(move_me)); | |
249 | stddeque.insert(stddeque.begin(), i); | |
250 | } | |
251 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; | |
252 | ||
253 | //Test insertion from list | |
254 | { | |
255 | std::list<int> l(50, int(1)); | |
256 | cntdeque.insert(cntdeque.begin(), l.begin(), l.end()); | |
257 | stddeque.insert(stddeque.begin(), l.begin(), l.end()); | |
258 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; | |
259 | cntdeque.assign(l.begin(), l.end()); | |
260 | stddeque.assign(l.begin(), l.end()); | |
261 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; | |
262 | } | |
263 | ||
264 | cntdeque.resize(100); | |
265 | stddeque.resize(100); | |
266 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; | |
267 | ||
268 | cntdeque.resize(200); | |
269 | stddeque.resize(200); | |
270 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; | |
271 | } | |
272 | ||
92f5a8d4 TL |
273 | #ifndef BOOST_CONTAINER_NO_CXX17_CTAD |
274 | //Check Constructor Template Auto Deduction | |
275 | { | |
276 | auto gold = MyStdDeque{ 1, 2, 3 }; | |
277 | auto test = deque(gold.begin(), gold.end()); | |
278 | if(!test::CheckEqualContainers(gold, test)) return false; | |
279 | } | |
280 | { | |
281 | auto gold = MyStdDeque{ 1, 2, 3 }; | |
282 | auto test = deque(gold.begin(), gold.end(), new_allocator<int>()); | |
283 | if(!test::CheckEqualContainers(gold, test)) return false; | |
284 | } | |
285 | #endif | |
286 | ||
7c673cae FG |
287 | std::cout << std::endl << "Test OK!" << std::endl; |
288 | return true; | |
289 | } | |
290 | ||
291 | template<class VoidAllocator> | |
292 | struct GetAllocatorCont | |
293 | { | |
294 | template<class ValueType> | |
295 | struct apply | |
296 | { | |
297 | typedef deque< ValueType | |
298 | , typename allocator_traits<VoidAllocator> | |
299 | ::template portable_rebind_alloc<ValueType>::type | |
300 | > type; | |
301 | }; | |
302 | }; | |
303 | ||
304 | template<class VoidAllocator> | |
305 | int test_cont_variants() | |
306 | { | |
307 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont; | |
308 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont; | |
309 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont; | |
310 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont; | |
311 | ||
312 | if(test::vector_test<MyCont>()) | |
313 | return 1; | |
314 | if(test::vector_test<MyMoveCont>()) | |
315 | return 1; | |
316 | if(test::vector_test<MyCopyMoveCont>()) | |
317 | return 1; | |
318 | if(test::vector_test<MyCopyCont>()) | |
319 | return 1; | |
320 | return 0; | |
321 | } | |
322 | ||
323 | struct boost_container_deque; | |
324 | ||
325 | namespace boost { namespace container { namespace test { | |
326 | ||
327 | template<> | |
328 | struct alloc_propagate_base<boost_container_deque> | |
329 | { | |
330 | template <class T, class Allocator> | |
331 | struct apply | |
332 | { | |
333 | typedef boost::container::deque<T, Allocator> type; | |
334 | }; | |
335 | }; | |
336 | ||
337 | }}} //namespace boost::container::test | |
338 | ||
339 | int main () | |
340 | { | |
341 | if(!do_test<int>()) | |
342 | return 1; | |
343 | ||
344 | if(!do_test<test::movable_int>()) | |
345 | return 1; | |
346 | ||
347 | if(!do_test<test::movable_and_copyable_int>()) | |
348 | return 1; | |
349 | ||
350 | if(!do_test<test::copyable_int>()) | |
351 | return 1; | |
352 | ||
353 | //Test non-copy-move operations | |
354 | { | |
355 | deque<test::non_copymovable_int> d; | |
356 | d.emplace_back(); | |
357 | d.emplace_front(1); | |
358 | d.resize(10); | |
359 | d.resize(1); | |
360 | } | |
361 | ||
362 | //////////////////////////////////// | |
363 | // Allocator implementations | |
364 | //////////////////////////////////// | |
365 | // std:allocator | |
366 | if(test_cont_variants< std::allocator<void> >()){ | |
367 | std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl; | |
368 | return 1; | |
369 | } | |
370 | // boost::container::allocator | |
371 | if(test_cont_variants< allocator<void> >()){ | |
372 | std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl; | |
373 | return 1; | |
374 | } | |
375 | //////////////////////////////////// | |
376 | // Default init test | |
377 | //////////////////////////////////// | |
378 | if(!test::default_init_test< deque<int, test::default_init_allocator<int> > >()){ | |
379 | std::cerr << "Default init test failed" << std::endl; | |
380 | return 1; | |
381 | } | |
382 | ||
383 | //////////////////////////////////// | |
384 | // Emplace testing | |
385 | //////////////////////////////////// | |
386 | const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE); | |
387 | ||
388 | if(!boost::container::test::test_emplace | |
389 | < deque<test::EmplaceInt>, Options>()) | |
390 | return 1; | |
391 | //////////////////////////////////// | |
392 | // Allocator propagation testing | |
393 | //////////////////////////////////// | |
394 | if(!boost::container::test::test_propagate_allocator<boost_container_deque>()) | |
395 | return 1; | |
396 | ||
397 | //////////////////////////////////// | |
398 | // Initializer lists testing | |
399 | //////////////////////////////////// | |
400 | if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for | |
401 | < boost::container::deque<int> >()) { | |
402 | return 1; | |
403 | } | |
404 | ||
405 | //////////////////////////////////// | |
406 | // Iterator testing | |
407 | //////////////////////////////////// | |
408 | { | |
409 | typedef boost::container::deque<int> cont_int; | |
410 | cont_int a; a.push_back(0); a.push_back(1); a.push_back(2); | |
411 | boost::intrusive::test::test_iterator_random< cont_int >(a); | |
412 | if(boost::report_errors() != 0) { | |
413 | return 1; | |
414 | } | |
415 | } | |
416 | ||
92f5a8d4 TL |
417 | //////////////////////////////////// |
418 | // has_trivial_destructor_after_move testing | |
419 | //////////////////////////////////// | |
420 | // default allocator | |
421 | { | |
422 | typedef boost::container::deque<int> cont; | |
423 | typedef cont::allocator_type allocator_type; | |
424 | typedef boost::container::allocator_traits<allocator_type>::pointer pointer; | |
20effc67 TL |
425 | BOOST_STATIC_ASSERT_MSG(!(boost::has_trivial_destructor_after_move<cont>::value != |
426 | boost::has_trivial_destructor_after_move<allocator_type>::value && | |
427 | boost::has_trivial_destructor_after_move<pointer>::value) | |
428 | , "has_trivial_destructor_after_move(std::allocator) test failed"); | |
92f5a8d4 TL |
429 | } |
430 | // std::allocator | |
431 | { | |
432 | typedef boost::container::deque<int, std::allocator<int> > cont; | |
433 | typedef cont::allocator_type allocator_type; | |
434 | typedef boost::container::allocator_traits<allocator_type>::pointer pointer; | |
20effc67 TL |
435 | BOOST_STATIC_ASSERT_MSG(!(boost::has_trivial_destructor_after_move<cont>::value != |
436 | boost::has_trivial_destructor_after_move<allocator_type>::value && | |
437 | boost::has_trivial_destructor_after_move<pointer>::value) | |
438 | , "has_trivial_destructor_after_move(std::allocator) test failed"); | |
92f5a8d4 TL |
439 | } |
440 | ||
7c673cae FG |
441 | return 0; |
442 | } |