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 15373 : 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 15373 : TEST(FunctionalTest, HashFloatZero) {
24 : hash<float> h;
25 2 : EXPECT_EQ(h(0.0f), h(-0.0f));
26 1 : }
27 :
28 :
29 15373 : 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 140 : 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 10300 : 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_SUITE(FunctionalTest, FunctionalTypes);
68 :
69 12376 : TYPED_TEST(FunctionalTest, EqualToImpliesSameHashCode) {
70 : hash<TypeParam> h;
71 : std::equal_to<TypeParam> e;
72 : TypeParam values[32];
73 20 : this->rng()->NextBytes(values, sizeof(values));
74 2580 : TRACED_FOREACH(TypeParam, v1, values) {
75 82560 : TRACED_FOREACH(TypeParam, v2, values) {
76 20480 : if (e(v1, v2)) {
77 1928 : EXPECT_EQ(h(v1), h(v2));
78 : }
79 : }
80 : }
81 20 : }
82 :
83 :
84 12376 : TYPED_TEST(FunctionalTest, HashEqualsHashValue) {
85 5140 : for (int i = 0; i < 128; ++i) {
86 : TypeParam v;
87 2560 : this->rng()->NextBytes(&v, sizeof(v));
88 : hash<TypeParam> h;
89 8576 : EXPECT_EQ(h(v), hash_value(v));
90 : }
91 20 : }
92 :
93 :
94 12376 : TYPED_TEST(FunctionalTest, HashIsStateless) {
95 : hash<TypeParam> h1, h2;
96 5140 : for (int i = 0; i < 128; ++i) {
97 : TypeParam v;
98 2560 : this->rng()->NextBytes(&v, sizeof(v));
99 9216 : EXPECT_EQ(h1(v), h2(v));
100 : }
101 20 : }
102 :
103 :
104 12376 : TYPED_TEST(FunctionalTest, HashIsOkish) {
105 : std::set<TypeParam> vs;
106 5140 : for (size_t i = 0; i < 128; ++i) {
107 : TypeParam v;
108 2560 : this->rng()->NextBytes(&v, sizeof(v));
109 : vs.insert(v);
110 : }
111 : std::set<size_t> hs;
112 2434 : for (const auto& v : vs) {
113 : hash<TypeParam> h;
114 7242 : hs.insert(h(v));
115 : }
116 20 : EXPECT_LE(vs.size() / 4u, hs.size());
117 20 : }
118 :
119 :
120 12376 : TYPED_TEST(FunctionalTest, HashValueArrayUsesHashRange) {
121 : TypeParam values[128];
122 20 : this->rng()->NextBytes(&values, sizeof(values));
123 60 : EXPECT_EQ(hash_range(values, values + arraysize(values)), hash_value(values));
124 20 : }
125 :
126 :
127 12376 : TYPED_TEST(FunctionalTest, BitEqualTo) {
128 : bit_equal_to<TypeParam> pred;
129 5140 : for (size_t i = 0; i < 128; ++i) {
130 : TypeParam v1, v2;
131 2560 : this->rng()->NextBytes(&v1, sizeof(v1));
132 2560 : this->rng()->NextBytes(&v2, sizeof(v2));
133 2560 : EXPECT_PRED2(pred, v1, v1);
134 2560 : EXPECT_PRED2(pred, v2, v2);
135 5376 : EXPECT_EQ(memcmp(&v1, &v2, sizeof(TypeParam)) == 0, pred(v1, v2));
136 : }
137 20 : }
138 :
139 :
140 12376 : TYPED_TEST(FunctionalTest, BitEqualToImpliesSameBitHash) {
141 : bit_hash<TypeParam> h;
142 : bit_equal_to<TypeParam> e;
143 : TypeParam values[32];
144 20 : this->rng()->NextBytes(&values, sizeof(values));
145 2580 : TRACED_FOREACH(TypeParam, v1, values) {
146 82560 : TRACED_FOREACH(TypeParam, v2, values) {
147 20480 : if (e(v1, v2)) {
148 1928 : EXPECT_EQ(h(v1), h(v2));
149 : }
150 : }
151 : }
152 20 : }
153 :
154 :
155 : namespace {
156 :
157 : struct Foo {
158 : int x;
159 : double y;
160 : };
161 :
162 :
163 72 : size_t hash_value(Foo const& v) { return hash_combine(v.x, v.y); }
164 :
165 : } // namespace
166 :
167 :
168 15373 : TEST(FunctionalTest, HashUsesArgumentDependentLookup) {
169 : const int kIntValues[] = {std::numeric_limits<int>::min(), -1, 0, 1, 42,
170 1 : std::numeric_limits<int>::max()};
171 : const double kDoubleValues[] = {
172 : std::numeric_limits<double>::min(), -1, -0, 0, 1,
173 1 : std::numeric_limits<double>::max()};
174 25 : TRACED_FOREACH(int, x, kIntValues) {
175 150 : TRACED_FOREACH(double, y, kDoubleValues) {
176 : hash<Foo> h;
177 36 : Foo foo = {x, y};
178 108 : EXPECT_EQ(hash_combine(x, y), h(foo));
179 : }
180 : }
181 1 : }
182 :
183 :
184 15373 : TEST(FunctionalTest, BitEqualToFloat) {
185 : bit_equal_to<float> pred;
186 : EXPECT_FALSE(pred(0.0f, -0.0f));
187 : EXPECT_FALSE(pred(-0.0f, 0.0f));
188 1 : float const qNaN = std::numeric_limits<float>::quiet_NaN();
189 1 : float const sNaN = std::numeric_limits<float>::signaling_NaN();
190 1 : EXPECT_PRED2(pred, qNaN, qNaN);
191 1 : EXPECT_PRED2(pred, sNaN, sNaN);
192 1 : }
193 :
194 :
195 15373 : TEST(FunctionalTest, BitHashFloatDifferentForZeroAndMinusZero) {
196 : bit_hash<float> h;
197 2 : EXPECT_NE(h(0.0f), h(-0.0f));
198 1 : }
199 :
200 :
201 15373 : TEST(FunctionalTest, BitEqualToDouble) {
202 : bit_equal_to<double> pred;
203 : EXPECT_FALSE(pred(0.0, -0.0));
204 : EXPECT_FALSE(pred(-0.0, 0.0));
205 1 : double const qNaN = std::numeric_limits<double>::quiet_NaN();
206 1 : double const sNaN = std::numeric_limits<double>::signaling_NaN();
207 1 : EXPECT_PRED2(pred, qNaN, qNaN);
208 1 : EXPECT_PRED2(pred, sNaN, sNaN);
209 1 : }
210 :
211 :
212 15373 : TEST(FunctionalTest, BitHashDoubleDifferentForZeroAndMinusZero) {
213 : bit_hash<double> h;
214 2 : EXPECT_NE(h(0.0), h(-0.0));
215 1 : }
216 :
217 : } // namespace base
218 9222 : } // namespace v8
|