libmoost
|
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()