• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Boost.Pointer Container
3 //
4 //  Copyright Thorsten Ottosen 2008. Use, modification and
5 //  distribution is subject to the Boost Software License, Version
6 //  1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 //  http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // For more information, see http://www.boost.org/libs/ptr_container/
10 //
11 
12 #include "test_data.hpp"
13 #include <boost/test/unit_test.hpp>
14 #include <boost/ptr_container/exception.hpp>
15 #include <boost/ptr_container/detail/ptr_container_disable_deprecated.hpp>
16 #include <boost/range/sub_range.hpp>
17 #include <boost/cast.hpp>
18 #include <cstdlib>
19 #include <iostream>
20 #include <memory>
21 #include <string>
22 
23 //
24 // abstract base class definition
25 //
26 struct abstract_base
27 {
~abstract_baseabstract_base28     virtual ~abstract_base() {}
29     virtual void foo() = 0;
30     virtual abstract_base* clone() const = 0;
31 };
32 
33 struct implementation : abstract_base
34 {
implementationimplementation35     implementation()
36     { }
37 
implementationimplementation38     implementation( const implementation& )
39     { }
40 
implementationimplementation41     implementation( int, std::string, int, std::string )
42     { }
43 
fooimplementation44     virtual void foo() {}
cloneimplementation45     virtual abstract_base* clone() const
46     {
47         return new implementation( *this );
48     }
49 };
50 
operator <<(std::ostream & out,const abstract_base & r)51 inline std::ostream& operator<<( std::ostream& out, const abstract_base& r )
52 {
53     return out;
54 }
55 
new_clone(const abstract_base & r)56 inline abstract_base* new_clone( const abstract_base& r )
57 {
58     return r.clone();
59 }
60 
hash_value(const abstract_base & b)61 inline std::size_t hash_value( const abstract_base& b )
62 {
63     return boost::hash_value( &b );
64 }
65 
66 //
67 // ptr_map test
68 //
69 
70 template< typename C, typename B, typename T >
71 void ptr_map_test();
72 
73 template< class Key >
74 Key get_next_key( const Key& k );
75 
76 template<>
get_next_key(const int &)77 int get_next_key<int>( const int& )
78 {
79     return rand();
80 }
81 
82 template<>
get_next_key(const std::string &)83 std::string get_next_key<std::string>( const std::string& )
84 {
85     return boost::lexical_cast<std::string>( rand() );
86 }
87 
88 
89 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
90 #pragma GCC diagnostic push
91 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
92 #endif
93 
94 template< typename C, typename B, typename T >
ptr_map_test()95 void ptr_map_test()
96 {
97     using namespace boost;
98 
99     BOOST_TEST_MESSAGE( "starting associative container test" );
100     enum { max_cnt = 10, size = 100 };
101     C  c;
102     BOOST_CHECK( c.size() == 0 );
103 
104     const C c2( c.begin(), c.end() );
105     BOOST_CHECK( c.size() == c2.size() );
106 
107     C c3;
108 
109     BOOST_TEST_MESSAGE( "finished construction test" );
110 
111     BOOST_DEDUCED_TYPENAME C::allocator_type alloc        = c.get_allocator();
112     BOOST_DEDUCED_TYPENAME C::iterator i                  = c.begin();
113     BOOST_DEDUCED_TYPENAME C::const_iterator ci           = c2.begin();
114     BOOST_DEDUCED_TYPENAME C::iterator i2                 = c.end();
115     hide_warning(i2);
116     BOOST_DEDUCED_TYPENAME C::const_iterator ci2          = c2.begin();
117     hide_warning(ci2);
118     ci = c.cbegin();
119     ci = c.cend();
120 
121     BOOST_DEDUCED_TYPENAME C::key_type a_key;
122 
123     BOOST_TEST_MESSAGE( "finished iterator test" );
124 
125     BOOST_DEDUCED_TYPENAME C::size_type s                 = c.size();
126     BOOST_DEDUCED_TYPENAME C::size_type s2                = c.max_size();
127     hide_warning(s2);
128     BOOST_CHECK_EQUAL( c.size(), s );
129     bool b                                                = c.empty();
130     hide_warning(b);
131     BOOST_TEST_MESSAGE( "finished accessors test" );
132 
133     a_key = get_next_key( a_key );
134     c.insert( a_key, new T );
135     a_key = get_next_key( a_key );
136     c.insert( a_key, new T );
137     c3.insert( c.begin(), c.end() );
138     c.insert( c3 );
139     c.erase( c.begin() );
140     BOOST_CHECK( c3.end() == c3.erase( boost::make_iterator_range(c3) ) );
141     c3.erase( a_key );
142 
143     BOOST_CHECK( c3.empty() );
144     c.swap( c3 );
145     swap(c,c3);
146     swap(c3,c);
147     BOOST_CHECK( !c3.empty() );
148     c3.clear();
149     BOOST_CHECK( c3.empty() );
150     BOOST_TEST_MESSAGE( "finished modifiers test" );
151 
152 
153     a_key = get_next_key( a_key );
154     c.insert( a_key, new T );
155     a_key = get_next_key( a_key );
156 #ifndef BOOST_NO_AUTO_PTR
157     c.insert( a_key, std::auto_ptr<T>( new T ) );
158 #endif
159 #ifndef BOOST_NO_CXX11_SMART_PTR
160     c.insert( a_key, std::unique_ptr<T>( new T ) );
161 #endif
162     typename C::auto_type ptr2  = c.release( c.begin() );
163 #ifndef BOOST_NO_AUTO_PTR
164     std::auto_ptr<C> ap         = c.release();
165 #else
166     std::unique_ptr<C> up       = c.release();
167 #endif
168     c                           = c2.clone();
169     BOOST_TEST_MESSAGE( "finished release/clone test" );
170 
171 
172     a_key = get_next_key( a_key );
173     c3.insert( a_key, new T );
174     a_key = get_next_key( a_key );
175     c3.insert( a_key, new T );
176 
177     c. BOOST_NESTED_TEMPLATE transfer<C>( c3.begin(), c3 );
178     c. BOOST_NESTED_TEMPLATE transfer<C>( c3.begin(), c3.end(), c3 );
179     BOOST_CHECK( c3.empty() );
180     BOOST_CHECK( !c.empty() );
181     c3. BOOST_NESTED_TEMPLATE transfer<C>( c );
182     BOOST_CHECK( !c3.empty() );
183     BOOST_CHECK( c.empty() );
184 #ifdef BOOST_NO_SFINAE
185 #else
186     c. BOOST_NESTED_TEMPLATE transfer<C>( make_iterator_range(c3), c3 );
187     BOOST_CHECK( !c.empty() );
188     BOOST_CHECK( c3.empty() );
189     c3. BOOST_NESTED_TEMPLATE transfer<C>(c);
190 #endif
191     BOOST_TEST_MESSAGE( "finished transfer test" );
192 
193     BOOST_CHECK( !c3.empty() );
194     c3.replace( c3.begin(), new T );
195 #ifndef BOOST_NO_AUTO_PTR
196     c3.replace( c3.begin(), std::auto_ptr<T>( new T ) );
197 #endif
198 #ifndef BOOST_NO_CXX11_SMART_PTR
199     c3.replace( c3.begin(), std::unique_ptr<T>( new T ) );
200 #endif
201     BOOST_TEST_MESSAGE( "finished set/map interface test" );
202 
203     // @todo: make macro with algorithms so that the right erase() is called.
204     //  c.unique();
205     //  c.unique( std::not_equal_to<T>() );
206     //  c.remove( T() );
207     //  c.remove_if( std::binder1st< std::equal_to<T> >( T() ) );
208 
209     sub_range<C>        sub;
210     sub_range<const C> csub;
211 
212     i  = c.find( get_next_key( a_key ) );
213     ci = c2.find( get_next_key( a_key ) );
214     c2.count( get_next_key( a_key ) );
215     sub  = c.equal_range( get_next_key( a_key ) );
216     csub = c2.equal_range( get_next_key( a_key ) );
217 
218     try
219     {
220         c.at( get_next_key( a_key ) );
221     }
222     catch( const bad_ptr_container_operation& )
223     { }
224 
225     try
226     {
227         c2.at( get_next_key( a_key ) );
228     }
229     catch( const bad_ptr_container_operation& )
230     { }
231 
232     BOOST_TEST_MESSAGE( "finished algorithms interface test" );
233 
234     typename C::iterator it = c.begin(), e = c.end();
235     for( ; it != e; ++it )
236     {
237         std::cout << "\n mapped value = " << *it->second << " key = " << it->first;
238         //std::cout << "\n mapped value = " << it.value() << " key = " << it.key();
239     }
240 
241     BOOST_TEST_MESSAGE( "finished iterator test" );
242 
243     a_key = get_next_key( a_key );
244     c.insert( a_key, new T );
245     c.erase( a_key );
246     c.erase( a_key );
247 
248 }
249 
250 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
251 #pragma GCC diagnostic pop
252 #endif
253 
254 
255 template< class CDerived, class CBase, class T >
test_transfer()256 void test_transfer()
257 {
258     CDerived from;
259     CBase    to;
260 
261     int key = get_next_key( key );
262     from.insert( key, new T );
263     key = get_next_key( key );
264     from.insert( key, new T );
265     transfer_test( from, to );
266 }
267 
268 
269 
270 template< class BaseContainer, class DerivedContainer, class Derived >
map_container_assignment_test()271 void map_container_assignment_test()
272 {
273     DerivedContainer derived;
274     std::string foo( "foo" );
275     std::string bar( "foo" );
276     derived.insert( foo, new Derived );
277     derived.insert( bar, new Derived );
278 
279     BaseContainer base_container( derived );
280     BOOST_CHECK_EQUAL( derived.size(), base_container.size() );
281     base_container.clear();
282     base_container = derived;
283     BOOST_CHECK_EQUAL( derived.size(), base_container.size() );
284 
285     BaseContainer base2( base_container );
286     BOOST_CHECK_EQUAL( base2.size(), base_container.size() );
287     base2 = base_container;
288     BOOST_CHECK_EQUAL( base2.size(), base_container.size() );
289     base_container = base_container;
290 }
291 
292 
293 
294 template< class Cont, class Key, class T >
test_unordered_interface()295 void test_unordered_interface()
296 {
297     Cont c;
298     T* t = new T;
299     Key key = get_next_key( key );
300     c.insert( key, t );
301     typename Cont::local_iterator i = c.begin( 0 );
302     typename Cont::const_local_iterator ci = i;
303     ci = c.cbegin( 0 );
304     i = c.end( 0 );
305     ci = c.cend( 0 );
306     typename Cont::size_type s = c.bucket_count();
307     hide_warning(s);
308     s = c.max_bucket_count();
309     s = c.bucket_size( 0 );
310     s = c.bucket( key );
311     float f = c.load_factor();
312     f       = c.max_load_factor();
313     c.max_load_factor(f);
314     c.rehash(1000);
315 }
316 
317 #include <boost/ptr_container/ptr_unordered_map.hpp>
318 
319 using namespace std;
320 
test_map()321 void test_map()
322 {
323     ptr_map_test< ptr_unordered_map<int, Base>, Base, Derived_class >();
324     ptr_map_test< ptr_unordered_map<int, Value>, Value, Value >();
325     ptr_map_test< ptr_unordered_map<int, nullable<Base> >, Base, Derived_class >();
326     ptr_map_test< ptr_unordered_map<int, nullable<Value> >, Value, Value >();
327     ptr_map_test< ptr_unordered_map<int, abstract_base>, abstract_base, implementation >();
328 
329     ptr_map_test< ptr_unordered_multimap<int,Base>, Base, Derived_class >();
330     ptr_map_test< ptr_unordered_multimap<int,Value>, Value, Value >();
331     ptr_map_test< ptr_unordered_multimap<int, nullable<Base> >, Base, Derived_class >();
332     ptr_map_test< ptr_unordered_multimap<int, nullable<Value> >, Value, Value >();
333 
334     map_container_assignment_test< ptr_unordered_map<std::string,Base>,
335                                    ptr_unordered_map<std::string,Derived_class>,
336                                    Derived_class>();
337     map_container_assignment_test< ptr_unordered_map<std::string, nullable<Base> >,
338                                    ptr_unordered_map<std::string,Derived_class>,
339                                    Derived_class>();
340     map_container_assignment_test< ptr_unordered_map<std::string, nullable<Base> >,
341                                    ptr_unordered_map<std::string, nullable<Derived_class> >,
342                                    Derived_class>();
343    map_container_assignment_test< ptr_unordered_multimap<std::string,Base>,
344                                    ptr_unordered_multimap<std::string,Derived_class>,
345                                    Derived_class>();
346     map_container_assignment_test< ptr_unordered_multimap<std::string, nullable<Base> >,
347                                    ptr_unordered_multimap<std::string,Derived_class>,
348                                    Derived_class>();
349     map_container_assignment_test< ptr_unordered_multimap<std::string, nullable<Base> >,
350                                    ptr_unordered_multimap<std::string, nullable<Derived_class> >,
351                                    Derived_class>();
352 
353 
354     test_transfer< ptr_unordered_map<int,Derived_class>, ptr_unordered_map<int,Base>, Derived_class >();
355     test_transfer< ptr_unordered_multimap<int,Derived_class>, ptr_unordered_multimap<int,Base>, Derived_class >();
356 
357     string joe   = "joe";
358     string brian = "brian";
359     string kenny = "kenny";
360 
361     ptr_unordered_map<string,int> m;
362     m.insert( joe, new int( 4 ) );
363     m.insert( brian, new int( 6 ) );
364     BOOST_CHECK( m[ "foo" ] == 0 );
365     m[ "bar" ] += 5;
366     BOOST_CHECK( m[ "bar" ] == 5 );
367     m[ joe ]   += 56;
368     m[ brian ] += 10;
369 
370     BOOST_CHECK_THROW( (m.insert(kenny, 0 )), bad_ptr_container_operation );
371     BOOST_CHECK_THROW( (m.replace(m.begin(), 0 )), bad_ptr_container_operation );
372     BOOST_CHECK_THROW( (m.at("not there")), bad_ptr_container_operation );
373 
374     for( ptr_unordered_map<string,int>::iterator i = m.begin();
375          i != m.end(); ++i )
376     {
377         if( is_null(i) )
378             BOOST_CHECK( false );
379         const string& ref  = i->first;
380         hide_warning(ref);
381         int&          ref2 = *(*i).second;
382         ref2++;
383     }
384 
385     typedef ptr_unordered_map<string,Derived_class> map_type;
386     map_type m2;
387     m2.insert( joe, new Derived_class );
388     //
389     // This works fine since 'm2' is not const
390     //
391     m2.begin()->second->foo();
392 
393     //
394     // These all return an implementation-defined proxy
395     // with two public members: 'first' and 'second'
396     //
397     map_type::value_type       a_value      = *m2.begin();
398     a_value.second->foo();
399     map_type::reference        a_reference  = *m2.begin();
400     a_reference.second->foo();
401     map_type::const_reference  a_creference = *const_begin(m2);
402     hide_warning(a_creference);
403 
404     //
405     //
406     // These will fail as iterators propagate constness
407     //
408     //a_creference.second->foo();
409     //a_cpointer->second->foo();
410     //const_begin(m2)->second->foo();
411 
412     test_unordered_interface< ptr_unordered_map<string,Base>, string, Derived_class >();
413     test_unordered_interface< ptr_unordered_map<string,Base>, string, Derived_class >();
414 }
415 
416 using boost::unit_test::test_suite;
417 
init_unit_test_suite(int argc,char * argv[])418 test_suite* init_unit_test_suite( int argc, char* argv[] )
419 {
420     test_suite* test = BOOST_TEST_SUITE( "Pointer Container Test Suite" );
421 
422     test->add( BOOST_TEST_CASE( &test_map ) );
423 
424     return test;
425 }
426