summaryrefslogtreecommitdiff
path: root/absl/container/flat_hash_set_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/container/flat_hash_set_test.cc')
-rw-r--r--absl/container/flat_hash_set_test.cc136
1 files changed, 95 insertions, 41 deletions
diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc
index a60b4bf5..0dd43269 100644
--- a/absl/container/flat_hash_set_test.cc
+++ b/absl/container/flat_hash_set_test.cc
@@ -16,6 +16,7 @@
#include <cstdint>
#include <memory>
+#include <type_traits>
#include <utility>
#include <vector>
@@ -24,6 +25,7 @@
#include "absl/base/config.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/hash_generator_testing.h"
+#include "absl/container/internal/test_allocator.h"
#include "absl/container/internal/unordered_set_constructor_test.h"
#include "absl/container/internal/unordered_set_lookup_test.h"
#include "absl/container/internal/unordered_set_members_test.h"
@@ -179,15 +181,46 @@ TEST(FlatHashSet, EraseIf) {
}
}
-class PoisonInline {
+TEST(FlatHashSet, CForEach) {
+ using ValueType = std::pair<int, int>;
+ flat_hash_set<ValueType> s;
+ std::vector<ValueType> expected;
+ for (int i = 0; i < 100; ++i) {
+ {
+ SCOPED_TRACE("mutable object iteration");
+ std::vector<ValueType> v;
+ absl::container_internal::c_for_each_fast(
+ s, [&v](const ValueType& p) { v.push_back(p); });
+ ASSERT_THAT(v, UnorderedElementsAreArray(expected));
+ }
+ {
+ SCOPED_TRACE("const object iteration");
+ std::vector<ValueType> v;
+ const flat_hash_set<ValueType>& cs = s;
+ absl::container_internal::c_for_each_fast(
+ cs, [&v](const ValueType& p) { v.push_back(p); });
+ ASSERT_THAT(v, UnorderedElementsAreArray(expected));
+ }
+ {
+ SCOPED_TRACE("temporary object iteration");
+ std::vector<ValueType> v;
+ absl::container_internal::c_for_each_fast(
+ flat_hash_set<ValueType>(s),
+ [&v](const ValueType& p) { v.push_back(p); });
+ ASSERT_THAT(v, UnorderedElementsAreArray(expected));
+ }
+ s.emplace(i, i);
+ expected.emplace_back(i, i);
+ }
+}
+
+class PoisonSoo {
int64_t data_;
public:
- explicit PoisonInline(int64_t d) : data_(d) {
- SanitizerPoisonObject(&data_);
- }
- PoisonInline(const PoisonInline& that) : PoisonInline(*that) {}
- ~PoisonInline() { SanitizerUnpoisonObject(&data_); }
+ explicit PoisonSoo(int64_t d) : data_(d) { SanitizerPoisonObject(&data_); }
+ PoisonSoo(const PoisonSoo& that) : PoisonSoo(*that) {}
+ ~PoisonSoo() { SanitizerUnpoisonObject(&data_); }
int64_t operator*() const {
SanitizerUnpoisonObject(&data_);
@@ -196,45 +229,66 @@ class PoisonInline {
return ret;
}
template <typename H>
- friend H AbslHashValue(H h, const PoisonInline& pi) {
+ friend H AbslHashValue(H h, const PoisonSoo& pi) {
return H::combine(std::move(h), *pi);
}
- bool operator==(const PoisonInline& rhs) const { return **this == *rhs; }
+ bool operator==(const PoisonSoo& rhs) const { return **this == *rhs; }
};
-// Tests that we don't touch the poison_ member of PoisonInline.
-TEST(FlatHashSet, PoisonInline) {
- PoisonInline a(0), b(1);
- { // basic usage
- flat_hash_set<PoisonInline> set;
- set.insert(a);
- EXPECT_THAT(set, UnorderedElementsAre(a));
- set.insert(b);
- EXPECT_THAT(set, UnorderedElementsAre(a, b));
- set.erase(a);
- EXPECT_THAT(set, UnorderedElementsAre(b));
- set.rehash(0); // shrink to inline
- EXPECT_THAT(set, UnorderedElementsAre(b));
- }
- { // test move constructor from inline to inline
- flat_hash_set<PoisonInline> set;
- set.insert(a);
- flat_hash_set<PoisonInline> set2(std::move(set));
- EXPECT_THAT(set2, UnorderedElementsAre(a));
- }
- { // test move assignment from inline to inline
- flat_hash_set<PoisonInline> set, set2;
- set.insert(a);
- set2 = std::move(set);
- EXPECT_THAT(set2, UnorderedElementsAre(a));
- }
- { // test alloc move constructor from inline to inline
- flat_hash_set<PoisonInline> set;
- set.insert(a);
- flat_hash_set<PoisonInline> set2(std::move(set),
- std::allocator<PoisonInline>());
- EXPECT_THAT(set2, UnorderedElementsAre(a));
- }
+TEST(FlatHashSet, PoisonSooBasic) {
+ PoisonSoo a(0), b(1);
+ flat_hash_set<PoisonSoo> set;
+ set.insert(a);
+ EXPECT_THAT(set, UnorderedElementsAre(a));
+ set.insert(b);
+ EXPECT_THAT(set, UnorderedElementsAre(a, b));
+ set.erase(a);
+ EXPECT_THAT(set, UnorderedElementsAre(b));
+ set.rehash(0); // Shrink to SOO.
+ EXPECT_THAT(set, UnorderedElementsAre(b));
+}
+
+TEST(FlatHashSet, PoisonSooMoveConstructSooToSoo) {
+ PoisonSoo a(0);
+ flat_hash_set<PoisonSoo> set;
+ set.insert(a);
+ flat_hash_set<PoisonSoo> set2(std::move(set));
+ EXPECT_THAT(set2, UnorderedElementsAre(a));
+}
+
+TEST(FlatHashSet, PoisonSooAllocMoveConstructSooToSoo) {
+ PoisonSoo a(0);
+ flat_hash_set<PoisonSoo> set;
+ set.insert(a);
+ flat_hash_set<PoisonSoo> set2(std::move(set), std::allocator<PoisonSoo>());
+ EXPECT_THAT(set2, UnorderedElementsAre(a));
+}
+
+TEST(FlatHashSet, PoisonSooMoveAssignFullSooToEmptySoo) {
+ PoisonSoo a(0);
+ flat_hash_set<PoisonSoo> set, set2;
+ set.insert(a);
+ set2 = std::move(set);
+ EXPECT_THAT(set2, UnorderedElementsAre(a));
+}
+
+TEST(FlatHashSet, PoisonSooMoveAssignFullSooToFullSoo) {
+ PoisonSoo a(0), b(1);
+ flat_hash_set<PoisonSoo> set, set2;
+ set.insert(a);
+ set2.insert(b);
+ set2 = std::move(set);
+ EXPECT_THAT(set2, UnorderedElementsAre(a));
+}
+
+TEST(FlatHashSet, FlatHashSetPolicyDestroyReturnsTrue) {
+ EXPECT_TRUE((decltype(FlatHashSetPolicy<int>::destroy<std::allocator<int>>(
+ nullptr, nullptr))()));
+ EXPECT_FALSE(
+ (decltype(FlatHashSetPolicy<int>::destroy<CountingAllocator<int>>(
+ nullptr, nullptr))()));
+ EXPECT_FALSE((decltype(FlatHashSetPolicy<std::unique_ptr<int>>::destroy<
+ std::allocator<int>>(nullptr, nullptr))()));
}
} // namespace