• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Olaf Krzikalla 2004-2006.
4 // (C) Copyright Ion Gaztanaga  2006-2013.
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 //    (See accompanying file LICENSE_1_0.txt or copy at
8 //          http://www.boost.org/LICENSE_1_0.txt)
9 //
10 // See http://www.boost.org/libs/intrusive for documentation.
11 //
12 /////////////////////////////////////////////////////////////////////////////
13 #include <boost/container/vector.hpp>
14 #include <boost/intrusive/detail/config_begin.hpp>
15 #include "common_functors.hpp"
16 #include <boost/detail/lightweight_test.hpp>
17 #include <boost/intrusive/options.hpp>
18 #include <boost/intrusive/detail/iterator.hpp>
19 #include "test_macros.hpp"
20 #include "test_container.hpp"
21 #include "generic_assoc_test.hpp"
22 #include <typeinfo>
23 
24 namespace boost{
25 namespace intrusive{
26 namespace test{
27 
28 template<class ContainerDefiner>
29 struct test_generic_multiset
30 {
31    typedef typename ContainerDefiner::value_cont_type    value_cont_type;
32 
33    static void test_all();
34    static void test_sort(value_cont_type&);
35    static void test_insert(value_cont_type&);
36    static void test_swap(value_cont_type&);
37    static void test_merge(value_cont_type&);
38    static void test_find(value_cont_type&);
39    static void test_impl();
40 };
41 
42 template<class ContainerDefiner>
test_all()43 void test_generic_multiset<ContainerDefiner>::test_all ()
44 {
45    static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
46    value_cont_type values (6);
47    for (int i = 0; i < 6; ++i)
48       (&values[i])->value_ = random_init[i];
49    typedef typename ContainerDefiner::template container
50       <>::type multiset_type;
51    {
52       multiset_type testset(values.begin(), values.end());
53       test::test_container(testset);
54       testset.clear();
55       testset.insert(values.begin(), values.end());
56       test::test_common_unordered_and_associative_container(testset, values);
57       testset.clear();
58       testset.insert(values.begin(), values.end());
59       test::test_associative_container(testset, values);
60       testset.clear();
61       testset.insert(values.begin(), values.end());
62       test::test_non_unique_container(testset, values);
63    }
64    test_sort(values);
65    test_insert(values);
66    test_swap(values);
67    test_merge(values);
68    test_find(values);
69    test_impl();
70    test_generic_assoc<ContainerDefiner>::test_all(values);
71 }
72 
73 //test case due to an error in tree implementation:
74 template<class ContainerDefiner>
test_impl()75 void test_generic_multiset<ContainerDefiner>::test_impl()
76 {
77    value_cont_type values (5);
78    for (int i = 0; i < 5; ++i)
79       (&values[i])->value_ = i;
80    typedef typename ContainerDefiner::template container
81       <>::type multiset_type;
82 
83    multiset_type testset;
84    for (int i = 0; i < 5; ++i)
85       testset.insert (values[i]);
86 
87    testset.erase (testset.iterator_to (values[0]));
88    testset.erase (testset.iterator_to (values[1]));
89    testset.insert (values[1]);
90 
91    testset.erase (testset.iterator_to (values[2]));
92    testset.erase (testset.iterator_to (values[3]));
93 }
94 
95 //test: constructor, iterator, clear, reverse_iterator, front, back, size:
96 template<class ContainerDefiner>
test_sort(value_cont_type & values)97 void test_generic_multiset<ContainerDefiner>::test_sort(value_cont_type& values)
98 {
99    typedef typename ContainerDefiner::template container
100       <>::type multiset_type;
101 
102    multiset_type testset1 (values.begin(), values.end());
103    {  int init_values [] = { 1, 2, 2, 3, 4, 5 };
104       TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() );  }
105 
106    testset1.clear();
107    BOOST_TEST (testset1.empty());
108 
109    typedef typename ContainerDefiner::template container
110       <compare<even_odd>
111       >::type multiset_type2;
112 
113    multiset_type2 testset2 (values.begin(), values.begin() + 6);
114    {  int init_values [] = { 5, 3, 1, 4, 2, 2 };
115       TEST_INTRUSIVE_SEQUENCE( init_values, testset2.rbegin() );  }
116 
117    BOOST_TEST (testset2.begin()->value_ == 2);
118    BOOST_TEST (testset2.rbegin()->value_ == 5);
119 }
120 
121 //test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
122 template<class ContainerDefiner>
test_insert(value_cont_type & values)123 void test_generic_multiset<ContainerDefiner>::test_insert(value_cont_type& values)
124 {
125    typedef typename ContainerDefiner::template container
126       <>::type multiset_type;
127 
128    multiset_type testset;
129    testset.insert(values.begin() + 2, values.begin() + 5);
130    testset.check();
131    {  int init_values [] = { 1, 4, 5 };
132       TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() );  }
133 
134    typename multiset_type::iterator i = testset.begin();
135    BOOST_TEST (i->value_ == 1);
136 
137    i = testset.insert (i, values[0]);
138    testset.check();
139    BOOST_TEST (&*i == &values[0]);
140 
141    {  int init_values [] = { 5, 4, 3, 1 };
142       TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() );  }
143 
144    i = testset.iterator_to (values[2]);
145    BOOST_TEST (&*i == &values[2]);
146 
147    i = multiset_type::s_iterator_to (values[2]);
148    BOOST_TEST (&*i == &values[2]);
149 
150    testset.erase(i);
151    testset.check();
152 
153    {  int init_values [] = { 1, 3, 5 };
154       TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() );  }
155 }
156 
157 //test: insert (seq-version), swap, erase (seq-version), size:
158 template<class ContainerDefiner>
test_swap(value_cont_type & values)159 void test_generic_multiset<ContainerDefiner>::test_swap(value_cont_type& values)
160 {
161    typedef typename ContainerDefiner::template container
162       <>::type multiset_type;
163    multiset_type testset1 (values.begin(), values.begin() + 2);
164    multiset_type testset2;
165    testset2.insert (values.begin() + 2, values.begin() + 6);
166    testset1.swap (testset2);
167 
168    {  int init_values [] = { 1, 2, 4, 5 };
169       TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() );  }
170    {  int init_values [] = { 2, 3 };
171       TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() );  }
172 
173    testset1.erase (testset1.iterator_to(values[5]), testset1.end());
174    BOOST_TEST (testset1.size() == 1);
175    BOOST_TEST (&*testset1.begin() == &values[3]);
176 }
177 
178 template<class ContainerDefiner>
test_merge(value_cont_type & values)179 void test_generic_multiset<ContainerDefiner>::test_merge(value_cont_type& values)
180 {
181    typedef typename ContainerDefiner::template container
182       <>::type multiset_type;
183    typedef typename multiset_type::key_of_value key_of_value;
184    typedef typename multiset_type::key_type     key_type;
185 
186    typedef typename ContainerDefiner::template container
187       < compare< std::greater<key_type> > >::type multiset_greater_type;
188 
189    //original vector: 3, 2, 4, 1, 5, 2
190    //2,3
191    multiset_type testset1 (values.begin(), values.begin() + 2);
192    //5, 4, 2, 1
193    multiset_greater_type testset2;
194    testset2.insert (values.begin() + 2, values.begin() + 6);
195 
196    testset2.merge(testset1);
197    testset1.check();
198    testset2.check();
199 
200    BOOST_TEST (testset1.empty());
201    BOOST_TEST (testset2.size() == 6);
202    {  int init_values [] = { 5, 4, 3, 2, 2, 1 };
203       TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() );  }
204 
205    value_cont_type cmp_val_cont(1);
206    typename value_cont_type::reference cmp_val = cmp_val_cont.front();
207    (&cmp_val)->value_ = 2;
208 
209    BOOST_TEST (*testset2.find(key_of_value()(cmp_val)) == values[5]);
210    BOOST_TEST (*testset2.find(2, any_greater()) == values[5]);
211    BOOST_TEST (&*(++testset2.find(key_of_value()(cmp_val))) == &values[1]);
212 
213    testset1.merge(testset2);
214    testset1.check();
215    testset2.check();
216 
217    BOOST_TEST (testset1.size() == 6);
218    {  int init_values [] = { 1, 2, 2, 3, 4, 5 };
219       TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() );  }
220    BOOST_TEST (*testset1.find(key_of_value()(cmp_val)) == values[5]);
221    BOOST_TEST (*testset1.find(2, any_less()) == values[5]);
222    BOOST_TEST (&*(++testset1.find(key_of_value()(cmp_val))) == &values[1]);
223    BOOST_TEST (testset2.empty());
224 }
225 
226 //test: find, equal_range (lower_bound, upper_bound):
227 template<class ContainerDefiner>
test_find(value_cont_type & values)228 void test_generic_multiset<ContainerDefiner>::test_find(value_cont_type& values)
229 {
230    typedef typename ContainerDefiner::template container
231       <>::type multiset_type;
232    typedef typename multiset_type::key_of_value key_of_value;
233    multiset_type testset (values.begin(), values.end());
234    typedef typename multiset_type::iterator        iterator;
235    typedef typename multiset_type::const_iterator  const_iterator;
236 
237    {
238       value_cont_type cmp_val_cont(1);
239       typename value_cont_type::reference cmp_val = cmp_val_cont.front();
240       (&cmp_val)->value_ = 2;
241       iterator i = testset.find (key_of_value()(cmp_val));
242       BOOST_TEST (i == testset.find (2, any_less()));
243       BOOST_TEST (i->value_ == 2);
244       BOOST_TEST ((++i)->value_ == 2);
245       std::pair<iterator,iterator> range = testset.equal_range (key_of_value()(cmp_val));
246       BOOST_TEST(range == testset.equal_range (2, any_less()));
247 
248       BOOST_TEST (range.first->value_ == 2);
249       BOOST_TEST (range.second->value_ == 3);
250       BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 2);
251 
252       (&cmp_val)->value_ = 7;
253       BOOST_TEST (testset.find(key_of_value()(cmp_val)) == testset.end());
254       BOOST_TEST (testset.find (7, any_less()) == testset.end());
255    }
256    {  //1, 2, 2, 3, 4, 5
257       const multiset_type &const_testset = testset;
258       std::pair<iterator,iterator> range;
259       std::pair<const_iterator, const_iterator> const_range;
260       value_cont_type cmp_val_cont(2);
261       typename value_cont_type::reference cmp_val_lower = cmp_val_cont.front();
262       typename value_cont_type::reference cmp_val_upper = cmp_val_cont.back();
263       {
264       (&cmp_val_lower)->value_ = 1;
265       (&cmp_val_upper)->value_ = 2;
266       //left-closed, right-closed
267       range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, true);
268       BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), true, true));
269       BOOST_TEST (range.first->value_ == 1);
270       BOOST_TEST (range.second->value_ == 3);
271       BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 3);
272       }
273       {
274       (&cmp_val_lower)->value_ = 1;
275       (&cmp_val_upper)->value_ = 2;
276       const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false);
277       BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), true, false));
278       BOOST_TEST (const_range.first->value_ == 1);
279       BOOST_TEST (const_range.second->value_ == 2);
280       BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1);
281 
282       (&cmp_val_lower)->value_ = 1;
283       (&cmp_val_upper)->value_ = 3;
284       range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false);
285       BOOST_TEST (range == testset.bounded_range (1, 3, any_less(), true, false));
286       BOOST_TEST (range.first->value_ == 1);
287       BOOST_TEST (range.second->value_ == 3);
288       BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 3);
289       }
290       {
291       (&cmp_val_lower)->value_ = 1;
292       (&cmp_val_upper)->value_ = 2;
293       const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, true);
294       BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), false, true));
295       BOOST_TEST (const_range.first->value_ == 2);
296       BOOST_TEST (const_range.second->value_ == 3);
297       BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 2);
298       }
299       {
300       (&cmp_val_lower)->value_ = 1;
301       (&cmp_val_upper)->value_ = 2;
302       range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, false);
303       BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), false, false));
304       BOOST_TEST (range.first->value_ == 2);
305       BOOST_TEST (range.second->value_ == 2);
306       BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 0);
307       }
308       {
309       (&cmp_val_lower)->value_ = 5;
310       (&cmp_val_upper)->value_ = 6;
311       const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false);
312       BOOST_TEST (const_range == const_testset.bounded_range (5, 6, any_less(), true, false));
313       BOOST_TEST (const_range.first->value_ == 5);
314       BOOST_TEST (const_range.second == const_testset.end());
315       BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1);
316       }
317    }
318 }
319 
320 }}}   //namespace boost::intrusive::test
321 
322 #include <boost/intrusive/detail/config_end.hpp>
323