1 // Boost.Bimap
2 //
3 // Copyright (c) 2006-2007 Matias Capeletto
4 //
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 
9 #ifndef LIBS_BIMAP_TEST_BIMAP_TEST_HPP
10 #define LIBS_BIMAP_TEST_BIMAP_TEST_HPP
11 
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15 
16 #include <boost/config.hpp>
17 
18 // std
19 #include <cassert>
20 #include <algorithm>
21 #include <iterator>
22 
23 #include <boost/lambda/lambda.hpp>
24 #include <boost/static_assert.hpp>
25 #include <boost/type_traits/is_same.hpp>
26 #include <boost/utility.hpp>
27 
28 template< class Container, class Data >
test_container(Container & c,const Data & d)29 void test_container(Container & c, const Data & d)
30 {
31     assert( d.size() > 2 );
32 
33     c.clear();
34 
35     BOOST_CHECK( c.size() == 0 );
36     BOOST_CHECK( c.empty() );
37 
38     c.insert( *d.begin() );
39 
40     c.insert( ++d.begin(),d.end() );
41 
42     BOOST_CHECK( c.size() == d.size() );
43 
44     BOOST_CHECK( c.size() <= c.max_size() );
45     BOOST_CHECK( ! c.empty() );
46 
47     c.erase( c.begin() );
48 
49     BOOST_CHECK( c.size() == d.size() - 1 );
50 
51     c.erase( c.begin(), c.end() );
52 
53     BOOST_CHECK( c.empty() );
54 
55     c.insert( *d.begin() );
56 
57     BOOST_CHECK( c.size() == 1 );
58 
59     c.insert( c.begin(), *(++d.begin()) );
60 
61     BOOST_CHECK( c.size() == 2 );
62 
63     BOOST_CHECK( c.begin() != c.end() );
64 }
65 
66 template< class Container, class Data >
test_sequence_container(Container & c,const Data & d)67 void test_sequence_container(Container & c, const Data & d)
68 {
69     assert( d.size() > 2 );
70 
71     c.clear();
72 
73     BOOST_CHECK( c.size() == 0 );
74     BOOST_CHECK( c.empty() );
75 
76     c.push_front( *   d.begin()  );
77     c.push_back ( *(++d.begin()) );
78 
79     BOOST_CHECK( c.front() == *   c.begin()  );
80     BOOST_CHECK( c.back () == *(++c.begin()) );
81 
82     BOOST_CHECK( c.size() == 2 );
83 
84     BOOST_CHECK( c.size() <= c.max_size() );
85     BOOST_CHECK( ! c.empty() );
86 
87     c.erase( c.begin() );
88 
89     BOOST_CHECK( c.size() == 1 );
90 
91     c.insert( c.begin(), *(++d.begin()) );
92 
93     c.erase( c.begin(), c.end() );
94 
95     BOOST_CHECK( c.empty() );
96 
97     c.push_front( *d.begin() );
98 
99     BOOST_CHECK( c.size() == 1 );
100 
101     BOOST_CHECK( c.begin() != c.end() );
102 
103     c.clear();
104     BOOST_CHECK( c.empty() );
105 
106     // assign
107 
108     c.assign(d.begin(),d.end());
109     BOOST_CHECK( c.size() == d.size() );
110     BOOST_CHECK( std::equal( c.begin(), c.end(), d.begin() ) );
111 
112     c.assign(d.size(),*d.begin());
113     BOOST_CHECK( c.size() == d.size() );
114     BOOST_CHECK( *c.begin() == *d.begin() );
115 
116     // Check insert(IterPos,InputIter,InputIter)
117 
118     c.clear();
119     c.insert( c.begin(), d.begin(), d.end() );
120     c.insert( boost::next(c.begin(),2), d.begin(), d.end() );
121 
122     BOOST_CHECK( std::equal( boost::next(c.begin(),2)
123                            , boost::next(c.begin(),2+d.size()) , d.begin() ) );
124 
125     // Check resize
126 
127     c.clear() ;
128     c.resize(4,*d.begin());
129     BOOST_CHECK( c.size() == 4 );
130     BOOST_CHECK( *c.begin() == *d.begin() ) ;
131 
132     BOOST_CHECK(     c == c   );
133     BOOST_CHECK( ! ( c != c ) );
134     BOOST_CHECK( ! ( c  < c ) );
135     BOOST_CHECK(   ( c <= c ) );
136     BOOST_CHECK( ! ( c  > c ) );
137     BOOST_CHECK(   ( c >= c ) );
138 }
139 
140 template< class Container, class Data >
test_vector_container(Container & c,const Data & d)141 void test_vector_container(Container & c, const Data & d)
142 {
143     assert( d.size() > 2 );
144 
145     c.clear() ;
146     c.reserve(2) ;
147     BOOST_CHECK( c.capacity() >= 2 ) ;
148     c.assign(d.begin(),d.end());
149     BOOST_CHECK( c.capacity() >= c.size() ) ;
150 
151     BOOST_CHECK( c[0] == *d.begin() ) ;
152     BOOST_CHECK( c.at(1) == *boost::next(d.begin()) );
153 
154     test_sequence_container(c,d) ;
155 }
156 
157 template< class Container, class Data >
test_associative_container(Container & c,const Data & d)158 void test_associative_container(Container & c, const Data & d)
159 {
160     assert( d.size() > 2 );
161 
162     c.clear();
163     c.insert(d.begin(),d.end());
164 
165     for( typename Data::const_iterator di = d.begin(), de = d.end();
166          di != de; ++di )
167     {
168         BOOST_CHECK( c.find(*di) != c.end() );
169     }
170 
171     typename Data::const_iterator da =   d.begin();
172     typename Data::const_iterator db = ++d.begin();
173 
174     c.erase(*da);
175 
176     BOOST_CHECK( c.size() == d.size()-1 );
177 
178     BOOST_CHECK( c.count(*da) == 0 );
179     BOOST_CHECK( c.count(*db) == 1 );
180 
181     BOOST_CHECK( c.find(*da) == c.end() );
182     BOOST_CHECK( c.find(*db) != c.end() );
183 
184     BOOST_CHECK( c.equal_range(*db).first != c.end() );
185 
186     c.clear();
187 
188     BOOST_CHECK( c.equal_range(*da).first == c.end() );
189 }
190 
191 
192 template< class Container >
test_mapped_container(Container &)193 void test_mapped_container(Container &)
194 {
195     typedef BOOST_DEDUCED_TYPENAME Container:: value_type  value_type ;
196     typedef BOOST_DEDUCED_TYPENAME Container::   key_type    key_type ;
197     typedef BOOST_DEDUCED_TYPENAME Container::  data_type   data_type ;
198     typedef BOOST_DEDUCED_TYPENAME Container::mapped_type mapped_type ;
199 
200     typedef BOOST_DEDUCED_TYPENAME
201         boost::is_same< key_type
202                       , BOOST_DEDUCED_TYPENAME value_type::first_type
203                       >::type test_key_type;
204     BOOST_STATIC_ASSERT(test_key_type::value);
205 
206     typedef BOOST_DEDUCED_TYPENAME
207         boost::is_same< data_type
208                       , BOOST_DEDUCED_TYPENAME value_type::second_type
209                       >::type test_data_type;
210     BOOST_STATIC_ASSERT(test_data_type::value);
211 
212     typedef BOOST_DEDUCED_TYPENAME
213         boost::is_same< mapped_type
214                       , BOOST_DEDUCED_TYPENAME value_type::second_type
215                       >::type test_mapped_type;
216     BOOST_STATIC_ASSERT(test_mapped_type::value);
217 }
218 
219 template< class Container, class Data >
test_pair_associative_container(Container & c,const Data & d)220 void test_pair_associative_container(Container & c, const Data & d)
221 {
222     test_mapped_container(c);
223 
224     assert( d.size() > 2 );
225 
226     c.clear();
227     c.insert(d.begin(),d.end());
228 
229     for( typename Data::const_iterator di = d.begin(), de = d.end();
230          di != de; ++di )
231     {
232         BOOST_CHECK( c.find(di->first) != c.end() );
233     }
234 
235     typename Data::const_iterator da =   d.begin();
236     typename Data::const_iterator db = ++d.begin();
237 
238     c.erase(da->first);
239 
240     BOOST_CHECK( c.size() == d.size()-1 );
241 
242     BOOST_CHECK( c.count(da->first) == 0 );
243     BOOST_CHECK( c.count(db->first) == 1 );
244 
245     BOOST_CHECK( c.find(da->first) == c.end() );
246     BOOST_CHECK( c.find(db->first) != c.end() );
247 
248     BOOST_CHECK( c.equal_range(db->first).first != c.end() );
249 
250     c.clear();
251 
252     BOOST_CHECK( c.equal_range(da->first).first == c.end() );
253 }
254 
255 
256 template< class Container, class Data >
test_simple_ordered_associative_container_equality(Container & c,const Data & d)257 void test_simple_ordered_associative_container_equality(Container & c, const Data & d)
258 {
259     BOOST_CHECK( std::equal( c. begin(), c. end(), d. begin() ) );
260     BOOST_CHECK( std::equal( c.rbegin(), c.rend(), d.rbegin() ) );
261 
262     BOOST_CHECK( c.lower_bound( *d.begin() ) ==   c.begin() );
263     BOOST_CHECK( c.upper_bound( *d.begin() ) == ++c.begin() );
264 }
265 
266 template< class Container, class Data >
test_simple_ordered_associative_container(Container & c,const Data & d)267 void test_simple_ordered_associative_container(Container & c, const Data & d)
268 {
269     assert( d.size() > 2 );
270 
271     c.clear();
272     c.insert(d.begin(),d.end());
273 
274     for( typename Data::const_iterator di = d.begin(), de = d.end();
275          di != de; ++di )
276     {
277         typename Container::const_iterator ci = c.find(*di);
278         BOOST_CHECK( ci != c.end() );
279 
280         BOOST_CHECK( ! c.key_comp()(*ci,*di) );
281         BOOST_CHECK( ! c.value_comp()(*ci,*di) );
282     }
283 
284     test_simple_ordered_associative_container_equality(c, d);
285 
286     const Container & cr = c;
287 
288     test_simple_ordered_associative_container_equality(cr, d);
289 
290     BOOST_CHECK(     c == c   );
291     BOOST_CHECK( ! ( c != c ) );
292     BOOST_CHECK( ! ( c  < c ) );
293     BOOST_CHECK(   ( c <= c ) );
294     BOOST_CHECK( ! ( c  > c ) );
295     BOOST_CHECK(   ( c >= c ) );
296 
297     /*
298     BOOST_CHECK( c.range( *c.begin() <= ::boost::lambda::_1,
299                             ::boost::lambda::_1 <= *(++c.begin()) ).
300                     first == c.begin()
301     );
302     */
303 }
304 
305 template< class Container, class Data >
test_simple_unordered_associative_container(Container & c,const Data & d)306 void test_simple_unordered_associative_container(Container & c, const Data & d)
307 {
308     c.clear();
309     c.insert( d.begin(), d.end() );
310 
311     BOOST_CHECK( c.bucket_count() * c.max_load_factor() >= d.size() );
312     BOOST_CHECK( c.max_bucket_count() >= c.bucket_count() );
313 
314     for( typename Data::const_iterator di = d.begin(), de = d.end() ;
315          di != de ; ++di )
316     {
317         // non const
318         {
319             typename Container::size_type nb = c.bucket(*c.find(*di));
320 
321             BOOST_CHECK( c.begin(nb) != c.end(nb) );
322         }
323 
324         // const
325         {
326             const Container & const_c = c;
327 
328             BOOST_CHECK(
329                 const_c.bucket_size(const_c.bucket(*di)) == 1
330             );
331 
332             typename Container::size_type nb =
333                 const_c.bucket(*const_c.find(*di));
334 
335             BOOST_CHECK(
336                 const_c.begin(nb) != const_c.end(nb)
337             );
338         }
339     }
340 
341 
342     BOOST_CHECK( c.load_factor() < c.max_load_factor() );
343 
344     c.max_load_factor(0.75);
345 
346     BOOST_CHECK( c.max_load_factor() == 0.75 );
347 
348     c.rehash(10);
349 }
350 
351 
352 template< class Container, class Data >
test_pair_ordered_associative_container_equality(Container & c,const Data & d)353 void test_pair_ordered_associative_container_equality(Container & c, const Data & d)
354 {
355     BOOST_CHECK( std::equal( c. begin(), c. end(), d. begin() ) );
356     BOOST_CHECK( std::equal( c.rbegin(), c.rend(), d.rbegin() ) );
357 
358     BOOST_CHECK( c.lower_bound( d.begin()->first ) ==   c.begin() );
359     BOOST_CHECK( c.upper_bound( d.begin()->first ) == ++c.begin() );
360 }
361 
362 template< class Container, class Data >
test_pair_ordered_associative_container(Container & c,const Data & d)363 void test_pair_ordered_associative_container(Container & c, const Data & d)
364 {
365     assert( d.size() > 2 );
366 
367     c.clear();
368     c.insert(d.begin(),d.end());
369 
370     for( typename Container::const_iterator ci = c.begin(), ce = c.end();
371          ci != ce; ++ci )
372     {
373         typename Data::const_iterator di = d.find(ci->first);
374         BOOST_CHECK( di != d.end() );
375         BOOST_CHECK( ! c.key_comp()(di->first,ci->first) );
376         BOOST_CHECK( ! c.value_comp()(*ci,*di) );
377     }
378 
379     test_pair_ordered_associative_container_equality(c, d);
380 
381     const Container & cr = c;
382 
383     test_pair_ordered_associative_container_equality(cr, d);
384 
385     BOOST_CHECK( c.range( c.begin()->first <= ::boost::lambda::_1,
386                           ::boost::lambda::_1 <= (++c.begin())->first ).
387                     first == c.begin()
388     );
389 }
390 
391 
392 template< class Container, class Data >
test_pair_unordered_associative_container(Container & c,const Data & d)393 void test_pair_unordered_associative_container(Container & c, const Data & d)
394 {
395     c.clear();
396     c.insert( d.begin(), d.end() );
397 
398     BOOST_CHECK( c.bucket_count() * c.max_load_factor() >= d.size() );
399     BOOST_CHECK( c.max_bucket_count() >= c.bucket_count() );
400 
401     for( typename Data::const_iterator di = d.begin(), de = d.end() ;
402          di != de ; ++di )
403     {
404         // non const
405         {
406             typename Container::size_type nb =
407                 c.bucket(c.find(di->first)->first);
408 
409             BOOST_CHECK( c.begin(nb) != c.end(nb) );
410         }
411 
412         // const
413         {
414             const Container & const_c = c;
415 
416             BOOST_CHECK( const_c.bucket_size(const_c.bucket(di->first)) == 1 );
417 
418             typename Container::size_type nb =
419                 const_c.bucket(const_c.find(di->first)->first);
420 
421             BOOST_CHECK( const_c.begin(nb) != const_c.end(nb) );
422         }
423     }
424 
425 
426     BOOST_CHECK( c.load_factor() < c.max_load_factor() );
427 
428     c.max_load_factor(0.75);
429 
430     BOOST_CHECK( c.max_load_factor() == 0.75 );
431 
432     c.rehash(10);
433 }
434 
435 
436 template< class Container, class Data >
test_unique_container(Container & c,Data & d)437 void test_unique_container(Container & c, Data & d)
438 {
439     c.clear();
440     c.insert(d.begin(),d.end());
441     c.insert(*d.begin());
442     BOOST_CHECK( c.size() == d.size() );
443 }
444 
445 template< class Container, class Data >
test_non_unique_container(Container & c,Data & d)446 void test_non_unique_container(Container & c, Data & d)
447 {
448     c.clear();
449     c.insert(d.begin(),d.end());
450     c.insert(*d.begin());
451     BOOST_CHECK( c.size() == (d.size()+1) );
452 }
453 
454 
455 
456 template< class Bimap, class Data, class LeftData, class RightData >
test_basic_bimap(Bimap & b,const Data & d,const LeftData & ld,const RightData & rd)457 void test_basic_bimap( Bimap & b,
458                       const Data & d,
459                       const LeftData & ld, const RightData & rd)
460 {
461     using namespace boost::bimaps;
462 
463     test_container(b,d);
464 
465     BOOST_CHECK( & b.left  == & b.template by<member_at::left >() );
466     BOOST_CHECK( & b.right == & b.template by<member_at::right>() );
467 
468     test_container(b.left , ld);
469     test_container(b.right, rd);
470 }
471 
472 template< class LeftTag, class RightTag, class Bimap, class Data >
test_tagged_bimap(Bimap & b,const Data & d)473 void test_tagged_bimap(Bimap & b,
474                        const Data & d)
475 {
476     using namespace boost::bimaps;
477 
478     BOOST_CHECK( &b.left  == & b.template by<LeftTag >() );
479     BOOST_CHECK( &b.right == & b.template by<RightTag>() );
480 
481     b.clear();
482     b.insert( *d.begin() );
483 
484     BOOST_CHECK(
485         b.begin()->template get<LeftTag>() ==
486             b.template by<RightTag>().begin()->template get<LeftTag>()
487     );
488 
489     BOOST_CHECK(
490         b.begin()->template get<RightTag>() ==
491             b.template by<LeftTag>().begin()->template get<RightTag>()
492     );
493 
494     // const test
495     {
496 
497     const Bimap & bc = b;
498 
499     BOOST_CHECK( &bc.left  == & bc.template by<LeftTag>() );
500     BOOST_CHECK( &bc.right == & bc.template by<RightTag>() );
501 
502     BOOST_CHECK( bc.begin()->template get<LeftTag>() ==
503                     bc.template by<RightTag>().begin()->template get<LeftTag>() );
504 
505     BOOST_CHECK( bc.begin()->template get<RightTag>() ==
506                     bc.template by<LeftTag>().begin()->template get<RightTag>() );
507     }
508 }
509 
510 
511 template< class Bimap, class Data, class LeftData, class RightData >
test_set_set_bimap(Bimap & b,const Data & d,const LeftData & ld,const RightData & rd)512 void test_set_set_bimap(Bimap & b,
513                         const Data & d,
514                         const LeftData & ld, const RightData & rd)
515 {
516     using namespace boost::bimaps;
517 
518     test_basic_bimap(b,d,ld,rd);
519 
520     test_associative_container(b,d);
521     test_simple_ordered_associative_container(b,d);
522 
523     test_pair_associative_container(b.left, ld);
524     test_pair_ordered_associative_container(b.left, ld);
525     test_unique_container(b.left, ld);
526 
527     test_pair_associative_container(b.right, rd);
528     test_pair_ordered_associative_container(b.right, rd);
529     test_unique_container(b.right, rd);
530 
531 }
532 
533 
534 template< class Bimap, class Data, class LeftData, class RightData >
test_multiset_multiset_bimap(Bimap & b,const Data & d,const LeftData & ld,const RightData & rd)535 void test_multiset_multiset_bimap(Bimap & b,
536                                   const Data & d,
537                                   const LeftData & ld, const RightData & rd)
538 {
539     using namespace boost::bimaps;
540 
541     test_basic_bimap(b,d,ld,rd);
542     test_associative_container(b,d);
543     test_simple_ordered_associative_container(b,d);
544 
545     test_pair_associative_container(b.left, ld);
546     test_pair_ordered_associative_container(b.left, ld);
547     test_non_unique_container(b.left, ld);
548 
549     test_pair_associative_container(b.right, rd);
550     test_pair_ordered_associative_container(b.right, rd);
551     test_non_unique_container(b.right, rd);
552 }
553 
554 template< class Bimap, class Data, class LeftData, class RightData >
test_unordered_set_unordered_multiset_bimap(Bimap & b,const Data & d,const LeftData & ld,const RightData & rd)555 void test_unordered_set_unordered_multiset_bimap(Bimap & b,
556                                                  const Data & d,
557                                                  const LeftData & ld,
558                                                  const RightData & rd)
559 {
560     using namespace boost::bimaps;
561 
562     test_basic_bimap(b,d,ld,rd);
563     test_associative_container(b,d);
564     test_simple_unordered_associative_container(b,d);
565 
566     test_pair_associative_container(b.left, ld);
567     test_pair_unordered_associative_container(b.left, ld);
568     test_unique_container(b.left, ld);
569 
570     test_pair_associative_container(b.right, rd);
571     test_pair_unordered_associative_container(b.right, rd);
572 
573     // Caution, this side is a non unique container, but the other side is a
574     // unique container so, the overall bimap is a unique one.
575     test_unique_container(b.right, rd);
576 }
577 
578 template< class Bimap, class Data>
test_bimap_init_copy_swap(const Data & d)579 void test_bimap_init_copy_swap(const Data&d)
580 {
581     Bimap b1(d.begin(),d.end());
582     Bimap b2( b1 );
583     BOOST_CHECK( b1 == b2 );
584 
585     b2.clear();
586     b2 = b1;
587     BOOST_CHECK( b2 == b1 );
588 
589     b2.clear();
590     b2.left = b1.left;
591     BOOST_CHECK( b2 == b1 );
592 
593     b2.clear();
594     b2.right = b1.right;
595     BOOST_CHECK( b2 == b1 );
596 
597     b1.clear();
598     b2.swap(b1);
599     BOOST_CHECK( b2.empty() && !b1.empty() );
600 
601     b1.left.swap( b2.left );
602     BOOST_CHECK( b1.empty() && !b2.empty() );
603 
604     b1.right.swap( b2.right );
605     BOOST_CHECK( b2.empty() && !b1.empty() );
606 }
607 
608 #endif // LIBS_BIMAP_TEST_BIMAP_TEST_HPP
609 
610