1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/container/btree_test.h"
16
17 #include <algorithm>
18 #include <array>
19 #include <cstdint>
20 #include <functional>
21 #include <iterator>
22 #include <limits>
23 #include <map>
24 #include <memory>
25 #include <numeric>
26 #include <stdexcept>
27 #include <string>
28 #include <type_traits>
29 #include <utility>
30 #include <vector>
31
32 #include "gmock/gmock.h"
33 #include "gtest/gtest.h"
34 #include "absl/algorithm/container.h"
35 #include "absl/base/internal/raw_logging.h"
36 #include "absl/base/macros.h"
37 #include "absl/container/btree_map.h"
38 #include "absl/container/btree_set.h"
39 #include "absl/container/internal/counting_allocator.h"
40 #include "absl/container/internal/test_instance_tracker.h"
41 #include "absl/flags/flag.h"
42 #include "absl/hash/hash_testing.h"
43 #include "absl/memory/memory.h"
44 #include "absl/random/random.h"
45 #include "absl/strings/str_cat.h"
46 #include "absl/strings/str_split.h"
47 #include "absl/strings/string_view.h"
48 #include "absl/types/compare.h"
49
50 ABSL_FLAG(int, test_values, 10000, "The number of values to use for tests");
51
52 namespace absl {
53 ABSL_NAMESPACE_BEGIN
54 namespace container_internal {
55 namespace {
56
57 using ::absl::test_internal::CopyableMovableInstance;
58 using ::absl::test_internal::InstanceTracker;
59 using ::absl::test_internal::MovableOnlyInstance;
60 using ::testing::ElementsAre;
61 using ::testing::ElementsAreArray;
62 using ::testing::IsEmpty;
63 using ::testing::IsNull;
64 using ::testing::Pair;
65 using ::testing::SizeIs;
66
67 template <typename T, typename U>
CheckPairEquals(const T & x,const U & y)68 void CheckPairEquals(const T &x, const U &y) {
69 ABSL_INTERNAL_CHECK(x == y, "Values are unequal.");
70 }
71
72 template <typename T, typename U, typename V, typename W>
CheckPairEquals(const std::pair<T,U> & x,const std::pair<V,W> & y)73 void CheckPairEquals(const std::pair<T, U> &x, const std::pair<V, W> &y) {
74 CheckPairEquals(x.first, y.first);
75 CheckPairEquals(x.second, y.second);
76 }
77
IsAssertEnabled()78 bool IsAssertEnabled() {
79 // Use an assert with side-effects to figure out if they are actually enabled.
80 bool assert_enabled = false;
81 assert([&]() { // NOLINT
82 assert_enabled = true;
83 return true;
84 }());
85 return assert_enabled;
86 }
87 } // namespace
88
89 // The base class for a sorted associative container checker. TreeType is the
90 // container type to check and CheckerType is the container type to check
91 // against. TreeType is expected to be btree_{set,map,multiset,multimap} and
92 // CheckerType is expected to be {set,map,multiset,multimap}.
93 template <typename TreeType, typename CheckerType>
94 class base_checker {
95 public:
96 using key_type = typename TreeType::key_type;
97 using value_type = typename TreeType::value_type;
98 using key_compare = typename TreeType::key_compare;
99 using pointer = typename TreeType::pointer;
100 using const_pointer = typename TreeType::const_pointer;
101 using reference = typename TreeType::reference;
102 using const_reference = typename TreeType::const_reference;
103 using size_type = typename TreeType::size_type;
104 using difference_type = typename TreeType::difference_type;
105 using iterator = typename TreeType::iterator;
106 using const_iterator = typename TreeType::const_iterator;
107 using reverse_iterator = typename TreeType::reverse_iterator;
108 using const_reverse_iterator = typename TreeType::const_reverse_iterator;
109
110 public:
base_checker()111 base_checker() : const_tree_(tree_) {}
base_checker(const base_checker & other)112 base_checker(const base_checker &other)
113 : tree_(other.tree_), const_tree_(tree_), checker_(other.checker_) {}
114 template <typename InputIterator>
base_checker(InputIterator b,InputIterator e)115 base_checker(InputIterator b, InputIterator e)
116 : tree_(b, e), const_tree_(tree_), checker_(b, e) {}
117
begin()118 iterator begin() { return tree_.begin(); }
begin() const119 const_iterator begin() const { return tree_.begin(); }
end()120 iterator end() { return tree_.end(); }
end() const121 const_iterator end() const { return tree_.end(); }
rbegin()122 reverse_iterator rbegin() { return tree_.rbegin(); }
rbegin() const123 const_reverse_iterator rbegin() const { return tree_.rbegin(); }
rend()124 reverse_iterator rend() { return tree_.rend(); }
rend() const125 const_reverse_iterator rend() const { return tree_.rend(); }
126
127 template <typename IterType, typename CheckerIterType>
iter_check(IterType tree_iter,CheckerIterType checker_iter) const128 IterType iter_check(IterType tree_iter, CheckerIterType checker_iter) const {
129 if (tree_iter == tree_.end()) {
130 ABSL_INTERNAL_CHECK(checker_iter == checker_.end(),
131 "Checker iterator not at end.");
132 } else {
133 CheckPairEquals(*tree_iter, *checker_iter);
134 }
135 return tree_iter;
136 }
137 template <typename IterType, typename CheckerIterType>
riter_check(IterType tree_iter,CheckerIterType checker_iter) const138 IterType riter_check(IterType tree_iter, CheckerIterType checker_iter) const {
139 if (tree_iter == tree_.rend()) {
140 ABSL_INTERNAL_CHECK(checker_iter == checker_.rend(),
141 "Checker iterator not at rend.");
142 } else {
143 CheckPairEquals(*tree_iter, *checker_iter);
144 }
145 return tree_iter;
146 }
value_check(const value_type & v)147 void value_check(const value_type &v) {
148 typename KeyOfValue<typename TreeType::key_type,
149 typename TreeType::value_type>::type key_of_value;
150 const key_type &key = key_of_value(v);
151 CheckPairEquals(*find(key), v);
152 lower_bound(key);
153 upper_bound(key);
154 equal_range(key);
155 contains(key);
156 count(key);
157 }
erase_check(const key_type & key)158 void erase_check(const key_type &key) {
159 EXPECT_FALSE(tree_.contains(key));
160 EXPECT_EQ(tree_.find(key), const_tree_.end());
161 EXPECT_FALSE(const_tree_.contains(key));
162 EXPECT_EQ(const_tree_.find(key), tree_.end());
163 EXPECT_EQ(tree_.equal_range(key).first,
164 const_tree_.equal_range(key).second);
165 }
166
lower_bound(const key_type & key)167 iterator lower_bound(const key_type &key) {
168 return iter_check(tree_.lower_bound(key), checker_.lower_bound(key));
169 }
lower_bound(const key_type & key) const170 const_iterator lower_bound(const key_type &key) const {
171 return iter_check(tree_.lower_bound(key), checker_.lower_bound(key));
172 }
upper_bound(const key_type & key)173 iterator upper_bound(const key_type &key) {
174 return iter_check(tree_.upper_bound(key), checker_.upper_bound(key));
175 }
upper_bound(const key_type & key) const176 const_iterator upper_bound(const key_type &key) const {
177 return iter_check(tree_.upper_bound(key), checker_.upper_bound(key));
178 }
equal_range(const key_type & key)179 std::pair<iterator, iterator> equal_range(const key_type &key) {
180 std::pair<typename CheckerType::iterator, typename CheckerType::iterator>
181 checker_res = checker_.equal_range(key);
182 std::pair<iterator, iterator> tree_res = tree_.equal_range(key);
183 iter_check(tree_res.first, checker_res.first);
184 iter_check(tree_res.second, checker_res.second);
185 return tree_res;
186 }
equal_range(const key_type & key) const187 std::pair<const_iterator, const_iterator> equal_range(
188 const key_type &key) const {
189 std::pair<typename CheckerType::const_iterator,
190 typename CheckerType::const_iterator>
191 checker_res = checker_.equal_range(key);
192 std::pair<const_iterator, const_iterator> tree_res = tree_.equal_range(key);
193 iter_check(tree_res.first, checker_res.first);
194 iter_check(tree_res.second, checker_res.second);
195 return tree_res;
196 }
find(const key_type & key)197 iterator find(const key_type &key) {
198 return iter_check(tree_.find(key), checker_.find(key));
199 }
find(const key_type & key) const200 const_iterator find(const key_type &key) const {
201 return iter_check(tree_.find(key), checker_.find(key));
202 }
contains(const key_type & key) const203 bool contains(const key_type &key) const { return find(key) != end(); }
count(const key_type & key) const204 size_type count(const key_type &key) const {
205 size_type res = checker_.count(key);
206 EXPECT_EQ(res, tree_.count(key));
207 return res;
208 }
209
operator =(const base_checker & other)210 base_checker &operator=(const base_checker &other) {
211 tree_ = other.tree_;
212 checker_ = other.checker_;
213 return *this;
214 }
215
erase(const key_type & key)216 int erase(const key_type &key) {
217 int size = tree_.size();
218 int res = checker_.erase(key);
219 EXPECT_EQ(res, tree_.count(key));
220 EXPECT_EQ(res, tree_.erase(key));
221 EXPECT_EQ(tree_.count(key), 0);
222 EXPECT_EQ(tree_.size(), size - res);
223 erase_check(key);
224 return res;
225 }
erase(iterator iter)226 iterator erase(iterator iter) {
227 key_type key = iter.key();
228 int size = tree_.size();
229 int count = tree_.count(key);
230 auto checker_iter = checker_.lower_bound(key);
231 for (iterator tmp(tree_.lower_bound(key)); tmp != iter; ++tmp) {
232 ++checker_iter;
233 }
234 auto checker_next = checker_iter;
235 ++checker_next;
236 checker_.erase(checker_iter);
237 iter = tree_.erase(iter);
238 EXPECT_EQ(tree_.size(), checker_.size());
239 EXPECT_EQ(tree_.size(), size - 1);
240 EXPECT_EQ(tree_.count(key), count - 1);
241 if (count == 1) {
242 erase_check(key);
243 }
244 return iter_check(iter, checker_next);
245 }
246
erase(iterator begin,iterator end)247 void erase(iterator begin, iterator end) {
248 int size = tree_.size();
249 int count = std::distance(begin, end);
250 auto checker_begin = checker_.lower_bound(begin.key());
251 for (iterator tmp(tree_.lower_bound(begin.key())); tmp != begin; ++tmp) {
252 ++checker_begin;
253 }
254 auto checker_end =
255 end == tree_.end() ? checker_.end() : checker_.lower_bound(end.key());
256 if (end != tree_.end()) {
257 for (iterator tmp(tree_.lower_bound(end.key())); tmp != end; ++tmp) {
258 ++checker_end;
259 }
260 }
261 const auto checker_ret = checker_.erase(checker_begin, checker_end);
262 const auto tree_ret = tree_.erase(begin, end);
263 EXPECT_EQ(std::distance(checker_.begin(), checker_ret),
264 std::distance(tree_.begin(), tree_ret));
265 EXPECT_EQ(tree_.size(), checker_.size());
266 EXPECT_EQ(tree_.size(), size - count);
267 }
268
clear()269 void clear() {
270 tree_.clear();
271 checker_.clear();
272 }
swap(base_checker & other)273 void swap(base_checker &other) {
274 tree_.swap(other.tree_);
275 checker_.swap(other.checker_);
276 }
277
verify() const278 void verify() const {
279 tree_.verify();
280 EXPECT_EQ(tree_.size(), checker_.size());
281
282 // Move through the forward iterators using increment.
283 auto checker_iter = checker_.begin();
284 const_iterator tree_iter(tree_.begin());
285 for (; tree_iter != tree_.end(); ++tree_iter, ++checker_iter) {
286 CheckPairEquals(*tree_iter, *checker_iter);
287 }
288
289 // Move through the forward iterators using decrement.
290 for (int n = tree_.size() - 1; n >= 0; --n) {
291 iter_check(tree_iter, checker_iter);
292 --tree_iter;
293 --checker_iter;
294 }
295 EXPECT_EQ(tree_iter, tree_.begin());
296 EXPECT_EQ(checker_iter, checker_.begin());
297
298 // Move through the reverse iterators using increment.
299 auto checker_riter = checker_.rbegin();
300 const_reverse_iterator tree_riter(tree_.rbegin());
301 for (; tree_riter != tree_.rend(); ++tree_riter, ++checker_riter) {
302 CheckPairEquals(*tree_riter, *checker_riter);
303 }
304
305 // Move through the reverse iterators using decrement.
306 for (int n = tree_.size() - 1; n >= 0; --n) {
307 riter_check(tree_riter, checker_riter);
308 --tree_riter;
309 --checker_riter;
310 }
311 EXPECT_EQ(tree_riter, tree_.rbegin());
312 EXPECT_EQ(checker_riter, checker_.rbegin());
313 }
314
tree() const315 const TreeType &tree() const { return tree_; }
316
size() const317 size_type size() const {
318 EXPECT_EQ(tree_.size(), checker_.size());
319 return tree_.size();
320 }
max_size() const321 size_type max_size() const { return tree_.max_size(); }
empty() const322 bool empty() const {
323 EXPECT_EQ(tree_.empty(), checker_.empty());
324 return tree_.empty();
325 }
326
327 protected:
328 TreeType tree_;
329 const TreeType &const_tree_;
330 CheckerType checker_;
331 };
332
333 namespace {
334 // A checker for unique sorted associative containers. TreeType is expected to
335 // be btree_{set,map} and CheckerType is expected to be {set,map}.
336 template <typename TreeType, typename CheckerType>
337 class unique_checker : public base_checker<TreeType, CheckerType> {
338 using super_type = base_checker<TreeType, CheckerType>;
339
340 public:
341 using iterator = typename super_type::iterator;
342 using value_type = typename super_type::value_type;
343
344 public:
unique_checker()345 unique_checker() : super_type() {}
unique_checker(const unique_checker & other)346 unique_checker(const unique_checker &other) : super_type(other) {}
347 template <class InputIterator>
unique_checker(InputIterator b,InputIterator e)348 unique_checker(InputIterator b, InputIterator e) : super_type(b, e) {}
349 unique_checker &operator=(const unique_checker &) = default;
350
351 // Insertion routines.
insert(const value_type & v)352 std::pair<iterator, bool> insert(const value_type &v) {
353 int size = this->tree_.size();
354 std::pair<typename CheckerType::iterator, bool> checker_res =
355 this->checker_.insert(v);
356 std::pair<iterator, bool> tree_res = this->tree_.insert(v);
357 CheckPairEquals(*tree_res.first, *checker_res.first);
358 EXPECT_EQ(tree_res.second, checker_res.second);
359 EXPECT_EQ(this->tree_.size(), this->checker_.size());
360 EXPECT_EQ(this->tree_.size(), size + tree_res.second);
361 return tree_res;
362 }
insert(iterator position,const value_type & v)363 iterator insert(iterator position, const value_type &v) {
364 int size = this->tree_.size();
365 std::pair<typename CheckerType::iterator, bool> checker_res =
366 this->checker_.insert(v);
367 iterator tree_res = this->tree_.insert(position, v);
368 CheckPairEquals(*tree_res, *checker_res.first);
369 EXPECT_EQ(this->tree_.size(), this->checker_.size());
370 EXPECT_EQ(this->tree_.size(), size + checker_res.second);
371 return tree_res;
372 }
373 template <typename InputIterator>
insert(InputIterator b,InputIterator e)374 void insert(InputIterator b, InputIterator e) {
375 for (; b != e; ++b) {
376 insert(*b);
377 }
378 }
379 };
380
381 // A checker for multiple sorted associative containers. TreeType is expected
382 // to be btree_{multiset,multimap} and CheckerType is expected to be
383 // {multiset,multimap}.
384 template <typename TreeType, typename CheckerType>
385 class multi_checker : public base_checker<TreeType, CheckerType> {
386 using super_type = base_checker<TreeType, CheckerType>;
387
388 public:
389 using iterator = typename super_type::iterator;
390 using value_type = typename super_type::value_type;
391
392 public:
multi_checker()393 multi_checker() : super_type() {}
multi_checker(const multi_checker & other)394 multi_checker(const multi_checker &other) : super_type(other) {}
395 template <class InputIterator>
multi_checker(InputIterator b,InputIterator e)396 multi_checker(InputIterator b, InputIterator e) : super_type(b, e) {}
397 multi_checker &operator=(const multi_checker &) = default;
398
399 // Insertion routines.
insert(const value_type & v)400 iterator insert(const value_type &v) {
401 int size = this->tree_.size();
402 auto checker_res = this->checker_.insert(v);
403 iterator tree_res = this->tree_.insert(v);
404 CheckPairEquals(*tree_res, *checker_res);
405 EXPECT_EQ(this->tree_.size(), this->checker_.size());
406 EXPECT_EQ(this->tree_.size(), size + 1);
407 return tree_res;
408 }
insert(iterator position,const value_type & v)409 iterator insert(iterator position, const value_type &v) {
410 int size = this->tree_.size();
411 auto checker_res = this->checker_.insert(v);
412 iterator tree_res = this->tree_.insert(position, v);
413 CheckPairEquals(*tree_res, *checker_res);
414 EXPECT_EQ(this->tree_.size(), this->checker_.size());
415 EXPECT_EQ(this->tree_.size(), size + 1);
416 return tree_res;
417 }
418 template <typename InputIterator>
insert(InputIterator b,InputIterator e)419 void insert(InputIterator b, InputIterator e) {
420 for (; b != e; ++b) {
421 insert(*b);
422 }
423 }
424 };
425
426 template <typename T, typename V>
DoTest(const char * name,T * b,const std::vector<V> & values)427 void DoTest(const char *name, T *b, const std::vector<V> &values) {
428 typename KeyOfValue<typename T::key_type, V>::type key_of_value;
429
430 T &mutable_b = *b;
431 const T &const_b = *b;
432
433 // Test insert.
434 for (int i = 0; i < values.size(); ++i) {
435 mutable_b.insert(values[i]);
436 mutable_b.value_check(values[i]);
437 }
438 ASSERT_EQ(mutable_b.size(), values.size());
439
440 const_b.verify();
441
442 // Test copy constructor.
443 T b_copy(const_b);
444 EXPECT_EQ(b_copy.size(), const_b.size());
445 for (int i = 0; i < values.size(); ++i) {
446 CheckPairEquals(*b_copy.find(key_of_value(values[i])), values[i]);
447 }
448
449 // Test range constructor.
450 T b_range(const_b.begin(), const_b.end());
451 EXPECT_EQ(b_range.size(), const_b.size());
452 for (int i = 0; i < values.size(); ++i) {
453 CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
454 }
455
456 // Test range insertion for values that already exist.
457 b_range.insert(b_copy.begin(), b_copy.end());
458 b_range.verify();
459
460 // Test range insertion for new values.
461 b_range.clear();
462 b_range.insert(b_copy.begin(), b_copy.end());
463 EXPECT_EQ(b_range.size(), b_copy.size());
464 for (int i = 0; i < values.size(); ++i) {
465 CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
466 }
467
468 // Test assignment to self. Nothing should change.
469 b_range.operator=(b_range);
470 EXPECT_EQ(b_range.size(), b_copy.size());
471
472 // Test assignment of new values.
473 b_range.clear();
474 b_range = b_copy;
475 EXPECT_EQ(b_range.size(), b_copy.size());
476
477 // Test swap.
478 b_range.clear();
479 b_range.swap(b_copy);
480 EXPECT_EQ(b_copy.size(), 0);
481 EXPECT_EQ(b_range.size(), const_b.size());
482 for (int i = 0; i < values.size(); ++i) {
483 CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
484 }
485 b_range.swap(b_copy);
486
487 // Test non-member function swap.
488 swap(b_range, b_copy);
489 EXPECT_EQ(b_copy.size(), 0);
490 EXPECT_EQ(b_range.size(), const_b.size());
491 for (int i = 0; i < values.size(); ++i) {
492 CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
493 }
494 swap(b_range, b_copy);
495
496 // Test erase via values.
497 for (int i = 0; i < values.size(); ++i) {
498 mutable_b.erase(key_of_value(values[i]));
499 // Erasing a non-existent key should have no effect.
500 ASSERT_EQ(mutable_b.erase(key_of_value(values[i])), 0);
501 }
502
503 const_b.verify();
504 EXPECT_EQ(const_b.size(), 0);
505
506 // Test erase via iterators.
507 mutable_b = b_copy;
508 for (int i = 0; i < values.size(); ++i) {
509 mutable_b.erase(mutable_b.find(key_of_value(values[i])));
510 }
511
512 const_b.verify();
513 EXPECT_EQ(const_b.size(), 0);
514
515 // Test insert with hint.
516 for (int i = 0; i < values.size(); i++) {
517 mutable_b.insert(mutable_b.upper_bound(key_of_value(values[i])), values[i]);
518 }
519
520 const_b.verify();
521
522 // Test range erase.
523 mutable_b.erase(mutable_b.begin(), mutable_b.end());
524 EXPECT_EQ(mutable_b.size(), 0);
525 const_b.verify();
526
527 // First half.
528 mutable_b = b_copy;
529 typename T::iterator mutable_iter_end = mutable_b.begin();
530 for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_end;
531 mutable_b.erase(mutable_b.begin(), mutable_iter_end);
532 EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 2);
533 const_b.verify();
534
535 // Second half.
536 mutable_b = b_copy;
537 typename T::iterator mutable_iter_begin = mutable_b.begin();
538 for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_begin;
539 mutable_b.erase(mutable_iter_begin, mutable_b.end());
540 EXPECT_EQ(mutable_b.size(), values.size() / 2);
541 const_b.verify();
542
543 // Second quarter.
544 mutable_b = b_copy;
545 mutable_iter_begin = mutable_b.begin();
546 for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_begin;
547 mutable_iter_end = mutable_iter_begin;
548 for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_end;
549 mutable_b.erase(mutable_iter_begin, mutable_iter_end);
550 EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 4);
551 const_b.verify();
552
553 mutable_b.clear();
554 }
555
556 template <typename T>
ConstTest()557 void ConstTest() {
558 using value_type = typename T::value_type;
559 typename KeyOfValue<typename T::key_type, value_type>::type key_of_value;
560
561 T mutable_b;
562 const T &const_b = mutable_b;
563
564 // Insert a single value into the container and test looking it up.
565 value_type value = Generator<value_type>(2)(2);
566 mutable_b.insert(value);
567 EXPECT_TRUE(mutable_b.contains(key_of_value(value)));
568 EXPECT_NE(mutable_b.find(key_of_value(value)), const_b.end());
569 EXPECT_TRUE(const_b.contains(key_of_value(value)));
570 EXPECT_NE(const_b.find(key_of_value(value)), mutable_b.end());
571 EXPECT_EQ(*const_b.lower_bound(key_of_value(value)), value);
572 EXPECT_EQ(const_b.upper_bound(key_of_value(value)), const_b.end());
573 EXPECT_EQ(*const_b.equal_range(key_of_value(value)).first, value);
574
575 // We can only create a non-const iterator from a non-const container.
576 typename T::iterator mutable_iter(mutable_b.begin());
577 EXPECT_EQ(mutable_iter, const_b.begin());
578 EXPECT_NE(mutable_iter, const_b.end());
579 EXPECT_EQ(const_b.begin(), mutable_iter);
580 EXPECT_NE(const_b.end(), mutable_iter);
581 typename T::reverse_iterator mutable_riter(mutable_b.rbegin());
582 EXPECT_EQ(mutable_riter, const_b.rbegin());
583 EXPECT_NE(mutable_riter, const_b.rend());
584 EXPECT_EQ(const_b.rbegin(), mutable_riter);
585 EXPECT_NE(const_b.rend(), mutable_riter);
586
587 // We can create a const iterator from a non-const iterator.
588 typename T::const_iterator const_iter(mutable_iter);
589 EXPECT_EQ(const_iter, mutable_b.begin());
590 EXPECT_NE(const_iter, mutable_b.end());
591 EXPECT_EQ(mutable_b.begin(), const_iter);
592 EXPECT_NE(mutable_b.end(), const_iter);
593 typename T::const_reverse_iterator const_riter(mutable_riter);
594 EXPECT_EQ(const_riter, mutable_b.rbegin());
595 EXPECT_NE(const_riter, mutable_b.rend());
596 EXPECT_EQ(mutable_b.rbegin(), const_riter);
597 EXPECT_NE(mutable_b.rend(), const_riter);
598
599 // Make sure various methods can be invoked on a const container.
600 const_b.verify();
601 ASSERT_TRUE(!const_b.empty());
602 EXPECT_EQ(const_b.size(), 1);
603 EXPECT_GT(const_b.max_size(), 0);
604 EXPECT_TRUE(const_b.contains(key_of_value(value)));
605 EXPECT_EQ(const_b.count(key_of_value(value)), 1);
606 }
607
608 template <typename T, typename C>
BtreeTest()609 void BtreeTest() {
610 ConstTest<T>();
611
612 using V = typename remove_pair_const<typename T::value_type>::type;
613 const std::vector<V> random_values = GenerateValuesWithSeed<V>(
614 absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values),
615 GTEST_FLAG_GET(random_seed));
616
617 unique_checker<T, C> container;
618
619 // Test key insertion/deletion in sorted order.
620 std::vector<V> sorted_values(random_values);
621 std::sort(sorted_values.begin(), sorted_values.end());
622 DoTest("sorted: ", &container, sorted_values);
623
624 // Test key insertion/deletion in reverse sorted order.
625 std::reverse(sorted_values.begin(), sorted_values.end());
626 DoTest("rsorted: ", &container, sorted_values);
627
628 // Test key insertion/deletion in random order.
629 DoTest("random: ", &container, random_values);
630 }
631
632 template <typename T, typename C>
BtreeMultiTest()633 void BtreeMultiTest() {
634 ConstTest<T>();
635
636 using V = typename remove_pair_const<typename T::value_type>::type;
637 const std::vector<V> random_values = GenerateValuesWithSeed<V>(
638 absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values),
639 GTEST_FLAG_GET(random_seed));
640
641 multi_checker<T, C> container;
642
643 // Test keys in sorted order.
644 std::vector<V> sorted_values(random_values);
645 std::sort(sorted_values.begin(), sorted_values.end());
646 DoTest("sorted: ", &container, sorted_values);
647
648 // Test keys in reverse sorted order.
649 std::reverse(sorted_values.begin(), sorted_values.end());
650 DoTest("rsorted: ", &container, sorted_values);
651
652 // Test keys in random order.
653 DoTest("random: ", &container, random_values);
654
655 // Test keys in random order w/ duplicates.
656 std::vector<V> duplicate_values(random_values);
657 duplicate_values.insert(duplicate_values.end(), random_values.begin(),
658 random_values.end());
659 DoTest("duplicates:", &container, duplicate_values);
660
661 // Test all identical keys.
662 std::vector<V> identical_values(100);
663 std::fill(identical_values.begin(), identical_values.end(),
664 Generator<V>(2)(2));
665 DoTest("identical: ", &container, identical_values);
666 }
667
668 template <typename T>
669 struct PropagatingCountingAlloc : public CountingAllocator<T> {
670 using propagate_on_container_copy_assignment = std::true_type;
671 using propagate_on_container_move_assignment = std::true_type;
672 using propagate_on_container_swap = std::true_type;
673
674 using Base = CountingAllocator<T>;
675 using Base::Base;
676
677 template <typename U>
PropagatingCountingAllocabsl::container_internal::__anon2a41e4430311::PropagatingCountingAlloc678 explicit PropagatingCountingAlloc(const PropagatingCountingAlloc<U> &other)
679 : Base(other.bytes_used_) {}
680
681 template <typename U>
682 struct rebind {
683 using other = PropagatingCountingAlloc<U>;
684 };
685 };
686
687 template <typename T>
BtreeAllocatorTest()688 void BtreeAllocatorTest() {
689 using value_type = typename T::value_type;
690
691 int64_t bytes1 = 0, bytes2 = 0;
692 PropagatingCountingAlloc<T> allocator1(&bytes1);
693 PropagatingCountingAlloc<T> allocator2(&bytes2);
694 Generator<value_type> generator(1000);
695
696 // Test that we allocate properly aligned memory. If we don't, then Layout
697 // will assert fail.
698 auto unused1 = allocator1.allocate(1);
699 auto unused2 = allocator2.allocate(1);
700
701 // Test copy assignment
702 {
703 T b1(typename T::key_compare(), allocator1);
704 T b2(typename T::key_compare(), allocator2);
705
706 int64_t original_bytes1 = bytes1;
707 b1.insert(generator(0));
708 EXPECT_GT(bytes1, original_bytes1);
709
710 // This should propagate the allocator.
711 b1 = b2;
712 EXPECT_EQ(b1.size(), 0);
713 EXPECT_EQ(b2.size(), 0);
714 EXPECT_EQ(bytes1, original_bytes1);
715
716 for (int i = 1; i < 1000; i++) {
717 b1.insert(generator(i));
718 }
719
720 // We should have allocated out of allocator2.
721 EXPECT_GT(bytes2, bytes1);
722 }
723
724 // Test move assignment
725 {
726 T b1(typename T::key_compare(), allocator1);
727 T b2(typename T::key_compare(), allocator2);
728
729 int64_t original_bytes1 = bytes1;
730 b1.insert(generator(0));
731 EXPECT_GT(bytes1, original_bytes1);
732
733 // This should propagate the allocator.
734 b1 = std::move(b2);
735 EXPECT_EQ(b1.size(), 0);
736 EXPECT_EQ(bytes1, original_bytes1);
737
738 for (int i = 1; i < 1000; i++) {
739 b1.insert(generator(i));
740 }
741
742 // We should have allocated out of allocator2.
743 EXPECT_GT(bytes2, bytes1);
744 }
745
746 // Test swap
747 {
748 T b1(typename T::key_compare(), allocator1);
749 T b2(typename T::key_compare(), allocator2);
750
751 int64_t original_bytes1 = bytes1;
752 b1.insert(generator(0));
753 EXPECT_GT(bytes1, original_bytes1);
754
755 // This should swap the allocators.
756 swap(b1, b2);
757 EXPECT_EQ(b1.size(), 0);
758 EXPECT_EQ(b2.size(), 1);
759 EXPECT_GT(bytes1, original_bytes1);
760
761 for (int i = 1; i < 1000; i++) {
762 b1.insert(generator(i));
763 }
764
765 // We should have allocated out of allocator2.
766 EXPECT_GT(bytes2, bytes1);
767 }
768
769 allocator1.deallocate(unused1, 1);
770 allocator2.deallocate(unused2, 1);
771 }
772
773 template <typename T>
BtreeMapTest()774 void BtreeMapTest() {
775 using value_type = typename T::value_type;
776 using mapped_type = typename T::mapped_type;
777
778 mapped_type m = Generator<mapped_type>(0)(0);
779 (void)m;
780
781 T b;
782
783 // Verify we can insert using operator[].
784 for (int i = 0; i < 1000; i++) {
785 value_type v = Generator<value_type>(1000)(i);
786 b[v.first] = v.second;
787 }
788 EXPECT_EQ(b.size(), 1000);
789
790 // Test whether we can use the "->" operator on iterators and
791 // reverse_iterators. This stresses the btree_map_params::pair_pointer
792 // mechanism.
793 EXPECT_EQ(b.begin()->first, Generator<value_type>(1000)(0).first);
794 EXPECT_EQ(b.begin()->second, Generator<value_type>(1000)(0).second);
795 EXPECT_EQ(b.rbegin()->first, Generator<value_type>(1000)(999).first);
796 EXPECT_EQ(b.rbegin()->second, Generator<value_type>(1000)(999).second);
797 }
798
799 template <typename T>
BtreeMultiMapTest()800 void BtreeMultiMapTest() {
801 using mapped_type = typename T::mapped_type;
802 mapped_type m = Generator<mapped_type>(0)(0);
803 (void)m;
804 }
805
806 template <typename K, int N = 256>
SetTest()807 void SetTest() {
808 EXPECT_EQ(
809 sizeof(absl::btree_set<K>),
810 2 * sizeof(void *) + sizeof(typename absl::btree_set<K>::size_type));
811 using BtreeSet = absl::btree_set<K>;
812 using CountingBtreeSet =
813 absl::btree_set<K, std::less<K>, PropagatingCountingAlloc<K>>;
814 BtreeTest<BtreeSet, std::set<K>>();
815 BtreeAllocatorTest<CountingBtreeSet>();
816 }
817
818 template <typename K, int N = 256>
MapTest()819 void MapTest() {
820 EXPECT_EQ(
821 sizeof(absl::btree_map<K, K>),
822 2 * sizeof(void *) + sizeof(typename absl::btree_map<K, K>::size_type));
823 using BtreeMap = absl::btree_map<K, K>;
824 using CountingBtreeMap =
825 absl::btree_map<K, K, std::less<K>,
826 PropagatingCountingAlloc<std::pair<const K, K>>>;
827 BtreeTest<BtreeMap, std::map<K, K>>();
828 BtreeAllocatorTest<CountingBtreeMap>();
829 BtreeMapTest<BtreeMap>();
830 }
831
TEST(Btree,set_int32)832 TEST(Btree, set_int32) { SetTest<int32_t>(); }
TEST(Btree,set_int64)833 TEST(Btree, set_int64) { SetTest<int64_t>(); }
TEST(Btree,set_string)834 TEST(Btree, set_string) { SetTest<std::string>(); }
TEST(Btree,set_cord)835 TEST(Btree, set_cord) { SetTest<absl::Cord>(); }
TEST(Btree,set_pair)836 TEST(Btree, set_pair) { SetTest<std::pair<int, int>>(); }
TEST(Btree,map_int32)837 TEST(Btree, map_int32) { MapTest<int32_t>(); }
TEST(Btree,map_int64)838 TEST(Btree, map_int64) { MapTest<int64_t>(); }
TEST(Btree,map_string)839 TEST(Btree, map_string) { MapTest<std::string>(); }
TEST(Btree,map_cord)840 TEST(Btree, map_cord) { MapTest<absl::Cord>(); }
TEST(Btree,map_pair)841 TEST(Btree, map_pair) { MapTest<std::pair<int, int>>(); }
842
843 template <typename K, int N = 256>
MultiSetTest()844 void MultiSetTest() {
845 EXPECT_EQ(
846 sizeof(absl::btree_multiset<K>),
847 2 * sizeof(void *) + sizeof(typename absl::btree_multiset<K>::size_type));
848 using BtreeMSet = absl::btree_multiset<K>;
849 using CountingBtreeMSet =
850 absl::btree_multiset<K, std::less<K>, PropagatingCountingAlloc<K>>;
851 BtreeMultiTest<BtreeMSet, std::multiset<K>>();
852 BtreeAllocatorTest<CountingBtreeMSet>();
853 }
854
855 template <typename K, int N = 256>
MultiMapTest()856 void MultiMapTest() {
857 EXPECT_EQ(sizeof(absl::btree_multimap<K, K>),
858 2 * sizeof(void *) +
859 sizeof(typename absl::btree_multimap<K, K>::size_type));
860 using BtreeMMap = absl::btree_multimap<K, K>;
861 using CountingBtreeMMap =
862 absl::btree_multimap<K, K, std::less<K>,
863 PropagatingCountingAlloc<std::pair<const K, K>>>;
864 BtreeMultiTest<BtreeMMap, std::multimap<K, K>>();
865 BtreeMultiMapTest<BtreeMMap>();
866 BtreeAllocatorTest<CountingBtreeMMap>();
867 }
868
TEST(Btree,multiset_int32)869 TEST(Btree, multiset_int32) { MultiSetTest<int32_t>(); }
TEST(Btree,multiset_int64)870 TEST(Btree, multiset_int64) { MultiSetTest<int64_t>(); }
TEST(Btree,multiset_string)871 TEST(Btree, multiset_string) { MultiSetTest<std::string>(); }
TEST(Btree,multiset_cord)872 TEST(Btree, multiset_cord) { MultiSetTest<absl::Cord>(); }
TEST(Btree,multiset_pair)873 TEST(Btree, multiset_pair) { MultiSetTest<std::pair<int, int>>(); }
TEST(Btree,multimap_int32)874 TEST(Btree, multimap_int32) { MultiMapTest<int32_t>(); }
TEST(Btree,multimap_int64)875 TEST(Btree, multimap_int64) { MultiMapTest<int64_t>(); }
TEST(Btree,multimap_string)876 TEST(Btree, multimap_string) { MultiMapTest<std::string>(); }
TEST(Btree,multimap_cord)877 TEST(Btree, multimap_cord) { MultiMapTest<absl::Cord>(); }
TEST(Btree,multimap_pair)878 TEST(Btree, multimap_pair) { MultiMapTest<std::pair<int, int>>(); }
879
880 struct CompareIntToString {
operator ()absl::container_internal::__anon2a41e4430311::CompareIntToString881 bool operator()(const std::string &a, const std::string &b) const {
882 return a < b;
883 }
operator ()absl::container_internal::__anon2a41e4430311::CompareIntToString884 bool operator()(const std::string &a, int b) const {
885 return a < absl::StrCat(b);
886 }
operator ()absl::container_internal::__anon2a41e4430311::CompareIntToString887 bool operator()(int a, const std::string &b) const {
888 return absl::StrCat(a) < b;
889 }
890 using is_transparent = void;
891 };
892
893 struct NonTransparentCompare {
894 template <typename T, typename U>
operator ()absl::container_internal::__anon2a41e4430311::NonTransparentCompare895 bool operator()(const T &t, const U &u) const {
896 // Treating all comparators as transparent can cause inefficiencies (see
897 // N3657 C++ proposal). Test that for comparators without 'is_transparent'
898 // alias (like this one), we do not attempt heterogeneous lookup.
899 EXPECT_TRUE((std::is_same<T, U>()));
900 return t < u;
901 }
902 };
903
904 template <typename T>
905 bool CanEraseWithEmptyBrace(T t, decltype(t.erase({})) *) {
906 return true;
907 }
908
909 template <typename T>
CanEraseWithEmptyBrace(T,...)910 bool CanEraseWithEmptyBrace(T, ...) {
911 return false;
912 }
913
914 template <typename T>
TestHeterogeneous(T table)915 void TestHeterogeneous(T table) {
916 auto lb = table.lower_bound("3");
917 EXPECT_EQ(lb, table.lower_bound(3));
918 EXPECT_NE(lb, table.lower_bound(4));
919 EXPECT_EQ(lb, table.lower_bound({"3"}));
920 EXPECT_NE(lb, table.lower_bound({}));
921
922 auto ub = table.upper_bound("3");
923 EXPECT_EQ(ub, table.upper_bound(3));
924 EXPECT_NE(ub, table.upper_bound(5));
925 EXPECT_EQ(ub, table.upper_bound({"3"}));
926 EXPECT_NE(ub, table.upper_bound({}));
927
928 auto er = table.equal_range("3");
929 EXPECT_EQ(er, table.equal_range(3));
930 EXPECT_NE(er, table.equal_range(4));
931 EXPECT_EQ(er, table.equal_range({"3"}));
932 EXPECT_NE(er, table.equal_range({}));
933
934 auto it = table.find("3");
935 EXPECT_EQ(it, table.find(3));
936 EXPECT_NE(it, table.find(4));
937 EXPECT_EQ(it, table.find({"3"}));
938 EXPECT_NE(it, table.find({}));
939
940 EXPECT_TRUE(table.contains(3));
941 EXPECT_FALSE(table.contains(4));
942 EXPECT_TRUE(table.count({"3"}));
943 EXPECT_FALSE(table.contains({}));
944
945 EXPECT_EQ(1, table.count(3));
946 EXPECT_EQ(0, table.count(4));
947 EXPECT_EQ(1, table.count({"3"}));
948 EXPECT_EQ(0, table.count({}));
949
950 auto copy = table;
951 copy.erase(3);
952 EXPECT_EQ(table.size() - 1, copy.size());
953 copy.erase(4);
954 EXPECT_EQ(table.size() - 1, copy.size());
955 copy.erase({"5"});
956 EXPECT_EQ(table.size() - 2, copy.size());
957 EXPECT_FALSE(CanEraseWithEmptyBrace(table, nullptr));
958
959 // Also run it with const T&.
960 if (std::is_class<T>()) TestHeterogeneous<const T &>(table);
961 }
962
TEST(Btree,HeterogeneousLookup)963 TEST(Btree, HeterogeneousLookup) {
964 TestHeterogeneous(btree_set<std::string, CompareIntToString>{"1", "3", "5"});
965 TestHeterogeneous(btree_map<std::string, int, CompareIntToString>{
966 {"1", 1}, {"3", 3}, {"5", 5}});
967 TestHeterogeneous(
968 btree_multiset<std::string, CompareIntToString>{"1", "3", "5"});
969 TestHeterogeneous(btree_multimap<std::string, int, CompareIntToString>{
970 {"1", 1}, {"3", 3}, {"5", 5}});
971
972 // Only maps have .at()
973 btree_map<std::string, int, CompareIntToString> map{
974 {"", -1}, {"1", 1}, {"3", 3}, {"5", 5}};
975 EXPECT_EQ(1, map.at(1));
976 EXPECT_EQ(3, map.at({"3"}));
977 EXPECT_EQ(-1, map.at({}));
978 const auto &cmap = map;
979 EXPECT_EQ(1, cmap.at(1));
980 EXPECT_EQ(3, cmap.at({"3"}));
981 EXPECT_EQ(-1, cmap.at({}));
982 }
983
TEST(Btree,NoHeterogeneousLookupWithoutAlias)984 TEST(Btree, NoHeterogeneousLookupWithoutAlias) {
985 using StringSet = absl::btree_set<std::string, NonTransparentCompare>;
986 StringSet s;
987 ASSERT_TRUE(s.insert("hello").second);
988 ASSERT_TRUE(s.insert("world").second);
989 EXPECT_TRUE(s.end() == s.find("blah"));
990 EXPECT_TRUE(s.begin() == s.lower_bound("hello"));
991 EXPECT_EQ(1, s.count("world"));
992 EXPECT_TRUE(s.contains("hello"));
993 EXPECT_TRUE(s.contains("world"));
994 EXPECT_FALSE(s.contains("blah"));
995
996 using StringMultiSet =
997 absl::btree_multiset<std::string, NonTransparentCompare>;
998 StringMultiSet ms;
999 ms.insert("hello");
1000 ms.insert("world");
1001 ms.insert("world");
1002 EXPECT_TRUE(ms.end() == ms.find("blah"));
1003 EXPECT_TRUE(ms.begin() == ms.lower_bound("hello"));
1004 EXPECT_EQ(2, ms.count("world"));
1005 EXPECT_TRUE(ms.contains("hello"));
1006 EXPECT_TRUE(ms.contains("world"));
1007 EXPECT_FALSE(ms.contains("blah"));
1008 }
1009
TEST(Btree,DefaultTransparent)1010 TEST(Btree, DefaultTransparent) {
1011 {
1012 // `int` does not have a default transparent comparator.
1013 // The input value is converted to key_type.
1014 btree_set<int> s = {1};
1015 double d = 1.1;
1016 EXPECT_EQ(s.begin(), s.find(d));
1017 EXPECT_TRUE(s.contains(d));
1018 }
1019
1020 {
1021 // `std::string` has heterogeneous support.
1022 btree_set<std::string> s = {"A"};
1023 EXPECT_EQ(s.begin(), s.find(absl::string_view("A")));
1024 EXPECT_TRUE(s.contains(absl::string_view("A")));
1025 }
1026 }
1027
1028 class StringLike {
1029 public:
1030 StringLike() = default;
1031
StringLike(const char * s)1032 StringLike(const char *s) : s_(s) { // NOLINT
1033 ++constructor_calls_;
1034 }
1035
operator <(const StringLike & a) const1036 bool operator<(const StringLike &a) const { return s_ < a.s_; }
1037
clear_constructor_call_count()1038 static void clear_constructor_call_count() { constructor_calls_ = 0; }
1039
constructor_calls()1040 static int constructor_calls() { return constructor_calls_; }
1041
1042 private:
1043 static int constructor_calls_;
1044 std::string s_;
1045 };
1046
1047 int StringLike::constructor_calls_ = 0;
1048
TEST(Btree,HeterogeneousLookupDoesntDegradePerformance)1049 TEST(Btree, HeterogeneousLookupDoesntDegradePerformance) {
1050 using StringSet = absl::btree_set<StringLike>;
1051 StringSet s;
1052 for (int i = 0; i < 100; ++i) {
1053 ASSERT_TRUE(s.insert(absl::StrCat(i).c_str()).second);
1054 }
1055 StringLike::clear_constructor_call_count();
1056 s.find("50");
1057 ASSERT_EQ(1, StringLike::constructor_calls());
1058
1059 StringLike::clear_constructor_call_count();
1060 s.contains("50");
1061 ASSERT_EQ(1, StringLike::constructor_calls());
1062
1063 StringLike::clear_constructor_call_count();
1064 s.count("50");
1065 ASSERT_EQ(1, StringLike::constructor_calls());
1066
1067 StringLike::clear_constructor_call_count();
1068 s.lower_bound("50");
1069 ASSERT_EQ(1, StringLike::constructor_calls());
1070
1071 StringLike::clear_constructor_call_count();
1072 s.upper_bound("50");
1073 ASSERT_EQ(1, StringLike::constructor_calls());
1074
1075 StringLike::clear_constructor_call_count();
1076 s.equal_range("50");
1077 ASSERT_EQ(1, StringLike::constructor_calls());
1078
1079 StringLike::clear_constructor_call_count();
1080 s.erase("50");
1081 ASSERT_EQ(1, StringLike::constructor_calls());
1082 }
1083
1084 // Verify that swapping btrees swaps the key comparison functors and that we can
1085 // use non-default constructible comparators.
1086 struct SubstringLess {
1087 SubstringLess() = delete;
SubstringLessabsl::container_internal::__anon2a41e4430311::SubstringLess1088 explicit SubstringLess(int length) : n(length) {}
operator ()absl::container_internal::__anon2a41e4430311::SubstringLess1089 bool operator()(const std::string &a, const std::string &b) const {
1090 return absl::string_view(a).substr(0, n) <
1091 absl::string_view(b).substr(0, n);
1092 }
1093 int n;
1094 };
1095
TEST(Btree,SwapKeyCompare)1096 TEST(Btree, SwapKeyCompare) {
1097 using SubstringSet = absl::btree_set<std::string, SubstringLess>;
1098 SubstringSet s1(SubstringLess(1), SubstringSet::allocator_type());
1099 SubstringSet s2(SubstringLess(2), SubstringSet::allocator_type());
1100
1101 ASSERT_TRUE(s1.insert("a").second);
1102 ASSERT_FALSE(s1.insert("aa").second);
1103
1104 ASSERT_TRUE(s2.insert("a").second);
1105 ASSERT_TRUE(s2.insert("aa").second);
1106 ASSERT_FALSE(s2.insert("aaa").second);
1107
1108 swap(s1, s2);
1109
1110 ASSERT_TRUE(s1.insert("b").second);
1111 ASSERT_TRUE(s1.insert("bb").second);
1112 ASSERT_FALSE(s1.insert("bbb").second);
1113
1114 ASSERT_TRUE(s2.insert("b").second);
1115 ASSERT_FALSE(s2.insert("bb").second);
1116 }
1117
TEST(Btree,UpperBoundRegression)1118 TEST(Btree, UpperBoundRegression) {
1119 // Regress a bug where upper_bound would default-construct a new key_compare
1120 // instead of copying the existing one.
1121 using SubstringSet = absl::btree_set<std::string, SubstringLess>;
1122 SubstringSet my_set(SubstringLess(3));
1123 my_set.insert("aab");
1124 my_set.insert("abb");
1125 // We call upper_bound("aaa"). If this correctly uses the length 3
1126 // comparator, aaa < aab < abb, so we should get aab as the result.
1127 // If it instead uses the default-constructed length 2 comparator,
1128 // aa == aa < ab, so we'll get abb as our result.
1129 SubstringSet::iterator it = my_set.upper_bound("aaa");
1130 ASSERT_TRUE(it != my_set.end());
1131 EXPECT_EQ("aab", *it);
1132 }
1133
TEST(Btree,Comparison)1134 TEST(Btree, Comparison) {
1135 const int kSetSize = 1201;
1136 absl::btree_set<int64_t> my_set;
1137 for (int i = 0; i < kSetSize; ++i) {
1138 my_set.insert(i);
1139 }
1140 absl::btree_set<int64_t> my_set_copy(my_set);
1141 EXPECT_TRUE(my_set_copy == my_set);
1142 EXPECT_TRUE(my_set == my_set_copy);
1143 EXPECT_FALSE(my_set_copy != my_set);
1144 EXPECT_FALSE(my_set != my_set_copy);
1145
1146 my_set.insert(kSetSize);
1147 EXPECT_FALSE(my_set_copy == my_set);
1148 EXPECT_FALSE(my_set == my_set_copy);
1149 EXPECT_TRUE(my_set_copy != my_set);
1150 EXPECT_TRUE(my_set != my_set_copy);
1151
1152 my_set.erase(kSetSize - 1);
1153 EXPECT_FALSE(my_set_copy == my_set);
1154 EXPECT_FALSE(my_set == my_set_copy);
1155 EXPECT_TRUE(my_set_copy != my_set);
1156 EXPECT_TRUE(my_set != my_set_copy);
1157
1158 absl::btree_map<std::string, int64_t> my_map;
1159 for (int i = 0; i < kSetSize; ++i) {
1160 my_map[std::string(i, 'a')] = i;
1161 }
1162 absl::btree_map<std::string, int64_t> my_map_copy(my_map);
1163 EXPECT_TRUE(my_map_copy == my_map);
1164 EXPECT_TRUE(my_map == my_map_copy);
1165 EXPECT_FALSE(my_map_copy != my_map);
1166 EXPECT_FALSE(my_map != my_map_copy);
1167
1168 ++my_map_copy[std::string(7, 'a')];
1169 EXPECT_FALSE(my_map_copy == my_map);
1170 EXPECT_FALSE(my_map == my_map_copy);
1171 EXPECT_TRUE(my_map_copy != my_map);
1172 EXPECT_TRUE(my_map != my_map_copy);
1173
1174 my_map_copy = my_map;
1175 my_map["hello"] = kSetSize;
1176 EXPECT_FALSE(my_map_copy == my_map);
1177 EXPECT_FALSE(my_map == my_map_copy);
1178 EXPECT_TRUE(my_map_copy != my_map);
1179 EXPECT_TRUE(my_map != my_map_copy);
1180
1181 my_map.erase(std::string(kSetSize - 1, 'a'));
1182 EXPECT_FALSE(my_map_copy == my_map);
1183 EXPECT_FALSE(my_map == my_map_copy);
1184 EXPECT_TRUE(my_map_copy != my_map);
1185 EXPECT_TRUE(my_map != my_map_copy);
1186 }
1187
TEST(Btree,RangeCtorSanity)1188 TEST(Btree, RangeCtorSanity) {
1189 std::vector<int> ivec;
1190 ivec.push_back(1);
1191 std::map<int, int> imap;
1192 imap.insert(std::make_pair(1, 2));
1193 absl::btree_multiset<int> tmset(ivec.begin(), ivec.end());
1194 absl::btree_multimap<int, int> tmmap(imap.begin(), imap.end());
1195 absl::btree_set<int> tset(ivec.begin(), ivec.end());
1196 absl::btree_map<int, int> tmap(imap.begin(), imap.end());
1197 EXPECT_EQ(1, tmset.size());
1198 EXPECT_EQ(1, tmmap.size());
1199 EXPECT_EQ(1, tset.size());
1200 EXPECT_EQ(1, tmap.size());
1201 }
1202
1203 } // namespace
1204
1205 class BtreeNodePeer {
1206 public:
1207 // Yields the size of a leaf node with a specific number of values.
1208 template <typename ValueType>
GetTargetNodeSize(size_t target_values_per_node)1209 constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
1210 return btree_node<
1211 set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
1212 /*TargetNodeSize=*/256, // This parameter isn't used here.
1213 /*Multi=*/false>>::SizeWithNSlots(target_values_per_node);
1214 }
1215
1216 // Yields the number of slots in a (non-root) leaf node for this btree.
1217 template <typename Btree>
GetNumSlotsPerNode()1218 constexpr static size_t GetNumSlotsPerNode() {
1219 return btree_node<typename Btree::params_type>::kNodeSlots;
1220 }
1221
1222 template <typename Btree>
GetMaxFieldType()1223 constexpr static size_t GetMaxFieldType() {
1224 return std::numeric_limits<
1225 typename btree_node<typename Btree::params_type>::field_type>::max();
1226 }
1227
1228 template <typename Btree>
UsesLinearNodeSearch()1229 constexpr static bool UsesLinearNodeSearch() {
1230 return btree_node<typename Btree::params_type>::use_linear_search::value;
1231 }
1232
1233 template <typename Btree>
UsesGenerations()1234 constexpr static bool UsesGenerations() {
1235 return Btree::params_type::kEnableGenerations;
1236 }
1237 };
1238
1239 namespace {
1240
1241 class BtreeMapTest : public ::testing::Test {
1242 public:
1243 struct Key {};
1244 struct Cmp {
1245 template <typename T>
operator ()absl::container_internal::__anon2a41e4430411::BtreeMapTest::Cmp1246 bool operator()(T, T) const {
1247 return false;
1248 }
1249 };
1250
1251 struct KeyLin {
1252 using absl_btree_prefer_linear_node_search = std::true_type;
1253 };
1254 struct CmpLin : Cmp {
1255 using absl_btree_prefer_linear_node_search = std::true_type;
1256 };
1257
1258 struct KeyBin {
1259 using absl_btree_prefer_linear_node_search = std::false_type;
1260 };
1261 struct CmpBin : Cmp {
1262 using absl_btree_prefer_linear_node_search = std::false_type;
1263 };
1264
1265 template <typename K, typename C>
IsLinear()1266 static bool IsLinear() {
1267 return BtreeNodePeer::UsesLinearNodeSearch<absl::btree_map<K, int, C>>();
1268 }
1269 };
1270
TEST_F(BtreeMapTest,TestLinearSearchPreferredForKeyLinearViaAlias)1271 TEST_F(BtreeMapTest, TestLinearSearchPreferredForKeyLinearViaAlias) {
1272 // Test requesting linear search by directly exporting an alias.
1273 EXPECT_FALSE((IsLinear<Key, Cmp>()));
1274 EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
1275 EXPECT_TRUE((IsLinear<Key, CmpLin>()));
1276 EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
1277 }
1278
TEST_F(BtreeMapTest,LinearChoiceTree)1279 TEST_F(BtreeMapTest, LinearChoiceTree) {
1280 // Cmp has precedence, and is forcing binary
1281 EXPECT_FALSE((IsLinear<Key, CmpBin>()));
1282 EXPECT_FALSE((IsLinear<KeyLin, CmpBin>()));
1283 EXPECT_FALSE((IsLinear<KeyBin, CmpBin>()));
1284 EXPECT_FALSE((IsLinear<int, CmpBin>()));
1285 EXPECT_FALSE((IsLinear<std::string, CmpBin>()));
1286 // Cmp has precedence, and is forcing linear
1287 EXPECT_TRUE((IsLinear<Key, CmpLin>()));
1288 EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
1289 EXPECT_TRUE((IsLinear<KeyBin, CmpLin>()));
1290 EXPECT_TRUE((IsLinear<int, CmpLin>()));
1291 EXPECT_TRUE((IsLinear<std::string, CmpLin>()));
1292 // Cmp has no preference, Key determines linear vs binary.
1293 EXPECT_FALSE((IsLinear<Key, Cmp>()));
1294 EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
1295 EXPECT_FALSE((IsLinear<KeyBin, Cmp>()));
1296 // arithmetic key w/ std::less or std::greater: linear
1297 EXPECT_TRUE((IsLinear<int, std::less<int>>()));
1298 EXPECT_TRUE((IsLinear<double, std::greater<double>>()));
1299 // arithmetic key w/ custom compare: binary
1300 EXPECT_FALSE((IsLinear<int, Cmp>()));
1301 // non-arithmetic key: binary
1302 EXPECT_FALSE((IsLinear<std::string, std::less<std::string>>()));
1303 }
1304
TEST(Btree,BtreeMapCanHoldMoveOnlyTypes)1305 TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) {
1306 absl::btree_map<std::string, std::unique_ptr<std::string>> m;
1307
1308 std::unique_ptr<std::string> &v = m["A"];
1309 EXPECT_TRUE(v == nullptr);
1310 v = absl::make_unique<std::string>("X");
1311
1312 auto iter = m.find("A");
1313 EXPECT_EQ("X", *iter->second);
1314 }
1315
TEST(Btree,InitializerListConstructor)1316 TEST(Btree, InitializerListConstructor) {
1317 absl::btree_set<std::string> set({"a", "b"});
1318 EXPECT_EQ(set.count("a"), 1);
1319 EXPECT_EQ(set.count("b"), 1);
1320
1321 absl::btree_multiset<int> mset({1, 1, 4});
1322 EXPECT_EQ(mset.count(1), 2);
1323 EXPECT_EQ(mset.count(4), 1);
1324
1325 absl::btree_map<int, int> map({{1, 5}, {2, 10}});
1326 EXPECT_EQ(map[1], 5);
1327 EXPECT_EQ(map[2], 10);
1328
1329 absl::btree_multimap<int, int> mmap({{1, 5}, {1, 10}});
1330 auto range = mmap.equal_range(1);
1331 auto it = range.first;
1332 ASSERT_NE(it, range.second);
1333 EXPECT_EQ(it->second, 5);
1334 ASSERT_NE(++it, range.second);
1335 EXPECT_EQ(it->second, 10);
1336 EXPECT_EQ(++it, range.second);
1337 }
1338
TEST(Btree,InitializerListInsert)1339 TEST(Btree, InitializerListInsert) {
1340 absl::btree_set<std::string> set;
1341 set.insert({"a", "b"});
1342 EXPECT_EQ(set.count("a"), 1);
1343 EXPECT_EQ(set.count("b"), 1);
1344
1345 absl::btree_multiset<int> mset;
1346 mset.insert({1, 1, 4});
1347 EXPECT_EQ(mset.count(1), 2);
1348 EXPECT_EQ(mset.count(4), 1);
1349
1350 absl::btree_map<int, int> map;
1351 map.insert({{1, 5}, {2, 10}});
1352 // Test that inserting one element using an initializer list also works.
1353 map.insert({3, 15});
1354 EXPECT_EQ(map[1], 5);
1355 EXPECT_EQ(map[2], 10);
1356 EXPECT_EQ(map[3], 15);
1357
1358 absl::btree_multimap<int, int> mmap;
1359 mmap.insert({{1, 5}, {1, 10}});
1360 auto range = mmap.equal_range(1);
1361 auto it = range.first;
1362 ASSERT_NE(it, range.second);
1363 EXPECT_EQ(it->second, 5);
1364 ASSERT_NE(++it, range.second);
1365 EXPECT_EQ(it->second, 10);
1366 EXPECT_EQ(++it, range.second);
1367 }
1368
1369 template <typename Compare, typename Key>
AssertKeyCompareStringAdapted()1370 void AssertKeyCompareStringAdapted() {
1371 using Adapted = typename key_compare_adapter<Compare, Key>::type;
1372 static_assert(
1373 std::is_same<Adapted, StringBtreeDefaultLess>::value ||
1374 std::is_same<Adapted, StringBtreeDefaultGreater>::value,
1375 "key_compare_adapter should have string-adapted this comparator.");
1376 }
1377 template <typename Compare, typename Key>
AssertKeyCompareNotStringAdapted()1378 void AssertKeyCompareNotStringAdapted() {
1379 using Adapted = typename key_compare_adapter<Compare, Key>::type;
1380 static_assert(
1381 !std::is_same<Adapted, StringBtreeDefaultLess>::value &&
1382 !std::is_same<Adapted, StringBtreeDefaultGreater>::value,
1383 "key_compare_adapter shouldn't have string-adapted this comparator.");
1384 }
1385
TEST(Btree,KeyCompareAdapter)1386 TEST(Btree, KeyCompareAdapter) {
1387 AssertKeyCompareStringAdapted<std::less<std::string>, std::string>();
1388 AssertKeyCompareStringAdapted<std::greater<std::string>, std::string>();
1389 AssertKeyCompareStringAdapted<std::less<absl::string_view>,
1390 absl::string_view>();
1391 AssertKeyCompareStringAdapted<std::greater<absl::string_view>,
1392 absl::string_view>();
1393 AssertKeyCompareStringAdapted<std::less<absl::Cord>, absl::Cord>();
1394 AssertKeyCompareStringAdapted<std::greater<absl::Cord>, absl::Cord>();
1395 AssertKeyCompareNotStringAdapted<std::less<int>, int>();
1396 AssertKeyCompareNotStringAdapted<std::greater<int>, int>();
1397 }
1398
TEST(Btree,RValueInsert)1399 TEST(Btree, RValueInsert) {
1400 InstanceTracker tracker;
1401
1402 absl::btree_set<MovableOnlyInstance> set;
1403 set.insert(MovableOnlyInstance(1));
1404 set.insert(MovableOnlyInstance(3));
1405 MovableOnlyInstance two(2);
1406 set.insert(set.find(MovableOnlyInstance(3)), std::move(two));
1407 auto it = set.find(MovableOnlyInstance(2));
1408 ASSERT_NE(it, set.end());
1409 ASSERT_NE(++it, set.end());
1410 EXPECT_EQ(it->value(), 3);
1411
1412 absl::btree_multiset<MovableOnlyInstance> mset;
1413 MovableOnlyInstance zero(0);
1414 MovableOnlyInstance zero2(0);
1415 mset.insert(std::move(zero));
1416 mset.insert(mset.find(MovableOnlyInstance(0)), std::move(zero2));
1417 EXPECT_EQ(mset.count(MovableOnlyInstance(0)), 2);
1418
1419 absl::btree_map<int, MovableOnlyInstance> map;
1420 std::pair<const int, MovableOnlyInstance> p1 = {1, MovableOnlyInstance(5)};
1421 std::pair<const int, MovableOnlyInstance> p2 = {2, MovableOnlyInstance(10)};
1422 std::pair<const int, MovableOnlyInstance> p3 = {3, MovableOnlyInstance(15)};
1423 map.insert(std::move(p1));
1424 map.insert(std::move(p3));
1425 map.insert(map.find(3), std::move(p2));
1426 ASSERT_NE(map.find(2), map.end());
1427 EXPECT_EQ(map.find(2)->second.value(), 10);
1428
1429 absl::btree_multimap<int, MovableOnlyInstance> mmap;
1430 std::pair<const int, MovableOnlyInstance> p4 = {1, MovableOnlyInstance(5)};
1431 std::pair<const int, MovableOnlyInstance> p5 = {1, MovableOnlyInstance(10)};
1432 mmap.insert(std::move(p4));
1433 mmap.insert(mmap.find(1), std::move(p5));
1434 auto range = mmap.equal_range(1);
1435 auto it1 = range.first;
1436 ASSERT_NE(it1, range.second);
1437 EXPECT_EQ(it1->second.value(), 10);
1438 ASSERT_NE(++it1, range.second);
1439 EXPECT_EQ(it1->second.value(), 5);
1440 EXPECT_EQ(++it1, range.second);
1441
1442 EXPECT_EQ(tracker.copies(), 0);
1443 EXPECT_EQ(tracker.swaps(), 0);
1444 }
1445
1446 template <typename Cmp>
1447 struct CheckedCompareOptedOutCmp : Cmp, BtreeTestOnlyCheckedCompareOptOutBase {
1448 using Cmp::Cmp;
CheckedCompareOptedOutCmpabsl::container_internal::__anon2a41e4430411::CheckedCompareOptedOutCmp1449 CheckedCompareOptedOutCmp() {}
CheckedCompareOptedOutCmpabsl::container_internal::__anon2a41e4430411::CheckedCompareOptedOutCmp1450 CheckedCompareOptedOutCmp(Cmp cmp) : Cmp(std::move(cmp)) {} // NOLINT
1451 };
1452
1453 // A btree set with a specific number of values per node. Opt out of
1454 // checked_compare so that we can expect exact numbers of comparisons.
1455 template <typename Key, int TargetValuesPerNode, typename Cmp = std::less<Key>>
1456 class SizedBtreeSet
1457 : public btree_set_container<btree<
1458 set_params<Key, CheckedCompareOptedOutCmp<Cmp>, std::allocator<Key>,
1459 BtreeNodePeer::GetTargetNodeSize<Key>(TargetValuesPerNode),
1460 /*Multi=*/false>>> {
1461 using Base = typename SizedBtreeSet::btree_set_container;
1462
1463 public:
SizedBtreeSet()1464 SizedBtreeSet() {}
1465 using Base::Base;
1466 };
1467
1468 template <typename Set>
ExpectOperationCounts(const int expected_moves,const int expected_comparisons,const std::vector<int> & values,InstanceTracker * tracker,Set * set)1469 void ExpectOperationCounts(const int expected_moves,
1470 const int expected_comparisons,
1471 const std::vector<int> &values,
1472 InstanceTracker *tracker, Set *set) {
1473 for (const int v : values) set->insert(MovableOnlyInstance(v));
1474 set->clear();
1475 EXPECT_EQ(tracker->moves(), expected_moves);
1476 EXPECT_EQ(tracker->comparisons(), expected_comparisons);
1477 EXPECT_EQ(tracker->copies(), 0);
1478 EXPECT_EQ(tracker->swaps(), 0);
1479 tracker->ResetCopiesMovesSwaps();
1480 }
1481
1482 // Note: when the values in this test change, it is expected to have an impact
1483 // on performance.
TEST(Btree,MovesComparisonsCopiesSwapsTracking)1484 TEST(Btree, MovesComparisonsCopiesSwapsTracking) {
1485 InstanceTracker tracker;
1486 // Note: this is minimum number of values per node.
1487 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/4> set4;
1488 // Note: this is the default number of values per node for a set of int32s
1489 // (with 64-bit pointers).
1490 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61> set61;
1491 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/100> set100;
1492
1493 // Don't depend on flags for random values because then the expectations will
1494 // fail if the flags change.
1495 std::vector<int> values =
1496 GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23);
1497
1498 EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set4)>(), 4);
1499 EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>(), 61);
1500 EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set100)>(), 100);
1501 if (sizeof(void *) == 8) {
1502 EXPECT_EQ(
1503 BtreeNodePeer::GetNumSlotsPerNode<absl::btree_set<int32_t>>(),
1504 // When we have generations, there is one fewer slot.
1505 BtreeNodePeer::UsesGenerations<absl::btree_set<int32_t>>() ? 60 : 61);
1506 }
1507
1508 // Test key insertion/deletion in random order.
1509 ExpectOperationCounts(56540, 134212, values, &tracker, &set4);
1510 ExpectOperationCounts(386718, 129807, values, &tracker, &set61);
1511 ExpectOperationCounts(586761, 130310, values, &tracker, &set100);
1512
1513 // Test key insertion/deletion in sorted order.
1514 std::sort(values.begin(), values.end());
1515 ExpectOperationCounts(24972, 85563, values, &tracker, &set4);
1516 ExpectOperationCounts(20208, 87757, values, &tracker, &set61);
1517 ExpectOperationCounts(20124, 96583, values, &tracker, &set100);
1518
1519 // Test key insertion/deletion in reverse sorted order.
1520 std::reverse(values.begin(), values.end());
1521 ExpectOperationCounts(54949, 127531, values, &tracker, &set4);
1522 ExpectOperationCounts(338813, 118266, values, &tracker, &set61);
1523 ExpectOperationCounts(534529, 125279, values, &tracker, &set100);
1524 }
1525
1526 struct MovableOnlyInstanceThreeWayCompare {
operator ()absl::container_internal::__anon2a41e4430411::MovableOnlyInstanceThreeWayCompare1527 absl::weak_ordering operator()(const MovableOnlyInstance &a,
1528 const MovableOnlyInstance &b) const {
1529 return a.compare(b);
1530 }
1531 };
1532
1533 // Note: when the values in this test change, it is expected to have an impact
1534 // on performance.
TEST(Btree,MovesComparisonsCopiesSwapsTrackingThreeWayCompare)1535 TEST(Btree, MovesComparisonsCopiesSwapsTrackingThreeWayCompare) {
1536 InstanceTracker tracker;
1537 // Note: this is minimum number of values per node.
1538 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/4,
1539 MovableOnlyInstanceThreeWayCompare>
1540 set4;
1541 // Note: this is the default number of values per node for a set of int32s
1542 // (with 64-bit pointers).
1543 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61,
1544 MovableOnlyInstanceThreeWayCompare>
1545 set61;
1546 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/100,
1547 MovableOnlyInstanceThreeWayCompare>
1548 set100;
1549
1550 // Don't depend on flags for random values because then the expectations will
1551 // fail if the flags change.
1552 std::vector<int> values =
1553 GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23);
1554
1555 EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set4)>(), 4);
1556 EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>(), 61);
1557 EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set100)>(), 100);
1558 if (sizeof(void *) == 8) {
1559 EXPECT_EQ(
1560 BtreeNodePeer::GetNumSlotsPerNode<absl::btree_set<int32_t>>(),
1561 // When we have generations, there is one fewer slot.
1562 BtreeNodePeer::UsesGenerations<absl::btree_set<int32_t>>() ? 60 : 61);
1563 }
1564
1565 // Test key insertion/deletion in random order.
1566 ExpectOperationCounts(56540, 124221, values, &tracker, &set4);
1567 ExpectOperationCounts(386718, 119816, values, &tracker, &set61);
1568 ExpectOperationCounts(586761, 120319, values, &tracker, &set100);
1569
1570 // Test key insertion/deletion in sorted order.
1571 std::sort(values.begin(), values.end());
1572 ExpectOperationCounts(24972, 85563, values, &tracker, &set4);
1573 ExpectOperationCounts(20208, 87757, values, &tracker, &set61);
1574 ExpectOperationCounts(20124, 96583, values, &tracker, &set100);
1575
1576 // Test key insertion/deletion in reverse sorted order.
1577 std::reverse(values.begin(), values.end());
1578 ExpectOperationCounts(54949, 117532, values, &tracker, &set4);
1579 ExpectOperationCounts(338813, 108267, values, &tracker, &set61);
1580 ExpectOperationCounts(534529, 115280, values, &tracker, &set100);
1581 }
1582
1583 struct NoDefaultCtor {
1584 int num;
NoDefaultCtorabsl::container_internal::__anon2a41e4430411::NoDefaultCtor1585 explicit NoDefaultCtor(int i) : num(i) {}
1586
operator <(const NoDefaultCtor & a,const NoDefaultCtor & b)1587 friend bool operator<(const NoDefaultCtor &a, const NoDefaultCtor &b) {
1588 return a.num < b.num;
1589 }
1590 };
1591
TEST(Btree,BtreeMapCanHoldNoDefaultCtorTypes)1592 TEST(Btree, BtreeMapCanHoldNoDefaultCtorTypes) {
1593 absl::btree_map<NoDefaultCtor, NoDefaultCtor> m;
1594
1595 for (int i = 1; i <= 99; ++i) {
1596 SCOPED_TRACE(i);
1597 EXPECT_TRUE(m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i)).second);
1598 }
1599 EXPECT_FALSE(m.emplace(NoDefaultCtor(78), NoDefaultCtor(0)).second);
1600
1601 auto iter99 = m.find(NoDefaultCtor(99));
1602 ASSERT_NE(iter99, m.end());
1603 EXPECT_EQ(iter99->second.num, 1);
1604
1605 auto iter1 = m.find(NoDefaultCtor(1));
1606 ASSERT_NE(iter1, m.end());
1607 EXPECT_EQ(iter1->second.num, 99);
1608
1609 auto iter50 = m.find(NoDefaultCtor(50));
1610 ASSERT_NE(iter50, m.end());
1611 EXPECT_EQ(iter50->second.num, 50);
1612
1613 auto iter25 = m.find(NoDefaultCtor(25));
1614 ASSERT_NE(iter25, m.end());
1615 EXPECT_EQ(iter25->second.num, 75);
1616 }
1617
TEST(Btree,BtreeMultimapCanHoldNoDefaultCtorTypes)1618 TEST(Btree, BtreeMultimapCanHoldNoDefaultCtorTypes) {
1619 absl::btree_multimap<NoDefaultCtor, NoDefaultCtor> m;
1620
1621 for (int i = 1; i <= 99; ++i) {
1622 SCOPED_TRACE(i);
1623 m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i));
1624 }
1625
1626 auto iter99 = m.find(NoDefaultCtor(99));
1627 ASSERT_NE(iter99, m.end());
1628 EXPECT_EQ(iter99->second.num, 1);
1629
1630 auto iter1 = m.find(NoDefaultCtor(1));
1631 ASSERT_NE(iter1, m.end());
1632 EXPECT_EQ(iter1->second.num, 99);
1633
1634 auto iter50 = m.find(NoDefaultCtor(50));
1635 ASSERT_NE(iter50, m.end());
1636 EXPECT_EQ(iter50->second.num, 50);
1637
1638 auto iter25 = m.find(NoDefaultCtor(25));
1639 ASSERT_NE(iter25, m.end());
1640 EXPECT_EQ(iter25->second.num, 75);
1641 }
1642
TEST(Btree,MapAt)1643 TEST(Btree, MapAt) {
1644 absl::btree_map<int, int> map = {{1, 2}, {2, 4}};
1645 EXPECT_EQ(map.at(1), 2);
1646 EXPECT_EQ(map.at(2), 4);
1647 map.at(2) = 8;
1648 const absl::btree_map<int, int> &const_map = map;
1649 EXPECT_EQ(const_map.at(1), 2);
1650 EXPECT_EQ(const_map.at(2), 8);
1651 #ifdef ABSL_HAVE_EXCEPTIONS
1652 EXPECT_THROW(map.at(3), std::out_of_range);
1653 #else
1654 EXPECT_DEATH_IF_SUPPORTED(map.at(3), "absl::btree_map::at");
1655 #endif
1656 }
1657
TEST(Btree,BtreeMultisetEmplace)1658 TEST(Btree, BtreeMultisetEmplace) {
1659 const int value_to_insert = 123456;
1660 absl::btree_multiset<int> s;
1661 auto iter = s.emplace(value_to_insert);
1662 ASSERT_NE(iter, s.end());
1663 EXPECT_EQ(*iter, value_to_insert);
1664 iter = s.emplace(value_to_insert);
1665 ASSERT_NE(iter, s.end());
1666 EXPECT_EQ(*iter, value_to_insert);
1667 auto result = s.equal_range(value_to_insert);
1668 EXPECT_EQ(std::distance(result.first, result.second), 2);
1669 }
1670
TEST(Btree,BtreeMultisetEmplaceHint)1671 TEST(Btree, BtreeMultisetEmplaceHint) {
1672 const int value_to_insert = 123456;
1673 absl::btree_multiset<int> s;
1674 auto iter = s.emplace(value_to_insert);
1675 ASSERT_NE(iter, s.end());
1676 EXPECT_EQ(*iter, value_to_insert);
1677 iter = s.emplace_hint(iter, value_to_insert);
1678 // The new element should be before the previously inserted one.
1679 EXPECT_EQ(iter, s.lower_bound(value_to_insert));
1680 ASSERT_NE(iter, s.end());
1681 EXPECT_EQ(*iter, value_to_insert);
1682 }
1683
TEST(Btree,BtreeMultimapEmplace)1684 TEST(Btree, BtreeMultimapEmplace) {
1685 const int key_to_insert = 123456;
1686 const char value0[] = "a";
1687 absl::btree_multimap<int, std::string> m;
1688 auto iter = m.emplace(key_to_insert, value0);
1689 ASSERT_NE(iter, m.end());
1690 EXPECT_EQ(iter->first, key_to_insert);
1691 EXPECT_EQ(iter->second, value0);
1692 const char value1[] = "b";
1693 iter = m.emplace(key_to_insert, value1);
1694 ASSERT_NE(iter, m.end());
1695 EXPECT_EQ(iter->first, key_to_insert);
1696 EXPECT_EQ(iter->second, value1);
1697 auto result = m.equal_range(key_to_insert);
1698 EXPECT_EQ(std::distance(result.first, result.second), 2);
1699 }
1700
TEST(Btree,BtreeMultimapEmplaceHint)1701 TEST(Btree, BtreeMultimapEmplaceHint) {
1702 const int key_to_insert = 123456;
1703 const char value0[] = "a";
1704 absl::btree_multimap<int, std::string> m;
1705 auto iter = m.emplace(key_to_insert, value0);
1706 ASSERT_NE(iter, m.end());
1707 EXPECT_EQ(iter->first, key_to_insert);
1708 EXPECT_EQ(iter->second, value0);
1709 const char value1[] = "b";
1710 iter = m.emplace_hint(iter, key_to_insert, value1);
1711 // The new element should be before the previously inserted one.
1712 EXPECT_EQ(iter, m.lower_bound(key_to_insert));
1713 ASSERT_NE(iter, m.end());
1714 EXPECT_EQ(iter->first, key_to_insert);
1715 EXPECT_EQ(iter->second, value1);
1716 }
1717
TEST(Btree,ConstIteratorAccessors)1718 TEST(Btree, ConstIteratorAccessors) {
1719 absl::btree_set<int> set;
1720 for (int i = 0; i < 100; ++i) {
1721 set.insert(i);
1722 }
1723
1724 auto it = set.cbegin();
1725 auto r_it = set.crbegin();
1726 for (int i = 0; i < 100; ++i, ++it, ++r_it) {
1727 ASSERT_EQ(*it, i);
1728 ASSERT_EQ(*r_it, 99 - i);
1729 }
1730 EXPECT_EQ(it, set.cend());
1731 EXPECT_EQ(r_it, set.crend());
1732 }
1733
TEST(Btree,StrSplitCompatible)1734 TEST(Btree, StrSplitCompatible) {
1735 const absl::btree_set<std::string> split_set = absl::StrSplit("a,b,c", ',');
1736 const absl::btree_set<std::string> expected_set = {"a", "b", "c"};
1737
1738 EXPECT_EQ(split_set, expected_set);
1739 }
1740
TEST(Btree,KeyComp)1741 TEST(Btree, KeyComp) {
1742 absl::btree_set<int> s;
1743 EXPECT_TRUE(s.key_comp()(1, 2));
1744 EXPECT_FALSE(s.key_comp()(2, 2));
1745 EXPECT_FALSE(s.key_comp()(2, 1));
1746
1747 absl::btree_map<int, int> m1;
1748 EXPECT_TRUE(m1.key_comp()(1, 2));
1749 EXPECT_FALSE(m1.key_comp()(2, 2));
1750 EXPECT_FALSE(m1.key_comp()(2, 1));
1751
1752 // Even though we internally adapt the comparator of `m2` to be three-way and
1753 // heterogeneous, the comparator we expose through key_comp() is the original
1754 // unadapted comparator.
1755 absl::btree_map<std::string, int> m2;
1756 EXPECT_TRUE(m2.key_comp()("a", "b"));
1757 EXPECT_FALSE(m2.key_comp()("b", "b"));
1758 EXPECT_FALSE(m2.key_comp()("b", "a"));
1759 }
1760
TEST(Btree,ValueComp)1761 TEST(Btree, ValueComp) {
1762 absl::btree_set<int> s;
1763 EXPECT_TRUE(s.value_comp()(1, 2));
1764 EXPECT_FALSE(s.value_comp()(2, 2));
1765 EXPECT_FALSE(s.value_comp()(2, 1));
1766
1767 absl::btree_map<int, int> m1;
1768 EXPECT_TRUE(m1.value_comp()(std::make_pair(1, 0), std::make_pair(2, 0)));
1769 EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(2, 0)));
1770 EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(1, 0)));
1771
1772 // Even though we internally adapt the comparator of `m2` to be three-way and
1773 // heterogeneous, the comparator we expose through value_comp() is based on
1774 // the original unadapted comparator.
1775 absl::btree_map<std::string, int> m2;
1776 EXPECT_TRUE(m2.value_comp()(std::make_pair("a", 0), std::make_pair("b", 0)));
1777 EXPECT_FALSE(m2.value_comp()(std::make_pair("b", 0), std::make_pair("b", 0)));
1778 EXPECT_FALSE(m2.value_comp()(std::make_pair("b", 0), std::make_pair("a", 0)));
1779 }
1780
1781 // Test that we have the protected members from the std::map::value_compare API.
1782 // See https://en.cppreference.com/w/cpp/container/map/value_compare.
TEST(Btree,MapValueCompProtected)1783 TEST(Btree, MapValueCompProtected) {
1784 struct key_compare {
1785 bool operator()(int l, int r) const { return l < r; }
1786 int id;
1787 };
1788 using value_compare = absl::btree_map<int, int, key_compare>::value_compare;
1789 struct value_comp_child : public value_compare {
1790 explicit value_comp_child(key_compare kc) : value_compare(kc) {}
1791 int GetId() const { return comp.id; }
1792 };
1793 value_comp_child c(key_compare{10});
1794 EXPECT_EQ(c.GetId(), 10);
1795 }
1796
TEST(Btree,DefaultConstruction)1797 TEST(Btree, DefaultConstruction) {
1798 absl::btree_set<int> s;
1799 absl::btree_map<int, int> m;
1800 absl::btree_multiset<int> ms;
1801 absl::btree_multimap<int, int> mm;
1802
1803 EXPECT_TRUE(s.empty());
1804 EXPECT_TRUE(m.empty());
1805 EXPECT_TRUE(ms.empty());
1806 EXPECT_TRUE(mm.empty());
1807 }
1808
TEST(Btree,SwissTableHashable)1809 TEST(Btree, SwissTableHashable) {
1810 static constexpr int kValues = 10000;
1811 std::vector<int> values(kValues);
1812 std::iota(values.begin(), values.end(), 0);
1813 std::vector<std::pair<int, int>> map_values;
1814 for (int v : values) map_values.emplace_back(v, -v);
1815
1816 using set = absl::btree_set<int>;
1817 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
1818 set{},
1819 set{1},
1820 set{2},
1821 set{1, 2},
1822 set{2, 1},
1823 set(values.begin(), values.end()),
1824 set(values.rbegin(), values.rend()),
1825 }));
1826
1827 using mset = absl::btree_multiset<int>;
1828 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
1829 mset{},
1830 mset{1},
1831 mset{1, 1},
1832 mset{2},
1833 mset{2, 2},
1834 mset{1, 2},
1835 mset{1, 1, 2},
1836 mset{1, 2, 2},
1837 mset{1, 1, 2, 2},
1838 mset(values.begin(), values.end()),
1839 mset(values.rbegin(), values.rend()),
1840 }));
1841
1842 using map = absl::btree_map<int, int>;
1843 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
1844 map{},
1845 map{{1, 0}},
1846 map{{1, 1}},
1847 map{{2, 0}},
1848 map{{2, 2}},
1849 map{{1, 0}, {2, 1}},
1850 map(map_values.begin(), map_values.end()),
1851 map(map_values.rbegin(), map_values.rend()),
1852 }));
1853
1854 using mmap = absl::btree_multimap<int, int>;
1855 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
1856 mmap{},
1857 mmap{{1, 0}},
1858 mmap{{1, 1}},
1859 mmap{{1, 0}, {1, 1}},
1860 mmap{{1, 1}, {1, 0}},
1861 mmap{{2, 0}},
1862 mmap{{2, 2}},
1863 mmap{{1, 0}, {2, 1}},
1864 mmap(map_values.begin(), map_values.end()),
1865 mmap(map_values.rbegin(), map_values.rend()),
1866 }));
1867 }
1868
TEST(Btree,ComparableSet)1869 TEST(Btree, ComparableSet) {
1870 absl::btree_set<int> s1 = {1, 2};
1871 absl::btree_set<int> s2 = {2, 3};
1872 EXPECT_LT(s1, s2);
1873 EXPECT_LE(s1, s2);
1874 EXPECT_LE(s1, s1);
1875 EXPECT_GT(s2, s1);
1876 EXPECT_GE(s2, s1);
1877 EXPECT_GE(s1, s1);
1878 }
1879
TEST(Btree,ComparableSetsDifferentLength)1880 TEST(Btree, ComparableSetsDifferentLength) {
1881 absl::btree_set<int> s1 = {1, 2};
1882 absl::btree_set<int> s2 = {1, 2, 3};
1883 EXPECT_LT(s1, s2);
1884 EXPECT_LE(s1, s2);
1885 EXPECT_GT(s2, s1);
1886 EXPECT_GE(s2, s1);
1887 }
1888
TEST(Btree,ComparableMultiset)1889 TEST(Btree, ComparableMultiset) {
1890 absl::btree_multiset<int> s1 = {1, 2};
1891 absl::btree_multiset<int> s2 = {2, 3};
1892 EXPECT_LT(s1, s2);
1893 EXPECT_LE(s1, s2);
1894 EXPECT_LE(s1, s1);
1895 EXPECT_GT(s2, s1);
1896 EXPECT_GE(s2, s1);
1897 EXPECT_GE(s1, s1);
1898 }
1899
TEST(Btree,ComparableMap)1900 TEST(Btree, ComparableMap) {
1901 absl::btree_map<int, int> s1 = {{1, 2}};
1902 absl::btree_map<int, int> s2 = {{2, 3}};
1903 EXPECT_LT(s1, s2);
1904 EXPECT_LE(s1, s2);
1905 EXPECT_LE(s1, s1);
1906 EXPECT_GT(s2, s1);
1907 EXPECT_GE(s2, s1);
1908 EXPECT_GE(s1, s1);
1909 }
1910
TEST(Btree,ComparableMultimap)1911 TEST(Btree, ComparableMultimap) {
1912 absl::btree_multimap<int, int> s1 = {{1, 2}};
1913 absl::btree_multimap<int, int> s2 = {{2, 3}};
1914 EXPECT_LT(s1, s2);
1915 EXPECT_LE(s1, s2);
1916 EXPECT_LE(s1, s1);
1917 EXPECT_GT(s2, s1);
1918 EXPECT_GE(s2, s1);
1919 EXPECT_GE(s1, s1);
1920 }
1921
TEST(Btree,ComparableSetWithCustomComparator)1922 TEST(Btree, ComparableSetWithCustomComparator) {
1923 // As specified by
1924 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf section
1925 // [container.requirements.general].12, ordering associative containers always
1926 // uses default '<' operator
1927 // - even if otherwise the container uses custom functor.
1928 absl::btree_set<int, std::greater<int>> s1 = {1, 2};
1929 absl::btree_set<int, std::greater<int>> s2 = {2, 3};
1930 EXPECT_LT(s1, s2);
1931 EXPECT_LE(s1, s2);
1932 EXPECT_LE(s1, s1);
1933 EXPECT_GT(s2, s1);
1934 EXPECT_GE(s2, s1);
1935 EXPECT_GE(s1, s1);
1936 }
1937
TEST(Btree,EraseReturnsIterator)1938 TEST(Btree, EraseReturnsIterator) {
1939 absl::btree_set<int> set = {1, 2, 3, 4, 5};
1940 auto result_it = set.erase(set.begin(), set.find(3));
1941 EXPECT_EQ(result_it, set.find(3));
1942 result_it = set.erase(set.find(5));
1943 EXPECT_EQ(result_it, set.end());
1944 }
1945
TEST(Btree,ExtractAndInsertNodeHandleSet)1946 TEST(Btree, ExtractAndInsertNodeHandleSet) {
1947 absl::btree_set<int> src1 = {1, 2, 3, 4, 5};
1948 auto nh = src1.extract(src1.find(3));
1949 EXPECT_THAT(src1, ElementsAre(1, 2, 4, 5));
1950 absl::btree_set<int> other;
1951 absl::btree_set<int>::insert_return_type res = other.insert(std::move(nh));
1952 EXPECT_THAT(other, ElementsAre(3));
1953 EXPECT_EQ(res.position, other.find(3));
1954 EXPECT_TRUE(res.inserted);
1955 EXPECT_TRUE(res.node.empty());
1956
1957 absl::btree_set<int> src2 = {3, 4};
1958 nh = src2.extract(src2.find(3));
1959 EXPECT_THAT(src2, ElementsAre(4));
1960 res = other.insert(std::move(nh));
1961 EXPECT_THAT(other, ElementsAre(3));
1962 EXPECT_EQ(res.position, other.find(3));
1963 EXPECT_FALSE(res.inserted);
1964 ASSERT_FALSE(res.node.empty());
1965 EXPECT_EQ(res.node.value(), 3);
1966 }
1967
1968 template <typename Set>
TestExtractWithTrackingForSet()1969 void TestExtractWithTrackingForSet() {
1970 InstanceTracker tracker;
1971 {
1972 Set s;
1973 // Add enough elements to make sure we test internal nodes too.
1974 const size_t kSize = 1000;
1975 while (s.size() < kSize) {
1976 s.insert(MovableOnlyInstance(s.size()));
1977 }
1978 for (int i = 0; i < kSize; ++i) {
1979 // Extract with key
1980 auto nh = s.extract(MovableOnlyInstance(i));
1981 EXPECT_EQ(s.size(), kSize - 1);
1982 EXPECT_EQ(nh.value().value(), i);
1983 // Insert with node
1984 s.insert(std::move(nh));
1985 EXPECT_EQ(s.size(), kSize);
1986
1987 // Extract with iterator
1988 auto it = s.find(MovableOnlyInstance(i));
1989 nh = s.extract(it);
1990 EXPECT_EQ(s.size(), kSize - 1);
1991 EXPECT_EQ(nh.value().value(), i);
1992 // Insert with node and hint
1993 s.insert(s.begin(), std::move(nh));
1994 EXPECT_EQ(s.size(), kSize);
1995 }
1996 }
1997 EXPECT_EQ(0, tracker.instances());
1998 }
1999
2000 template <typename Map>
TestExtractWithTrackingForMap()2001 void TestExtractWithTrackingForMap() {
2002 InstanceTracker tracker;
2003 {
2004 Map m;
2005 // Add enough elements to make sure we test internal nodes too.
2006 const size_t kSize = 1000;
2007 while (m.size() < kSize) {
2008 m.insert(
2009 {CopyableMovableInstance(m.size()), MovableOnlyInstance(m.size())});
2010 }
2011 for (int i = 0; i < kSize; ++i) {
2012 // Extract with key
2013 auto nh = m.extract(CopyableMovableInstance(i));
2014 EXPECT_EQ(m.size(), kSize - 1);
2015 EXPECT_EQ(nh.key().value(), i);
2016 EXPECT_EQ(nh.mapped().value(), i);
2017 // Insert with node
2018 m.insert(std::move(nh));
2019 EXPECT_EQ(m.size(), kSize);
2020
2021 // Extract with iterator
2022 auto it = m.find(CopyableMovableInstance(i));
2023 nh = m.extract(it);
2024 EXPECT_EQ(m.size(), kSize - 1);
2025 EXPECT_EQ(nh.key().value(), i);
2026 EXPECT_EQ(nh.mapped().value(), i);
2027 // Insert with node and hint
2028 m.insert(m.begin(), std::move(nh));
2029 EXPECT_EQ(m.size(), kSize);
2030 }
2031 }
2032 EXPECT_EQ(0, tracker.instances());
2033 }
2034
TEST(Btree,ExtractTracking)2035 TEST(Btree, ExtractTracking) {
2036 TestExtractWithTrackingForSet<absl::btree_set<MovableOnlyInstance>>();
2037 TestExtractWithTrackingForSet<absl::btree_multiset<MovableOnlyInstance>>();
2038 TestExtractWithTrackingForMap<
2039 absl::btree_map<CopyableMovableInstance, MovableOnlyInstance>>();
2040 TestExtractWithTrackingForMap<
2041 absl::btree_multimap<CopyableMovableInstance, MovableOnlyInstance>>();
2042 }
2043
TEST(Btree,ExtractAndInsertNodeHandleMultiSet)2044 TEST(Btree, ExtractAndInsertNodeHandleMultiSet) {
2045 absl::btree_multiset<int> src1 = {1, 2, 3, 3, 4, 5};
2046 auto nh = src1.extract(src1.find(3));
2047 EXPECT_THAT(src1, ElementsAre(1, 2, 3, 4, 5));
2048 absl::btree_multiset<int> other;
2049 auto res = other.insert(std::move(nh));
2050 EXPECT_THAT(other, ElementsAre(3));
2051 EXPECT_EQ(res, other.find(3));
2052
2053 absl::btree_multiset<int> src2 = {3, 4};
2054 nh = src2.extract(src2.find(3));
2055 EXPECT_THAT(src2, ElementsAre(4));
2056 res = other.insert(std::move(nh));
2057 EXPECT_THAT(other, ElementsAre(3, 3));
2058 EXPECT_EQ(res, ++other.find(3));
2059 }
2060
TEST(Btree,ExtractAndInsertNodeHandleMap)2061 TEST(Btree, ExtractAndInsertNodeHandleMap) {
2062 absl::btree_map<int, int> src1 = {{1, 2}, {3, 4}, {5, 6}};
2063 auto nh = src1.extract(src1.find(3));
2064 EXPECT_THAT(src1, ElementsAre(Pair(1, 2), Pair(5, 6)));
2065 absl::btree_map<int, int> other;
2066 absl::btree_map<int, int>::insert_return_type res =
2067 other.insert(std::move(nh));
2068 EXPECT_THAT(other, ElementsAre(Pair(3, 4)));
2069 EXPECT_EQ(res.position, other.find(3));
2070 EXPECT_TRUE(res.inserted);
2071 EXPECT_TRUE(res.node.empty());
2072
2073 absl::btree_map<int, int> src2 = {{3, 6}};
2074 nh = src2.extract(src2.find(3));
2075 EXPECT_TRUE(src2.empty());
2076 res = other.insert(std::move(nh));
2077 EXPECT_THAT(other, ElementsAre(Pair(3, 4)));
2078 EXPECT_EQ(res.position, other.find(3));
2079 EXPECT_FALSE(res.inserted);
2080 ASSERT_FALSE(res.node.empty());
2081 EXPECT_EQ(res.node.key(), 3);
2082 EXPECT_EQ(res.node.mapped(), 6);
2083 }
2084
TEST(Btree,ExtractAndInsertNodeHandleMultiMap)2085 TEST(Btree, ExtractAndInsertNodeHandleMultiMap) {
2086 absl::btree_multimap<int, int> src1 = {{1, 2}, {3, 4}, {5, 6}};
2087 auto nh = src1.extract(src1.find(3));
2088 EXPECT_THAT(src1, ElementsAre(Pair(1, 2), Pair(5, 6)));
2089 absl::btree_multimap<int, int> other;
2090 auto res = other.insert(std::move(nh));
2091 EXPECT_THAT(other, ElementsAre(Pair(3, 4)));
2092 EXPECT_EQ(res, other.find(3));
2093
2094 absl::btree_multimap<int, int> src2 = {{3, 6}};
2095 nh = src2.extract(src2.find(3));
2096 EXPECT_TRUE(src2.empty());
2097 res = other.insert(std::move(nh));
2098 EXPECT_THAT(other, ElementsAre(Pair(3, 4), Pair(3, 6)));
2099 EXPECT_EQ(res, ++other.begin());
2100 }
2101
TEST(Btree,ExtractMultiMapEquivalentKeys)2102 TEST(Btree, ExtractMultiMapEquivalentKeys) {
2103 // Note: using string keys means a three-way comparator.
2104 absl::btree_multimap<std::string, int> map;
2105 for (int i = 0; i < 100; ++i) {
2106 for (int j = 0; j < 100; ++j) {
2107 map.insert({absl::StrCat(i), j});
2108 }
2109 }
2110
2111 for (int i = 0; i < 100; ++i) {
2112 const std::string key = absl::StrCat(i);
2113 auto node_handle = map.extract(key);
2114 EXPECT_EQ(node_handle.key(), key);
2115 EXPECT_EQ(node_handle.mapped(), 0) << i;
2116 }
2117
2118 for (int i = 0; i < 100; ++i) {
2119 const std::string key = absl::StrCat(i);
2120 auto node_handle = map.extract(key);
2121 EXPECT_EQ(node_handle.key(), key);
2122 EXPECT_EQ(node_handle.mapped(), 1) << i;
2123 }
2124 }
2125
TEST(Btree,ExtractAndGetNextSet)2126 TEST(Btree, ExtractAndGetNextSet) {
2127 absl::btree_set<int> src = {1, 2, 3, 4, 5};
2128 auto it = src.find(3);
2129 auto extracted_and_next = src.extract_and_get_next(it);
2130 EXPECT_THAT(src, ElementsAre(1, 2, 4, 5));
2131 EXPECT_EQ(extracted_and_next.node.value(), 3);
2132 EXPECT_EQ(*extracted_and_next.next, 4);
2133 }
2134
TEST(Btree,ExtractAndGetNextMultiSet)2135 TEST(Btree, ExtractAndGetNextMultiSet) {
2136 absl::btree_multiset<int> src = {1, 2, 3, 4, 5};
2137 auto it = src.find(3);
2138 auto extracted_and_next = src.extract_and_get_next(it);
2139 EXPECT_THAT(src, ElementsAre(1, 2, 4, 5));
2140 EXPECT_EQ(extracted_and_next.node.value(), 3);
2141 EXPECT_EQ(*extracted_and_next.next, 4);
2142 }
2143
TEST(Btree,ExtractAndGetNextMap)2144 TEST(Btree, ExtractAndGetNextMap) {
2145 absl::btree_map<int, int> src = {{1, 2}, {3, 4}, {5, 6}};
2146 auto it = src.find(3);
2147 auto extracted_and_next = src.extract_and_get_next(it);
2148 EXPECT_THAT(src, ElementsAre(Pair(1, 2), Pair(5, 6)));
2149 EXPECT_EQ(extracted_and_next.node.key(), 3);
2150 EXPECT_EQ(extracted_and_next.node.mapped(), 4);
2151 EXPECT_THAT(*extracted_and_next.next, Pair(5, 6));
2152 }
2153
TEST(Btree,ExtractAndGetNextMultiMap)2154 TEST(Btree, ExtractAndGetNextMultiMap) {
2155 absl::btree_multimap<int, int> src = {{1, 2}, {3, 4}, {5, 6}};
2156 auto it = src.find(3);
2157 auto extracted_and_next = src.extract_and_get_next(it);
2158 EXPECT_THAT(src, ElementsAre(Pair(1, 2), Pair(5, 6)));
2159 EXPECT_EQ(extracted_and_next.node.key(), 3);
2160 EXPECT_EQ(extracted_and_next.node.mapped(), 4);
2161 EXPECT_THAT(*extracted_and_next.next, Pair(5, 6));
2162 }
2163
TEST(Btree,ExtractAndGetNextEndIter)2164 TEST(Btree, ExtractAndGetNextEndIter) {
2165 absl::btree_set<int> src = {1, 2, 3, 4, 5};
2166 auto it = src.find(5);
2167 auto extracted_and_next = src.extract_and_get_next(it);
2168 EXPECT_THAT(src, ElementsAre(1, 2, 3, 4));
2169 EXPECT_EQ(extracted_and_next.node.value(), 5);
2170 EXPECT_EQ(extracted_and_next.next, src.end());
2171 }
2172
TEST(Btree,ExtractDoesntCauseExtraMoves)2173 TEST(Btree, ExtractDoesntCauseExtraMoves) {
2174 #ifdef _MSC_VER
2175 GTEST_SKIP() << "This test fails on MSVC.";
2176 #endif
2177
2178 using Set = absl::btree_set<MovableOnlyInstance>;
2179 std::array<std::function<void(Set &)>, 3> extracters = {
2180 [](Set &s) { auto node = s.extract(s.begin()); },
2181 [](Set &s) { auto ret = s.extract_and_get_next(s.begin()); },
2182 [](Set &s) { auto node = s.extract(MovableOnlyInstance(0)); }};
2183
2184 InstanceTracker tracker;
2185 for (int i = 0; i < 3; ++i) {
2186 Set s;
2187 s.insert(MovableOnlyInstance(0));
2188 tracker.ResetCopiesMovesSwaps();
2189
2190 extracters[i](s);
2191 // We expect to see exactly 1 move: from the original slot into the
2192 // extracted node.
2193 EXPECT_EQ(tracker.copies(), 0) << i;
2194 EXPECT_EQ(tracker.moves(), 1) << i;
2195 EXPECT_EQ(tracker.swaps(), 0) << i;
2196 }
2197 }
2198
2199 // For multisets, insert with hint also affects correctness because we need to
2200 // insert immediately before the hint if possible.
2201 struct InsertMultiHintData {
2202 int key;
2203 int not_key;
operator ==absl::container_internal::__anon2a41e4430411::InsertMultiHintData2204 bool operator==(const InsertMultiHintData other) const {
2205 return key == other.key && not_key == other.not_key;
2206 }
2207 };
2208
2209 struct InsertMultiHintDataKeyCompare {
2210 using is_transparent = void;
operator ()absl::container_internal::__anon2a41e4430411::InsertMultiHintDataKeyCompare2211 bool operator()(const InsertMultiHintData a,
2212 const InsertMultiHintData b) const {
2213 return a.key < b.key;
2214 }
operator ()absl::container_internal::__anon2a41e4430411::InsertMultiHintDataKeyCompare2215 bool operator()(const int a, const InsertMultiHintData b) const {
2216 return a < b.key;
2217 }
operator ()absl::container_internal::__anon2a41e4430411::InsertMultiHintDataKeyCompare2218 bool operator()(const InsertMultiHintData a, const int b) const {
2219 return a.key < b;
2220 }
2221 };
2222
TEST(Btree,InsertHintNodeHandle)2223 TEST(Btree, InsertHintNodeHandle) {
2224 // For unique sets, insert with hint is just a performance optimization.
2225 // Test that insert works correctly when the hint is right or wrong.
2226 {
2227 absl::btree_set<int> src = {1, 2, 3, 4, 5};
2228 auto nh = src.extract(src.find(3));
2229 EXPECT_THAT(src, ElementsAre(1, 2, 4, 5));
2230 absl::btree_set<int> other = {0, 100};
2231 // Test a correct hint.
2232 auto it = other.insert(other.lower_bound(3), std::move(nh));
2233 EXPECT_THAT(other, ElementsAre(0, 3, 100));
2234 EXPECT_EQ(it, other.find(3));
2235
2236 nh = src.extract(src.find(5));
2237 // Test an incorrect hint.
2238 it = other.insert(other.end(), std::move(nh));
2239 EXPECT_THAT(other, ElementsAre(0, 3, 5, 100));
2240 EXPECT_EQ(it, other.find(5));
2241 }
2242
2243 absl::btree_multiset<InsertMultiHintData, InsertMultiHintDataKeyCompare> src =
2244 {{1, 2}, {3, 4}, {3, 5}};
2245 auto nh = src.extract(src.lower_bound(3));
2246 EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 4}));
2247 absl::btree_multiset<InsertMultiHintData, InsertMultiHintDataKeyCompare>
2248 other = {{3, 1}, {3, 2}, {3, 3}};
2249 auto it = other.insert(--other.end(), std::move(nh));
2250 EXPECT_THAT(
2251 other, ElementsAre(InsertMultiHintData{3, 1}, InsertMultiHintData{3, 2},
2252 InsertMultiHintData{3, 4}, InsertMultiHintData{3, 3}));
2253 EXPECT_EQ(it, --(--other.end()));
2254
2255 nh = src.extract(src.find(3));
2256 EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 5}));
2257 it = other.insert(other.begin(), std::move(nh));
2258 EXPECT_THAT(other,
2259 ElementsAre(InsertMultiHintData{3, 5}, InsertMultiHintData{3, 1},
2260 InsertMultiHintData{3, 2}, InsertMultiHintData{3, 4},
2261 InsertMultiHintData{3, 3}));
2262 EXPECT_EQ(it, other.begin());
2263 }
2264
2265 struct IntCompareToCmp {
operator ()absl::container_internal::__anon2a41e4430411::IntCompareToCmp2266 absl::weak_ordering operator()(int a, int b) const {
2267 if (a < b) return absl::weak_ordering::less;
2268 if (a > b) return absl::weak_ordering::greater;
2269 return absl::weak_ordering::equivalent;
2270 }
2271 };
2272
TEST(Btree,MergeIntoUniqueContainers)2273 TEST(Btree, MergeIntoUniqueContainers) {
2274 absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
2275 absl::btree_multiset<int> src2 = {3, 4, 4, 5};
2276 absl::btree_set<int> dst;
2277
2278 dst.merge(src1);
2279 EXPECT_TRUE(src1.empty());
2280 EXPECT_THAT(dst, ElementsAre(1, 2, 3));
2281 dst.merge(src2);
2282 EXPECT_THAT(src2, ElementsAre(3, 4));
2283 EXPECT_THAT(dst, ElementsAre(1, 2, 3, 4, 5));
2284 }
2285
TEST(Btree,MergeIntoUniqueContainersWithCompareTo)2286 TEST(Btree, MergeIntoUniqueContainersWithCompareTo) {
2287 absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
2288 absl::btree_multiset<int> src2 = {3, 4, 4, 5};
2289 absl::btree_set<int, IntCompareToCmp> dst;
2290
2291 dst.merge(src1);
2292 EXPECT_TRUE(src1.empty());
2293 EXPECT_THAT(dst, ElementsAre(1, 2, 3));
2294 dst.merge(src2);
2295 EXPECT_THAT(src2, ElementsAre(3, 4));
2296 EXPECT_THAT(dst, ElementsAre(1, 2, 3, 4, 5));
2297 }
2298
TEST(Btree,MergeIntoMultiContainers)2299 TEST(Btree, MergeIntoMultiContainers) {
2300 absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
2301 absl::btree_multiset<int> src2 = {3, 4, 4, 5};
2302 absl::btree_multiset<int> dst;
2303
2304 dst.merge(src1);
2305 EXPECT_TRUE(src1.empty());
2306 EXPECT_THAT(dst, ElementsAre(1, 2, 3));
2307 dst.merge(src2);
2308 EXPECT_TRUE(src2.empty());
2309 EXPECT_THAT(dst, ElementsAre(1, 2, 3, 3, 4, 4, 5));
2310 }
2311
TEST(Btree,MergeIntoMultiContainersWithCompareTo)2312 TEST(Btree, MergeIntoMultiContainersWithCompareTo) {
2313 absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
2314 absl::btree_multiset<int> src2 = {3, 4, 4, 5};
2315 absl::btree_multiset<int, IntCompareToCmp> dst;
2316
2317 dst.merge(src1);
2318 EXPECT_TRUE(src1.empty());
2319 EXPECT_THAT(dst, ElementsAre(1, 2, 3));
2320 dst.merge(src2);
2321 EXPECT_TRUE(src2.empty());
2322 EXPECT_THAT(dst, ElementsAre(1, 2, 3, 3, 4, 4, 5));
2323 }
2324
TEST(Btree,MergeIntoMultiMapsWithDifferentComparators)2325 TEST(Btree, MergeIntoMultiMapsWithDifferentComparators) {
2326 absl::btree_map<int, int, IntCompareToCmp> src1 = {{1, 1}, {2, 2}, {3, 3}};
2327 absl::btree_multimap<int, int, std::greater<int>> src2 = {
2328 {5, 5}, {4, 1}, {4, 4}, {3, 2}};
2329 absl::btree_multimap<int, int> dst;
2330
2331 dst.merge(src1);
2332 EXPECT_TRUE(src1.empty());
2333 EXPECT_THAT(dst, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3)));
2334 dst.merge(src2);
2335 EXPECT_TRUE(src2.empty());
2336 EXPECT_THAT(dst, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), Pair(3, 2),
2337 Pair(4, 1), Pair(4, 4), Pair(5, 5)));
2338 }
2339
TEST(Btree,MergeIntoSetMovableOnly)2340 TEST(Btree, MergeIntoSetMovableOnly) {
2341 absl::btree_set<MovableOnlyInstance> src;
2342 src.insert(MovableOnlyInstance(1));
2343 absl::btree_multiset<MovableOnlyInstance> dst1;
2344 dst1.insert(MovableOnlyInstance(2));
2345 absl::btree_set<MovableOnlyInstance> dst2;
2346
2347 // Test merge into multiset.
2348 dst1.merge(src);
2349
2350 EXPECT_TRUE(src.empty());
2351 // ElementsAre/ElementsAreArray don't work with move-only types.
2352 ASSERT_THAT(dst1, SizeIs(2));
2353 EXPECT_EQ(*dst1.begin(), MovableOnlyInstance(1));
2354 EXPECT_EQ(*std::next(dst1.begin()), MovableOnlyInstance(2));
2355
2356 // Test merge into set.
2357 dst2.merge(dst1);
2358
2359 EXPECT_TRUE(dst1.empty());
2360 ASSERT_THAT(dst2, SizeIs(2));
2361 EXPECT_EQ(*dst2.begin(), MovableOnlyInstance(1));
2362 EXPECT_EQ(*std::next(dst2.begin()), MovableOnlyInstance(2));
2363 }
2364
2365 struct KeyCompareToWeakOrdering {
2366 template <typename T>
operator ()absl::container_internal::__anon2a41e4430411::KeyCompareToWeakOrdering2367 absl::weak_ordering operator()(const T &a, const T &b) const {
2368 return a < b ? absl::weak_ordering::less
2369 : a == b ? absl::weak_ordering::equivalent
2370 : absl::weak_ordering::greater;
2371 }
2372 };
2373
2374 struct KeyCompareToStrongOrdering {
2375 template <typename T>
operator ()absl::container_internal::__anon2a41e4430411::KeyCompareToStrongOrdering2376 absl::strong_ordering operator()(const T &a, const T &b) const {
2377 return a < b ? absl::strong_ordering::less
2378 : a == b ? absl::strong_ordering::equal
2379 : absl::strong_ordering::greater;
2380 }
2381 };
2382
TEST(Btree,UserProvidedKeyCompareToComparators)2383 TEST(Btree, UserProvidedKeyCompareToComparators) {
2384 absl::btree_set<int, KeyCompareToWeakOrdering> weak_set = {1, 2, 3};
2385 EXPECT_TRUE(weak_set.contains(2));
2386 EXPECT_FALSE(weak_set.contains(4));
2387
2388 absl::btree_set<int, KeyCompareToStrongOrdering> strong_set = {1, 2, 3};
2389 EXPECT_TRUE(strong_set.contains(2));
2390 EXPECT_FALSE(strong_set.contains(4));
2391 }
2392
TEST(Btree,TryEmplaceBasicTest)2393 TEST(Btree, TryEmplaceBasicTest) {
2394 absl::btree_map<int, std::string> m;
2395
2396 // Should construct a string from the literal.
2397 m.try_emplace(1, "one");
2398 EXPECT_EQ(1, m.size());
2399
2400 // Try other string constructors and const lvalue key.
2401 const int key(42);
2402 m.try_emplace(key, 3, 'a');
2403 m.try_emplace(2, std::string("two"));
2404
2405 EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
2406 EXPECT_THAT(m, ElementsAreArray(std::vector<std::pair<int, std::string>>{
2407 {1, "one"}, {2, "two"}, {42, "aaa"}}));
2408 }
2409
TEST(Btree,TryEmplaceWithHintWorks)2410 TEST(Btree, TryEmplaceWithHintWorks) {
2411 // Use a counting comparator here to verify that hint is used.
2412 int calls = 0;
2413 auto cmp = [&calls](int x, int y) {
2414 ++calls;
2415 return x < y;
2416 };
2417 using Cmp = decltype(cmp);
2418
2419 // Use a map that is opted out of key_compare being adapted so we can expect
2420 // strict comparison call limits.
2421 absl::btree_map<int, int, CheckedCompareOptedOutCmp<Cmp>> m(cmp);
2422 for (int i = 0; i < 128; ++i) {
2423 m.emplace(i, i);
2424 }
2425
2426 // Sanity check for the comparator
2427 calls = 0;
2428 m.emplace(127, 127);
2429 EXPECT_GE(calls, 4);
2430
2431 // Try with begin hint:
2432 calls = 0;
2433 auto it = m.try_emplace(m.begin(), -1, -1);
2434 EXPECT_EQ(129, m.size());
2435 EXPECT_EQ(it, m.begin());
2436 EXPECT_LE(calls, 2);
2437
2438 // Try with end hint:
2439 calls = 0;
2440 std::pair<int, int> pair1024 = {1024, 1024};
2441 it = m.try_emplace(m.end(), pair1024.first, pair1024.second);
2442 EXPECT_EQ(130, m.size());
2443 EXPECT_EQ(it, --m.end());
2444 EXPECT_LE(calls, 2);
2445
2446 // Try value already present, bad hint; ensure no duplicate added:
2447 calls = 0;
2448 it = m.try_emplace(m.end(), 16, 17);
2449 EXPECT_EQ(130, m.size());
2450 EXPECT_GE(calls, 4);
2451 EXPECT_EQ(it, m.find(16));
2452
2453 // Try value already present, hint points directly to it:
2454 calls = 0;
2455 it = m.try_emplace(it, 16, 17);
2456 EXPECT_EQ(130, m.size());
2457 EXPECT_LE(calls, 2);
2458 EXPECT_EQ(it, m.find(16));
2459
2460 m.erase(2);
2461 EXPECT_EQ(129, m.size());
2462 auto hint = m.find(3);
2463 // Try emplace in the middle of two other elements.
2464 calls = 0;
2465 m.try_emplace(hint, 2, 2);
2466 EXPECT_EQ(130, m.size());
2467 EXPECT_LE(calls, 2);
2468
2469 EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
2470 }
2471
TEST(Btree,TryEmplaceWithBadHint)2472 TEST(Btree, TryEmplaceWithBadHint) {
2473 absl::btree_map<int, int> m = {{1, 1}, {9, 9}};
2474
2475 // Bad hint (too small), should still emplace:
2476 auto it = m.try_emplace(m.begin(), 2, 2);
2477 EXPECT_EQ(it, ++m.begin());
2478 EXPECT_THAT(m, ElementsAreArray(
2479 std::vector<std::pair<int, int>>{{1, 1}, {2, 2}, {9, 9}}));
2480
2481 // Bad hint, too large this time:
2482 it = m.try_emplace(++(++m.begin()), 0, 0);
2483 EXPECT_EQ(it, m.begin());
2484 EXPECT_THAT(m, ElementsAreArray(std::vector<std::pair<int, int>>{
2485 {0, 0}, {1, 1}, {2, 2}, {9, 9}}));
2486 }
2487
TEST(Btree,TryEmplaceMaintainsSortedOrder)2488 TEST(Btree, TryEmplaceMaintainsSortedOrder) {
2489 absl::btree_map<int, std::string> m;
2490 std::pair<int, std::string> pair5 = {5, "five"};
2491
2492 // Test both lvalue & rvalue emplace.
2493 m.try_emplace(10, "ten");
2494 m.try_emplace(pair5.first, pair5.second);
2495 EXPECT_EQ(2, m.size());
2496 EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
2497
2498 int int100{100};
2499 m.try_emplace(int100, "hundred");
2500 m.try_emplace(1, "one");
2501 EXPECT_EQ(4, m.size());
2502 EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
2503 }
2504
TEST(Btree,TryEmplaceWithHintAndNoValueArgsWorks)2505 TEST(Btree, TryEmplaceWithHintAndNoValueArgsWorks) {
2506 absl::btree_map<int, int> m;
2507 m.try_emplace(m.end(), 1);
2508 EXPECT_EQ(0, m[1]);
2509 }
2510
TEST(Btree,TryEmplaceWithHintAndMultipleValueArgsWorks)2511 TEST(Btree, TryEmplaceWithHintAndMultipleValueArgsWorks) {
2512 absl::btree_map<int, std::string> m;
2513 m.try_emplace(m.end(), 1, 10, 'a');
2514 EXPECT_EQ(std::string(10, 'a'), m[1]);
2515 }
2516
TEST(Btree,MoveAssignmentAllocatorPropagation)2517 TEST(Btree, MoveAssignmentAllocatorPropagation) {
2518 InstanceTracker tracker;
2519
2520 int64_t bytes1 = 0, bytes2 = 0;
2521 PropagatingCountingAlloc<MovableOnlyInstance> allocator1(&bytes1);
2522 PropagatingCountingAlloc<MovableOnlyInstance> allocator2(&bytes2);
2523 std::less<MovableOnlyInstance> cmp;
2524
2525 // Test propagating allocator_type.
2526 {
2527 absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>,
2528 PropagatingCountingAlloc<MovableOnlyInstance>>
2529 set1(cmp, allocator1), set2(cmp, allocator2);
2530
2531 for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i));
2532
2533 tracker.ResetCopiesMovesSwaps();
2534 set2 = std::move(set1);
2535 EXPECT_EQ(tracker.moves(), 0);
2536 }
2537 // Test non-propagating allocator_type with equal allocators.
2538 {
2539 absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>,
2540 CountingAllocator<MovableOnlyInstance>>
2541 set1(cmp, allocator1), set2(cmp, allocator1);
2542
2543 for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i));
2544
2545 tracker.ResetCopiesMovesSwaps();
2546 set2 = std::move(set1);
2547 EXPECT_EQ(tracker.moves(), 0);
2548 }
2549 // Test non-propagating allocator_type with different allocators.
2550 {
2551 absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>,
2552 CountingAllocator<MovableOnlyInstance>>
2553 set1(cmp, allocator1), set2(cmp, allocator2);
2554
2555 for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i));
2556
2557 tracker.ResetCopiesMovesSwaps();
2558 set2 = std::move(set1);
2559 EXPECT_GE(tracker.moves(), 100);
2560 }
2561 }
2562
TEST(Btree,EmptyTree)2563 TEST(Btree, EmptyTree) {
2564 absl::btree_set<int> s;
2565 EXPECT_TRUE(s.empty());
2566 EXPECT_EQ(s.size(), 0);
2567 EXPECT_GT(s.max_size(), 0);
2568 }
2569
IsEven(int k)2570 bool IsEven(int k) { return k % 2 == 0; }
2571
TEST(Btree,EraseIf)2572 TEST(Btree, EraseIf) {
2573 // Test that erase_if works with all the container types and supports lambdas.
2574 {
2575 absl::btree_set<int> s = {1, 3, 5, 6, 100};
2576 EXPECT_EQ(erase_if(s, [](int k) { return k > 3; }), 3);
2577 EXPECT_THAT(s, ElementsAre(1, 3));
2578 }
2579 {
2580 absl::btree_multiset<int> s = {1, 3, 3, 5, 6, 6, 100};
2581 EXPECT_EQ(erase_if(s, [](int k) { return k <= 3; }), 3);
2582 EXPECT_THAT(s, ElementsAre(5, 6, 6, 100));
2583 }
2584 {
2585 absl::btree_map<int, int> m = {{1, 1}, {3, 3}, {6, 6}, {100, 100}};
2586 EXPECT_EQ(
2587 erase_if(m, [](std::pair<const int, int> kv) { return kv.first > 3; }),
2588 2);
2589 EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3)));
2590 }
2591 {
2592 absl::btree_multimap<int, int> m = {{1, 1}, {3, 3}, {3, 6},
2593 {6, 6}, {6, 7}, {100, 6}};
2594 EXPECT_EQ(
2595 erase_if(m,
2596 [](std::pair<const int, int> kv) { return kv.second == 6; }),
2597 3);
2598 EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3), Pair(6, 7)));
2599 }
2600 // Test that erasing all elements from a large set works and test support for
2601 // function pointers.
2602 {
2603 absl::btree_set<int> s;
2604 for (int i = 0; i < 1000; ++i) s.insert(2 * i);
2605 EXPECT_EQ(erase_if(s, IsEven), 1000);
2606 EXPECT_THAT(s, IsEmpty());
2607 }
2608 // Test that erase_if supports other format of function pointers.
2609 {
2610 absl::btree_set<int> s = {1, 3, 5, 6, 100};
2611 EXPECT_EQ(erase_if(s, &IsEven), 2);
2612 EXPECT_THAT(s, ElementsAre(1, 3, 5));
2613 }
2614 // Test that erase_if invokes the predicate once per element.
2615 {
2616 absl::btree_set<int> s;
2617 for (int i = 0; i < 1000; ++i) s.insert(i);
2618 int pred_calls = 0;
2619 EXPECT_EQ(erase_if(s,
2620 [&pred_calls](int k) {
2621 ++pred_calls;
2622 return k % 2;
2623 }),
2624 500);
2625 EXPECT_THAT(s, SizeIs(500));
2626 EXPECT_EQ(pred_calls, 1000);
2627 }
2628 }
2629
TEST(Btree,InsertOrAssign)2630 TEST(Btree, InsertOrAssign) {
2631 absl::btree_map<int, int> m = {{1, 1}, {3, 3}};
2632 using value_type = typename decltype(m)::value_type;
2633
2634 auto ret = m.insert_or_assign(4, 4);
2635 EXPECT_EQ(*ret.first, value_type(4, 4));
2636 EXPECT_TRUE(ret.second);
2637 ret = m.insert_or_assign(3, 100);
2638 EXPECT_EQ(*ret.first, value_type(3, 100));
2639 EXPECT_FALSE(ret.second);
2640
2641 auto hint_ret = m.insert_or_assign(ret.first, 3, 200);
2642 EXPECT_EQ(*hint_ret, value_type(3, 200));
2643 hint_ret = m.insert_or_assign(m.find(1), 0, 1);
2644 EXPECT_EQ(*hint_ret, value_type(0, 1));
2645 // Test with bad hint.
2646 hint_ret = m.insert_or_assign(m.end(), -1, 1);
2647 EXPECT_EQ(*hint_ret, value_type(-1, 1));
2648
2649 EXPECT_THAT(m, ElementsAre(Pair(-1, 1), Pair(0, 1), Pair(1, 1), Pair(3, 200),
2650 Pair(4, 4)));
2651 }
2652
TEST(Btree,InsertOrAssignMovableOnly)2653 TEST(Btree, InsertOrAssignMovableOnly) {
2654 absl::btree_map<int, MovableOnlyInstance> m;
2655 using value_type = typename decltype(m)::value_type;
2656
2657 auto ret = m.insert_or_assign(4, MovableOnlyInstance(4));
2658 EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(4)));
2659 EXPECT_TRUE(ret.second);
2660 ret = m.insert_or_assign(4, MovableOnlyInstance(100));
2661 EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(100)));
2662 EXPECT_FALSE(ret.second);
2663
2664 auto hint_ret = m.insert_or_assign(ret.first, 3, MovableOnlyInstance(200));
2665 EXPECT_EQ(*hint_ret, value_type(3, MovableOnlyInstance(200)));
2666
2667 EXPECT_EQ(m.size(), 2);
2668 }
2669
TEST(Btree,BitfieldArgument)2670 TEST(Btree, BitfieldArgument) {
2671 union {
2672 int n : 1;
2673 };
2674 n = 0;
2675 absl::btree_map<int, int> m;
2676 m.erase(n);
2677 m.count(n);
2678 m.find(n);
2679 m.contains(n);
2680 m.equal_range(n);
2681 m.insert_or_assign(n, n);
2682 m.insert_or_assign(m.end(), n, n);
2683 m.try_emplace(n);
2684 m.try_emplace(m.end(), n);
2685 m.at(n);
2686 m[n];
2687 }
2688
TEST(Btree,SetRangeConstructorAndInsertSupportExplicitConversionComparable)2689 TEST(Btree, SetRangeConstructorAndInsertSupportExplicitConversionComparable) {
2690 const absl::string_view names[] = {"n1", "n2"};
2691
2692 absl::btree_set<std::string> name_set1{std::begin(names), std::end(names)};
2693 EXPECT_THAT(name_set1, ElementsAreArray(names));
2694
2695 absl::btree_set<std::string> name_set2;
2696 name_set2.insert(std::begin(names), std::end(names));
2697 EXPECT_THAT(name_set2, ElementsAreArray(names));
2698 }
2699
2700 // A type that is explicitly convertible from int and counts constructor calls.
2701 struct ConstructorCounted {
ConstructorCountedabsl::container_internal::__anon2a41e4430411::ConstructorCounted2702 explicit ConstructorCounted(int i) : i(i) { ++constructor_calls; }
operator ==absl::container_internal::__anon2a41e4430411::ConstructorCounted2703 bool operator==(int other) const { return i == other; }
2704
2705 int i;
2706 static int constructor_calls;
2707 };
2708 int ConstructorCounted::constructor_calls = 0;
2709
2710 struct ConstructorCountedCompare {
operator ()absl::container_internal::__anon2a41e4430411::ConstructorCountedCompare2711 bool operator()(int a, const ConstructorCounted &b) const { return a < b.i; }
operator ()absl::container_internal::__anon2a41e4430411::ConstructorCountedCompare2712 bool operator()(const ConstructorCounted &a, int b) const { return a.i < b; }
operator ()absl::container_internal::__anon2a41e4430411::ConstructorCountedCompare2713 bool operator()(const ConstructorCounted &a,
2714 const ConstructorCounted &b) const {
2715 return a.i < b.i;
2716 }
2717 using is_transparent = void;
2718 };
2719
TEST(Btree,SetRangeConstructorAndInsertExplicitConvComparableLimitConstruction)2720 TEST(Btree,
2721 SetRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
2722 const int i[] = {0, 1, 1};
2723 ConstructorCounted::constructor_calls = 0;
2724
2725 absl::btree_set<ConstructorCounted, ConstructorCountedCompare> set{
2726 std::begin(i), std::end(i)};
2727 EXPECT_THAT(set, ElementsAre(0, 1));
2728 EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
2729
2730 set.insert(std::begin(i), std::end(i));
2731 EXPECT_THAT(set, ElementsAre(0, 1));
2732 EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
2733 }
2734
TEST(Btree,SetRangeConstructorAndInsertSupportExplicitConversionNonComparable)2735 TEST(Btree,
2736 SetRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
2737 const int i[] = {0, 1};
2738
2739 absl::btree_set<std::vector<void *>> s1{std::begin(i), std::end(i)};
2740 EXPECT_THAT(s1, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
2741
2742 absl::btree_set<std::vector<void *>> s2;
2743 s2.insert(std::begin(i), std::end(i));
2744 EXPECT_THAT(s2, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
2745 }
2746
2747 // libstdc++ included with GCC 4.9 has a bug in the std::pair constructors that
2748 // prevents explicit conversions between pair types.
2749 // We only run this test for the libstdc++ from GCC 7 or newer because we can't
2750 // reliably check the libstdc++ version prior to that release.
2751 #if !defined(__GLIBCXX__) || \
2752 (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7)
TEST(Btree,MapRangeConstructorAndInsertSupportExplicitConversionComparable)2753 TEST(Btree, MapRangeConstructorAndInsertSupportExplicitConversionComparable) {
2754 const std::pair<absl::string_view, int> names[] = {{"n1", 1}, {"n2", 2}};
2755
2756 absl::btree_map<std::string, int> name_map1{std::begin(names),
2757 std::end(names)};
2758 EXPECT_THAT(name_map1, ElementsAre(Pair("n1", 1), Pair("n2", 2)));
2759
2760 absl::btree_map<std::string, int> name_map2;
2761 name_map2.insert(std::begin(names), std::end(names));
2762 EXPECT_THAT(name_map2, ElementsAre(Pair("n1", 1), Pair("n2", 2)));
2763 }
2764
TEST(Btree,MapRangeConstructorAndInsertExplicitConvComparableLimitConstruction)2765 TEST(Btree,
2766 MapRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
2767 const std::pair<int, int> i[] = {{0, 1}, {1, 2}, {1, 3}};
2768 ConstructorCounted::constructor_calls = 0;
2769
2770 absl::btree_map<ConstructorCounted, int, ConstructorCountedCompare> map{
2771 std::begin(i), std::end(i)};
2772 EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));
2773 EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
2774
2775 map.insert(std::begin(i), std::end(i));
2776 EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));
2777 EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
2778 }
2779
TEST(Btree,MapRangeConstructorAndInsertSupportExplicitConversionNonComparable)2780 TEST(Btree,
2781 MapRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
2782 const std::pair<int, int> i[] = {{0, 1}, {1, 2}};
2783
2784 absl::btree_map<std::vector<void *>, int> m1{std::begin(i), std::end(i)};
2785 EXPECT_THAT(m1,
2786 ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));
2787
2788 absl::btree_map<std::vector<void *>, int> m2;
2789 m2.insert(std::begin(i), std::end(i));
2790 EXPECT_THAT(m2,
2791 ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));
2792 }
2793
TEST(Btree,HeterogeneousTryEmplace)2794 TEST(Btree, HeterogeneousTryEmplace) {
2795 absl::btree_map<std::string, int> m;
2796 std::string s = "key";
2797 absl::string_view sv = s;
2798 m.try_emplace(sv, 1);
2799 EXPECT_EQ(m[s], 1);
2800
2801 m.try_emplace(m.end(), sv, 2);
2802 EXPECT_EQ(m[s], 1);
2803 }
2804
TEST(Btree,HeterogeneousOperatorMapped)2805 TEST(Btree, HeterogeneousOperatorMapped) {
2806 absl::btree_map<std::string, int> m;
2807 std::string s = "key";
2808 absl::string_view sv = s;
2809 m[sv] = 1;
2810 EXPECT_EQ(m[s], 1);
2811
2812 m[sv] = 2;
2813 EXPECT_EQ(m[s], 2);
2814 }
2815
TEST(Btree,HeterogeneousInsertOrAssign)2816 TEST(Btree, HeterogeneousInsertOrAssign) {
2817 absl::btree_map<std::string, int> m;
2818 std::string s = "key";
2819 absl::string_view sv = s;
2820 m.insert_or_assign(sv, 1);
2821 EXPECT_EQ(m[s], 1);
2822
2823 m.insert_or_assign(m.end(), sv, 2);
2824 EXPECT_EQ(m[s], 2);
2825 }
2826 #endif
2827
2828 // This test requires std::launder for mutable key access in node handles.
2829 #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
TEST(Btree,NodeHandleMutableKeyAccess)2830 TEST(Btree, NodeHandleMutableKeyAccess) {
2831 {
2832 absl::btree_map<std::string, std::string> map;
2833
2834 map["key1"] = "mapped";
2835
2836 auto nh = map.extract(map.begin());
2837 nh.key().resize(3);
2838 map.insert(std::move(nh));
2839
2840 EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
2841 }
2842 // Also for multimap.
2843 {
2844 absl::btree_multimap<std::string, std::string> map;
2845
2846 map.emplace("key1", "mapped");
2847
2848 auto nh = map.extract(map.begin());
2849 nh.key().resize(3);
2850 map.insert(std::move(nh));
2851
2852 EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
2853 }
2854 }
2855 #endif
2856
2857 struct MultiKey {
2858 int i1;
2859 int i2;
2860 };
2861
operator ==(const MultiKey a,const MultiKey b)2862 bool operator==(const MultiKey a, const MultiKey b) {
2863 return a.i1 == b.i1 && a.i2 == b.i2;
2864 }
2865
2866 // A heterogeneous comparator that has different equivalence classes for
2867 // different lookup types.
2868 struct MultiKeyComp {
2869 using is_transparent = void;
operator ()absl::container_internal::__anon2a41e4430411::MultiKeyComp2870 bool operator()(const MultiKey a, const MultiKey b) const {
2871 if (a.i1 != b.i1) return a.i1 < b.i1;
2872 return a.i2 < b.i2;
2873 }
operator ()absl::container_internal::__anon2a41e4430411::MultiKeyComp2874 bool operator()(const int a, const MultiKey b) const { return a < b.i1; }
operator ()absl::container_internal::__anon2a41e4430411::MultiKeyComp2875 bool operator()(const MultiKey a, const int b) const { return a.i1 < b; }
2876 };
2877
2878 // A heterogeneous, three-way comparator that has different equivalence classes
2879 // for different lookup types.
2880 struct MultiKeyThreeWayComp {
2881 using is_transparent = void;
operator ()absl::container_internal::__anon2a41e4430411::MultiKeyThreeWayComp2882 absl::weak_ordering operator()(const MultiKey a, const MultiKey b) const {
2883 if (a.i1 < b.i1) return absl::weak_ordering::less;
2884 if (a.i1 > b.i1) return absl::weak_ordering::greater;
2885 if (a.i2 < b.i2) return absl::weak_ordering::less;
2886 if (a.i2 > b.i2) return absl::weak_ordering::greater;
2887 return absl::weak_ordering::equivalent;
2888 }
operator ()absl::container_internal::__anon2a41e4430411::MultiKeyThreeWayComp2889 absl::weak_ordering operator()(const int a, const MultiKey b) const {
2890 if (a < b.i1) return absl::weak_ordering::less;
2891 if (a > b.i1) return absl::weak_ordering::greater;
2892 return absl::weak_ordering::equivalent;
2893 }
operator ()absl::container_internal::__anon2a41e4430411::MultiKeyThreeWayComp2894 absl::weak_ordering operator()(const MultiKey a, const int b) const {
2895 if (a.i1 < b) return absl::weak_ordering::less;
2896 if (a.i1 > b) return absl::weak_ordering::greater;
2897 return absl::weak_ordering::equivalent;
2898 }
2899 };
2900
2901 template <typename Compare>
2902 class BtreeMultiKeyTest : public ::testing::Test {};
2903 using MultiKeyComps = ::testing::Types<MultiKeyComp, MultiKeyThreeWayComp>;
2904 TYPED_TEST_SUITE(BtreeMultiKeyTest, MultiKeyComps);
2905
TYPED_TEST(BtreeMultiKeyTest,EqualRange)2906 TYPED_TEST(BtreeMultiKeyTest, EqualRange) {
2907 absl::btree_set<MultiKey, TypeParam> set;
2908 for (int i = 0; i < 100; ++i) {
2909 for (int j = 0; j < 100; ++j) {
2910 set.insert({i, j});
2911 }
2912 }
2913
2914 for (int i = 0; i < 100; ++i) {
2915 auto equal_range = set.equal_range(i);
2916 EXPECT_EQ(equal_range.first->i1, i);
2917 EXPECT_EQ(equal_range.first->i2, 0) << i;
2918 EXPECT_EQ(std::distance(equal_range.first, equal_range.second), 100) << i;
2919 }
2920 }
2921
TYPED_TEST(BtreeMultiKeyTest,Extract)2922 TYPED_TEST(BtreeMultiKeyTest, Extract) {
2923 absl::btree_set<MultiKey, TypeParam> set;
2924 for (int i = 0; i < 100; ++i) {
2925 for (int j = 0; j < 100; ++j) {
2926 set.insert({i, j});
2927 }
2928 }
2929
2930 for (int i = 0; i < 100; ++i) {
2931 auto node_handle = set.extract(i);
2932 EXPECT_EQ(node_handle.value().i1, i);
2933 EXPECT_EQ(node_handle.value().i2, 0) << i;
2934 }
2935
2936 for (int i = 0; i < 100; ++i) {
2937 auto node_handle = set.extract(i);
2938 EXPECT_EQ(node_handle.value().i1, i);
2939 EXPECT_EQ(node_handle.value().i2, 1) << i;
2940 }
2941 }
2942
TYPED_TEST(BtreeMultiKeyTest,Erase)2943 TYPED_TEST(BtreeMultiKeyTest, Erase) {
2944 absl::btree_set<MultiKey, TypeParam> set = {
2945 {1, 1}, {2, 1}, {2, 2}, {3, 1}};
2946 EXPECT_EQ(set.erase(2), 2);
2947 EXPECT_THAT(set, ElementsAre(MultiKey{1, 1}, MultiKey{3, 1}));
2948 }
2949
TYPED_TEST(BtreeMultiKeyTest,Count)2950 TYPED_TEST(BtreeMultiKeyTest, Count) {
2951 const absl::btree_set<MultiKey, TypeParam> set = {
2952 {1, 1}, {2, 1}, {2, 2}, {3, 1}};
2953 EXPECT_EQ(set.count(2), 2);
2954 }
2955
TEST(Btree,AllocConstructor)2956 TEST(Btree, AllocConstructor) {
2957 using Alloc = CountingAllocator<int>;
2958 using Set = absl::btree_set<int, std::less<int>, Alloc>;
2959 int64_t bytes_used = 0;
2960 Alloc alloc(&bytes_used);
2961 Set set(alloc);
2962
2963 set.insert({1, 2, 3});
2964
2965 EXPECT_THAT(set, ElementsAre(1, 2, 3));
2966 EXPECT_GT(bytes_used, set.size() * sizeof(int));
2967 }
2968
TEST(Btree,AllocInitializerListConstructor)2969 TEST(Btree, AllocInitializerListConstructor) {
2970 using Alloc = CountingAllocator<int>;
2971 using Set = absl::btree_set<int, std::less<int>, Alloc>;
2972 int64_t bytes_used = 0;
2973 Alloc alloc(&bytes_used);
2974 Set set({1, 2, 3}, alloc);
2975
2976 EXPECT_THAT(set, ElementsAre(1, 2, 3));
2977 EXPECT_GT(bytes_used, set.size() * sizeof(int));
2978 }
2979
TEST(Btree,AllocRangeConstructor)2980 TEST(Btree, AllocRangeConstructor) {
2981 using Alloc = CountingAllocator<int>;
2982 using Set = absl::btree_set<int, std::less<int>, Alloc>;
2983 int64_t bytes_used = 0;
2984 Alloc alloc(&bytes_used);
2985 std::vector<int> v = {1, 2, 3};
2986 Set set(v.begin(), v.end(), alloc);
2987
2988 EXPECT_THAT(set, ElementsAre(1, 2, 3));
2989 EXPECT_GT(bytes_used, set.size() * sizeof(int));
2990 }
2991
TEST(Btree,AllocCopyConstructor)2992 TEST(Btree, AllocCopyConstructor) {
2993 using Alloc = CountingAllocator<int>;
2994 using Set = absl::btree_set<int, std::less<int>, Alloc>;
2995 int64_t bytes_used1 = 0;
2996 Alloc alloc1(&bytes_used1);
2997 Set set1(alloc1);
2998
2999 set1.insert({1, 2, 3});
3000
3001 int64_t bytes_used2 = 0;
3002 Alloc alloc2(&bytes_used2);
3003 Set set2(set1, alloc2);
3004
3005 EXPECT_THAT(set1, ElementsAre(1, 2, 3));
3006 EXPECT_THAT(set2, ElementsAre(1, 2, 3));
3007 EXPECT_GT(bytes_used1, set1.size() * sizeof(int));
3008 EXPECT_EQ(bytes_used1, bytes_used2);
3009 }
3010
TEST(Btree,AllocMoveConstructor_SameAlloc)3011 TEST(Btree, AllocMoveConstructor_SameAlloc) {
3012 using Alloc = CountingAllocator<int>;
3013 using Set = absl::btree_set<int, std::less<int>, Alloc>;
3014 int64_t bytes_used = 0;
3015 Alloc alloc(&bytes_used);
3016 Set set1(alloc);
3017
3018 set1.insert({1, 2, 3});
3019
3020 const int64_t original_bytes_used = bytes_used;
3021 EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
3022
3023 Set set2(std::move(set1), alloc);
3024
3025 EXPECT_THAT(set2, ElementsAre(1, 2, 3));
3026 EXPECT_EQ(bytes_used, original_bytes_used);
3027 }
3028
TEST(Btree,AllocMoveConstructor_DifferentAlloc)3029 TEST(Btree, AllocMoveConstructor_DifferentAlloc) {
3030 using Alloc = CountingAllocator<int>;
3031 using Set = absl::btree_set<int, std::less<int>, Alloc>;
3032 int64_t bytes_used1 = 0;
3033 Alloc alloc1(&bytes_used1);
3034 Set set1(alloc1);
3035
3036 set1.insert({1, 2, 3});
3037
3038 const int64_t original_bytes_used = bytes_used1;
3039 EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
3040
3041 int64_t bytes_used2 = 0;
3042 Alloc alloc2(&bytes_used2);
3043 Set set2(std::move(set1), alloc2);
3044
3045 EXPECT_THAT(set2, ElementsAre(1, 2, 3));
3046 // We didn't free these bytes allocated by `set1` yet.
3047 EXPECT_EQ(bytes_used1, original_bytes_used);
3048 EXPECT_EQ(bytes_used2, original_bytes_used);
3049 }
3050
IntCmp(const int a,const int b)3051 bool IntCmp(const int a, const int b) { return a < b; }
3052
TEST(Btree,SupportsFunctionPtrComparator)3053 TEST(Btree, SupportsFunctionPtrComparator) {
3054 absl::btree_set<int, decltype(IntCmp) *> set(IntCmp);
3055 set.insert({1, 2, 3});
3056 EXPECT_THAT(set, ElementsAre(1, 2, 3));
3057 EXPECT_TRUE(set.key_comp()(1, 2));
3058 EXPECT_TRUE(set.value_comp()(1, 2));
3059
3060 absl::btree_map<int, int, decltype(IntCmp) *> map(&IntCmp);
3061 map[1] = 1;
3062 EXPECT_THAT(map, ElementsAre(Pair(1, 1)));
3063 EXPECT_TRUE(map.key_comp()(1, 2));
3064 EXPECT_TRUE(map.value_comp()(std::make_pair(1, 1), std::make_pair(2, 2)));
3065 }
3066
3067 template <typename Compare>
3068 struct TransparentPassThroughComp {
3069 using is_transparent = void;
3070
3071 // This will fail compilation if we attempt a comparison that Compare does not
3072 // support, and the failure will happen inside the function implementation so
3073 // it can't be avoided by using SFINAE on this comparator.
3074 template <typename T, typename U>
operator ()absl::container_internal::__anon2a41e4430411::TransparentPassThroughComp3075 bool operator()(const T &lhs, const U &rhs) const {
3076 return Compare()(lhs, rhs);
3077 }
3078 };
3079
TEST(Btree,SupportsTransparentComparatorThatDoesNotImplementAllVisibleOperators)3080 TEST(Btree,
3081 SupportsTransparentComparatorThatDoesNotImplementAllVisibleOperators) {
3082 absl::btree_set<MultiKey, TransparentPassThroughComp<MultiKeyComp>> set;
3083 set.insert(MultiKey{1, 2});
3084 EXPECT_TRUE(set.contains(1));
3085 }
3086
TEST(Btree,ConstructImplicitlyWithUnadaptedComparator)3087 TEST(Btree, ConstructImplicitlyWithUnadaptedComparator) {
3088 absl::btree_set<MultiKey, MultiKeyComp> set = {{}, MultiKeyComp{}};
3089 }
3090
TEST(Btree,InvalidComparatorsCaught)3091 TEST(Btree, InvalidComparatorsCaught) {
3092 if (!IsAssertEnabled()) GTEST_SKIP() << "Assertions not enabled.";
3093
3094 {
3095 struct ZeroAlwaysLessCmp {
3096 bool operator()(int lhs, int rhs) const {
3097 if (lhs == 0) return true;
3098 return lhs < rhs;
3099 }
3100 };
3101 absl::btree_set<int, ZeroAlwaysLessCmp> set;
3102 EXPECT_DEATH(set.insert({0, 1, 2}), "is_self_equivalent");
3103 }
3104 {
3105 struct ThreeWayAlwaysLessCmp {
3106 absl::weak_ordering operator()(int, int) const {
3107 return absl::weak_ordering::less;
3108 }
3109 };
3110 absl::btree_set<int, ThreeWayAlwaysLessCmp> set;
3111 EXPECT_DEATH(set.insert({0, 1, 2}), "is_self_equivalent");
3112 }
3113 {
3114 struct SumGreaterZeroCmp {
3115 bool operator()(int lhs, int rhs) const {
3116 // First, do equivalence correctly - so we can test later condition.
3117 if (lhs == rhs) return false;
3118 return lhs + rhs > 0;
3119 }
3120 };
3121 absl::btree_set<int, SumGreaterZeroCmp> set;
3122 // Note: '!' only needs to be escaped when it's the first character.
3123 EXPECT_DEATH(set.insert({0, 1, 2}),
3124 R"regex(\!lhs_comp_rhs \|\| !comp\(\)\(rhs, lhs\))regex");
3125 }
3126 {
3127 struct ThreeWaySumGreaterZeroCmp {
3128 absl::weak_ordering operator()(int lhs, int rhs) const {
3129 // First, do equivalence correctly - so we can test later condition.
3130 if (lhs == rhs) return absl::weak_ordering::equivalent;
3131
3132 if (lhs + rhs > 0) return absl::weak_ordering::less;
3133 if (lhs + rhs == 0) return absl::weak_ordering::equivalent;
3134 return absl::weak_ordering::greater;
3135 }
3136 };
3137 absl::btree_set<int, ThreeWaySumGreaterZeroCmp> set;
3138 EXPECT_DEATH(set.insert({0, 1, 2}), "lhs_comp_rhs < 0 -> rhs_comp_lhs > 0");
3139 }
3140 }
3141
3142 #ifndef _MSC_VER
3143 // This test crashes on MSVC.
TEST(Btree,InvalidIteratorUse)3144 TEST(Btree, InvalidIteratorUse) {
3145 if (!BtreeNodePeer::UsesGenerations<absl::btree_set<int>>())
3146 GTEST_SKIP() << "Generation validation for iterators is disabled.";
3147
3148 {
3149 absl::btree_set<int> set;
3150 for (int i = 0; i < 10; ++i) set.insert(i);
3151 auto it = set.begin();
3152 set.erase(it++);
3153 EXPECT_DEATH(set.erase(it++), "invalidated iterator");
3154 }
3155 {
3156 absl::btree_set<int> set;
3157 for (int i = 0; i < 10; ++i) set.insert(i);
3158 auto it = set.insert(20).first;
3159 set.insert(30);
3160 EXPECT_DEATH(*it, "invalidated iterator");
3161 }
3162 {
3163 absl::btree_set<int> set;
3164 for (int i = 0; i < 10000; ++i) set.insert(i);
3165 auto it = set.find(5000);
3166 ASSERT_NE(it, set.end());
3167 set.erase(1);
3168 EXPECT_DEATH(*it, "invalidated iterator");
3169 }
3170 {
3171 absl::btree_set<int> set;
3172 for (int i = 0; i < 10; ++i) set.insert(i);
3173 auto it = set.insert(20).first;
3174 set.insert(30);
3175 EXPECT_DEATH(void(it == set.begin()), "invalidated iterator");
3176 EXPECT_DEATH(void(set.begin() == it), "invalidated iterator");
3177 }
3178 }
3179 #endif
3180
3181 class OnlyConstructibleByAllocator {
OnlyConstructibleByAllocator(int i)3182 explicit OnlyConstructibleByAllocator(int i) : i_(i) {}
3183
3184 public:
OnlyConstructibleByAllocator(const OnlyConstructibleByAllocator & other)3185 OnlyConstructibleByAllocator(const OnlyConstructibleByAllocator &other)
3186 : i_(other.i_) {}
operator =(const OnlyConstructibleByAllocator & other)3187 OnlyConstructibleByAllocator &operator=(
3188 const OnlyConstructibleByAllocator &other) {
3189 i_ = other.i_;
3190 return *this;
3191 }
Get() const3192 int Get() const { return i_; }
operator ==(int i) const3193 bool operator==(int i) const { return i_ == i; }
3194
3195 private:
3196 template <typename T>
3197 friend class OnlyConstructibleAllocator;
3198
3199 int i_;
3200 };
3201
3202 template <typename T = OnlyConstructibleByAllocator>
3203 class OnlyConstructibleAllocator : public std::allocator<T> {
3204 public:
3205 OnlyConstructibleAllocator() = default;
3206 template <class U>
OnlyConstructibleAllocator(const OnlyConstructibleAllocator<U> &)3207 explicit OnlyConstructibleAllocator(const OnlyConstructibleAllocator<U> &) {}
3208
construct(OnlyConstructibleByAllocator * p,int i)3209 void construct(OnlyConstructibleByAllocator *p, int i) {
3210 new (p) OnlyConstructibleByAllocator(i);
3211 }
3212 template <typename Pair>
construct(Pair * p,const int i)3213 void construct(Pair *p, const int i) {
3214 OnlyConstructibleByAllocator only(i);
3215 new (p) Pair(std::move(only), i);
3216 }
3217
3218 template <class U>
3219 struct rebind {
3220 using other = OnlyConstructibleAllocator<U>;
3221 };
3222 };
3223
3224 struct OnlyConstructibleByAllocatorComp {
3225 using is_transparent = void;
operator ()absl::container_internal::__anon2a41e4430411::OnlyConstructibleByAllocatorComp3226 bool operator()(OnlyConstructibleByAllocator a,
3227 OnlyConstructibleByAllocator b) const {
3228 return a.Get() < b.Get();
3229 }
operator ()absl::container_internal::__anon2a41e4430411::OnlyConstructibleByAllocatorComp3230 bool operator()(int a, OnlyConstructibleByAllocator b) const {
3231 return a < b.Get();
3232 }
operator ()absl::container_internal::__anon2a41e4430411::OnlyConstructibleByAllocatorComp3233 bool operator()(OnlyConstructibleByAllocator a, int b) const {
3234 return a.Get() < b;
3235 }
3236 };
3237
TEST(Btree,OnlyConstructibleByAllocatorType)3238 TEST(Btree, OnlyConstructibleByAllocatorType) {
3239 const std::array<int, 2> arr = {3, 4};
3240 {
3241 absl::btree_set<OnlyConstructibleByAllocator,
3242 OnlyConstructibleByAllocatorComp,
3243 OnlyConstructibleAllocator<>>
3244 set;
3245 set.emplace(1);
3246 set.emplace_hint(set.end(), 2);
3247 set.insert(arr.begin(), arr.end());
3248 EXPECT_THAT(set, ElementsAre(1, 2, 3, 4));
3249 }
3250 {
3251 absl::btree_multiset<OnlyConstructibleByAllocator,
3252 OnlyConstructibleByAllocatorComp,
3253 OnlyConstructibleAllocator<>>
3254 set;
3255 set.emplace(1);
3256 set.emplace_hint(set.end(), 2);
3257 // TODO(ezb): fix insert_multi to allow this to compile.
3258 // set.insert(arr.begin(), arr.end());
3259 EXPECT_THAT(set, ElementsAre(1, 2));
3260 }
3261 {
3262 absl::btree_map<OnlyConstructibleByAllocator, int,
3263 OnlyConstructibleByAllocatorComp,
3264 OnlyConstructibleAllocator<>>
3265 map;
3266 map.emplace(1);
3267 map.emplace_hint(map.end(), 2);
3268 map.insert(arr.begin(), arr.end());
3269 EXPECT_THAT(map,
3270 ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), Pair(4, 4)));
3271 }
3272 {
3273 absl::btree_multimap<OnlyConstructibleByAllocator, int,
3274 OnlyConstructibleByAllocatorComp,
3275 OnlyConstructibleAllocator<>>
3276 map;
3277 map.emplace(1);
3278 map.emplace_hint(map.end(), 2);
3279 // TODO(ezb): fix insert_multi to allow this to compile.
3280 // map.insert(arr.begin(), arr.end());
3281 EXPECT_THAT(map, ElementsAre(Pair(1, 1), Pair(2, 2)));
3282 }
3283 }
3284
3285 class NotAssignable {
3286 public:
NotAssignable(int i)3287 explicit NotAssignable(int i) : i_(i) {}
NotAssignable(const NotAssignable & other)3288 NotAssignable(const NotAssignable &other) : i_(other.i_) {}
3289 NotAssignable &operator=(NotAssignable &&other) = delete;
Get() const3290 int Get() const { return i_; }
operator ==(int i) const3291 bool operator==(int i) const { return i_ == i; }
operator <(NotAssignable a,NotAssignable b)3292 friend bool operator<(NotAssignable a, NotAssignable b) {
3293 return a.i_ < b.i_;
3294 }
3295
3296 private:
3297 int i_;
3298 };
3299
TEST(Btree,NotAssignableType)3300 TEST(Btree, NotAssignableType) {
3301 {
3302 absl::btree_set<NotAssignable> set;
3303 set.emplace(1);
3304 set.emplace_hint(set.end(), 2);
3305 set.insert(NotAssignable(3));
3306 set.insert(set.end(), NotAssignable(4));
3307 EXPECT_THAT(set, ElementsAre(1, 2, 3, 4));
3308 set.erase(set.begin());
3309 EXPECT_THAT(set, ElementsAre(2, 3, 4));
3310 }
3311 {
3312 absl::btree_multiset<NotAssignable> set;
3313 set.emplace(1);
3314 set.emplace_hint(set.end(), 2);
3315 set.insert(NotAssignable(2));
3316 set.insert(set.end(), NotAssignable(3));
3317 EXPECT_THAT(set, ElementsAre(1, 2, 2, 3));
3318 set.erase(set.begin());
3319 EXPECT_THAT(set, ElementsAre(2, 2, 3));
3320 }
3321 {
3322 absl::btree_map<NotAssignable, int> map;
3323 map.emplace(NotAssignable(1), 1);
3324 map.emplace_hint(map.end(), NotAssignable(2), 2);
3325 map.insert({NotAssignable(3), 3});
3326 map.insert(map.end(), {NotAssignable(4), 4});
3327 EXPECT_THAT(map,
3328 ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), Pair(4, 4)));
3329 map.erase(map.begin());
3330 EXPECT_THAT(map, ElementsAre(Pair(2, 2), Pair(3, 3), Pair(4, 4)));
3331 }
3332 {
3333 absl::btree_multimap<NotAssignable, int> map;
3334 map.emplace(NotAssignable(1), 1);
3335 map.emplace_hint(map.end(), NotAssignable(2), 2);
3336 map.insert({NotAssignable(2), 3});
3337 map.insert(map.end(), {NotAssignable(3), 3});
3338 EXPECT_THAT(map,
3339 ElementsAre(Pair(1, 1), Pair(2, 2), Pair(2, 3), Pair(3, 3)));
3340 map.erase(map.begin());
3341 EXPECT_THAT(map, ElementsAre(Pair(2, 2), Pair(2, 3), Pair(3, 3)));
3342 }
3343 }
3344
3345 struct ArenaLike {
3346 void* recycled = nullptr;
3347 size_t recycled_size = 0;
3348 };
3349
3350 // A very simple implementation of arena allocation.
3351 template <typename T>
3352 class ArenaLikeAllocator : public std::allocator<T> {
3353 public:
3354 // Standard library containers require the ability to allocate objects of
3355 // different types which they can do so via rebind.other.
3356 template <typename U>
3357 struct rebind {
3358 using other = ArenaLikeAllocator<U>;
3359 };
3360
ArenaLikeAllocator(ArenaLike * arena)3361 explicit ArenaLikeAllocator(ArenaLike* arena) noexcept : arena_(arena) {}
3362
~ArenaLikeAllocator()3363 ~ArenaLikeAllocator() {
3364 if (arena_->recycled != nullptr) {
3365 delete [] static_cast<T*>(arena_->recycled);
3366 arena_->recycled = nullptr;
3367 }
3368 }
3369
3370 template<typename U>
ArenaLikeAllocator(const ArenaLikeAllocator<U> & other)3371 explicit ArenaLikeAllocator(const ArenaLikeAllocator<U>& other) noexcept
3372 : arena_(other.arena_) {}
3373
allocate(size_t num_objects,const void * =nullptr)3374 T* allocate(size_t num_objects, const void* = nullptr) {
3375 size_t size = num_objects * sizeof(T);
3376 if (arena_->recycled != nullptr && arena_->recycled_size == size) {
3377 T* result = static_cast<T*>(arena_->recycled);
3378 arena_->recycled = nullptr;
3379 return result;
3380 }
3381 return new T[num_objects];
3382 }
3383
deallocate(T * p,size_t num_objects)3384 void deallocate(T* p, size_t num_objects) {
3385 size_t size = num_objects * sizeof(T);
3386
3387 // Simulate writing to the freed memory as an actual arena allocator might
3388 // do. This triggers an error report if the memory is poisoned.
3389 memset(p, 0xde, size);
3390
3391 if (arena_->recycled == nullptr) {
3392 arena_->recycled = p;
3393 arena_->recycled_size = size;
3394 } else {
3395 delete [] p;
3396 }
3397 }
3398
3399 ArenaLike* arena_;
3400 };
3401
3402 // This test verifies that an arena allocator that reuses memory will not be
3403 // asked to free poisoned BTree memory.
TEST(Btree,ReusePoisonMemory)3404 TEST(Btree, ReusePoisonMemory) {
3405 using Alloc = ArenaLikeAllocator<int64_t>;
3406 using Set = absl::btree_set<int64_t, std::less<int64_t>, Alloc>;
3407 ArenaLike arena;
3408 Alloc alloc(&arena);
3409 Set set(alloc);
3410
3411 set.insert(0);
3412 set.erase(0);
3413 set.insert(0);
3414 }
3415
TEST(Btree,IteratorSubtraction)3416 TEST(Btree, IteratorSubtraction) {
3417 absl::BitGen bitgen;
3418 std::vector<int> vec;
3419 // Randomize the set's insertion order so the nodes aren't all full.
3420 for (int i = 0; i < 1000000; ++i) vec.push_back(i);
3421 absl::c_shuffle(vec, bitgen);
3422
3423 absl::btree_set<int> set;
3424 for (int i : vec) set.insert(i);
3425
3426 for (int i = 0; i < 1000; ++i) {
3427 size_t begin = absl::Uniform(bitgen, 0u, set.size());
3428 size_t end = absl::Uniform(bitgen, begin, set.size());
3429 ASSERT_EQ(end - begin, set.find(end) - set.find(begin))
3430 << begin << " " << end;
3431 }
3432 }
3433
TEST(Btree,DereferencingEndIterator)3434 TEST(Btree, DereferencingEndIterator) {
3435 if (!IsAssertEnabled()) GTEST_SKIP() << "Assertions not enabled.";
3436
3437 absl::btree_set<int> set;
3438 for (int i = 0; i < 1000; ++i) set.insert(i);
3439 EXPECT_DEATH(*set.end(), R"regex(Dereferencing end\(\) iterator)regex");
3440 }
3441
TEST(Btree,InvalidIteratorComparison)3442 TEST(Btree, InvalidIteratorComparison) {
3443 if (!IsAssertEnabled()) GTEST_SKIP() << "Assertions not enabled.";
3444
3445 absl::btree_set<int> set1, set2;
3446 for (int i = 0; i < 1000; ++i) {
3447 set1.insert(i);
3448 set2.insert(i);
3449 }
3450
3451 constexpr const char *kValueInitDeathMessage =
3452 "Comparing default-constructed iterator with .*non-default-constructed "
3453 "iterator";
3454 typename absl::btree_set<int>::iterator iter1, iter2;
3455 EXPECT_EQ(iter1, iter2);
3456 EXPECT_DEATH(void(set1.begin() == iter1), kValueInitDeathMessage);
3457 EXPECT_DEATH(void(iter1 == set1.begin()), kValueInitDeathMessage);
3458
3459 constexpr const char *kDifferentContainerDeathMessage =
3460 "Comparing iterators from different containers";
3461 iter1 = set1.begin();
3462 iter2 = set2.begin();
3463 EXPECT_DEATH(void(iter1 == iter2), kDifferentContainerDeathMessage);
3464 EXPECT_DEATH(void(iter2 == iter1), kDifferentContainerDeathMessage);
3465 }
3466
3467 } // namespace
3468 } // namespace container_internal
3469 ABSL_NAMESPACE_END
3470 } // namespace absl
3471