1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/base/functional.h"
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include <limits>
8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include <set>
9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
10958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "test/unittests/test-utils.h"
11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace base {
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST(FunctionalTest, HashBool) {
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  hash<bool> h, h1, h2;
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_EQ(h1(true), h2(true));
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_EQ(h1(false), h2(false));
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_NE(h(true), h(false));
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST(FunctionalTest, HashFloatZero) {
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  hash<float> h;
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_EQ(h(0.0f), h(-0.0f));
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST(FunctionalTest, HashDoubleZero) {
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  hash<double> h;
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_EQ(h(0.0), h(-0.0));
32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <typename T>
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass FunctionalTest : public TestWithRandomNumberGenerator {};
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef ::testing::Types<signed char, unsigned char,
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         short,                    // NOLINT(runtime/int)
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         unsigned short,           // NOLINT(runtime/int)
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         int, unsigned int, long,  // NOLINT(runtime/int)
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         unsigned long,            // NOLINT(runtime/int)
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         long long,                // NOLINT(runtime/int)
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         unsigned long long,       // NOLINT(runtime/int)
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         int64_t, uint64_t, float, double> FunctionalTypes;
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTYPED_TEST_CASE(FunctionalTest, FunctionalTypes);
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTYPED_TEST(FunctionalTest, EqualToImpliesSameHashCode) {
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  hash<TypeParam> h;
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  std::equal_to<TypeParam> e;
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  TypeParam values[32];
55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  this->rng()->NextBytes(values, sizeof(values));
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  TRACED_FOREACH(TypeParam, v1, values) {
57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    TRACED_FOREACH(TypeParam, v2, values) {
58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (e(v1, v2)) EXPECT_EQ(h(v1), h(v2));
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTYPED_TEST(FunctionalTest, HashEqualsHashValue) {
65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0; i < 128; ++i) {
66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    TypeParam v;
67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    this->rng()->NextBytes(&v, sizeof(v));
68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    hash<TypeParam> h;
69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    EXPECT_EQ(h(v), hash_value(v));
70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTYPED_TEST(FunctionalTest, HashIsStateless) {
75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  hash<TypeParam> h1, h2;
76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0; i < 128; ++i) {
77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    TypeParam v;
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    this->rng()->NextBytes(&v, sizeof(v));
79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    EXPECT_EQ(h1(v), h2(v));
80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTYPED_TEST(FunctionalTest, HashIsOkish) {
85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  std::set<TypeParam> vs;
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (size_t i = 0; i < 128; ++i) {
87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    TypeParam v;
88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    this->rng()->NextBytes(&v, sizeof(v));
89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vs.insert(v);
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  std::set<size_t> hs;
92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (const auto& v : vs) {
93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    hash<TypeParam> h;
94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    hs.insert(h(v));
95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_LE(vs.size() / 4u, hs.size());
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTYPED_TEST(FunctionalTest, HashValueArrayUsesHashRange) {
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  TypeParam values[128];
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  this->rng()->NextBytes(&values, sizeof(values));
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_EQ(hash_range(values, values + arraysize(values)), hash_value(values));
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTYPED_TEST(FunctionalTest, BitEqualTo) {
108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bit_equal_to<TypeParam> pred;
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (size_t i = 0; i < 128; ++i) {
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    TypeParam v1, v2;
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    this->rng()->NextBytes(&v1, sizeof(v1));
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    this->rng()->NextBytes(&v2, sizeof(v2));
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    EXPECT_PRED2(pred, v1, v1);
114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    EXPECT_PRED2(pred, v2, v2);
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    EXPECT_EQ(memcmp(&v1, &v2, sizeof(TypeParam)) == 0, pred(v1, v2));
116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTYPED_TEST(FunctionalTest, BitEqualToImpliesSameBitHash) {
121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bit_hash<TypeParam> h;
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bit_equal_to<TypeParam> e;
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  TypeParam values[32];
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  this->rng()->NextBytes(&values, sizeof(values));
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  TRACED_FOREACH(TypeParam, v1, values) {
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    TRACED_FOREACH(TypeParam, v2, values) {
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (e(v1, v2)) EXPECT_EQ(h(v1), h(v2));
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace {
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstruct Foo {
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int x;
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  double y;
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniersize_t hash_value(Foo const& v) { return hash_combine(v.x, v.y); }
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace
144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST(FunctionalTest, HashUsesArgumentDependentLookup) {
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const int kIntValues[] = {std::numeric_limits<int>::min(), -1, 0, 1, 42,
148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                            std::numeric_limits<int>::max()};
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const double kDoubleValues[] = {
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      std::numeric_limits<double>::min(), -1, -0, 0, 1,
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      std::numeric_limits<double>::max()};
152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  TRACED_FOREACH(int, x, kIntValues) {
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    TRACED_FOREACH(double, y, kDoubleValues) {
154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      hash<Foo> h;
155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Foo foo = {x, y};
156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      EXPECT_EQ(hash_combine(x, y), h(foo));
157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST(FunctionalTest, BitEqualToFloat) {
163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bit_equal_to<float> pred;
164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_FALSE(pred(0.0f, -0.0f));
165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_FALSE(pred(-0.0f, 0.0f));
166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  float const qNaN = std::numeric_limits<float>::quiet_NaN();
167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  float const sNaN = std::numeric_limits<float>::signaling_NaN();
168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_PRED2(pred, qNaN, qNaN);
169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_PRED2(pred, sNaN, sNaN);
170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST(FunctionalTest, BitHashFloatDifferentForZeroAndMinusZero) {
174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bit_hash<float> h;
175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_NE(h(0.0f), h(-0.0f));
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST(FunctionalTest, BitEqualToDouble) {
180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bit_equal_to<double> pred;
181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_FALSE(pred(0.0, -0.0));
182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_FALSE(pred(-0.0, 0.0));
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  double const qNaN = std::numeric_limits<double>::quiet_NaN();
184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  double const sNaN = std::numeric_limits<double>::signaling_NaN();
185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_PRED2(pred, qNaN, qNaN);
186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_PRED2(pred, sNaN, sNaN);
187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST(FunctionalTest, BitHashDoubleDifferentForZeroAndMinusZero) {
191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bit_hash<double> h;
192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EXPECT_NE(h(0.0), h(-0.0));
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace base
196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace v8
197