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