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