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/slist.hpp>
11 #include <boost/container/node_allocator.hpp>
12
13 #include <memory>
14 #include "dummy_test_allocator.hpp"
15 #include "movable_int.hpp"
16 #include "list_test.hpp"
17 #include "propagate_allocator_test.hpp"
18 #include "emplace_test.hpp"
19 #include "../../intrusive/test/iterator_test.hpp"
20
21 using namespace boost::container;
22
23 class recursive_slist
24 {
25 public:
26 int id_;
27 slist<recursive_slist> slist_;
28 slist<recursive_slist>::iterator it_;
29 slist<recursive_slist>::const_iterator cit_;
30
operator =(const recursive_slist & o)31 recursive_slist &operator=(const recursive_slist &o)
32 { slist_ = o.slist_; return *this; }
33 };
34
recursive_slist_test()35 void recursive_slist_test()//Test for recursive types
36 {
37 slist<recursive_slist> recursive_list_list;
38 }
39
40 template<class VoidAllocator>
41 struct GetAllocatorCont
42 {
43 template<class ValueType>
44 struct apply
45 {
46 typedef slist< ValueType
47 , typename allocator_traits<VoidAllocator>
48 ::template portable_rebind_alloc<ValueType>::type
49 > type;
50 };
51 };
52
test_support_for_initializer_list()53 bool test_support_for_initializer_list()
54 {
55 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
56 const std::initializer_list<int> il = {5, 10, 15};
57 const slist<int> expected_list(il.begin(), il.end());
58 {
59 slist<int> sl = il;
60 if(sl != expected_list)
61 return false;
62 }
63
64 {
65 slist<int> sl = {1, 2};
66 sl = il;
67 if(sl != expected_list)
68 return false;
69 }
70 {
71 slist<int> sl({ 1, 2 }, slist<int>::allocator_type());
72 sl = il;
73 if (sl != expected_list)
74 return false;
75 }
76 {
77 slist<int> sl = {4, 5};
78 sl.assign(il);
79 if(sl != expected_list)
80 return false;
81 }
82
83 {
84 slist<int> sl = {15};
85 sl.insert(sl.cbegin(), {5, 10});
86 if(sl != expected_list)
87 return false;
88 }
89
90 {
91 slist<int> sl = {5};
92 sl.insert_after(sl.cbegin(), {10, 15});
93 if(sl != expected_list)
94 return false;
95 }
96 return true;
97 #endif
98 return true;
99 }
100
test_for_splice()101 bool test_for_splice()
102 {
103 {
104 slist<int> list1; list1.push_front(3); list1.push_front(2); list1.push_front(1); list1.push_front(0);
105 slist<int> list2;
106 slist<int> expected1; expected1.push_front(3); expected1.push_front(2); expected1.push_front(0);
107 slist<int> expected2; expected2.push_front(1);
108
109 list2.splice(list2.begin(), list1, ++list1.begin());
110
111 if (!(expected1 == list1 && expected2 == list2))
112 return false;
113 }
114 {
115 slist<int> list1; list1.push_front(3); list1.push_front(2); list1.push_front(1); list1.push_front(0);
116 slist<int> list2;
117 slist<int> expected1;
118 slist<int> expected2; expected2.push_front(3); expected2.push_front(2); expected2.push_front(1); expected2.push_front(0);
119
120 list2.splice(list2.begin(), list1, list1.begin(), list1.end());
121
122 if (!(expected1 == list1 && expected2 == list2))
123 return false;
124 }
125 return true;
126 }
127
128 struct boost_container_slist;
129
130 namespace boost {
131 namespace container {
132 namespace test {
133
134 template<>
135 struct alloc_propagate_base<boost_container_slist>
136 {
137 template <class T, class Allocator>
138 struct apply
139 {
140 typedef boost::container::slist<T, Allocator> type;
141 };
142 };
143
144 }}}
145
main()146 int main ()
147 {
148 recursive_slist_test();
149 {
150 //Now test move semantics
151 slist<recursive_slist> original;
152 slist<recursive_slist> move_ctor(boost::move(original));
153 slist<recursive_slist> move_assign;
154 move_assign = boost::move(move_ctor);
155 move_assign.swap(original);
156 {
157 slist<recursive_slist> recursive, copy;
158 //Test to test both move emulations
159 if(!copy.size()){
160 copy = recursive;
161 }
162 }
163 }
164 ////////////////////////////////////
165 // Testing allocator implementations
166 ////////////////////////////////////
167 if (test::list_test<slist<int, std::allocator<int> >, false>())
168 return 1;
169 if (test::list_test<slist<int>, false>())
170 return 1;
171 if (test::list_test<slist<int, node_allocator<int> >, false>())
172 return 1;
173 if (test::list_test<slist<test::movable_int>, false>())
174 return 1;
175 if (test::list_test<slist<test::movable_and_copyable_int>, false>())
176 return 1;
177 if (test::list_test<slist<test::copyable_int>, false>())
178 return 1;
179
180 ////////////////////////////////////
181 // Emplace testing
182 ////////////////////////////////////
183 const test::EmplaceOptions Options = (test::EmplaceOptions)
184 (test::EMPLACE_FRONT | test::EMPLACE_AFTER | test::EMPLACE_BEFORE | test::EMPLACE_AFTER);
185
186 if(!boost::container::test::test_emplace
187 < slist<test::EmplaceInt>, Options>())
188 return 1;
189
190 ////////////////////////////////////
191 // Allocator propagation testing
192 ////////////////////////////////////
193 if(!boost::container::test::test_propagate_allocator<boost_container_slist>())
194 return 1;
195
196 ////////////////////////////////////
197 // Initializer lists
198 ////////////////////////////////////
199 if(!test_support_for_initializer_list())
200 return 1;
201
202 ////////////////////////////////////
203 // Splice testing
204 ////////////////////////////////////
205 if(!test_for_splice())
206 return 1;
207
208 ////////////////////////////////////
209 // Iterator testing
210 ////////////////////////////////////
211 {
212 typedef boost::container::slist<int> vector_int;
213 vector_int a; a.push_front(2); a.push_front(1); a.push_front(0);
214 boost::intrusive::test::test_iterator_forward< boost::container::slist<int> >(a);
215 if(boost::report_errors() != 0) {
216 return 1;
217 }
218 }
219 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
220 ////////////////////////////////////
221 // Constructor Template Auto Deduction Tests
222 ////////////////////////////////////
223 {
224 auto gold = std::list{ 1, 2, 3 };
225 auto test = boost::container::slist(gold.begin(), gold.end());
226 if (test.size() != 3) {
227 return 1;
228 }
229 if (test.front() != 1)
230 return 1;
231 test.pop_front();
232 if (test.front() != 2)
233 return 1;
234 test.pop_front();
235 if (test.front() != 3)
236 return 1;
237 test.pop_front();
238 }
239 {
240 auto gold = std::list{ 1, 2, 3 };
241 auto test = boost::container::slist(gold.begin(), gold.end(), new_allocator<int>());
242 if (test.size() != 3) {
243 return 1;
244 }
245 if (test.front() != 1)
246 return 1;
247 test.pop_front();
248 if (test.front() != 2)
249 return 1;
250 test.pop_front();
251 if (test.front() != 3)
252 return 1;
253 test.pop_front();
254 }
255 #endif
256
257 ////////////////////////////////////
258 // has_trivial_destructor_after_move testing
259 ////////////////////////////////////
260 // default allocator
261 {
262 typedef boost::container::slist<int> cont;
263 typedef cont::allocator_type allocator_type;
264 typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
265 if (boost::has_trivial_destructor_after_move<cont>::value !=
266 boost::has_trivial_destructor_after_move<allocator_type>::value &&
267 boost::has_trivial_destructor_after_move<pointer>::value) {
268 std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
269 return 1;
270 }
271 }
272 // std::allocator
273 {
274 typedef boost::container::slist<int, std::allocator<int> > cont;
275 typedef cont::allocator_type allocator_type;
276 typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
277 if (boost::has_trivial_destructor_after_move<cont>::value !=
278 boost::has_trivial_destructor_after_move<allocator_type>::value &&
279 boost::has_trivial_destructor_after_move<pointer>::value) {
280 std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
281 return 1;
282 }
283 }
284
285 return 0;
286 }
287