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 | #include <boost/container/small_vector.hpp> |
11 | #include "vector_test.hpp" |
12 | #include "movable_int.hpp" |
13 | #include "propagate_allocator_test.hpp" |
14 | #include "default_init_test.hpp" |
15 | #include "../../intrusive/test/iterator_test.hpp" |
16 | |
17 | #include <boost/container/allocator_traits.hpp> |
18 | |
19 | #include <iostream> |
20 | |
21 | struct boost_container_small_vector; |
22 | |
23 | namespace boost { namespace container { namespace test { |
24 | |
25 | template<> |
26 | struct alloc_propagate_base<boost_container_small_vector> |
27 | { |
28 | template <class T, class Allocator> |
29 | struct apply |
30 | { |
31 | typedef boost::container::small_vector<T, 10, Allocator> type; |
32 | }; |
33 | }; |
34 | |
35 | }}} //namespace boost::container::test |
36 | |
37 | bool test_small_vector_base_test() |
38 | { |
39 | typedef boost::container::small_vector_base<int> smb_t; |
40 | { |
41 | typedef boost::container::small_vector<int, 5> sm5_t; |
42 | BOOST_CONTAINER_STATIC_ASSERT(sm5_t::static_capacity == 5); |
43 | sm5_t sm5; |
44 | smb_t &smb = sm5; |
45 | smb.push_back(x: 1); |
46 | sm5_t sm5_copy(sm5); |
47 | sm5_copy.push_back(x: 1); |
48 | if (!boost::container::test::CheckEqualContainers(cont_a: sm5, cont_b: smb)) |
49 | return false; |
50 | } |
51 | { |
52 | typedef boost::container::small_vector<int, 7> sm7_t; |
53 | BOOST_CONTAINER_STATIC_ASSERT(sm7_t::static_capacity == 7); |
54 | sm7_t sm7; |
55 | smb_t &smb = sm7; |
56 | smb.push_back(x: 2); |
57 | sm7_t sm7_copy(sm7); |
58 | sm7_copy.push_back(x: 2); |
59 | if (!boost::container::test::CheckEqualContainers(cont_a: sm7, cont_b: smb)) |
60 | return false; |
61 | } |
62 | { |
63 | typedef boost::container::small_vector<int, 5> sm5_t; |
64 | sm5_t sm5; |
65 | smb_t &smb = sm5; |
66 | smb.push_back(x: 1); |
67 | sm5_t sm5_copy(smb); |
68 | if (!boost::container::test::CheckEqualContainers(cont_a: sm5, cont_b: sm5_copy)) |
69 | return false; |
70 | smb.push_back(x: 2); |
71 | if(smb.size() != 2){ |
72 | return false; |
73 | } |
74 | sm5_copy = smb; |
75 | if (!boost::container::test::CheckEqualContainers(cont_a: sm5, cont_b: sm5_copy)) |
76 | return false; |
77 | sm5_t sm5_move(boost::move(t&: smb)); |
78 | smb.clear(); |
79 | if (!boost::container::test::CheckEqualContainers(cont_a: sm5_move, cont_b: sm5_copy)) |
80 | return false; |
81 | smb = sm5_copy; |
82 | sm5_move = boost::move(t&: smb); |
83 | smb.clear(); |
84 | if (!boost::container::test::CheckEqualContainers(cont_a: sm5_move, cont_b: sm5_copy)) |
85 | return false; |
86 | } |
87 | |
88 | return true; |
89 | } |
90 | |
91 | //small vector has internal storage so some special swap cases must be tested |
92 | bool test_swap() |
93 | { |
94 | typedef boost::container::small_vector<int, 10> vec; |
95 | { //v bigger than static capacity, w empty |
96 | vec v; |
97 | for(std::size_t i = 0, max = v.capacity()+1; i != max; ++i){ |
98 | v.push_back(x: int(i)); |
99 | } |
100 | vec w; |
101 | const std::size_t v_size = v.size(); |
102 | const std::size_t w_size = w.size(); |
103 | v.swap(other&: w); |
104 | if(v.size() != w_size || w.size() != v_size) |
105 | return false; |
106 | } |
107 | { //v smaller than static capacity, w empty |
108 | vec v; |
109 | for(std::size_t i = 0, max = v.capacity()-1; i != max; ++i){ |
110 | v.push_back(x: int(i)); |
111 | } |
112 | vec w; |
113 | const std::size_t v_size = v.size(); |
114 | const std::size_t w_size = w.size(); |
115 | v.swap(other&: w); |
116 | if(v.size() != w_size || w.size() != v_size) |
117 | return false; |
118 | } |
119 | { //v & w smaller than static capacity |
120 | vec v; |
121 | for(std::size_t i = 0, max = v.capacity()-1; i != max; ++i){ |
122 | v.push_back(x: int(i)); |
123 | } |
124 | vec w; |
125 | for(std::size_t i = 0, max = v.capacity()/2; i != max; ++i){ |
126 | w.push_back(x: int(i)); |
127 | } |
128 | const std::size_t v_size = v.size(); |
129 | const std::size_t w_size = w.size(); |
130 | v.swap(other&: w); |
131 | if(v.size() != w_size || w.size() != v_size) |
132 | return false; |
133 | } |
134 | { //v & w bigger than static capacity |
135 | vec v; |
136 | for(std::size_t i = 0, max = v.capacity()+1; i != max; ++i){ |
137 | v.push_back(x: int(i)); |
138 | } |
139 | vec w; |
140 | for(std::size_t i = 0, max = v.capacity()*2; i != max; ++i){ |
141 | w.push_back(x: int(i)); |
142 | } |
143 | const std::size_t v_size = v.size(); |
144 | const std::size_t w_size = w.size(); |
145 | v.swap(other&: w); |
146 | if(v.size() != w_size || w.size() != v_size) |
147 | return false; |
148 | } |
149 | return true; |
150 | } |
151 | |
152 | template<class VoidAllocator> |
153 | struct GetAllocatorCont |
154 | { |
155 | template<class ValueType> |
156 | struct apply |
157 | { |
158 | typedef boost::container::small_vector< ValueType, 10 |
159 | , typename boost::container::allocator_traits<VoidAllocator> |
160 | ::template portable_rebind_alloc<ValueType>::type |
161 | > type; |
162 | }; |
163 | }; |
164 | |
165 | template<class VoidAllocator> |
166 | int test_cont_variants() |
167 | { |
168 | using namespace boost::container; |
169 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont; |
170 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont; |
171 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont; |
172 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont; |
173 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::moveconstruct_int>::type MyMoveConstructCont; |
174 | |
175 | if (test::vector_test<MyCont>()) |
176 | return 1; |
177 | if (test::vector_test<MyMoveCont>()) |
178 | return 1; |
179 | if (test::vector_test<MyCopyMoveCont>()) |
180 | return 1; |
181 | if (test::vector_test<MyCopyCont>()) |
182 | return 1; |
183 | if (test::vector_test<MyMoveConstructCont>()) |
184 | return 1; |
185 | |
186 | return 0; |
187 | } |
188 | |
189 | int main() |
190 | { |
191 | using namespace boost::container; |
192 | |
193 | if(!test_swap()) |
194 | return 1; |
195 | |
196 | if(test::vector_test< small_vector<int, 0> >()) |
197 | return 1; |
198 | |
199 | if(test::vector_test< small_vector<int, 2000> >()) |
200 | return 1; |
201 | |
202 | if (test_cont_variants< new_allocator<void> >()) |
203 | return 1; |
204 | |
205 | //////////////////////////////////// |
206 | // Default init test |
207 | //////////////////////////////////// |
208 | if(!test::default_init_test< small_vector<int, 5, test::default_init_allocator<int> > >()){ |
209 | std::cerr << "Default init test failed" << std::endl; |
210 | return 1; |
211 | } |
212 | |
213 | //////////////////////////////////// |
214 | // Emplace testing |
215 | //////////////////////////////////// |
216 | const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE); |
217 | if(!boost::container::test::test_emplace< small_vector<test::EmplaceInt, 5>, Options>()){ |
218 | return 1; |
219 | } |
220 | |
221 | //////////////////////////////////// |
222 | // Allocator propagation testing |
223 | //////////////////////////////////// |
224 | if(!boost::container::test::test_propagate_allocator<boost_container_small_vector>()){ |
225 | return 1; |
226 | } |
227 | |
228 | //////////////////////////////////// |
229 | // Initializer lists testing |
230 | //////////////////////////////////// |
231 | if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for |
232 | < boost::container::small_vector<int, 5> >()) { |
233 | return 1; |
234 | } |
235 | |
236 | //////////////////////////////////// |
237 | // Small vector base |
238 | //////////////////////////////////// |
239 | if (!test_small_vector_base_test()){ |
240 | return 1; |
241 | } |
242 | |
243 | //////////////////////////////////// |
244 | // Iterator testing |
245 | //////////////////////////////////// |
246 | { |
247 | typedef boost::container::small_vector<int, 0> cont_int; |
248 | cont_int a; a.push_back(x: 0); a.push_back(x: 1); a.push_back(x: 2); |
249 | boost::intrusive::test::test_iterator_random< cont_int >(c&: a); |
250 | if(boost::report_errors() != 0) { |
251 | return 1; |
252 | } |
253 | } |
254 | |
255 | //////////////////////////////////// |
256 | // has_trivial_destructor_after_move testing |
257 | //////////////////////////////////// |
258 | // default allocator |
259 | { |
260 | typedef boost::container::small_vector<int, 0> cont; |
261 | if (boost::has_trivial_destructor_after_move<cont>::value) { |
262 | std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; |
263 | return 1; |
264 | } |
265 | } |
266 | // std::allocator |
267 | { |
268 | typedef boost::container::small_vector<int, 0, std::allocator<int> > cont; |
269 | if (boost::has_trivial_destructor_after_move<cont>::value) { |
270 | std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; |
271 | return 1; |
272 | } |
273 | } |
274 | |
275 | return 0; |
276 | } |
277 | |