1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker #include "absl/hash/hash.h"
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker #include <algorithm>
18*9356374aSAndroid Build Coastguard Worker #include <array>
19*9356374aSAndroid Build Coastguard Worker #include <bitset>
20*9356374aSAndroid Build Coastguard Worker #include <cstddef>
21*9356374aSAndroid Build Coastguard Worker #include <cstdint>
22*9356374aSAndroid Build Coastguard Worker #include <cstdlib>
23*9356374aSAndroid Build Coastguard Worker #include <cstring>
24*9356374aSAndroid Build Coastguard Worker #include <functional>
25*9356374aSAndroid Build Coastguard Worker #include <initializer_list>
26*9356374aSAndroid Build Coastguard Worker #include <ios>
27*9356374aSAndroid Build Coastguard Worker #include <limits>
28*9356374aSAndroid Build Coastguard Worker #include <memory>
29*9356374aSAndroid Build Coastguard Worker #include <ostream>
30*9356374aSAndroid Build Coastguard Worker #include <set>
31*9356374aSAndroid Build Coastguard Worker #include <string>
32*9356374aSAndroid Build Coastguard Worker #include <tuple>
33*9356374aSAndroid Build Coastguard Worker #include <type_traits>
34*9356374aSAndroid Build Coastguard Worker #include <unordered_map>
35*9356374aSAndroid Build Coastguard Worker #include <utility>
36*9356374aSAndroid Build Coastguard Worker #include <vector>
37*9356374aSAndroid Build Coastguard Worker
38*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
39*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
40*9356374aSAndroid Build Coastguard Worker #include "absl/container/flat_hash_set.h"
41*9356374aSAndroid Build Coastguard Worker #include "absl/hash/hash_testing.h"
42*9356374aSAndroid Build Coastguard Worker #include "absl/hash/internal/hash_test.h"
43*9356374aSAndroid Build Coastguard Worker #include "absl/hash/internal/spy_hash_state.h"
44*9356374aSAndroid Build Coastguard Worker #include "absl/memory/memory.h"
45*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h"
46*9356374aSAndroid Build Coastguard Worker #include "absl/strings/cord_test_helpers.h"
47*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
48*9356374aSAndroid Build Coastguard Worker #include "absl/types/optional.h"
49*9356374aSAndroid Build Coastguard Worker #include "absl/types/variant.h"
50*9356374aSAndroid Build Coastguard Worker
51*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_STD_FILESYSTEM_PATH_HASH_AVAILABLE
52*9356374aSAndroid Build Coastguard Worker #include <filesystem> // NOLINT
53*9356374aSAndroid Build Coastguard Worker #endif
54*9356374aSAndroid Build Coastguard Worker
55*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_HAVE_STD_STRING_VIEW
56*9356374aSAndroid Build Coastguard Worker #include <string_view>
57*9356374aSAndroid Build Coastguard Worker #endif
58*9356374aSAndroid Build Coastguard Worker
59*9356374aSAndroid Build Coastguard Worker namespace {
60*9356374aSAndroid Build Coastguard Worker
61*9356374aSAndroid Build Coastguard Worker using ::absl::hash_test_internal::is_hashable;
62*9356374aSAndroid Build Coastguard Worker using ::absl::hash_test_internal::TypeErasedContainer;
63*9356374aSAndroid Build Coastguard Worker using ::absl::hash_test_internal::TypeErasedValue;
64*9356374aSAndroid Build Coastguard Worker
65*9356374aSAndroid Build Coastguard Worker template <typename T>
66*9356374aSAndroid Build Coastguard Worker using TypeErasedVector = TypeErasedContainer<std::vector<T>>;
67*9356374aSAndroid Build Coastguard Worker
68*9356374aSAndroid Build Coastguard Worker using absl::Hash;
69*9356374aSAndroid Build Coastguard Worker using absl::hash_internal::SpyHashState;
70*9356374aSAndroid Build Coastguard Worker
71*9356374aSAndroid Build Coastguard Worker template <typename T>
72*9356374aSAndroid Build Coastguard Worker class HashValueIntTest : public testing::Test {
73*9356374aSAndroid Build Coastguard Worker };
74*9356374aSAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(HashValueIntTest);
75*9356374aSAndroid Build Coastguard Worker
76*9356374aSAndroid Build Coastguard Worker template <typename T>
SpyHash(const T & value)77*9356374aSAndroid Build Coastguard Worker SpyHashState SpyHash(const T& value) {
78*9356374aSAndroid Build Coastguard Worker return SpyHashState::combine(SpyHashState(), value);
79*9356374aSAndroid Build Coastguard Worker }
80*9356374aSAndroid Build Coastguard Worker
TYPED_TEST_P(HashValueIntTest,BasicUsage)81*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(HashValueIntTest, BasicUsage) {
82*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<TypeParam>::value));
83*9356374aSAndroid Build Coastguard Worker
84*9356374aSAndroid Build Coastguard Worker TypeParam n = 42;
85*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(SpyHash(n), SpyHash(TypeParam{42}));
86*9356374aSAndroid Build Coastguard Worker EXPECT_NE(SpyHash(n), SpyHash(TypeParam{0}));
87*9356374aSAndroid Build Coastguard Worker EXPECT_NE(SpyHash(std::numeric_limits<TypeParam>::max()),
88*9356374aSAndroid Build Coastguard Worker SpyHash(std::numeric_limits<TypeParam>::min()));
89*9356374aSAndroid Build Coastguard Worker }
90*9356374aSAndroid Build Coastguard Worker
TYPED_TEST_P(HashValueIntTest,FastPath)91*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(HashValueIntTest, FastPath) {
92*9356374aSAndroid Build Coastguard Worker // Test the fast-path to make sure the values are the same.
93*9356374aSAndroid Build Coastguard Worker TypeParam n = 42;
94*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::Hash<TypeParam>{}(n),
95*9356374aSAndroid Build Coastguard Worker absl::Hash<std::tuple<TypeParam>>{}(std::tuple<TypeParam>(n)));
96*9356374aSAndroid Build Coastguard Worker }
97*9356374aSAndroid Build Coastguard Worker
98*9356374aSAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(HashValueIntTest, BasicUsage, FastPath);
99*9356374aSAndroid Build Coastguard Worker using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
100*9356374aSAndroid Build Coastguard Worker uint32_t, uint64_t, size_t>;
101*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueIntTest, IntTypes);
102*9356374aSAndroid Build Coastguard Worker
103*9356374aSAndroid Build Coastguard Worker enum LegacyEnum { kValue1, kValue2, kValue3 };
104*9356374aSAndroid Build Coastguard Worker
105*9356374aSAndroid Build Coastguard Worker enum class EnumClass { kValue4, kValue5, kValue6 };
106*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,EnumAndBool)107*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, EnumAndBool) {
108*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<LegacyEnum>::value));
109*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<EnumClass>::value));
110*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<bool>::value));
111*9356374aSAndroid Build Coastguard Worker
112*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
113*9356374aSAndroid Build Coastguard Worker LegacyEnum::kValue1, LegacyEnum::kValue2, LegacyEnum::kValue3)));
114*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
115*9356374aSAndroid Build Coastguard Worker EnumClass::kValue4, EnumClass::kValue5, EnumClass::kValue6)));
116*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
117*9356374aSAndroid Build Coastguard Worker std::make_tuple(true, false)));
118*9356374aSAndroid Build Coastguard Worker }
119*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,FloatingPoint)120*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, FloatingPoint) {
121*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<float>::value));
122*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<double>::value));
123*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<long double>::value));
124*9356374aSAndroid Build Coastguard Worker
125*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
126*9356374aSAndroid Build Coastguard Worker std::make_tuple(42.f, 0.f, -0.f, std::numeric_limits<float>::infinity(),
127*9356374aSAndroid Build Coastguard Worker -std::numeric_limits<float>::infinity())));
128*9356374aSAndroid Build Coastguard Worker
129*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
130*9356374aSAndroid Build Coastguard Worker std::make_tuple(42., 0., -0., std::numeric_limits<double>::infinity(),
131*9356374aSAndroid Build Coastguard Worker -std::numeric_limits<double>::infinity())));
132*9356374aSAndroid Build Coastguard Worker
133*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
134*9356374aSAndroid Build Coastguard Worker // Add some values with small exponent to test that NORMAL values also
135*9356374aSAndroid Build Coastguard Worker // append their category.
136*9356374aSAndroid Build Coastguard Worker .5L, 1.L, 2.L, 4.L, 42.L, 0.L, -0.L,
137*9356374aSAndroid Build Coastguard Worker 17 * static_cast<long double>(std::numeric_limits<double>::max()),
138*9356374aSAndroid Build Coastguard Worker std::numeric_limits<long double>::infinity(),
139*9356374aSAndroid Build Coastguard Worker -std::numeric_limits<long double>::infinity())));
140*9356374aSAndroid Build Coastguard Worker }
141*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,Pointer)142*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, Pointer) {
143*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<int*>::value));
144*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<int(*)(char, float)>::value));
145*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<void(*)(int, int, ...)>::value));
146*9356374aSAndroid Build Coastguard Worker
147*9356374aSAndroid Build Coastguard Worker int i;
148*9356374aSAndroid Build Coastguard Worker int* ptr = &i;
149*9356374aSAndroid Build Coastguard Worker int* n = nullptr;
150*9356374aSAndroid Build Coastguard Worker
151*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
152*9356374aSAndroid Build Coastguard Worker std::make_tuple(&i, ptr, nullptr, ptr + 1, n)));
153*9356374aSAndroid Build Coastguard Worker }
154*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,PointerAlignment)155*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, PointerAlignment) {
156*9356374aSAndroid Build Coastguard Worker // We want to make sure that pointer alignment will not cause bits to be
157*9356374aSAndroid Build Coastguard Worker // stuck.
158*9356374aSAndroid Build Coastguard Worker
159*9356374aSAndroid Build Coastguard Worker constexpr size_t kTotalSize = 1 << 20;
160*9356374aSAndroid Build Coastguard Worker std::unique_ptr<char[]> data(new char[kTotalSize]);
161*9356374aSAndroid Build Coastguard Worker constexpr size_t kLog2NumValues = 5;
162*9356374aSAndroid Build Coastguard Worker constexpr size_t kNumValues = 1 << kLog2NumValues;
163*9356374aSAndroid Build Coastguard Worker
164*9356374aSAndroid Build Coastguard Worker for (size_t align = 1; align < kTotalSize / kNumValues;
165*9356374aSAndroid Build Coastguard Worker align < 8 ? align += 1 : align < 1024 ? align += 8 : align += 32) {
166*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(align);
167*9356374aSAndroid Build Coastguard Worker ASSERT_LE(align * kNumValues, kTotalSize);
168*9356374aSAndroid Build Coastguard Worker
169*9356374aSAndroid Build Coastguard Worker size_t bits_or = 0;
170*9356374aSAndroid Build Coastguard Worker size_t bits_and = ~size_t{};
171*9356374aSAndroid Build Coastguard Worker
172*9356374aSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumValues; ++i) {
173*9356374aSAndroid Build Coastguard Worker size_t hash = absl::Hash<void*>()(data.get() + i * align);
174*9356374aSAndroid Build Coastguard Worker bits_or |= hash;
175*9356374aSAndroid Build Coastguard Worker bits_and &= hash;
176*9356374aSAndroid Build Coastguard Worker }
177*9356374aSAndroid Build Coastguard Worker
178*9356374aSAndroid Build Coastguard Worker // Limit the scope to the bits we would be using for Swisstable.
179*9356374aSAndroid Build Coastguard Worker constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1;
180*9356374aSAndroid Build Coastguard Worker size_t stuck_bits = (~bits_or | bits_and) & kMask;
181*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(stuck_bits, 0u) << "0x" << std::hex << stuck_bits;
182*9356374aSAndroid Build Coastguard Worker }
183*9356374aSAndroid Build Coastguard Worker }
184*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,PointerToMember)185*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, PointerToMember) {
186*9356374aSAndroid Build Coastguard Worker struct Bass {
187*9356374aSAndroid Build Coastguard Worker void q() {}
188*9356374aSAndroid Build Coastguard Worker };
189*9356374aSAndroid Build Coastguard Worker
190*9356374aSAndroid Build Coastguard Worker struct A : Bass {
191*9356374aSAndroid Build Coastguard Worker virtual ~A() = default;
192*9356374aSAndroid Build Coastguard Worker virtual void vfa() {}
193*9356374aSAndroid Build Coastguard Worker
194*9356374aSAndroid Build Coastguard Worker static auto pq() -> void (A::*)() { return &A::q; }
195*9356374aSAndroid Build Coastguard Worker };
196*9356374aSAndroid Build Coastguard Worker
197*9356374aSAndroid Build Coastguard Worker struct B : Bass {
198*9356374aSAndroid Build Coastguard Worker virtual ~B() = default;
199*9356374aSAndroid Build Coastguard Worker virtual void vfb() {}
200*9356374aSAndroid Build Coastguard Worker
201*9356374aSAndroid Build Coastguard Worker static auto pq() -> void (B::*)() { return &B::q; }
202*9356374aSAndroid Build Coastguard Worker };
203*9356374aSAndroid Build Coastguard Worker
204*9356374aSAndroid Build Coastguard Worker struct Foo : A, B {
205*9356374aSAndroid Build Coastguard Worker void f1() {}
206*9356374aSAndroid Build Coastguard Worker void f2() const {}
207*9356374aSAndroid Build Coastguard Worker
208*9356374aSAndroid Build Coastguard Worker int g1() & { return 0; }
209*9356374aSAndroid Build Coastguard Worker int g2() const & { return 0; }
210*9356374aSAndroid Build Coastguard Worker int g3() && { return 0; }
211*9356374aSAndroid Build Coastguard Worker int g4() const && { return 0; }
212*9356374aSAndroid Build Coastguard Worker
213*9356374aSAndroid Build Coastguard Worker int h1() & { return 0; }
214*9356374aSAndroid Build Coastguard Worker int h2() const & { return 0; }
215*9356374aSAndroid Build Coastguard Worker int h3() && { return 0; }
216*9356374aSAndroid Build Coastguard Worker int h4() const && { return 0; }
217*9356374aSAndroid Build Coastguard Worker
218*9356374aSAndroid Build Coastguard Worker int a;
219*9356374aSAndroid Build Coastguard Worker int b;
220*9356374aSAndroid Build Coastguard Worker
221*9356374aSAndroid Build Coastguard Worker const int c = 11;
222*9356374aSAndroid Build Coastguard Worker const int d = 22;
223*9356374aSAndroid Build Coastguard Worker };
224*9356374aSAndroid Build Coastguard Worker
225*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<float Foo::*>::value));
226*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<double (Foo::*)(int, int)&&>::value));
227*9356374aSAndroid Build Coastguard Worker
228*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
229*9356374aSAndroid Build Coastguard Worker std::make_tuple(&Foo::a, &Foo::b, static_cast<int Foo::*>(nullptr))));
230*9356374aSAndroid Build Coastguard Worker
231*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
232*9356374aSAndroid Build Coastguard Worker std::make_tuple(&Foo::c, &Foo::d, static_cast<const int Foo::*>(nullptr),
233*9356374aSAndroid Build Coastguard Worker &Foo::a, &Foo::b)));
234*9356374aSAndroid Build Coastguard Worker
235*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
236*9356374aSAndroid Build Coastguard Worker &Foo::f1, static_cast<void (Foo::*)()>(nullptr))));
237*9356374aSAndroid Build Coastguard Worker
238*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
239*9356374aSAndroid Build Coastguard Worker &Foo::f2, static_cast<void (Foo::*)() const>(nullptr))));
240*9356374aSAndroid Build Coastguard Worker
241*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
242*9356374aSAndroid Build Coastguard Worker &Foo::g1, &Foo::h1, static_cast<int (Foo::*)() &>(nullptr))));
243*9356374aSAndroid Build Coastguard Worker
244*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
245*9356374aSAndroid Build Coastguard Worker &Foo::g2, &Foo::h2, static_cast<int (Foo::*)() const &>(nullptr))));
246*9356374aSAndroid Build Coastguard Worker
247*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
248*9356374aSAndroid Build Coastguard Worker &Foo::g3, &Foo::h3, static_cast<int (Foo::*)() &&>(nullptr))));
249*9356374aSAndroid Build Coastguard Worker
250*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
251*9356374aSAndroid Build Coastguard Worker &Foo::g4, &Foo::h4, static_cast<int (Foo::*)() const &&>(nullptr))));
252*9356374aSAndroid Build Coastguard Worker
253*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
254*9356374aSAndroid Build Coastguard Worker std::make_tuple(static_cast<void (Foo::*)()>(&Foo::vfa),
255*9356374aSAndroid Build Coastguard Worker static_cast<void (Foo::*)()>(&Foo::vfb),
256*9356374aSAndroid Build Coastguard Worker static_cast<void (Foo::*)()>(nullptr))));
257*9356374aSAndroid Build Coastguard Worker
258*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
259*9356374aSAndroid Build Coastguard Worker std::make_tuple(static_cast<void (Foo::*)()>(Foo::A::pq()),
260*9356374aSAndroid Build Coastguard Worker static_cast<void (Foo::*)()>(Foo::B::pq()),
261*9356374aSAndroid Build Coastguard Worker static_cast<void (Foo::*)()>(nullptr))));
262*9356374aSAndroid Build Coastguard Worker }
263*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,PairAndTuple)264*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, PairAndTuple) {
265*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::pair<int, int>>::value));
266*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::pair<const int&, const int&>>::value));
267*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::tuple<int&, int&>>::value));
268*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::tuple<int&&, int&&>>::value));
269*9356374aSAndroid Build Coastguard Worker
270*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
271*9356374aSAndroid Build Coastguard Worker std::make_pair(0, 42), std::make_pair(0, 42), std::make_pair(42, 0),
272*9356374aSAndroid Build Coastguard Worker std::make_pair(0, 0), std::make_pair(42, 42), std::make_pair(1, 42))));
273*9356374aSAndroid Build Coastguard Worker
274*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
275*9356374aSAndroid Build Coastguard Worker std::make_tuple(std::make_tuple(0, 0, 0), std::make_tuple(0, 0, 42),
276*9356374aSAndroid Build Coastguard Worker std::make_tuple(0, 23, 0), std::make_tuple(17, 0, 0),
277*9356374aSAndroid Build Coastguard Worker std::make_tuple(42, 0, 0), std::make_tuple(3, 9, 9),
278*9356374aSAndroid Build Coastguard Worker std::make_tuple(0, 0, -42))));
279*9356374aSAndroid Build Coastguard Worker
280*9356374aSAndroid Build Coastguard Worker // Test that tuples of lvalue references work (so we need a few lvalues):
281*9356374aSAndroid Build Coastguard Worker int a = 0, b = 1, c = 17, d = 23;
282*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
283*9356374aSAndroid Build Coastguard Worker std::tie(a, a), std::tie(a, b), std::tie(b, c), std::tie(c, d))));
284*9356374aSAndroid Build Coastguard Worker
285*9356374aSAndroid Build Coastguard Worker // Test that tuples of rvalue references work:
286*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
287*9356374aSAndroid Build Coastguard Worker std::forward_as_tuple(0, 0, 0), std::forward_as_tuple(0, 0, 42),
288*9356374aSAndroid Build Coastguard Worker std::forward_as_tuple(0, 23, 0), std::forward_as_tuple(17, 0, 0),
289*9356374aSAndroid Build Coastguard Worker std::forward_as_tuple(42, 0, 0), std::forward_as_tuple(3, 9, 9),
290*9356374aSAndroid Build Coastguard Worker std::forward_as_tuple(0, 0, -42))));
291*9356374aSAndroid Build Coastguard Worker }
292*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,CombineContiguousWorks)293*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, CombineContiguousWorks) {
294*9356374aSAndroid Build Coastguard Worker std::vector<std::tuple<int>> v1 = {std::make_tuple(1), std::make_tuple(3)};
295*9356374aSAndroid Build Coastguard Worker std::vector<std::tuple<int>> v2 = {std::make_tuple(1), std::make_tuple(2)};
296*9356374aSAndroid Build Coastguard Worker
297*9356374aSAndroid Build Coastguard Worker auto vh1 = SpyHash(v1);
298*9356374aSAndroid Build Coastguard Worker auto vh2 = SpyHash(v2);
299*9356374aSAndroid Build Coastguard Worker EXPECT_NE(vh1, vh2);
300*9356374aSAndroid Build Coastguard Worker }
301*9356374aSAndroid Build Coastguard Worker
302*9356374aSAndroid Build Coastguard Worker struct DummyDeleter {
303*9356374aSAndroid Build Coastguard Worker template <typename T>
operator ()__anon1097c0110111::DummyDeleter304*9356374aSAndroid Build Coastguard Worker void operator() (T* ptr) {}
305*9356374aSAndroid Build Coastguard Worker };
306*9356374aSAndroid Build Coastguard Worker
307*9356374aSAndroid Build Coastguard Worker struct SmartPointerEq {
308*9356374aSAndroid Build Coastguard Worker template <typename T, typename U>
operator ()__anon1097c0110111::SmartPointerEq309*9356374aSAndroid Build Coastguard Worker bool operator()(const T& t, const U& u) const {
310*9356374aSAndroid Build Coastguard Worker return GetPtr(t) == GetPtr(u);
311*9356374aSAndroid Build Coastguard Worker }
312*9356374aSAndroid Build Coastguard Worker
313*9356374aSAndroid Build Coastguard Worker template <typename T>
GetPtr__anon1097c0110111::SmartPointerEq314*9356374aSAndroid Build Coastguard Worker static auto GetPtr(const T& t) -> decltype(&*t) {
315*9356374aSAndroid Build Coastguard Worker return t ? &*t : nullptr;
316*9356374aSAndroid Build Coastguard Worker }
317*9356374aSAndroid Build Coastguard Worker
GetPtr__anon1097c0110111::SmartPointerEq318*9356374aSAndroid Build Coastguard Worker static std::nullptr_t GetPtr(std::nullptr_t) { return nullptr; }
319*9356374aSAndroid Build Coastguard Worker };
320*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,SmartPointers)321*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, SmartPointers) {
322*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::unique_ptr<int>>::value));
323*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::unique_ptr<int, DummyDeleter>>::value));
324*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::shared_ptr<int>>::value));
325*9356374aSAndroid Build Coastguard Worker
326*9356374aSAndroid Build Coastguard Worker int i, j;
327*9356374aSAndroid Build Coastguard Worker std::unique_ptr<int, DummyDeleter> unique1(&i);
328*9356374aSAndroid Build Coastguard Worker std::unique_ptr<int, DummyDeleter> unique2(&i);
329*9356374aSAndroid Build Coastguard Worker std::unique_ptr<int, DummyDeleter> unique_other(&j);
330*9356374aSAndroid Build Coastguard Worker std::unique_ptr<int, DummyDeleter> unique_null;
331*9356374aSAndroid Build Coastguard Worker
332*9356374aSAndroid Build Coastguard Worker std::shared_ptr<int> shared1(&i, DummyDeleter());
333*9356374aSAndroid Build Coastguard Worker std::shared_ptr<int> shared2(&i, DummyDeleter());
334*9356374aSAndroid Build Coastguard Worker std::shared_ptr<int> shared_other(&j, DummyDeleter());
335*9356374aSAndroid Build Coastguard Worker std::shared_ptr<int> shared_null;
336*9356374aSAndroid Build Coastguard Worker
337*9356374aSAndroid Build Coastguard Worker // Sanity check of the Eq function.
338*9356374aSAndroid Build Coastguard Worker ASSERT_TRUE(SmartPointerEq{}(unique1, shared1));
339*9356374aSAndroid Build Coastguard Worker ASSERT_FALSE(SmartPointerEq{}(unique1, shared_other));
340*9356374aSAndroid Build Coastguard Worker ASSERT_TRUE(SmartPointerEq{}(unique_null, nullptr));
341*9356374aSAndroid Build Coastguard Worker ASSERT_FALSE(SmartPointerEq{}(shared2, nullptr));
342*9356374aSAndroid Build Coastguard Worker
343*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
344*9356374aSAndroid Build Coastguard Worker std::forward_as_tuple(&i, nullptr, //
345*9356374aSAndroid Build Coastguard Worker unique1, unique2, unique_null, //
346*9356374aSAndroid Build Coastguard Worker absl::make_unique<int>(), //
347*9356374aSAndroid Build Coastguard Worker shared1, shared2, shared_null, //
348*9356374aSAndroid Build Coastguard Worker std::make_shared<int>()),
349*9356374aSAndroid Build Coastguard Worker SmartPointerEq{}));
350*9356374aSAndroid Build Coastguard Worker }
351*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,FunctionPointer)352*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, FunctionPointer) {
353*9356374aSAndroid Build Coastguard Worker using Func = int (*)();
354*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_hashable<Func>::value);
355*9356374aSAndroid Build Coastguard Worker
356*9356374aSAndroid Build Coastguard Worker Func p1 = [] { return 2; }, p2 = [] { return 1; };
357*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
358*9356374aSAndroid Build Coastguard Worker std::make_tuple(p1, p2, nullptr)));
359*9356374aSAndroid Build Coastguard Worker }
360*9356374aSAndroid Build Coastguard Worker
361*9356374aSAndroid Build Coastguard Worker struct WrapInTuple {
362*9356374aSAndroid Build Coastguard Worker template <typename T>
operator ()__anon1097c0110111::WrapInTuple363*9356374aSAndroid Build Coastguard Worker std::tuple<int, T, size_t> operator()(const T& t) const {
364*9356374aSAndroid Build Coastguard Worker return std::make_tuple(7, t, 0xdeadbeef);
365*9356374aSAndroid Build Coastguard Worker }
366*9356374aSAndroid Build Coastguard Worker };
367*9356374aSAndroid Build Coastguard Worker
FlatCord(absl::string_view sv)368*9356374aSAndroid Build Coastguard Worker absl::Cord FlatCord(absl::string_view sv) {
369*9356374aSAndroid Build Coastguard Worker absl::Cord c(sv);
370*9356374aSAndroid Build Coastguard Worker c.Flatten();
371*9356374aSAndroid Build Coastguard Worker return c;
372*9356374aSAndroid Build Coastguard Worker }
373*9356374aSAndroid Build Coastguard Worker
FragmentedCord(absl::string_view sv)374*9356374aSAndroid Build Coastguard Worker absl::Cord FragmentedCord(absl::string_view sv) {
375*9356374aSAndroid Build Coastguard Worker if (sv.size() < 2) {
376*9356374aSAndroid Build Coastguard Worker return absl::Cord(sv);
377*9356374aSAndroid Build Coastguard Worker }
378*9356374aSAndroid Build Coastguard Worker size_t halfway = sv.size() / 2;
379*9356374aSAndroid Build Coastguard Worker std::vector<absl::string_view> parts = {sv.substr(0, halfway),
380*9356374aSAndroid Build Coastguard Worker sv.substr(halfway)};
381*9356374aSAndroid Build Coastguard Worker return absl::MakeFragmentedCord(parts);
382*9356374aSAndroid Build Coastguard Worker }
383*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,Strings)384*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, Strings) {
385*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::string>::value));
386*9356374aSAndroid Build Coastguard Worker
387*9356374aSAndroid Build Coastguard Worker const std::string small = "foo";
388*9356374aSAndroid Build Coastguard Worker const std::string dup = "foofoo";
389*9356374aSAndroid Build Coastguard Worker const std::string large = std::string(2048, 'x'); // multiple of chunk size
390*9356374aSAndroid Build Coastguard Worker const std::string huge = std::string(5000, 'a'); // not a multiple
391*9356374aSAndroid Build Coastguard Worker
392*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( //
393*9356374aSAndroid Build Coastguard Worker std::string(), absl::string_view(), absl::Cord(), //
394*9356374aSAndroid Build Coastguard Worker std::string(""), absl::string_view(""), absl::Cord(""), //
395*9356374aSAndroid Build Coastguard Worker std::string(small), absl::string_view(small), absl::Cord(small), //
396*9356374aSAndroid Build Coastguard Worker std::string(dup), absl::string_view(dup), absl::Cord(dup), //
397*9356374aSAndroid Build Coastguard Worker std::string(large), absl::string_view(large), absl::Cord(large), //
398*9356374aSAndroid Build Coastguard Worker std::string(huge), absl::string_view(huge), FlatCord(huge), //
399*9356374aSAndroid Build Coastguard Worker FragmentedCord(huge))));
400*9356374aSAndroid Build Coastguard Worker
401*9356374aSAndroid Build Coastguard Worker // Also check that nested types maintain the same hash.
402*9356374aSAndroid Build Coastguard Worker const WrapInTuple t{};
403*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( //
404*9356374aSAndroid Build Coastguard Worker t(std::string()), t(absl::string_view()), t(absl::Cord()), //
405*9356374aSAndroid Build Coastguard Worker t(std::string("")), t(absl::string_view("")), t(absl::Cord("")), //
406*9356374aSAndroid Build Coastguard Worker t(std::string(small)), t(absl::string_view(small)), //
407*9356374aSAndroid Build Coastguard Worker t(absl::Cord(small)), //
408*9356374aSAndroid Build Coastguard Worker t(std::string(dup)), t(absl::string_view(dup)), t(absl::Cord(dup)), //
409*9356374aSAndroid Build Coastguard Worker t(std::string(large)), t(absl::string_view(large)), //
410*9356374aSAndroid Build Coastguard Worker t(absl::Cord(large)), //
411*9356374aSAndroid Build Coastguard Worker t(std::string(huge)), t(absl::string_view(huge)), //
412*9356374aSAndroid Build Coastguard Worker t(FlatCord(huge)), t(FragmentedCord(huge)))));
413*9356374aSAndroid Build Coastguard Worker
414*9356374aSAndroid Build Coastguard Worker // Make sure that hashing a `const char*` does not use its string-value.
415*9356374aSAndroid Build Coastguard Worker EXPECT_NE(SpyHash(static_cast<const char*>("ABC")),
416*9356374aSAndroid Build Coastguard Worker SpyHash(absl::string_view("ABC")));
417*9356374aSAndroid Build Coastguard Worker }
418*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,WString)419*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, WString) {
420*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::wstring>::value));
421*9356374aSAndroid Build Coastguard Worker
422*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
423*9356374aSAndroid Build Coastguard Worker std::wstring(), std::wstring(L"ABC"), std::wstring(L"ABC"),
424*9356374aSAndroid Build Coastguard Worker std::wstring(L"Some other different string"),
425*9356374aSAndroid Build Coastguard Worker std::wstring(L"Iñtërnâtiônàlizætiøn"))));
426*9356374aSAndroid Build Coastguard Worker }
427*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,U16String)428*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, U16String) {
429*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::u16string>::value));
430*9356374aSAndroid Build Coastguard Worker
431*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
432*9356374aSAndroid Build Coastguard Worker std::u16string(), std::u16string(u"ABC"), std::u16string(u"ABC"),
433*9356374aSAndroid Build Coastguard Worker std::u16string(u"Some other different string"),
434*9356374aSAndroid Build Coastguard Worker std::u16string(u"Iñtërnâtiônàlizætiøn"))));
435*9356374aSAndroid Build Coastguard Worker }
436*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,U32String)437*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, U32String) {
438*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::u32string>::value));
439*9356374aSAndroid Build Coastguard Worker
440*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
441*9356374aSAndroid Build Coastguard Worker std::u32string(), std::u32string(U"ABC"), std::u32string(U"ABC"),
442*9356374aSAndroid Build Coastguard Worker std::u32string(U"Some other different string"),
443*9356374aSAndroid Build Coastguard Worker std::u32string(U"Iñtërnâtiônàlizætiøn"))));
444*9356374aSAndroid Build Coastguard Worker }
445*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,WStringView)446*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, WStringView) {
447*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_HAVE_STD_STRING_VIEW
448*9356374aSAndroid Build Coastguard Worker GTEST_SKIP();
449*9356374aSAndroid Build Coastguard Worker #else
450*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::wstring_view>::value));
451*9356374aSAndroid Build Coastguard Worker
452*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
453*9356374aSAndroid Build Coastguard Worker std::wstring_view(), std::wstring_view(L"ABC"), std::wstring_view(L"ABC"),
454*9356374aSAndroid Build Coastguard Worker std::wstring_view(L"Some other different string_view"),
455*9356374aSAndroid Build Coastguard Worker std::wstring_view(L"Iñtërnâtiônàlizætiøn"))));
456*9356374aSAndroid Build Coastguard Worker #endif
457*9356374aSAndroid Build Coastguard Worker }
458*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,U16StringView)459*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, U16StringView) {
460*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_HAVE_STD_STRING_VIEW
461*9356374aSAndroid Build Coastguard Worker GTEST_SKIP();
462*9356374aSAndroid Build Coastguard Worker #else
463*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::u16string_view>::value));
464*9356374aSAndroid Build Coastguard Worker
465*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
466*9356374aSAndroid Build Coastguard Worker std::make_tuple(std::u16string_view(), std::u16string_view(u"ABC"),
467*9356374aSAndroid Build Coastguard Worker std::u16string_view(u"ABC"),
468*9356374aSAndroid Build Coastguard Worker std::u16string_view(u"Some other different string_view"),
469*9356374aSAndroid Build Coastguard Worker std::u16string_view(u"Iñtërnâtiônàlizætiøn"))));
470*9356374aSAndroid Build Coastguard Worker #endif
471*9356374aSAndroid Build Coastguard Worker }
472*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,U32StringView)473*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, U32StringView) {
474*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_HAVE_STD_STRING_VIEW
475*9356374aSAndroid Build Coastguard Worker GTEST_SKIP();
476*9356374aSAndroid Build Coastguard Worker #else
477*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::u32string_view>::value));
478*9356374aSAndroid Build Coastguard Worker
479*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
480*9356374aSAndroid Build Coastguard Worker std::make_tuple(std::u32string_view(), std::u32string_view(U"ABC"),
481*9356374aSAndroid Build Coastguard Worker std::u32string_view(U"ABC"),
482*9356374aSAndroid Build Coastguard Worker std::u32string_view(U"Some other different string_view"),
483*9356374aSAndroid Build Coastguard Worker std::u32string_view(U"Iñtërnâtiônàlizætiøn"))));
484*9356374aSAndroid Build Coastguard Worker #endif
485*9356374aSAndroid Build Coastguard Worker }
486*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,StdFilesystemPath)487*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, StdFilesystemPath) {
488*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_INTERNAL_STD_FILESYSTEM_PATH_HASH_AVAILABLE
489*9356374aSAndroid Build Coastguard Worker GTEST_SKIP() << "std::filesystem::path is unavailable on this platform";
490*9356374aSAndroid Build Coastguard Worker #else
491*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::filesystem::path>::value));
492*9356374aSAndroid Build Coastguard Worker
493*9356374aSAndroid Build Coastguard Worker // clang-format off
494*9356374aSAndroid Build Coastguard Worker const auto kTestCases = std::make_tuple(
495*9356374aSAndroid Build Coastguard Worker std::filesystem::path(),
496*9356374aSAndroid Build Coastguard Worker std::filesystem::path("/"),
497*9356374aSAndroid Build Coastguard Worker #ifndef __GLIBCXX__
498*9356374aSAndroid Build Coastguard Worker // libstdc++ has a known issue normalizing "//".
499*9356374aSAndroid Build Coastguard Worker // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106452
500*9356374aSAndroid Build Coastguard Worker std::filesystem::path("//"),
501*9356374aSAndroid Build Coastguard Worker #endif
502*9356374aSAndroid Build Coastguard Worker std::filesystem::path("/a/b"),
503*9356374aSAndroid Build Coastguard Worker std::filesystem::path("/a//b"),
504*9356374aSAndroid Build Coastguard Worker std::filesystem::path("a/b"),
505*9356374aSAndroid Build Coastguard Worker std::filesystem::path("a/b/"),
506*9356374aSAndroid Build Coastguard Worker std::filesystem::path("a//b"),
507*9356374aSAndroid Build Coastguard Worker std::filesystem::path("a//b/"),
508*9356374aSAndroid Build Coastguard Worker std::filesystem::path("c:/"),
509*9356374aSAndroid Build Coastguard Worker std::filesystem::path("c:\\"),
510*9356374aSAndroid Build Coastguard Worker std::filesystem::path("c:\\/"),
511*9356374aSAndroid Build Coastguard Worker std::filesystem::path("c:\\//"),
512*9356374aSAndroid Build Coastguard Worker std::filesystem::path("c://"),
513*9356374aSAndroid Build Coastguard Worker std::filesystem::path("c://\\"),
514*9356374aSAndroid Build Coastguard Worker std::filesystem::path("/e/p"),
515*9356374aSAndroid Build Coastguard Worker std::filesystem::path("/s/../e/p"),
516*9356374aSAndroid Build Coastguard Worker std::filesystem::path("e/p"),
517*9356374aSAndroid Build Coastguard Worker std::filesystem::path("s/../e/p"));
518*9356374aSAndroid Build Coastguard Worker // clang-format on
519*9356374aSAndroid Build Coastguard Worker
520*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(kTestCases));
521*9356374aSAndroid Build Coastguard Worker #endif
522*9356374aSAndroid Build Coastguard Worker }
523*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,StdArray)524*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, StdArray) {
525*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::array<int, 3>>::value));
526*9356374aSAndroid Build Coastguard Worker
527*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
528*9356374aSAndroid Build Coastguard Worker std::make_tuple(std::array<int, 3>{}, std::array<int, 3>{{0, 23, 42}})));
529*9356374aSAndroid Build Coastguard Worker }
530*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,StdBitset)531*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, StdBitset) {
532*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::bitset<257>>::value));
533*9356374aSAndroid Build Coastguard Worker
534*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
535*9356374aSAndroid Build Coastguard Worker {std::bitset<2>("00"), std::bitset<2>("01"), std::bitset<2>("10"),
536*9356374aSAndroid Build Coastguard Worker std::bitset<2>("11")}));
537*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
538*9356374aSAndroid Build Coastguard Worker {std::bitset<5>("10101"), std::bitset<5>("10001"), std::bitset<5>()}));
539*9356374aSAndroid Build Coastguard Worker
540*9356374aSAndroid Build Coastguard Worker constexpr int kNumBits = 256;
541*9356374aSAndroid Build Coastguard Worker std::array<std::string, 6> bit_strings;
542*9356374aSAndroid Build Coastguard Worker bit_strings.fill(std::string(kNumBits, '1'));
543*9356374aSAndroid Build Coastguard Worker bit_strings[1][0] = '0';
544*9356374aSAndroid Build Coastguard Worker bit_strings[2][1] = '0';
545*9356374aSAndroid Build Coastguard Worker bit_strings[3][kNumBits / 3] = '0';
546*9356374aSAndroid Build Coastguard Worker bit_strings[4][kNumBits - 2] = '0';
547*9356374aSAndroid Build Coastguard Worker bit_strings[5][kNumBits - 1] = '0';
548*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
549*9356374aSAndroid Build Coastguard Worker {std::bitset<kNumBits>(bit_strings[0].c_str()),
550*9356374aSAndroid Build Coastguard Worker std::bitset<kNumBits>(bit_strings[1].c_str()),
551*9356374aSAndroid Build Coastguard Worker std::bitset<kNumBits>(bit_strings[2].c_str()),
552*9356374aSAndroid Build Coastguard Worker std::bitset<kNumBits>(bit_strings[3].c_str()),
553*9356374aSAndroid Build Coastguard Worker std::bitset<kNumBits>(bit_strings[4].c_str()),
554*9356374aSAndroid Build Coastguard Worker std::bitset<kNumBits>(bit_strings[5].c_str())}));
555*9356374aSAndroid Build Coastguard Worker } // namespace
556*9356374aSAndroid Build Coastguard Worker
557*9356374aSAndroid Build Coastguard Worker // Private type that only supports AbslHashValue to make sure our chosen hash
558*9356374aSAndroid Build Coastguard Worker // implementation is recursive within absl::Hash.
559*9356374aSAndroid Build Coastguard Worker // It uses std::abs() on the value to provide different bitwise representations
560*9356374aSAndroid Build Coastguard Worker // of the same logical value.
561*9356374aSAndroid Build Coastguard Worker struct Private {
562*9356374aSAndroid Build Coastguard Worker int i;
563*9356374aSAndroid Build Coastguard Worker template <typename H>
AbslHashValue(H h,Private p)564*9356374aSAndroid Build Coastguard Worker friend H AbslHashValue(H h, Private p) {
565*9356374aSAndroid Build Coastguard Worker return H::combine(std::move(h), std::abs(p.i));
566*9356374aSAndroid Build Coastguard Worker }
567*9356374aSAndroid Build Coastguard Worker
operator ==(Private a,Private b)568*9356374aSAndroid Build Coastguard Worker friend bool operator==(Private a, Private b) {
569*9356374aSAndroid Build Coastguard Worker return std::abs(a.i) == std::abs(b.i);
570*9356374aSAndroid Build Coastguard Worker }
571*9356374aSAndroid Build Coastguard Worker
operator <<(std::ostream & o,Private p)572*9356374aSAndroid Build Coastguard Worker friend std::ostream& operator<<(std::ostream& o, Private p) {
573*9356374aSAndroid Build Coastguard Worker return o << p.i;
574*9356374aSAndroid Build Coastguard Worker }
575*9356374aSAndroid Build Coastguard Worker };
576*9356374aSAndroid Build Coastguard Worker
577*9356374aSAndroid Build Coastguard Worker // Test helper for combine_piecewise_buffer. It holds a string_view to the
578*9356374aSAndroid Build Coastguard Worker // buffer-to-be-hashed. Its AbslHashValue specialization will split up its
579*9356374aSAndroid Build Coastguard Worker // contents at the character offsets requested.
580*9356374aSAndroid Build Coastguard Worker class PiecewiseHashTester {
581*9356374aSAndroid Build Coastguard Worker public:
582*9356374aSAndroid Build Coastguard Worker // Create a hash view of a buffer to be hashed contiguously.
PiecewiseHashTester(absl::string_view buf)583*9356374aSAndroid Build Coastguard Worker explicit PiecewiseHashTester(absl::string_view buf)
584*9356374aSAndroid Build Coastguard Worker : buf_(buf), piecewise_(false), split_locations_() {}
585*9356374aSAndroid Build Coastguard Worker
586*9356374aSAndroid Build Coastguard Worker // Create a hash view of a buffer to be hashed piecewise, with breaks at the
587*9356374aSAndroid Build Coastguard Worker // given locations.
PiecewiseHashTester(absl::string_view buf,std::set<size_t> split_locations)588*9356374aSAndroid Build Coastguard Worker PiecewiseHashTester(absl::string_view buf, std::set<size_t> split_locations)
589*9356374aSAndroid Build Coastguard Worker : buf_(buf),
590*9356374aSAndroid Build Coastguard Worker piecewise_(true),
591*9356374aSAndroid Build Coastguard Worker split_locations_(std::move(split_locations)) {}
592*9356374aSAndroid Build Coastguard Worker
593*9356374aSAndroid Build Coastguard Worker template <typename H>
AbslHashValue(H h,const PiecewiseHashTester & p)594*9356374aSAndroid Build Coastguard Worker friend H AbslHashValue(H h, const PiecewiseHashTester& p) {
595*9356374aSAndroid Build Coastguard Worker if (!p.piecewise_) {
596*9356374aSAndroid Build Coastguard Worker return H::combine_contiguous(std::move(h), p.buf_.data(), p.buf_.size());
597*9356374aSAndroid Build Coastguard Worker }
598*9356374aSAndroid Build Coastguard Worker absl::hash_internal::PiecewiseCombiner combiner;
599*9356374aSAndroid Build Coastguard Worker if (p.split_locations_.empty()) {
600*9356374aSAndroid Build Coastguard Worker h = combiner.add_buffer(std::move(h), p.buf_.data(), p.buf_.size());
601*9356374aSAndroid Build Coastguard Worker return combiner.finalize(std::move(h));
602*9356374aSAndroid Build Coastguard Worker }
603*9356374aSAndroid Build Coastguard Worker size_t begin = 0;
604*9356374aSAndroid Build Coastguard Worker for (size_t next : p.split_locations_) {
605*9356374aSAndroid Build Coastguard Worker absl::string_view chunk = p.buf_.substr(begin, next - begin);
606*9356374aSAndroid Build Coastguard Worker h = combiner.add_buffer(std::move(h), chunk.data(), chunk.size());
607*9356374aSAndroid Build Coastguard Worker begin = next;
608*9356374aSAndroid Build Coastguard Worker }
609*9356374aSAndroid Build Coastguard Worker absl::string_view last_chunk = p.buf_.substr(begin);
610*9356374aSAndroid Build Coastguard Worker if (!last_chunk.empty()) {
611*9356374aSAndroid Build Coastguard Worker h = combiner.add_buffer(std::move(h), last_chunk.data(),
612*9356374aSAndroid Build Coastguard Worker last_chunk.size());
613*9356374aSAndroid Build Coastguard Worker }
614*9356374aSAndroid Build Coastguard Worker return combiner.finalize(std::move(h));
615*9356374aSAndroid Build Coastguard Worker }
616*9356374aSAndroid Build Coastguard Worker
617*9356374aSAndroid Build Coastguard Worker private:
618*9356374aSAndroid Build Coastguard Worker absl::string_view buf_;
619*9356374aSAndroid Build Coastguard Worker bool piecewise_;
620*9356374aSAndroid Build Coastguard Worker std::set<size_t> split_locations_;
621*9356374aSAndroid Build Coastguard Worker };
622*9356374aSAndroid Build Coastguard Worker
623*9356374aSAndroid Build Coastguard Worker // Dummy object that hashes as two distinct contiguous buffers, "foo" followed
624*9356374aSAndroid Build Coastguard Worker // by "bar"
625*9356374aSAndroid Build Coastguard Worker struct DummyFooBar {
626*9356374aSAndroid Build Coastguard Worker template <typename H>
AbslHashValue(H h,const DummyFooBar &)627*9356374aSAndroid Build Coastguard Worker friend H AbslHashValue(H h, const DummyFooBar&) {
628*9356374aSAndroid Build Coastguard Worker const char* foo = "foo";
629*9356374aSAndroid Build Coastguard Worker const char* bar = "bar";
630*9356374aSAndroid Build Coastguard Worker h = H::combine_contiguous(std::move(h), foo, 3);
631*9356374aSAndroid Build Coastguard Worker h = H::combine_contiguous(std::move(h), bar, 3);
632*9356374aSAndroid Build Coastguard Worker return h;
633*9356374aSAndroid Build Coastguard Worker }
634*9356374aSAndroid Build Coastguard Worker };
635*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,CombinePiecewiseBuffer)636*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, CombinePiecewiseBuffer) {
637*9356374aSAndroid Build Coastguard Worker absl::Hash<PiecewiseHashTester> hash;
638*9356374aSAndroid Build Coastguard Worker
639*9356374aSAndroid Build Coastguard Worker // Check that hashing an empty buffer through the piecewise API works.
640*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(hash(PiecewiseHashTester("")), hash(PiecewiseHashTester("", {})));
641*9356374aSAndroid Build Coastguard Worker
642*9356374aSAndroid Build Coastguard Worker // Similarly, small buffers should give consistent results
643*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(hash(PiecewiseHashTester("foobar")),
644*9356374aSAndroid Build Coastguard Worker hash(PiecewiseHashTester("foobar", {})));
645*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(hash(PiecewiseHashTester("foobar")),
646*9356374aSAndroid Build Coastguard Worker hash(PiecewiseHashTester("foobar", {3})));
647*9356374aSAndroid Build Coastguard Worker
648*9356374aSAndroid Build Coastguard Worker // But hashing "foobar" in pieces gives a different answer than hashing "foo"
649*9356374aSAndroid Build Coastguard Worker // contiguously, then "bar" contiguously.
650*9356374aSAndroid Build Coastguard Worker EXPECT_NE(hash(PiecewiseHashTester("foobar", {3})),
651*9356374aSAndroid Build Coastguard Worker absl::Hash<DummyFooBar>()(DummyFooBar{}));
652*9356374aSAndroid Build Coastguard Worker
653*9356374aSAndroid Build Coastguard Worker // Test hashing a large buffer incrementally, broken up in several different
654*9356374aSAndroid Build Coastguard Worker // ways. Arrange for breaks on and near the stride boundaries to look for
655*9356374aSAndroid Build Coastguard Worker // off-by-one errors in the implementation.
656*9356374aSAndroid Build Coastguard Worker //
657*9356374aSAndroid Build Coastguard Worker // This test is run on a buffer that is a multiple of the stride size, and one
658*9356374aSAndroid Build Coastguard Worker // that isn't.
659*9356374aSAndroid Build Coastguard Worker for (size_t big_buffer_size : {1024u * 2 + 512u, 1024u * 3}) {
660*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(big_buffer_size);
661*9356374aSAndroid Build Coastguard Worker std::string big_buffer;
662*9356374aSAndroid Build Coastguard Worker for (size_t i = 0; i < big_buffer_size; ++i) {
663*9356374aSAndroid Build Coastguard Worker // Arbitrary string
664*9356374aSAndroid Build Coastguard Worker big_buffer.push_back(32 + (i * (i / 3)) % 64);
665*9356374aSAndroid Build Coastguard Worker }
666*9356374aSAndroid Build Coastguard Worker auto big_buffer_hash = hash(PiecewiseHashTester(big_buffer));
667*9356374aSAndroid Build Coastguard Worker
668*9356374aSAndroid Build Coastguard Worker const int possible_breaks = 9;
669*9356374aSAndroid Build Coastguard Worker size_t breaks[possible_breaks] = {1, 512, 1023, 1024, 1025,
670*9356374aSAndroid Build Coastguard Worker 1536, 2047, 2048, 2049};
671*9356374aSAndroid Build Coastguard Worker for (unsigned test_mask = 0; test_mask < (1u << possible_breaks);
672*9356374aSAndroid Build Coastguard Worker ++test_mask) {
673*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(test_mask);
674*9356374aSAndroid Build Coastguard Worker std::set<size_t> break_locations;
675*9356374aSAndroid Build Coastguard Worker for (int j = 0; j < possible_breaks; ++j) {
676*9356374aSAndroid Build Coastguard Worker if (test_mask & (1u << j)) {
677*9356374aSAndroid Build Coastguard Worker break_locations.insert(breaks[j]);
678*9356374aSAndroid Build Coastguard Worker }
679*9356374aSAndroid Build Coastguard Worker }
680*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(
681*9356374aSAndroid Build Coastguard Worker hash(PiecewiseHashTester(big_buffer, std::move(break_locations))),
682*9356374aSAndroid Build Coastguard Worker big_buffer_hash);
683*9356374aSAndroid Build Coastguard Worker }
684*9356374aSAndroid Build Coastguard Worker }
685*9356374aSAndroid Build Coastguard Worker }
686*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,PrivateSanity)687*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, PrivateSanity) {
688*9356374aSAndroid Build Coastguard Worker // Sanity check that Private is working as the tests below expect it to work.
689*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_hashable<Private>::value);
690*9356374aSAndroid Build Coastguard Worker EXPECT_NE(SpyHash(Private{0}), SpyHash(Private{1}));
691*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(SpyHash(Private{1}), SpyHash(Private{1}));
692*9356374aSAndroid Build Coastguard Worker }
693*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,Optional)694*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, Optional) {
695*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_hashable<absl::optional<Private>>::value);
696*9356374aSAndroid Build Coastguard Worker
697*9356374aSAndroid Build Coastguard Worker using O = absl::optional<Private>;
698*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
699*9356374aSAndroid Build Coastguard Worker std::make_tuple(O{}, O{{1}}, O{{-1}}, O{{10}})));
700*9356374aSAndroid Build Coastguard Worker }
701*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,Variant)702*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, Variant) {
703*9356374aSAndroid Build Coastguard Worker using V = absl::variant<Private, std::string>;
704*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_hashable<V>::value);
705*9356374aSAndroid Build Coastguard Worker
706*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
707*9356374aSAndroid Build Coastguard Worker V(Private{1}), V(Private{-1}), V(Private{2}), V("ABC"), V("BCD"))));
708*9356374aSAndroid Build Coastguard Worker
709*9356374aSAndroid Build Coastguard Worker #if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
710*9356374aSAndroid Build Coastguard Worker struct S {};
711*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(is_hashable<absl::variant<S>>::value);
712*9356374aSAndroid Build Coastguard Worker #endif
713*9356374aSAndroid Build Coastguard Worker }
714*9356374aSAndroid Build Coastguard Worker
TEST(HashValueTest,ReferenceWrapper)715*9356374aSAndroid Build Coastguard Worker TEST(HashValueTest, ReferenceWrapper) {
716*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_hashable<std::reference_wrapper<Private>>::value);
717*9356374aSAndroid Build Coastguard Worker
718*9356374aSAndroid Build Coastguard Worker Private p1{1}, p10{10};
719*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
720*9356374aSAndroid Build Coastguard Worker p1, p10, std::ref(p1), std::ref(p10), std::cref(p1), std::cref(p10))));
721*9356374aSAndroid Build Coastguard Worker
722*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_hashable<std::reference_wrapper<int>>::value);
723*9356374aSAndroid Build Coastguard Worker int one = 1, ten = 10;
724*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
725*9356374aSAndroid Build Coastguard Worker one, ten, std::ref(one), std::ref(ten), std::cref(one), std::cref(ten))));
726*9356374aSAndroid Build Coastguard Worker
727*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
728*9356374aSAndroid Build Coastguard Worker std::make_tuple(std::tuple<std::reference_wrapper<int>>(std::ref(one)),
729*9356374aSAndroid Build Coastguard Worker std::tuple<std::reference_wrapper<int>>(std::ref(ten)),
730*9356374aSAndroid Build Coastguard Worker std::tuple<int>(one), std::tuple<int>(ten))));
731*9356374aSAndroid Build Coastguard Worker }
732*9356374aSAndroid Build Coastguard Worker
733*9356374aSAndroid Build Coastguard Worker template <typename T, typename = void>
734*9356374aSAndroid Build Coastguard Worker struct IsHashCallable : std::false_type {};
735*9356374aSAndroid Build Coastguard Worker
736*9356374aSAndroid Build Coastguard Worker template <typename T>
737*9356374aSAndroid Build Coastguard Worker struct IsHashCallable<T, absl::void_t<decltype(std::declval<absl::Hash<T>>()(
738*9356374aSAndroid Build Coastguard Worker std::declval<const T&>()))>> : std::true_type {};
739*9356374aSAndroid Build Coastguard Worker
740*9356374aSAndroid Build Coastguard Worker template <typename T, typename = void>
741*9356374aSAndroid Build Coastguard Worker struct IsAggregateInitializable : std::false_type {};
742*9356374aSAndroid Build Coastguard Worker
743*9356374aSAndroid Build Coastguard Worker template <typename T>
744*9356374aSAndroid Build Coastguard Worker struct IsAggregateInitializable<T, absl::void_t<decltype(T{})>>
745*9356374aSAndroid Build Coastguard Worker : std::true_type {};
746*9356374aSAndroid Build Coastguard Worker
TEST(IsHashableTest,ValidHash)747*9356374aSAndroid Build Coastguard Worker TEST(IsHashableTest, ValidHash) {
748*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<int>::value));
749*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(std::is_default_constructible<absl::Hash<int>>::value);
750*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(std::is_copy_constructible<absl::Hash<int>>::value);
751*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(std::is_move_constructible<absl::Hash<int>>::value);
752*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::is_copy_assignable<absl::Hash<int>>::value);
753*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(absl::is_move_assignable<absl::Hash<int>>::value);
754*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(IsHashCallable<int>::value);
755*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(IsAggregateInitializable<absl::Hash<int>>::value);
756*9356374aSAndroid Build Coastguard Worker }
757*9356374aSAndroid Build Coastguard Worker
758*9356374aSAndroid Build Coastguard Worker #if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
TEST(IsHashableTest,PoisonHash)759*9356374aSAndroid Build Coastguard Worker TEST(IsHashableTest, PoisonHash) {
760*9356374aSAndroid Build Coastguard Worker struct X {};
761*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE((is_hashable<X>::value));
762*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(std::is_default_constructible<absl::Hash<X>>::value);
763*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(std::is_copy_constructible<absl::Hash<X>>::value);
764*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(std::is_move_constructible<absl::Hash<X>>::value);
765*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(absl::is_copy_assignable<absl::Hash<X>>::value);
766*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(absl::is_move_assignable<absl::Hash<X>>::value);
767*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(IsHashCallable<X>::value);
768*9356374aSAndroid Build Coastguard Worker #if !defined(__GNUC__) || defined(__clang__)
769*9356374aSAndroid Build Coastguard Worker // TODO(b/144368551): As of GCC 8.4 this does not compile.
770*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(IsAggregateInitializable<absl::Hash<X>>::value);
771*9356374aSAndroid Build Coastguard Worker #endif
772*9356374aSAndroid Build Coastguard Worker }
773*9356374aSAndroid Build Coastguard Worker #endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
774*9356374aSAndroid Build Coastguard Worker
775*9356374aSAndroid Build Coastguard Worker // Hashable types
776*9356374aSAndroid Build Coastguard Worker //
777*9356374aSAndroid Build Coastguard Worker // These types exist simply to exercise various AbslHashValue behaviors, so
778*9356374aSAndroid Build Coastguard Worker // they are named by what their AbslHashValue overload does.
779*9356374aSAndroid Build Coastguard Worker struct NoOp {
780*9356374aSAndroid Build Coastguard Worker template <typename HashCode>
AbslHashValue(HashCode h,NoOp n)781*9356374aSAndroid Build Coastguard Worker friend HashCode AbslHashValue(HashCode h, NoOp n) {
782*9356374aSAndroid Build Coastguard Worker return h;
783*9356374aSAndroid Build Coastguard Worker }
784*9356374aSAndroid Build Coastguard Worker };
785*9356374aSAndroid Build Coastguard Worker
786*9356374aSAndroid Build Coastguard Worker struct EmptyCombine {
787*9356374aSAndroid Build Coastguard Worker template <typename HashCode>
AbslHashValue(HashCode h,EmptyCombine e)788*9356374aSAndroid Build Coastguard Worker friend HashCode AbslHashValue(HashCode h, EmptyCombine e) {
789*9356374aSAndroid Build Coastguard Worker return HashCode::combine(std::move(h));
790*9356374aSAndroid Build Coastguard Worker }
791*9356374aSAndroid Build Coastguard Worker };
792*9356374aSAndroid Build Coastguard Worker
793*9356374aSAndroid Build Coastguard Worker template <typename Int>
794*9356374aSAndroid Build Coastguard Worker struct CombineIterative {
795*9356374aSAndroid Build Coastguard Worker template <typename HashCode>
AbslHashValue(HashCode h,CombineIterative c)796*9356374aSAndroid Build Coastguard Worker friend HashCode AbslHashValue(HashCode h, CombineIterative c) {
797*9356374aSAndroid Build Coastguard Worker for (int i = 0; i < 5; ++i) {
798*9356374aSAndroid Build Coastguard Worker h = HashCode::combine(std::move(h), Int(i));
799*9356374aSAndroid Build Coastguard Worker }
800*9356374aSAndroid Build Coastguard Worker return h;
801*9356374aSAndroid Build Coastguard Worker }
802*9356374aSAndroid Build Coastguard Worker };
803*9356374aSAndroid Build Coastguard Worker
804*9356374aSAndroid Build Coastguard Worker template <typename Int>
805*9356374aSAndroid Build Coastguard Worker struct CombineVariadic {
806*9356374aSAndroid Build Coastguard Worker template <typename HashCode>
AbslHashValue(HashCode h,CombineVariadic c)807*9356374aSAndroid Build Coastguard Worker friend HashCode AbslHashValue(HashCode h, CombineVariadic c) {
808*9356374aSAndroid Build Coastguard Worker return HashCode::combine(std::move(h), Int(0), Int(1), Int(2), Int(3),
809*9356374aSAndroid Build Coastguard Worker Int(4));
810*9356374aSAndroid Build Coastguard Worker }
811*9356374aSAndroid Build Coastguard Worker };
812*9356374aSAndroid Build Coastguard Worker enum class InvokeTag {
813*9356374aSAndroid Build Coastguard Worker kUniquelyRepresented,
814*9356374aSAndroid Build Coastguard Worker kHashValue,
815*9356374aSAndroid Build Coastguard Worker #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
816*9356374aSAndroid Build Coastguard Worker kLegacyHash,
817*9356374aSAndroid Build Coastguard Worker #endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
818*9356374aSAndroid Build Coastguard Worker kStdHash,
819*9356374aSAndroid Build Coastguard Worker kNone
820*9356374aSAndroid Build Coastguard Worker };
821*9356374aSAndroid Build Coastguard Worker
822*9356374aSAndroid Build Coastguard Worker template <InvokeTag T>
823*9356374aSAndroid Build Coastguard Worker using InvokeTagConstant = std::integral_constant<InvokeTag, T>;
824*9356374aSAndroid Build Coastguard Worker
825*9356374aSAndroid Build Coastguard Worker template <InvokeTag... Tags>
826*9356374aSAndroid Build Coastguard Worker struct MinTag;
827*9356374aSAndroid Build Coastguard Worker
828*9356374aSAndroid Build Coastguard Worker template <InvokeTag a, InvokeTag b, InvokeTag... Tags>
829*9356374aSAndroid Build Coastguard Worker struct MinTag<a, b, Tags...> : MinTag<(a < b ? a : b), Tags...> {};
830*9356374aSAndroid Build Coastguard Worker
831*9356374aSAndroid Build Coastguard Worker template <InvokeTag a>
832*9356374aSAndroid Build Coastguard Worker struct MinTag<a> : InvokeTagConstant<a> {};
833*9356374aSAndroid Build Coastguard Worker
834*9356374aSAndroid Build Coastguard Worker template <InvokeTag... Tags>
835*9356374aSAndroid Build Coastguard Worker struct CustomHashType {
CustomHashType__anon1097c0110111::CustomHashType836*9356374aSAndroid Build Coastguard Worker explicit CustomHashType(size_t val) : value(val) {}
837*9356374aSAndroid Build Coastguard Worker size_t value;
838*9356374aSAndroid Build Coastguard Worker };
839*9356374aSAndroid Build Coastguard Worker
840*9356374aSAndroid Build Coastguard Worker template <InvokeTag allowed, InvokeTag... tags>
841*9356374aSAndroid Build Coastguard Worker struct EnableIfContained
842*9356374aSAndroid Build Coastguard Worker : std::enable_if<absl::disjunction<
843*9356374aSAndroid Build Coastguard Worker std::integral_constant<bool, allowed == tags>...>::value> {};
844*9356374aSAndroid Build Coastguard Worker
845*9356374aSAndroid Build Coastguard Worker template <
846*9356374aSAndroid Build Coastguard Worker typename H, InvokeTag... Tags,
847*9356374aSAndroid Build Coastguard Worker typename = typename EnableIfContained<InvokeTag::kHashValue, Tags...>::type>
AbslHashValue(H state,CustomHashType<Tags...> t)848*9356374aSAndroid Build Coastguard Worker H AbslHashValue(H state, CustomHashType<Tags...> t) {
849*9356374aSAndroid Build Coastguard Worker static_assert(MinTag<Tags...>::value == InvokeTag::kHashValue, "");
850*9356374aSAndroid Build Coastguard Worker return H::combine(std::move(state),
851*9356374aSAndroid Build Coastguard Worker t.value + static_cast<int>(InvokeTag::kHashValue));
852*9356374aSAndroid Build Coastguard Worker }
853*9356374aSAndroid Build Coastguard Worker
854*9356374aSAndroid Build Coastguard Worker } // namespace
855*9356374aSAndroid Build Coastguard Worker
856*9356374aSAndroid Build Coastguard Worker namespace absl {
857*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
858*9356374aSAndroid Build Coastguard Worker namespace hash_internal {
859*9356374aSAndroid Build Coastguard Worker template <InvokeTag... Tags>
860*9356374aSAndroid Build Coastguard Worker struct is_uniquely_represented<
861*9356374aSAndroid Build Coastguard Worker CustomHashType<Tags...>,
862*9356374aSAndroid Build Coastguard Worker typename EnableIfContained<InvokeTag::kUniquelyRepresented, Tags...>::type>
863*9356374aSAndroid Build Coastguard Worker : std::true_type {};
864*9356374aSAndroid Build Coastguard Worker } // namespace hash_internal
865*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
866*9356374aSAndroid Build Coastguard Worker } // namespace absl
867*9356374aSAndroid Build Coastguard Worker
868*9356374aSAndroid Build Coastguard Worker #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
869*9356374aSAndroid Build Coastguard Worker namespace ABSL_INTERNAL_LEGACY_HASH_NAMESPACE {
870*9356374aSAndroid Build Coastguard Worker template <InvokeTag... Tags>
871*9356374aSAndroid Build Coastguard Worker struct hash<CustomHashType<Tags...>> {
872*9356374aSAndroid Build Coastguard Worker template <InvokeTag... TagsIn, typename = typename EnableIfContained<
873*9356374aSAndroid Build Coastguard Worker InvokeTag::kLegacyHash, TagsIn...>::type>
operator ()ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash874*9356374aSAndroid Build Coastguard Worker size_t operator()(CustomHashType<TagsIn...> t) const {
875*9356374aSAndroid Build Coastguard Worker static_assert(MinTag<Tags...>::value == InvokeTag::kLegacyHash, "");
876*9356374aSAndroid Build Coastguard Worker return t.value + static_cast<int>(InvokeTag::kLegacyHash);
877*9356374aSAndroid Build Coastguard Worker }
878*9356374aSAndroid Build Coastguard Worker };
879*9356374aSAndroid Build Coastguard Worker } // namespace ABSL_INTERNAL_LEGACY_HASH_NAMESPACE
880*9356374aSAndroid Build Coastguard Worker #endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
881*9356374aSAndroid Build Coastguard Worker
882*9356374aSAndroid Build Coastguard Worker namespace std {
883*9356374aSAndroid Build Coastguard Worker template <InvokeTag... Tags> // NOLINT
884*9356374aSAndroid Build Coastguard Worker struct hash<CustomHashType<Tags...>> {
885*9356374aSAndroid Build Coastguard Worker template <InvokeTag... TagsIn, typename = typename EnableIfContained<
886*9356374aSAndroid Build Coastguard Worker InvokeTag::kStdHash, TagsIn...>::type>
operator ()std::hash887*9356374aSAndroid Build Coastguard Worker size_t operator()(CustomHashType<TagsIn...> t) const {
888*9356374aSAndroid Build Coastguard Worker static_assert(MinTag<Tags...>::value == InvokeTag::kStdHash, "");
889*9356374aSAndroid Build Coastguard Worker return t.value + static_cast<int>(InvokeTag::kStdHash);
890*9356374aSAndroid Build Coastguard Worker }
891*9356374aSAndroid Build Coastguard Worker };
892*9356374aSAndroid Build Coastguard Worker } // namespace std
893*9356374aSAndroid Build Coastguard Worker
894*9356374aSAndroid Build Coastguard Worker namespace {
895*9356374aSAndroid Build Coastguard Worker
896*9356374aSAndroid Build Coastguard Worker template <typename... T>
TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>,T...)897*9356374aSAndroid Build Coastguard Worker void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>, T...) {
898*9356374aSAndroid Build Coastguard Worker using type = CustomHashType<T::value...>;
899*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(testing::PrintToString(std::vector<InvokeTag>{T::value...}));
900*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_hashable<type>());
901*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_hashable<const type>());
902*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_hashable<const type&>());
903*9356374aSAndroid Build Coastguard Worker
904*9356374aSAndroid Build Coastguard Worker const size_t offset = static_cast<int>(std::min({T::value...}));
905*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(SpyHash(type(7)), SpyHash(size_t{7 + offset}));
906*9356374aSAndroid Build Coastguard Worker }
907*9356374aSAndroid Build Coastguard Worker
TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>)908*9356374aSAndroid Build Coastguard Worker void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>) {
909*9356374aSAndroid Build Coastguard Worker #if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
910*9356374aSAndroid Build Coastguard Worker // is_hashable is false if we don't support any of the hooks.
911*9356374aSAndroid Build Coastguard Worker using type = CustomHashType<>;
912*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(is_hashable<type>());
913*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(is_hashable<const type>());
914*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(is_hashable<const type&>());
915*9356374aSAndroid Build Coastguard Worker #endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
916*9356374aSAndroid Build Coastguard Worker }
917*9356374aSAndroid Build Coastguard Worker
918*9356374aSAndroid Build Coastguard Worker template <InvokeTag Tag, typename... T>
TestCustomHashType(InvokeTagConstant<Tag> tag,T...t)919*9356374aSAndroid Build Coastguard Worker void TestCustomHashType(InvokeTagConstant<Tag> tag, T... t) {
920*9356374aSAndroid Build Coastguard Worker constexpr auto next = static_cast<InvokeTag>(static_cast<int>(Tag) + 1);
921*9356374aSAndroid Build Coastguard Worker TestCustomHashType(InvokeTagConstant<next>(), tag, t...);
922*9356374aSAndroid Build Coastguard Worker TestCustomHashType(InvokeTagConstant<next>(), t...);
923*9356374aSAndroid Build Coastguard Worker }
924*9356374aSAndroid Build Coastguard Worker
TEST(HashTest,CustomHashType)925*9356374aSAndroid Build Coastguard Worker TEST(HashTest, CustomHashType) {
926*9356374aSAndroid Build Coastguard Worker TestCustomHashType(InvokeTagConstant<InvokeTag{}>());
927*9356374aSAndroid Build Coastguard Worker }
928*9356374aSAndroid Build Coastguard Worker
TEST(HashTest,NoOpsAreEquivalent)929*9356374aSAndroid Build Coastguard Worker TEST(HashTest, NoOpsAreEquivalent) {
930*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Hash<NoOp>()({}), Hash<NoOp>()({}));
931*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Hash<NoOp>()({}), Hash<EmptyCombine>()({}));
932*9356374aSAndroid Build Coastguard Worker }
933*9356374aSAndroid Build Coastguard Worker
934*9356374aSAndroid Build Coastguard Worker template <typename T>
935*9356374aSAndroid Build Coastguard Worker class HashIntTest : public testing::Test {
936*9356374aSAndroid Build Coastguard Worker };
937*9356374aSAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(HashIntTest);
938*9356374aSAndroid Build Coastguard Worker
TYPED_TEST_P(HashIntTest,BasicUsage)939*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(HashIntTest, BasicUsage) {
940*9356374aSAndroid Build Coastguard Worker EXPECT_NE(Hash<NoOp>()({}), Hash<TypeParam>()(0));
941*9356374aSAndroid Build Coastguard Worker EXPECT_NE(Hash<NoOp>()({}),
942*9356374aSAndroid Build Coastguard Worker Hash<TypeParam>()(std::numeric_limits<TypeParam>::max()));
943*9356374aSAndroid Build Coastguard Worker if (std::numeric_limits<TypeParam>::min() != 0) {
944*9356374aSAndroid Build Coastguard Worker EXPECT_NE(Hash<NoOp>()({}),
945*9356374aSAndroid Build Coastguard Worker Hash<TypeParam>()(std::numeric_limits<TypeParam>::min()));
946*9356374aSAndroid Build Coastguard Worker }
947*9356374aSAndroid Build Coastguard Worker
948*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Hash<CombineIterative<TypeParam>>()({}),
949*9356374aSAndroid Build Coastguard Worker Hash<CombineVariadic<TypeParam>>()({}));
950*9356374aSAndroid Build Coastguard Worker }
951*9356374aSAndroid Build Coastguard Worker
952*9356374aSAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(HashIntTest, BasicUsage);
953*9356374aSAndroid Build Coastguard Worker using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
954*9356374aSAndroid Build Coastguard Worker uint32_t, uint64_t, size_t>;
955*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(My, HashIntTest, IntTypes);
956*9356374aSAndroid Build Coastguard Worker
957*9356374aSAndroid Build Coastguard Worker struct StructWithPadding {
958*9356374aSAndroid Build Coastguard Worker char c;
959*9356374aSAndroid Build Coastguard Worker int i;
960*9356374aSAndroid Build Coastguard Worker
961*9356374aSAndroid Build Coastguard Worker template <typename H>
AbslHashValue(H hash_state,const StructWithPadding & s)962*9356374aSAndroid Build Coastguard Worker friend H AbslHashValue(H hash_state, const StructWithPadding& s) {
963*9356374aSAndroid Build Coastguard Worker return H::combine(std::move(hash_state), s.c, s.i);
964*9356374aSAndroid Build Coastguard Worker }
965*9356374aSAndroid Build Coastguard Worker };
966*9356374aSAndroid Build Coastguard Worker
967*9356374aSAndroid Build Coastguard Worker static_assert(sizeof(StructWithPadding) > sizeof(char) + sizeof(int),
968*9356374aSAndroid Build Coastguard Worker "StructWithPadding doesn't have padding");
969*9356374aSAndroid Build Coastguard Worker static_assert(std::is_standard_layout<StructWithPadding>::value, "");
970*9356374aSAndroid Build Coastguard Worker
971*9356374aSAndroid Build Coastguard Worker // This check has to be disabled because libstdc++ doesn't support it.
972*9356374aSAndroid Build Coastguard Worker // static_assert(std::is_trivially_constructible<StructWithPadding>::value, "");
973*9356374aSAndroid Build Coastguard Worker
974*9356374aSAndroid Build Coastguard Worker template <typename T>
975*9356374aSAndroid Build Coastguard Worker struct ArraySlice {
976*9356374aSAndroid Build Coastguard Worker T* begin;
977*9356374aSAndroid Build Coastguard Worker T* end;
978*9356374aSAndroid Build Coastguard Worker
979*9356374aSAndroid Build Coastguard Worker template <typename H>
AbslHashValue(H hash_state,const ArraySlice & slice)980*9356374aSAndroid Build Coastguard Worker friend H AbslHashValue(H hash_state, const ArraySlice& slice) {
981*9356374aSAndroid Build Coastguard Worker for (auto t = slice.begin; t != slice.end; ++t) {
982*9356374aSAndroid Build Coastguard Worker hash_state = H::combine(std::move(hash_state), *t);
983*9356374aSAndroid Build Coastguard Worker }
984*9356374aSAndroid Build Coastguard Worker return hash_state;
985*9356374aSAndroid Build Coastguard Worker }
986*9356374aSAndroid Build Coastguard Worker };
987*9356374aSAndroid Build Coastguard Worker
TEST(HashTest,HashNonUniquelyRepresentedType)988*9356374aSAndroid Build Coastguard Worker TEST(HashTest, HashNonUniquelyRepresentedType) {
989*9356374aSAndroid Build Coastguard Worker // Create equal StructWithPadding objects that are known to have non-equal
990*9356374aSAndroid Build Coastguard Worker // padding bytes.
991*9356374aSAndroid Build Coastguard Worker static const size_t kNumStructs = 10;
992*9356374aSAndroid Build Coastguard Worker unsigned char buffer1[kNumStructs * sizeof(StructWithPadding)];
993*9356374aSAndroid Build Coastguard Worker std::memset(buffer1, 0, sizeof(buffer1));
994*9356374aSAndroid Build Coastguard Worker auto* s1 = reinterpret_cast<StructWithPadding*>(buffer1);
995*9356374aSAndroid Build Coastguard Worker
996*9356374aSAndroid Build Coastguard Worker unsigned char buffer2[kNumStructs * sizeof(StructWithPadding)];
997*9356374aSAndroid Build Coastguard Worker std::memset(buffer2, 255, sizeof(buffer2));
998*9356374aSAndroid Build Coastguard Worker auto* s2 = reinterpret_cast<StructWithPadding*>(buffer2);
999*9356374aSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumStructs; ++i) {
1000*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(i);
1001*9356374aSAndroid Build Coastguard Worker s1[i].c = s2[i].c = static_cast<char>('0' + i);
1002*9356374aSAndroid Build Coastguard Worker s1[i].i = s2[i].i = static_cast<int>(i);
1003*9356374aSAndroid Build Coastguard Worker ASSERT_FALSE(memcmp(buffer1 + i * sizeof(StructWithPadding),
1004*9356374aSAndroid Build Coastguard Worker buffer2 + i * sizeof(StructWithPadding),
1005*9356374aSAndroid Build Coastguard Worker sizeof(StructWithPadding)) == 0)
1006*9356374aSAndroid Build Coastguard Worker << "Bug in test code: objects do not have unequal"
1007*9356374aSAndroid Build Coastguard Worker << " object representations";
1008*9356374aSAndroid Build Coastguard Worker }
1009*9356374aSAndroid Build Coastguard Worker
1010*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Hash<StructWithPadding>()(s1[0]), Hash<StructWithPadding>()(s2[0]));
1011*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Hash<ArraySlice<StructWithPadding>>()({s1, s1 + kNumStructs}),
1012*9356374aSAndroid Build Coastguard Worker Hash<ArraySlice<StructWithPadding>>()({s2, s2 + kNumStructs}));
1013*9356374aSAndroid Build Coastguard Worker }
1014*9356374aSAndroid Build Coastguard Worker
TEST(HashTest,StandardHashContainerUsage)1015*9356374aSAndroid Build Coastguard Worker TEST(HashTest, StandardHashContainerUsage) {
1016*9356374aSAndroid Build Coastguard Worker std::unordered_map<int, std::string, Hash<int>> map = {{0, "foo"},
1017*9356374aSAndroid Build Coastguard Worker {42, "bar"}};
1018*9356374aSAndroid Build Coastguard Worker
1019*9356374aSAndroid Build Coastguard Worker EXPECT_NE(map.find(0), map.end());
1020*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(map.find(1), map.end());
1021*9356374aSAndroid Build Coastguard Worker EXPECT_NE(map.find(0u), map.end());
1022*9356374aSAndroid Build Coastguard Worker }
1023*9356374aSAndroid Build Coastguard Worker
1024*9356374aSAndroid Build Coastguard Worker struct ConvertibleFromNoOp {
ConvertibleFromNoOp__anon1097c0110411::ConvertibleFromNoOp1025*9356374aSAndroid Build Coastguard Worker ConvertibleFromNoOp(NoOp) {} // NOLINT(runtime/explicit)
1026*9356374aSAndroid Build Coastguard Worker
1027*9356374aSAndroid Build Coastguard Worker template <typename H>
AbslHashValue(H hash_state,ConvertibleFromNoOp)1028*9356374aSAndroid Build Coastguard Worker friend H AbslHashValue(H hash_state, ConvertibleFromNoOp) {
1029*9356374aSAndroid Build Coastguard Worker return H::combine(std::move(hash_state), 1);
1030*9356374aSAndroid Build Coastguard Worker }
1031*9356374aSAndroid Build Coastguard Worker };
1032*9356374aSAndroid Build Coastguard Worker
TEST(HashTest,HeterogeneousCall)1033*9356374aSAndroid Build Coastguard Worker TEST(HashTest, HeterogeneousCall) {
1034*9356374aSAndroid Build Coastguard Worker EXPECT_NE(Hash<ConvertibleFromNoOp>()(NoOp()),
1035*9356374aSAndroid Build Coastguard Worker Hash<NoOp>()(NoOp()));
1036*9356374aSAndroid Build Coastguard Worker }
1037*9356374aSAndroid Build Coastguard Worker
TEST(IsUniquelyRepresentedTest,SanityTest)1038*9356374aSAndroid Build Coastguard Worker TEST(IsUniquelyRepresentedTest, SanityTest) {
1039*9356374aSAndroid Build Coastguard Worker using absl::hash_internal::is_uniquely_represented;
1040*9356374aSAndroid Build Coastguard Worker
1041*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_uniquely_represented<unsigned char>::value);
1042*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(is_uniquely_represented<int>::value);
1043*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(is_uniquely_represented<bool>::value);
1044*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(is_uniquely_represented<int*>::value);
1045*9356374aSAndroid Build Coastguard Worker }
1046*9356374aSAndroid Build Coastguard Worker
1047*9356374aSAndroid Build Coastguard Worker struct IntAndString {
1048*9356374aSAndroid Build Coastguard Worker int i;
1049*9356374aSAndroid Build Coastguard Worker std::string s;
1050*9356374aSAndroid Build Coastguard Worker
1051*9356374aSAndroid Build Coastguard Worker template <typename H>
AbslHashValue(H hash_state,IntAndString int_and_string)1052*9356374aSAndroid Build Coastguard Worker friend H AbslHashValue(H hash_state, IntAndString int_and_string) {
1053*9356374aSAndroid Build Coastguard Worker return H::combine(std::move(hash_state), int_and_string.s,
1054*9356374aSAndroid Build Coastguard Worker int_and_string.i);
1055*9356374aSAndroid Build Coastguard Worker }
1056*9356374aSAndroid Build Coastguard Worker };
1057*9356374aSAndroid Build Coastguard Worker
TEST(HashTest,SmallValueOn64ByteBoundary)1058*9356374aSAndroid Build Coastguard Worker TEST(HashTest, SmallValueOn64ByteBoundary) {
1059*9356374aSAndroid Build Coastguard Worker Hash<IntAndString>()(IntAndString{0, std::string(63, '0')});
1060*9356374aSAndroid Build Coastguard Worker }
1061*9356374aSAndroid Build Coastguard Worker
TEST(HashTest,TypeErased)1062*9356374aSAndroid Build Coastguard Worker TEST(HashTest, TypeErased) {
1063*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<TypeErasedValue<size_t>>::value));
1064*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((is_hashable<std::pair<TypeErasedValue<size_t>, int>>::value));
1065*9356374aSAndroid Build Coastguard Worker
1066*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(SpyHash(TypeErasedValue<size_t>(7)), SpyHash(size_t{7}));
1067*9356374aSAndroid Build Coastguard Worker EXPECT_NE(SpyHash(TypeErasedValue<size_t>(7)), SpyHash(size_t{13}));
1068*9356374aSAndroid Build Coastguard Worker
1069*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(SpyHash(std::make_pair(TypeErasedValue<size_t>(7), 17)),
1070*9356374aSAndroid Build Coastguard Worker SpyHash(std::make_pair(size_t{7}, 17)));
1071*9356374aSAndroid Build Coastguard Worker
1072*9356374aSAndroid Build Coastguard Worker absl::flat_hash_set<absl::flat_hash_set<int>> ss = {{1, 2}, {3, 4}};
1073*9356374aSAndroid Build Coastguard Worker TypeErasedContainer<absl::flat_hash_set<absl::flat_hash_set<int>>> es = {
1074*9356374aSAndroid Build Coastguard Worker absl::flat_hash_set<int>{1, 2}, {3, 4}};
1075*9356374aSAndroid Build Coastguard Worker absl::flat_hash_set<TypeErasedContainer<absl::flat_hash_set<int>>> se = {
1076*9356374aSAndroid Build Coastguard Worker {1, 2}, {3, 4}};
1077*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(SpyHash(ss), SpyHash(es));
1078*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(SpyHash(ss), SpyHash(se));
1079*9356374aSAndroid Build Coastguard Worker }
1080*9356374aSAndroid Build Coastguard Worker
1081*9356374aSAndroid Build Coastguard Worker struct ValueWithBoolConversion {
operator bool__anon1097c0110411::ValueWithBoolConversion1082*9356374aSAndroid Build Coastguard Worker operator bool() const { return false; }
1083*9356374aSAndroid Build Coastguard Worker int i;
1084*9356374aSAndroid Build Coastguard Worker };
1085*9356374aSAndroid Build Coastguard Worker
1086*9356374aSAndroid Build Coastguard Worker } // namespace
1087*9356374aSAndroid Build Coastguard Worker namespace std {
1088*9356374aSAndroid Build Coastguard Worker template <>
1089*9356374aSAndroid Build Coastguard Worker struct hash<ValueWithBoolConversion> {
operator ()std::hash1090*9356374aSAndroid Build Coastguard Worker size_t operator()(ValueWithBoolConversion v) {
1091*9356374aSAndroid Build Coastguard Worker return static_cast<size_t>(v.i);
1092*9356374aSAndroid Build Coastguard Worker }
1093*9356374aSAndroid Build Coastguard Worker };
1094*9356374aSAndroid Build Coastguard Worker } // namespace std
1095*9356374aSAndroid Build Coastguard Worker
1096*9356374aSAndroid Build Coastguard Worker namespace {
1097*9356374aSAndroid Build Coastguard Worker
TEST(HashTest,DoesNotUseImplicitConversionsToBool)1098*9356374aSAndroid Build Coastguard Worker TEST(HashTest, DoesNotUseImplicitConversionsToBool) {
1099*9356374aSAndroid Build Coastguard Worker EXPECT_NE(absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{0}),
1100*9356374aSAndroid Build Coastguard Worker absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{1}));
1101*9356374aSAndroid Build Coastguard Worker }
1102*9356374aSAndroid Build Coastguard Worker
TEST(HashOf,MatchesHashForSingleArgument)1103*9356374aSAndroid Build Coastguard Worker TEST(HashOf, MatchesHashForSingleArgument) {
1104*9356374aSAndroid Build Coastguard Worker std::string s = "forty two";
1105*9356374aSAndroid Build Coastguard Worker double d = 42.0;
1106*9356374aSAndroid Build Coastguard Worker std::tuple<int, int> t{4, 2};
1107*9356374aSAndroid Build Coastguard Worker int i = 42;
1108*9356374aSAndroid Build Coastguard Worker int neg_i = -42;
1109*9356374aSAndroid Build Coastguard Worker int16_t i16 = 42;
1110*9356374aSAndroid Build Coastguard Worker int16_t neg_i16 = -42;
1111*9356374aSAndroid Build Coastguard Worker int8_t i8 = 42;
1112*9356374aSAndroid Build Coastguard Worker int8_t neg_i8 = -42;
1113*9356374aSAndroid Build Coastguard Worker
1114*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(s), absl::Hash<std::string>{}(s));
1115*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(d), absl::Hash<double>{}(d));
1116*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(t), (absl::Hash<std::tuple<int, int>>{}(t)));
1117*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(i), absl::Hash<int>{}(i));
1118*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(neg_i), absl::Hash<int>{}(neg_i));
1119*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(i16), absl::Hash<int16_t>{}(i16));
1120*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(neg_i16), absl::Hash<int16_t>{}(neg_i16));
1121*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(i8), absl::Hash<int8_t>{}(i8));
1122*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(neg_i8), absl::Hash<int8_t>{}(neg_i8));
1123*9356374aSAndroid Build Coastguard Worker }
1124*9356374aSAndroid Build Coastguard Worker
TEST(HashOf,MatchesHashOfTupleForMultipleArguments)1125*9356374aSAndroid Build Coastguard Worker TEST(HashOf, MatchesHashOfTupleForMultipleArguments) {
1126*9356374aSAndroid Build Coastguard Worker std::string hello = "hello";
1127*9356374aSAndroid Build Coastguard Worker std::string world = "world";
1128*9356374aSAndroid Build Coastguard Worker
1129*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(), absl::HashOf(std::make_tuple()));
1130*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(hello), absl::HashOf(std::make_tuple(hello)));
1131*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::HashOf(hello, world),
1132*9356374aSAndroid Build Coastguard Worker absl::HashOf(std::make_tuple(hello, world)));
1133*9356374aSAndroid Build Coastguard Worker }
1134*9356374aSAndroid Build Coastguard Worker
1135*9356374aSAndroid Build Coastguard Worker template <typename T>
1136*9356374aSAndroid Build Coastguard Worker std::true_type HashOfExplicitParameter(decltype(absl::HashOf<T>(0))) {
1137*9356374aSAndroid Build Coastguard Worker return {};
1138*9356374aSAndroid Build Coastguard Worker }
1139*9356374aSAndroid Build Coastguard Worker template <typename T>
HashOfExplicitParameter(size_t)1140*9356374aSAndroid Build Coastguard Worker std::false_type HashOfExplicitParameter(size_t) {
1141*9356374aSAndroid Build Coastguard Worker return {};
1142*9356374aSAndroid Build Coastguard Worker }
1143*9356374aSAndroid Build Coastguard Worker
TEST(HashOf,CantPassExplicitTemplateParameters)1144*9356374aSAndroid Build Coastguard Worker TEST(HashOf, CantPassExplicitTemplateParameters) {
1145*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(HashOfExplicitParameter<int>(0));
1146*9356374aSAndroid Build Coastguard Worker }
1147*9356374aSAndroid Build Coastguard Worker
1148*9356374aSAndroid Build Coastguard Worker } // namespace
1149