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