hash_function_defaults_test.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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. #include "absl/container/internal/hash_function_defaults.h"
  15. #include <functional>
  16. #include <type_traits>
  17. #include <utility>
  18. #include "gtest/gtest.h"
  19. #include "absl/random/random.h"
  20. #include "absl/strings/cord.h"
  21. #include "absl/strings/cord_test_helpers.h"
  22. #include "absl/strings/string_view.h"
  23. namespace absl {
  24. ABSL_NAMESPACE_BEGIN
  25. namespace container_internal {
  26. namespace {
  27. using ::testing::Types;
  28. TEST(Eq, Int32) {
  29. hash_default_eq<int32_t> eq;
  30. EXPECT_TRUE(eq(1, 1u));
  31. EXPECT_TRUE(eq(1, char{1}));
  32. EXPECT_TRUE(eq(1, true));
  33. EXPECT_TRUE(eq(1, double{1.1}));
  34. EXPECT_FALSE(eq(1, char{2}));
  35. EXPECT_FALSE(eq(1, 2u));
  36. EXPECT_FALSE(eq(1, false));
  37. EXPECT_FALSE(eq(1, 2.));
  38. }
  39. TEST(Hash, Int32) {
  40. hash_default_hash<int32_t> hash;
  41. auto h = hash(1);
  42. EXPECT_EQ(h, hash(1u));
  43. EXPECT_EQ(h, hash(char{1}));
  44. EXPECT_EQ(h, hash(true));
  45. EXPECT_EQ(h, hash(double{1.1}));
  46. EXPECT_NE(h, hash(2u));
  47. EXPECT_NE(h, hash(char{2}));
  48. EXPECT_NE(h, hash(false));
  49. EXPECT_NE(h, hash(2.));
  50. }
  51. enum class MyEnum { A, B, C, D };
  52. TEST(Eq, Enum) {
  53. hash_default_eq<MyEnum> eq;
  54. EXPECT_TRUE(eq(MyEnum::A, MyEnum::A));
  55. EXPECT_FALSE(eq(MyEnum::A, MyEnum::B));
  56. }
  57. TEST(Hash, Enum) {
  58. hash_default_hash<MyEnum> hash;
  59. for (MyEnum e : {MyEnum::A, MyEnum::B, MyEnum::C}) {
  60. auto h = hash(e);
  61. EXPECT_EQ(h, hash_default_hash<int>{}(static_cast<int>(e)));
  62. EXPECT_NE(h, hash(MyEnum::D));
  63. }
  64. }
  65. using StringTypes = ::testing::Types<std::string, absl::string_view>;
  66. template <class T>
  67. struct EqString : ::testing::Test {
  68. hash_default_eq<T> key_eq;
  69. };
  70. TYPED_TEST_SUITE(EqString, StringTypes);
  71. template <class T>
  72. struct HashString : ::testing::Test {
  73. hash_default_hash<T> hasher;
  74. };
  75. TYPED_TEST_SUITE(HashString, StringTypes);
  76. TYPED_TEST(EqString, Works) {
  77. auto eq = this->key_eq;
  78. EXPECT_TRUE(eq("a", "a"));
  79. EXPECT_TRUE(eq("a", absl::string_view("a")));
  80. EXPECT_TRUE(eq("a", std::string("a")));
  81. EXPECT_FALSE(eq("a", "b"));
  82. EXPECT_FALSE(eq("a", absl::string_view("b")));
  83. EXPECT_FALSE(eq("a", std::string("b")));
  84. }
  85. TYPED_TEST(HashString, Works) {
  86. auto hash = this->hasher;
  87. auto h = hash("a");
  88. EXPECT_EQ(h, hash(absl::string_view("a")));
  89. EXPECT_EQ(h, hash(std::string("a")));
  90. EXPECT_NE(h, hash(absl::string_view("b")));
  91. EXPECT_NE(h, hash(std::string("b")));
  92. }
  93. struct NoDeleter {
  94. template <class T>
  95. void operator()(const T* ptr) const {}
  96. };
  97. using PointerTypes =
  98. ::testing::Types<const int*, int*, std::unique_ptr<const int>,
  99. std::unique_ptr<const int, NoDeleter>,
  100. std::unique_ptr<int>, std::unique_ptr<int, NoDeleter>,
  101. std::shared_ptr<const int>, std::shared_ptr<int>>;
  102. template <class T>
  103. struct EqPointer : ::testing::Test {
  104. hash_default_eq<T> key_eq;
  105. };
  106. TYPED_TEST_SUITE(EqPointer, PointerTypes);
  107. template <class T>
  108. struct HashPointer : ::testing::Test {
  109. hash_default_hash<T> hasher;
  110. };
  111. TYPED_TEST_SUITE(HashPointer, PointerTypes);
  112. TYPED_TEST(EqPointer, Works) {
  113. int dummy;
  114. auto eq = this->key_eq;
  115. auto sptr = std::make_shared<int>();
  116. std::shared_ptr<const int> csptr = sptr;
  117. int* ptr = sptr.get();
  118. const int* cptr = ptr;
  119. std::unique_ptr<int, NoDeleter> uptr(ptr);
  120. std::unique_ptr<const int, NoDeleter> cuptr(ptr);
  121. EXPECT_TRUE(eq(ptr, cptr));
  122. EXPECT_TRUE(eq(ptr, sptr));
  123. EXPECT_TRUE(eq(ptr, uptr));
  124. EXPECT_TRUE(eq(ptr, csptr));
  125. EXPECT_TRUE(eq(ptr, cuptr));
  126. EXPECT_FALSE(eq(&dummy, cptr));
  127. EXPECT_FALSE(eq(&dummy, sptr));
  128. EXPECT_FALSE(eq(&dummy, uptr));
  129. EXPECT_FALSE(eq(&dummy, csptr));
  130. EXPECT_FALSE(eq(&dummy, cuptr));
  131. }
  132. TEST(Hash, DerivedAndBase) {
  133. struct Base {};
  134. struct Derived : Base {};
  135. hash_default_hash<Base*> hasher;
  136. Base base;
  137. Derived derived;
  138. EXPECT_NE(hasher(&base), hasher(&derived));
  139. EXPECT_EQ(hasher(static_cast<Base*>(&derived)), hasher(&derived));
  140. auto dp = std::make_shared<Derived>();
  141. EXPECT_EQ(hasher(static_cast<Base*>(dp.get())), hasher(dp));
  142. }
  143. TEST(Hash, FunctionPointer) {
  144. using Func = int (*)();
  145. hash_default_hash<Func> hasher;
  146. hash_default_eq<Func> eq;
  147. Func p1 = [] { return 1; }, p2 = [] { return 2; };
  148. EXPECT_EQ(hasher(p1), hasher(p1));
  149. EXPECT_TRUE(eq(p1, p1));
  150. EXPECT_NE(hasher(p1), hasher(p2));
  151. EXPECT_FALSE(eq(p1, p2));
  152. }
  153. TYPED_TEST(HashPointer, Works) {
  154. int dummy;
  155. auto hash = this->hasher;
  156. auto sptr = std::make_shared<int>();
  157. std::shared_ptr<const int> csptr = sptr;
  158. int* ptr = sptr.get();
  159. const int* cptr = ptr;
  160. std::unique_ptr<int, NoDeleter> uptr(ptr);
  161. std::unique_ptr<const int, NoDeleter> cuptr(ptr);
  162. EXPECT_EQ(hash(ptr), hash(cptr));
  163. EXPECT_EQ(hash(ptr), hash(sptr));
  164. EXPECT_EQ(hash(ptr), hash(uptr));
  165. EXPECT_EQ(hash(ptr), hash(csptr));
  166. EXPECT_EQ(hash(ptr), hash(cuptr));
  167. EXPECT_NE(hash(&dummy), hash(cptr));
  168. EXPECT_NE(hash(&dummy), hash(sptr));
  169. EXPECT_NE(hash(&dummy), hash(uptr));
  170. EXPECT_NE(hash(&dummy), hash(csptr));
  171. EXPECT_NE(hash(&dummy), hash(cuptr));
  172. }
  173. TEST(EqCord, Works) {
  174. hash_default_eq<absl::Cord> eq;
  175. const absl::string_view a_string_view = "a";
  176. const absl::Cord a_cord(a_string_view);
  177. const absl::string_view b_string_view = "b";
  178. const absl::Cord b_cord(b_string_view);
  179. EXPECT_TRUE(eq(a_cord, a_cord));
  180. EXPECT_TRUE(eq(a_cord, a_string_view));
  181. EXPECT_TRUE(eq(a_string_view, a_cord));
  182. EXPECT_FALSE(eq(a_cord, b_cord));
  183. EXPECT_FALSE(eq(a_cord, b_string_view));
  184. EXPECT_FALSE(eq(b_string_view, a_cord));
  185. }
  186. TEST(HashCord, Works) {
  187. hash_default_hash<absl::Cord> hash;
  188. const absl::string_view a_string_view = "a";
  189. const absl::Cord a_cord(a_string_view);
  190. const absl::string_view b_string_view = "b";
  191. const absl::Cord b_cord(b_string_view);
  192. EXPECT_EQ(hash(a_cord), hash(a_cord));
  193. EXPECT_EQ(hash(b_cord), hash(b_cord));
  194. EXPECT_EQ(hash(a_string_view), hash(a_cord));
  195. EXPECT_EQ(hash(b_string_view), hash(b_cord));
  196. EXPECT_EQ(hash(absl::Cord("")), hash(""));
  197. EXPECT_EQ(hash(absl::Cord()), hash(absl::string_view()));
  198. EXPECT_NE(hash(a_cord), hash(b_cord));
  199. EXPECT_NE(hash(a_cord), hash(b_string_view));
  200. EXPECT_NE(hash(a_string_view), hash(b_cord));
  201. EXPECT_NE(hash(a_string_view), hash(b_string_view));
  202. }
  203. void NoOpReleaser(absl::string_view data, void* arg) {}
  204. TEST(HashCord, FragmentedCordWorks) {
  205. hash_default_hash<absl::Cord> hash;
  206. absl::Cord c = absl::MakeFragmentedCord({"a", "b", "c"});
  207. EXPECT_FALSE(c.TryFlat().has_value());
  208. EXPECT_EQ(hash(c), hash("abc"));
  209. }
  210. TEST(HashCord, FragmentedLongCordWorks) {
  211. hash_default_hash<absl::Cord> hash;
  212. // Crete some large strings which do not fit on the stack.
  213. std::string a(65536, 'a');
  214. std::string b(65536, 'b');
  215. absl::Cord c = absl::MakeFragmentedCord({a, b});
  216. EXPECT_FALSE(c.TryFlat().has_value());
  217. EXPECT_EQ(hash(c), hash(a + b));
  218. }
  219. TEST(HashCord, RandomCord) {
  220. hash_default_hash<absl::Cord> hash;
  221. auto bitgen = absl::BitGen();
  222. for (int i = 0; i < 1000; ++i) {
  223. const int number_of_segments = absl::Uniform(bitgen, 0, 10);
  224. std::vector<std::string> pieces;
  225. for (size_t s = 0; s < number_of_segments; ++s) {
  226. std::string str;
  227. str.resize(absl::Uniform(bitgen, 0, 4096));
  228. // MSVC needed the explicit return type in the lambda.
  229. std::generate(str.begin(), str.end(), [&]() -> char {
  230. return static_cast<char>(absl::Uniform<unsigned char>(bitgen));
  231. });
  232. pieces.push_back(str);
  233. }
  234. absl::Cord c = absl::MakeFragmentedCord(pieces);
  235. EXPECT_EQ(hash(c), hash(std::string(c)));
  236. }
  237. }
  238. // Cartesian product of (std::string, absl::string_view)
  239. // with (std::string, absl::string_view, const char*, absl::Cord).
  240. using StringTypesCartesianProduct = Types<
  241. // clang-format off
  242. std::pair<absl::Cord, std::string>,
  243. std::pair<absl::Cord, absl::string_view>,
  244. std::pair<absl::Cord, absl::Cord>,
  245. std::pair<absl::Cord, const char*>,
  246. std::pair<std::string, absl::Cord>,
  247. std::pair<absl::string_view, absl::Cord>,
  248. std::pair<absl::string_view, std::string>,
  249. std::pair<absl::string_view, absl::string_view>,
  250. std::pair<absl::string_view, const char*>>;
  251. // clang-format on
  252. constexpr char kFirstString[] = "abc123";
  253. constexpr char kSecondString[] = "ijk456";
  254. template <typename T>
  255. struct StringLikeTest : public ::testing::Test {
  256. typename T::first_type a1{kFirstString};
  257. typename T::second_type b1{kFirstString};
  258. typename T::first_type a2{kSecondString};
  259. typename T::second_type b2{kSecondString};
  260. hash_default_eq<typename T::first_type> eq;
  261. hash_default_hash<typename T::first_type> hash;
  262. };
  263. TYPED_TEST_CASE_P(StringLikeTest);
  264. TYPED_TEST_P(StringLikeTest, Eq) {
  265. EXPECT_TRUE(this->eq(this->a1, this->b1));
  266. EXPECT_TRUE(this->eq(this->b1, this->a1));
  267. }
  268. TYPED_TEST_P(StringLikeTest, NotEq) {
  269. EXPECT_FALSE(this->eq(this->a1, this->b2));
  270. EXPECT_FALSE(this->eq(this->b2, this->a1));
  271. }
  272. TYPED_TEST_P(StringLikeTest, HashEq) {
  273. EXPECT_EQ(this->hash(this->a1), this->hash(this->b1));
  274. EXPECT_EQ(this->hash(this->a2), this->hash(this->b2));
  275. // It would be a poor hash function which collides on these strings.
  276. EXPECT_NE(this->hash(this->a1), this->hash(this->b2));
  277. }
  278. TYPED_TEST_SUITE(StringLikeTest, StringTypesCartesianProduct);
  279. } // namespace
  280. } // namespace container_internal
  281. ABSL_NAMESPACE_END
  282. } // namespace absl
  283. enum Hash : size_t {
  284. kStd = 0x1, // std::hash
  285. #ifdef _MSC_VER
  286. kExtension = kStd, // In MSVC, std::hash == ::hash
  287. #else // _MSC_VER
  288. kExtension = 0x2, // ::hash (GCC extension)
  289. #endif // _MSC_VER
  290. };
  291. // H is a bitmask of Hash enumerations.
  292. // Hashable<H> is hashable via all means specified in H.
  293. template <int H>
  294. struct Hashable {
  295. static constexpr bool HashableBy(Hash h) { return h & H; }
  296. };
  297. namespace std {
  298. template <int H>
  299. struct hash<Hashable<H>> {
  300. template <class E = Hashable<H>,
  301. class = typename std::enable_if<E::HashableBy(kStd)>::type>
  302. size_t operator()(E) const {
  303. return kStd;
  304. }
  305. };
  306. } // namespace std
  307. namespace absl {
  308. ABSL_NAMESPACE_BEGIN
  309. namespace container_internal {
  310. namespace {
  311. template <class T>
  312. size_t Hash(const T& v) {
  313. return hash_default_hash<T>()(v);
  314. }
  315. TEST(Delegate, HashDispatch) {
  316. EXPECT_EQ(Hash(kStd), Hash(Hashable<kStd>()));
  317. }
  318. } // namespace
  319. } // namespace container_internal
  320. ABSL_NAMESPACE_END
  321. } // namespace absl