Home | History | Annotate | Download | only in base
      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