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 <cstdint>
18 #include <limits>
19 #include <map>
20 #include <memory>
21 #include <stdexcept>
22 #include <string>
23 #include <type_traits>
24 #include <utility>
25
26 #include "gmock/gmock.h"
27 #include "gtest/gtest.h"
28 #include "absl/base/internal/raw_logging.h"
29 #include "absl/base/macros.h"
30 #include "absl/container/btree_map.h"
31 #include "absl/container/btree_set.h"
32 #include "absl/container/internal/counting_allocator.h"
33 #include "absl/container/internal/test_instance_tracker.h"
34 #include "absl/flags/flag.h"
35 #include "absl/hash/hash_testing.h"
36 #include "absl/memory/memory.h"
37 #include "absl/meta/type_traits.h"
38 #include "absl/strings/str_cat.h"
39 #include "absl/strings/str_split.h"
40 #include "absl/strings/string_view.h"
41 #include "absl/types/compare.h"
42
43 ABSL_FLAG(int, test_values, 10000, "The number of values to use for tests");
44
45 namespace absl {
46 ABSL_NAMESPACE_BEGIN
47 namespace container_internal {
48 namespace {
49
50 using ::absl::test_internal::CopyableMovableInstance;
51 using ::absl::test_internal::InstanceTracker;
52 using ::absl::test_internal::MovableOnlyInstance;
53 using ::testing::ElementsAre;
54 using ::testing::ElementsAreArray;
55 using ::testing::IsEmpty;
56 using ::testing::IsNull;
57 using ::testing::Pair;
58
59 template <typename T, typename U>
CheckPairEquals(const T & x,const U & y)60 void CheckPairEquals(const T &x, const U &y) {
61 ABSL_INTERNAL_CHECK(x == y, "Values are unequal.");
62 }
63
64 template <typename T, typename U, typename V, typename W>
CheckPairEquals(const std::pair<T,U> & x,const std::pair<V,W> & y)65 void CheckPairEquals(const std::pair<T, U> &x, const std::pair<V, W> &y) {
66 CheckPairEquals(x.first, y.first);
67 CheckPairEquals(x.second, y.second);
68 }
69 } // namespace
70
71 // The base class for a sorted associative container checker. TreeType is the
72 // container type to check and CheckerType is the container type to check
73 // against. TreeType is expected to be btree_{set,map,multiset,multimap} and
74 // CheckerType is expected to be {set,map,multiset,multimap}.
75 template <typename TreeType, typename CheckerType>
76 class base_checker {
77 public:
78 using key_type = typename TreeType::key_type;
79 using value_type = typename TreeType::value_type;
80 using key_compare = typename TreeType::key_compare;
81 using pointer = typename TreeType::pointer;
82 using const_pointer = typename TreeType::const_pointer;
83 using reference = typename TreeType::reference;
84 using const_reference = typename TreeType::const_reference;
85 using size_type = typename TreeType::size_type;
86 using difference_type = typename TreeType::difference_type;
87 using iterator = typename TreeType::iterator;
88 using const_iterator = typename TreeType::const_iterator;
89 using reverse_iterator = typename TreeType::reverse_iterator;
90 using const_reverse_iterator = typename TreeType::const_reverse_iterator;
91
92 public:
base_checker()93 base_checker() : const_tree_(tree_) {}
base_checker(const base_checker & other)94 base_checker(const base_checker &other)
95 : tree_(other.tree_), const_tree_(tree_), checker_(other.checker_) {}
96 template <typename InputIterator>
base_checker(InputIterator b,InputIterator e)97 base_checker(InputIterator b, InputIterator e)
98 : tree_(b, e), const_tree_(tree_), checker_(b, e) {}
99
begin()100 iterator begin() { return tree_.begin(); }
begin() const101 const_iterator begin() const { return tree_.begin(); }
end()102 iterator end() { return tree_.end(); }
end() const103 const_iterator end() const { return tree_.end(); }
rbegin()104 reverse_iterator rbegin() { return tree_.rbegin(); }
rbegin() const105 const_reverse_iterator rbegin() const { return tree_.rbegin(); }
rend()106 reverse_iterator rend() { return tree_.rend(); }
rend() const107 const_reverse_iterator rend() const { return tree_.rend(); }
108
109 template <typename IterType, typename CheckerIterType>
iter_check(IterType tree_iter,CheckerIterType checker_iter) const110 IterType iter_check(IterType tree_iter, CheckerIterType checker_iter) const {
111 if (tree_iter == tree_.end()) {
112 ABSL_INTERNAL_CHECK(checker_iter == checker_.end(),
113 "Checker iterator not at end.");
114 } else {
115 CheckPairEquals(*tree_iter, *checker_iter);
116 }
117 return tree_iter;
118 }
119 template <typename IterType, typename CheckerIterType>
riter_check(IterType tree_iter,CheckerIterType checker_iter) const120 IterType riter_check(IterType tree_iter, CheckerIterType checker_iter) const {
121 if (tree_iter == tree_.rend()) {
122 ABSL_INTERNAL_CHECK(checker_iter == checker_.rend(),
123 "Checker iterator not at rend.");
124 } else {
125 CheckPairEquals(*tree_iter, *checker_iter);
126 }
127 return tree_iter;
128 }
value_check(const value_type & v)129 void value_check(const value_type &v) {
130 typename KeyOfValue<typename TreeType::key_type,
131 typename TreeType::value_type>::type key_of_value;
132 const key_type &key = key_of_value(v);
133 CheckPairEquals(*find(key), v);
134 lower_bound(key);
135 upper_bound(key);
136 equal_range(key);
137 contains(key);
138 count(key);
139 }
erase_check(const key_type & key)140 void erase_check(const key_type &key) {
141 EXPECT_FALSE(tree_.contains(key));
142 EXPECT_EQ(tree_.find(key), const_tree_.end());
143 EXPECT_FALSE(const_tree_.contains(key));
144 EXPECT_EQ(const_tree_.find(key), tree_.end());
145 EXPECT_EQ(tree_.equal_range(key).first,
146 const_tree_.equal_range(key).second);
147 }
148
lower_bound(const key_type & key)149 iterator lower_bound(const key_type &key) {
150 return iter_check(tree_.lower_bound(key), checker_.lower_bound(key));
151 }
lower_bound(const key_type & key) const152 const_iterator lower_bound(const key_type &key) const {
153 return iter_check(tree_.lower_bound(key), checker_.lower_bound(key));
154 }
upper_bound(const key_type & key)155 iterator upper_bound(const key_type &key) {
156 return iter_check(tree_.upper_bound(key), checker_.upper_bound(key));
157 }
upper_bound(const key_type & key) const158 const_iterator upper_bound(const key_type &key) const {
159 return iter_check(tree_.upper_bound(key), checker_.upper_bound(key));
160 }
equal_range(const key_type & key)161 std::pair<iterator, iterator> equal_range(const key_type &key) {
162 std::pair<typename CheckerType::iterator, typename CheckerType::iterator>
163 checker_res = checker_.equal_range(key);
164 std::pair<iterator, iterator> tree_res = tree_.equal_range(key);
165 iter_check(tree_res.first, checker_res.first);
166 iter_check(tree_res.second, checker_res.second);
167 return tree_res;
168 }
equal_range(const key_type & key) const169 std::pair<const_iterator, const_iterator> equal_range(
170 const key_type &key) const {
171 std::pair<typename CheckerType::const_iterator,
172 typename CheckerType::const_iterator>
173 checker_res = checker_.equal_range(key);
174 std::pair<const_iterator, const_iterator> tree_res = tree_.equal_range(key);
175 iter_check(tree_res.first, checker_res.first);
176 iter_check(tree_res.second, checker_res.second);
177 return tree_res;
178 }
find(const key_type & key)179 iterator find(const key_type &key) {
180 return iter_check(tree_.find(key), checker_.find(key));
181 }
find(const key_type & key) const182 const_iterator find(const key_type &key) const {
183 return iter_check(tree_.find(key), checker_.find(key));
184 }
contains(const key_type & key) const185 bool contains(const key_type &key) const { return find(key) != end(); }
count(const key_type & key) const186 size_type count(const key_type &key) const {
187 size_type res = checker_.count(key);
188 EXPECT_EQ(res, tree_.count(key));
189 return res;
190 }
191
operator =(const base_checker & other)192 base_checker &operator=(const base_checker &other) {
193 tree_ = other.tree_;
194 checker_ = other.checker_;
195 return *this;
196 }
197
erase(const key_type & key)198 int erase(const key_type &key) {
199 int size = tree_.size();
200 int res = checker_.erase(key);
201 EXPECT_EQ(res, tree_.count(key));
202 EXPECT_EQ(res, tree_.erase(key));
203 EXPECT_EQ(tree_.count(key), 0);
204 EXPECT_EQ(tree_.size(), size - res);
205 erase_check(key);
206 return res;
207 }
erase(iterator iter)208 iterator erase(iterator iter) {
209 key_type key = iter.key();
210 int size = tree_.size();
211 int count = tree_.count(key);
212 auto checker_iter = checker_.lower_bound(key);
213 for (iterator tmp(tree_.lower_bound(key)); tmp != iter; ++tmp) {
214 ++checker_iter;
215 }
216 auto checker_next = checker_iter;
217 ++checker_next;
218 checker_.erase(checker_iter);
219 iter = tree_.erase(iter);
220 EXPECT_EQ(tree_.size(), checker_.size());
221 EXPECT_EQ(tree_.size(), size - 1);
222 EXPECT_EQ(tree_.count(key), count - 1);
223 if (count == 1) {
224 erase_check(key);
225 }
226 return iter_check(iter, checker_next);
227 }
228
erase(iterator begin,iterator end)229 void erase(iterator begin, iterator end) {
230 int size = tree_.size();
231 int count = std::distance(begin, end);
232 auto checker_begin = checker_.lower_bound(begin.key());
233 for (iterator tmp(tree_.lower_bound(begin.key())); tmp != begin; ++tmp) {
234 ++checker_begin;
235 }
236 auto checker_end =
237 end == tree_.end() ? checker_.end() : checker_.lower_bound(end.key());
238 if (end != tree_.end()) {
239 for (iterator tmp(tree_.lower_bound(end.key())); tmp != end; ++tmp) {
240 ++checker_end;
241 }
242 }
243 const auto checker_ret = checker_.erase(checker_begin, checker_end);
244 const auto tree_ret = tree_.erase(begin, end);
245 EXPECT_EQ(std::distance(checker_.begin(), checker_ret),
246 std::distance(tree_.begin(), tree_ret));
247 EXPECT_EQ(tree_.size(), checker_.size());
248 EXPECT_EQ(tree_.size(), size - count);
249 }
250
clear()251 void clear() {
252 tree_.clear();
253 checker_.clear();
254 }
swap(base_checker & other)255 void swap(base_checker &other) {
256 tree_.swap(other.tree_);
257 checker_.swap(other.checker_);
258 }
259
verify() const260 void verify() const {
261 tree_.verify();
262 EXPECT_EQ(tree_.size(), checker_.size());
263
264 // Move through the forward iterators using increment.
265 auto checker_iter = checker_.begin();
266 const_iterator tree_iter(tree_.begin());
267 for (; tree_iter != tree_.end(); ++tree_iter, ++checker_iter) {
268 CheckPairEquals(*tree_iter, *checker_iter);
269 }
270
271 // Move through the forward iterators using decrement.
272 for (int n = tree_.size() - 1; n >= 0; --n) {
273 iter_check(tree_iter, checker_iter);
274 --tree_iter;
275 --checker_iter;
276 }
277 EXPECT_EQ(tree_iter, tree_.begin());
278 EXPECT_EQ(checker_iter, checker_.begin());
279
280 // Move through the reverse iterators using increment.
281 auto checker_riter = checker_.rbegin();
282 const_reverse_iterator tree_riter(tree_.rbegin());
283 for (; tree_riter != tree_.rend(); ++tree_riter, ++checker_riter) {
284 CheckPairEquals(*tree_riter, *checker_riter);
285 }
286
287 // Move through the reverse iterators using decrement.
288 for (int n = tree_.size() - 1; n >= 0; --n) {
289 riter_check(tree_riter, checker_riter);
290 --tree_riter;
291 --checker_riter;
292 }
293 EXPECT_EQ(tree_riter, tree_.rbegin());
294 EXPECT_EQ(checker_riter, checker_.rbegin());
295 }
296
tree() const297 const TreeType &tree() const { return tree_; }
298
size() const299 size_type size() const {
300 EXPECT_EQ(tree_.size(), checker_.size());
301 return tree_.size();
302 }
max_size() const303 size_type max_size() const { return tree_.max_size(); }
empty() const304 bool empty() const {
305 EXPECT_EQ(tree_.empty(), checker_.empty());
306 return tree_.empty();
307 }
308
309 protected:
310 TreeType tree_;
311 const TreeType &const_tree_;
312 CheckerType checker_;
313 };
314
315 namespace {
316 // A checker for unique sorted associative containers. TreeType is expected to
317 // be btree_{set,map} and CheckerType is expected to be {set,map}.
318 template <typename TreeType, typename CheckerType>
319 class unique_checker : public base_checker<TreeType, CheckerType> {
320 using super_type = base_checker<TreeType, CheckerType>;
321
322 public:
323 using iterator = typename super_type::iterator;
324 using value_type = typename super_type::value_type;
325
326 public:
unique_checker()327 unique_checker() : super_type() {}
unique_checker(const unique_checker & other)328 unique_checker(const unique_checker &other) : super_type(other) {}
329 template <class InputIterator>
unique_checker(InputIterator b,InputIterator e)330 unique_checker(InputIterator b, InputIterator e) : super_type(b, e) {}
331 unique_checker &operator=(const unique_checker &) = default;
332
333 // Insertion routines.
insert(const value_type & v)334 std::pair<iterator, bool> insert(const value_type &v) {
335 int size = this->tree_.size();
336 std::pair<typename CheckerType::iterator, bool> checker_res =
337 this->checker_.insert(v);
338 std::pair<iterator, bool> tree_res = this->tree_.insert(v);
339 CheckPairEquals(*tree_res.first, *checker_res.first);
340 EXPECT_EQ(tree_res.second, checker_res.second);
341 EXPECT_EQ(this->tree_.size(), this->checker_.size());
342 EXPECT_EQ(this->tree_.size(), size + tree_res.second);
343 return tree_res;
344 }
insert(iterator position,const value_type & v)345 iterator insert(iterator position, const value_type &v) {
346 int size = this->tree_.size();
347 std::pair<typename CheckerType::iterator, bool> checker_res =
348 this->checker_.insert(v);
349 iterator tree_res = this->tree_.insert(position, v);
350 CheckPairEquals(*tree_res, *checker_res.first);
351 EXPECT_EQ(this->tree_.size(), this->checker_.size());
352 EXPECT_EQ(this->tree_.size(), size + checker_res.second);
353 return tree_res;
354 }
355 template <typename InputIterator>
insert(InputIterator b,InputIterator e)356 void insert(InputIterator b, InputIterator e) {
357 for (; b != e; ++b) {
358 insert(*b);
359 }
360 }
361 };
362
363 // A checker for multiple sorted associative containers. TreeType is expected
364 // to be btree_{multiset,multimap} and CheckerType is expected to be
365 // {multiset,multimap}.
366 template <typename TreeType, typename CheckerType>
367 class multi_checker : public base_checker<TreeType, CheckerType> {
368 using super_type = base_checker<TreeType, CheckerType>;
369
370 public:
371 using iterator = typename super_type::iterator;
372 using value_type = typename super_type::value_type;
373
374 public:
multi_checker()375 multi_checker() : super_type() {}
multi_checker(const multi_checker & other)376 multi_checker(const multi_checker &other) : super_type(other) {}
377 template <class InputIterator>
multi_checker(InputIterator b,InputIterator e)378 multi_checker(InputIterator b, InputIterator e) : super_type(b, e) {}
379 multi_checker &operator=(const multi_checker &) = default;
380
381 // Insertion routines.
insert(const value_type & v)382 iterator insert(const value_type &v) {
383 int size = this->tree_.size();
384 auto checker_res = this->checker_.insert(v);
385 iterator tree_res = this->tree_.insert(v);
386 CheckPairEquals(*tree_res, *checker_res);
387 EXPECT_EQ(this->tree_.size(), this->checker_.size());
388 EXPECT_EQ(this->tree_.size(), size + 1);
389 return tree_res;
390 }
insert(iterator position,const value_type & v)391 iterator insert(iterator position, const value_type &v) {
392 int size = this->tree_.size();
393 auto checker_res = this->checker_.insert(v);
394 iterator tree_res = this->tree_.insert(position, v);
395 CheckPairEquals(*tree_res, *checker_res);
396 EXPECT_EQ(this->tree_.size(), this->checker_.size());
397 EXPECT_EQ(this->tree_.size(), size + 1);
398 return tree_res;
399 }
400 template <typename InputIterator>
insert(InputIterator b,InputIterator e)401 void insert(InputIterator b, InputIterator e) {
402 for (; b != e; ++b) {
403 insert(*b);
404 }
405 }
406 };
407
408 template <typename T, typename V>
DoTest(const char * name,T * b,const std::vector<V> & values)409 void DoTest(const char *name, T *b, const std::vector<V> &values) {
410 typename KeyOfValue<typename T::key_type, V>::type key_of_value;
411
412 T &mutable_b = *b;
413 const T &const_b = *b;
414
415 // Test insert.
416 for (int i = 0; i < values.size(); ++i) {
417 mutable_b.insert(values[i]);
418 mutable_b.value_check(values[i]);
419 }
420 ASSERT_EQ(mutable_b.size(), values.size());
421
422 const_b.verify();
423
424 // Test copy constructor.
425 T b_copy(const_b);
426 EXPECT_EQ(b_copy.size(), const_b.size());
427 for (int i = 0; i < values.size(); ++i) {
428 CheckPairEquals(*b_copy.find(key_of_value(values[i])), values[i]);
429 }
430
431 // Test range constructor.
432 T b_range(const_b.begin(), const_b.end());
433 EXPECT_EQ(b_range.size(), const_b.size());
434 for (int i = 0; i < values.size(); ++i) {
435 CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
436 }
437
438 // Test range insertion for values that already exist.
439 b_range.insert(b_copy.begin(), b_copy.end());
440 b_range.verify();
441
442 // Test range insertion for new values.
443 b_range.clear();
444 b_range.insert(b_copy.begin(), b_copy.end());
445 EXPECT_EQ(b_range.size(), b_copy.size());
446 for (int i = 0; i < values.size(); ++i) {
447 CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
448 }
449
450 // Test assignment to self. Nothing should change.
451 b_range.operator=(b_range);
452 EXPECT_EQ(b_range.size(), b_copy.size());
453
454 // Test assignment of new values.
455 b_range.clear();
456 b_range = b_copy;
457 EXPECT_EQ(b_range.size(), b_copy.size());
458
459 // Test swap.
460 b_range.clear();
461 b_range.swap(b_copy);
462 EXPECT_EQ(b_copy.size(), 0);
463 EXPECT_EQ(b_range.size(), const_b.size());
464 for (int i = 0; i < values.size(); ++i) {
465 CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
466 }
467 b_range.swap(b_copy);
468
469 // Test non-member function swap.
470 swap(b_range, b_copy);
471 EXPECT_EQ(b_copy.size(), 0);
472 EXPECT_EQ(b_range.size(), const_b.size());
473 for (int i = 0; i < values.size(); ++i) {
474 CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
475 }
476 swap(b_range, b_copy);
477
478 // Test erase via values.
479 for (int i = 0; i < values.size(); ++i) {
480 mutable_b.erase(key_of_value(values[i]));
481 // Erasing a non-existent key should have no effect.
482 ASSERT_EQ(mutable_b.erase(key_of_value(values[i])), 0);
483 }
484
485 const_b.verify();
486 EXPECT_EQ(const_b.size(), 0);
487
488 // Test erase via iterators.
489 mutable_b = b_copy;
490 for (int i = 0; i < values.size(); ++i) {
491 mutable_b.erase(mutable_b.find(key_of_value(values[i])));
492 }
493
494 const_b.verify();
495 EXPECT_EQ(const_b.size(), 0);
496
497 // Test insert with hint.
498 for (int i = 0; i < values.size(); i++) {
499 mutable_b.insert(mutable_b.upper_bound(key_of_value(values[i])), values[i]);
500 }
501
502 const_b.verify();
503
504 // Test range erase.
505 mutable_b.erase(mutable_b.begin(), mutable_b.end());
506 EXPECT_EQ(mutable_b.size(), 0);
507 const_b.verify();
508
509 // First half.
510 mutable_b = b_copy;
511 typename T::iterator mutable_iter_end = mutable_b.begin();
512 for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_end;
513 mutable_b.erase(mutable_b.begin(), mutable_iter_end);
514 EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 2);
515 const_b.verify();
516
517 // Second half.
518 mutable_b = b_copy;
519 typename T::iterator mutable_iter_begin = mutable_b.begin();
520 for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_begin;
521 mutable_b.erase(mutable_iter_begin, mutable_b.end());
522 EXPECT_EQ(mutable_b.size(), values.size() / 2);
523 const_b.verify();
524
525 // Second quarter.
526 mutable_b = b_copy;
527 mutable_iter_begin = mutable_b.begin();
528 for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_begin;
529 mutable_iter_end = mutable_iter_begin;
530 for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_end;
531 mutable_b.erase(mutable_iter_begin, mutable_iter_end);
532 EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 4);
533 const_b.verify();
534
535 mutable_b.clear();
536 }
537
538 template <typename T>
ConstTest()539 void ConstTest() {
540 using value_type = typename T::value_type;
541 typename KeyOfValue<typename T::key_type, value_type>::type key_of_value;
542
543 T mutable_b;
544 const T &const_b = mutable_b;
545
546 // Insert a single value into the container and test looking it up.
547 value_type value = Generator<value_type>(2)(2);
548 mutable_b.insert(value);
549 EXPECT_TRUE(mutable_b.contains(key_of_value(value)));
550 EXPECT_NE(mutable_b.find(key_of_value(value)), const_b.end());
551 EXPECT_TRUE(const_b.contains(key_of_value(value)));
552 EXPECT_NE(const_b.find(key_of_value(value)), mutable_b.end());
553 EXPECT_EQ(*const_b.lower_bound(key_of_value(value)), value);
554 EXPECT_EQ(const_b.upper_bound(key_of_value(value)), const_b.end());
555 EXPECT_EQ(*const_b.equal_range(key_of_value(value)).first, value);
556
557 // We can only create a non-const iterator from a non-const container.
558 typename T::iterator mutable_iter(mutable_b.begin());
559 EXPECT_EQ(mutable_iter, const_b.begin());
560 EXPECT_NE(mutable_iter, const_b.end());
561 EXPECT_EQ(const_b.begin(), mutable_iter);
562 EXPECT_NE(const_b.end(), mutable_iter);
563 typename T::reverse_iterator mutable_riter(mutable_b.rbegin());
564 EXPECT_EQ(mutable_riter, const_b.rbegin());
565 EXPECT_NE(mutable_riter, const_b.rend());
566 EXPECT_EQ(const_b.rbegin(), mutable_riter);
567 EXPECT_NE(const_b.rend(), mutable_riter);
568
569 // We can create a const iterator from a non-const iterator.
570 typename T::const_iterator const_iter(mutable_iter);
571 EXPECT_EQ(const_iter, mutable_b.begin());
572 EXPECT_NE(const_iter, mutable_b.end());
573 EXPECT_EQ(mutable_b.begin(), const_iter);
574 EXPECT_NE(mutable_b.end(), const_iter);
575 typename T::const_reverse_iterator const_riter(mutable_riter);
576 EXPECT_EQ(const_riter, mutable_b.rbegin());
577 EXPECT_NE(const_riter, mutable_b.rend());
578 EXPECT_EQ(mutable_b.rbegin(), const_riter);
579 EXPECT_NE(mutable_b.rend(), const_riter);
580
581 // Make sure various methods can be invoked on a const container.
582 const_b.verify();
583 ASSERT_TRUE(!const_b.empty());
584 EXPECT_EQ(const_b.size(), 1);
585 EXPECT_GT(const_b.max_size(), 0);
586 EXPECT_TRUE(const_b.contains(key_of_value(value)));
587 EXPECT_EQ(const_b.count(key_of_value(value)), 1);
588 }
589
590 template <typename T, typename C>
BtreeTest()591 void BtreeTest() {
592 ConstTest<T>();
593
594 using V = typename remove_pair_const<typename T::value_type>::type;
595 const std::vector<V> random_values = GenerateValuesWithSeed<V>(
596 absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values),
597 testing::GTEST_FLAG(random_seed));
598
599 unique_checker<T, C> container;
600
601 // Test key insertion/deletion in sorted order.
602 std::vector<V> sorted_values(random_values);
603 std::sort(sorted_values.begin(), sorted_values.end());
604 DoTest("sorted: ", &container, sorted_values);
605
606 // Test key insertion/deletion in reverse sorted order.
607 std::reverse(sorted_values.begin(), sorted_values.end());
608 DoTest("rsorted: ", &container, sorted_values);
609
610 // Test key insertion/deletion in random order.
611 DoTest("random: ", &container, random_values);
612 }
613
614 template <typename T, typename C>
BtreeMultiTest()615 void BtreeMultiTest() {
616 ConstTest<T>();
617
618 using V = typename remove_pair_const<typename T::value_type>::type;
619 const std::vector<V> random_values = GenerateValuesWithSeed<V>(
620 absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values),
621 testing::GTEST_FLAG(random_seed));
622
623 multi_checker<T, C> container;
624
625 // Test keys in sorted order.
626 std::vector<V> sorted_values(random_values);
627 std::sort(sorted_values.begin(), sorted_values.end());
628 DoTest("sorted: ", &container, sorted_values);
629
630 // Test keys in reverse sorted order.
631 std::reverse(sorted_values.begin(), sorted_values.end());
632 DoTest("rsorted: ", &container, sorted_values);
633
634 // Test keys in random order.
635 DoTest("random: ", &container, random_values);
636
637 // Test keys in random order w/ duplicates.
638 std::vector<V> duplicate_values(random_values);
639 duplicate_values.insert(duplicate_values.end(), random_values.begin(),
640 random_values.end());
641 DoTest("duplicates:", &container, duplicate_values);
642
643 // Test all identical keys.
644 std::vector<V> identical_values(100);
645 std::fill(identical_values.begin(), identical_values.end(),
646 Generator<V>(2)(2));
647 DoTest("identical: ", &container, identical_values);
648 }
649
650 template <typename T>
651 struct PropagatingCountingAlloc : public CountingAllocator<T> {
652 using propagate_on_container_copy_assignment = std::true_type;
653 using propagate_on_container_move_assignment = std::true_type;
654 using propagate_on_container_swap = std::true_type;
655
656 using Base = CountingAllocator<T>;
657 using Base::Base;
658
659 template <typename U>
PropagatingCountingAllocabsl::container_internal::__anonc80c217f0211::PropagatingCountingAlloc660 explicit PropagatingCountingAlloc(const PropagatingCountingAlloc<U> &other)
661 : Base(other.bytes_used_) {}
662
663 template <typename U>
664 struct rebind {
665 using other = PropagatingCountingAlloc<U>;
666 };
667 };
668
669 template <typename T>
BtreeAllocatorTest()670 void BtreeAllocatorTest() {
671 using value_type = typename T::value_type;
672
673 int64_t bytes1 = 0, bytes2 = 0;
674 PropagatingCountingAlloc<T> allocator1(&bytes1);
675 PropagatingCountingAlloc<T> allocator2(&bytes2);
676 Generator<value_type> generator(1000);
677
678 // Test that we allocate properly aligned memory. If we don't, then Layout
679 // will assert fail.
680 auto unused1 = allocator1.allocate(1);
681 auto unused2 = allocator2.allocate(1);
682
683 // Test copy assignment
684 {
685 T b1(typename T::key_compare(), allocator1);
686 T b2(typename T::key_compare(), allocator2);
687
688 int64_t original_bytes1 = bytes1;
689 b1.insert(generator(0));
690 EXPECT_GT(bytes1, original_bytes1);
691
692 // This should propagate the allocator.
693 b1 = b2;
694 EXPECT_EQ(b1.size(), 0);
695 EXPECT_EQ(b2.size(), 0);
696 EXPECT_EQ(bytes1, original_bytes1);
697
698 for (int i = 1; i < 1000; i++) {
699 b1.insert(generator(i));
700 }
701
702 // We should have allocated out of allocator2.
703 EXPECT_GT(bytes2, bytes1);
704 }
705
706 // Test move assignment
707 {
708 T b1(typename T::key_compare(), allocator1);
709 T b2(typename T::key_compare(), allocator2);
710
711 int64_t original_bytes1 = bytes1;
712 b1.insert(generator(0));
713 EXPECT_GT(bytes1, original_bytes1);
714
715 // This should propagate the allocator.
716 b1 = std::move(b2);
717 EXPECT_EQ(b1.size(), 0);
718 EXPECT_EQ(bytes1, original_bytes1);
719
720 for (int i = 1; i < 1000; i++) {
721 b1.insert(generator(i));
722 }
723
724 // We should have allocated out of allocator2.
725 EXPECT_GT(bytes2, bytes1);
726 }
727
728 // Test swap
729 {
730 T b1(typename T::key_compare(), allocator1);
731 T b2(typename T::key_compare(), allocator2);
732
733 int64_t original_bytes1 = bytes1;
734 b1.insert(generator(0));
735 EXPECT_GT(bytes1, original_bytes1);
736
737 // This should swap the allocators.
738 swap(b1, b2);
739 EXPECT_EQ(b1.size(), 0);
740 EXPECT_EQ(b2.size(), 1);
741 EXPECT_GT(bytes1, original_bytes1);
742
743 for (int i = 1; i < 1000; i++) {
744 b1.insert(generator(i));
745 }
746
747 // We should have allocated out of allocator2.
748 EXPECT_GT(bytes2, bytes1);
749 }
750
751 allocator1.deallocate(unused1, 1);
752 allocator2.deallocate(unused2, 1);
753 }
754
755 template <typename T>
BtreeMapTest()756 void BtreeMapTest() {
757 using value_type = typename T::value_type;
758 using mapped_type = typename T::mapped_type;
759
760 mapped_type m = Generator<mapped_type>(0)(0);
761 (void)m;
762
763 T b;
764
765 // Verify we can insert using operator[].
766 for (int i = 0; i < 1000; i++) {
767 value_type v = Generator<value_type>(1000)(i);
768 b[v.first] = v.second;
769 }
770 EXPECT_EQ(b.size(), 1000);
771
772 // Test whether we can use the "->" operator on iterators and
773 // reverse_iterators. This stresses the btree_map_params::pair_pointer
774 // mechanism.
775 EXPECT_EQ(b.begin()->first, Generator<value_type>(1000)(0).first);
776 EXPECT_EQ(b.begin()->second, Generator<value_type>(1000)(0).second);
777 EXPECT_EQ(b.rbegin()->first, Generator<value_type>(1000)(999).first);
778 EXPECT_EQ(b.rbegin()->second, Generator<value_type>(1000)(999).second);
779 }
780
781 template <typename T>
BtreeMultiMapTest()782 void BtreeMultiMapTest() {
783 using mapped_type = typename T::mapped_type;
784 mapped_type m = Generator<mapped_type>(0)(0);
785 (void)m;
786 }
787
788 template <typename K, int N = 256>
SetTest()789 void SetTest() {
790 EXPECT_EQ(
791 sizeof(absl::btree_set<K>),
792 2 * sizeof(void *) + sizeof(typename absl::btree_set<K>::size_type));
793 using BtreeSet = absl::btree_set<K>;
794 using CountingBtreeSet =
795 absl::btree_set<K, std::less<K>, PropagatingCountingAlloc<K>>;
796 BtreeTest<BtreeSet, std::set<K>>();
797 BtreeAllocatorTest<CountingBtreeSet>();
798 }
799
800 template <typename K, int N = 256>
MapTest()801 void MapTest() {
802 EXPECT_EQ(
803 sizeof(absl::btree_map<K, K>),
804 2 * sizeof(void *) + sizeof(typename absl::btree_map<K, K>::size_type));
805 using BtreeMap = absl::btree_map<K, K>;
806 using CountingBtreeMap =
807 absl::btree_map<K, K, std::less<K>,
808 PropagatingCountingAlloc<std::pair<const K, K>>>;
809 BtreeTest<BtreeMap, std::map<K, K>>();
810 BtreeAllocatorTest<CountingBtreeMap>();
811 BtreeMapTest<BtreeMap>();
812 }
813
TEST(Btree,set_int32)814 TEST(Btree, set_int32) { SetTest<int32_t>(); }
TEST(Btree,set_int64)815 TEST(Btree, set_int64) { SetTest<int64_t>(); }
TEST(Btree,set_string)816 TEST(Btree, set_string) { SetTest<std::string>(); }
TEST(Btree,set_cord)817 TEST(Btree, set_cord) { SetTest<absl::Cord>(); }
TEST(Btree,set_pair)818 TEST(Btree, set_pair) { SetTest<std::pair<int, int>>(); }
TEST(Btree,map_int32)819 TEST(Btree, map_int32) { MapTest<int32_t>(); }
TEST(Btree,map_int64)820 TEST(Btree, map_int64) { MapTest<int64_t>(); }
TEST(Btree,map_string)821 TEST(Btree, map_string) { MapTest<std::string>(); }
TEST(Btree,map_cord)822 TEST(Btree, map_cord) { MapTest<absl::Cord>(); }
TEST(Btree,map_pair)823 TEST(Btree, map_pair) { MapTest<std::pair<int, int>>(); }
824
825 template <typename K, int N = 256>
MultiSetTest()826 void MultiSetTest() {
827 EXPECT_EQ(
828 sizeof(absl::btree_multiset<K>),
829 2 * sizeof(void *) + sizeof(typename absl::btree_multiset<K>::size_type));
830 using BtreeMSet = absl::btree_multiset<K>;
831 using CountingBtreeMSet =
832 absl::btree_multiset<K, std::less<K>, PropagatingCountingAlloc<K>>;
833 BtreeMultiTest<BtreeMSet, std::multiset<K>>();
834 BtreeAllocatorTest<CountingBtreeMSet>();
835 }
836
837 template <typename K, int N = 256>
MultiMapTest()838 void MultiMapTest() {
839 EXPECT_EQ(sizeof(absl::btree_multimap<K, K>),
840 2 * sizeof(void *) +
841 sizeof(typename absl::btree_multimap<K, K>::size_type));
842 using BtreeMMap = absl::btree_multimap<K, K>;
843 using CountingBtreeMMap =
844 absl::btree_multimap<K, K, std::less<K>,
845 PropagatingCountingAlloc<std::pair<const K, K>>>;
846 BtreeMultiTest<BtreeMMap, std::multimap<K, K>>();
847 BtreeMultiMapTest<BtreeMMap>();
848 BtreeAllocatorTest<CountingBtreeMMap>();
849 }
850
TEST(Btree,multiset_int32)851 TEST(Btree, multiset_int32) { MultiSetTest<int32_t>(); }
TEST(Btree,multiset_int64)852 TEST(Btree, multiset_int64) { MultiSetTest<int64_t>(); }
TEST(Btree,multiset_string)853 TEST(Btree, multiset_string) { MultiSetTest<std::string>(); }
TEST(Btree,multiset_cord)854 TEST(Btree, multiset_cord) { MultiSetTest<absl::Cord>(); }
TEST(Btree,multiset_pair)855 TEST(Btree, multiset_pair) { MultiSetTest<std::pair<int, int>>(); }
TEST(Btree,multimap_int32)856 TEST(Btree, multimap_int32) { MultiMapTest<int32_t>(); }
TEST(Btree,multimap_int64)857 TEST(Btree, multimap_int64) { MultiMapTest<int64_t>(); }
TEST(Btree,multimap_string)858 TEST(Btree, multimap_string) { MultiMapTest<std::string>(); }
TEST(Btree,multimap_cord)859 TEST(Btree, multimap_cord) { MultiMapTest<absl::Cord>(); }
TEST(Btree,multimap_pair)860 TEST(Btree, multimap_pair) { MultiMapTest<std::pair<int, int>>(); }
861
862 struct CompareIntToString {
operator ()absl::container_internal::__anonc80c217f0211::CompareIntToString863 bool operator()(const std::string &a, const std::string &b) const {
864 return a < b;
865 }
operator ()absl::container_internal::__anonc80c217f0211::CompareIntToString866 bool operator()(const std::string &a, int b) const {
867 return a < absl::StrCat(b);
868 }
operator ()absl::container_internal::__anonc80c217f0211::CompareIntToString869 bool operator()(int a, const std::string &b) const {
870 return absl::StrCat(a) < b;
871 }
872 using is_transparent = void;
873 };
874
875 struct NonTransparentCompare {
876 template <typename T, typename U>
operator ()absl::container_internal::__anonc80c217f0211::NonTransparentCompare877 bool operator()(const T &t, const U &u) const {
878 // Treating all comparators as transparent can cause inefficiencies (see
879 // N3657 C++ proposal). Test that for comparators without 'is_transparent'
880 // alias (like this one), we do not attempt heterogeneous lookup.
881 EXPECT_TRUE((std::is_same<T, U>()));
882 return t < u;
883 }
884 };
885
886 template <typename T>
887 bool CanEraseWithEmptyBrace(T t, decltype(t.erase({})) *) {
888 return true;
889 }
890
891 template <typename T>
CanEraseWithEmptyBrace(T,...)892 bool CanEraseWithEmptyBrace(T, ...) {
893 return false;
894 }
895
896 template <typename T>
TestHeterogeneous(T table)897 void TestHeterogeneous(T table) {
898 auto lb = table.lower_bound("3");
899 EXPECT_EQ(lb, table.lower_bound(3));
900 EXPECT_NE(lb, table.lower_bound(4));
901 EXPECT_EQ(lb, table.lower_bound({"3"}));
902 EXPECT_NE(lb, table.lower_bound({}));
903
904 auto ub = table.upper_bound("3");
905 EXPECT_EQ(ub, table.upper_bound(3));
906 EXPECT_NE(ub, table.upper_bound(5));
907 EXPECT_EQ(ub, table.upper_bound({"3"}));
908 EXPECT_NE(ub, table.upper_bound({}));
909
910 auto er = table.equal_range("3");
911 EXPECT_EQ(er, table.equal_range(3));
912 EXPECT_NE(er, table.equal_range(4));
913 EXPECT_EQ(er, table.equal_range({"3"}));
914 EXPECT_NE(er, table.equal_range({}));
915
916 auto it = table.find("3");
917 EXPECT_EQ(it, table.find(3));
918 EXPECT_NE(it, table.find(4));
919 EXPECT_EQ(it, table.find({"3"}));
920 EXPECT_NE(it, table.find({}));
921
922 EXPECT_TRUE(table.contains(3));
923 EXPECT_FALSE(table.contains(4));
924 EXPECT_TRUE(table.count({"3"}));
925 EXPECT_FALSE(table.contains({}));
926
927 EXPECT_EQ(1, table.count(3));
928 EXPECT_EQ(0, table.count(4));
929 EXPECT_EQ(1, table.count({"3"}));
930 EXPECT_EQ(0, table.count({}));
931
932 auto copy = table;
933 copy.erase(3);
934 EXPECT_EQ(table.size() - 1, copy.size());
935 copy.erase(4);
936 EXPECT_EQ(table.size() - 1, copy.size());
937 copy.erase({"5"});
938 EXPECT_EQ(table.size() - 2, copy.size());
939 EXPECT_FALSE(CanEraseWithEmptyBrace(table, nullptr));
940
941 // Also run it with const T&.
942 if (std::is_class<T>()) TestHeterogeneous<const T &>(table);
943 }
944
TEST(Btree,HeterogeneousLookup)945 TEST(Btree, HeterogeneousLookup) {
946 TestHeterogeneous(btree_set<std::string, CompareIntToString>{"1", "3", "5"});
947 TestHeterogeneous(btree_map<std::string, int, CompareIntToString>{
948 {"1", 1}, {"3", 3}, {"5", 5}});
949 TestHeterogeneous(
950 btree_multiset<std::string, CompareIntToString>{"1", "3", "5"});
951 TestHeterogeneous(btree_multimap<std::string, int, CompareIntToString>{
952 {"1", 1}, {"3", 3}, {"5", 5}});
953
954 // Only maps have .at()
955 btree_map<std::string, int, CompareIntToString> map{
956 {"", -1}, {"1", 1}, {"3", 3}, {"5", 5}};
957 EXPECT_EQ(1, map.at(1));
958 EXPECT_EQ(3, map.at({"3"}));
959 EXPECT_EQ(-1, map.at({}));
960 const auto &cmap = map;
961 EXPECT_EQ(1, cmap.at(1));
962 EXPECT_EQ(3, cmap.at({"3"}));
963 EXPECT_EQ(-1, cmap.at({}));
964 }
965
TEST(Btree,NoHeterogeneousLookupWithoutAlias)966 TEST(Btree, NoHeterogeneousLookupWithoutAlias) {
967 using StringSet = absl::btree_set<std::string, NonTransparentCompare>;
968 StringSet s;
969 ASSERT_TRUE(s.insert("hello").second);
970 ASSERT_TRUE(s.insert("world").second);
971 EXPECT_TRUE(s.end() == s.find("blah"));
972 EXPECT_TRUE(s.begin() == s.lower_bound("hello"));
973 EXPECT_EQ(1, s.count("world"));
974 EXPECT_TRUE(s.contains("hello"));
975 EXPECT_TRUE(s.contains("world"));
976 EXPECT_FALSE(s.contains("blah"));
977
978 using StringMultiSet =
979 absl::btree_multiset<std::string, NonTransparentCompare>;
980 StringMultiSet ms;
981 ms.insert("hello");
982 ms.insert("world");
983 ms.insert("world");
984 EXPECT_TRUE(ms.end() == ms.find("blah"));
985 EXPECT_TRUE(ms.begin() == ms.lower_bound("hello"));
986 EXPECT_EQ(2, ms.count("world"));
987 EXPECT_TRUE(ms.contains("hello"));
988 EXPECT_TRUE(ms.contains("world"));
989 EXPECT_FALSE(ms.contains("blah"));
990 }
991
TEST(Btree,DefaultTransparent)992 TEST(Btree, DefaultTransparent) {
993 {
994 // `int` does not have a default transparent comparator.
995 // The input value is converted to key_type.
996 btree_set<int> s = {1};
997 double d = 1.1;
998 EXPECT_EQ(s.begin(), s.find(d));
999 EXPECT_TRUE(s.contains(d));
1000 }
1001
1002 {
1003 // `std::string` has heterogeneous support.
1004 btree_set<std::string> s = {"A"};
1005 EXPECT_EQ(s.begin(), s.find(absl::string_view("A")));
1006 EXPECT_TRUE(s.contains(absl::string_view("A")));
1007 }
1008 }
1009
1010 class StringLike {
1011 public:
1012 StringLike() = default;
1013
StringLike(const char * s)1014 StringLike(const char *s) : s_(s) { // NOLINT
1015 ++constructor_calls_;
1016 }
1017
operator <(const StringLike & a) const1018 bool operator<(const StringLike &a) const { return s_ < a.s_; }
1019
clear_constructor_call_count()1020 static void clear_constructor_call_count() { constructor_calls_ = 0; }
1021
constructor_calls()1022 static int constructor_calls() { return constructor_calls_; }
1023
1024 private:
1025 static int constructor_calls_;
1026 std::string s_;
1027 };
1028
1029 int StringLike::constructor_calls_ = 0;
1030
TEST(Btree,HeterogeneousLookupDoesntDegradePerformance)1031 TEST(Btree, HeterogeneousLookupDoesntDegradePerformance) {
1032 using StringSet = absl::btree_set<StringLike>;
1033 StringSet s;
1034 for (int i = 0; i < 100; ++i) {
1035 ASSERT_TRUE(s.insert(absl::StrCat(i).c_str()).second);
1036 }
1037 StringLike::clear_constructor_call_count();
1038 s.find("50");
1039 ASSERT_EQ(1, StringLike::constructor_calls());
1040
1041 StringLike::clear_constructor_call_count();
1042 s.contains("50");
1043 ASSERT_EQ(1, StringLike::constructor_calls());
1044
1045 StringLike::clear_constructor_call_count();
1046 s.count("50");
1047 ASSERT_EQ(1, StringLike::constructor_calls());
1048
1049 StringLike::clear_constructor_call_count();
1050 s.lower_bound("50");
1051 ASSERT_EQ(1, StringLike::constructor_calls());
1052
1053 StringLike::clear_constructor_call_count();
1054 s.upper_bound("50");
1055 ASSERT_EQ(1, StringLike::constructor_calls());
1056
1057 StringLike::clear_constructor_call_count();
1058 s.equal_range("50");
1059 ASSERT_EQ(1, StringLike::constructor_calls());
1060
1061 StringLike::clear_constructor_call_count();
1062 s.erase("50");
1063 ASSERT_EQ(1, StringLike::constructor_calls());
1064 }
1065
1066 // Verify that swapping btrees swaps the key comparison functors and that we can
1067 // use non-default constructible comparators.
1068 struct SubstringLess {
1069 SubstringLess() = delete;
SubstringLessabsl::container_internal::__anonc80c217f0211::SubstringLess1070 explicit SubstringLess(int length) : n(length) {}
operator ()absl::container_internal::__anonc80c217f0211::SubstringLess1071 bool operator()(const std::string &a, const std::string &b) const {
1072 return absl::string_view(a).substr(0, n) <
1073 absl::string_view(b).substr(0, n);
1074 }
1075 int n;
1076 };
1077
TEST(Btree,SwapKeyCompare)1078 TEST(Btree, SwapKeyCompare) {
1079 using SubstringSet = absl::btree_set<std::string, SubstringLess>;
1080 SubstringSet s1(SubstringLess(1), SubstringSet::allocator_type());
1081 SubstringSet s2(SubstringLess(2), SubstringSet::allocator_type());
1082
1083 ASSERT_TRUE(s1.insert("a").second);
1084 ASSERT_FALSE(s1.insert("aa").second);
1085
1086 ASSERT_TRUE(s2.insert("a").second);
1087 ASSERT_TRUE(s2.insert("aa").second);
1088 ASSERT_FALSE(s2.insert("aaa").second);
1089
1090 swap(s1, s2);
1091
1092 ASSERT_TRUE(s1.insert("b").second);
1093 ASSERT_TRUE(s1.insert("bb").second);
1094 ASSERT_FALSE(s1.insert("bbb").second);
1095
1096 ASSERT_TRUE(s2.insert("b").second);
1097 ASSERT_FALSE(s2.insert("bb").second);
1098 }
1099
TEST(Btree,UpperBoundRegression)1100 TEST(Btree, UpperBoundRegression) {
1101 // Regress a bug where upper_bound would default-construct a new key_compare
1102 // instead of copying the existing one.
1103 using SubstringSet = absl::btree_set<std::string, SubstringLess>;
1104 SubstringSet my_set(SubstringLess(3));
1105 my_set.insert("aab");
1106 my_set.insert("abb");
1107 // We call upper_bound("aaa"). If this correctly uses the length 3
1108 // comparator, aaa < aab < abb, so we should get aab as the result.
1109 // If it instead uses the default-constructed length 2 comparator,
1110 // aa == aa < ab, so we'll get abb as our result.
1111 SubstringSet::iterator it = my_set.upper_bound("aaa");
1112 ASSERT_TRUE(it != my_set.end());
1113 EXPECT_EQ("aab", *it);
1114 }
1115
TEST(Btree,Comparison)1116 TEST(Btree, Comparison) {
1117 const int kSetSize = 1201;
1118 absl::btree_set<int64_t> my_set;
1119 for (int i = 0; i < kSetSize; ++i) {
1120 my_set.insert(i);
1121 }
1122 absl::btree_set<int64_t> my_set_copy(my_set);
1123 EXPECT_TRUE(my_set_copy == my_set);
1124 EXPECT_TRUE(my_set == my_set_copy);
1125 EXPECT_FALSE(my_set_copy != my_set);
1126 EXPECT_FALSE(my_set != my_set_copy);
1127
1128 my_set.insert(kSetSize);
1129 EXPECT_FALSE(my_set_copy == my_set);
1130 EXPECT_FALSE(my_set == my_set_copy);
1131 EXPECT_TRUE(my_set_copy != my_set);
1132 EXPECT_TRUE(my_set != my_set_copy);
1133
1134 my_set.erase(kSetSize - 1);
1135 EXPECT_FALSE(my_set_copy == my_set);
1136 EXPECT_FALSE(my_set == my_set_copy);
1137 EXPECT_TRUE(my_set_copy != my_set);
1138 EXPECT_TRUE(my_set != my_set_copy);
1139
1140 absl::btree_map<std::string, int64_t> my_map;
1141 for (int i = 0; i < kSetSize; ++i) {
1142 my_map[std::string(i, 'a')] = i;
1143 }
1144 absl::btree_map<std::string, int64_t> my_map_copy(my_map);
1145 EXPECT_TRUE(my_map_copy == my_map);
1146 EXPECT_TRUE(my_map == my_map_copy);
1147 EXPECT_FALSE(my_map_copy != my_map);
1148 EXPECT_FALSE(my_map != my_map_copy);
1149
1150 ++my_map_copy[std::string(7, 'a')];
1151 EXPECT_FALSE(my_map_copy == my_map);
1152 EXPECT_FALSE(my_map == my_map_copy);
1153 EXPECT_TRUE(my_map_copy != my_map);
1154 EXPECT_TRUE(my_map != my_map_copy);
1155
1156 my_map_copy = my_map;
1157 my_map["hello"] = kSetSize;
1158 EXPECT_FALSE(my_map_copy == my_map);
1159 EXPECT_FALSE(my_map == my_map_copy);
1160 EXPECT_TRUE(my_map_copy != my_map);
1161 EXPECT_TRUE(my_map != my_map_copy);
1162
1163 my_map.erase(std::string(kSetSize - 1, 'a'));
1164 EXPECT_FALSE(my_map_copy == my_map);
1165 EXPECT_FALSE(my_map == my_map_copy);
1166 EXPECT_TRUE(my_map_copy != my_map);
1167 EXPECT_TRUE(my_map != my_map_copy);
1168 }
1169
TEST(Btree,RangeCtorSanity)1170 TEST(Btree, RangeCtorSanity) {
1171 std::vector<int> ivec;
1172 ivec.push_back(1);
1173 std::map<int, int> imap;
1174 imap.insert(std::make_pair(1, 2));
1175 absl::btree_multiset<int> tmset(ivec.begin(), ivec.end());
1176 absl::btree_multimap<int, int> tmmap(imap.begin(), imap.end());
1177 absl::btree_set<int> tset(ivec.begin(), ivec.end());
1178 absl::btree_map<int, int> tmap(imap.begin(), imap.end());
1179 EXPECT_EQ(1, tmset.size());
1180 EXPECT_EQ(1, tmmap.size());
1181 EXPECT_EQ(1, tset.size());
1182 EXPECT_EQ(1, tmap.size());
1183 }
1184
TEST(Btree,BtreeMapCanHoldMoveOnlyTypes)1185 TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) {
1186 absl::btree_map<std::string, std::unique_ptr<std::string>> m;
1187
1188 std::unique_ptr<std::string> &v = m["A"];
1189 EXPECT_TRUE(v == nullptr);
1190 v.reset(new std::string("X"));
1191
1192 auto iter = m.find("A");
1193 EXPECT_EQ("X", *iter->second);
1194 }
1195
TEST(Btree,InitializerListConstructor)1196 TEST(Btree, InitializerListConstructor) {
1197 absl::btree_set<std::string> set({"a", "b"});
1198 EXPECT_EQ(set.count("a"), 1);
1199 EXPECT_EQ(set.count("b"), 1);
1200
1201 absl::btree_multiset<int> mset({1, 1, 4});
1202 EXPECT_EQ(mset.count(1), 2);
1203 EXPECT_EQ(mset.count(4), 1);
1204
1205 absl::btree_map<int, int> map({{1, 5}, {2, 10}});
1206 EXPECT_EQ(map[1], 5);
1207 EXPECT_EQ(map[2], 10);
1208
1209 absl::btree_multimap<int, int> mmap({{1, 5}, {1, 10}});
1210 auto range = mmap.equal_range(1);
1211 auto it = range.first;
1212 ASSERT_NE(it, range.second);
1213 EXPECT_EQ(it->second, 5);
1214 ASSERT_NE(++it, range.second);
1215 EXPECT_EQ(it->second, 10);
1216 EXPECT_EQ(++it, range.second);
1217 }
1218
TEST(Btree,InitializerListInsert)1219 TEST(Btree, InitializerListInsert) {
1220 absl::btree_set<std::string> set;
1221 set.insert({"a", "b"});
1222 EXPECT_EQ(set.count("a"), 1);
1223 EXPECT_EQ(set.count("b"), 1);
1224
1225 absl::btree_multiset<int> mset;
1226 mset.insert({1, 1, 4});
1227 EXPECT_EQ(mset.count(1), 2);
1228 EXPECT_EQ(mset.count(4), 1);
1229
1230 absl::btree_map<int, int> map;
1231 map.insert({{1, 5}, {2, 10}});
1232 // Test that inserting one element using an initializer list also works.
1233 map.insert({3, 15});
1234 EXPECT_EQ(map[1], 5);
1235 EXPECT_EQ(map[2], 10);
1236 EXPECT_EQ(map[3], 15);
1237
1238 absl::btree_multimap<int, int> mmap;
1239 mmap.insert({{1, 5}, {1, 10}});
1240 auto range = mmap.equal_range(1);
1241 auto it = range.first;
1242 ASSERT_NE(it, range.second);
1243 EXPECT_EQ(it->second, 5);
1244 ASSERT_NE(++it, range.second);
1245 EXPECT_EQ(it->second, 10);
1246 EXPECT_EQ(++it, range.second);
1247 }
1248
1249 template <typename Compare, typename K>
AssertKeyCompareToAdapted()1250 void AssertKeyCompareToAdapted() {
1251 using Adapted = typename key_compare_to_adapter<Compare>::type;
1252 static_assert(!std::is_same<Adapted, Compare>::value,
1253 "key_compare_to_adapter should have adapted this comparator.");
1254 static_assert(
1255 std::is_same<absl::weak_ordering,
1256 absl::result_of_t<Adapted(const K &, const K &)>>::value,
1257 "Adapted comparator should be a key-compare-to comparator.");
1258 }
1259 template <typename Compare, typename K>
AssertKeyCompareToNotAdapted()1260 void AssertKeyCompareToNotAdapted() {
1261 using Unadapted = typename key_compare_to_adapter<Compare>::type;
1262 static_assert(
1263 std::is_same<Unadapted, Compare>::value,
1264 "key_compare_to_adapter shouldn't have adapted this comparator.");
1265 static_assert(
1266 std::is_same<bool,
1267 absl::result_of_t<Unadapted(const K &, const K &)>>::value,
1268 "Un-adapted comparator should return bool.");
1269 }
1270
TEST(Btree,KeyCompareToAdapter)1271 TEST(Btree, KeyCompareToAdapter) {
1272 AssertKeyCompareToAdapted<std::less<std::string>, std::string>();
1273 AssertKeyCompareToAdapted<std::greater<std::string>, std::string>();
1274 AssertKeyCompareToAdapted<std::less<absl::string_view>, absl::string_view>();
1275 AssertKeyCompareToAdapted<std::greater<absl::string_view>,
1276 absl::string_view>();
1277 AssertKeyCompareToAdapted<std::less<absl::Cord>, absl::Cord>();
1278 AssertKeyCompareToAdapted<std::greater<absl::Cord>, absl::Cord>();
1279 AssertKeyCompareToNotAdapted<std::less<int>, int>();
1280 AssertKeyCompareToNotAdapted<std::greater<int>, int>();
1281 }
1282
TEST(Btree,RValueInsert)1283 TEST(Btree, RValueInsert) {
1284 InstanceTracker tracker;
1285
1286 absl::btree_set<MovableOnlyInstance> set;
1287 set.insert(MovableOnlyInstance(1));
1288 set.insert(MovableOnlyInstance(3));
1289 MovableOnlyInstance two(2);
1290 set.insert(set.find(MovableOnlyInstance(3)), std::move(two));
1291 auto it = set.find(MovableOnlyInstance(2));
1292 ASSERT_NE(it, set.end());
1293 ASSERT_NE(++it, set.end());
1294 EXPECT_EQ(it->value(), 3);
1295
1296 absl::btree_multiset<MovableOnlyInstance> mset;
1297 MovableOnlyInstance zero(0);
1298 MovableOnlyInstance zero2(0);
1299 mset.insert(std::move(zero));
1300 mset.insert(mset.find(MovableOnlyInstance(0)), std::move(zero2));
1301 EXPECT_EQ(mset.count(MovableOnlyInstance(0)), 2);
1302
1303 absl::btree_map<int, MovableOnlyInstance> map;
1304 std::pair<const int, MovableOnlyInstance> p1 = {1, MovableOnlyInstance(5)};
1305 std::pair<const int, MovableOnlyInstance> p2 = {2, MovableOnlyInstance(10)};
1306 std::pair<const int, MovableOnlyInstance> p3 = {3, MovableOnlyInstance(15)};
1307 map.insert(std::move(p1));
1308 map.insert(std::move(p3));
1309 map.insert(map.find(3), std::move(p2));
1310 ASSERT_NE(map.find(2), map.end());
1311 EXPECT_EQ(map.find(2)->second.value(), 10);
1312
1313 absl::btree_multimap<int, MovableOnlyInstance> mmap;
1314 std::pair<const int, MovableOnlyInstance> p4 = {1, MovableOnlyInstance(5)};
1315 std::pair<const int, MovableOnlyInstance> p5 = {1, MovableOnlyInstance(10)};
1316 mmap.insert(std::move(p4));
1317 mmap.insert(mmap.find(1), std::move(p5));
1318 auto range = mmap.equal_range(1);
1319 auto it1 = range.first;
1320 ASSERT_NE(it1, range.second);
1321 EXPECT_EQ(it1->second.value(), 10);
1322 ASSERT_NE(++it1, range.second);
1323 EXPECT_EQ(it1->second.value(), 5);
1324 EXPECT_EQ(++it1, range.second);
1325
1326 EXPECT_EQ(tracker.copies(), 0);
1327 EXPECT_EQ(tracker.swaps(), 0);
1328 }
1329
1330 } // namespace
1331
1332 class BtreeNodePeer {
1333 public:
1334 // Yields the size of a leaf node with a specific number of values.
1335 template <typename ValueType>
GetTargetNodeSize(size_t target_values_per_node)1336 constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
1337 return btree_node<
1338 set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
1339 /*TargetNodeSize=*/256, // This parameter isn't used here.
1340 /*Multi=*/false>>::SizeWithNValues(target_values_per_node);
1341 }
1342
1343 // Yields the number of values in a (non-root) leaf node for this set.
1344 template <typename Set>
GetNumValuesPerNode()1345 constexpr static size_t GetNumValuesPerNode() {
1346 return btree_node<typename Set::params_type>::kNodeValues;
1347 }
1348
1349 template <typename Set>
GetMaxFieldType()1350 constexpr static size_t GetMaxFieldType() {
1351 return std::numeric_limits<
1352 typename btree_node<typename Set::params_type>::field_type>::max();
1353 }
1354 };
1355
1356 namespace {
1357
1358 // A btree set with a specific number of values per node.
1359 template <typename Key, int TargetValuesPerNode, typename Cmp = std::less<Key>>
1360 class SizedBtreeSet
1361 : public btree_set_container<btree<
1362 set_params<Key, Cmp, std::allocator<Key>,
1363 BtreeNodePeer::GetTargetNodeSize<Key>(TargetValuesPerNode),
1364 /*Multi=*/false>>> {
1365 using Base = typename SizedBtreeSet::btree_set_container;
1366
1367 public:
SizedBtreeSet()1368 SizedBtreeSet() {}
1369 using Base::Base;
1370 };
1371
1372 template <typename Set>
ExpectOperationCounts(const int expected_moves,const int expected_comparisons,const std::vector<int> & values,InstanceTracker * tracker,Set * set)1373 void ExpectOperationCounts(const int expected_moves,
1374 const int expected_comparisons,
1375 const std::vector<int> &values,
1376 InstanceTracker *tracker, Set *set) {
1377 for (const int v : values) set->insert(MovableOnlyInstance(v));
1378 set->clear();
1379 EXPECT_EQ(tracker->moves(), expected_moves);
1380 EXPECT_EQ(tracker->comparisons(), expected_comparisons);
1381 EXPECT_EQ(tracker->copies(), 0);
1382 EXPECT_EQ(tracker->swaps(), 0);
1383 tracker->ResetCopiesMovesSwaps();
1384 }
1385
1386 // Note: when the values in this test change, it is expected to have an impact
1387 // on performance.
TEST(Btree,MovesComparisonsCopiesSwapsTracking)1388 TEST(Btree, MovesComparisonsCopiesSwapsTracking) {
1389 InstanceTracker tracker;
1390 // Note: this is minimum number of values per node.
1391 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/3> set3;
1392 // Note: this is the default number of values per node for a set of int32s
1393 // (with 64-bit pointers).
1394 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61> set61;
1395 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/100> set100;
1396
1397 // Don't depend on flags for random values because then the expectations will
1398 // fail if the flags change.
1399 std::vector<int> values =
1400 GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23);
1401
1402 EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set3)>(), 3);
1403 EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>(), 61);
1404 EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set100)>(), 100);
1405 if (sizeof(void *) == 8) {
1406 EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<absl::btree_set<int32_t>>(),
1407 BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>());
1408 }
1409
1410 // Test key insertion/deletion in random order.
1411 ExpectOperationCounts(45281, 132551, values, &tracker, &set3);
1412 ExpectOperationCounts(386718, 129807, values, &tracker, &set61);
1413 ExpectOperationCounts(586761, 130310, values, &tracker, &set100);
1414
1415 // Test key insertion/deletion in sorted order.
1416 std::sort(values.begin(), values.end());
1417 ExpectOperationCounts(26638, 92134, values, &tracker, &set3);
1418 ExpectOperationCounts(20208, 87757, values, &tracker, &set61);
1419 ExpectOperationCounts(20124, 96583, values, &tracker, &set100);
1420
1421 // Test key insertion/deletion in reverse sorted order.
1422 std::reverse(values.begin(), values.end());
1423 ExpectOperationCounts(49951, 119325, values, &tracker, &set3);
1424 ExpectOperationCounts(338813, 118266, values, &tracker, &set61);
1425 ExpectOperationCounts(534529, 125279, values, &tracker, &set100);
1426 }
1427
1428 struct MovableOnlyInstanceThreeWayCompare {
operator ()absl::container_internal::__anonc80c217f0311::MovableOnlyInstanceThreeWayCompare1429 absl::weak_ordering operator()(const MovableOnlyInstance &a,
1430 const MovableOnlyInstance &b) const {
1431 return a.compare(b);
1432 }
1433 };
1434
1435 // Note: when the values in this test change, it is expected to have an impact
1436 // on performance.
TEST(Btree,MovesComparisonsCopiesSwapsTrackingThreeWayCompare)1437 TEST(Btree, MovesComparisonsCopiesSwapsTrackingThreeWayCompare) {
1438 InstanceTracker tracker;
1439 // Note: this is minimum number of values per node.
1440 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/3,
1441 MovableOnlyInstanceThreeWayCompare>
1442 set3;
1443 // Note: this is the default number of values per node for a set of int32s
1444 // (with 64-bit pointers).
1445 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61,
1446 MovableOnlyInstanceThreeWayCompare>
1447 set61;
1448 SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/100,
1449 MovableOnlyInstanceThreeWayCompare>
1450 set100;
1451
1452 // Don't depend on flags for random values because then the expectations will
1453 // fail if the flags change.
1454 std::vector<int> values =
1455 GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23);
1456
1457 EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set3)>(), 3);
1458 EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>(), 61);
1459 EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set100)>(), 100);
1460 if (sizeof(void *) == 8) {
1461 EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<absl::btree_set<int32_t>>(),
1462 BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>());
1463 }
1464
1465 // Test key insertion/deletion in random order.
1466 ExpectOperationCounts(45281, 122560, values, &tracker, &set3);
1467 ExpectOperationCounts(386718, 119816, values, &tracker, &set61);
1468 ExpectOperationCounts(586761, 120319, values, &tracker, &set100);
1469
1470 // Test key insertion/deletion in sorted order.
1471 std::sort(values.begin(), values.end());
1472 ExpectOperationCounts(26638, 92134, values, &tracker, &set3);
1473 ExpectOperationCounts(20208, 87757, values, &tracker, &set61);
1474 ExpectOperationCounts(20124, 96583, values, &tracker, &set100);
1475
1476 // Test key insertion/deletion in reverse sorted order.
1477 std::reverse(values.begin(), values.end());
1478 ExpectOperationCounts(49951, 109326, values, &tracker, &set3);
1479 ExpectOperationCounts(338813, 108267, values, &tracker, &set61);
1480 ExpectOperationCounts(534529, 115280, values, &tracker, &set100);
1481 }
1482
1483 struct NoDefaultCtor {
1484 int num;
NoDefaultCtorabsl::container_internal::__anonc80c217f0311::NoDefaultCtor1485 explicit NoDefaultCtor(int i) : num(i) {}
1486
operator <(const NoDefaultCtor & a,const NoDefaultCtor & b)1487 friend bool operator<(const NoDefaultCtor &a, const NoDefaultCtor &b) {
1488 return a.num < b.num;
1489 }
1490 };
1491
TEST(Btree,BtreeMapCanHoldNoDefaultCtorTypes)1492 TEST(Btree, BtreeMapCanHoldNoDefaultCtorTypes) {
1493 absl::btree_map<NoDefaultCtor, NoDefaultCtor> m;
1494
1495 for (int i = 1; i <= 99; ++i) {
1496 SCOPED_TRACE(i);
1497 EXPECT_TRUE(m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i)).second);
1498 }
1499 EXPECT_FALSE(m.emplace(NoDefaultCtor(78), NoDefaultCtor(0)).second);
1500
1501 auto iter99 = m.find(NoDefaultCtor(99));
1502 ASSERT_NE(iter99, m.end());
1503 EXPECT_EQ(iter99->second.num, 1);
1504
1505 auto iter1 = m.find(NoDefaultCtor(1));
1506 ASSERT_NE(iter1, m.end());
1507 EXPECT_EQ(iter1->second.num, 99);
1508
1509 auto iter50 = m.find(NoDefaultCtor(50));
1510 ASSERT_NE(iter50, m.end());
1511 EXPECT_EQ(iter50->second.num, 50);
1512
1513 auto iter25 = m.find(NoDefaultCtor(25));
1514 ASSERT_NE(iter25, m.end());
1515 EXPECT_EQ(iter25->second.num, 75);
1516 }
1517
TEST(Btree,BtreeMultimapCanHoldNoDefaultCtorTypes)1518 TEST(Btree, BtreeMultimapCanHoldNoDefaultCtorTypes) {
1519 absl::btree_multimap<NoDefaultCtor, NoDefaultCtor> m;
1520
1521 for (int i = 1; i <= 99; ++i) {
1522 SCOPED_TRACE(i);
1523 m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i));
1524 }
1525
1526 auto iter99 = m.find(NoDefaultCtor(99));
1527 ASSERT_NE(iter99, m.end());
1528 EXPECT_EQ(iter99->second.num, 1);
1529
1530 auto iter1 = m.find(NoDefaultCtor(1));
1531 ASSERT_NE(iter1, m.end());
1532 EXPECT_EQ(iter1->second.num, 99);
1533
1534 auto iter50 = m.find(NoDefaultCtor(50));
1535 ASSERT_NE(iter50, m.end());
1536 EXPECT_EQ(iter50->second.num, 50);
1537
1538 auto iter25 = m.find(NoDefaultCtor(25));
1539 ASSERT_NE(iter25, m.end());
1540 EXPECT_EQ(iter25->second.num, 75);
1541 }
1542
TEST(Btree,MapAt)1543 TEST(Btree, MapAt) {
1544 absl::btree_map<int, int> map = {{1, 2}, {2, 4}};
1545 EXPECT_EQ(map.at(1), 2);
1546 EXPECT_EQ(map.at(2), 4);
1547 map.at(2) = 8;
1548 const absl::btree_map<int, int> &const_map = map;
1549 EXPECT_EQ(const_map.at(1), 2);
1550 EXPECT_EQ(const_map.at(2), 8);
1551 #ifdef ABSL_HAVE_EXCEPTIONS
1552 EXPECT_THROW(map.at(3), std::out_of_range);
1553 #else
1554 EXPECT_DEATH_IF_SUPPORTED(map.at(3), "absl::btree_map::at");
1555 #endif
1556 }
1557
TEST(Btree,BtreeMultisetEmplace)1558 TEST(Btree, BtreeMultisetEmplace) {
1559 const int value_to_insert = 123456;
1560 absl::btree_multiset<int> s;
1561 auto iter = s.emplace(value_to_insert);
1562 ASSERT_NE(iter, s.end());
1563 EXPECT_EQ(*iter, value_to_insert);
1564 auto iter2 = s.emplace(value_to_insert);
1565 EXPECT_NE(iter2, iter);
1566 ASSERT_NE(iter2, s.end());
1567 EXPECT_EQ(*iter2, value_to_insert);
1568 auto result = s.equal_range(value_to_insert);
1569 EXPECT_EQ(std::distance(result.first, result.second), 2);
1570 }
1571
TEST(Btree,BtreeMultisetEmplaceHint)1572 TEST(Btree, BtreeMultisetEmplaceHint) {
1573 const int value_to_insert = 123456;
1574 absl::btree_multiset<int> s;
1575 auto iter = s.emplace(value_to_insert);
1576 ASSERT_NE(iter, s.end());
1577 EXPECT_EQ(*iter, value_to_insert);
1578 auto emplace_iter = s.emplace_hint(iter, value_to_insert);
1579 EXPECT_NE(emplace_iter, iter);
1580 ASSERT_NE(emplace_iter, s.end());
1581 EXPECT_EQ(*emplace_iter, value_to_insert);
1582 }
1583
TEST(Btree,BtreeMultimapEmplace)1584 TEST(Btree, BtreeMultimapEmplace) {
1585 const int key_to_insert = 123456;
1586 const char value0[] = "a";
1587 absl::btree_multimap<int, std::string> s;
1588 auto iter = s.emplace(key_to_insert, value0);
1589 ASSERT_NE(iter, s.end());
1590 EXPECT_EQ(iter->first, key_to_insert);
1591 EXPECT_EQ(iter->second, value0);
1592 const char value1[] = "b";
1593 auto iter2 = s.emplace(key_to_insert, value1);
1594 EXPECT_NE(iter2, iter);
1595 ASSERT_NE(iter2, s.end());
1596 EXPECT_EQ(iter2->first, key_to_insert);
1597 EXPECT_EQ(iter2->second, value1);
1598 auto result = s.equal_range(key_to_insert);
1599 EXPECT_EQ(std::distance(result.first, result.second), 2);
1600 }
1601
TEST(Btree,BtreeMultimapEmplaceHint)1602 TEST(Btree, BtreeMultimapEmplaceHint) {
1603 const int key_to_insert = 123456;
1604 const char value0[] = "a";
1605 absl::btree_multimap<int, std::string> s;
1606 auto iter = s.emplace(key_to_insert, value0);
1607 ASSERT_NE(iter, s.end());
1608 EXPECT_EQ(iter->first, key_to_insert);
1609 EXPECT_EQ(iter->second, value0);
1610 const char value1[] = "b";
1611 auto emplace_iter = s.emplace_hint(iter, key_to_insert, value1);
1612 EXPECT_NE(emplace_iter, iter);
1613 ASSERT_NE(emplace_iter, s.end());
1614 EXPECT_EQ(emplace_iter->first, key_to_insert);
1615 EXPECT_EQ(emplace_iter->second, value1);
1616 }
1617
TEST(Btree,ConstIteratorAccessors)1618 TEST(Btree, ConstIteratorAccessors) {
1619 absl::btree_set<int> set;
1620 for (int i = 0; i < 100; ++i) {
1621 set.insert(i);
1622 }
1623
1624 auto it = set.cbegin();
1625 auto r_it = set.crbegin();
1626 for (int i = 0; i < 100; ++i, ++it, ++r_it) {
1627 ASSERT_EQ(*it, i);
1628 ASSERT_EQ(*r_it, 99 - i);
1629 }
1630 EXPECT_EQ(it, set.cend());
1631 EXPECT_EQ(r_it, set.crend());
1632 }
1633
TEST(Btree,StrSplitCompatible)1634 TEST(Btree, StrSplitCompatible) {
1635 const absl::btree_set<std::string> split_set = absl::StrSplit("a,b,c", ',');
1636 const absl::btree_set<std::string> expected_set = {"a", "b", "c"};
1637
1638 EXPECT_EQ(split_set, expected_set);
1639 }
1640
1641 // We can't use EXPECT_EQ/etc. to compare absl::weak_ordering because they
1642 // convert literal 0 to int and absl::weak_ordering can only be compared with
1643 // literal 0. Defining this function allows for avoiding ClangTidy warnings.
Identity(const bool b)1644 bool Identity(const bool b) { return b; }
1645
TEST(Btree,ValueComp)1646 TEST(Btree, ValueComp) {
1647 absl::btree_set<int> s;
1648 EXPECT_TRUE(s.value_comp()(1, 2));
1649 EXPECT_FALSE(s.value_comp()(2, 2));
1650 EXPECT_FALSE(s.value_comp()(2, 1));
1651
1652 absl::btree_map<int, int> m1;
1653 EXPECT_TRUE(m1.value_comp()(std::make_pair(1, 0), std::make_pair(2, 0)));
1654 EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(2, 0)));
1655 EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(1, 0)));
1656
1657 absl::btree_map<std::string, int> m2;
1658 EXPECT_TRUE(Identity(
1659 m2.value_comp()(std::make_pair("a", 0), std::make_pair("b", 0)) < 0));
1660 EXPECT_TRUE(Identity(
1661 m2.value_comp()(std::make_pair("b", 0), std::make_pair("b", 0)) == 0));
1662 EXPECT_TRUE(Identity(
1663 m2.value_comp()(std::make_pair("b", 0), std::make_pair("a", 0)) > 0));
1664 }
1665
TEST(Btree,DefaultConstruction)1666 TEST(Btree, DefaultConstruction) {
1667 absl::btree_set<int> s;
1668 absl::btree_map<int, int> m;
1669 absl::btree_multiset<int> ms;
1670 absl::btree_multimap<int, int> mm;
1671
1672 EXPECT_TRUE(s.empty());
1673 EXPECT_TRUE(m.empty());
1674 EXPECT_TRUE(ms.empty());
1675 EXPECT_TRUE(mm.empty());
1676 }
1677
TEST(Btree,SwissTableHashable)1678 TEST(Btree, SwissTableHashable) {
1679 static constexpr int kValues = 10000;
1680 std::vector<int> values(kValues);
1681 std::iota(values.begin(), values.end(), 0);
1682 std::vector<std::pair<int, int>> map_values;
1683 for (int v : values) map_values.emplace_back(v, -v);
1684
1685 using set = absl::btree_set<int>;
1686 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
1687 set{},
1688 set{1},
1689 set{2},
1690 set{1, 2},
1691 set{2, 1},
1692 set(values.begin(), values.end()),
1693 set(values.rbegin(), values.rend()),
1694 }));
1695
1696 using mset = absl::btree_multiset<int>;
1697 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
1698 mset{},
1699 mset{1},
1700 mset{1, 1},
1701 mset{2},
1702 mset{2, 2},
1703 mset{1, 2},
1704 mset{1, 1, 2},
1705 mset{1, 2, 2},
1706 mset{1, 1, 2, 2},
1707 mset(values.begin(), values.end()),
1708 mset(values.rbegin(), values.rend()),
1709 }));
1710
1711 using map = absl::btree_map<int, int>;
1712 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
1713 map{},
1714 map{{1, 0}},
1715 map{{1, 1}},
1716 map{{2, 0}},
1717 map{{2, 2}},
1718 map{{1, 0}, {2, 1}},
1719 map(map_values.begin(), map_values.end()),
1720 map(map_values.rbegin(), map_values.rend()),
1721 }));
1722
1723 using mmap = absl::btree_multimap<int, int>;
1724 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
1725 mmap{},
1726 mmap{{1, 0}},
1727 mmap{{1, 1}},
1728 mmap{{1, 0}, {1, 1}},
1729 mmap{{1, 1}, {1, 0}},
1730 mmap{{2, 0}},
1731 mmap{{2, 2}},
1732 mmap{{1, 0}, {2, 1}},
1733 mmap(map_values.begin(), map_values.end()),
1734 mmap(map_values.rbegin(), map_values.rend()),
1735 }));
1736 }
1737
TEST(Btree,ComparableSet)1738 TEST(Btree, ComparableSet) {
1739 absl::btree_set<int> s1 = {1, 2};
1740 absl::btree_set<int> s2 = {2, 3};
1741 EXPECT_LT(s1, s2);
1742 EXPECT_LE(s1, s2);
1743 EXPECT_LE(s1, s1);
1744 EXPECT_GT(s2, s1);
1745 EXPECT_GE(s2, s1);
1746 EXPECT_GE(s1, s1);
1747 }
1748
TEST(Btree,ComparableSetsDifferentLength)1749 TEST(Btree, ComparableSetsDifferentLength) {
1750 absl::btree_set<int> s1 = {1, 2};
1751 absl::btree_set<int> s2 = {1, 2, 3};
1752 EXPECT_LT(s1, s2);
1753 EXPECT_LE(s1, s2);
1754 EXPECT_GT(s2, s1);
1755 EXPECT_GE(s2, s1);
1756 }
1757
TEST(Btree,ComparableMultiset)1758 TEST(Btree, ComparableMultiset) {
1759 absl::btree_multiset<int> s1 = {1, 2};
1760 absl::btree_multiset<int> s2 = {2, 3};
1761 EXPECT_LT(s1, s2);
1762 EXPECT_LE(s1, s2);
1763 EXPECT_LE(s1, s1);
1764 EXPECT_GT(s2, s1);
1765 EXPECT_GE(s2, s1);
1766 EXPECT_GE(s1, s1);
1767 }
1768
TEST(Btree,ComparableMap)1769 TEST(Btree, ComparableMap) {
1770 absl::btree_map<int, int> s1 = {{1, 2}};
1771 absl::btree_map<int, int> s2 = {{2, 3}};
1772 EXPECT_LT(s1, s2);
1773 EXPECT_LE(s1, s2);
1774 EXPECT_LE(s1, s1);
1775 EXPECT_GT(s2, s1);
1776 EXPECT_GE(s2, s1);
1777 EXPECT_GE(s1, s1);
1778 }
1779
TEST(Btree,ComparableMultimap)1780 TEST(Btree, ComparableMultimap) {
1781 absl::btree_multimap<int, int> s1 = {{1, 2}};
1782 absl::btree_multimap<int, int> s2 = {{2, 3}};
1783 EXPECT_LT(s1, s2);
1784 EXPECT_LE(s1, s2);
1785 EXPECT_LE(s1, s1);
1786 EXPECT_GT(s2, s1);
1787 EXPECT_GE(s2, s1);
1788 EXPECT_GE(s1, s1);
1789 }
1790
TEST(Btree,ComparableSetWithCustomComparator)1791 TEST(Btree, ComparableSetWithCustomComparator) {
1792 // As specified by
1793 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf section
1794 // [container.requirements.general].12, ordering associative containers always
1795 // uses default '<' operator
1796 // - even if otherwise the container uses custom functor.
1797 absl::btree_set<int, std::greater<int>> s1 = {1, 2};
1798 absl::btree_set<int, std::greater<int>> s2 = {2, 3};
1799 EXPECT_LT(s1, s2);
1800 EXPECT_LE(s1, s2);
1801 EXPECT_LE(s1, s1);
1802 EXPECT_GT(s2, s1);
1803 EXPECT_GE(s2, s1);
1804 EXPECT_GE(s1, s1);
1805 }
1806
TEST(Btree,EraseReturnsIterator)1807 TEST(Btree, EraseReturnsIterator) {
1808 absl::btree_set<int> set = {1, 2, 3, 4, 5};
1809 auto result_it = set.erase(set.begin(), set.find(3));
1810 EXPECT_EQ(result_it, set.find(3));
1811 result_it = set.erase(set.find(5));
1812 EXPECT_EQ(result_it, set.end());
1813 }
1814
TEST(Btree,ExtractAndInsertNodeHandleSet)1815 TEST(Btree, ExtractAndInsertNodeHandleSet) {
1816 absl::btree_set<int> src1 = {1, 2, 3, 4, 5};
1817 auto nh = src1.extract(src1.find(3));
1818 EXPECT_THAT(src1, ElementsAre(1, 2, 4, 5));
1819 absl::btree_set<int> other;
1820 absl::btree_set<int>::insert_return_type res = other.insert(std::move(nh));
1821 EXPECT_THAT(other, ElementsAre(3));
1822 EXPECT_EQ(res.position, other.find(3));
1823 EXPECT_TRUE(res.inserted);
1824 EXPECT_TRUE(res.node.empty());
1825
1826 absl::btree_set<int> src2 = {3, 4};
1827 nh = src2.extract(src2.find(3));
1828 EXPECT_THAT(src2, ElementsAre(4));
1829 res = other.insert(std::move(nh));
1830 EXPECT_THAT(other, ElementsAre(3));
1831 EXPECT_EQ(res.position, other.find(3));
1832 EXPECT_FALSE(res.inserted);
1833 ASSERT_FALSE(res.node.empty());
1834 EXPECT_EQ(res.node.value(), 3);
1835 }
1836
1837 template <typename Set>
TestExtractWithTrackingForSet()1838 void TestExtractWithTrackingForSet() {
1839 InstanceTracker tracker;
1840 {
1841 Set s;
1842 // Add enough elements to make sure we test internal nodes too.
1843 const size_t kSize = 1000;
1844 while (s.size() < kSize) {
1845 s.insert(MovableOnlyInstance(s.size()));
1846 }
1847 for (int i = 0; i < kSize; ++i) {
1848 // Extract with key
1849 auto nh = s.extract(MovableOnlyInstance(i));
1850 EXPECT_EQ(s.size(), kSize - 1);
1851 EXPECT_EQ(nh.value().value(), i);
1852 // Insert with node
1853 s.insert(std::move(nh));
1854 EXPECT_EQ(s.size(), kSize);
1855
1856 // Extract with iterator
1857 auto it = s.find(MovableOnlyInstance(i));
1858 nh = s.extract(it);
1859 EXPECT_EQ(s.size(), kSize - 1);
1860 EXPECT_EQ(nh.value().value(), i);
1861 // Insert with node and hint
1862 s.insert(s.begin(), std::move(nh));
1863 EXPECT_EQ(s.size(), kSize);
1864 }
1865 }
1866 EXPECT_EQ(0, tracker.instances());
1867 }
1868
1869 template <typename Map>
TestExtractWithTrackingForMap()1870 void TestExtractWithTrackingForMap() {
1871 InstanceTracker tracker;
1872 {
1873 Map m;
1874 // Add enough elements to make sure we test internal nodes too.
1875 const size_t kSize = 1000;
1876 while (m.size() < kSize) {
1877 m.insert(
1878 {CopyableMovableInstance(m.size()), MovableOnlyInstance(m.size())});
1879 }
1880 for (int i = 0; i < kSize; ++i) {
1881 // Extract with key
1882 auto nh = m.extract(CopyableMovableInstance(i));
1883 EXPECT_EQ(m.size(), kSize - 1);
1884 EXPECT_EQ(nh.key().value(), i);
1885 EXPECT_EQ(nh.mapped().value(), i);
1886 // Insert with node
1887 m.insert(std::move(nh));
1888 EXPECT_EQ(m.size(), kSize);
1889
1890 // Extract with iterator
1891 auto it = m.find(CopyableMovableInstance(i));
1892 nh = m.extract(it);
1893 EXPECT_EQ(m.size(), kSize - 1);
1894 EXPECT_EQ(nh.key().value(), i);
1895 EXPECT_EQ(nh.mapped().value(), i);
1896 // Insert with node and hint
1897 m.insert(m.begin(), std::move(nh));
1898 EXPECT_EQ(m.size(), kSize);
1899 }
1900 }
1901 EXPECT_EQ(0, tracker.instances());
1902 }
1903
TEST(Btree,ExtractTracking)1904 TEST(Btree, ExtractTracking) {
1905 TestExtractWithTrackingForSet<absl::btree_set<MovableOnlyInstance>>();
1906 TestExtractWithTrackingForSet<absl::btree_multiset<MovableOnlyInstance>>();
1907 TestExtractWithTrackingForMap<
1908 absl::btree_map<CopyableMovableInstance, MovableOnlyInstance>>();
1909 TestExtractWithTrackingForMap<
1910 absl::btree_multimap<CopyableMovableInstance, MovableOnlyInstance>>();
1911 }
1912
TEST(Btree,ExtractAndInsertNodeHandleMultiSet)1913 TEST(Btree, ExtractAndInsertNodeHandleMultiSet) {
1914 absl::btree_multiset<int> src1 = {1, 2, 3, 3, 4, 5};
1915 auto nh = src1.extract(src1.find(3));
1916 EXPECT_THAT(src1, ElementsAre(1, 2, 3, 4, 5));
1917 absl::btree_multiset<int> other;
1918 auto res = other.insert(std::move(nh));
1919 EXPECT_THAT(other, ElementsAre(3));
1920 EXPECT_EQ(res, other.find(3));
1921
1922 absl::btree_multiset<int> src2 = {3, 4};
1923 nh = src2.extract(src2.find(3));
1924 EXPECT_THAT(src2, ElementsAre(4));
1925 res = other.insert(std::move(nh));
1926 EXPECT_THAT(other, ElementsAre(3, 3));
1927 EXPECT_EQ(res, ++other.find(3));
1928 }
1929
TEST(Btree,ExtractAndInsertNodeHandleMap)1930 TEST(Btree, ExtractAndInsertNodeHandleMap) {
1931 absl::btree_map<int, int> src1 = {{1, 2}, {3, 4}, {5, 6}};
1932 auto nh = src1.extract(src1.find(3));
1933 EXPECT_THAT(src1, ElementsAre(Pair(1, 2), Pair(5, 6)));
1934 absl::btree_map<int, int> other;
1935 absl::btree_map<int, int>::insert_return_type res =
1936 other.insert(std::move(nh));
1937 EXPECT_THAT(other, ElementsAre(Pair(3, 4)));
1938 EXPECT_EQ(res.position, other.find(3));
1939 EXPECT_TRUE(res.inserted);
1940 EXPECT_TRUE(res.node.empty());
1941
1942 absl::btree_map<int, int> src2 = {{3, 6}};
1943 nh = src2.extract(src2.find(3));
1944 EXPECT_TRUE(src2.empty());
1945 res = other.insert(std::move(nh));
1946 EXPECT_THAT(other, ElementsAre(Pair(3, 4)));
1947 EXPECT_EQ(res.position, other.find(3));
1948 EXPECT_FALSE(res.inserted);
1949 ASSERT_FALSE(res.node.empty());
1950 EXPECT_EQ(res.node.key(), 3);
1951 EXPECT_EQ(res.node.mapped(), 6);
1952 }
1953
TEST(Btree,ExtractAndInsertNodeHandleMultiMap)1954 TEST(Btree, ExtractAndInsertNodeHandleMultiMap) {
1955 absl::btree_multimap<int, int> src1 = {{1, 2}, {3, 4}, {5, 6}};
1956 auto nh = src1.extract(src1.find(3));
1957 EXPECT_THAT(src1, ElementsAre(Pair(1, 2), Pair(5, 6)));
1958 absl::btree_multimap<int, int> other;
1959 auto res = other.insert(std::move(nh));
1960 EXPECT_THAT(other, ElementsAre(Pair(3, 4)));
1961 EXPECT_EQ(res, other.find(3));
1962
1963 absl::btree_multimap<int, int> src2 = {{3, 6}};
1964 nh = src2.extract(src2.find(3));
1965 EXPECT_TRUE(src2.empty());
1966 res = other.insert(std::move(nh));
1967 EXPECT_THAT(other, ElementsAre(Pair(3, 4), Pair(3, 6)));
1968 EXPECT_EQ(res, ++other.begin());
1969 }
1970
1971 // For multisets, insert with hint also affects correctness because we need to
1972 // insert immediately before the hint if possible.
1973 struct InsertMultiHintData {
1974 int key;
1975 int not_key;
operator ==absl::container_internal::__anonc80c217f0311::InsertMultiHintData1976 bool operator==(const InsertMultiHintData other) const {
1977 return key == other.key && not_key == other.not_key;
1978 }
1979 };
1980
1981 struct InsertMultiHintDataKeyCompare {
1982 using is_transparent = void;
operator ()absl::container_internal::__anonc80c217f0311::InsertMultiHintDataKeyCompare1983 bool operator()(const InsertMultiHintData a,
1984 const InsertMultiHintData b) const {
1985 return a.key < b.key;
1986 }
operator ()absl::container_internal::__anonc80c217f0311::InsertMultiHintDataKeyCompare1987 bool operator()(const int a, const InsertMultiHintData b) const {
1988 return a < b.key;
1989 }
operator ()absl::container_internal::__anonc80c217f0311::InsertMultiHintDataKeyCompare1990 bool operator()(const InsertMultiHintData a, const int b) const {
1991 return a.key < b;
1992 }
1993 };
1994
TEST(Btree,InsertHintNodeHandle)1995 TEST(Btree, InsertHintNodeHandle) {
1996 // For unique sets, insert with hint is just a performance optimization.
1997 // Test that insert works correctly when the hint is right or wrong.
1998 {
1999 absl::btree_set<int> src = {1, 2, 3, 4, 5};
2000 auto nh = src.extract(src.find(3));
2001 EXPECT_THAT(src, ElementsAre(1, 2, 4, 5));
2002 absl::btree_set<int> other = {0, 100};
2003 // Test a correct hint.
2004 auto it = other.insert(other.lower_bound(3), std::move(nh));
2005 EXPECT_THAT(other, ElementsAre(0, 3, 100));
2006 EXPECT_EQ(it, other.find(3));
2007
2008 nh = src.extract(src.find(5));
2009 // Test an incorrect hint.
2010 it = other.insert(other.end(), std::move(nh));
2011 EXPECT_THAT(other, ElementsAre(0, 3, 5, 100));
2012 EXPECT_EQ(it, other.find(5));
2013 }
2014
2015 absl::btree_multiset<InsertMultiHintData, InsertMultiHintDataKeyCompare> src =
2016 {{1, 2}, {3, 4}, {3, 5}};
2017 auto nh = src.extract(src.lower_bound(3));
2018 EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 4}));
2019 absl::btree_multiset<InsertMultiHintData, InsertMultiHintDataKeyCompare>
2020 other = {{3, 1}, {3, 2}, {3, 3}};
2021 auto it = other.insert(--other.end(), std::move(nh));
2022 EXPECT_THAT(
2023 other, ElementsAre(InsertMultiHintData{3, 1}, InsertMultiHintData{3, 2},
2024 InsertMultiHintData{3, 4}, InsertMultiHintData{3, 3}));
2025 EXPECT_EQ(it, --(--other.end()));
2026
2027 nh = src.extract(src.find(3));
2028 EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 5}));
2029 it = other.insert(other.begin(), std::move(nh));
2030 EXPECT_THAT(other,
2031 ElementsAre(InsertMultiHintData{3, 5}, InsertMultiHintData{3, 1},
2032 InsertMultiHintData{3, 2}, InsertMultiHintData{3, 4},
2033 InsertMultiHintData{3, 3}));
2034 EXPECT_EQ(it, other.begin());
2035 }
2036
2037 struct IntCompareToCmp {
operator ()absl::container_internal::__anonc80c217f0311::IntCompareToCmp2038 absl::weak_ordering operator()(int a, int b) const {
2039 if (a < b) return absl::weak_ordering::less;
2040 if (a > b) return absl::weak_ordering::greater;
2041 return absl::weak_ordering::equivalent;
2042 }
2043 };
2044
TEST(Btree,MergeIntoUniqueContainers)2045 TEST(Btree, MergeIntoUniqueContainers) {
2046 absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
2047 absl::btree_multiset<int> src2 = {3, 4, 4, 5};
2048 absl::btree_set<int> dst;
2049
2050 dst.merge(src1);
2051 EXPECT_TRUE(src1.empty());
2052 EXPECT_THAT(dst, ElementsAre(1, 2, 3));
2053 dst.merge(src2);
2054 EXPECT_THAT(src2, ElementsAre(3, 4));
2055 EXPECT_THAT(dst, ElementsAre(1, 2, 3, 4, 5));
2056 }
2057
TEST(Btree,MergeIntoUniqueContainersWithCompareTo)2058 TEST(Btree, MergeIntoUniqueContainersWithCompareTo) {
2059 absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
2060 absl::btree_multiset<int> src2 = {3, 4, 4, 5};
2061 absl::btree_set<int, IntCompareToCmp> dst;
2062
2063 dst.merge(src1);
2064 EXPECT_TRUE(src1.empty());
2065 EXPECT_THAT(dst, ElementsAre(1, 2, 3));
2066 dst.merge(src2);
2067 EXPECT_THAT(src2, ElementsAre(3, 4));
2068 EXPECT_THAT(dst, ElementsAre(1, 2, 3, 4, 5));
2069 }
2070
TEST(Btree,MergeIntoMultiContainers)2071 TEST(Btree, MergeIntoMultiContainers) {
2072 absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
2073 absl::btree_multiset<int> src2 = {3, 4, 4, 5};
2074 absl::btree_multiset<int> dst;
2075
2076 dst.merge(src1);
2077 EXPECT_TRUE(src1.empty());
2078 EXPECT_THAT(dst, ElementsAre(1, 2, 3));
2079 dst.merge(src2);
2080 EXPECT_TRUE(src2.empty());
2081 EXPECT_THAT(dst, ElementsAre(1, 2, 3, 3, 4, 4, 5));
2082 }
2083
TEST(Btree,MergeIntoMultiContainersWithCompareTo)2084 TEST(Btree, MergeIntoMultiContainersWithCompareTo) {
2085 absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
2086 absl::btree_multiset<int> src2 = {3, 4, 4, 5};
2087 absl::btree_multiset<int, IntCompareToCmp> dst;
2088
2089 dst.merge(src1);
2090 EXPECT_TRUE(src1.empty());
2091 EXPECT_THAT(dst, ElementsAre(1, 2, 3));
2092 dst.merge(src2);
2093 EXPECT_TRUE(src2.empty());
2094 EXPECT_THAT(dst, ElementsAre(1, 2, 3, 3, 4, 4, 5));
2095 }
2096
TEST(Btree,MergeIntoMultiMapsWithDifferentComparators)2097 TEST(Btree, MergeIntoMultiMapsWithDifferentComparators) {
2098 absl::btree_map<int, int, IntCompareToCmp> src1 = {{1, 1}, {2, 2}, {3, 3}};
2099 absl::btree_multimap<int, int, std::greater<int>> src2 = {
2100 {5, 5}, {4, 1}, {4, 4}, {3, 2}};
2101 absl::btree_multimap<int, int> dst;
2102
2103 dst.merge(src1);
2104 EXPECT_TRUE(src1.empty());
2105 EXPECT_THAT(dst, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3)));
2106 dst.merge(src2);
2107 EXPECT_TRUE(src2.empty());
2108 EXPECT_THAT(dst, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), Pair(3, 2),
2109 Pair(4, 1), Pair(4, 4), Pair(5, 5)));
2110 }
2111
2112 struct KeyCompareToWeakOrdering {
2113 template <typename T>
operator ()absl::container_internal::__anonc80c217f0311::KeyCompareToWeakOrdering2114 absl::weak_ordering operator()(const T &a, const T &b) const {
2115 return a < b ? absl::weak_ordering::less
2116 : a == b ? absl::weak_ordering::equivalent
2117 : absl::weak_ordering::greater;
2118 }
2119 };
2120
2121 struct KeyCompareToStrongOrdering {
2122 template <typename T>
operator ()absl::container_internal::__anonc80c217f0311::KeyCompareToStrongOrdering2123 absl::strong_ordering operator()(const T &a, const T &b) const {
2124 return a < b ? absl::strong_ordering::less
2125 : a == b ? absl::strong_ordering::equal
2126 : absl::strong_ordering::greater;
2127 }
2128 };
2129
TEST(Btree,UserProvidedKeyCompareToComparators)2130 TEST(Btree, UserProvidedKeyCompareToComparators) {
2131 absl::btree_set<int, KeyCompareToWeakOrdering> weak_set = {1, 2, 3};
2132 EXPECT_TRUE(weak_set.contains(2));
2133 EXPECT_FALSE(weak_set.contains(4));
2134
2135 absl::btree_set<int, KeyCompareToStrongOrdering> strong_set = {1, 2, 3};
2136 EXPECT_TRUE(strong_set.contains(2));
2137 EXPECT_FALSE(strong_set.contains(4));
2138 }
2139
TEST(Btree,TryEmplaceBasicTest)2140 TEST(Btree, TryEmplaceBasicTest) {
2141 absl::btree_map<int, std::string> m;
2142
2143 // Should construct a string from the literal.
2144 m.try_emplace(1, "one");
2145 EXPECT_EQ(1, m.size());
2146
2147 // Try other string constructors and const lvalue key.
2148 const int key(42);
2149 m.try_emplace(key, 3, 'a');
2150 m.try_emplace(2, std::string("two"));
2151
2152 EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
2153 EXPECT_THAT(m, ElementsAreArray(std::vector<std::pair<int, std::string>>{
2154 {1, "one"}, {2, "two"}, {42, "aaa"}}));
2155 }
2156
TEST(Btree,TryEmplaceWithHintWorks)2157 TEST(Btree, TryEmplaceWithHintWorks) {
2158 // Use a counting comparator here to verify that hint is used.
2159 int calls = 0;
2160 auto cmp = [&calls](int x, int y) {
2161 ++calls;
2162 return x < y;
2163 };
2164 using Cmp = decltype(cmp);
2165
2166 absl::btree_map<int, int, Cmp> m(cmp);
2167 for (int i = 0; i < 128; ++i) {
2168 m.emplace(i, i);
2169 }
2170
2171 // Sanity check for the comparator
2172 calls = 0;
2173 m.emplace(127, 127);
2174 EXPECT_GE(calls, 4);
2175
2176 // Try with begin hint:
2177 calls = 0;
2178 auto it = m.try_emplace(m.begin(), -1, -1);
2179 EXPECT_EQ(129, m.size());
2180 EXPECT_EQ(it, m.begin());
2181 EXPECT_LE(calls, 2);
2182
2183 // Try with end hint:
2184 calls = 0;
2185 std::pair<int, int> pair1024 = {1024, 1024};
2186 it = m.try_emplace(m.end(), pair1024.first, pair1024.second);
2187 EXPECT_EQ(130, m.size());
2188 EXPECT_EQ(it, --m.end());
2189 EXPECT_LE(calls, 2);
2190
2191 // Try value already present, bad hint; ensure no duplicate added:
2192 calls = 0;
2193 it = m.try_emplace(m.end(), 16, 17);
2194 EXPECT_EQ(130, m.size());
2195 EXPECT_GE(calls, 4);
2196 EXPECT_EQ(it, m.find(16));
2197
2198 // Try value already present, hint points directly to it:
2199 calls = 0;
2200 it = m.try_emplace(it, 16, 17);
2201 EXPECT_EQ(130, m.size());
2202 EXPECT_LE(calls, 2);
2203 EXPECT_EQ(it, m.find(16));
2204
2205 m.erase(2);
2206 EXPECT_EQ(129, m.size());
2207 auto hint = m.find(3);
2208 // Try emplace in the middle of two other elements.
2209 calls = 0;
2210 m.try_emplace(hint, 2, 2);
2211 EXPECT_EQ(130, m.size());
2212 EXPECT_LE(calls, 2);
2213
2214 EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
2215 }
2216
TEST(Btree,TryEmplaceWithBadHint)2217 TEST(Btree, TryEmplaceWithBadHint) {
2218 absl::btree_map<int, int> m = {{1, 1}, {9, 9}};
2219
2220 // Bad hint (too small), should still emplace:
2221 auto it = m.try_emplace(m.begin(), 2, 2);
2222 EXPECT_EQ(it, ++m.begin());
2223 EXPECT_THAT(m, ElementsAreArray(
2224 std::vector<std::pair<int, int>>{{1, 1}, {2, 2}, {9, 9}}));
2225
2226 // Bad hint, too large this time:
2227 it = m.try_emplace(++(++m.begin()), 0, 0);
2228 EXPECT_EQ(it, m.begin());
2229 EXPECT_THAT(m, ElementsAreArray(std::vector<std::pair<int, int>>{
2230 {0, 0}, {1, 1}, {2, 2}, {9, 9}}));
2231 }
2232
TEST(Btree,TryEmplaceMaintainsSortedOrder)2233 TEST(Btree, TryEmplaceMaintainsSortedOrder) {
2234 absl::btree_map<int, std::string> m;
2235 std::pair<int, std::string> pair5 = {5, "five"};
2236
2237 // Test both lvalue & rvalue emplace.
2238 m.try_emplace(10, "ten");
2239 m.try_emplace(pair5.first, pair5.second);
2240 EXPECT_EQ(2, m.size());
2241 EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
2242
2243 int int100{100};
2244 m.try_emplace(int100, "hundred");
2245 m.try_emplace(1, "one");
2246 EXPECT_EQ(4, m.size());
2247 EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
2248 }
2249
TEST(Btree,TryEmplaceWithHintAndNoValueArgsWorks)2250 TEST(Btree, TryEmplaceWithHintAndNoValueArgsWorks) {
2251 absl::btree_map<int, int> m;
2252 m.try_emplace(m.end(), 1);
2253 EXPECT_EQ(0, m[1]);
2254 }
2255
TEST(Btree,TryEmplaceWithHintAndMultipleValueArgsWorks)2256 TEST(Btree, TryEmplaceWithHintAndMultipleValueArgsWorks) {
2257 absl::btree_map<int, std::string> m;
2258 m.try_emplace(m.end(), 1, 10, 'a');
2259 EXPECT_EQ(std::string(10, 'a'), m[1]);
2260 }
2261
TEST(Btree,MoveAssignmentAllocatorPropagation)2262 TEST(Btree, MoveAssignmentAllocatorPropagation) {
2263 InstanceTracker tracker;
2264
2265 int64_t bytes1 = 0, bytes2 = 0;
2266 PropagatingCountingAlloc<MovableOnlyInstance> allocator1(&bytes1);
2267 PropagatingCountingAlloc<MovableOnlyInstance> allocator2(&bytes2);
2268 std::less<MovableOnlyInstance> cmp;
2269
2270 // Test propagating allocator_type.
2271 {
2272 absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>,
2273 PropagatingCountingAlloc<MovableOnlyInstance>>
2274 set1(cmp, allocator1), set2(cmp, allocator2);
2275
2276 for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i));
2277
2278 tracker.ResetCopiesMovesSwaps();
2279 set2 = std::move(set1);
2280 EXPECT_EQ(tracker.moves(), 0);
2281 }
2282 // Test non-propagating allocator_type with equal allocators.
2283 {
2284 absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>,
2285 CountingAllocator<MovableOnlyInstance>>
2286 set1(cmp, allocator1), set2(cmp, allocator1);
2287
2288 for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i));
2289
2290 tracker.ResetCopiesMovesSwaps();
2291 set2 = std::move(set1);
2292 EXPECT_EQ(tracker.moves(), 0);
2293 }
2294 // Test non-propagating allocator_type with different allocators.
2295 {
2296 absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>,
2297 CountingAllocator<MovableOnlyInstance>>
2298 set1(cmp, allocator1), set2(cmp, allocator2);
2299
2300 for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i));
2301
2302 tracker.ResetCopiesMovesSwaps();
2303 set2 = std::move(set1);
2304 EXPECT_GE(tracker.moves(), 100);
2305 }
2306 }
2307
TEST(Btree,EmptyTree)2308 TEST(Btree, EmptyTree) {
2309 absl::btree_set<int> s;
2310 EXPECT_TRUE(s.empty());
2311 EXPECT_EQ(s.size(), 0);
2312 EXPECT_GT(s.max_size(), 0);
2313 }
2314
IsEven(int k)2315 bool IsEven(int k) { return k % 2 == 0; }
2316
TEST(Btree,EraseIf)2317 TEST(Btree, EraseIf) {
2318 // Test that erase_if works with all the container types and supports lambdas.
2319 {
2320 absl::btree_set<int> s = {1, 3, 5, 6, 100};
2321 erase_if(s, [](int k) { return k > 3; });
2322 EXPECT_THAT(s, ElementsAre(1, 3));
2323 }
2324 {
2325 absl::btree_multiset<int> s = {1, 3, 3, 5, 6, 6, 100};
2326 erase_if(s, [](int k) { return k <= 3; });
2327 EXPECT_THAT(s, ElementsAre(5, 6, 6, 100));
2328 }
2329 {
2330 absl::btree_map<int, int> m = {{1, 1}, {3, 3}, {6, 6}, {100, 100}};
2331 erase_if(m, [](std::pair<const int, int> kv) { return kv.first > 3; });
2332 EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3)));
2333 }
2334 {
2335 absl::btree_multimap<int, int> m = {{1, 1}, {3, 3}, {3, 6},
2336 {6, 6}, {6, 7}, {100, 6}};
2337 erase_if(m, [](std::pair<const int, int> kv) { return kv.second == 6; });
2338 EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3), Pair(6, 7)));
2339 }
2340 // Test that erasing all elements from a large set works and test support for
2341 // function pointers.
2342 {
2343 absl::btree_set<int> s;
2344 for (int i = 0; i < 1000; ++i) s.insert(2 * i);
2345 erase_if(s, IsEven);
2346 EXPECT_THAT(s, IsEmpty());
2347 }
2348 // Test that erase_if supports other format of function pointers.
2349 {
2350 absl::btree_set<int> s = {1, 3, 5, 6, 100};
2351 erase_if(s, &IsEven);
2352 EXPECT_THAT(s, ElementsAre(1, 3, 5));
2353 }
2354 }
2355
TEST(Btree,InsertOrAssign)2356 TEST(Btree, InsertOrAssign) {
2357 absl::btree_map<int, int> m = {{1, 1}, {3, 3}};
2358 using value_type = typename decltype(m)::value_type;
2359
2360 auto ret = m.insert_or_assign(4, 4);
2361 EXPECT_EQ(*ret.first, value_type(4, 4));
2362 EXPECT_TRUE(ret.second);
2363 ret = m.insert_or_assign(3, 100);
2364 EXPECT_EQ(*ret.first, value_type(3, 100));
2365 EXPECT_FALSE(ret.second);
2366
2367 auto hint_ret = m.insert_or_assign(ret.first, 3, 200);
2368 EXPECT_EQ(*hint_ret, value_type(3, 200));
2369 hint_ret = m.insert_or_assign(m.find(1), 0, 1);
2370 EXPECT_EQ(*hint_ret, value_type(0, 1));
2371 // Test with bad hint.
2372 hint_ret = m.insert_or_assign(m.end(), -1, 1);
2373 EXPECT_EQ(*hint_ret, value_type(-1, 1));
2374
2375 EXPECT_THAT(m, ElementsAre(Pair(-1, 1), Pair(0, 1), Pair(1, 1), Pair(3, 200),
2376 Pair(4, 4)));
2377 }
2378
TEST(Btree,InsertOrAssignMovableOnly)2379 TEST(Btree, InsertOrAssignMovableOnly) {
2380 absl::btree_map<int, MovableOnlyInstance> m;
2381 using value_type = typename decltype(m)::value_type;
2382
2383 auto ret = m.insert_or_assign(4, MovableOnlyInstance(4));
2384 EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(4)));
2385 EXPECT_TRUE(ret.second);
2386 ret = m.insert_or_assign(4, MovableOnlyInstance(100));
2387 EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(100)));
2388 EXPECT_FALSE(ret.second);
2389
2390 auto hint_ret = m.insert_or_assign(ret.first, 3, MovableOnlyInstance(200));
2391 EXPECT_EQ(*hint_ret, value_type(3, MovableOnlyInstance(200)));
2392
2393 EXPECT_EQ(m.size(), 2);
2394 }
2395
TEST(Btree,BitfieldArgument)2396 TEST(Btree, BitfieldArgument) {
2397 union {
2398 int n : 1;
2399 };
2400 n = 0;
2401 absl::btree_map<int, int> m;
2402 m.erase(n);
2403 m.count(n);
2404 m.find(n);
2405 m.contains(n);
2406 m.equal_range(n);
2407 m.insert_or_assign(n, n);
2408 m.insert_or_assign(m.end(), n, n);
2409 m.try_emplace(n);
2410 m.try_emplace(m.end(), n);
2411 m.at(n);
2412 m[n];
2413 }
2414
TEST(Btree,SetRangeConstructorAndInsertSupportExplicitConversionComparable)2415 TEST(Btree, SetRangeConstructorAndInsertSupportExplicitConversionComparable) {
2416 const absl::string_view names[] = {"n1", "n2"};
2417
2418 absl::btree_set<std::string> name_set1{std::begin(names), std::end(names)};
2419 EXPECT_THAT(name_set1, ElementsAreArray(names));
2420
2421 absl::btree_set<std::string> name_set2;
2422 name_set2.insert(std::begin(names), std::end(names));
2423 EXPECT_THAT(name_set2, ElementsAreArray(names));
2424 }
2425
2426 // A type that is explicitly convertible from int and counts constructor calls.
2427 struct ConstructorCounted {
ConstructorCountedabsl::container_internal::__anonc80c217f0311::ConstructorCounted2428 explicit ConstructorCounted(int i) : i(i) { ++constructor_calls; }
operator ==absl::container_internal::__anonc80c217f0311::ConstructorCounted2429 bool operator==(int other) const { return i == other; }
2430
2431 int i;
2432 static int constructor_calls;
2433 };
2434 int ConstructorCounted::constructor_calls = 0;
2435
2436 struct ConstructorCountedCompare {
operator ()absl::container_internal::__anonc80c217f0311::ConstructorCountedCompare2437 bool operator()(int a, const ConstructorCounted &b) const { return a < b.i; }
operator ()absl::container_internal::__anonc80c217f0311::ConstructorCountedCompare2438 bool operator()(const ConstructorCounted &a, int b) const { return a.i < b; }
operator ()absl::container_internal::__anonc80c217f0311::ConstructorCountedCompare2439 bool operator()(const ConstructorCounted &a,
2440 const ConstructorCounted &b) const {
2441 return a.i < b.i;
2442 }
2443 using is_transparent = void;
2444 };
2445
TEST(Btree,SetRangeConstructorAndInsertExplicitConvComparableLimitConstruction)2446 TEST(Btree,
2447 SetRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
2448 const int i[] = {0, 1, 1};
2449 ConstructorCounted::constructor_calls = 0;
2450
2451 absl::btree_set<ConstructorCounted, ConstructorCountedCompare> set{
2452 std::begin(i), std::end(i)};
2453 EXPECT_THAT(set, ElementsAre(0, 1));
2454 EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
2455
2456 set.insert(std::begin(i), std::end(i));
2457 EXPECT_THAT(set, ElementsAre(0, 1));
2458 EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
2459 }
2460
TEST(Btree,SetRangeConstructorAndInsertSupportExplicitConversionNonComparable)2461 TEST(Btree,
2462 SetRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
2463 const int i[] = {0, 1};
2464
2465 absl::btree_set<std::vector<void *>> s1{std::begin(i), std::end(i)};
2466 EXPECT_THAT(s1, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
2467
2468 absl::btree_set<std::vector<void *>> s2;
2469 s2.insert(std::begin(i), std::end(i));
2470 EXPECT_THAT(s2, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
2471 }
2472
2473 // libstdc++ included with GCC 4.9 has a bug in the std::pair constructors that
2474 // prevents explicit conversions between pair types.
2475 // We only run this test for the libstdc++ from GCC 7 or newer because we can't
2476 // reliably check the libstdc++ version prior to that release.
2477 #if !defined(__GLIBCXX__) || \
2478 (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7)
TEST(Btree,MapRangeConstructorAndInsertSupportExplicitConversionComparable)2479 TEST(Btree, MapRangeConstructorAndInsertSupportExplicitConversionComparable) {
2480 const std::pair<absl::string_view, int> names[] = {{"n1", 1}, {"n2", 2}};
2481
2482 absl::btree_map<std::string, int> name_map1{std::begin(names),
2483 std::end(names)};
2484 EXPECT_THAT(name_map1, ElementsAre(Pair("n1", 1), Pair("n2", 2)));
2485
2486 absl::btree_map<std::string, int> name_map2;
2487 name_map2.insert(std::begin(names), std::end(names));
2488 EXPECT_THAT(name_map2, ElementsAre(Pair("n1", 1), Pair("n2", 2)));
2489 }
2490
TEST(Btree,MapRangeConstructorAndInsertExplicitConvComparableLimitConstruction)2491 TEST(Btree,
2492 MapRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
2493 const std::pair<int, int> i[] = {{0, 1}, {1, 2}, {1, 3}};
2494 ConstructorCounted::constructor_calls = 0;
2495
2496 absl::btree_map<ConstructorCounted, int, ConstructorCountedCompare> map{
2497 std::begin(i), std::end(i)};
2498 EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));
2499 EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
2500
2501 map.insert(std::begin(i), std::end(i));
2502 EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));
2503 EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
2504 }
2505
TEST(Btree,MapRangeConstructorAndInsertSupportExplicitConversionNonComparable)2506 TEST(Btree,
2507 MapRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
2508 const std::pair<int, int> i[] = {{0, 1}, {1, 2}};
2509
2510 absl::btree_map<std::vector<void *>, int> m1{std::begin(i), std::end(i)};
2511 EXPECT_THAT(m1,
2512 ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));
2513
2514 absl::btree_map<std::vector<void *>, int> m2;
2515 m2.insert(std::begin(i), std::end(i));
2516 EXPECT_THAT(m2,
2517 ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));
2518 }
2519
TEST(Btree,HeterogeneousTryEmplace)2520 TEST(Btree, HeterogeneousTryEmplace) {
2521 absl::btree_map<std::string, int> m;
2522 std::string s = "key";
2523 absl::string_view sv = s;
2524 m.try_emplace(sv, 1);
2525 EXPECT_EQ(m[s], 1);
2526
2527 m.try_emplace(m.end(), sv, 2);
2528 EXPECT_EQ(m[s], 1);
2529 }
2530
TEST(Btree,HeterogeneousOperatorMapped)2531 TEST(Btree, HeterogeneousOperatorMapped) {
2532 absl::btree_map<std::string, int> m;
2533 std::string s = "key";
2534 absl::string_view sv = s;
2535 m[sv] = 1;
2536 EXPECT_EQ(m[s], 1);
2537
2538 m[sv] = 2;
2539 EXPECT_EQ(m[s], 2);
2540 }
2541
TEST(Btree,HeterogeneousInsertOrAssign)2542 TEST(Btree, HeterogeneousInsertOrAssign) {
2543 absl::btree_map<std::string, int> m;
2544 std::string s = "key";
2545 absl::string_view sv = s;
2546 m.insert_or_assign(sv, 1);
2547 EXPECT_EQ(m[s], 1);
2548
2549 m.insert_or_assign(m.end(), sv, 2);
2550 EXPECT_EQ(m[s], 2);
2551 }
2552 #endif
2553
2554 // This test requires std::launder for mutable key access in node handles.
2555 #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
TEST(Btree,NodeHandleMutableKeyAccess)2556 TEST(Btree, NodeHandleMutableKeyAccess) {
2557 {
2558 absl::btree_map<std::string, std::string> map;
2559
2560 map["key1"] = "mapped";
2561
2562 auto nh = map.extract(map.begin());
2563 nh.key().resize(3);
2564 map.insert(std::move(nh));
2565
2566 EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
2567 }
2568 // Also for multimap.
2569 {
2570 absl::btree_multimap<std::string, std::string> map;
2571
2572 map.emplace("key1", "mapped");
2573
2574 auto nh = map.extract(map.begin());
2575 nh.key().resize(3);
2576 map.insert(std::move(nh));
2577
2578 EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
2579 }
2580 }
2581 #endif
2582
2583 struct MultiKey {
2584 int i1;
2585 int i2;
2586 };
2587
2588 struct MultiKeyComp {
2589 using is_transparent = void;
operator ()absl::container_internal::__anonc80c217f0311::MultiKeyComp2590 bool operator()(const MultiKey a, const MultiKey b) const {
2591 if (a.i1 != b.i1) return a.i1 < b.i1;
2592 return a.i2 < b.i2;
2593 }
operator ()absl::container_internal::__anonc80c217f0311::MultiKeyComp2594 bool operator()(const int a, const MultiKey b) const { return a < b.i1; }
operator ()absl::container_internal::__anonc80c217f0311::MultiKeyComp2595 bool operator()(const MultiKey a, const int b) const { return a.i1 < b; }
2596 };
2597
2598 // Test that when there's a heterogeneous comparator that behaves differently
2599 // for some heterogeneous operators, we get equal_range() right.
TEST(Btree,MultiKeyEqualRange)2600 TEST(Btree, MultiKeyEqualRange) {
2601 absl::btree_set<MultiKey, MultiKeyComp> set;
2602
2603 for (int i = 0; i < 100; ++i) {
2604 for (int j = 0; j < 100; ++j) {
2605 set.insert({i, j});
2606 }
2607 }
2608
2609 for (int i = 0; i < 100; ++i) {
2610 auto equal_range = set.equal_range(i);
2611 EXPECT_EQ(equal_range.first->i1, i);
2612 EXPECT_EQ(equal_range.first->i2, 0);
2613 EXPECT_EQ(std::distance(equal_range.first, equal_range.second), 100) << i;
2614 }
2615 }
2616
2617 } // namespace
2618 } // namespace container_internal
2619 ABSL_NAMESPACE_END
2620 } // namespace absl
2621