abseil-cpp/absl/hash/hash_test.cc
Go to the documentation of this file.
1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/hash/hash.h"
16 
17 #include <algorithm>
18 #include <array>
19 #include <bitset>
20 #include <cstring>
21 #include <deque>
22 #include <forward_list>
23 #include <functional>
24 #include <initializer_list>
25 #include <iterator>
26 #include <limits>
27 #include <list>
28 #include <map>
29 #include <memory>
30 #include <numeric>
31 #include <random>
32 #include <set>
33 #include <string>
34 #include <tuple>
35 #include <type_traits>
36 #include <unordered_map>
37 #include <unordered_set>
38 #include <utility>
39 #include <vector>
40 
41 #include "gmock/gmock.h"
42 #include "gtest/gtest.h"
43 #include "absl/container/btree_map.h"
44 #include "absl/container/btree_set.h"
45 #include "absl/container/flat_hash_map.h"
46 #include "absl/container/flat_hash_set.h"
47 #include "absl/container/node_hash_map.h"
48 #include "absl/container/node_hash_set.h"
49 #include "absl/hash/hash_testing.h"
50 #include "absl/hash/internal/spy_hash_state.h"
51 #include "absl/meta/type_traits.h"
52 #include "absl/numeric/int128.h"
53 #include "absl/strings/cord_test_helpers.h"
54 
55 namespace {
56 
57 // Utility wrapper of T for the purposes of testing the `AbslHash` type erasure
58 // mechanism. `TypeErasedValue<T>` can be constructed with a `T`, and can
59 // be compared and hashed. However, all hashing goes through the hashing
60 // type-erasure framework.
61 template <typename T>
62 class TypeErasedValue {
63  public:
64  TypeErasedValue() = default;
65  TypeErasedValue(const TypeErasedValue&) = default;
66  TypeErasedValue(TypeErasedValue&&) = default;
67  explicit TypeErasedValue(const T& n) : n_(n) {}
68 
69  template <typename H>
70  friend H AbslHashValue(H hash_state, const TypeErasedValue& v) {
71  v.HashValue(absl::HashState::Create(&hash_state));
72  return hash_state;
73  }
74 
75  void HashValue(absl::HashState state) const {
77  }
78 
79  bool operator==(const TypeErasedValue& rhs) const { return n_ == rhs.n_; }
80  bool operator!=(const TypeErasedValue& rhs) const { return !(*this == rhs); }
81 
82  private:
83  T n_;
84 };
85 
86 // A TypeErasedValue refinement, for containers. It exposes the wrapped
87 // `value_type` and is constructible from an initializer list.
88 template <typename T>
89 class TypeErasedContainer : public TypeErasedValue<T> {
90  public:
91  using value_type = typename T::value_type;
92  TypeErasedContainer() = default;
93  TypeErasedContainer(const TypeErasedContainer&) = default;
94  TypeErasedContainer(TypeErasedContainer&&) = default;
95  explicit TypeErasedContainer(const T& n) : TypeErasedValue<T>(n) {}
96  TypeErasedContainer(std::initializer_list<value_type> init_list)
97  : TypeErasedContainer(T(init_list.begin(), init_list.end())) {}
98  // one-argument constructor of value type T, to appease older toolchains that
99  // get confused by one-element initializer lists in some contexts
100  explicit TypeErasedContainer(const value_type& v)
101  : TypeErasedContainer(T(&v, &v + 1)) {}
102 };
103 
104 template <typename T>
105 using TypeErasedVector = TypeErasedContainer<std::vector<T>>;
106 
107 using absl::Hash;
109 
110 template <typename T>
111 class HashValueIntTest : public testing::Test {
112 };
113 TYPED_TEST_SUITE_P(HashValueIntTest);
114 
115 template <typename T>
116 SpyHashState SpyHash(const T& value) {
117  return SpyHashState::combine(SpyHashState(), value);
118 }
119 
120 // Helper trait to verify if T is hashable. We use absl::Hash's poison status to
121 // detect it.
122 template <typename T>
123 using is_hashable = std::is_default_constructible<absl::Hash<T>>;
124 
125 TYPED_TEST_P(HashValueIntTest, BasicUsage) {
127 
128  TypeParam n = 42;
129  EXPECT_EQ(SpyHash(n), SpyHash(TypeParam{42}));
130  EXPECT_NE(SpyHash(n), SpyHash(TypeParam{0}));
133 }
134 
135 TYPED_TEST_P(HashValueIntTest, FastPath) {
136  // Test the fast-path to make sure the values are the same.
137  TypeParam n = 42;
139  absl::Hash<std::tuple<TypeParam>>{}(std::tuple<TypeParam>(n)));
140 }
141 
142 REGISTER_TYPED_TEST_SUITE_P(HashValueIntTest, BasicUsage, FastPath);
143 using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
144  uint32_t, uint64_t, size_t>;
145 INSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueIntTest, IntTypes);
146 
147 enum LegacyEnum { kValue1, kValue2, kValue3 };
148 
149 enum class EnumClass { kValue4, kValue5, kValue6 };
150 
151 TEST(HashValueTest, EnumAndBool) {
155 
157  LegacyEnum::kValue1, LegacyEnum::kValue2, LegacyEnum::kValue3)));
159  EnumClass::kValue4, EnumClass::kValue5, EnumClass::kValue6)));
161  std::make_tuple(true, false)));
162 }
163 
164 TEST(HashValueTest, FloatingPoint) {
168 
170  std::make_tuple(42.f, 0.f, -0.f, std::numeric_limits<float>::infinity(),
171  -std::numeric_limits<float>::infinity())));
172 
174  std::make_tuple(42., 0., -0., std::numeric_limits<double>::infinity(),
175  -std::numeric_limits<double>::infinity())));
176 
178  // Add some values with small exponent to test that NORMAL values also
179  // append their category.
180  .5L, 1.L, 2.L, 4.L, 42.L, 0.L, -0.L,
181  17 * static_cast<long double>(std::numeric_limits<double>::max()),
182  std::numeric_limits<long double>::infinity(),
183  -std::numeric_limits<long double>::infinity())));
184 }
185 
186 TEST(HashValueTest, Pointer) {
188  EXPECT_TRUE((is_hashable<int(*)(char, float)>::value));
189  EXPECT_TRUE((is_hashable<void(*)(int, int, ...)>::value));
190 
191  int i;
192  int* ptr = &i;
193  int* n = nullptr;
194 
196  std::make_tuple(&i, ptr, nullptr, ptr + 1, n)));
197 }
198 
199 TEST(HashValueTest, PointerAlignment) {
200  // We want to make sure that pointer alignment will not cause bits to be
201  // stuck.
202 
203  constexpr size_t kTotalSize = 1 << 20;
204  std::unique_ptr<char[]> data(new char[kTotalSize]);
205  constexpr size_t kLog2NumValues = 5;
206  constexpr size_t kNumValues = 1 << kLog2NumValues;
207 
208  for (size_t align = 1; align < kTotalSize / kNumValues;
209  align < 8 ? align += 1 : align < 1024 ? align += 8 : align += 32) {
211  ASSERT_LE(align * kNumValues, kTotalSize);
212 
213  size_t bits_or = 0;
214  size_t bits_and = ~size_t{};
215 
216  for (size_t i = 0; i < kNumValues; ++i) {
217  size_t hash = absl::Hash<void*>()(data.get() + i * align);
218  bits_or |= hash;
219  bits_and &= hash;
220  }
221 
222  // Limit the scope to the bits we would be using for Swisstable.
223  constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1;
224  size_t stuck_bits = (~bits_or | bits_and) & kMask;
225  EXPECT_EQ(stuck_bits, 0) << "0x" << std::hex << stuck_bits;
226  }
227 }
228 
229 TEST(HashValueTest, PointerToMember) {
230  struct Bass {
231  void q() {}
232  };
233 
234  struct A : Bass {
235  virtual ~A() = default;
236  virtual void vfa() {}
237 
238  static auto pq() -> void (A::*)() { return &A::q; }
239  };
240 
241  struct B : Bass {
242  virtual ~B() = default;
243  virtual void vfb() {}
244 
245  static auto pq() -> void (B::*)() { return &B::q; }
246  };
247 
248  struct Foo : A, B {
249  void f1() {}
250  void f2() const {}
251 
252  int g1() & { return 0; }
253  int g2() const & { return 0; }
254  int g3() && { return 0; }
255  int g4() const && { return 0; }
256 
257  int h1() & { return 0; }
258  int h2() const & { return 0; }
259  int h3() && { return 0; }
260  int h4() const && { return 0; }
261 
262  int a;
263  int b;
264 
265  const int c = 11;
266  const int d = 22;
267  };
268 
270  EXPECT_TRUE((is_hashable<double (Foo::*)(int, int)&&>::value));
271 
273  std::make_tuple(&Foo::a, &Foo::b, static_cast<int Foo::*>(nullptr))));
274 
276  std::make_tuple(&Foo::c, &Foo::d, static_cast<const int Foo::*>(nullptr),
277  &Foo::a, &Foo::b)));
278 
280  &Foo::f1, static_cast<void (Foo::*)()>(nullptr))));
281 
283  &Foo::f2, static_cast<void (Foo::*)() const>(nullptr))));
284 
286  &Foo::g1, &Foo::h1, static_cast<int (Foo::*)() &>(nullptr))));
287 
289  &Foo::g2, &Foo::h2, static_cast<int (Foo::*)() const &>(nullptr))));
290 
292  &Foo::g3, &Foo::h3, static_cast<int (Foo::*)() &&>(nullptr))));
293 
295  &Foo::g4, &Foo::h4, static_cast<int (Foo::*)() const &&>(nullptr))));
296 
298  std::make_tuple(static_cast<void (Foo::*)()>(&Foo::vfa),
299  static_cast<void (Foo::*)()>(&Foo::vfb),
300  static_cast<void (Foo::*)()>(nullptr))));
301 
303  std::make_tuple(static_cast<void (Foo::*)()>(Foo::A::pq()),
304  static_cast<void (Foo::*)()>(Foo::B::pq()),
305  static_cast<void (Foo::*)()>(nullptr))));
306 }
307 
308 TEST(HashValueTest, PairAndTuple) {
309  EXPECT_TRUE((is_hashable<std::pair<int, int>>::value));
310  EXPECT_TRUE((is_hashable<std::pair<const int&, const int&>>::value));
311  EXPECT_TRUE((is_hashable<std::tuple<int&, int&>>::value));
312  EXPECT_TRUE((is_hashable<std::tuple<int&&, int&&>>::value));
313 
315  std::make_pair(0, 42), std::make_pair(0, 42), std::make_pair(42, 0),
316  std::make_pair(0, 0), std::make_pair(42, 42), std::make_pair(1, 42))));
317 
319  std::make_tuple(std::make_tuple(0, 0, 0), std::make_tuple(0, 0, 42),
320  std::make_tuple(0, 23, 0), std::make_tuple(17, 0, 0),
321  std::make_tuple(42, 0, 0), std::make_tuple(3, 9, 9),
322  std::make_tuple(0, 0, -42))));
323 
324  // Test that tuples of lvalue references work (so we need a few lvalues):
325  int a = 0, b = 1, c = 17, d = 23;
327  std::tie(a, a), std::tie(a, b), std::tie(b, c), std::tie(c, d))));
328 
329  // Test that tuples of rvalue references work:
331  std::forward_as_tuple(0, 0, 0), std::forward_as_tuple(0, 0, 42),
332  std::forward_as_tuple(0, 23, 0), std::forward_as_tuple(17, 0, 0),
333  std::forward_as_tuple(42, 0, 0), std::forward_as_tuple(3, 9, 9),
334  std::forward_as_tuple(0, 0, -42))));
335 }
336 
337 TEST(HashValueTest, CombineContiguousWorks) {
338  std::vector<std::tuple<int>> v1 = {std::make_tuple(1), std::make_tuple(3)};
339  std::vector<std::tuple<int>> v2 = {std::make_tuple(1), std::make_tuple(2)};
340 
341  auto vh1 = SpyHash(v1);
342  auto vh2 = SpyHash(v2);
343  EXPECT_NE(vh1, vh2);
344 }
345 
346 struct DummyDeleter {
347  template <typename T>
348  void operator() (T* ptr) {}
349 };
350 
351 struct SmartPointerEq {
352  template <typename T, typename U>
353  bool operator()(const T& t, const U& u) const {
354  return GetPtr(t) == GetPtr(u);
355  }
356 
357  template <typename T>
358  static auto GetPtr(const T& t) -> decltype(&*t) {
359  return t ? &*t : nullptr;
360  }
361 
362  static std::nullptr_t GetPtr(std::nullptr_t) { return nullptr; }
363 };
364 
365 TEST(HashValueTest, SmartPointers) {
366  EXPECT_TRUE((is_hashable<std::unique_ptr<int>>::value));
367  EXPECT_TRUE((is_hashable<std::unique_ptr<int, DummyDeleter>>::value));
368  EXPECT_TRUE((is_hashable<std::shared_ptr<int>>::value));
369 
370  int i, j;
371  std::unique_ptr<int, DummyDeleter> unique1(&i);
372  std::unique_ptr<int, DummyDeleter> unique2(&i);
373  std::unique_ptr<int, DummyDeleter> unique_other(&j);
374  std::unique_ptr<int, DummyDeleter> unique_null;
375 
376  std::shared_ptr<int> shared1(&i, DummyDeleter());
377  std::shared_ptr<int> shared2(&i, DummyDeleter());
378  std::shared_ptr<int> shared_other(&j, DummyDeleter());
379  std::shared_ptr<int> shared_null;
380 
381  // Sanity check of the Eq function.
382  ASSERT_TRUE(SmartPointerEq{}(unique1, shared1));
383  ASSERT_FALSE(SmartPointerEq{}(unique1, shared_other));
384  ASSERT_TRUE(SmartPointerEq{}(unique_null, nullptr));
385  ASSERT_FALSE(SmartPointerEq{}(shared2, nullptr));
386 
388  std::forward_as_tuple(&i, nullptr, //
389  unique1, unique2, unique_null, //
390  absl::make_unique<int>(), //
391  shared1, shared2, shared_null, //
392  std::make_shared<int>()),
393  SmartPointerEq{}));
394 }
395 
396 TEST(HashValueTest, FunctionPointer) {
397  using Func = int (*)();
399 
400  Func p1 = [] { return 2; }, p2 = [] { return 1; };
402  std::make_tuple(p1, p2, nullptr)));
403 }
404 
405 struct WrapInTuple {
406  template <typename T>
407  std::tuple<int, T, size_t> operator()(const T& t) const {
408  return std::make_tuple(7, t, 0xdeadbeef);
409  }
410 };
411 
413  absl::Cord c(sv);
414  c.Flatten();
415  return c;
416 }
417 
419  if (sv.size() < 2) {
420  return absl::Cord(sv);
421  }
422  size_t halfway = sv.size() / 2;
423  std::vector<absl::string_view> parts = {sv.substr(0, halfway),
424  sv.substr(halfway)};
425  return absl::MakeFragmentedCord(parts);
426 }
427 
428 TEST(HashValueTest, Strings) {
430 
431  const std::string small = "foo";
432  const std::string dup = "foofoo";
433  const std::string large = std::string(2048, 'x'); // multiple of chunk size
434  const std::string huge = std::string(5000, 'a'); // not a multiple
435 
438  std::string(""), absl::string_view(""), absl::Cord(""), //
439  std::string(small), absl::string_view(small), absl::Cord(small), //
440  std::string(dup), absl::string_view(dup), absl::Cord(dup), //
442  std::string(huge), absl::string_view(huge), FlatCord(huge), //
443  FragmentedCord(huge))));
444 
445  // Also check that nested types maintain the same hash.
446  const WrapInTuple t{};
449  t(std::string("")), t(absl::string_view("")), t(absl::Cord("")), //
450  t(std::string(small)), t(absl::string_view(small)), //
451  t(absl::Cord(small)), //
452  t(std::string(dup)), t(absl::string_view(dup)), t(absl::Cord(dup)), //
454  t(absl::Cord(large)), //
455  t(std::string(huge)), t(absl::string_view(huge)), //
456  t(FlatCord(huge)), t(FragmentedCord(huge)))));
457 
458  // Make sure that hashing a `const char*` does not use its string-value.
459  EXPECT_NE(SpyHash(static_cast<const char*>("ABC")),
460  SpyHash(absl::string_view("ABC")));
461 }
462 
463 TEST(HashValueTest, WString) {
465 
467  std::wstring(), std::wstring(L"ABC"), std::wstring(L"ABC"),
468  std::wstring(L"Some other different string"),
469  std::wstring(L"Iñtërnâtiônàlizætiøn"))));
470 }
471 
472 TEST(HashValueTest, U16String) {
474 
476  std::u16string(), std::u16string(u"ABC"), std::u16string(u"ABC"),
477  std::u16string(u"Some other different string"),
478  std::u16string(u"Iñtërnâtiônàlizætiøn"))));
479 }
480 
481 TEST(HashValueTest, U32String) {
483 
485  std::u32string(), std::u32string(U"ABC"), std::u32string(U"ABC"),
486  std::u32string(U"Some other different string"),
487  std::u32string(U"Iñtërnâtiônàlizætiøn"))));
488 }
489 
490 TEST(HashValueTest, StdArray) {
491  EXPECT_TRUE((is_hashable<std::array<int, 3>>::value));
492 
494  std::make_tuple(std::array<int, 3>{}, std::array<int, 3>{{0, 23, 42}})));
495 }
496 
497 TEST(HashValueTest, StdBitset) {
498  EXPECT_TRUE((is_hashable<std::bitset<257>>::value));
499 
501  {std::bitset<2>("00"), std::bitset<2>("01"), std::bitset<2>("10"),
502  std::bitset<2>("11")}));
504  {std::bitset<5>("10101"), std::bitset<5>("10001"), std::bitset<5>()}));
505 
506  constexpr int kNumBits = 256;
507  std::array<std::string, 6> bit_strings;
508  bit_strings.fill(std::string(kNumBits, '1'));
509  bit_strings[1][0] = '0';
510  bit_strings[2][1] = '0';
511  bit_strings[3][kNumBits / 3] = '0';
512  bit_strings[4][kNumBits - 2] = '0';
513  bit_strings[5][kNumBits - 1] = '0';
515  {std::bitset<kNumBits>(bit_strings[0].c_str()),
516  std::bitset<kNumBits>(bit_strings[1].c_str()),
517  std::bitset<kNumBits>(bit_strings[2].c_str()),
518  std::bitset<kNumBits>(bit_strings[3].c_str()),
519  std::bitset<kNumBits>(bit_strings[4].c_str()),
520  std::bitset<kNumBits>(bit_strings[5].c_str())}));
521 } // namespace
522 
523 // Dummy type with unordered equality and hashing semantics. This preserves
524 // input order internally, and is used below to ensure we get test coverage
525 // for equal sequences with different iteraton orders.
526 template <typename T>
527 class UnorderedSequence {
528  public:
529  UnorderedSequence() = default;
530  template <typename TT>
531  UnorderedSequence(std::initializer_list<TT> l)
532  : values_(l.begin(), l.end()) {}
533  template <typename ForwardIterator,
535  bool>::type = true>
536  UnorderedSequence(ForwardIterator begin, ForwardIterator end)
537  : values_(begin, end) {}
538  // one-argument constructor of value type T, to appease older toolchains that
539  // get confused by one-element initializer lists in some contexts
540  explicit UnorderedSequence(const T& v) : values_(&v, &v + 1) {}
541 
542  using value_type = T;
543 
544  size_t size() const { return values_.size(); }
545  typename std::vector<T>::const_iterator begin() const {
546  return values_.begin();
547  }
548  typename std::vector<T>::const_iterator end() const { return values_.end(); }
549 
550  friend bool operator==(const UnorderedSequence& lhs,
551  const UnorderedSequence& rhs) {
552  return lhs.size() == rhs.size() &&
553  std::is_permutation(lhs.begin(), lhs.end(), rhs.begin());
554  }
555  friend bool operator!=(const UnorderedSequence& lhs,
556  const UnorderedSequence& rhs) {
557  return !(lhs == rhs);
558  }
559  template <typename H>
560  friend H AbslHashValue(H h, const UnorderedSequence& u) {
561  return H::combine(H::combine_unordered(std::move(h), u.begin(), u.end()),
562  u.size());
563  }
564 
565  private:
566  std::vector<T> values_;
567 };
568 
569 template <typename T>
570 class HashValueSequenceTest : public testing::Test {
571 };
572 TYPED_TEST_SUITE_P(HashValueSequenceTest);
573 
574 TYPED_TEST_P(HashValueSequenceTest, BasicUsage) {
576 
577  using IntType = typename TypeParam::value_type;
578  auto a = static_cast<IntType>(0);
579  auto b = static_cast<IntType>(23);
580  auto c = static_cast<IntType>(42);
581 
582  std::vector<TypeParam> exemplars = {
583  TypeParam(), TypeParam(), TypeParam{a, b, c},
584  TypeParam{a, c, b}, TypeParam{c, a, b}, TypeParam{a},
585  TypeParam{a, a}, TypeParam{a, a, a}, TypeParam{a, a, b},
586  TypeParam{a, b, a}, TypeParam{b, a, a}, TypeParam{a, b},
587  TypeParam{b, c}};
589 }
590 
591 REGISTER_TYPED_TEST_SUITE_P(HashValueSequenceTest, BasicUsage);
592 using IntSequenceTypes = testing::Types<
593  std::deque<int>, std::forward_list<int>, std::list<int>, std::vector<int>,
594  std::vector<bool>, TypeErasedContainer<std::vector<int>>, std::set<int>,
595  std::multiset<int>, UnorderedSequence<int>,
596  TypeErasedContainer<UnorderedSequence<int>>, std::unordered_set<int>,
597  std::unordered_multiset<int>, absl::flat_hash_set<int>,
599 INSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueSequenceTest, IntSequenceTypes);
600 
601 template <typename T>
602 class HashValueNestedSequenceTest : public testing::Test {};
603 TYPED_TEST_SUITE_P(HashValueNestedSequenceTest);
604 
605 TYPED_TEST_P(HashValueNestedSequenceTest, BasicUsage) {
606  using T = TypeParam;
607  using V = typename T::value_type;
608  std::vector<T> exemplars = {
609  // empty case
610  T{},
611  // sets of empty sets
612  T{V{}}, T{V{}, V{}}, T{V{}, V{}, V{}},
613  // multisets of different values
614  T{V{1}}, T{V{1, 1}, V{1, 1}}, T{V{1, 1, 1}, V{1, 1, 1}, V{1, 1, 1}},
615  // various orderings of same nested sets
616  T{V{}, V{1, 2}}, T{V{}, V{2, 1}}, T{V{1, 2}, V{}}, T{V{2, 1}, V{}},
617  // various orderings of various nested sets, case 2
618  T{V{1, 2}, V{3, 4}}, T{V{1, 2}, V{4, 3}}, T{V{1, 3}, V{2, 4}},
619  T{V{1, 3}, V{4, 2}}, T{V{1, 4}, V{2, 3}}, T{V{1, 4}, V{3, 2}},
620  T{V{2, 3}, V{1, 4}}, T{V{2, 3}, V{4, 1}}, T{V{2, 4}, V{1, 3}},
621  T{V{2, 4}, V{3, 1}}, T{V{3, 4}, V{1, 2}}, T{V{3, 4}, V{2, 1}}};
623 }
624 
625 REGISTER_TYPED_TEST_SUITE_P(HashValueNestedSequenceTest, BasicUsage);
626 template <typename T>
627 using TypeErasedSet = TypeErasedContainer<UnorderedSequence<T>>;
628 
629 using NestedIntSequenceTypes = testing::Types<
630  std::vector<std::vector<int>>, std::vector<UnorderedSequence<int>>,
631  std::vector<TypeErasedSet<int>>, UnorderedSequence<std::vector<int>>,
632  UnorderedSequence<UnorderedSequence<int>>,
633  UnorderedSequence<TypeErasedSet<int>>, TypeErasedSet<std::vector<int>>,
634  TypeErasedSet<UnorderedSequence<int>>, TypeErasedSet<TypeErasedSet<int>>>;
635 INSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueNestedSequenceTest,
636  NestedIntSequenceTypes);
637 
638 // Private type that only supports AbslHashValue to make sure our chosen hash
639 // implementation is recursive within absl::Hash.
640 // It uses std::abs() on the value to provide different bitwise representations
641 // of the same logical value.
642 struct Private {
643  int i;
644  template <typename H>
645  friend H AbslHashValue(H h, Private p) {
646  return H::combine(std::move(h), std::abs(p.i));
647  }
648 
649  friend bool operator==(Private a, Private b) {
650  return std::abs(a.i) == std::abs(b.i);
651  }
652 
653  friend std::ostream& operator<<(std::ostream& o, Private p) {
654  return o << p.i;
655  }
656 };
657 
658 // Test helper for combine_piecewise_buffer. It holds a string_view to the
659 // buffer-to-be-hashed. Its AbslHashValue specialization will split up its
660 // contents at the character offsets requested.
661 class PiecewiseHashTester {
662  public:
663  // Create a hash view of a buffer to be hashed contiguously.
664  explicit PiecewiseHashTester(absl::string_view buf)
665  : buf_(buf), piecewise_(false), split_locations_() {}
666 
667  // Create a hash view of a buffer to be hashed piecewise, with breaks at the
668  // given locations.
669  PiecewiseHashTester(absl::string_view buf, std::set<size_t> split_locations)
670  : buf_(buf),
671  piecewise_(true),
672  split_locations_(std::move(split_locations)) {}
673 
674  template <typename H>
675  friend H AbslHashValue(H h, const PiecewiseHashTester& p) {
676  if (!p.piecewise_) {
677  return H::combine_contiguous(std::move(h), p.buf_.data(), p.buf_.size());
678  }
680  if (p.split_locations_.empty()) {
681  h = combiner.add_buffer(std::move(h), p.buf_.data(), p.buf_.size());
682  return combiner.finalize(std::move(h));
683  }
684  size_t begin = 0;
685  for (size_t next : p.split_locations_) {
686  absl::string_view chunk = p.buf_.substr(begin, next - begin);
687  h = combiner.add_buffer(std::move(h), chunk.data(), chunk.size());
688  begin = next;
689  }
690  absl::string_view last_chunk = p.buf_.substr(begin);
691  if (!last_chunk.empty()) {
692  h = combiner.add_buffer(std::move(h), last_chunk.data(),
693  last_chunk.size());
694  }
695  return combiner.finalize(std::move(h));
696  }
697 
698  private:
700  bool piecewise_;
701  std::set<size_t> split_locations_;
702 };
703 
704 // Dummy object that hashes as two distinct contiguous buffers, "foo" followed
705 // by "bar"
706 struct DummyFooBar {
707  template <typename H>
708  friend H AbslHashValue(H h, const DummyFooBar&) {
709  const char* foo = "foo";
710  const char* bar = "bar";
711  h = H::combine_contiguous(std::move(h), foo, 3);
712  h = H::combine_contiguous(std::move(h), bar, 3);
713  return h;
714  }
715 };
716 
717 TEST(HashValueTest, CombinePiecewiseBuffer) {
719 
720  // Check that hashing an empty buffer through the piecewise API works.
721  EXPECT_EQ(hash(PiecewiseHashTester("")), hash(PiecewiseHashTester("", {})));
722 
723  // Similarly, small buffers should give consistent results
724  EXPECT_EQ(hash(PiecewiseHashTester("foobar")),
725  hash(PiecewiseHashTester("foobar", {})));
726  EXPECT_EQ(hash(PiecewiseHashTester("foobar")),
727  hash(PiecewiseHashTester("foobar", {3})));
728 
729  // But hashing "foobar" in pieces gives a different answer than hashing "foo"
730  // contiguously, then "bar" contiguously.
731  EXPECT_NE(hash(PiecewiseHashTester("foobar", {3})),
732  absl::Hash<DummyFooBar>()(DummyFooBar{}));
733 
734  // Test hashing a large buffer incrementally, broken up in several different
735  // ways. Arrange for breaks on and near the stride boundaries to look for
736  // off-by-one errors in the implementation.
737  //
738  // This test is run on a buffer that is a multiple of the stride size, and one
739  // that isn't.
740  for (size_t big_buffer_size : {1024 * 2 + 512, 1024 * 3}) {
741  SCOPED_TRACE(big_buffer_size);
742  std::string big_buffer;
743  for (int i = 0; i < big_buffer_size; ++i) {
744  // Arbitrary string
745  big_buffer.push_back(32 + (i * (i / 3)) % 64);
746  }
747  auto big_buffer_hash = hash(PiecewiseHashTester(big_buffer));
748 
749  const int possible_breaks = 9;
750  size_t breaks[possible_breaks] = {1, 512, 1023, 1024, 1025,
751  1536, 2047, 2048, 2049};
752  for (unsigned test_mask = 0; test_mask < (1u << possible_breaks);
753  ++test_mask) {
754  SCOPED_TRACE(test_mask);
755  std::set<size_t> break_locations;
756  for (int j = 0; j < possible_breaks; ++j) {
757  if (test_mask & (1u << j)) {
758  break_locations.insert(breaks[j]);
759  }
760  }
761  EXPECT_EQ(
762  hash(PiecewiseHashTester(big_buffer, std::move(break_locations))),
763  big_buffer_hash);
764  }
765  }
766 }
767 
768 TEST(HashValueTest, PrivateSanity) {
769  // Sanity check that Private is working as the tests below expect it to work.
771  EXPECT_NE(SpyHash(Private{0}), SpyHash(Private{1}));
772  EXPECT_EQ(SpyHash(Private{1}), SpyHash(Private{1}));
773 }
774 
775 TEST(HashValueTest, Optional) {
777 
778  using O = absl::optional<Private>;
780  std::make_tuple(O{}, O{{1}}, O{{-1}}, O{{10}})));
781 }
782 
783 TEST(HashValueTest, Variant) {
786 
788  V(Private{1}), V(Private{-1}), V(Private{2}), V("ABC"), V("BCD"))));
789 
790 #if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
791  struct S {};
792  EXPECT_FALSE(is_hashable<absl::variant<S>>::value);
793 #endif
794 }
795 
796 template <typename T>
797 class HashValueAssociativeMapTest : public testing::Test {};
798 TYPED_TEST_SUITE_P(HashValueAssociativeMapTest);
799 
800 TYPED_TEST_P(HashValueAssociativeMapTest, BasicUsage) {
801  using M = TypeParam;
802  using V = typename M::value_type;
803  std::vector<M> exemplars{M{},
804  M{V{0, "foo"}},
805  M{V{1, "foo"}},
806  M{V{0, "bar"}},
807  M{V{1, "bar"}},
808  M{V{0, "foo"}, V{42, "bar"}},
809  M{V{42, "bar"}, V{0, "foo"}},
810  M{V{1, "foo"}, V{42, "bar"}},
811  M{V{1, "foo"}, V{43, "bar"}},
812  M{V{1, "foo"}, V{43, "baz"}}};
814 }
815 
816 REGISTER_TYPED_TEST_SUITE_P(HashValueAssociativeMapTest, BasicUsage);
817 using AssociativeMapTypes = testing::Types<
818  std::map<int, std::string>, std::unordered_map<int, std::string>,
821  UnorderedSequence<std::pair<const int, std::string>>>;
822 INSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueAssociativeMapTest,
823  AssociativeMapTypes);
824 
825 template <typename T>
826 class HashValueAssociativeMultimapTest : public testing::Test {};
827 TYPED_TEST_SUITE_P(HashValueAssociativeMultimapTest);
828 
829 TYPED_TEST_P(HashValueAssociativeMultimapTest, BasicUsage) {
830  using MM = TypeParam;
831  using V = typename MM::value_type;
832  std::vector<MM> exemplars{MM{},
833  MM{V{0, "foo"}},
834  MM{V{1, "foo"}},
835  MM{V{0, "bar"}},
836  MM{V{1, "bar"}},
837  MM{V{0, "foo"}, V{0, "bar"}},
838  MM{V{0, "bar"}, V{0, "foo"}},
839  MM{V{0, "foo"}, V{42, "bar"}},
840  MM{V{1, "foo"}, V{42, "bar"}},
841  MM{V{1, "foo"}, V{1, "foo"}, V{43, "bar"}},
842  MM{V{1, "foo"}, V{43, "bar"}, V{1, "foo"}},
843  MM{V{1, "foo"}, V{43, "baz"}}};
845 }
846 
847 REGISTER_TYPED_TEST_SUITE_P(HashValueAssociativeMultimapTest, BasicUsage);
848 using AssociativeMultimapTypes =
850  std::unordered_multimap<int, std::string>>;
851 INSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueAssociativeMultimapTest,
852  AssociativeMultimapTypes);
853 
854 TEST(HashValueTest, ReferenceWrapper) {
855  EXPECT_TRUE(is_hashable<std::reference_wrapper<Private>>::value);
856 
857  Private p1{1}, p10{10};
859  p1, p10, std::ref(p1), std::ref(p10), std::cref(p1), std::cref(p10))));
860 
861  EXPECT_TRUE(is_hashable<std::reference_wrapper<int>>::value);
862  int one = 1, ten = 10;
864  one, ten, std::ref(one), std::ref(ten), std::cref(one), std::cref(ten))));
865 
867  std::make_tuple(std::tuple<std::reference_wrapper<int>>(std::ref(one)),
868  std::tuple<std::reference_wrapper<int>>(std::ref(ten)),
869  std::tuple<int>(one), std::tuple<int>(ten))));
870 }
871 
872 template <typename T, typename = void>
873 struct IsHashCallable : std::false_type {};
874 
875 template <typename T>
876 struct IsHashCallable<T, absl::void_t<decltype(std::declval<absl::Hash<T>>()(
877  std::declval<const T&>()))>> : std::true_type {};
878 
879 template <typename T, typename = void>
880 struct IsAggregateInitializable : std::false_type {};
881 
882 template <typename T>
883 struct IsAggregateInitializable<T, absl::void_t<decltype(T{})>>
884  : std::true_type {};
885 
886 TEST(IsHashableTest, ValidHash) {
888  EXPECT_TRUE(std::is_default_constructible<absl::Hash<int>>::value);
889  EXPECT_TRUE(std::is_copy_constructible<absl::Hash<int>>::value);
890  EXPECT_TRUE(std::is_move_constructible<absl::Hash<int>>::value);
894  EXPECT_TRUE(IsAggregateInitializable<absl::Hash<int>>::value);
895 }
896 
897 #if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
898 TEST(IsHashableTest, PoisonHash) {
899  struct X {};
901  EXPECT_FALSE(std::is_default_constructible<absl::Hash<X>>::value);
902  EXPECT_FALSE(std::is_copy_constructible<absl::Hash<X>>::value);
903  EXPECT_FALSE(std::is_move_constructible<absl::Hash<X>>::value);
907 #if !defined(__GNUC__) || __GNUC__ < 9
908  // This doesn't compile on GCC 9.
909  EXPECT_FALSE(IsAggregateInitializable<absl::Hash<X>>::value);
910 #endif
911 }
912 #endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
913 
914 // Hashable types
915 //
916 // These types exist simply to exercise various AbslHashValue behaviors, so
917 // they are named by what their AbslHashValue overload does.
918 struct NoOp {
919  template <typename HashCode>
920  friend HashCode AbslHashValue(HashCode h, NoOp n) {
921  return h;
922  }
923 };
924 
925 struct EmptyCombine {
926  template <typename HashCode>
927  friend HashCode AbslHashValue(HashCode h, EmptyCombine e) {
928  return HashCode::combine(std::move(h));
929  }
930 };
931 
932 template <typename Int>
933 struct CombineIterative {
934  template <typename HashCode>
935  friend HashCode AbslHashValue(HashCode h, CombineIterative c) {
936  for (int i = 0; i < 5; ++i) {
937  h = HashCode::combine(std::move(h), Int(i));
938  }
939  return h;
940  }
941 };
942 
943 template <typename Int>
944 struct CombineVariadic {
945  template <typename HashCode>
946  friend HashCode AbslHashValue(HashCode h, CombineVariadic c) {
947  return HashCode::combine(std::move(h), Int(0), Int(1), Int(2), Int(3),
948  Int(4));
949  }
950 };
951 enum class InvokeTag {
952  kUniquelyRepresented,
953  kHashValue,
954 #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
955  kLegacyHash,
956 #endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
957  kStdHash,
958  kNone
959 };
960 
961 template <InvokeTag T>
962 using InvokeTagConstant = std::integral_constant<InvokeTag, T>;
963 
964 template <InvokeTag... Tags>
965 struct MinTag;
966 
967 template <InvokeTag a, InvokeTag b, InvokeTag... Tags>
968 struct MinTag<a, b, Tags...> : MinTag<(a < b ? a : b), Tags...> {};
969 
970 template <InvokeTag a>
971 struct MinTag<a> : InvokeTagConstant<a> {};
972 
973 template <InvokeTag... Tags>
974 struct CustomHashType {
975  explicit CustomHashType(size_t val) : value(val) {}
976  size_t value;
977 };
978 
979 template <InvokeTag allowed, InvokeTag... tags>
980 struct EnableIfContained
981  : std::enable_if<absl::disjunction<
982  std::integral_constant<bool, allowed == tags>...>::value> {};
983 
984 template <
985  typename H, InvokeTag... Tags,
986  typename = typename EnableIfContained<InvokeTag::kHashValue, Tags...>::type>
987 H AbslHashValue(H state, CustomHashType<Tags...> t) {
988  static_assert(MinTag<Tags...>::value == InvokeTag::kHashValue, "");
989  return H::combine(std::move(state),
990  t.value + static_cast<int>(InvokeTag::kHashValue));
991 }
992 
993 } // namespace
994 
995 namespace absl {
996 ABSL_NAMESPACE_BEGIN
997 namespace hash_internal {
998 template <InvokeTag... Tags>
999 struct is_uniquely_represented<
1000  CustomHashType<Tags...>,
1001  typename EnableIfContained<InvokeTag::kUniquelyRepresented, Tags...>::type>
1002  : std::true_type {};
1003 } // namespace hash_internal
1004 ABSL_NAMESPACE_END
1005 } // namespace absl
1006 
1007 #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
1008 namespace ABSL_INTERNAL_LEGACY_HASH_NAMESPACE {
1009 template <InvokeTag... Tags>
1010 struct hash<CustomHashType<Tags...>> {
1011  template <InvokeTag... TagsIn, typename = typename EnableIfContained<
1012  InvokeTag::kLegacyHash, TagsIn...>::type>
1013  size_t operator()(CustomHashType<TagsIn...> t) const {
1014  static_assert(MinTag<Tags...>::value == InvokeTag::kLegacyHash, "");
1015  return t.value + static_cast<int>(InvokeTag::kLegacyHash);
1016  }
1017 };
1018 } // namespace ABSL_INTERNAL_LEGACY_HASH_NAMESPACE
1019 #endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
1020 
1021 namespace std {
1022 template <InvokeTag... Tags> // NOLINT
1023 struct hash<CustomHashType<Tags...>> {
1024  template <InvokeTag... TagsIn, typename = typename EnableIfContained<
1025  InvokeTag::kStdHash, TagsIn...>::type>
1026  size_t operator()(CustomHashType<TagsIn...> t) const {
1027  static_assert(MinTag<Tags...>::value == InvokeTag::kStdHash, "");
1028  return t.value + static_cast<int>(InvokeTag::kStdHash);
1029  }
1030 };
1031 } // namespace std
1032 
1033 namespace {
1034 
1035 template <typename... T>
1036 void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>, T...) {
1037  using type = CustomHashType<T::value...>;
1038  SCOPED_TRACE(testing::PrintToString(std::vector<InvokeTag>{T::value...}));
1039  EXPECT_TRUE(is_hashable<type>());
1040  EXPECT_TRUE(is_hashable<const type>());
1041  EXPECT_TRUE(is_hashable<const type&>());
1042 
1043  const size_t offset = static_cast<int>(std::min({T::value...}));
1044  EXPECT_EQ(SpyHash(type(7)), SpyHash(size_t{7 + offset}));
1045 }
1046 
1047 void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>) {
1048 #if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
1049  // is_hashable is false if we don't support any of the hooks.
1050  using type = CustomHashType<>;
1051  EXPECT_FALSE(is_hashable<type>());
1052  EXPECT_FALSE(is_hashable<const type>());
1053  EXPECT_FALSE(is_hashable<const type&>());
1054 #endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
1055 }
1056 
1057 template <InvokeTag Tag, typename... T>
1058 void TestCustomHashType(InvokeTagConstant<Tag> tag, T... t) {
1059  constexpr auto next = static_cast<InvokeTag>(static_cast<int>(Tag) + 1);
1060  TestCustomHashType(InvokeTagConstant<next>(), tag, t...);
1061  TestCustomHashType(InvokeTagConstant<next>(), t...);
1062 }
1063 
1064 TEST(HashTest, CustomHashType) {
1065  TestCustomHashType(InvokeTagConstant<InvokeTag{}>());
1066 }
1067 
1068 TEST(HashTest, NoOpsAreEquivalent) {
1069  EXPECT_EQ(Hash<NoOp>()({}), Hash<NoOp>()({}));
1070  EXPECT_EQ(Hash<NoOp>()({}), Hash<EmptyCombine>()({}));
1071 }
1072 
1073 template <typename T>
1074 class HashIntTest : public testing::Test {
1075 };
1076 TYPED_TEST_SUITE_P(HashIntTest);
1077 
1078 TYPED_TEST_P(HashIntTest, BasicUsage) {
1079  EXPECT_NE(Hash<NoOp>()({}), Hash<TypeParam>()(0));
1080  EXPECT_NE(Hash<NoOp>()({}),
1081  Hash<TypeParam>()(std::numeric_limits<TypeParam>::max()));
1082  if (std::numeric_limits<TypeParam>::min() != 0) {
1083  EXPECT_NE(Hash<NoOp>()({}),
1084  Hash<TypeParam>()(std::numeric_limits<TypeParam>::min()));
1085  }
1086 
1087  EXPECT_EQ(Hash<CombineIterative<TypeParam>>()({}),
1088  Hash<CombineVariadic<TypeParam>>()({}));
1089 }
1090 
1091 REGISTER_TYPED_TEST_SUITE_P(HashIntTest, BasicUsage);
1092 using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
1093  uint32_t, uint64_t, size_t>;
1094 INSTANTIATE_TYPED_TEST_SUITE_P(My, HashIntTest, IntTypes);
1095 
1096 struct StructWithPadding {
1097  char c;
1098  int i;
1099 
1100  template <typename H>
1101  friend H AbslHashValue(H hash_state, const StructWithPadding& s) {
1102  return H::combine(std::move(hash_state), s.c, s.i);
1103  }
1104 };
1105 
1106 static_assert(sizeof(StructWithPadding) > sizeof(char) + sizeof(int),
1107  "StructWithPadding doesn't have padding");
1108 static_assert(std::is_standard_layout<StructWithPadding>::value, "");
1109 
1110 // This check has to be disabled because libstdc++ doesn't support it.
1111 // static_assert(std::is_trivially_constructible<StructWithPadding>::value, "");
1112 
1113 template <typename T>
1114 struct ArraySlice {
1115  T* begin;
1116  T* end;
1117 
1118  template <typename H>
1119  friend H AbslHashValue(H hash_state, const ArraySlice& slice) {
1120  for (auto t = slice.begin; t != slice.end; ++t) {
1121  hash_state = H::combine(std::move(hash_state), *t);
1122  }
1123  return hash_state;
1124  }
1125 };
1126 
1127 TEST(HashTest, HashNonUniquelyRepresentedType) {
1128  // Create equal StructWithPadding objects that are known to have non-equal
1129  // padding bytes.
1130  static const size_t kNumStructs = 10;
1131  unsigned char buffer1[kNumStructs * sizeof(StructWithPadding)];
1132  std::memset(buffer1, 0, sizeof(buffer1));
1133  auto* s1 = reinterpret_cast<StructWithPadding*>(buffer1);
1134 
1135  unsigned char buffer2[kNumStructs * sizeof(StructWithPadding)];
1136  std::memset(buffer2, 255, sizeof(buffer2));
1137  auto* s2 = reinterpret_cast<StructWithPadding*>(buffer2);
1138  for (int i = 0; i < kNumStructs; ++i) {
1139  SCOPED_TRACE(i);
1140  s1[i].c = s2[i].c = '0' + i;
1141  s1[i].i = s2[i].i = i;
1142  ASSERT_FALSE(memcmp(buffer1 + i * sizeof(StructWithPadding),
1143  buffer2 + i * sizeof(StructWithPadding),
1144  sizeof(StructWithPadding)) == 0)
1145  << "Bug in test code: objects do not have unequal"
1146  << " object representations";
1147  }
1148 
1150  EXPECT_EQ(Hash<ArraySlice<StructWithPadding>>()({s1, s1 + kNumStructs}),
1151  Hash<ArraySlice<StructWithPadding>>()({s2, s2 + kNumStructs}));
1152 }
1153 
1154 TEST(HashTest, StandardHashContainerUsage) {
1155  std::unordered_map<int, std::string, Hash<int>> map = {{0, "foo"},
1156  {42, "bar"}};
1157 
1158  EXPECT_NE(map.find(0), map.end());
1159  EXPECT_EQ(map.find(1), map.end());
1160  EXPECT_NE(map.find(0u), map.end());
1161 }
1162 
1163 struct ConvertibleFromNoOp {
1164  ConvertibleFromNoOp(NoOp) {} // NOLINT(runtime/explicit)
1165 
1166  template <typename H>
1167  friend H AbslHashValue(H hash_state, ConvertibleFromNoOp) {
1168  return H::combine(std::move(hash_state), 1);
1169  }
1170 };
1171 
1172 TEST(HashTest, HeterogeneousCall) {
1174  Hash<NoOp>()(NoOp()));
1175 }
1176 
1177 TEST(IsUniquelyRepresentedTest, SanityTest) {
1179 
1184 }
1185 
1186 struct IntAndString {
1187  int i;
1188  std::string s;
1189 
1190  template <typename H>
1191  friend H AbslHashValue(H hash_state, IntAndString int_and_string) {
1192  return H::combine(std::move(hash_state), int_and_string.s,
1193  int_and_string.i);
1194  }
1195 };
1196 
1197 TEST(HashTest, SmallValueOn64ByteBoundary) {
1198  Hash<IntAndString>()(IntAndString{0, std::string(63, '0')});
1199 }
1200 
1201 TEST(HashTest, TypeErased) {
1202  EXPECT_TRUE((is_hashable<TypeErasedValue<size_t>>::value));
1203  EXPECT_TRUE((is_hashable<std::pair<TypeErasedValue<size_t>, int>>::value));
1204 
1205  EXPECT_EQ(SpyHash(TypeErasedValue<size_t>(7)), SpyHash(size_t{7}));
1206  EXPECT_NE(SpyHash(TypeErasedValue<size_t>(7)), SpyHash(size_t{13}));
1207 
1208  EXPECT_EQ(SpyHash(std::make_pair(TypeErasedValue<size_t>(7), 17)),
1209  SpyHash(std::make_pair(size_t{7}, 17)));
1210 
1211  absl::flat_hash_set<absl::flat_hash_set<int>> ss = {{1, 2}, {3, 4}};
1212  TypeErasedContainer<absl::flat_hash_set<absl::flat_hash_set<int>>> es = {
1213  absl::flat_hash_set<int>{1, 2}, {3, 4}};
1215  {1, 2}, {3, 4}};
1216  EXPECT_EQ(SpyHash(ss), SpyHash(es));
1217  EXPECT_EQ(SpyHash(ss), SpyHash(se));
1218 }
1219 
1220 struct ValueWithBoolConversion {
1221  operator bool() const { return false; }
1222  int i;
1223 };
1224 
1225 } // namespace
1226 namespace std {
1227 template <>
1228 struct hash<ValueWithBoolConversion> {
1229  size_t operator()(ValueWithBoolConversion v) { return v.i; }
1230 };
1231 } // namespace std
1232 
1233 namespace {
1234 
1235 TEST(HashTest, DoesNotUseImplicitConversionsToBool) {
1236  EXPECT_NE(absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{0}),
1237  absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{1}));
1238 }
1239 
1240 TEST(HashOf, MatchesHashForSingleArgument) {
1241  std::string s = "forty two";
1242  int i = 42;
1243  double d = 42.0;
1244  std::tuple<int, int> t{4, 2};
1245 
1249  EXPECT_EQ(absl::HashOf(t), (absl::Hash<std::tuple<int, int>>{}(t)));
1250 }
1251 
1252 TEST(HashOf, MatchesHashOfTupleForMultipleArguments) {
1253  std::string hello = "hello";
1254  std::string world = "world";
1255 
1258  EXPECT_EQ(absl::HashOf(hello, world),
1260 }
1261 
1262 template <typename T>
1263 std::true_type HashOfExplicitParameter(decltype(absl::HashOf<T>(0))) {
1264  return {};
1265 }
1266 template <typename T>
1267 std::false_type HashOfExplicitParameter(size_t) {
1268  return {};
1269 }
1270 
1271 TEST(HashOf, CantPassExplicitTemplateParameters) {
1272  EXPECT_FALSE(HashOfExplicitParameter<int>(0));
1273 }
1274 
1275 } // namespace
TYPED_TEST_P
#define TYPED_TEST_P(SuiteName, TestName)
Definition: googletest/googletest/include/gtest/gtest-typed-test.h:270
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
absl::Cord
Definition: abseil-cpp/absl/strings/cord.h:150
absl::debugging_internal::Optional
static bool Optional(bool)
Definition: abseil-cpp/absl/debugging/internal/demangle.cc:333
absl::AbslHashValue
H AbslHashValue(H h, const absl::InlinedVector< T, N, A > &a)
Definition: abseil-cpp/absl/container/inlined_vector.h:858
absl::HashState::Create
static HashState Create(T *state)
Definition: abseil-cpp/absl/hash/hash.h:321
Hash
Hash
Definition: abseil-cpp/absl/container/internal/hash_function_defaults_test.cc:339
absl::str_format_internal::LengthMod::j
@ j
absl::VerifyTypeImplementsAbslHashCorrectly
ABSL_NAMESPACE_BEGIN ABSL_MUST_USE_RESULT testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(const Container &values)
Definition: abseil-cpp/absl/hash/hash_testing.h:345
grpc_event_engine::experimental::slice_detail::operator==
bool operator==(const BaseSlice &a, const BaseSlice &b)
Definition: include/grpc/event_engine/slice.h:117
absl::hash_internal::Hash
Definition: abseil-cpp/absl/hash/internal/hash.h:1221
X
#define X(c)
const
#define const
Definition: bloaty/third_party/zlib/zconf.h:230
bool
bool
Definition: setup_once.h:312
absl::HashOf
size_t HashOf(const Types &... values)
Definition: abseil-cpp/absl/hash/hash.h:264
memset
return memset(p, 0, total)
S
#define S(s)
begin
char * begin
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1007
false
#define false
Definition: setup_once.h:323
std::tr1::make_tuple
tuple make_tuple()
Definition: cares/cares/test/gmock-1.8.0/gtest/gtest.h:1619
NoOp
Definition: bm_call_create.cc:477
xds_manager.f1
f1
Definition: xds_manager.py:42
large
int large
Definition: bloaty/third_party/zlib/examples/enough.c:172
bar
Definition: bloaty/third_party/googletest/googletest/test/googletest-output-test_.cc:562
google::protobuf.internal::true_type
integral_constant< bool, true > true_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:89
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
google::protobuf.internal::false_type
integral_constant< bool, false > false_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:90
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
absl::hash_internal::is_uniquely_represented
Definition: abseil-cpp/absl/hash/internal/hash.h:296
foo
Definition: bloaty/third_party/googletest/googletest/test/googletest-output-test_.cc:546
absl::node_hash_map
Definition: abseil-cpp/absl/container/node_hash_map.h:107
absl::hash_internal::HashStateBase< HashState >::combine
static HashState combine(HashState state, const T &value, const Ts &... values)
Definition: abseil-cpp/absl/hash/internal/hash.h:1226
absl::btree_set
Definition: abseil-cpp/absl/container/btree_set.h:86
absl::FormatConversionChar::s
@ s
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
ASSERT_LE
#define ASSERT_LE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2064
xds_manager.p
p
Definition: xds_manager.py:60
absl::flags_internal::HelpMode::kNone
@ kNone
absl::container_internal::hash_internal::EnumClass
EnumClass
Definition: abseil-cpp/absl/container/internal/hash_generator_testing.h:58
map
zval * map
Definition: php/ext/google/protobuf/encode_decode.c:480
T
#define T(upbtypeconst, upbtype, ctype, default_value)
gen_build_yaml.struct
def struct(**kwargs)
Definition: test/core/end2end/gen_build_yaml.py:30
true
#define true
Definition: setup_once.h:324
testing::Test
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:402
FragmentedCord
absl::Cord FragmentedCord(size_t size)
Definition: abseil-cpp/absl/hash/hash_benchmark.cc:94
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
o
UnboundConversion o
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:97
hash
uint64_t hash
Definition: ring_hash.cc:284
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
testing::internal::ProxyTypeList
Definition: googletest/googletest/include/gtest/internal/gtest-type-util.h:155
hello
static z_const char hello[]
Definition: bloaty/third_party/zlib/test/example.c:29
c
void c(T a)
Definition: miscompile_with_no_unique_address_test.cc:40
SCOPED_TRACE
#define SCOPED_TRACE(message)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2264
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
xds_interop_client.int
int
Definition: xds_interop_client.py:113
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
absl::hash_internal::PiecewiseCombiner::add_buffer
H add_buffer(H state, const unsigned char *data, size_t size)
Definition: abseil-cpp/absl/hash/internal/hash.h:1249
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
absl::string_view::size
constexpr size_type size() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:277
Foo
Definition: abseil-cpp/absl/debugging/symbolize_test.cc:65
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
TEST
#define TEST(name, init_size,...)
Definition: arena_test.cc:75
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
absl::random_internal_nanobenchmark::Func
FuncOutput(*)(const void *, FuncInput) Func
Definition: abseil-cpp/absl/random/internal/nanobenchmark.h:68
FlatCord
absl::Cord FlatCord(size_t size)
Definition: abseil-cpp/absl/hash/hash_benchmark.cc:88
EXPECT_NE
#define EXPECT_NE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2028
slice
grpc_slice slice
Definition: src/core/lib/surface/server.cc:467
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
absl::flat_hash_set
Definition: abseil-cpp/absl/container/flat_hash_set.h:105
absl::optional
Definition: abseil-cpp/absl/types/internal/optional.h:61
absl::inlined_vector_internal::Pointer
typename AllocatorTraits< A >::pointer Pointer
Definition: abseil-cpp/absl/container/internal/inlined_vector.h:52
ref
unsigned ref
Definition: cxa_demangle.cpp:4909
absl::compare_internal::value_type
int8_t value_type
Definition: abseil-cpp/absl/types/compare.h:45
operator!=
bool operator!=(const Bytes &a, const Bytes &b)
Definition: boringssl-with-bazel/src/crypto/test/test_util.h:58
buf_
char buf_[N]
Definition: cxa_demangle.cpp:4722
INSTANTIATE_TYPED_TEST_SUITE_P
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types,...)
Definition: googletest/googletest/include/gtest/gtest-typed-test.h:306
testing::internal::wstring
::std::wstring wstring
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:887
REGISTER_TYPED_TEST_SUITE_P
#define REGISTER_TYPED_TEST_SUITE_P(SuiteName,...)
Definition: googletest/googletest/include/gtest/gtest-typed-test.h:289
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
min
#define min(a, b)
Definition: qsort.h:83
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
n_
int n_
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3877
Json::Int
int Int
Definition: third_party/bloaty/third_party/protobuf/conformance/third_party/jsoncpp/json.h:228
d
static const fe d
Definition: curve25519_tables.h:19
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
H
#define H(b, c, d)
Definition: md4.c:114
absl::node_hash_set
Definition: abseil-cpp/absl/container/node_hash_set.h:100
value
const char * value
Definition: hpack_parser_table.cc:165
TYPED_TEST_SUITE_P
#define TYPED_TEST_SUITE_P(SuiteName)
Definition: googletest/googletest/include/gtest/gtest-typed-test.h:259
absl::void_t
typename type_traits_internal::VoidTImpl< Ts... >::type void_t
Definition: abseil-cpp/absl/meta/type_traits.h:218
A::~A
~A()
Definition: miscompile_with_no_unique_address_test.cc:25
absl::time_internal::cctz::detail::align
CONSTEXPR_F fields align(second_tag, fields f) noexcept
Definition: abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h:325
std::hash< ValueWithBoolConversion >::operator()
size_t operator()(ValueWithBoolConversion v)
Definition: abseil-cpp/absl/hash/hash_test.cc:1229
absl::hash_internal::SpyHashState
SpyHashStateImpl< void > SpyHashState
Definition: abseil-cpp/absl/hash/internal/spy_hash_state.h:260
absl::str_format_internal::LengthMod::t
@ t
next
AllocList * next[kMaxLevel]
Definition: abseil-cpp/absl/base/internal/low_level_alloc.cc:100
L
lua_State * L
Definition: upb/upb/bindings/lua/main.c:35
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
absl::flat_hash_map
Definition: abseil-cpp/absl/container/flat_hash_map.h:113
A
Definition: miscompile_with_no_unique_address_test.cc:23
ASSERT_TRUE
#define ASSERT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1973
ASSERT_FALSE
#define ASSERT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1976
state
Definition: bloaty/third_party/zlib/contrib/blast/blast.c:41
absl::is_copy_assignable
Definition: abseil-cpp/absl/meta/type_traits.h:194
absl::hash_internal::PiecewiseCombiner::finalize
H finalize(H state)
Definition: abseil-cpp/absl/hash/internal/hash.h:1282
testing::internal::Strings
::std::vector< ::std::string > Strings
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-printers.h:872
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1967
absl::str_format_internal::LengthMod::q
@ q
absl::MakeFragmentedCord
Cord MakeFragmentedCord(const Container &c)
Definition: abseil-cpp/absl/strings/cord_test_helpers.h:103
absl::string_view::empty
constexpr bool empty() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:292
absl::is_move_assignable
Definition: abseil-cpp/absl/meta/type_traits.h:199
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
xds_manager.f2
f2
Definition: xds_manager.py:85
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
setup.template
template
Definition: setup.py:47
run_grpclb_interop_tests.l
dictionary l
Definition: run_grpclb_interop_tests.py:410
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
grpc::operator<<
std::ostream & operator<<(std::ostream &out, const string_ref &string)
Definition: grpcpp/impl/codegen/string_ref.h:145
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
absl::variant
Definition: abseil-cpp/absl/types/internal/variant.h:46
absl::string_view::data
constexpr const_pointer data() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:336
absl::str_format_internal::LengthMod::h
@ h
absl::btree_map
Definition: abseil-cpp/absl/container/btree_map.h:84
pair
std::pair< std::string, std::string > pair
Definition: abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc:78
absl::string_view::substr
constexpr string_view substr(size_type pos=0, size_type n=npos) const
Definition: abseil-cpp/absl/strings/string_view.h:399
absl::HashState
Definition: abseil-cpp/absl/hash/hash.h:312
absl::hash_internal::PiecewiseCombiner
Definition: abseil-cpp/absl/hash/internal/hash.h:89
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
absl::Hash
absl::hash_internal::Hash< T > Hash
Definition: abseil-cpp/absl/hash/hash.h:247


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:01