| 1 | // |
|---|
| 2 | // Boost.Pointer Container |
|---|
| 3 | // |
|---|
| 4 | // Copyright Thorsten Ottosen 2003-2005. 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 <boost/test/unit_test.hpp> |
|---|
| 13 | #include "test_data.hpp" |
|---|
| 14 | #include <boost/ptr_container/exception.hpp> |
|---|
| 15 | #include <boost/range/sub_range.hpp> |
|---|
| 16 | #include <boost/cast.hpp> |
|---|
| 17 | #include <cstdlib> |
|---|
| 18 | #include <string> |
|---|
| 19 | #include <iostream> |
|---|
| 20 | |
|---|
| 21 | template< typename C, typename B, typename T > |
|---|
| 22 | void ptr_map_test(); |
|---|
| 23 | |
|---|
| 24 | template< class Key > |
|---|
| 25 | Key get_next_key( const Key& k ); |
|---|
| 26 | |
|---|
| 27 | template<> |
|---|
| 28 | int get_next_key<int>( const int& ) |
|---|
| 29 | { |
|---|
| 30 | return rand(); |
|---|
| 31 | } |
|---|
| 32 | |
|---|
| 33 | template<> |
|---|
| 34 | std::string get_next_key<std::string>( const std::string& ) |
|---|
| 35 | { |
|---|
| 36 | return boost::lexical_cast<std::string>( rand() ); |
|---|
| 37 | } |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | template< typename C, typename B, typename T > |
|---|
| 41 | void ptr_map_test() |
|---|
| 42 | { |
|---|
| 43 | using namespace boost; |
|---|
| 44 | |
|---|
| 45 | BOOST_MESSAGE( "starting associative container test" ); |
|---|
| 46 | enum { max_cnt = 10, size = 100 }; |
|---|
| 47 | C c; |
|---|
| 48 | BOOST_CHECK( c.size() == 0 ); |
|---|
| 49 | |
|---|
| 50 | const C c2( c.begin(), c.end() ); |
|---|
| 51 | BOOST_CHECK( c.size() == c2.size() ); |
|---|
| 52 | |
|---|
| 53 | C c3; |
|---|
| 54 | |
|---|
| 55 | BOOST_MESSAGE( "finished construction test" ); |
|---|
| 56 | |
|---|
| 57 | BOOST_DEDUCED_TYPENAME C::allocator_type alloc = c.get_allocator(); |
|---|
| 58 | BOOST_DEDUCED_TYPENAME C::iterator i = c.begin(); |
|---|
| 59 | BOOST_DEDUCED_TYPENAME C::const_iterator ci = c2.begin(); |
|---|
| 60 | BOOST_DEDUCED_TYPENAME C::iterator i2 = c.end(); |
|---|
| 61 | BOOST_DEDUCED_TYPENAME C::const_iterator ci2 = c2.begin(); |
|---|
| 62 | BOOST_DEDUCED_TYPENAME C::reverse_iterator ri = c.rbegin(); |
|---|
| 63 | BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cri = c2.rbegin(); |
|---|
| 64 | BOOST_DEDUCED_TYPENAME C::reverse_iterator rv2 = c.rend(); |
|---|
| 65 | BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cvr2 = c2.rend(); |
|---|
| 66 | |
|---|
| 67 | BOOST_DEDUCED_TYPENAME C::key_type a_key; |
|---|
| 68 | |
|---|
| 69 | BOOST_MESSAGE( "finished iterator test" ); |
|---|
| 70 | |
|---|
| 71 | BOOST_DEDUCED_TYPENAME C::size_type s = c.size(); |
|---|
| 72 | BOOST_DEDUCED_TYPENAME C::size_type s2 = c.max_size(); |
|---|
| 73 | hide_warning(s2); |
|---|
| 74 | BOOST_CHECK_EQUAL( c.size(), s ); |
|---|
| 75 | bool b = c.empty(); |
|---|
| 76 | hide_warning(b); |
|---|
| 77 | BOOST_MESSAGE( "finished accessors test" ); |
|---|
| 78 | |
|---|
| 79 | a_key = get_next_key( a_key ); |
|---|
| 80 | c.insert( a_key, new T ); |
|---|
| 81 | a_key = get_next_key( a_key ); |
|---|
| 82 | c.insert( a_key, new T ); |
|---|
| 83 | c3.insert( c.begin(), c.end() ); |
|---|
| 84 | c.insert( c3 ); |
|---|
| 85 | c.erase( c.begin() ); |
|---|
| 86 | c3.erase( c3.begin(), c3.end() ); |
|---|
| 87 | |
|---|
| 88 | BOOST_CHECK( c3.empty() ); |
|---|
| 89 | c.swap( c3 ); |
|---|
| 90 | swap(c,c3); |
|---|
| 91 | swap(c3,c); |
|---|
| 92 | BOOST_CHECK( !c3.empty() ); |
|---|
| 93 | c3.clear(); |
|---|
| 94 | BOOST_CHECK( c3.empty() ); |
|---|
| 95 | BOOST_MESSAGE( "finished modifiers test" ); |
|---|
| 96 | |
|---|
| 97 | |
|---|
| 98 | a_key = get_next_key( a_key ); |
|---|
| 99 | c.insert( a_key, new T ); |
|---|
| 100 | a_key = get_next_key( a_key ); |
|---|
| 101 | c.insert( a_key, new T ); |
|---|
| 102 | typename C::auto_type ptr2 = c.release( c.begin() ); |
|---|
| 103 | std::auto_ptr<C> ap = c.release(); |
|---|
| 104 | c = c2.clone(); |
|---|
| 105 | BOOST_MESSAGE( "finished release/clone test" ); |
|---|
| 106 | |
|---|
| 107 | |
|---|
| 108 | a_key = get_next_key( a_key ); |
|---|
| 109 | c3.insert( a_key, new T ); |
|---|
| 110 | a_key = get_next_key( a_key ); |
|---|
| 111 | c3.insert( a_key, new T ); |
|---|
| 112 | |
|---|
| 113 | c.transfer( c3.begin(), c3 ); |
|---|
| 114 | c.transfer( c3.begin(), c3.end(), c3 ); |
|---|
| 115 | BOOST_CHECK( c3.empty() ); |
|---|
| 116 | BOOST_CHECK( !c.empty() ); |
|---|
| 117 | c3.transfer( c ); |
|---|
| 118 | BOOST_CHECK( !c3.empty() ); |
|---|
| 119 | BOOST_CHECK( c.empty() ); |
|---|
| 120 | #ifdef BOOST_NO_SFINAE |
|---|
| 121 | #else |
|---|
| 122 | c.transfer( make_iterator_range(c3), c3 ); |
|---|
| 123 | BOOST_CHECK( !c.empty() ); |
|---|
| 124 | BOOST_CHECK( c3.empty() ); |
|---|
| 125 | c3.transfer(c); |
|---|
| 126 | #endif |
|---|
| 127 | BOOST_MESSAGE( "finished transfer test" ); |
|---|
| 128 | |
|---|
| 129 | BOOST_CHECK( !c3.empty() ); |
|---|
| 130 | c3.replace( c3.begin(), new T ); |
|---|
| 131 | BOOST_MESSAGE( "finished set/map interface test" ); |
|---|
| 132 | |
|---|
| 133 | // @todo: make macro with algorithms so that the right erase() is called. |
|---|
| 134 | // c.unique(); |
|---|
| 135 | // c.unique( std::not_equal_to<T>() ); |
|---|
| 136 | // c.remove( T() ); |
|---|
| 137 | // c.remove_if( std::binder1st< std::equal_to<T> >( T() ) ); |
|---|
| 138 | |
|---|
| 139 | sub_range<C> sub; |
|---|
| 140 | sub_range<const C> csub; |
|---|
| 141 | |
|---|
| 142 | i = c.find( get_next_key( a_key ) ); |
|---|
| 143 | ci = c2.find( get_next_key( a_key ) ); |
|---|
| 144 | c2.count( get_next_key( a_key ) ); |
|---|
| 145 | i = c.lower_bound( get_next_key( a_key ) ); |
|---|
| 146 | ci = c2.lower_bound( get_next_key( a_key ) ); |
|---|
| 147 | i = c.upper_bound( get_next_key( a_key ) ); |
|---|
| 148 | ci = c2.upper_bound( get_next_key( a_key ) ); |
|---|
| 149 | sub = c.equal_range( get_next_key( a_key ) ); |
|---|
| 150 | csub = c2.equal_range( get_next_key( a_key ) ); |
|---|
| 151 | |
|---|
| 152 | try |
|---|
| 153 | { |
|---|
| 154 | c.at( get_next_key( a_key ) ); |
|---|
| 155 | } |
|---|
| 156 | catch( const bad_ptr_container_operation& ) |
|---|
| 157 | { } |
|---|
| 158 | |
|---|
| 159 | try |
|---|
| 160 | { |
|---|
| 161 | c2.at( get_next_key( a_key ) ); |
|---|
| 162 | } |
|---|
| 163 | catch( const bad_ptr_container_operation& ) |
|---|
| 164 | { } |
|---|
| 165 | |
|---|
| 166 | BOOST_MESSAGE( "finished algorithms interface test" ); |
|---|
| 167 | |
|---|
| 168 | typename C::iterator it = c.begin(), e = c.end(); |
|---|
| 169 | for( ; it != e; ++it ) |
|---|
| 170 | { |
|---|
| 171 | std::cout << "\n mapped value = " << *it << " key = " << i.key(); |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | BOOST_MESSAGE( "finished iterator test" ); |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | |
|---|
| 178 | #include <boost/ptr_container/ptr_map.hpp> |
|---|
| 179 | |
|---|
| 180 | using namespace std; |
|---|
| 181 | |
|---|
| 182 | void test_map() |
|---|
| 183 | { |
|---|
| 184 | ptr_map_test< ptr_map<int, Base>, Base, Derived_class >(); |
|---|
| 185 | ptr_map_test< ptr_map<int, Value>, Value, Value >(); |
|---|
| 186 | ptr_map_test< ptr_map<int, nullable<Base> >, Base, Derived_class >(); |
|---|
| 187 | ptr_map_test< ptr_map<int, nullable<Value> >, Value, Value >(); |
|---|
| 188 | |
|---|
| 189 | ptr_map_test< ptr_multimap<int,Base>, Base, Derived_class >(); |
|---|
| 190 | ptr_map_test< ptr_multimap<int,Value>, Value, Value >(); |
|---|
| 191 | ptr_map_test< ptr_multimap<int, nullable<Base> >, Base, Derived_class >(); |
|---|
| 192 | ptr_map_test< ptr_multimap<int, nullable<Value> >, Value, Value >(); |
|---|
| 193 | |
|---|
| 194 | string joe = "joe"; |
|---|
| 195 | string brian = "brian"; |
|---|
| 196 | string kenny = "kenny"; |
|---|
| 197 | |
|---|
| 198 | ptr_map<string,int> m; |
|---|
| 199 | m.insert( joe, new int( 4 ) ); |
|---|
| 200 | m.insert( brian, new int( 6 ) ); |
|---|
| 201 | BOOST_CHECK( m[ "foo" ] == 0 ); |
|---|
| 202 | m[ "bar" ] += 5; |
|---|
| 203 | BOOST_CHECK( m[ "bar" ] == 5 ); |
|---|
| 204 | m[ joe ] += 56; |
|---|
| 205 | m[ brian ] += 10; |
|---|
| 206 | |
|---|
| 207 | BOOST_CHECK_THROW( (m.insert(kenny, 0 )), bad_ptr_container_operation ); |
|---|
| 208 | BOOST_CHECK_THROW( (m.replace(m.begin(), 0 )), bad_ptr_container_operation ); |
|---|
| 209 | BOOST_CHECK_THROW( (m.at("not there")), bad_ptr_container_operation ); |
|---|
| 210 | |
|---|
| 211 | for( ptr_map<string,int>::iterator i = m.begin(); |
|---|
| 212 | i != m.end(); ++i ) |
|---|
| 213 | { |
|---|
| 214 | if( is_null(i) ) |
|---|
| 215 | BOOST_CHECK( false ); |
|---|
| 216 | const string& ref = i.key(); |
|---|
| 217 | hide_warning(ref); |
|---|
| 218 | int& ref2 = *i; |
|---|
| 219 | ref2++; |
|---|
| 220 | } |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | using boost::unit_test::test_suite; |
|---|
| 224 | |
|---|
| 225 | test_suite* init_unit_test_suite( int argc, char* argv[] ) |
|---|
| 226 | { |
|---|
| 227 | test_suite* test = BOOST_TEST_SUITE( "Pointer Container Test Suite" ); |
|---|
| 228 | |
|---|
| 229 | test->add( BOOST_TEST_CASE( &test_map ) ); |
|---|
| 230 | |
|---|
| 231 | return test; |
|---|
| 232 | } |
|---|
| 233 | |
|---|
| 234 | |
|---|
| 235 | |
|---|
| 236 | |
|---|
| 237 | |
|---|
| 238 | |
|---|
| 239 | |
|---|