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