1 /* SuperRead pipeline 2 * Copyright (C) 2012 Genome group at University of Maryland. 3 * 4 * This program is free software: you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation, either version 3 of the 7 * License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 19 #include <gtest/gtest.h> 20 #include <unittests/misc.hpp> 21 #include <multi_thread_skip_list_set.hpp> 22 23 #include <string> 24 #include <vector> 25 26 namespace { 27 // Compute the power at compile time in a stupid way 28 template<long x, long n> 29 struct lpow { 30 enum { value = x * lpow<x, n-1>::value }; 31 }; 32 template<long x> 33 struct lpow<x, 0> { 34 enum { value = 1 }; 35 }; 36 37 typedef multi_thread_skip_list_set<int> set_type; 38 typedef set_type::iterator set_iterator; 39 typedef set_type::const_iterator const_set_iterator; 40 typedef std::pair<set_iterator, bool> set_ins; 41 42 typedef std::set<int>::iterator std_iterator; 43 typedef std::set<int>::const_iterator const_std_iterator; 44 typedef std::pair<std_iterator, bool> std_ins; 45 TEST(MTSkipListSet,Init)46 TEST(MTSkipListSet, Init) { 47 static const int max_height = 5; 48 set_type sls(max_height); 49 EXPECT_TRUE(sls.empty()); 50 EXPECT_EQ((size_t)0, sls.size()); 51 EXPECT_TRUE(sls.end() == sls.begin()); 52 EXPECT_EQ(((size_t)lpow<set_type::p, max_height>::value), sls.max_size()); 53 } 54 TEST(MTSkipListSet,InsertOneThread)55 TEST(MTSkipListSet, InsertOneThread) { 56 set_type sls(5, std::less<int>(), xor_random(random())); 57 set_type::thread th(sls); 58 std::set<int> set; 59 60 61 for(int i = 0; i < 100; ++i) { 62 int x = random() % 50; 63 std_ins set_res = set.insert(x); 64 set_ins sls_res = th.insert(x); 65 EXPECT_EQ(set_res.second, sls_res.second); 66 EXPECT_EQ(*set_res.first, *sls_res.first); 67 EXPECT_EQ(x, *sls_res.first); 68 EXPECT_EQ(set.empty(), sls.empty()); 69 EXPECT_EQ(set.size(), sls.size()); 70 } 71 72 const_set_iterator set_it = sls.begin(); 73 for(const_std_iterator std_it = set.begin(); std_it != set.end(); 74 ++std_it, ++set_it) { 75 ASSERT_FALSE(set_it == sls.end()); 76 EXPECT_EQ(*std_it, *set_it); 77 } 78 ASSERT_TRUE(set_it == sls.end()); 79 } 80 81 struct thread_insert_data { 82 set_type set; // The set to add to 83 jflib::atomic_field<int> ids; // Counter to get a thread id 84 std::vector<int> v; // The data to insert 85 jflib::atomic_field<int> new_elt; // Nb new element inserted 86 jflib::atomic_field<int> exist_elt; // Nb existing element inserted 87 88 static const int per_th = 10000; // Nb elements per thread thread_insert_data__anon0e0178f80111::thread_insert_data89 thread_insert_data(int nb_threads) : 90 set(10, std::less<int>(), xor_random(random())), ids(-1), 91 new_elt(0), exist_elt(0) 92 { 93 const int n = per_th * nb_threads; 94 for(int i = 0; i < n; ++i) 95 v.push_back(random() % n); 96 } 97 }; insert_from_thread(void * d)98 void* insert_from_thread(void* d) { 99 auto data = (thread_insert_data*)d; 100 set_type::thread th(data->set); 101 102 int tid = (data->ids += 1); 103 int new_elt = 0, exist_elt = 0; 104 for(int i = tid * data->per_th; i < (tid+1) * data->per_th; ++i) { 105 auto res = th.insert(data->v[i]); 106 if(res.second) 107 ++new_elt; 108 else 109 ++exist_elt; 110 } 111 new_elt = (data->new_elt += new_elt); 112 exist_elt = (data->exist_elt += exist_elt); 113 114 return 0; 115 } TEST(MTSkipListSet,InsertManyThreads)116 TEST(MTSkipListSet, InsertManyThreads) { 117 const int nb_threads = 5; 118 thread_insert_data data(nb_threads); 119 120 pdo(nb_threads, insert_from_thread, (void*)&data); 121 EXPECT_EQ(data.v.size(), (size_t)(data.new_elt + data.exist_elt)); 122 123 // Do the same single threads into a set and check the statistics 124 std::set<int> std_set; 125 int new_elt = 0, exist_elt = 0; 126 for(auto it = data.v.begin(); it != data.v.end(); ++it) { 127 auto res = std_set.insert(*it); 128 if(res.second) 129 ++new_elt; 130 else 131 ++exist_elt; 132 } 133 EXPECT_EQ(new_elt, data.new_elt); 134 EXPECT_EQ(exist_elt, data.exist_elt); 135 EXPECT_EQ(std_set.size(), data.set.size()); 136 137 set_type::thread th(data.set); 138 for(int i = -1; i <= (int)data.v.size(); ++i) { 139 EXPECT_EQ(std_set.count(i), data.set.count(i)); 140 { // Test find 141 auto std_res = std_set.find(i); 142 auto set_res = data.set.find(i); 143 if(std_res == std_set.end()) 144 EXPECT_EQ(data.set.end(), set_res); 145 else 146 EXPECT_EQ(*std_res, *set_res); 147 EXPECT_EQ(set_res, th.find(i)); 148 } 149 { // Test equal_range 150 auto std_res = std_set.equal_range(i); 151 auto set_res = data.set.equal_range(i); 152 auto th_res = th.equal_range(i); 153 EXPECT_EQ(std_res.first == std_res.second, set_res.first == set_res.second); 154 EXPECT_EQ(std_res.second == std_set.end(), set_res.second == data.set.end()); 155 ASSERT_EQ(set_res, th_res); 156 if(std_res.first != std_res.second) { 157 EXPECT_EQ(i, *set_res.first); 158 EXPECT_EQ(set_res.second, ++set_res.first); 159 } 160 } 161 { // Test lower_bound 162 auto std_res = std_set.lower_bound(i); 163 auto set_res = data.set.lower_bound(i); 164 if(std_res == std_set.end()) 165 EXPECT_EQ(data.set.end(), set_res); 166 else 167 EXPECT_EQ(*std_res, *set_res); 168 EXPECT_EQ(set_res, th.lower_bound(i)); 169 } 170 { // Test upper_bound 171 auto std_res = std_set.upper_bound(i); 172 auto set_res = data.set.upper_bound(i); 173 if(std_res == std_set.end()) 174 EXPECT_EQ(data.set.end(), set_res); 175 else 176 EXPECT_EQ(*std_res, *set_res); 177 EXPECT_EQ(set_res, th.upper_bound(i)); 178 } 179 } 180 } 181 // TEST(SkipListSet, InsertIterator) { 182 // skip_list_set<int> sls(5); 183 // std::set<int> set; 184 // typedef std::set<int>::iterator set_it_type; 185 // typedef skip_list_set<int>::iterator sls_it_type; 186 187 // std::vector<int> xs; 188 // for(int i = 0; i < 100; ++i) 189 // xs.push_back(random() % 50); 190 191 // set.insert(xs.begin(), xs.end()); 192 // sls.insert(xs.begin(), xs.end()); 193 // EXPECT_EQ(set.size(), sls.size()); 194 // EXPECT_EQ(set.empty(), sls.empty()); 195 196 // sls_it_type sls_it = sls.begin(); 197 // for(set_it_type set_it = set.begin(); set_it != set.end(); ++set_it, ++sls_it) { 198 // ASSERT_FALSE(sls.end() == sls_it); 199 // EXPECT_EQ(*set_it, *sls_it); 200 // } 201 // EXPECT_TRUE(sls.end() == sls_it); 202 203 // for(int i = 0; i < 51; ++i) { 204 // EXPECT_EQ(set.count(i), sls.count(i)); 205 // std::pair<set_it_type, set_it_type> set_its = set.equal_range(i); 206 // std::pair<sls_it_type, sls_it_type> sls_its = sls.equal_range(i); 207 // EXPECT_EQ(set_its.first == set_its.second, sls_its.first == sls_its.second); 208 // EXPECT_EQ(set_its.second == set.end(), sls_its.second == sls.end()); 209 // if(sls_its.first != sls_its.second) { 210 // EXPECT_EQ(i, *sls_its.first); 211 // EXPECT_EQ(sls_its.second, ++sls_its.first); 212 // } 213 214 // set_it_type set_it = set.find(i); 215 // sls_it_type sls_it = sls.find(i); 216 // if(set_it == set.end()) { 217 // EXPECT_EQ(sls.end(), sls_it); 218 // } else { 219 // ASSERT_NE(sls.end(), sls_it); 220 // EXPECT_EQ(*set_it, *sls_it); 221 // } 222 223 // set_it = set.lower_bound(i); 224 // sls_it = sls.lower_bound(i); 225 // if(set_it == set.end()) { 226 // EXPECT_EQ(sls.end(), sls_it); 227 // } else { 228 // ASSERT_NE(sls.end(), sls_it); 229 // EXPECT_EQ(*set_it, *sls_it); 230 // } 231 232 // set_it = set.upper_bound(i); 233 // sls_it = sls.upper_bound(i); 234 // if(set_it == set.end()) { 235 // EXPECT_EQ(sls.end(), sls_it); 236 // } else { 237 // ASSERT_NE(sls.end(), sls_it); 238 // EXPECT_EQ(*set_it, *sls_it); 239 // } 240 // } 241 242 // set.clear(); 243 // sls.clear(); 244 // EXPECT_EQ(set.size(), sls.size()); 245 // EXPECT_EQ(set.empty(), sls.empty()); 246 // EXPECT_EQ(sls.end(), sls.begin()); 247 // } 248 249 // TEST(SkipListSet, InsertErase) { 250 // skip_list_set<int> sls(5); 251 // std::set<int> set; 252 // std::vector<int> xs; 253 254 // for(int i = 0; i < 100; ++i) 255 // xs.push_back(i * 3); 256 // random_shuffle(xs.begin(), xs.end()); 257 258 // set.insert(xs.begin(), xs.end()); 259 // sls.insert(xs.begin(), xs.end()); 260 // EXPECT_TRUE(std::equal(set.begin(), set.end(), sls.begin())); 261 262 // random_shuffle(xs.begin(), xs.end()); 263 // for(std::vector<int>::iterator it = xs.begin(); it != xs.end(); ++it) { 264 // size_t set_n = set.erase(*it); 265 // size_t sls_n = sls.erase(*it); 266 // EXPECT_EQ(set_n, sls_n); 267 // EXPECT_EQ(set.size(), sls.size()); 268 // EXPECT_EQ(set.empty(), sls.empty()); 269 // EXPECT_TRUE(std::equal(set.begin(), set.end(), sls.begin())); 270 // } 271 // EXPECT_TRUE(sls.empty()); 272 // } 273 274 // TEST(SkipListSet, Copy) { 275 // skip_list_set<std::string> sls(7); 276 // std::string str(10, 'A'); 277 278 // static const size_t nb_elts = 100; 279 // for(size_t i = 0; i < nb_elts; ++i) { 280 // // Create random string 281 // for(size_t j = 0; j < str.size(); ++j) 282 // str[j] = 'A' + random() % 26; 283 // sls.insert(str); 284 // } 285 // // This could fail with very small probability, if two identical 286 // // random string are generated. 287 // EXPECT_EQ(nb_elts, sls.size()); 288 289 // skip_list_set<std::string> nsls(sls); 290 // EXPECT_EQ(sls.size(), nsls.size()); 291 // EXPECT_TRUE(std::equal(sls.begin(), sls.end(), nsls.begin())); 292 293 // skip_list_set<std::string> msls; 294 // EXPECT_TRUE(msls.empty()); 295 // msls = sls; 296 // EXPECT_EQ(sls.size(), nsls.size()); 297 // EXPECT_TRUE(std::equal(sls.begin(), sls.end(), nsls.begin())); 298 // } 299 300 } // namespace 301