libmoost
/home/mhx/git/github/libmoost/test/container/multi_map.cpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 // TODO: compression has not been tested yet!
00029 
00030 #include <boost/test/unit_test.hpp>
00031 #include <boost/test/test_tools.hpp>
00032 #include <boost/cstdint.hpp>
00033 
00034 #include <vector>
00035 #include <map>
00036 #include <set>
00037 
00038 #include "../../include/moost/container/multi_map.hpp"
00039 
00040 #include "../../include/moost/container/policies/dense_hash_map.hpp"
00041 #include "../../include/moost/container/policies/sparse_hash_map.hpp"
00042 #include "../../include/moost/container/policies/vector_map.hpp"
00043 
00044 using namespace moost::container;
00045 using namespace std;
00046 
00047 BOOST_AUTO_TEST_SUITE( multi_map_test )
00048 
00049 template <typename TMultiMap>
00050 struct Fixture_generic
00051 {
00052    typedef TMultiMap multi_map_type;
00053 
00054    template< int WhichKey, typename TKey, typename TVal >
00055    void create_data(multi_map_type& map, TKey num_keys, TVal num_val)
00056    {
00057 
00058       vector< pair<TKey, TVal> > vec;
00059 
00060       if ( WhichKey == 1 )
00061       {
00062          for ( TKey k = 0; k < num_keys; ++k )
00063          {
00064             for ( TVal v = 0; v < num_val; ++v )
00065                vec.push_back( make_pair(k, v) );
00066          }
00067       }
00068       else
00069       {
00070          for ( TVal v = 0; v < num_val; ++v )
00071          {
00072             for ( TKey k = 0; k < num_keys; ++k )
00073                vec.push_back( make_pair(k, v) );
00074          }
00075       }
00076 
00077       map.template create_map<WhichKey>(vec);
00078    }
00079 
00080    void check_map( multi_map_type& map,
00081                    typename multi_map_type::first_type num_keys,
00082                    typename multi_map_type::second_type num_val)
00083    {
00084       // how many keys?
00085       BOOST_CHECK_EQUAL( map.size(), num_keys );
00086 
00087       std::set<typename multi_map_type::first_type> retrieved_keys;
00088       typename std::set<typename multi_map_type::first_type>::const_iterator rkIt;
00089 
00090       typename multi_map_type::first_type key;
00091       typename multi_map_type::second_type val;
00092 
00093       // const
00094       {
00095          const multi_map_type& cmap = map; // take a const to simulate passing by const
00096 
00097          // try to get a key that does NOT exist
00098          typename multi_map_type::const_range rt = cmap[num_keys+1];
00099          BOOST_CHECK( rt.empty() ); // not found!
00100 
00101          typename multi_map_type::const_range_iterator cmRangeIt;
00102          typename multi_map_type::second_type val;
00103 
00104          // checking getting a range from key
00105          for ( typename multi_map_type::first_type k = 0; k < num_keys; ++k )
00106          {
00107             // get the range for key 'k'
00108             rt = cmap[k];
00109             BOOST_CHECK( !rt.empty() );
00110             BOOST_CHECK_EQUAL( rt.size(), num_val );
00111 
00112             val = 0;
00113             // check each value associated to key 'k'
00114             for ( cmRangeIt = rt.begin(); cmRangeIt != rt.end(); ++cmRangeIt, ++val )
00115                BOOST_CHECK_EQUAL( *cmRangeIt, val );
00116          }
00117 
00118          // checking the available keys
00119          typename multi_map_type::const_iterator cmIt;
00120          for ( cmIt = cmap.begin(); cmIt != cmap.end(); ++cmIt )
00121          {
00122             retrieved_keys.insert(cmIt->first);
00123             BOOST_CHECK_EQUAL( cmIt->second.size(), num_val );
00124          }
00125 
00126          BOOST_CHECK_EQUAL(retrieved_keys.size(), num_keys);
00127          key = 0;
00128          for ( rkIt = retrieved_keys.begin(); rkIt != retrieved_keys.end(); ++rkIt, ++key )
00129             BOOST_CHECK_EQUAL( *rkIt, key );
00130       }
00131 
00132       // non const
00133       {
00134          // try to get a key that does NOT exist
00135          typename multi_map_type::range rt = map[num_keys+1];
00136          BOOST_CHECK( rt.empty() ); // not found!
00137 
00138          typename multi_map_type::range_iterator mRangeIt;
00139 
00140          for ( typename multi_map_type::first_type k = 0; k < num_keys; ++k )
00141          {
00142             // get the range for key 'k'
00143             rt = map[k];
00144             BOOST_CHECK( !rt.empty() );
00145             BOOST_CHECK_EQUAL( rt.size(), num_val );
00146 
00147             val = 0;
00148             // check each value associated to key 'k'
00149             for ( mRangeIt = rt.begin(); mRangeIt != rt.end(); ++mRangeIt, ++val )
00150                BOOST_CHECK_EQUAL( *mRangeIt, val );
00151          }
00152 
00153          // checking the available keys
00154          typename multi_map_type::iterator mIt;
00155          retrieved_keys.clear();
00156          for ( mIt = map.begin(); mIt != map.end(); ++mIt )
00157          {
00158             retrieved_keys.insert(mIt->first);
00159             BOOST_CHECK_EQUAL( mIt->second.size(), num_val );
00160          }
00161 
00162          BOOST_CHECK_EQUAL(retrieved_keys.size(), num_keys);
00163          key = 0;
00164          for ( rkIt = retrieved_keys.begin(); rkIt != retrieved_keys.end(); ++rkIt, ++key )
00165             BOOST_CHECK_EQUAL( *rkIt, key );
00166       }
00167    }
00168 
00169 };
00170 
00171 struct Fixture_default : public Fixture_generic< multi_map<int, boost::int8_t>  >
00172 {
00173    // using dense hash map
00174    // empty key is -1
00175    // initialized with bucket size of 1024
00176    Fixture_default()
00177       : m_map( multi_map_type::loc_map_policy_type(-1, 1024) )
00178    {}
00179 
00180    multi_map_type m_map;
00181 };
00182 
00183 BOOST_FIXTURE_TEST_CASE( test_default, Fixture_default )
00184 {
00185    multi_map_type::first_type num_keys = 5;
00186    multi_map_type::second_type num_vals = 10;
00187 
00188    // key on first
00189    create_data<1>( m_map, num_keys, num_vals );
00190    check_map(m_map, num_keys, num_vals);
00191 
00192    m_map.clear();
00193    BOOST_CHECK( m_map.empty() );
00194 
00195    create_data<2>( m_map, num_keys, num_vals );
00196 
00197    // key on second
00198    check_map( m_map, num_vals, num_keys );
00199 }
00200 
00201 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
00202 
00203 struct Fixture_dense : public Fixture_generic<
00204                               multi_map< int,
00205                                          boost::int8_t,
00206                                          moost::container::dense_hash_map< int, multimap_value_type >
00207                                        > >
00208 {
00209    // using dense hash map
00210    // empty key is -1
00211    // initialized with bucket size of 1024
00212    Fixture_dense()
00213       : m_map( multi_map_type::loc_map_policy_type(-1, 1024) )
00214    {}
00215 
00216    multi_map_type m_map;
00217 };
00218 
00219 // just check if it compiles
00220 BOOST_FIXTURE_TEST_CASE( test_dense, Fixture_dense )
00221 {
00222    multi_map_type::first_type num_keys = 5;
00223    multi_map_type::second_type num_vals = 10;
00224 
00225    // key on first
00226    create_data<1>( m_map, num_keys, num_vals );
00227    check_map(m_map, num_keys, num_vals);
00228 
00229    m_map.clear();
00230    BOOST_CHECK( m_map.empty() );
00231 
00232    create_data<2>( m_map, num_keys, num_vals );
00233 
00234    // key on second
00235    check_map( m_map, num_vals, num_keys );
00236 }
00237 
00238 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
00239 
00240 struct Fixture_sparse : public Fixture_generic<
00241                               multi_map< int,
00242                                          boost::int8_t,
00243                                          moost::container::sparse_hash_map< int, multimap_value_type >
00244                                        > >
00245 {
00246    // using sparse hash map
00247    // initialized with bucket size of 1024
00248    Fixture_sparse()
00249       : m_map( multi_map_type::loc_map_policy_type(1024) )
00250    {}
00251 
00252    multi_map_type m_map;
00253 };
00254 
00255 // just check if it compiles
00256 BOOST_FIXTURE_TEST_CASE( test_sparse, Fixture_sparse )
00257 {
00258    multi_map_type::first_type num_keys = 5;
00259    multi_map_type::second_type num_vals = 10;
00260 
00261    // key on first
00262    create_data<1>( m_map, num_keys, num_vals );
00263    check_map(m_map, num_keys, num_vals);
00264 
00265    m_map.clear();
00266    BOOST_CHECK( m_map.empty() );
00267 
00268    create_data<2>( m_map, num_keys, num_vals );
00269 
00270    // key on second
00271    check_map( m_map, num_vals, num_keys );
00272 }
00273 
00274 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
00275 
00276 struct Fixture_stl_map : public Fixture_generic<
00277                               multi_map< int,
00278                                          boost::int8_t,
00279                                          std::map< int, multimap_value_type >
00280                                        > >
00281 {
00282    // using sparse hash map
00283    // initialized with bucket size of 1024
00284    Fixture_stl_map()
00285    {}
00286 
00287    multi_map_type m_map;
00288 };
00289 
00290 // just check if it compiles
00291 BOOST_FIXTURE_TEST_CASE( test_stl_map, Fixture_stl_map )
00292 {
00293    multi_map_type::first_type num_keys = 5;
00294    multi_map_type::second_type num_vals = 10;
00295 
00296    // key on first
00297    create_data<1>( m_map, num_keys, num_vals );
00298    check_map(m_map, num_keys, num_vals);
00299 
00300    m_map.clear();
00301    BOOST_CHECK( m_map.empty() );
00302 
00303    create_data<2>( m_map, num_keys, num_vals );
00304 
00305    // key on second
00306    check_map( m_map, num_vals, num_keys );
00307 }
00308 
00309 
00310 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
00311 
00312 struct Fixture_map : public Fixture_generic<
00313                               multi_map< int,
00314                                          boost::int8_t,
00315                                          map<int, multimap_value_type>
00316                                        > >
00317 {
00318    // using a stl::map
00319    Fixture_map()
00320       : m_map( )
00321    {}
00322 
00323    multi_map_type m_map;
00324 };
00325 
00326 // just check if it compiles
00327 BOOST_FIXTURE_TEST_CASE( test_map, Fixture_map )
00328 {
00329    multi_map_type::first_type num_keys = 5;
00330    multi_map_type::second_type num_vals = 10;
00331 
00332    // key on first
00333    create_data<1>( m_map, num_keys, num_vals );
00334    check_map(m_map, num_keys, num_vals);
00335 
00336    m_map.clear();
00337    BOOST_CHECK( m_map.empty() );
00338 
00339    create_data<2>( m_map, num_keys, num_vals );
00340 
00341    // key on second
00342    check_map( m_map, num_vals, num_keys );
00343 }
00344 
00345 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
00346 
00347 struct Fixture_vector : public Fixture_generic<
00348                               multi_map< int,
00349                                          boost::int8_t,
00350                                          vector<multimap_value_type>
00351                                        > >
00352 {
00353    // using a vector
00354    // initialized with vector size of m_num_keys
00355    Fixture_vector()
00356       : m_num_keys(5), m_map( multi_map_type::loc_map_policy_type(m_num_keys) )
00357    {}
00358 
00359    multi_map_type::first_type m_num_keys;
00360    multi_map_type m_map;
00361 };
00362 
00363 // just check if it compiles
00364 BOOST_FIXTURE_TEST_CASE( test_vector1, Fixture_vector )
00365 {
00366    multi_map_type::second_type num_vals = 10;
00367 
00368    // key on first
00369    create_data<1>( m_map, m_num_keys, num_vals );
00370    check_map(m_map, m_num_keys, num_vals);
00371 
00372    m_map.clear();
00373    BOOST_CHECK( m_map.empty() );
00374 }
00375 
00376 // just check if it compiles
00377 BOOST_FIXTURE_TEST_CASE( test_vector2, Fixture_vector )
00378 {
00379    multi_map_type::second_type num_vals = 5; // must be the same size of the initialized one!
00380 
00381    create_data<2>( m_map, m_num_keys, num_vals );
00382    // key on second
00383    check_map( m_map, num_vals, m_num_keys );
00384 
00385    m_map.clear();
00386    BOOST_CHECK( m_map.empty() );
00387 }
00388 
00389 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
00390 
00391 BOOST_AUTO_TEST_SUITE_END()