Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/base/functional.h"
6 :
7 : #include <limits>
8 : #include <set>
9 :
10 : #include "test/unittests/test-utils.h"
11 :
12 : namespace v8 {
13 : namespace base {
14 :
15 15128 : TEST(FunctionalTest, HashBool) {
16 : hash<bool> h, h1, h2;
17 2 : EXPECT_EQ(h1(true), h2(true));
18 2 : EXPECT_EQ(h1(false), h2(false));
19 1 : EXPECT_NE(h(true), h(false));
20 1 : }
21 :
22 :
23 15128 : TEST(FunctionalTest, HashFloatZero) {
24 : hash<float> h;
25 2 : EXPECT_EQ(h(0.0f), h(-0.0f));
26 1 : }
27 :
28 :
29 15128 : TEST(FunctionalTest, HashDoubleZero) {
30 : hash<double> h;
31 2 : EXPECT_EQ(h(0.0), h(-0.0));
32 1 : }
33 :
34 : namespace {
35 :
36 : inline int64_t GetRandomSeedFromFlag(int random_seed) {
37 280 : return random_seed ? random_seed : TimeTicks::Now().ToInternalValue();
38 : }
39 :
40 : } // namespace
41 :
42 : template <typename T>
43 : class FunctionalTest : public ::testing::Test {
44 : public:
45 140 : FunctionalTest()
46 420 : : rng_(GetRandomSeedFromFlag(::v8::internal::FLAG_random_seed)) {}
47 140 : ~FunctionalTest() override = default;
48 :
49 : RandomNumberGenerator* rng() { return &rng_; }
50 :
51 : private:
52 : RandomNumberGenerator rng_;
53 :
54 : DISALLOW_COPY_AND_ASSIGN(FunctionalTest);
55 : };
56 :
57 : typedef ::testing::Types<signed char, unsigned char,
58 : short, // NOLINT(runtime/int)
59 : unsigned short, // NOLINT(runtime/int)
60 : int, unsigned int, long, // NOLINT(runtime/int)
61 : unsigned long, // NOLINT(runtime/int)
62 : long long, // NOLINT(runtime/int)
63 : unsigned long long, // NOLINT(runtime/int)
64 : int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
65 : int64_t, uint64_t, float, double> FunctionalTypes;
66 :
67 : TYPED_TEST_CASE(FunctionalTest, FunctionalTypes);
68 :
69 :
70 12180 : TYPED_TEST(FunctionalTest, EqualToImpliesSameHashCode) {
71 : hash<TypeParam> h;
72 : std::equal_to<TypeParam> e;
73 : TypeParam values[32];
74 20 : this->rng()->NextBytes(values, sizeof(values));
75 2580 : TRACED_FOREACH(TypeParam, v1, values) {
76 102400 : TRACED_FOREACH(TypeParam, v2, values) {
77 20480 : if (e(v1, v2)) {
78 1856 : EXPECT_EQ(h(v1), h(v2));
79 : }
80 : }
81 : }
82 20 : }
83 :
84 :
85 12180 : TYPED_TEST(FunctionalTest, HashEqualsHashValue) {
86 2580 : for (int i = 0; i < 128; ++i) {
87 : TypeParam v;
88 2560 : this->rng()->NextBytes(&v, sizeof(v));
89 : hash<TypeParam> h;
90 8576 : EXPECT_EQ(h(v), hash_value(v));
91 : }
92 20 : }
93 :
94 :
95 12180 : TYPED_TEST(FunctionalTest, HashIsStateless) {
96 : hash<TypeParam> h1, h2;
97 2580 : for (int i = 0; i < 128; ++i) {
98 : TypeParam v;
99 2560 : this->rng()->NextBytes(&v, sizeof(v));
100 9216 : EXPECT_EQ(h1(v), h2(v));
101 : }
102 20 : }
103 :
104 :
105 12180 : TYPED_TEST(FunctionalTest, HashIsOkish) {
106 : std::set<TypeParam> vs;
107 2580 : for (size_t i = 0; i < 128; ++i) {
108 : TypeParam v;
109 2560 : this->rng()->NextBytes(&v, sizeof(v));
110 : vs.insert(v);
111 : }
112 : std::set<size_t> hs;
113 2492 : for (const auto& v : vs) {
114 : hash<TypeParam> h;
115 7356 : hs.insert(h(v));
116 : }
117 40 : EXPECT_LE(vs.size() / 4u, hs.size());
118 20 : }
119 :
120 :
121 12180 : TYPED_TEST(FunctionalTest, HashValueArrayUsesHashRange) {
122 : TypeParam values[128];
123 20 : this->rng()->NextBytes(&values, sizeof(values));
124 60 : EXPECT_EQ(hash_range(values, values + arraysize(values)), hash_value(values));
125 20 : }
126 :
127 :
128 12180 : TYPED_TEST(FunctionalTest, BitEqualTo) {
129 : bit_equal_to<TypeParam> pred;
130 2580 : for (size_t i = 0; i < 128; ++i) {
131 : TypeParam v1, v2;
132 2560 : this->rng()->NextBytes(&v1, sizeof(v1));
133 2560 : this->rng()->NextBytes(&v2, sizeof(v2));
134 2560 : EXPECT_PRED2(pred, v1, v1);
135 2560 : EXPECT_PRED2(pred, v2, v2);
136 7680 : EXPECT_EQ(memcmp(&v1, &v2, sizeof(TypeParam)) == 0, pred(v1, v2));
137 : }
138 20 : }
139 :
140 :
141 12180 : TYPED_TEST(FunctionalTest, BitEqualToImpliesSameBitHash) {
142 : bit_hash<TypeParam> h;
143 : bit_equal_to<TypeParam> e;
144 : TypeParam values[32];
145 20 : this->rng()->NextBytes(&values, sizeof(values));
146 2580 : TRACED_FOREACH(TypeParam, v1, values) {
147 102400 : TRACED_FOREACH(TypeParam, v2, values) {
148 20480 : if (e(v1, v2)) {
149 1856 : EXPECT_EQ(h(v1), h(v2));
150 : }
151 : }
152 : }
153 20 : }
154 :
155 :
156 : namespace {
157 :
158 : struct Foo {
159 : int x;
160 : double y;
161 : };
162 :
163 :
164 72 : size_t hash_value(Foo const& v) { return hash_combine(v.x, v.y); }
165 :
166 : } // namespace
167 :
168 :
169 15128 : TEST(FunctionalTest, HashUsesArgumentDependentLookup) {
170 : const int kIntValues[] = {std::numeric_limits<int>::min(), -1, 0, 1, 42,
171 1 : std::numeric_limits<int>::max()};
172 : const double kDoubleValues[] = {
173 : std::numeric_limits<double>::min(), -1, -0, 0, 1,
174 1 : std::numeric_limits<double>::max()};
175 37 : TRACED_FOREACH(int, x, kIntValues) {
176 252 : TRACED_FOREACH(double, y, kDoubleValues) {
177 : hash<Foo> h;
178 36 : Foo foo = {x, y};
179 108 : EXPECT_EQ(hash_combine(x, y), h(foo));
180 36 : }
181 6 : }
182 1 : }
183 :
184 :
185 15128 : TEST(FunctionalTest, BitEqualToFloat) {
186 : bit_equal_to<float> pred;
187 : EXPECT_FALSE(pred(0.0f, -0.0f));
188 : EXPECT_FALSE(pred(-0.0f, 0.0f));
189 1 : float const qNaN = std::numeric_limits<float>::quiet_NaN();
190 1 : float const sNaN = std::numeric_limits<float>::signaling_NaN();
191 1 : EXPECT_PRED2(pred, qNaN, qNaN);
192 1 : EXPECT_PRED2(pred, sNaN, sNaN);
193 1 : }
194 :
195 :
196 15128 : TEST(FunctionalTest, BitHashFloatDifferentForZeroAndMinusZero) {
197 : bit_hash<float> h;
198 2 : EXPECT_NE(h(0.0f), h(-0.0f));
199 1 : }
200 :
201 :
202 15128 : TEST(FunctionalTest, BitEqualToDouble) {
203 : bit_equal_to<double> pred;
204 : EXPECT_FALSE(pred(0.0, -0.0));
205 : EXPECT_FALSE(pred(-0.0, 0.0));
206 1 : double const qNaN = std::numeric_limits<double>::quiet_NaN();
207 1 : double const sNaN = std::numeric_limits<double>::signaling_NaN();
208 1 : EXPECT_PRED2(pred, qNaN, qNaN);
209 1 : EXPECT_PRED2(pred, sNaN, sNaN);
210 1 : }
211 :
212 :
213 15128 : TEST(FunctionalTest, BitHashDoubleDifferentForZeroAndMinusZero) {
214 : bit_hash<double> h;
215 2 : EXPECT_NE(h(0.0), h(-0.0));
216 1 : }
217 :
218 : } // namespace base
219 9075 : } // namespace v8
|