aboutsummaryrefslogtreecommitdiff
path: root/absl/container/flat_hash_map_test.cc
diff options
context:
space:
mode:
authorEvan Brown <ezb@google.com>2024-06-06 11:12:29 -0700
committerCopybara-Service <copybara-worker@google.com>2024-06-06 11:13:25 -0700
commit66ef711d6846771b8e725e377de37bedae6c1527 (patch)
treeab97f865d2fb443845dc604e21a0721123b04c3c /absl/container/flat_hash_map_test.cc
parented34153e0d9cd15f9b9eb45e86b457e0a495aeea (diff)
downloadabseil-66ef711d6846771b8e725e377de37bedae6c1527.tar.gz
abseil-66ef711d6846771b8e725e377de37bedae6c1527.tar.bz2
abseil-66ef711d6846771b8e725e377de37bedae6c1527.zip
Add validation that hash/eq functors are consistent, meaning that `eq(k1, k2) -> hash(k1) == hash(k2)`.
Also add missing includes/dependencies in flat_hash_map_test. PiperOrigin-RevId: 640959222 Change-Id: I8d99544af05e97310045e6149f6ef6f7c82e552d
Diffstat (limited to 'absl/container/flat_hash_map_test.cc')
-rw-r--r--absl/container/flat_hash_map_test.cc36
1 files changed, 36 insertions, 0 deletions
diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc
index 8ef1a62b..eaa86925 100644
--- a/absl/container/flat_hash_map_test.cc
+++ b/absl/container/flat_hash_map_test.cc
@@ -16,12 +16,16 @@
#include <cstddef>
#include <memory>
+#include <string>
#include <type_traits>
#include <utility>
#include <vector>
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/base/config.h"
#include "absl/container/internal/hash_generator_testing.h"
+#include "absl/container/internal/hash_policy_testing.h"
#include "absl/container/internal/test_allocator.h"
#include "absl/container/internal/unordered_map_constructor_test.h"
#include "absl/container/internal/unordered_map_lookup_test.h"
@@ -363,6 +367,38 @@ TEST(FlatHashMap, FlatHashMapPolicyDestroyReturnsTrue) {
std::allocator<char>>(nullptr, nullptr))()));
}
+struct InconsistentHashEqType {
+ InconsistentHashEqType(int v1, int v2) : v1(v1), v2(v2) {}
+ template <typename H>
+ friend H AbslHashValue(H h, InconsistentHashEqType t) {
+ return H::combine(std::move(h), t.v1);
+ }
+ bool operator==(InconsistentHashEqType t) const { return v2 == t.v2; }
+ int v1, v2;
+};
+
+TEST(Iterator, InconsistentHashEqFunctorsValidation) {
+ if (!IsAssertEnabled()) GTEST_SKIP() << "Assertions not enabled.";
+
+ absl::flat_hash_map<InconsistentHashEqType, int> m;
+ for (int i = 0; i < 10; ++i) m[{i, i}] = 1;
+ // We need to insert multiple times to guarantee that we get the assertion
+ // because it's possible for the hash to collide with the inserted element
+ // that has v2==0. In those cases, the new element won't be inserted.
+ auto insert_conflicting_elems = [&] {
+ for (int i = 100; i < 20000; ++i) {
+ EXPECT_EQ((m[{i, 0}]), 1);
+ }
+ };
+
+ const char* crash_message = "hash/eq functors are inconsistent.";
+#if defined(__arm__) || defined(__aarch64__)
+ // On ARM, the crash message is garbled so don't expect a specific message.
+ crash_message = "";
+#endif
+ EXPECT_DEATH_IF_SUPPORTED(insert_conflicting_elems(), crash_message);
+}
+
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END