9207fa03ca0441422b6e432b580610dfeb48b068
[folly.git] / folly / test / sorted_vector_test.cpp
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <folly/sorted_vector_types.h>
18
19 #include <iterator>
20 #include <list>
21 #include <memory>
22
23 #include <folly/portability/GMock.h>
24 #include <folly/portability/GTest.h>
25
26 using folly::sorted_vector_set;
27 using folly::sorted_vector_map;
28
29 namespace {
30
31 template <class T>
32 struct less_invert {
33   bool operator()(const T& a, const T& b) const {
34     return b < a;
35   }
36 };
37
38 template<class Container>
39 void check_invariant(Container& c) {
40   auto it = c.begin();
41   auto end = c.end();
42   if (it == end)
43     return;
44   auto prev = it;
45   ++it;
46   for (; it != end; ++it, ++prev) {
47     EXPECT_TRUE(c.value_comp()(*prev, *it));
48   }
49 }
50
51 struct OneAtATimePolicy {
52   template<class Container>
53   void increase_capacity(Container& c) {
54     if (c.size() == c.capacity()) {
55       c.reserve(c.size() + 1);
56     }
57   }
58 };
59
60 struct CountCopyCtor {
61   explicit CountCopyCtor() : val_(0) {}
62
63   explicit CountCopyCtor(int val) : val_(val), count_(0) {}
64
65   CountCopyCtor(const CountCopyCtor& c)
66     : val_(c.val_)
67     , count_(c.count_ + 1)
68   {}
69
70   bool operator<(const CountCopyCtor& o) const {
71     return val_ < o.val_;
72   }
73
74   int val_;
75   int count_;
76 };
77
78 }
79
80 TEST(SortedVectorTypes, SimpleSetTest) {
81   sorted_vector_set<int> s;
82   EXPECT_TRUE(s.empty());
83   for (int i = 0; i < 1000; ++i) {
84     s.insert(rand() % 100000);
85   }
86   EXPECT_FALSE(s.empty());
87   check_invariant(s);
88
89   sorted_vector_set<int> s2;
90   s2.insert(s.begin(), s.end());
91   check_invariant(s2);
92   EXPECT_TRUE(s == s2);
93
94   auto it = s2.lower_bound(32);
95   if (*it == 32) {
96     s2.erase(it);
97     it = s2.lower_bound(32);
98   }
99   check_invariant(s2);
100   auto oldSz = s2.size();
101   s2.insert(it, 32);
102   EXPECT_TRUE(s2.size() == oldSz + 1);
103   check_invariant(s2);
104
105   const sorted_vector_set<int>& cs2 = s2;
106   auto range = cs2.equal_range(32);
107   auto lbound = cs2.lower_bound(32);
108   auto ubound = cs2.upper_bound(32);
109   EXPECT_TRUE(range.first == lbound);
110   EXPECT_TRUE(range.second == ubound);
111   EXPECT_TRUE(range.first != cs2.end());
112   EXPECT_TRUE(range.second != cs2.end());
113   EXPECT_TRUE(cs2.count(32) == 1);
114   EXPECT_FALSE(cs2.find(32) == cs2.end());
115
116   // Bad insert hint.
117   s2.insert(s2.begin() + 3, 33);
118   EXPECT_TRUE(s2.find(33) != s2.begin());
119   EXPECT_TRUE(s2.find(33) != s2.end());
120   check_invariant(s2);
121   s2.erase(33);
122   check_invariant(s2);
123
124   it = s2.find(32);
125   EXPECT_FALSE(it == s2.end());
126   s2.erase(it);
127   EXPECT_TRUE(s2.size() == oldSz);
128   check_invariant(s2);
129
130   sorted_vector_set<int> cpy(s);
131   check_invariant(cpy);
132   EXPECT_TRUE(cpy == s);
133   sorted_vector_set<int> cpy2(s);
134   cpy2.insert(100001);
135   EXPECT_TRUE(cpy2 != cpy);
136   EXPECT_TRUE(cpy2 != s);
137   check_invariant(cpy2);
138   EXPECT_TRUE(cpy2.count(100001) == 1);
139   s.swap(cpy2);
140   check_invariant(cpy2);
141   check_invariant(s);
142   EXPECT_TRUE(s != cpy);
143   EXPECT_TRUE(s != cpy2);
144   EXPECT_TRUE(cpy2 == cpy);
145 }
146
147 TEST(SortedVectorTypes, SimpleMapTest) {
148   sorted_vector_map<int,float> m;
149   for (int i = 0; i < 1000; ++i) {
150     m[i] = i / 1000.0;
151   }
152   check_invariant(m);
153
154   m[32] = 100.0;
155   check_invariant(m);
156   EXPECT_TRUE(m.count(32) == 1);
157   EXPECT_DOUBLE_EQ(100.0, m.at(32));
158   EXPECT_FALSE(m.find(32) == m.end());
159   m.erase(32);
160   EXPECT_TRUE(m.find(32) == m.end());
161   check_invariant(m);
162   EXPECT_THROW(m.at(32), std::out_of_range);
163
164   sorted_vector_map<int,float> m2 = m;
165   EXPECT_TRUE(m2 == m);
166   EXPECT_FALSE(m2 != m);
167   auto it = m2.lower_bound(1 << 20);
168   EXPECT_TRUE(it == m2.end());
169   m2.insert(it, std::make_pair(1 << 20, 10.0f));
170   check_invariant(m2);
171   EXPECT_TRUE(m2.count(1 << 20) == 1);
172   EXPECT_TRUE(m < m2);
173   EXPECT_TRUE(m <= m2);
174
175   const sorted_vector_map<int,float>& cm = m;
176   auto range = cm.equal_range(42);
177   auto lbound = cm.lower_bound(42);
178   auto ubound = cm.upper_bound(42);
179   EXPECT_TRUE(range.first == lbound);
180   EXPECT_TRUE(range.second == ubound);
181   EXPECT_FALSE(range.first == cm.end());
182   EXPECT_FALSE(range.second == cm.end());
183   m.erase(m.lower_bound(42));
184   check_invariant(m);
185
186   sorted_vector_map<int,float> m3;
187   m3.insert(m2.begin(), m2.end());
188   check_invariant(m3);
189   EXPECT_TRUE(m3 == m2);
190   EXPECT_FALSE(m3 == m);
191
192   EXPECT_TRUE(m != m2);
193   EXPECT_TRUE(m2 == m3);
194   EXPECT_TRUE(m3 != m);
195   m.swap(m3);
196   check_invariant(m);
197   check_invariant(m2);
198   check_invariant(m3);
199   EXPECT_TRUE(m3 != m2);
200   EXPECT_TRUE(m3 != m);
201   EXPECT_TRUE(m == m2);
202
203   // Bad insert hint.
204   m.insert(m.begin() + 3, std::make_pair(1 << 15, 1.0f));
205   check_invariant(m);
206 }
207
208 TEST(SortedVectorTypes, Sizes) {
209   EXPECT_EQ(sizeof(sorted_vector_set<int>),
210             sizeof(std::vector<int>));
211   EXPECT_EQ(sizeof(sorted_vector_map<int,int>),
212             sizeof(std::vector<std::pair<int,int> >));
213
214   typedef sorted_vector_set<int,std::less<int>,
215     std::allocator<int>,OneAtATimePolicy> SetT;
216   typedef sorted_vector_map<int,int,std::less<int>,
217     std::allocator<std::pair<int,int>>,OneAtATimePolicy> MapT;
218
219   EXPECT_EQ(sizeof(SetT), sizeof(std::vector<int>));
220   EXPECT_EQ(sizeof(MapT), sizeof(std::vector<std::pair<int,int> >));
221 }
222
223 TEST(SortedVectorTypes, InitializerLists) {
224   sorted_vector_set<int> empty_initialized_set{};
225   EXPECT_TRUE(empty_initialized_set.empty());
226
227   sorted_vector_set<int> singleton_initialized_set{1};
228   EXPECT_EQ(1, singleton_initialized_set.size());
229   EXPECT_EQ(1, *singleton_initialized_set.begin());
230
231   sorted_vector_set<int> forward_initialized_set{1, 2};
232   sorted_vector_set<int> backward_initialized_set{2, 1};
233   EXPECT_EQ(2, forward_initialized_set.size());
234   EXPECT_EQ(1, *forward_initialized_set.begin());
235   EXPECT_EQ(2, *forward_initialized_set.rbegin());
236   EXPECT_TRUE(forward_initialized_set == backward_initialized_set);
237
238   sorted_vector_map<int,int> empty_initialized_map{};
239   EXPECT_TRUE(empty_initialized_map.empty());
240
241   sorted_vector_map<int,int> singleton_initialized_map{{1,10}};
242   EXPECT_EQ(1, singleton_initialized_map.size());
243   EXPECT_EQ(10, singleton_initialized_map[1]);
244
245   sorted_vector_map<int,int> forward_initialized_map{{1,10}, {2,20}};
246   sorted_vector_map<int,int> backward_initialized_map{{2,20}, {1,10}};
247   EXPECT_EQ(2, forward_initialized_map.size());
248   EXPECT_EQ(10, forward_initialized_map[1]);
249   EXPECT_EQ(20, forward_initialized_map[2]);
250   EXPECT_TRUE(forward_initialized_map == backward_initialized_map);
251 }
252
253 TEST(SortedVectorTypes, CustomCompare) {
254   sorted_vector_set<int,less_invert<int> > s;
255   for (int i = 0; i < 200; ++i)
256     s.insert(i);
257   check_invariant(s);
258
259   sorted_vector_map<int,float,less_invert<int> > m;
260   for (int i = 0; i < 200; ++i)
261     m[i] = 12.0;
262   check_invariant(m);
263 }
264
265 TEST(SortedVectorTypes, GrowthPolicy) {
266   typedef sorted_vector_set<CountCopyCtor,
267                             std::less<CountCopyCtor>,
268                             std::allocator<CountCopyCtor>,
269                             OneAtATimePolicy>
270     SetT;
271
272   SetT a;
273   for (int i = 0; i < 20; ++i) {
274     a.insert(CountCopyCtor(i));
275   }
276   check_invariant(a);
277   SetT::iterator it = a.begin();
278   EXPECT_FALSE(it == a.end());
279   if (it != a.end()) {
280     EXPECT_EQ(it->val_, 0);
281     // 1 copy for the initial insertion, 19 more for reallocs on the
282     // additional insertions.
283     EXPECT_EQ(it->count_, 20);
284   }
285
286   std::list<CountCopyCtor> v;
287   for (int i = 0; i < 20; ++i) {
288     v.emplace_back(20 + i);
289   }
290   a.insert(v.begin(), v.end());
291   check_invariant(a);
292
293   it = a.begin();
294   EXPECT_FALSE(it == a.end());
295   if (it != a.end()) {
296     EXPECT_EQ(it->val_, 0);
297     // Should be only 1 more copy for inserting this above range.
298     EXPECT_EQ(it->count_, 21);
299   }
300 }
301
302 TEST(SortedVectorTest, EmptyTest) {
303   sorted_vector_set<int> emptySet;
304   EXPECT_TRUE(emptySet.lower_bound(10) == emptySet.end());
305   EXPECT_TRUE(emptySet.find(10) == emptySet.end());
306
307   sorted_vector_map<int,int> emptyMap;
308   EXPECT_TRUE(emptyMap.lower_bound(10) == emptyMap.end());
309   EXPECT_TRUE(emptyMap.find(10) == emptyMap.end());
310   EXPECT_THROW(emptyMap.at(10), std::out_of_range);
311 }
312
313 TEST(SortedVectorTest, MoveTest) {
314   sorted_vector_set<std::unique_ptr<int>> s;
315   s.insert(std::unique_ptr<int>(new int(5)));
316   s.insert(s.end(), std::unique_ptr<int>(new int(10)));
317   EXPECT_EQ(s.size(), 2);
318
319   for (const auto& p : s) {
320     EXPECT_TRUE(*p == 5 || *p == 10);
321   }
322
323   sorted_vector_map<int, std::unique_ptr<int>> m;
324   m.insert(std::make_pair(5, std::unique_ptr<int>(new int(5))));
325   m.insert(m.end(), std::make_pair(10, std::unique_ptr<int>(new int(10))));
326
327   EXPECT_EQ(*m[5], 5);
328   EXPECT_EQ(*m[10], 10);
329 }
330
331 TEST(SortedVectorTest, ShrinkTest) {
332   sorted_vector_set<int> s;
333   int i = 0;
334   // Hopefully your resize policy doubles when capacity is full, or this will
335   // hang forever :(
336   while (s.capacity() == s.size()) {
337     s.insert(i++);
338   }
339   s.shrink_to_fit();
340   // The standard does not actually enforce that this be true, but assume that
341   // vector::shrink_to_fit respects the caller.
342   EXPECT_EQ(s.capacity(), s.size());
343 }
344
345 TEST(SortedVectorTypes, EraseTest) {
346   sorted_vector_set<int> s1;
347   s1.insert(1);
348   sorted_vector_set<int> s2(s1);
349   EXPECT_EQ(0, s1.erase(0));
350   EXPECT_EQ(s2, s1);
351 }
352
353 std::vector<int> extractValues(sorted_vector_set<CountCopyCtor> const& in) {
354   std::vector<int> ret;
355   std::transform(
356       in.begin(),
357       in.end(),
358       std::back_inserter(ret),
359       [](const CountCopyCtor& c) { return c.val_; });
360   return ret;
361 }
362
363 template <typename T, typename S>
364 std::vector<T> makeVectorOfWrappers(std::vector<S> ss) {
365   std::vector<T> ts;
366   ts.reserve(ss.size());
367   for (auto const& s : ss) {
368     ts.emplace_back(s);
369   }
370   return ts;
371 }
372
373 TEST(SortedVectorTypes, TestSetBulkInsertionSortMerge) {
374   auto s = makeVectorOfWrappers<CountCopyCtor, int>({6, 4, 8, 2});
375
376   sorted_vector_set<CountCopyCtor> vset(s.begin(), s.end());
377   check_invariant(vset);
378
379   // Add an unsorted range that will have to be merged in.
380   s = makeVectorOfWrappers<CountCopyCtor, int>({10, 7, 5, 1});
381
382   vset.insert(s.begin(), s.end());
383   check_invariant(vset);
384   EXPECT_EQ(vset.rbegin()->count_, 1);
385
386   EXPECT_THAT(
387       extractValues(vset),
388       testing::ElementsAreArray({1, 2, 4, 5, 6, 7, 8, 10}));
389 }
390
391 TEST(SortedVectorTypes, TestSetBulkInsertionSortMergeDups) {
392   auto s = makeVectorOfWrappers<CountCopyCtor, int>({6, 4, 8, 2});
393
394   sorted_vector_set<CountCopyCtor> vset(s.begin(), s.end());
395   check_invariant(vset);
396
397   // Add an unsorted range that will have to be merged in.
398   s = makeVectorOfWrappers<CountCopyCtor, int>({10, 6, 5, 2});
399
400   vset.insert(s.begin(), s.end());
401   check_invariant(vset);
402   EXPECT_EQ(vset.rbegin()->count_, 1);
403   EXPECT_THAT(
404       extractValues(vset), testing::ElementsAreArray({2, 4, 5, 6, 8, 10}));
405 }
406
407 TEST(SortedVectorTypes, TestSetInsertionDupsOneByOne) {
408   auto s = makeVectorOfWrappers<CountCopyCtor, int>({6, 4, 8, 2});
409
410   sorted_vector_set<CountCopyCtor> vset(s.begin(), s.end());
411   check_invariant(vset);
412
413   // Add an unsorted range that will have to be merged in.
414   s = makeVectorOfWrappers<CountCopyCtor, int>({10, 6, 5, 2});
415
416   for (const auto& elem : s) {
417     vset.insert(elem);
418   }
419   check_invariant(vset);
420   EXPECT_EQ(vset.rbegin()->count_, 3);
421   EXPECT_THAT(
422       extractValues(vset), testing::ElementsAreArray({2, 4, 5, 6, 8, 10}));
423 }
424
425 TEST(SortedVectorTypes, TestSetBulkInsertionSortNoMerge) {
426   auto s = makeVectorOfWrappers<CountCopyCtor, int>({6, 4, 8, 2});
427
428   sorted_vector_set<CountCopyCtor> vset(s.begin(), s.end());
429   check_invariant(vset);
430
431   // Add an unsorted range that will not have to be merged in.
432   s = makeVectorOfWrappers<CountCopyCtor, int>({20, 15, 16, 13});
433
434   vset.insert(s.begin(), s.end());
435   check_invariant(vset);
436   EXPECT_EQ(vset.rbegin()->count_, 1);
437   EXPECT_THAT(
438       extractValues(vset),
439       testing::ElementsAreArray({2, 4, 6, 8, 13, 15, 16, 20}));
440 }
441
442 TEST(SortedVectorTypes, TestSetBulkInsertionNoSortMerge) {
443   auto s = makeVectorOfWrappers<CountCopyCtor, int>({6, 4, 8, 2});
444
445   sorted_vector_set<CountCopyCtor> vset(s.begin(), s.end());
446   check_invariant(vset);
447
448   // Add a sorted range that will have to be merged in.
449   s = makeVectorOfWrappers<CountCopyCtor, int>({1, 3, 5, 9});
450
451   vset.insert(s.begin(), s.end());
452   check_invariant(vset);
453   EXPECT_EQ(vset.rbegin()->count_, 1);
454   EXPECT_THAT(
455       extractValues(vset), testing::ElementsAreArray({1, 2, 3, 4, 5, 6, 8, 9}));
456 }
457
458 TEST(SortedVectorTypes, TestSetBulkInsertionNoSortNoMerge) {
459   auto s = makeVectorOfWrappers<CountCopyCtor, int>({6, 4, 8, 2});
460
461   sorted_vector_set<CountCopyCtor> vset(s.begin(), s.end());
462   check_invariant(vset);
463
464   // Add a sorted range that will not have to be merged in.
465   s = makeVectorOfWrappers<CountCopyCtor, int>({21, 22, 23, 24});
466
467   vset.insert(s.begin(), s.end());
468   check_invariant(vset);
469   EXPECT_EQ(vset.rbegin()->count_, 1);
470   EXPECT_THAT(
471       extractValues(vset),
472       testing::ElementsAreArray({2, 4, 6, 8, 21, 22, 23, 24}));
473 }
474
475 TEST(SortedVectorTypes, TestSetBulkInsertionEmptyRange) {
476   std::vector<CountCopyCtor> s;
477   EXPECT_TRUE(s.empty());
478
479   // insertion of empty range into empty container.
480   sorted_vector_set<CountCopyCtor> vset(s.begin(), s.end());
481   check_invariant(vset);
482
483   s = makeVectorOfWrappers<CountCopyCtor, int>({6, 4, 8, 2});
484
485   vset.insert(s.begin(), s.end());
486
487   // insertion of empty range into non-empty container.
488   s.clear();
489   vset.insert(s.begin(), s.end());
490   check_invariant(vset);
491
492   EXPECT_THAT(extractValues(vset), testing::ElementsAreArray({2, 4, 6, 8}));
493 }
494
495 // This is a test of compilation - the behavior has already been tested
496 // extensively above.
497 TEST(SortedVectorTypes, TestBulkInsertionUncopyableTypes) {
498   std::vector<std::pair<int, std::unique_ptr<int>>> s;
499   s.emplace_back(1, std::make_unique<int>(0));
500
501   sorted_vector_map<int, std::unique_ptr<int>> vmap(
502       std::make_move_iterator(s.begin()), std::make_move_iterator(s.end()));
503
504   s.clear();
505   s.emplace_back(3, std::make_unique<int>(0));
506   vmap.insert(
507       std::make_move_iterator(s.begin()), std::make_move_iterator(s.end()));
508 }
509
510 // A moveable and copyable struct, which we use to make sure that no copy
511 // operations are performed during bulk insertion if moving is an option.
512 struct Movable {
513   int x_;
514   explicit Movable(int x) : x_(x) {}
515   Movable(const Movable&) {
516     ADD_FAILURE() << "Copy ctor should not be called";
517   }
518   Movable& operator=(const Movable&) {
519     ADD_FAILURE() << "Copy assignment should not be called";
520     return *this;
521   }
522
523   Movable(Movable&&) = default;
524   Movable& operator=(Movable&&) = default;
525 };
526
527 TEST(SortedVectorTypes, TestBulkInsertionMovableTypes) {
528   std::vector<std::pair<int, Movable>> s;
529   s.emplace_back(3, Movable(2));
530   s.emplace_back(1, Movable(0));
531
532   sorted_vector_map<int, Movable> vmap(
533       std::make_move_iterator(s.begin()), std::make_move_iterator(s.end()));
534
535   s.clear();
536   s.emplace_back(4, Movable(3));
537   s.emplace_back(2, Movable(1));
538   vmap.insert(
539       std::make_move_iterator(s.begin()), std::make_move_iterator(s.end()));
540 }
541
542 TEST(SortedVectorTypes, TestSetCreationFromVector) {
543   std::vector<int> vec = {3, 1, -1, 5, 0};
544   sorted_vector_set<int> vset(std::move(vec));
545   check_invariant(vset);
546   EXPECT_THAT(vset, testing::ElementsAreArray({-1, 0, 1, 3, 5}));
547 }
548
549 TEST(SortedVectorTypes, TestMapCreationFromVector) {
550   std::vector<std::pair<int, int>> vec = {
551       {3, 1}, {1, 5}, {-1, 2}, {5, 3}, {0, 3}};
552   sorted_vector_map<int, int> vmap(std::move(vec));
553   check_invariant(vmap);
554   auto contents = std::vector<std::pair<int, int>>(vmap.begin(), vmap.end());
555   auto expected_contents = std::vector<std::pair<int, int>>({
556       {-1, 2}, {0, 3}, {1, 5}, {3, 1}, {5, 3},
557   });
558   EXPECT_EQ(contents, expected_contents);
559 }