15 #include "absl/container/btree_test.h"
27 #include <type_traits>
30 #include "gmock/gmock.h"
31 #include "gtest/gtest.h"
32 #include "absl/base/internal/raw_logging.h"
33 #include "absl/base/macros.h"
34 #include "absl/container/btree_map.h"
35 #include "absl/container/btree_set.h"
36 #include "absl/container/internal/counting_allocator.h"
37 #include "absl/container/internal/test_instance_tracker.h"
38 #include "absl/flags/flag.h"
39 #include "absl/hash/hash_testing.h"
40 #include "absl/memory/memory.h"
41 #include "absl/meta/type_traits.h"
42 #include "absl/strings/str_cat.h"
43 #include "absl/strings/str_split.h"
44 #include "absl/strings/string_view.h"
45 #include "absl/types/compare.h"
51 namespace container_internal {
54 using ::absl::test_internal::CopyableMovableInstance;
55 using ::absl::test_internal::InstanceTracker;
56 using ::absl::test_internal::MovableOnlyInstance;
64 template <
typename T,
typename U>
65 void CheckPairEquals(
const T &x,
const U &
y) {
69 template <
typename T,
typename U,
typename V,
typename W>
70 void CheckPairEquals(
const std::pair<T, U> &x,
const std::pair<V, W> &
y) {
71 CheckPairEquals(
x.first,
y.first);
72 CheckPairEquals(
x.second,
y.second);
80 template <
typename TreeType,
typename CheckerType>
86 using pointer =
typename TreeType::pointer;
101 template <
typename InputIterator>
114 template <
typename IterType,
typename CheckerIterType>
115 IterType
iter_check(IterType tree_iter, CheckerIterType checker_iter)
const {
116 if (tree_iter ==
tree_.end()) {
118 "Checker iterator not at end.");
120 CheckPairEquals(*tree_iter, *checker_iter);
124 template <
typename IterType,
typename CheckerIterType>
125 IterType
riter_check(IterType tree_iter, CheckerIterType checker_iter)
const {
126 if (tree_iter ==
tree_.rend()) {
128 "Checker iterator not at rend.");
130 CheckPairEquals(*tree_iter, *checker_iter);
167 std::pair<typename CheckerType::iterator, typename CheckerType::iterator>
169 std::pair<iterator, iterator> tree_res =
tree_.equal_range(
key);
170 iter_check(tree_res.first, checker_res.first);
171 iter_check(tree_res.second, checker_res.second);
176 std::pair<
typename CheckerType::const_iterator,
177 typename CheckerType::const_iterator>
179 std::pair<const_iterator, const_iterator> tree_res =
tree_.equal_range(
key);
180 iter_check(tree_res.first, checker_res.first);
181 iter_check(tree_res.second, checker_res.second);
221 auto checker_next = checker_iter;
248 const auto checker_ret =
checker_.erase(checker_begin, checker_end);
251 std::distance(
tree_.begin(), tree_ret));
270 auto checker_iter =
checker_.begin();
272 for (; tree_iter !=
tree_.end(); ++tree_iter, ++checker_iter) {
273 CheckPairEquals(*tree_iter, *checker_iter);
277 for (
int n =
tree_.size() - 1;
n >= 0; --
n) {
286 auto checker_riter =
checker_.rbegin();
288 for (; tree_riter !=
tree_.rend(); ++tree_riter, ++checker_riter) {
289 CheckPairEquals(*tree_riter, *checker_riter);
293 for (
int n =
tree_.size() - 1;
n >= 0; --
n) {
311 return tree_.empty();
323 template <
typename TreeType,
typename CheckerType>
324 class unique_checker :
public base_checker<TreeType, CheckerType> {
332 unique_checker() : super_type() {}
333 unique_checker(
const unique_checker &other) : super_type(other) {}
334 template <
class InputIterator>
335 unique_checker(InputIterator
b, InputIterator
e) : super_type(
b,
e) {}
336 unique_checker &operator=(
const unique_checker &) =
default;
341 std::pair<typename CheckerType::iterator, bool> checker_res =
342 this->checker_.insert(
v);
343 std::pair<iterator, bool> tree_res = this->
tree_.insert(v);
344 CheckPairEquals(*tree_res.first, *checker_res.first);
345 EXPECT_EQ(tree_res.second, checker_res.second);
352 std::pair<typename CheckerType::iterator, bool> checker_res =
353 this->checker_.insert(
v);
355 CheckPairEquals(*tree_res, *checker_res.first);
360 template <
typename InputIterator>
361 void insert(InputIterator
b, InputIterator
e) {
362 for (;
b !=
e; ++
b) {
371 template <
typename TreeType,
typename CheckerType>
372 class multi_checker :
public base_checker<TreeType, CheckerType> {
373 using super_type = base_checker<TreeType, CheckerType>;
380 multi_checker() : super_type() {}
381 multi_checker(
const multi_checker &other) : super_type(other) {}
382 template <
class InputIterator>
383 multi_checker(InputIterator
b, InputIterator e) : super_type(
b,
e) {}
384 multi_checker &operator=(
const multi_checker &) =
default;
389 auto checker_res = this->checker_.insert(
v);
391 CheckPairEquals(*tree_res, *checker_res);
398 auto checker_res = this->checker_.insert(
v);
400 CheckPairEquals(*tree_res, *checker_res);
405 template <
typename InputIterator>
406 void insert(InputIterator
b, InputIterator e) {
407 for (;
b !=
e; ++
b) {
413 template <
typename T,
typename V>
418 const T &const_b = *
b;
421 for (
int i = 0;
i <
values.size(); ++
i) {
422 mutable_b.insert(
values[i]);
423 mutable_b.value_check(
values[i]);
431 EXPECT_EQ(b_copy.size(), const_b.size());
432 for (
int i = 0;
i <
values.size(); ++
i) {
433 CheckPairEquals(*b_copy.find(key_of_value(
values[i])),
values[i]);
437 T b_range(const_b.begin(), const_b.end());
438 EXPECT_EQ(b_range.size(), const_b.size());
439 for (
int i = 0;
i <
values.size(); ++
i) {
440 CheckPairEquals(*b_range.find(key_of_value(
values[i])),
values[i]);
444 b_range.insert(b_copy.begin(), b_copy.end());
449 b_range.insert(b_copy.begin(), b_copy.end());
450 EXPECT_EQ(b_range.size(), b_copy.size());
451 for (
int i = 0;
i <
values.size(); ++
i) {
452 CheckPairEquals(*b_range.find(key_of_value(
values[i])),
values[i]);
456 b_range.operator=(b_range);
457 EXPECT_EQ(b_range.size(), b_copy.size());
462 EXPECT_EQ(b_range.size(), b_copy.size());
466 b_range.swap(b_copy);
468 EXPECT_EQ(b_range.size(), const_b.size());
469 for (
int i = 0;
i <
values.size(); ++
i) {
470 CheckPairEquals(*b_range.find(key_of_value(
values[i])),
values[i]);
472 b_range.swap(b_copy);
475 swap(b_range, b_copy);
477 EXPECT_EQ(b_range.size(), const_b.size());
478 for (
int i = 0;
i <
values.size(); ++
i) {
479 CheckPairEquals(*b_range.find(key_of_value(
values[i])),
values[i]);
481 swap(b_range, b_copy);
484 for (
int i = 0;
i <
values.size(); ++
i) {
485 mutable_b.erase(key_of_value(
values[i]));
495 for (
int i = 0;
i <
values.size(); ++
i) {
496 mutable_b.erase(mutable_b.find(key_of_value(
values[i])));
503 for (
int i = 0;
i <
values.size();
i++) {
504 mutable_b.insert(mutable_b.upper_bound(key_of_value(
values[i])),
values[i]);
510 mutable_b.erase(mutable_b.begin(), mutable_b.end());
516 typename T::iterator mutable_iter_end = mutable_b.begin();
517 for (
int i = 0;
i <
values.size() / 2; ++
i) ++mutable_iter_end;
518 mutable_b.erase(mutable_b.begin(), mutable_iter_end);
524 typename T::iterator mutable_iter_begin = mutable_b.begin();
525 for (
int i = 0;
i <
values.size() / 2; ++
i) ++mutable_iter_begin;
526 mutable_b.erase(mutable_iter_begin, mutable_b.end());
532 mutable_iter_begin = mutable_b.begin();
533 for (
int i = 0;
i <
values.size() / 4; ++
i) ++mutable_iter_begin;
534 mutable_iter_end = mutable_iter_begin;
535 for (
int i = 0;
i <
values.size() / 4; ++
i) ++mutable_iter_end;
536 mutable_b.erase(mutable_iter_begin, mutable_iter_end);
543 template <
typename T>
549 const T &const_b = mutable_b;
553 mutable_b.insert(
value);
559 EXPECT_EQ(const_b.upper_bound(key_of_value(
value)), const_b.end());
563 typename T::iterator mutable_iter(mutable_b.begin());
564 EXPECT_EQ(mutable_iter, const_b.begin());
566 EXPECT_EQ(const_b.begin(), mutable_iter);
568 typename T::reverse_iterator mutable_riter(mutable_b.rbegin());
569 EXPECT_EQ(mutable_riter, const_b.rbegin());
570 EXPECT_NE(mutable_riter, const_b.rend());
571 EXPECT_EQ(const_b.rbegin(), mutable_riter);
572 EXPECT_NE(const_b.rend(), mutable_riter);
575 typename T::const_iterator const_iter(mutable_iter);
576 EXPECT_EQ(const_iter, mutable_b.begin());
578 EXPECT_EQ(mutable_b.begin(), const_iter);
580 typename T::const_reverse_iterator const_riter(mutable_riter);
581 EXPECT_EQ(const_riter, mutable_b.rbegin());
582 EXPECT_NE(const_riter, mutable_b.rend());
583 EXPECT_EQ(mutable_b.rbegin(), const_riter);
584 EXPECT_NE(mutable_b.rend(), const_riter);
595 template <
typename T,
typename C>
600 const std::vector<V> random_values = GenerateValuesWithSeed<V>(
607 std::vector<V> sorted_values(random_values);
608 std::sort(sorted_values.begin(), sorted_values.end());
612 std::reverse(sorted_values.begin(), sorted_values.end());
619 template <
typename T,
typename C>
620 void BtreeMultiTest() {
624 const std::vector<V> random_values = GenerateValuesWithSeed<V>(
631 std::vector<V> sorted_values(random_values);
632 std::sort(sorted_values.begin(), sorted_values.end());
636 std::reverse(sorted_values.begin(), sorted_values.end());
643 std::vector<V> duplicate_values(random_values);
644 duplicate_values.insert(duplicate_values.end(), random_values.begin(),
645 random_values.end());
649 std::vector<V> identical_values(100);
650 std::fill(identical_values.begin(), identical_values.end(),
655 template <
typename T>
656 struct PropagatingCountingAlloc :
public CountingAllocator<T> {
661 using Base = CountingAllocator<T>;
664 template <
typename U>
665 explicit PropagatingCountingAlloc(
const PropagatingCountingAlloc<U> &other)
666 : Base(other.bytes_used_) {}
668 template <
typename U>
670 using other = PropagatingCountingAlloc<U>;
674 template <
typename T>
675 void BtreeAllocatorTest() {
678 int64_t bytes1 = 0, bytes2 = 0;
679 PropagatingCountingAlloc<T> allocator1(&bytes1);
680 PropagatingCountingAlloc<T> allocator2(&bytes2);
681 Generator<value_type> generator(1000);
685 auto unused1 = allocator1.allocate(1);
686 auto unused2 = allocator2.allocate(1);
690 T b1(
typename T::key_compare(), allocator1);
691 T b2(
typename T::key_compare(), allocator2);
693 int64_t original_bytes1 = bytes1;
694 b1.insert(generator(0));
703 for (
int i = 1;
i < 1000;
i++) {
704 b1.insert(generator(i));
713 T b1(
typename T::key_compare(), allocator1);
714 T b2(
typename T::key_compare(), allocator2);
716 int64_t original_bytes1 = bytes1;
717 b1.insert(generator(0));
725 for (
int i = 1;
i < 1000;
i++) {
726 b1.insert(generator(i));
735 T b1(
typename T::key_compare(), allocator1);
736 T b2(
typename T::key_compare(), allocator2);
738 int64_t original_bytes1 = bytes1;
739 b1.insert(generator(0));
748 for (
int i = 1;
i < 1000;
i++) {
749 b1.insert(generator(i));
756 allocator1.deallocate(unused1, 1);
757 allocator2.deallocate(unused2, 1);
760 template <
typename T>
761 void BtreeMapTest() {
763 using mapped_type =
typename T::mapped_type;
765 mapped_type
m = Generator<mapped_type>(0)(0);
771 for (
int i = 0;
i < 1000;
i++) {
773 b[
v.first] =
v.second;
780 EXPECT_EQ(
b.begin()->first, Generator<value_type>(1000)(0).first);
781 EXPECT_EQ(
b.begin()->second, Generator<value_type>(1000)(0).second);
782 EXPECT_EQ(
b.rbegin()->first, Generator<value_type>(1000)(999).first);
783 EXPECT_EQ(
b.rbegin()->second, Generator<value_type>(1000)(999).second);
786 template <
typename T>
787 void BtreeMultiMapTest() {
788 using mapped_type =
typename T::mapped_type;
789 mapped_type
m = Generator<mapped_type>(0)(0);
793 template <
typename K,
int N = 256>
799 using CountingBtreeSet =
801 BtreeTest<BtreeSet, std::set<K>>();
802 BtreeAllocatorTest<CountingBtreeSet>();
805 template <
typename K,
int N = 256>
811 using CountingBtreeMap =
813 PropagatingCountingAlloc<std::pair<const K, K>>>;
814 BtreeTest<BtreeMap, std::map<K, K>>();
815 BtreeAllocatorTest<CountingBtreeMap>();
816 BtreeMapTest<BtreeMap>();
819 TEST(Btree, set_int32) { SetTest<int32_t>(); }
820 TEST(Btree, set_int64) { SetTest<int64_t>(); }
821 TEST(Btree, set_string) { SetTest<std::string>(); }
822 TEST(Btree, set_cord) { SetTest<absl::Cord>(); }
823 TEST(Btree, set_pair) { SetTest<std::pair<int, int>>(); }
824 TEST(Btree, map_int32) { MapTest<int32_t>(); }
825 TEST(Btree, map_int64) { MapTest<int64_t>(); }
826 TEST(Btree, map_string) { MapTest<std::string>(); }
827 TEST(Btree, map_cord) { MapTest<absl::Cord>(); }
828 TEST(Btree, map_pair) { MapTest<std::pair<int, int>>(); }
830 template <
typename K,
int N = 256>
831 void MultiSetTest() {
836 using CountingBtreeMSet =
838 BtreeMultiTest<BtreeMSet, std::multiset<K>>();
839 BtreeAllocatorTest<CountingBtreeMSet>();
842 template <
typename K,
int N = 256>
843 void MultiMapTest() {
848 using CountingBtreeMMap =
850 PropagatingCountingAlloc<std::pair<const K, K>>>;
851 BtreeMultiTest<BtreeMMap, std::multimap<K, K>>();
852 BtreeMultiMapTest<BtreeMMap>();
853 BtreeAllocatorTest<CountingBtreeMMap>();
856 TEST(Btree, multiset_int32) { MultiSetTest<int32_t>(); }
857 TEST(Btree, multiset_int64) { MultiSetTest<int64_t>(); }
858 TEST(Btree, multiset_string) { MultiSetTest<std::string>(); }
859 TEST(Btree, multiset_cord) { MultiSetTest<absl::Cord>(); }
860 TEST(Btree, multiset_pair) { MultiSetTest<std::pair<int, int>>(); }
861 TEST(Btree, multimap_int32) { MultiMapTest<int32_t>(); }
862 TEST(Btree, multimap_int64) { MultiMapTest<int64_t>(); }
863 TEST(Btree, multimap_string) { MultiMapTest<std::string>(); }
864 TEST(Btree, multimap_cord) { MultiMapTest<absl::Cord>(); }
865 TEST(Btree, multimap_pair) { MultiMapTest<std::pair<int, int>>(); }
867 struct CompareIntToString {
877 using is_transparent = void;
880 struct NonTransparentCompare {
881 template <
typename T,
typename U>
882 bool operator()(
const T &t,
const U &u)
const {
891 template <
typename T>
892 bool CanEraseWithEmptyBrace(
T t, decltype(
t.erase({})) *) {
896 template <
typename T>
897 bool CanEraseWithEmptyBrace(
T, ...) {
901 template <
typename T>
902 void TestHeterogeneous(
T table) {
903 auto lb =
table.lower_bound(
"3");
909 auto ub =
table.upper_bound(
"3");
915 auto er =
table.equal_range(
"3");
947 if (std::is_class<T>()) TestHeterogeneous<const T &>(
table);
950 TEST(Btree, HeterogeneousLookup) {
951 TestHeterogeneous(btree_set<std::string, CompareIntToString>{
"1",
"3",
"5"});
952 TestHeterogeneous(btree_map<std::string, int, CompareIntToString>{
953 {
"1", 1}, {
"3", 3}, {
"5", 5}});
955 btree_multiset<std::string, CompareIntToString>{
"1",
"3",
"5"});
956 TestHeterogeneous(btree_multimap<std::string, int, CompareIntToString>{
957 {
"1", 1}, {
"3", 3}, {
"5", 5}});
960 btree_map<std::string, int, CompareIntToString>
map{
961 {
"", -1}, {
"1", 1}, {
"3", 3}, {
"5", 5}};
965 const auto &cmap =
map;
971 TEST(Btree, NoHeterogeneousLookupWithoutAlias) {
983 using StringMultiSet =
990 EXPECT_TRUE(ms.begin() == ms.lower_bound(
"hello"));
997 TEST(Btree, DefaultTransparent) {
1001 btree_set<int>
s = {1};
1009 btree_set<std::string>
s = {
"A"};
1017 StringLike() =
default;
1019 StringLike(
const char *s) :
s_(
s) {
1023 bool operator<(
const StringLike &a)
const {
return s_ <
a.s_; }
1036 TEST(Btree, HeterogeneousLookupDoesntDegradePerformance) {
1039 for (
int i = 0;
i < 100; ++
i) {
1042 StringLike::clear_constructor_call_count();
1046 StringLike::clear_constructor_call_count();
1050 StringLike::clear_constructor_call_count();
1054 StringLike::clear_constructor_call_count();
1055 s.lower_bound(
"50");
1058 StringLike::clear_constructor_call_count();
1059 s.upper_bound(
"50");
1062 StringLike::clear_constructor_call_count();
1063 s.equal_range(
"50");
1066 StringLike::clear_constructor_call_count();
1073 struct SubstringLess {
1074 SubstringLess() =
delete;
1083 TEST(Btree, SwapKeyCompare) {
1085 SubstringSet s1(SubstringLess(1), SubstringSet::allocator_type());
1086 SubstringSet s2(SubstringLess(2), SubstringSet::allocator_type());
1105 TEST(Btree, UpperBoundRegression) {
1109 SubstringSet my_set(SubstringLess(3));
1110 my_set.insert(
"aab");
1111 my_set.insert(
"abb");
1121 TEST(Btree, Comparison) {
1122 const int kSetSize = 1201;
1124 for (
int i = 0;
i < kSetSize; ++
i) {
1139 my_set.
erase(kSetSize - 1);
1146 for (
int i = 0;
i < kSetSize; ++
i) {
1161 my_map_copy = my_map;
1162 my_map[
"hello"] = kSetSize;
1175 TEST(Btree, RangeCtorSanity) {
1176 std::vector<int> ivec;
1178 std::map<int, int> imap;
1179 imap.insert(std::make_pair(1, 2));
1195 template <
typename ValueType>
1200 false>>::SizeWithNSlots(target_values_per_node);
1204 template <
typename Btree>
1209 template <
typename Btree>
1211 return std::numeric_limits<
1215 template <
typename Btree>
1220 template <
typename Btree>
1222 return Btree::params_type::kEnableGenerations;
1232 template <
typename T>
1233 bool operator()(
T,
T)
const {
1241 struct CmpLin : Cmp {
1248 struct CmpBin : Cmp {
1252 template <
typename K,
typename C>
1253 static bool IsLinear() {
1254 return BtreeNodePeer::UsesLinearNodeSearch<absl::btree_map<K, int, C>>();
1258 TEST_F(BtreeMapTest, TestLinearSearchPreferredForKeyLinearViaAlias) {
1266 TEST_F(BtreeMapTest, LinearChoiceTree) {
1285 EXPECT_TRUE((IsLinear<
double, std::greater<double>>()));
1292 TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) {
1295 std::unique_ptr<std::string> &
v =
m[
"A"];
1297 v = absl::make_unique<std::string>(
"X");
1299 auto iter =
m.find(
"A");
1303 TEST(Btree, InitializerListConstructor) {
1317 auto range = mmap.equal_range(1);
1326 TEST(Btree, InitializerListInsert) {
1328 set.insert({
"a",
"b"});
1338 map.insert({{1, 5}, {2, 10}});
1340 map.insert({3, 15});
1346 mmap.insert({{1, 5}, {1, 10}});
1347 auto range = mmap.equal_range(1);
1356 template <
typename Compare,
typename Key>
1357 void AssertKeyCompareStringAdapted() {
1362 "key_compare_adapter should have string-adapted this comparator.");
1364 template <
typename Compare,
typename Key>
1365 void AssertKeyCompareNotStringAdapted() {
1370 "key_compare_adapter shouldn't have string-adapted this comparator.");
1373 TEST(Btree, KeyCompareAdapter) {
1374 AssertKeyCompareStringAdapted<std::less<std::string>,
std::string>();
1375 AssertKeyCompareStringAdapted<std::greater<std::string>,
std::string>();
1376 AssertKeyCompareStringAdapted<std::less<absl::string_view>,
1378 AssertKeyCompareStringAdapted<std::greater<absl::string_view>,
1380 AssertKeyCompareStringAdapted<std::less<absl::Cord>,
absl::Cord>();
1381 AssertKeyCompareStringAdapted<std::greater<absl::Cord>,
absl::Cord>();
1382 AssertKeyCompareNotStringAdapted<std::less<int>,
int>();
1383 AssertKeyCompareNotStringAdapted<std::greater<int>,
int>();
1386 TEST(Btree, RValueInsert) {
1390 set.insert(MovableOnlyInstance(1));
1391 set.insert(MovableOnlyInstance(3));
1392 MovableOnlyInstance two(2);
1394 auto it =
set.find(MovableOnlyInstance(2));
1400 MovableOnlyInstance zero(0);
1401 MovableOnlyInstance zero2(0);
1407 std::pair<const int, MovableOnlyInstance> p1 = {1, MovableOnlyInstance(5)};
1408 std::pair<const int, MovableOnlyInstance> p2 = {2, MovableOnlyInstance(10)};
1409 std::pair<const int, MovableOnlyInstance> p3 = {3, MovableOnlyInstance(15)};
1417 std::pair<const int, MovableOnlyInstance> p4 = {1, MovableOnlyInstance(5)};
1418 std::pair<const int, MovableOnlyInstance> p5 = {1, MovableOnlyInstance(10)};
1420 mmap.insert(mmap.find(1),
std::move(p5));
1421 auto range = mmap.equal_range(1);
1422 auto it1 =
range.first;
1433 template <
typename Cmp>
1434 struct CheckedCompareOptedOutCmp : Cmp, BtreeTestOnlyCheckedCompareOptOutBase {
1436 CheckedCompareOptedOutCmp() {}
1442 template <
typename Key,
int TargetValuesPerNode,
typename Cmp = std::less<Key>>
1444 :
public btree_set_container<btree<
1445 set_params<Key, CheckedCompareOptedOutCmp<Cmp>, std::allocator<Key>,
1446 BtreeNodePeer::GetTargetNodeSize<Key>(TargetValuesPerNode),
1448 using Base =
typename SizedBtreeSet::btree_set_container;
1455 template <
typename Set>
1456 void ExpectOperationCounts(
const int expected_moves,
1457 const int expected_comparisons,
1458 const std::vector<int> &
values,
1460 for (
const int v :
values)
set->insert(MovableOnlyInstance(
v));
1466 tracker->ResetCopiesMovesSwaps();
1471 TEST(Btree, MovesComparisonsCopiesSwapsTracking) {
1474 SizedBtreeSet<MovableOnlyInstance, 4> set4;
1477 SizedBtreeSet<MovableOnlyInstance, 61> set61;
1478 SizedBtreeSet<MovableOnlyInstance, 100> set100;
1482 std::vector<int>
values =
1483 GenerateValuesWithSeed<int>(10000, 1 << 22, 23);
1488 if (
sizeof(
void *) == 8) {
1496 ExpectOperationCounts(56540, 134212,
values, &
tracker, &set4);
1497 ExpectOperationCounts(386718, 129807,
values, &
tracker, &set61);
1498 ExpectOperationCounts(586761, 130310,
values, &
tracker, &set100);
1502 ExpectOperationCounts(24972, 85563,
values, &
tracker, &set4);
1503 ExpectOperationCounts(20208, 87757,
values, &
tracker, &set61);
1504 ExpectOperationCounts(20124, 96583,
values, &
tracker, &set100);
1508 ExpectOperationCounts(54949, 127531,
values, &
tracker, &set4);
1509 ExpectOperationCounts(338813, 118266,
values, &
tracker, &set61);
1510 ExpectOperationCounts(534529, 125279,
values, &
tracker, &set100);
1513 struct MovableOnlyInstanceThreeWayCompare {
1515 const MovableOnlyInstance &
b)
const {
1516 return a.compare(
b);
1522 TEST(Btree, MovesComparisonsCopiesSwapsTrackingThreeWayCompare) {
1525 SizedBtreeSet<MovableOnlyInstance, 4,
1526 MovableOnlyInstanceThreeWayCompare>
1530 SizedBtreeSet<MovableOnlyInstance, 61,
1531 MovableOnlyInstanceThreeWayCompare>
1533 SizedBtreeSet<MovableOnlyInstance, 100,
1534 MovableOnlyInstanceThreeWayCompare>
1539 std::vector<int>
values =
1540 GenerateValuesWithSeed<int>(10000, 1 << 22, 23);
1545 if (
sizeof(
void *) == 8) {
1553 ExpectOperationCounts(56540, 124221,
values, &
tracker, &set4);
1554 ExpectOperationCounts(386718, 119816,
values, &
tracker, &set61);
1555 ExpectOperationCounts(586761, 120319,
values, &
tracker, &set100);
1559 ExpectOperationCounts(24972, 85563,
values, &
tracker, &set4);
1560 ExpectOperationCounts(20208, 87757,
values, &
tracker, &set61);
1561 ExpectOperationCounts(20124, 96583,
values, &
tracker, &set100);
1565 ExpectOperationCounts(54949, 117532,
values, &
tracker, &set4);
1566 ExpectOperationCounts(338813, 108267,
values, &
tracker, &set61);
1567 ExpectOperationCounts(534529, 115280,
values, &
tracker, &set100);
1570 struct NoDefaultCtor {
1572 explicit NoDefaultCtor(
int i) :
num(
i) {}
1574 friend bool operator<(
const NoDefaultCtor &a,
const NoDefaultCtor &
b) {
1575 return a.num <
b.num;
1579 TEST(Btree, BtreeMapCanHoldNoDefaultCtorTypes) {
1582 for (
int i = 1;
i <= 99; ++
i) {
1588 auto iter99 =
m.find(NoDefaultCtor(99));
1592 auto iter1 =
m.find(NoDefaultCtor(1));
1596 auto iter50 =
m.find(NoDefaultCtor(50));
1600 auto iter25 =
m.find(NoDefaultCtor(25));
1605 TEST(Btree, BtreeMultimapCanHoldNoDefaultCtorTypes) {
1608 for (
int i = 1;
i <= 99; ++
i) {
1610 m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i));
1613 auto iter99 =
m.find(NoDefaultCtor(99));
1617 auto iter1 =
m.find(NoDefaultCtor(1));
1621 auto iter50 =
m.find(NoDefaultCtor(50));
1625 auto iter25 =
m.find(NoDefaultCtor(25));
1630 TEST(Btree, MapAt) {
1638 #ifdef ABSL_HAVE_EXCEPTIONS
1645 TEST(Btree, BtreeMultisetEmplace) {
1646 const int value_to_insert = 123456;
1648 auto iter =
s.emplace(value_to_insert);
1651 auto iter2 =
s.emplace(value_to_insert);
1655 auto result =
s.equal_range(value_to_insert);
1659 TEST(Btree, BtreeMultisetEmplaceHint) {
1660 const int value_to_insert = 123456;
1662 auto iter =
s.emplace(value_to_insert);
1665 auto emplace_iter =
s.emplace_hint(
iter, value_to_insert);
1668 EXPECT_EQ(*emplace_iter, value_to_insert);
1671 TEST(Btree, BtreeMultimapEmplace) {
1672 const int key_to_insert = 123456;
1673 const char value0[] =
"a";
1675 auto iter =
s.emplace(key_to_insert, value0);
1679 const char value1[] =
"b";
1680 auto iter2 =
s.emplace(key_to_insert, value1);
1685 auto result =
s.equal_range(key_to_insert);
1689 TEST(Btree, BtreeMultimapEmplaceHint) {
1690 const int key_to_insert = 123456;
1691 const char value0[] =
"a";
1693 auto iter =
s.emplace(key_to_insert, value0);
1697 const char value1[] =
"b";
1698 auto emplace_iter =
s.emplace_hint(
iter, key_to_insert, value1);
1701 EXPECT_EQ(emplace_iter->first, key_to_insert);
1702 EXPECT_EQ(emplace_iter->second, value1);
1705 TEST(Btree, ConstIteratorAccessors) {
1707 for (
int i = 0;
i < 100; ++
i) {
1711 auto it =
set.cbegin();
1712 auto r_it =
set.crbegin();
1713 for (
int i = 0;
i < 100; ++
i, ++
it, ++r_it) {
1721 TEST(Btree, StrSplitCompatible) {
1728 TEST(Btree, KeyComp) {
1748 TEST(Btree, ValueComp) {
1755 EXPECT_TRUE(m1.value_comp()(std::make_pair(1, 0), std::make_pair(2, 0)));
1756 EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(2, 0)));
1757 EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(1, 0)));
1763 EXPECT_TRUE(m2.value_comp()(std::make_pair(
"a", 0), std::make_pair(
"b", 0)));
1764 EXPECT_FALSE(m2.value_comp()(std::make_pair(
"b", 0), std::make_pair(
"b", 0)));
1765 EXPECT_FALSE(m2.value_comp()(std::make_pair(
"b", 0), std::make_pair(
"a", 0)));
1770 TEST(Btree, MapValueCompProtected) {
1771 struct key_compare {
1772 bool operator()(
int l,
int r)
const {
return l <
r; }
1776 struct value_comp_child :
public value_compare {
1777 explicit value_comp_child(key_compare kc) : value_compare(kc) {}
1778 int GetId()
const {
return comp.id; }
1780 value_comp_child
c(key_compare{10});
1784 TEST(Btree, DefaultConstruction) {
1796 TEST(Btree, SwissTableHashable) {
1797 static constexpr
int kValues = 10000;
1798 std::vector<int>
values(kValues);
1800 std::vector<std::pair<int, int>> map_values;
1801 for (
int v :
values) map_values.emplace_back(
v, -
v);
1836 map{{1, 0}, {2, 1}},
1837 map(map_values.begin(), map_values.end()),
1838 map(map_values.rbegin(), map_values.rend()),
1846 mmap{{1, 0}, {1, 1}},
1847 mmap{{1, 1}, {1, 0}},
1850 mmap{{1, 0}, {2, 1}},
1851 mmap(map_values.begin(), map_values.end()),
1852 mmap(map_values.rbegin(), map_values.rend()),
1856 TEST(Btree, ComparableSet) {
1867 TEST(Btree, ComparableSetsDifferentLength) {
1876 TEST(Btree, ComparableMultiset) {
1887 TEST(Btree, ComparableMap) {
1898 TEST(Btree, ComparableMultimap) {
1909 TEST(Btree, ComparableSetWithCustomComparator) {
1925 TEST(Btree, EraseReturnsIterator) {
1927 auto result_it =
set.erase(
set.begin(),
set.find(3));
1929 result_it =
set.erase(
set.find(5));
1933 TEST(Btree, ExtractAndInsertNodeHandleSet) {
1955 template <
typename Set>
1956 void TestExtractWithTrackingForSet() {
1961 const size_t kSize = 1000;
1962 while (
s.size() < kSize) {
1963 s.insert(MovableOnlyInstance(
s.size()));
1965 for (
int i = 0;
i <
kSize; ++
i) {
1967 auto nh =
s.extract(MovableOnlyInstance(i));
1975 auto it =
s.find(MovableOnlyInstance(i));
1987 template <
typename Map>
1988 void TestExtractWithTrackingForMap() {
1993 const size_t kSize = 1000;
1994 while (
m.size() < kSize) {
1996 {CopyableMovableInstance(
m.size()), MovableOnlyInstance(
m.size())});
1998 for (
int i = 0;
i <
kSize; ++
i) {
2000 auto nh =
m.extract(CopyableMovableInstance(i));
2009 auto it =
m.find(CopyableMovableInstance(i));
2022 TEST(Btree, ExtractTracking) {
2023 TestExtractWithTrackingForSet<absl::btree_set<MovableOnlyInstance>>();
2024 TestExtractWithTrackingForSet<absl::btree_multiset<MovableOnlyInstance>>();
2025 TestExtractWithTrackingForMap<
2027 TestExtractWithTrackingForMap<
2031 TEST(Btree, ExtractAndInsertNodeHandleMultiSet) {
2048 TEST(Btree, ExtractAndInsertNodeHandleMap) {
2050 auto nh = src1.extract(src1.find(3));
2061 nh = src2.extract(src2.find(3));
2072 TEST(Btree, ExtractAndInsertNodeHandleMultiMap) {
2074 auto nh = src1.extract(src1.find(3));
2082 nh = src2.extract(src2.find(3));
2089 TEST(Btree, ExtractMultiMapEquivalentKeys) {
2092 for (
int i = 0;
i < 100; ++
i) {
2093 for (
int j = 0;
j < 100; ++
j) {
2098 for (
int i = 0;
i < 100; ++
i) {
2100 auto node_handle =
map.extract(
key);
2105 for (
int i = 0;
i < 100; ++
i) {
2107 auto node_handle =
map.extract(
key);
2115 struct InsertMultiHintData {
2118 bool operator==(
const InsertMultiHintData other)
const {
2119 return key == other.key &&
not_key == other.not_key;
2123 struct InsertMultiHintDataKeyCompare {
2124 using is_transparent = void;
2125 bool operator()(
const InsertMultiHintData a,
2126 const InsertMultiHintData
b)
const {
2127 return a.key <
b.key;
2129 bool operator()(
const int a,
const InsertMultiHintData
b)
const {
2132 bool operator()(
const InsertMultiHintData a,
const int b)
const {
2137 TEST(Btree, InsertHintNodeHandle) {
2158 {{1, 2}, {3, 4}, {3, 5}};
2160 EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 4}));
2162 other = {{3, 1}, {3, 2}, {3, 3}};
2165 other,
ElementsAre(InsertMultiHintData{3, 1}, InsertMultiHintData{3, 2},
2166 InsertMultiHintData{3, 4}, InsertMultiHintData{3, 3}));
2170 EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 5}));
2173 ElementsAre(InsertMultiHintData{3, 5}, InsertMultiHintData{3, 1},
2174 InsertMultiHintData{3, 2}, InsertMultiHintData{3, 4},
2175 InsertMultiHintData{3, 3}));
2179 struct IntCompareToCmp {
2181 if (a <
b)
return absl::weak_ordering::less;
2182 if (a >
b)
return absl::weak_ordering::greater;
2183 return absl::weak_ordering::equivalent;
2187 TEST(Btree, MergeIntoUniqueContainers) {
2200 TEST(Btree, MergeIntoUniqueContainersWithCompareTo) {
2213 TEST(Btree, MergeIntoMultiContainers) {
2226 TEST(Btree, MergeIntoMultiContainersWithCompareTo) {
2239 TEST(Btree, MergeIntoMultiMapsWithDifferentComparators) {
2242 {5, 5}, {4, 1}, {4, 4}, {3, 2}};
2254 TEST(Btree, MergeIntoSetMovableOnly) {
2256 src.
insert(MovableOnlyInstance(1));
2258 dst1.
insert(MovableOnlyInstance(2));
2279 struct KeyCompareToWeakOrdering {
2280 template <
typename T>
2282 return a <
b ? absl::weak_ordering::less
2283 :
a ==
b ? absl::weak_ordering::equivalent
2284 : absl::weak_ordering::greater;
2288 struct KeyCompareToStrongOrdering {
2289 template <
typename T>
2291 return a <
b ? absl::strong_ordering::less
2293 : absl::strong_ordering::greater;
2297 TEST(Btree, UserProvidedKeyCompareToComparators) {
2307 TEST(Btree, TryEmplaceBasicTest) {
2311 m.try_emplace(1,
"one");
2316 m.try_emplace(
key, 3,
'a');
2321 {1,
"one"}, {2,
"two"}, {42,
"aaa"}}));
2324 TEST(Btree, TryEmplaceWithHintWorks) {
2331 using Cmp = decltype(
cmp);
2336 for (
int i = 0;
i < 128; ++
i) {
2342 m.emplace(127, 127);
2347 auto it =
m.try_emplace(
m.begin(), -1, -1);
2354 std::pair<int, int> pair1024 = {1024, 1024};
2355 it =
m.try_emplace(
m.end(), pair1024.first, pair1024.second);
2362 it =
m.try_emplace(
m.end(), 16, 17);
2369 it =
m.try_emplace(
it, 16, 17);
2376 auto hint =
m.find(3);
2379 m.try_emplace(hint, 2, 2);
2386 TEST(Btree, TryEmplaceWithBadHint) {
2390 auto it =
m.try_emplace(
m.begin(), 2, 2);
2393 std::vector<std::pair<int, int>>{{1, 1}, {2, 2}, {9, 9}}));
2396 it =
m.try_emplace(++(++
m.begin()), 0, 0);
2399 {0, 0}, {1, 1}, {2, 2}, {9, 9}}));
2402 TEST(Btree, TryEmplaceMaintainsSortedOrder) {
2404 std::pair<int, std::string> pair5 = {5,
"five"};
2407 m.try_emplace(10,
"ten");
2408 m.try_emplace(pair5.first, pair5.second);
2413 m.try_emplace(int100,
"hundred");
2414 m.try_emplace(1,
"one");
2419 TEST(Btree, TryEmplaceWithHintAndNoValueArgsWorks) {
2421 m.try_emplace(
m.end(), 1);
2425 TEST(Btree, TryEmplaceWithHintAndMultipleValueArgsWorks) {
2427 m.try_emplace(
m.end(), 1, 10,
'a');
2431 TEST(Btree, MoveAssignmentAllocatorPropagation) {
2434 int64_t bytes1 = 0, bytes2 = 0;
2435 PropagatingCountingAlloc<MovableOnlyInstance> allocator1(&bytes1);
2436 PropagatingCountingAlloc<MovableOnlyInstance> allocator2(&bytes2);
2437 std::less<MovableOnlyInstance>
cmp;
2442 PropagatingCountingAlloc<MovableOnlyInstance>>
2443 set1(
cmp, allocator1), set2(
cmp, allocator2);
2445 for (
int i = 0;
i < 100; ++
i) set1.insert(MovableOnlyInstance(i));
2447 tracker.ResetCopiesMovesSwaps();
2454 CountingAllocator<MovableOnlyInstance>>
2455 set1(
cmp, allocator1), set2(
cmp, allocator1);
2457 for (
int i = 0;
i < 100; ++
i) set1.insert(MovableOnlyInstance(i));
2459 tracker.ResetCopiesMovesSwaps();
2466 CountingAllocator<MovableOnlyInstance>>
2467 set1(
cmp, allocator1), set2(
cmp, allocator2);
2469 for (
int i = 0;
i < 100; ++
i) set1.insert(MovableOnlyInstance(i));
2471 tracker.ResetCopiesMovesSwaps();
2477 TEST(Btree, EmptyTree) {
2484 bool IsEven(
int k) {
return k % 2 == 0; }
2501 erase_if(
m, [](std::pair<const int, int> kv) {
return kv.first > 3; }),
2507 {6, 6}, {6, 7}, {100, 6}};
2510 [](std::pair<const int, int> kv) {
return kv.second == 6; }),
2518 for (
int i = 0;
i < 1000; ++
i)
s.insert(2 * i);
2531 for (
int i = 0;
i < 1000; ++
i)
s.insert(i);
2534 [&pred_calls](
int k) {
2544 TEST(Btree, InsertOrAssign) {
2548 auto ret =
m.insert_or_assign(4, 4);
2551 ret =
m.insert_or_assign(3, 100);
2555 auto hint_ret =
m.insert_or_assign(
ret.first, 3, 200);
2557 hint_ret =
m.insert_or_assign(
m.find(1), 0, 1);
2560 hint_ret =
m.insert_or_assign(
m.end(), -1, 1);
2567 TEST(Btree, InsertOrAssignMovableOnly) {
2571 auto ret =
m.insert_or_assign(4, MovableOnlyInstance(4));
2574 ret =
m.insert_or_assign(4, MovableOnlyInstance(100));
2578 auto hint_ret =
m.insert_or_assign(
ret.first, 3, MovableOnlyInstance(200));
2584 TEST(Btree, BitfieldArgument) {
2595 m.insert_or_assign(n, n);
2596 m.insert_or_assign(
m.end(), n, n);
2598 m.try_emplace(
m.end(), n);
2603 TEST(Btree, SetRangeConstructorAndInsertSupportExplicitConversionComparable) {
2615 struct ConstructorCounted {
2617 bool operator==(
int other)
const {
return i == other; }
2624 struct ConstructorCountedCompare {
2625 bool operator()(
int a,
const ConstructorCounted &
b)
const {
return a <
b.i; }
2626 bool operator()(
const ConstructorCounted &a,
int b)
const {
return a.i <
b; }
2627 bool operator()(
const ConstructorCounted &a,
2628 const ConstructorCounted &
b)
const {
2631 using is_transparent = void;
2635 SetRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
2636 const int i[] = {0, 1, 1};
2650 SetRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
2651 const int i[] = {0, 1};
2665 #if !defined(__GLIBCXX__) || \
2666 (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7)
2667 TEST(Btree, MapRangeConstructorAndInsertSupportExplicitConversionComparable) {
2668 const std::pair<absl::string_view, int>
names[] = {{
"n1", 1}, {
"n2", 2}};
2680 MapRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
2681 const std::pair<int, int>
i[] = {{0, 1}, {1, 2}, {1, 3}};
2695 MapRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
2696 const std::pair<int, int>
i[] = {{0, 1}, {1, 2}};
2708 TEST(Btree, HeterogeneousTryEmplace) {
2712 m.try_emplace(sv, 1);
2715 m.try_emplace(
m.end(), sv, 2);
2719 TEST(Btree, HeterogeneousOperatorMapped) {
2730 TEST(Btree, HeterogeneousInsertOrAssign) {
2734 m.insert_or_assign(sv, 1);
2737 m.insert_or_assign(
m.end(), sv, 2);
2743 #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
2744 TEST(Btree, NodeHandleMutableKeyAccess) {
2748 map[
"key1"] =
"mapped";
2750 auto nh =
map.extract(
map.begin());
2760 map.emplace(
"key1",
"mapped");
2762 auto nh =
map.extract(
map.begin());
2776 bool operator==(
const MultiKey a,
const MultiKey
b) {
2777 return a.i1 ==
b.i1 &&
a.i2 ==
b.i2;
2782 struct MultiKeyComp {
2783 using is_transparent = void;
2784 bool operator()(
const MultiKey a,
const MultiKey
b)
const {
2785 if (
a.i1 !=
b.i1)
return a.i1 <
b.i1;
2788 bool operator()(
const int a,
const MultiKey
b)
const {
return a <
b.i1; }
2789 bool operator()(
const MultiKey a,
const int b)
const {
return a.i1 <
b; }
2794 struct MultiKeyThreeWayComp {
2795 using is_transparent = void;
2797 if (
a.i1 <
b.i1)
return absl::weak_ordering::less;
2798 if (
a.i1 >
b.i1)
return absl::weak_ordering::greater;
2799 if (
a.i2 <
b.i2)
return absl::weak_ordering::less;
2800 if (
a.i2 >
b.i2)
return absl::weak_ordering::greater;
2801 return absl::weak_ordering::equivalent;
2804 if (a <
b.i1)
return absl::weak_ordering::less;
2805 if (a >
b.i1)
return absl::weak_ordering::greater;
2806 return absl::weak_ordering::equivalent;
2809 if (
a.i1 <
b)
return absl::weak_ordering::less;
2810 if (
a.i1 >
b)
return absl::weak_ordering::greater;
2811 return absl::weak_ordering::equivalent;
2815 template <
typename Compare>
2822 for (
int i = 0;
i < 100; ++
i) {
2823 for (
int j = 0;
j < 100; ++
j) {
2828 for (
int i = 0;
i < 100; ++
i) {
2829 auto equal_range =
set.equal_range(i);
2832 EXPECT_EQ(std::distance(equal_range.first, equal_range.second), 100) <<
i;
2838 for (
int i = 0;
i < 100; ++
i) {
2839 for (
int j = 0;
j < 100; ++
j) {
2844 for (
int i = 0;
i < 100; ++
i) {
2845 auto node_handle =
set.extract(i);
2850 for (
int i = 0;
i < 100; ++
i) {
2851 auto node_handle =
set.extract(i);
2859 {1, 1}, {2, 1}, {2, 2}, {3, 1}};
2866 {1, 1}, {2, 1}, {2, 2}, {3, 1}};
2870 TEST(Btree, AllocConstructor) {
2871 using Alloc = CountingAllocator<int>;
2877 set.insert({1, 2, 3});
2883 TEST(Btree, AllocInitializerListConstructor) {
2884 using Alloc = CountingAllocator<int>;
2894 TEST(Btree, AllocRangeConstructor) {
2895 using Alloc = CountingAllocator<int>;
2899 std::vector<int>
v = {1, 2, 3};
2906 TEST(Btree, AllocCopyConstructor) {
2907 using Alloc = CountingAllocator<int>;
2910 Alloc alloc1(&bytes_used1);
2913 set1.insert({1, 2, 3});
2916 Alloc alloc2(&bytes_used2);
2917 Set set2(set1, alloc2);
2921 EXPECT_GT(bytes_used1, set1.size() *
sizeof(
int));
2925 TEST(Btree, AllocMoveConstructor_SameAlloc) {
2926 using Alloc = CountingAllocator<int>;
2932 set1.insert({1, 2, 3});
2934 const int64_t original_bytes_used = bytes_used;
2935 EXPECT_GT(original_bytes_used, set1.size() *
sizeof(
int));
2940 EXPECT_EQ(bytes_used, original_bytes_used);
2943 TEST(Btree, AllocMoveConstructor_DifferentAlloc) {
2944 using Alloc = CountingAllocator<int>;
2947 Alloc alloc1(&bytes_used1);
2950 set1.insert({1, 2, 3});
2952 const int64_t original_bytes_used = bytes_used1;
2953 EXPECT_GT(original_bytes_used, set1.size() *
sizeof(
int));
2956 Alloc alloc2(&bytes_used2);
2961 EXPECT_EQ(bytes_used1, original_bytes_used);
2962 EXPECT_EQ(bytes_used2, original_bytes_used);
2965 bool IntCmp(
const int a,
const int b) {
return a <
b; }
2967 TEST(Btree, SupportsFunctionPtrComparator) {
2969 set.insert({1, 2, 3});
2978 EXPECT_TRUE(
map.value_comp()(std::make_pair(1, 1), std::make_pair(2, 2)));
2981 template <
typename Compare>
2982 struct TransparentPassThroughComp {
2983 using is_transparent = void;
2988 template <
typename T,
typename U>
2989 bool operator()(
const T &lhs,
const U &rhs)
const {
2995 SupportsTransparentComparatorThatDoesNotImplementAllVisibleOperators) {
2997 set.insert(MultiKey{1, 2});
3001 TEST(Btree, ConstructImplicitlyWithUnadaptedComparator) {
3006 TEST(Btree, InvalidComparatorsCaught) {
3008 struct ZeroAlwaysLessCmp {
3009 bool operator()(
int lhs,
int rhs)
const {
3010 if (lhs == 0)
return true;
3015 EXPECT_DEATH(
set.insert({0, 1, 2}),
"is_self_equivalent");
3018 struct ThreeWayAlwaysLessCmp {
3020 return absl::weak_ordering::less;
3024 EXPECT_DEATH(
set.insert({0, 1, 2}),
"is_self_equivalent");
3027 struct SumGreaterZeroCmp {
3028 bool operator()(
int lhs,
int rhs)
const {
3030 if (lhs == rhs)
return false;
3031 return lhs + rhs > 0;
3036 EXPECT_DEATH(
set.insert({0, 1, 2}),
3037 R
"regex(\!lhs_comp_rhs \|\| !comp\(\)\(rhs, lhs\))regex");
3040 struct ThreeWaySumGreaterZeroCmp {
3043 if (lhs == rhs)
return absl::weak_ordering::equivalent;
3045 if (lhs + rhs > 0)
return absl::weak_ordering::less;
3046 if (lhs + rhs == 0)
return absl::weak_ordering::equivalent;
3047 return absl::weak_ordering::greater;
3051 EXPECT_DEATH(
set.insert({0, 1, 2}),
"lhs_comp_rhs < 0 -> rhs_comp_lhs > 0");
3058 TEST(Btree, InvalidIteratorUse) {
3060 GTEST_SKIP() <<
"Generation validation for iterators is disabled.";
3064 for (
int i = 0;
i < 10; ++
i)
set.insert(i);
3065 auto it =
set.begin();
3067 EXPECT_DEATH(
set.erase(
it++),
"invalidated iterator");
3071 for (
int i = 0;
i < 10; ++
i)
set.insert(i);
3072 auto it =
set.insert(20).first;
3074 EXPECT_DEATH(*
it,
"invalidated iterator");
3078 for (
int i = 0;
i < 10000; ++
i)
set.insert(i);
3079 auto it =
set.find(5000);
3082 EXPECT_DEATH(*
it,
"invalidated iterator");
3087 class OnlyConstructibleByAllocator {
3088 explicit OnlyConstructibleByAllocator(
int i) :
i_(
i) {}
3091 OnlyConstructibleByAllocator(
const OnlyConstructibleByAllocator &other)
3093 OnlyConstructibleByAllocator &operator=(
3094 const OnlyConstructibleByAllocator &other) {
3098 int Get()
const {
return i_; }
3102 template <
typename T>
3103 friend class OnlyConstructibleAllocator;
3108 template <
typename T = OnlyConstructibleByAllocator>
3109 class OnlyConstructibleAllocator :
public std::allocator<T> {
3111 OnlyConstructibleAllocator() =
default;
3113 explicit OnlyConstructibleAllocator(
const OnlyConstructibleAllocator<U> &) {}
3115 void construct(OnlyConstructibleByAllocator *p,
int i) {
3116 new (
p) OnlyConstructibleByAllocator(i);
3118 template <
typename Pair>
3120 OnlyConstructibleByAllocator only(i);
3126 using other = OnlyConstructibleAllocator<U>;
3130 struct OnlyConstructibleByAllocatorComp {
3131 using is_transparent = void;
3132 bool operator()(OnlyConstructibleByAllocator a,
3133 OnlyConstructibleByAllocator
b)
const {
3134 return a.Get() <
b.Get();
3136 bool operator()(
int a, OnlyConstructibleByAllocator
b)
const {
3139 bool operator()(OnlyConstructibleByAllocator a,
int b)
const {
3144 TEST(Btree, OnlyConstructibleByAllocatorType) {
3145 const std::array<int, 2> arr = {3, 4};
3148 OnlyConstructibleByAllocatorComp,
3149 OnlyConstructibleAllocator<>>
3152 set.emplace_hint(
set.end(), 2);
3153 set.insert(arr.begin(), arr.end());
3158 OnlyConstructibleByAllocatorComp,
3159 OnlyConstructibleAllocator<>>
3162 set.emplace_hint(
set.end(), 2);
3169 OnlyConstructibleByAllocatorComp,
3170 OnlyConstructibleAllocator<>>
3173 map.emplace_hint(
map.end(), 2);
3174 map.insert(arr.begin(), arr.end());
3180 OnlyConstructibleByAllocatorComp,
3181 OnlyConstructibleAllocator<>>
3184 map.emplace_hint(
map.end(), 2);
3191 class NotAssignable {
3193 explicit NotAssignable(
int i) :
i_(
i) {}
3194 NotAssignable(
const NotAssignable &other) :
i_(other.
i_) {}
3195 NotAssignable &operator=(NotAssignable &&other) =
delete;
3196 int Get()
const {
return i_; }
3198 friend bool operator<(NotAssignable a, NotAssignable
b) {
3206 TEST(Btree, NotAssignableType) {
3210 set.emplace_hint(
set.end(), 2);
3211 set.insert(NotAssignable(3));
3212 set.insert(
set.end(), NotAssignable(4));
3220 set.emplace_hint(
set.end(), 2);
3221 set.insert(NotAssignable(2));
3222 set.insert(
set.end(), NotAssignable(3));
3229 map.emplace(NotAssignable(1), 1);
3230 map.emplace_hint(
map.end(), NotAssignable(2), 2);
3231 map.insert({NotAssignable(3), 3});
3232 map.insert(
map.end(), {NotAssignable(4), 4});
3240 map.emplace(NotAssignable(1), 1);
3241 map.emplace_hint(
map.end(), NotAssignable(2), 2);
3242 map.insert({NotAssignable(2), 3});
3243 map.insert(
map.end(), {NotAssignable(3), 3});