libmoost
/home/mhx/git/github/libmoost/test/container/simple_multi_map.cpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 #include <boost/test/unit_test.hpp>
00029 #include <boost/test/test_tools.hpp>
00030 #include <boost/cstdint.hpp>
00031 
00032 #include <vector>
00033 #include <fstream>
00034 #include <iostream>
00035 #include <cmath>
00036 #include <climits>
00037 
00038 #include "../../include/moost/container/simple_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 #include "../../include/moost/container/policies/readers.hpp"
00045 
00046 using namespace moost::container;
00047 using namespace moost::container::policies;
00048 using namespace std;
00049 
00050 BOOST_AUTO_TEST_SUITE( simple_multi_map_test )
00051 
00052 struct FloatValueDoubler
00053 {
00054    void operator()(pair<int, float>& val) const
00055    {
00056       val.second = val.second * 2.0f;
00057    }
00058 };
00059 
00060 template <typename TMultiMap>
00061 struct Fixture_generic
00062 {
00063    typedef TMultiMap multi_map_type;
00064 
00065    int m_num_keys;
00066    int m_num_vals;
00067    const std::string m_fileName;
00068 
00069    Fixture_generic()
00070       : m_num_keys(10), m_num_vals(5), m_fileName("simple_multi_map_test_data.txt")
00071    {
00072       // create a test input file
00073       ofstream outFile(m_fileName.c_str());
00074 
00075       for ( int k = 0; k < m_num_keys; ++k )
00076       {
00077          outFile << k;
00078          for ( int v = 0; v < m_num_vals; ++v )
00079          {
00080             outFile << "\t" << v << "\t" << static_cast<float>(v);
00081          }
00082          outFile << endl;
00083       }
00084    }
00085 
00086    ~Fixture_generic()
00087    {
00088       remove( m_fileName.c_str() );
00089    }
00090 
00091    void load_data(multi_map_type& map, int maxEntriesPerVec = std::numeric_limits<int>::max(),
00092                     bool sortByValue = false, bool doubleValues = false)
00093    {
00094       if (doubleValues)
00095       {
00096          FloatValueDoubler floatValueDoubler;
00097          map.template create_map<tsv_sparsevec_reader<typename multi_map_type::first_type, float> >(
00098             m_fileName, floatValueDoubler, maxEntriesPerVec, sortByValue);
00099       }
00100       else
00101       {
00102          map.template create_map<tsv_sparsevec_reader<typename multi_map_type::first_type, float> >(
00103             m_fileName, maxEntriesPerVec, sortByValue);
00104       }
00105    }
00106 
00107    void check_map( multi_map_type& map, int maxEntriesPerVec = (std::numeric_limits<int>::max)(),
00108                     bool sortByValue = false, bool doubleValues = false)
00109    {
00110       BOOST_CHECK_EQUAL( static_cast<int>(map.size()), m_num_keys );
00111       pair<int, float> val;
00112       float eps = 0.00001f;
00113 
00114       int num_vals = min(m_num_vals, maxEntriesPerVec);
00115 
00116       // const
00117       {
00118          const multi_map_type& cmap = map;
00119          typename multi_map_type::const_range rt = cmap[m_num_keys+1];
00120          BOOST_CHECK( rt.empty() ); // not found!
00121 
00122          typename multi_map_type::const_range_iterator cmapIt;
00123 
00124          for ( typename multi_map_type::first_type k = 0; k < m_num_keys; ++k )
00125          {
00126             rt = cmap[k];
00127             BOOST_CHECK( !rt.empty() );
00128             BOOST_CHECK_EQUAL( static_cast<int>(rt.size()), num_vals );
00129 
00130             int i = 0;
00131             for ( cmapIt = rt.begin(); cmapIt != rt.end(); ++cmapIt, ++i )
00132             {
00133                if (sortByValue)  // order will be reversed
00134                   val.first = m_num_vals - 1 - i;
00135                else
00136                   val.first = i;
00137                val.second = static_cast<float>(val.first);
00138 
00139                BOOST_CHECK_EQUAL( cmapIt->first, val.first );
00140                if (doubleValues)
00141                   BOOST_CHECK( abs(cmapIt->second - val.second * 2.0f) < eps );
00142                else
00143                   BOOST_CHECK( abs(cmapIt->second - val.second) < eps );
00144             }
00145          }
00146 
00147       }
00148 
00149       // non const
00150       {
00151          typename multi_map_type::range rt = map[m_num_keys+1];
00152          BOOST_CHECK( rt.empty() ); // not found!
00153 
00154          typename multi_map_type::range_iterator mapIt;
00155 
00156          for ( typename multi_map_type::first_type k = 0; k < m_num_keys; ++k )
00157          {
00158             rt = map[k];
00159             BOOST_CHECK( !rt.empty() );
00160             BOOST_CHECK_EQUAL( static_cast<int>(rt.size()), num_vals );
00161 
00162             int i = 0;
00163             for ( mapIt = rt.begin(); mapIt != rt.end(); ++mapIt, ++i )
00164             {
00165                if (sortByValue)  // order will be reversed
00166                   val.first = m_num_vals - 1 - i;
00167                else
00168                   val.first = i;
00169                val.second = static_cast<float>(val.first);
00170 
00171                BOOST_CHECK_EQUAL( mapIt->first, val.first );
00172                if (doubleValues)
00173                   BOOST_CHECK( fabs(mapIt->second - val.second * 2.0f) < eps );
00174                else
00175                   BOOST_CHECK( fabs(mapIt->second - val.second) < eps );
00176             }
00177          }
00178       }
00179    }
00180 
00181 };
00182 
00183 struct Fixture_default : public Fixture_generic< simple_multi_map<> >
00184 {
00185    // using dense hash map
00186    // initialized with bucket size of 1024
00187    Fixture_default()
00188       : m_map( multi_map_type::loc_map_policy_type(-1) )  // policy is necessary because I saved key = 0
00189    {}
00190 
00191    multi_map_type m_map;
00192 };
00193 
00194 BOOST_FIXTURE_TEST_CASE( test_default, Fixture_default )
00195 {
00196    load_data(m_map);
00197    check_map(m_map);
00198 
00199    m_map.clear();
00200    BOOST_CHECK( m_map.empty() );
00201 
00202    // retest with truncated data, sorted by value
00203    load_data(m_map, 3, true);
00204    check_map(m_map, 3, true);
00205 
00206    m_map.clear();
00207    BOOST_CHECK( m_map.empty() );
00208 
00209    // retest transforming the values
00210    load_data(m_map, 3, true, true);
00211    check_map(m_map, 3, true, true);
00212 
00213    m_map.clear();
00214    BOOST_CHECK( m_map.empty() );
00215 }
00216 
00217 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
00218 
00219 struct Fixture_dense : public Fixture_generic<
00220                                        simple_multi_map< int, std::pair<int, float>,
00221                                        moost::container::dense_hash_map< int, multimap_value_type > > >
00222 {
00223    // using dense hash map
00224    // empty key is -1
00225    // no initialization of the bucket as simple_multi_map will figure it out
00226    Fixture_dense()
00227       : m_map( multi_map_type::loc_map_policy_type(-1) )
00228    {}
00229 
00230    multi_map_type m_map;
00231 };
00232 
00233 // just check if it compiles
00234 BOOST_FIXTURE_TEST_CASE( test_dense, Fixture_dense )
00235 {
00236    load_data(m_map);
00237    check_map(m_map);
00238 
00239    m_map.clear();
00240    BOOST_CHECK( m_map.empty() );
00241 
00242    // retest with truncated data, sorted by value
00243    load_data(m_map, 3, true);
00244    check_map(m_map, 3, true);
00245 
00246    m_map.clear();
00247    BOOST_CHECK( m_map.empty() );
00248 
00249    // retest transforming the values
00250    load_data(m_map, 3, true, true);
00251    check_map(m_map, 3, true, true);
00252 
00253    m_map.clear();
00254    BOOST_CHECK( m_map.empty() );
00255 }
00256 
00257 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
00258 
00259 struct Fixture_sparse : public Fixture_generic<
00260                               simple_multi_map< int, std::pair<int, float>,
00261                               moost::container::sparse_hash_map< int, multimap_value_type > > >
00262 {
00263    // using sparse hash map
00264    // no initialization of the bucket as simple_multi_map will figure it out
00265    Fixture_sparse()
00266       : m_map( multi_map_type::loc_map_policy_type() )
00267    {}
00268 
00269    multi_map_type m_map;
00270 };
00271 
00272 // just check if it compiles
00273 BOOST_FIXTURE_TEST_CASE( test_sparse, Fixture_sparse )
00274 {
00275    load_data(m_map);
00276    check_map(m_map);
00277 
00278    m_map.clear();
00279    BOOST_CHECK( m_map.empty() );
00280 
00281    // retest with truncated data, sorted by value
00282    load_data(m_map, 3, true);
00283    check_map(m_map, 3, true);
00284 
00285    m_map.clear();
00286    BOOST_CHECK( m_map.empty() );
00287 
00288    // retest transforming the values
00289    load_data(m_map, 3, true, true);
00290    check_map(m_map, 3, true, true);
00291 
00292    m_map.clear();
00293    BOOST_CHECK( m_map.empty() );
00294 }
00295 
00296 
00297 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
00298 
00299 struct Fixture_vector : public Fixture_generic<
00300                               simple_multi_map< int, std::pair<int, float>,
00301                               vector<multimap_value_type> > >
00302 {
00303    // using a vector
00304    // initialized with vector size of m_num_keys
00305    Fixture_vector()
00306    {}
00307 
00308    multi_map_type m_map;
00309 };
00310 
00311 // just check if it compiles
00312 BOOST_FIXTURE_TEST_CASE( test_vector, Fixture_vector )
00313 {
00314    load_data(m_map);
00315    check_map(m_map);
00316 
00317    m_map.clear();
00318    BOOST_CHECK( m_map.empty() );
00319 
00320    // retest with truncated data, sorted by value
00321    load_data(m_map, 3, true);
00322    check_map(m_map, 3, true);
00323 
00324    m_map.clear();
00325    BOOST_CHECK( m_map.empty() );
00326 
00327    // retest transforming the values
00328    load_data(m_map, 3, true, true);
00329    check_map(m_map, 3, true, true);
00330 
00331    m_map.clear();
00332    BOOST_CHECK( m_map.empty() );
00333 }
00334 
00335 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
00336 
00337 BOOST_AUTO_TEST_SUITE_END()