00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/hash/hash.h"
00016
00017 #include <array>
00018 #include <bitset>
00019 #include <cstring>
00020 #include <deque>
00021 #include <forward_list>
00022 #include <functional>
00023 #include <iterator>
00024 #include <limits>
00025 #include <list>
00026 #include <map>
00027 #include <memory>
00028 #include <numeric>
00029 #include <random>
00030 #include <set>
00031 #include <string>
00032 #include <tuple>
00033 #include <type_traits>
00034 #include <unordered_map>
00035 #include <utility>
00036 #include <vector>
00037
00038 #include "gmock/gmock.h"
00039 #include "gtest/gtest.h"
00040 #include "absl/container/flat_hash_set.h"
00041 #include "absl/hash/hash_testing.h"
00042 #include "absl/hash/internal/spy_hash_state.h"
00043 #include "absl/meta/type_traits.h"
00044 #include "absl/numeric/int128.h"
00045
00046 namespace {
00047
00048 using absl::Hash;
00049 using absl::hash_internal::SpyHashState;
00050
00051 template <typename T>
00052 class HashValueIntTest : public testing::Test {
00053 };
00054 TYPED_TEST_SUITE_P(HashValueIntTest);
00055
00056 template <typename T>
00057 SpyHashState SpyHash(const T& value) {
00058 return SpyHashState::combine(SpyHashState(), value);
00059 }
00060
00061
00062
00063 template <typename T>
00064 using is_hashable = std::is_default_constructible<absl::Hash<T>>;
00065
00066 TYPED_TEST_P(HashValueIntTest, BasicUsage) {
00067 EXPECT_TRUE((is_hashable<TypeParam>::value));
00068
00069 TypeParam n = 42;
00070 EXPECT_EQ(SpyHash(n), SpyHash(TypeParam{42}));
00071 EXPECT_NE(SpyHash(n), SpyHash(TypeParam{0}));
00072 EXPECT_NE(SpyHash(std::numeric_limits<TypeParam>::max()),
00073 SpyHash(std::numeric_limits<TypeParam>::min()));
00074 }
00075
00076 TYPED_TEST_P(HashValueIntTest, FastPath) {
00077
00078 TypeParam n = 42;
00079 EXPECT_EQ(absl::Hash<TypeParam>{}(n),
00080 absl::Hash<std::tuple<TypeParam>>{}(std::tuple<TypeParam>(n)));
00081 }
00082
00083 REGISTER_TYPED_TEST_CASE_P(HashValueIntTest, BasicUsage, FastPath);
00084 using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t, uint32_t,
00085 uint64_t, size_t>;
00086 INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueIntTest, IntTypes);
00087
00088 enum LegacyEnum { kValue1, kValue2, kValue3 };
00089
00090 enum class EnumClass { kValue4, kValue5, kValue6 };
00091
00092 TEST(HashValueTest, EnumAndBool) {
00093 EXPECT_TRUE((is_hashable<LegacyEnum>::value));
00094 EXPECT_TRUE((is_hashable<EnumClass>::value));
00095 EXPECT_TRUE((is_hashable<bool>::value));
00096
00097 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00098 LegacyEnum::kValue1, LegacyEnum::kValue2, LegacyEnum::kValue3)));
00099 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00100 EnumClass::kValue4, EnumClass::kValue5, EnumClass::kValue6)));
00101 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00102 std::make_tuple(true, false)));
00103 }
00104
00105 TEST(HashValueTest, FloatingPoint) {
00106 EXPECT_TRUE((is_hashable<float>::value));
00107 EXPECT_TRUE((is_hashable<double>::value));
00108 EXPECT_TRUE((is_hashable<long double>::value));
00109
00110 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00111 std::make_tuple(42.f, 0.f, -0.f, std::numeric_limits<float>::infinity(),
00112 -std::numeric_limits<float>::infinity())));
00113
00114 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00115 std::make_tuple(42., 0., -0., std::numeric_limits<double>::infinity(),
00116 -std::numeric_limits<double>::infinity())));
00117
00118 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00119
00120
00121 .5L, 1.L, 2.L, 4.L, 42.L, 0.L, -0.L,
00122 17 * static_cast<long double>(std::numeric_limits<double>::max()),
00123 std::numeric_limits<long double>::infinity(),
00124 -std::numeric_limits<long double>::infinity())));
00125 }
00126
00127 TEST(HashValueTest, Pointer) {
00128 EXPECT_TRUE((is_hashable<int*>::value));
00129
00130 int i;
00131 int* ptr = &i;
00132 int* n = nullptr;
00133
00134 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00135 std::make_tuple(&i, ptr, nullptr, ptr + 1, n)));
00136 }
00137
00138 TEST(HashValueTest, PointerAlignment) {
00139
00140
00141
00142 constexpr size_t kTotalSize = 1 << 20;
00143 std::unique_ptr<char[]> data(new char[kTotalSize]);
00144 constexpr size_t kLog2NumValues = 5;
00145 constexpr size_t kNumValues = 1 << kLog2NumValues;
00146
00147 for (size_t align = 1; align < kTotalSize / kNumValues;
00148 align < 8 ? align += 1 : align < 1024 ? align += 8 : align += 32) {
00149 SCOPED_TRACE(align);
00150 ASSERT_LE(align * kNumValues, kTotalSize);
00151
00152 size_t bits_or = 0;
00153 size_t bits_and = ~size_t{};
00154
00155 for (size_t i = 0; i < kNumValues; ++i) {
00156 size_t hash = absl::Hash<void*>()(data.get() + i * align);
00157 bits_or |= hash;
00158 bits_and &= hash;
00159 }
00160
00161
00162 constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1;
00163 size_t stuck_bits = (~bits_or | bits_and) & kMask;
00164 EXPECT_EQ(stuck_bits, 0) << "0x" << std::hex << stuck_bits;
00165 }
00166 }
00167
00168 TEST(HashValueTest, PairAndTuple) {
00169 EXPECT_TRUE((is_hashable<std::pair<int, int>>::value));
00170 EXPECT_TRUE((is_hashable<std::pair<const int&, const int&>>::value));
00171 EXPECT_TRUE((is_hashable<std::tuple<int&, int&>>::value));
00172 EXPECT_TRUE((is_hashable<std::tuple<int&&, int&&>>::value));
00173
00174 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00175 std::make_pair(0, 42), std::make_pair(0, 42), std::make_pair(42, 0),
00176 std::make_pair(0, 0), std::make_pair(42, 42), std::make_pair(1, 42))));
00177
00178 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00179 std::make_tuple(std::make_tuple(0, 0, 0), std::make_tuple(0, 0, 42),
00180 std::make_tuple(0, 23, 0), std::make_tuple(17, 0, 0),
00181 std::make_tuple(42, 0, 0), std::make_tuple(3, 9, 9),
00182 std::make_tuple(0, 0, -42))));
00183
00184
00185 int a = 0, b = 1, c = 17, d = 23;
00186 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00187 std::tie(a, a), std::tie(a, b), std::tie(b, c), std::tie(c, d))));
00188
00189
00190 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00191 std::forward_as_tuple(0, 0, 0), std::forward_as_tuple(0, 0, 42),
00192 std::forward_as_tuple(0, 23, 0), std::forward_as_tuple(17, 0, 0),
00193 std::forward_as_tuple(42, 0, 0), std::forward_as_tuple(3, 9, 9),
00194 std::forward_as_tuple(0, 0, -42))));
00195 }
00196
00197 TEST(HashValueTest, CombineContiguousWorks) {
00198 std::vector<std::tuple<int>> v1 = {std::make_tuple(1), std::make_tuple(3)};
00199 std::vector<std::tuple<int>> v2 = {std::make_tuple(1), std::make_tuple(2)};
00200
00201 auto vh1 = SpyHash(v1);
00202 auto vh2 = SpyHash(v2);
00203 EXPECT_NE(vh1, vh2);
00204 }
00205
00206 struct DummyDeleter {
00207 template <typename T>
00208 void operator() (T* ptr) {}
00209 };
00210
00211 struct SmartPointerEq {
00212 template <typename T, typename U>
00213 bool operator()(const T& t, const U& u) const {
00214 return GetPtr(t) == GetPtr(u);
00215 }
00216
00217 template <typename T>
00218 static auto GetPtr(const T& t) -> decltype(&*t) {
00219 return t ? &*t : nullptr;
00220 }
00221
00222 static std::nullptr_t GetPtr(std::nullptr_t) { return nullptr; }
00223 };
00224
00225 TEST(HashValueTest, SmartPointers) {
00226 EXPECT_TRUE((is_hashable<std::unique_ptr<int>>::value));
00227 EXPECT_TRUE((is_hashable<std::unique_ptr<int, DummyDeleter>>::value));
00228 EXPECT_TRUE((is_hashable<std::shared_ptr<int>>::value));
00229
00230 int i, j;
00231 std::unique_ptr<int, DummyDeleter> unique1(&i);
00232 std::unique_ptr<int, DummyDeleter> unique2(&i);
00233 std::unique_ptr<int, DummyDeleter> unique_other(&j);
00234 std::unique_ptr<int, DummyDeleter> unique_null;
00235
00236 std::shared_ptr<int> shared1(&i, DummyDeleter());
00237 std::shared_ptr<int> shared2(&i, DummyDeleter());
00238 std::shared_ptr<int> shared_other(&j, DummyDeleter());
00239 std::shared_ptr<int> shared_null;
00240
00241
00242 ASSERT_TRUE(SmartPointerEq{}(unique1, shared1));
00243 ASSERT_FALSE(SmartPointerEq{}(unique1, shared_other));
00244 ASSERT_TRUE(SmartPointerEq{}(unique_null, nullptr));
00245 ASSERT_FALSE(SmartPointerEq{}(shared2, nullptr));
00246
00247 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00248 std::forward_as_tuple(&i, nullptr,
00249 unique1, unique2, unique_null,
00250 absl::make_unique<int>(),
00251 shared1, shared2, shared_null,
00252 std::make_shared<int>()),
00253 SmartPointerEq{}));
00254 }
00255
00256 TEST(HashValueTest, FunctionPointer) {
00257 using Func = int (*)();
00258 EXPECT_TRUE(is_hashable<Func>::value);
00259
00260 Func p1 = [] { return 2; }, p2 = [] { return 1; };
00261 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00262 std::make_tuple(p1, p2, nullptr)));
00263 }
00264
00265 struct WrapInTuple {
00266 template <typename T>
00267 std::tuple<int, T, size_t> operator()(const T& t) const {
00268 return std::make_tuple(7, t, 0xdeadbeef);
00269 }
00270 };
00271
00272 TEST(HashValueTest, Strings) {
00273 EXPECT_TRUE((is_hashable<std::string>::value));
00274
00275 const std::string small = "foo";
00276 const std::string dup = "foofoo";
00277 const std::string large = "large";
00278 const std::string huge = std::string(5000, 'a');
00279
00280 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00281 std::string(), absl::string_view(),
00282 std::string(""), absl::string_view(""),
00283 std::string(small), absl::string_view(small),
00284 std::string(dup), absl::string_view(dup),
00285 std::string(large), absl::string_view(large),
00286 std::string(huge), absl::string_view(huge))));
00287
00288
00289 const WrapInTuple t{};
00290 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00291
00292 t(std::string()), t(absl::string_view()),
00293 t(std::string("")), t(absl::string_view("")),
00294 t(std::string(small)), t(absl::string_view(small)),
00295 t(std::string(dup)), t(absl::string_view(dup)),
00296 t(std::string(large)), t(absl::string_view(large)),
00297 t(std::string(huge)), t(absl::string_view(huge)))));
00298
00299
00300 EXPECT_NE(SpyHash(static_cast<const char*>("ABC")),
00301 SpyHash(absl::string_view("ABC")));
00302 }
00303
00304 TEST(HashValueTest, StdArray) {
00305 EXPECT_TRUE((is_hashable<std::array<int, 3>>::value));
00306
00307 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00308 std::make_tuple(std::array<int, 3>{}, std::array<int, 3>{{0, 23, 42}})));
00309 }
00310
00311 TEST(HashValueTest, StdBitset) {
00312 EXPECT_TRUE((is_hashable<std::bitset<257>>::value));
00313
00314 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00315 {std::bitset<2>("00"), std::bitset<2>("01"), std::bitset<2>("10"),
00316 std::bitset<2>("11")}));
00317 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00318 {std::bitset<5>("10101"), std::bitset<5>("10001"), std::bitset<5>()}));
00319
00320 constexpr int kNumBits = 256;
00321 std::array<std::string, 6> bit_strings;
00322 bit_strings.fill(std::string(kNumBits, '1'));
00323 bit_strings[1][0] = '0';
00324 bit_strings[2][1] = '0';
00325 bit_strings[3][kNumBits / 3] = '0';
00326 bit_strings[4][kNumBits - 2] = '0';
00327 bit_strings[5][kNumBits - 1] = '0';
00328 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00329 {std::bitset<kNumBits>(bit_strings[0].c_str()),
00330 std::bitset<kNumBits>(bit_strings[1].c_str()),
00331 std::bitset<kNumBits>(bit_strings[2].c_str()),
00332 std::bitset<kNumBits>(bit_strings[3].c_str()),
00333 std::bitset<kNumBits>(bit_strings[4].c_str()),
00334 std::bitset<kNumBits>(bit_strings[5].c_str())}));
00335 }
00336
00337 template <typename T>
00338 class HashValueSequenceTest : public testing::Test {
00339 };
00340 TYPED_TEST_SUITE_P(HashValueSequenceTest);
00341
00342 TYPED_TEST_P(HashValueSequenceTest, BasicUsage) {
00343 EXPECT_TRUE((is_hashable<TypeParam>::value));
00344
00345 using ValueType = typename TypeParam::value_type;
00346 auto a = static_cast<ValueType>(0);
00347 auto b = static_cast<ValueType>(23);
00348 auto c = static_cast<ValueType>(42);
00349
00350 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00351 std::make_tuple(TypeParam(), TypeParam{}, TypeParam{a, b, c},
00352 TypeParam{a, b}, TypeParam{b, c})));
00353 }
00354
00355 REGISTER_TYPED_TEST_CASE_P(HashValueSequenceTest, BasicUsage);
00356 using IntSequenceTypes =
00357 testing::Types<std::deque<int>, std::forward_list<int>, std::list<int>,
00358 std::vector<int>, std::vector<bool>, std::set<int>,
00359 std::multiset<int>>;
00360 INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueSequenceTest, IntSequenceTypes);
00361
00362
00363
00364
00365
00366 struct Private {
00367 int i;
00368 template <typename H>
00369 friend H AbslHashValue(H h, Private p) {
00370 return H::combine(std::move(h), std::abs(p.i));
00371 }
00372
00373 friend bool operator==(Private a, Private b) {
00374 return std::abs(a.i) == std::abs(b.i);
00375 }
00376
00377 friend std::ostream& operator<<(std::ostream& o, Private p) {
00378 return o << p.i;
00379 }
00380 };
00381
00382 TEST(HashValueTest, PrivateSanity) {
00383
00384 EXPECT_TRUE(is_hashable<Private>::value);
00385 EXPECT_NE(SpyHash(Private{0}), SpyHash(Private{1}));
00386 EXPECT_EQ(SpyHash(Private{1}), SpyHash(Private{1}));
00387 }
00388
00389 TEST(HashValueTest, Optional) {
00390 EXPECT_TRUE(is_hashable<absl::optional<Private>>::value);
00391
00392 using O = absl::optional<Private>;
00393 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
00394 std::make_tuple(O{}, O{{1}}, O{{-1}}, O{{10}})));
00395 }
00396
00397 TEST(HashValueTest, Variant) {
00398 using V = absl::variant<Private, std::string>;
00399 EXPECT_TRUE(is_hashable<V>::value);
00400
00401 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00402 V(Private{1}), V(Private{-1}), V(Private{2}), V("ABC"), V("BCD"))));
00403
00404 #if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
00405 struct S {};
00406 EXPECT_FALSE(is_hashable<absl::variant<S>>::value);
00407 #endif
00408 }
00409
00410 TEST(HashValueTest, Maps) {
00411 EXPECT_TRUE((is_hashable<std::map<int, std::string>>::value));
00412
00413 using M = std::map<int, std::string>;
00414 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00415 M{}, M{{0, "foo"}}, M{{1, "foo"}}, M{{0, "bar"}}, M{{1, "bar"}},
00416 M{{0, "foo"}, {42, "bar"}}, M{{1, "foo"}, {42, "bar"}},
00417 M{{1, "foo"}, {43, "bar"}}, M{{1, "foo"}, {43, "baz"}})));
00418
00419 using MM = std::multimap<int, std::string>;
00420 EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
00421 MM{}, MM{{0, "foo"}}, MM{{1, "foo"}}, MM{{0, "bar"}}, MM{{1, "bar"}},
00422 MM{{0, "foo"}, {0, "bar"}}, MM{{0, "bar"}, {0, "foo"}},
00423 MM{{0, "foo"}, {42, "bar"}}, MM{{1, "foo"}, {42, "bar"}},
00424 MM{{1, "foo"}, {1, "foo"}, {43, "bar"}}, MM{{1, "foo"}, {43, "baz"}})));
00425 }
00426
00427 template <typename T, typename = void>
00428 struct IsHashCallable : std::false_type {};
00429
00430 template <typename T>
00431 struct IsHashCallable<T, absl::void_t<decltype(std::declval<absl::Hash<T>>()(
00432 std::declval<const T&>()))>> : std::true_type {};
00433
00434 template <typename T, typename = void>
00435 struct IsAggregateInitializable : std::false_type {};
00436
00437 template <typename T>
00438 struct IsAggregateInitializable<T, absl::void_t<decltype(T{})>>
00439 : std::true_type {};
00440
00441 TEST(IsHashableTest, ValidHash) {
00442 EXPECT_TRUE((is_hashable<int>::value));
00443 EXPECT_TRUE(std::is_default_constructible<absl::Hash<int>>::value);
00444 EXPECT_TRUE(std::is_copy_constructible<absl::Hash<int>>::value);
00445 EXPECT_TRUE(std::is_move_constructible<absl::Hash<int>>::value);
00446 EXPECT_TRUE(absl::is_copy_assignable<absl::Hash<int>>::value);
00447 EXPECT_TRUE(absl::is_move_assignable<absl::Hash<int>>::value);
00448 EXPECT_TRUE(IsHashCallable<int>::value);
00449 EXPECT_TRUE(IsAggregateInitializable<absl::Hash<int>>::value);
00450 }
00451
00452 #if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
00453 TEST(IsHashableTest, PoisonHash) {
00454 struct X {};
00455 EXPECT_FALSE((is_hashable<X>::value));
00456 EXPECT_FALSE(std::is_default_constructible<absl::Hash<X>>::value);
00457 EXPECT_FALSE(std::is_copy_constructible<absl::Hash<X>>::value);
00458 EXPECT_FALSE(std::is_move_constructible<absl::Hash<X>>::value);
00459 EXPECT_FALSE(absl::is_copy_assignable<absl::Hash<X>>::value);
00460 EXPECT_FALSE(absl::is_move_assignable<absl::Hash<X>>::value);
00461 EXPECT_FALSE(IsHashCallable<X>::value);
00462 EXPECT_FALSE(IsAggregateInitializable<absl::Hash<X>>::value);
00463 }
00464 #endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
00465
00466
00467
00468
00469
00470 struct NoOp {
00471 template <typename HashCode>
00472 friend HashCode AbslHashValue(HashCode h, NoOp n) {
00473 return h;
00474 }
00475 };
00476
00477 struct EmptyCombine {
00478 template <typename HashCode>
00479 friend HashCode AbslHashValue(HashCode h, EmptyCombine e) {
00480 return HashCode::combine(std::move(h));
00481 }
00482 };
00483
00484 template <typename Int>
00485 struct CombineIterative {
00486 template <typename HashCode>
00487 friend HashCode AbslHashValue(HashCode h, CombineIterative c) {
00488 for (int i = 0; i < 5; ++i) {
00489 h = HashCode::combine(std::move(h), Int(i));
00490 }
00491 return h;
00492 }
00493 };
00494
00495 template <typename Int>
00496 struct CombineVariadic {
00497 template <typename HashCode>
00498 friend HashCode AbslHashValue(HashCode h, CombineVariadic c) {
00499 return HashCode::combine(std::move(h), Int(0), Int(1), Int(2), Int(3),
00500 Int(4));
00501 }
00502 };
00503 enum class InvokeTag {
00504 kUniquelyRepresented,
00505 kHashValue,
00506 #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
00507 kLegacyHash,
00508 #endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
00509 kStdHash,
00510 kNone
00511 };
00512
00513 template <InvokeTag T>
00514 using InvokeTagConstant = std::integral_constant<InvokeTag, T>;
00515
00516 template <InvokeTag... Tags>
00517 struct MinTag;
00518
00519 template <InvokeTag a, InvokeTag b, InvokeTag... Tags>
00520 struct MinTag<a, b, Tags...> : MinTag<(a < b ? a : b), Tags...> {};
00521
00522 template <InvokeTag a>
00523 struct MinTag<a> : InvokeTagConstant<a> {};
00524
00525 template <InvokeTag... Tags>
00526 struct CustomHashType {
00527 explicit CustomHashType(size_t val) : value(val) {}
00528 size_t value;
00529 };
00530
00531 template <InvokeTag allowed, InvokeTag... tags>
00532 struct EnableIfContained
00533 : std::enable_if<absl::disjunction<
00534 std::integral_constant<bool, allowed == tags>...>::value> {};
00535
00536 template <
00537 typename H, InvokeTag... Tags,
00538 typename = typename EnableIfContained<InvokeTag::kHashValue, Tags...>::type>
00539 H AbslHashValue(H state, CustomHashType<Tags...> t) {
00540 static_assert(MinTag<Tags...>::value == InvokeTag::kHashValue, "");
00541 return H::combine(std::move(state),
00542 t.value + static_cast<int>(InvokeTag::kHashValue));
00543 }
00544
00545 }
00546
00547 namespace absl {
00548 namespace hash_internal {
00549 template <InvokeTag... Tags>
00550 struct is_uniquely_represented<
00551 CustomHashType<Tags...>,
00552 typename EnableIfContained<InvokeTag::kUniquelyRepresented, Tags...>::type>
00553 : std::true_type {};
00554 }
00555 }
00556
00557 #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
00558 namespace ABSL_INTERNAL_LEGACY_HASH_NAMESPACE {
00559 template <InvokeTag... Tags>
00560 struct hash<CustomHashType<Tags...>> {
00561 template <InvokeTag... TagsIn, typename = typename EnableIfContained<
00562 InvokeTag::kLegacyHash, TagsIn...>::type>
00563 size_t operator()(CustomHashType<TagsIn...> t) const {
00564 static_assert(MinTag<Tags...>::value == InvokeTag::kLegacyHash, "");
00565 return t.value + static_cast<int>(InvokeTag::kLegacyHash);
00566 }
00567 };
00568 }
00569 #endif
00570
00571 namespace std {
00572 template <InvokeTag... Tags>
00573 struct hash<CustomHashType<Tags...>> {
00574 template <InvokeTag... TagsIn, typename = typename EnableIfContained<
00575 InvokeTag::kStdHash, TagsIn...>::type>
00576 size_t operator()(CustomHashType<TagsIn...> t) const {
00577 static_assert(MinTag<Tags...>::value == InvokeTag::kStdHash, "");
00578 return t.value + static_cast<int>(InvokeTag::kStdHash);
00579 }
00580 };
00581 }
00582
00583 namespace {
00584
00585 template <typename... T>
00586 void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>, T...) {
00587 using type = CustomHashType<T::value...>;
00588 SCOPED_TRACE(testing::PrintToString(std::vector<InvokeTag>{T::value...}));
00589 EXPECT_TRUE(is_hashable<type>());
00590 EXPECT_TRUE(is_hashable<const type>());
00591 EXPECT_TRUE(is_hashable<const type&>());
00592
00593 const size_t offset = static_cast<int>(std::min({T::value...}));
00594 EXPECT_EQ(SpyHash(type(7)), SpyHash(size_t{7 + offset}));
00595 }
00596
00597 void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>) {
00598 #if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
00599
00600 using type = CustomHashType<>;
00601 EXPECT_FALSE(is_hashable<type>());
00602 EXPECT_FALSE(is_hashable<const type>());
00603 EXPECT_FALSE(is_hashable<const type&>());
00604 #endif
00605 }
00606
00607 template <InvokeTag Tag, typename... T>
00608 void TestCustomHashType(InvokeTagConstant<Tag> tag, T... t) {
00609 constexpr auto next = static_cast<InvokeTag>(static_cast<int>(Tag) + 1);
00610 TestCustomHashType(InvokeTagConstant<next>(), tag, t...);
00611 TestCustomHashType(InvokeTagConstant<next>(), t...);
00612 }
00613
00614 TEST(HashTest, CustomHashType) {
00615 TestCustomHashType(InvokeTagConstant<InvokeTag{}>());
00616 }
00617
00618 TEST(HashTest, NoOpsAreEquivalent) {
00619 EXPECT_EQ(Hash<NoOp>()({}), Hash<NoOp>()({}));
00620 EXPECT_EQ(Hash<NoOp>()({}), Hash<EmptyCombine>()({}));
00621 }
00622
00623 template <typename T>
00624 class HashIntTest : public testing::Test {
00625 };
00626 TYPED_TEST_SUITE_P(HashIntTest);
00627
00628 TYPED_TEST_P(HashIntTest, BasicUsage) {
00629 EXPECT_NE(Hash<NoOp>()({}), Hash<TypeParam>()(0));
00630 EXPECT_NE(Hash<NoOp>()({}),
00631 Hash<TypeParam>()(std::numeric_limits<TypeParam>::max()));
00632 if (std::numeric_limits<TypeParam>::min() != 0) {
00633 EXPECT_NE(Hash<NoOp>()({}),
00634 Hash<TypeParam>()(std::numeric_limits<TypeParam>::min()));
00635 }
00636
00637 EXPECT_EQ(Hash<CombineIterative<TypeParam>>()({}),
00638 Hash<CombineVariadic<TypeParam>>()({}));
00639 }
00640
00641 REGISTER_TYPED_TEST_CASE_P(HashIntTest, BasicUsage);
00642 using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t, uint32_t,
00643 uint64_t, size_t>;
00644 INSTANTIATE_TYPED_TEST_CASE_P(My, HashIntTest, IntTypes);
00645
00646 struct StructWithPadding {
00647 char c;
00648 int i;
00649
00650 template <typename H>
00651 friend H AbslHashValue(H hash_state, const StructWithPadding& s) {
00652 return H::combine(std::move(hash_state), s.c, s.i);
00653 }
00654 };
00655
00656 static_assert(sizeof(StructWithPadding) > sizeof(char) + sizeof(int),
00657 "StructWithPadding doesn't have padding");
00658 static_assert(std::is_standard_layout<StructWithPadding>::value, "");
00659
00660
00661
00662
00663 template <typename T>
00664 struct ArraySlice {
00665 T* begin;
00666 T* end;
00667
00668 template <typename H>
00669 friend H AbslHashValue(H hash_state, const ArraySlice& slice) {
00670 for (auto t = slice.begin; t != slice.end; ++t) {
00671 hash_state = H::combine(std::move(hash_state), *t);
00672 }
00673 return hash_state;
00674 }
00675 };
00676
00677 TEST(HashTest, HashNonUniquelyRepresentedType) {
00678
00679
00680 static const size_t kNumStructs = 10;
00681 unsigned char buffer1[kNumStructs * sizeof(StructWithPadding)];
00682 std::memset(buffer1, 0, sizeof(buffer1));
00683 auto* s1 = reinterpret_cast<StructWithPadding*>(buffer1);
00684
00685 unsigned char buffer2[kNumStructs * sizeof(StructWithPadding)];
00686 std::memset(buffer2, 255, sizeof(buffer2));
00687 auto* s2 = reinterpret_cast<StructWithPadding*>(buffer2);
00688 for (int i = 0; i < kNumStructs; ++i) {
00689 SCOPED_TRACE(i);
00690 s1[i].c = s2[i].c = '0' + i;
00691 s1[i].i = s2[i].i = i;
00692 ASSERT_FALSE(memcmp(buffer1 + i * sizeof(StructWithPadding),
00693 buffer2 + i * sizeof(StructWithPadding),
00694 sizeof(StructWithPadding)) == 0)
00695 << "Bug in test code: objects do not have unequal"
00696 << " object representations";
00697 }
00698
00699 EXPECT_EQ(Hash<StructWithPadding>()(s1[0]), Hash<StructWithPadding>()(s2[0]));
00700 EXPECT_EQ(Hash<ArraySlice<StructWithPadding>>()({s1, s1 + kNumStructs}),
00701 Hash<ArraySlice<StructWithPadding>>()({s2, s2 + kNumStructs}));
00702 }
00703
00704 TEST(HashTest, StandardHashContainerUsage) {
00705 std::unordered_map<int, std::string, Hash<int>> map = {{0, "foo"},
00706 {42, "bar"}};
00707
00708 EXPECT_NE(map.find(0), map.end());
00709 EXPECT_EQ(map.find(1), map.end());
00710 EXPECT_NE(map.find(0u), map.end());
00711 }
00712
00713 struct ConvertibleFromNoOp {
00714 ConvertibleFromNoOp(NoOp) {}
00715
00716 template <typename H>
00717 friend H AbslHashValue(H hash_state, ConvertibleFromNoOp) {
00718 return H::combine(std::move(hash_state), 1);
00719 }
00720 };
00721
00722 TEST(HashTest, HeterogeneousCall) {
00723 EXPECT_NE(Hash<ConvertibleFromNoOp>()(NoOp()),
00724 Hash<NoOp>()(NoOp()));
00725 }
00726
00727 TEST(IsUniquelyRepresentedTest, SanityTest) {
00728 using absl::hash_internal::is_uniquely_represented;
00729
00730 EXPECT_TRUE(is_uniquely_represented<unsigned char>::value);
00731 EXPECT_TRUE(is_uniquely_represented<int>::value);
00732 EXPECT_FALSE(is_uniquely_represented<bool>::value);
00733 EXPECT_FALSE(is_uniquely_represented<int*>::value);
00734 }
00735
00736 struct IntAndString {
00737 int i;
00738 std::string s;
00739
00740 template <typename H>
00741 friend H AbslHashValue(H hash_state, IntAndString int_and_string) {
00742 return H::combine(std::move(hash_state), int_and_string.s,
00743 int_and_string.i);
00744 }
00745 };
00746
00747 TEST(HashTest, SmallValueOn64ByteBoundary) {
00748 Hash<IntAndString>()(IntAndString{0, std::string(63, '0')});
00749 }
00750
00751 struct TypeErased {
00752 size_t n;
00753
00754 template <typename H>
00755 friend H AbslHashValue(H hash_state, const TypeErased& v) {
00756 v.HashValue(absl::HashState::Create(&hash_state));
00757 return hash_state;
00758 }
00759
00760 void HashValue(absl::HashState state) const {
00761 absl::HashState::combine(std::move(state), n);
00762 }
00763 };
00764
00765 TEST(HashTest, TypeErased) {
00766 EXPECT_TRUE((is_hashable<TypeErased>::value));
00767 EXPECT_TRUE((is_hashable<std::pair<TypeErased, int>>::value));
00768
00769 EXPECT_EQ(SpyHash(TypeErased{7}), SpyHash(size_t{7}));
00770 EXPECT_NE(SpyHash(TypeErased{7}), SpyHash(size_t{13}));
00771
00772 EXPECT_EQ(SpyHash(std::make_pair(TypeErased{7}, 17)),
00773 SpyHash(std::make_pair(size_t{7}, 17)));
00774 }
00775
00776 struct ValueWithBoolConversion {
00777 operator bool() const { return false; }
00778 int i;
00779 };
00780
00781 }
00782 namespace std {
00783 template <>
00784 struct hash<ValueWithBoolConversion> {
00785 size_t operator()(ValueWithBoolConversion v) { return v.i; }
00786 };
00787 }
00788
00789 namespace {
00790
00791 TEST(HashTest, DoesNotUseImplicitConversionsToBool) {
00792 EXPECT_NE(absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{0}),
00793 absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{1}));
00794 }
00795
00796 }