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