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