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