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