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 TEST(FunctionalTest, HashBool) { 16 hash<bool> h, h1, h2; 17 EXPECT_EQ(h1(true), h2(true)); 18 EXPECT_EQ(h1(false), h2(false)); 19 EXPECT_NE(h(true), h(false)); 20 } 21 22 23 TEST(FunctionalTest, HashFloatZero) { 24 hash<float> h; 25 EXPECT_EQ(h(0.0f), h(-0.0f)); 26 } 27 28 29 TEST(FunctionalTest, HashDoubleZero) { 30 hash<double> h; 31 EXPECT_EQ(h(0.0), h(-0.0)); 32 } 33 34 35 template <typename T> 36 class FunctionalTest : public TestWithRandomNumberGenerator {}; 37 38 typedef ::testing::Types<signed char, unsigned char, 39 short, // NOLINT(runtime/int) 40 unsigned short, // NOLINT(runtime/int) 41 int, unsigned int, long, // NOLINT(runtime/int) 42 unsigned long, // NOLINT(runtime/int) 43 long long, // NOLINT(runtime/int) 44 unsigned long long, // NOLINT(runtime/int) 45 int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, 46 int64_t, uint64_t, float, double> FunctionalTypes; 47 48 TYPED_TEST_CASE(FunctionalTest, FunctionalTypes); 49 50 51 TYPED_TEST(FunctionalTest, EqualToImpliesSameHashCode) { 52 hash<TypeParam> h; 53 std::equal_to<TypeParam> e; 54 TypeParam values[32]; 55 this->rng()->NextBytes(values, sizeof(values)); 56 TRACED_FOREACH(TypeParam, v1, values) { 57 TRACED_FOREACH(TypeParam, v2, values) { 58 if (e(v1, v2)) EXPECT_EQ(h(v1), h(v2)); 59 } 60 } 61 } 62 63 64 TYPED_TEST(FunctionalTest, HashEqualsHashValue) { 65 for (int i = 0; i < 128; ++i) { 66 TypeParam v; 67 this->rng()->NextBytes(&v, sizeof(v)); 68 hash<TypeParam> h; 69 EXPECT_EQ(h(v), hash_value(v)); 70 } 71 } 72 73 74 TYPED_TEST(FunctionalTest, HashIsStateless) { 75 hash<TypeParam> h1, h2; 76 for (int i = 0; i < 128; ++i) { 77 TypeParam v; 78 this->rng()->NextBytes(&v, sizeof(v)); 79 EXPECT_EQ(h1(v), h2(v)); 80 } 81 } 82 83 84 TYPED_TEST(FunctionalTest, HashIsOkish) { 85 std::set<TypeParam> vs; 86 for (size_t i = 0; i < 128; ++i) { 87 TypeParam v; 88 this->rng()->NextBytes(&v, sizeof(v)); 89 vs.insert(v); 90 } 91 std::set<size_t> hs; 92 for (const auto& v : vs) { 93 hash<TypeParam> h; 94 hs.insert(h(v)); 95 } 96 EXPECT_LE(vs.size() / 4u, hs.size()); 97 } 98 99 100 TYPED_TEST(FunctionalTest, HashValueArrayUsesHashRange) { 101 TypeParam values[128]; 102 this->rng()->NextBytes(&values, sizeof(values)); 103 EXPECT_EQ(hash_range(values, values + arraysize(values)), hash_value(values)); 104 } 105 106 107 TYPED_TEST(FunctionalTest, BitEqualTo) { 108 bit_equal_to<TypeParam> pred; 109 for (size_t i = 0; i < 128; ++i) { 110 TypeParam v1, v2; 111 this->rng()->NextBytes(&v1, sizeof(v1)); 112 this->rng()->NextBytes(&v2, sizeof(v2)); 113 EXPECT_PRED2(pred, v1, v1); 114 EXPECT_PRED2(pred, v2, v2); 115 EXPECT_EQ(memcmp(&v1, &v2, sizeof(TypeParam)) == 0, pred(v1, v2)); 116 } 117 } 118 119 120 TYPED_TEST(FunctionalTest, BitEqualToImpliesSameBitHash) { 121 bit_hash<TypeParam> h; 122 bit_equal_to<TypeParam> e; 123 TypeParam values[32]; 124 this->rng()->NextBytes(&values, sizeof(values)); 125 TRACED_FOREACH(TypeParam, v1, values) { 126 TRACED_FOREACH(TypeParam, v2, values) { 127 if (e(v1, v2)) EXPECT_EQ(h(v1), h(v2)); 128 } 129 } 130 } 131 132 133 namespace { 134 135 struct Foo { 136 int x; 137 double y; 138 }; 139 140 141 size_t hash_value(Foo const& v) { return hash_combine(v.x, v.y); } 142 143 } // namespace 144 145 146 TEST(FunctionalTest, HashUsesArgumentDependentLookup) { 147 const int kIntValues[] = {std::numeric_limits<int>::min(), -1, 0, 1, 42, 148 std::numeric_limits<int>::max()}; 149 const double kDoubleValues[] = { 150 std::numeric_limits<double>::min(), -1, -0, 0, 1, 151 std::numeric_limits<double>::max()}; 152 TRACED_FOREACH(int, x, kIntValues) { 153 TRACED_FOREACH(double, y, kDoubleValues) { 154 hash<Foo> h; 155 Foo foo = {x, y}; 156 EXPECT_EQ(hash_combine(x, y), h(foo)); 157 } 158 } 159 } 160 161 162 TEST(FunctionalTest, BitEqualToFloat) { 163 bit_equal_to<float> pred; 164 EXPECT_FALSE(pred(0.0f, -0.0f)); 165 EXPECT_FALSE(pred(-0.0f, 0.0f)); 166 float const qNaN = std::numeric_limits<float>::quiet_NaN(); 167 float const sNaN = std::numeric_limits<float>::signaling_NaN(); 168 EXPECT_PRED2(pred, qNaN, qNaN); 169 EXPECT_PRED2(pred, sNaN, sNaN); 170 } 171 172 173 TEST(FunctionalTest, BitHashFloatDifferentForZeroAndMinusZero) { 174 bit_hash<float> h; 175 EXPECT_NE(h(0.0f), h(-0.0f)); 176 } 177 178 179 TEST(FunctionalTest, BitEqualToDouble) { 180 bit_equal_to<double> pred; 181 EXPECT_FALSE(pred(0.0, -0.0)); 182 EXPECT_FALSE(pred(-0.0, 0.0)); 183 double const qNaN = std::numeric_limits<double>::quiet_NaN(); 184 double const sNaN = std::numeric_limits<double>::signaling_NaN(); 185 EXPECT_PRED2(pred, qNaN, qNaN); 186 EXPECT_PRED2(pred, sNaN, sNaN); 187 } 188 189 190 TEST(FunctionalTest, BitHashDoubleDifferentForZeroAndMinusZero) { 191 bit_hash<double> h; 192 EXPECT_NE(h(0.0), h(-0.0)); 193 } 194 195 } // namespace base 196 } // namespace v8 197