move Arena, ThreadCachedArena, and Malloc to memory/
[folly.git] / folly / test / HashTest.cpp
index c3c0f17db37564b9cb526c396e47b555479a3945..759f9975984cc9bf6c01504253683a491d93f6fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
 #include <folly/portability/GTest.h>
 #include <stdint.h>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 
 using namespace folly::hash;
@@ -38,6 +39,12 @@ TEST(Hash, Fnv32) {
   const uint32_t s3_res = 2166136261UL;
   EXPECT_EQ(fnv32(s3), s3_res);
   EXPECT_EQ(fnv32(s3), fnv32_buf(s3, strlen(s3)));
+
+  const uint8_t s4_data[] = {0xFF, 0xFF, 0xFF, 0x00};
+  const char* s4 = reinterpret_cast<const char*>(s4_data);
+  const uint32_t s4_res = 2420936562UL;
+  EXPECT_EQ(fnv32(s4), s4_res);
+  EXPECT_EQ(fnv32(s4), fnv32_buf(s4, strlen(s4)));
 }
 
 TEST(Hash, Fnv64) {
@@ -56,6 +63,12 @@ TEST(Hash, Fnv64) {
   EXPECT_EQ(fnv64(s3), s3_res);
   EXPECT_EQ(fnv64(s3), fnv64_buf(s3, strlen(s3)));
 
+  const uint8_t s4_data[] = {0xFF, 0xFF, 0xFF, 0x00};
+  const char* s4 = reinterpret_cast<const char*>(s4_data);
+  const uint64_t s4_res = 2787597222566293202ULL;
+  EXPECT_EQ(fnv64(s4), s4_res);
+  EXPECT_EQ(fnv64(s4), fnv64_buf(s4, strlen(s4)));
+
   // note: Use fnv64_buf to make a single hash value from multiple
   // fields/datatypes.
   const char* t4_a = "E Pluribus";
@@ -117,7 +130,7 @@ void checkTWang(uint64_t r) {
   uint64_t result = twang_mix64(r);
   EXPECT_EQ(r, twang_unmix64(result));
 }
-}  // namespace
+} // namespace
 
 TEST(Hash, TWang_Unmix64) {
   // We'll try (1 << i), (1 << i) + 1, (1 << i) - 1
@@ -155,7 +168,7 @@ void checkJenkins(uint32_t r) {
   uint32_t result = jenkins_rev_mix32(r);
   EXPECT_EQ(r, jenkins_rev_unmix32(result));
 }
-}  // namespace
+} // namespace
 
 TEST(Hash, Jenkins_Rev_Unmix32) {
   // We'll try (1 << i), (1 << i) + 1, (1 << i) - 1
@@ -173,6 +186,37 @@ TEST(Hash, hasher) {
   EXPECT_EQ(get_default(m, 4), 5);
 }
 
+TEST(Hash, integral_types) {
+  // Basically just confirms that things compile ok.
+  std::unordered_set<size_t> hashes;
+  folly::Hash hasher;
+  hashes.insert(hasher((char)1));
+  hashes.insert(hasher((signed char)2));
+  hashes.insert(hasher((unsigned char)3));
+  hashes.insert(hasher((short)4));
+  hashes.insert(hasher((signed short)5));
+  hashes.insert(hasher((unsigned short)6));
+  hashes.insert(hasher((int)7));
+  hashes.insert(hasher((signed int)8));
+  hashes.insert(hasher((unsigned int)9));
+  hashes.insert(hasher((long)10));
+  hashes.insert(hasher((signed long)11));
+  hashes.insert(hasher((unsigned long)12));
+  hashes.insert(hasher((long long)13));
+  hashes.insert(hasher((signed long long)14));
+  hashes.insert(hasher((unsigned long long)15));
+  hashes.insert(hasher((int8_t)16));
+  hashes.insert(hasher((uint8_t)17));
+  hashes.insert(hasher((int16_t)18));
+  hashes.insert(hasher((uint16_t)19));
+  hashes.insert(hasher((int32_t)20));
+  hashes.insert(hasher((uint32_t)21));
+  hashes.insert(hasher((int64_t)22));
+  hashes.insert(hasher((uint64_t)23));
+  hashes.insert(hasher((size_t)24));
+  EXPECT_EQ(24, hashes.size());
+}
+
 // Not a full hasher since only handles one type
 class TestHasher {
  public:
@@ -229,6 +273,39 @@ TEST(Hash, hash_combine) {
   EXPECT_NE(hash_combine(1, 2), hash_combine(2, 1));
 }
 
+TEST(Hash, hash_bool) {
+  const auto hash = folly::Hash();
+  EXPECT_NE(hash(true), hash(false));
+}
+
+TEST(Hash, hash_bool10) {
+  const auto hash = folly::Hash();
+  std::set<size_t> values;
+  for (bool b1 : {false, true}) {
+    for (bool b2 : {false, true}) {
+      for (bool b3 : {false, true}) {
+        for (bool b4 : {false, true}) {
+          for (bool b5 : {false, true}) {
+            for (bool b6 : {false, true}) {
+              for (bool b7 : {false, true}) {
+                for (bool b8 : {false, true}) {
+                  for (bool b9 : {false, true}) {
+                    for (bool b10 : {false, true}) {
+                      values.insert(
+                          hash(b1, b2, b3, b4, b5, b6, b7, b8, b9, b10));
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  EXPECT_EQ(values.size(), 1 << 10);
+}
+
 TEST(Hash, std_tuple) {
   typedef std::tuple<int64_t, std::string, int32_t> tuple3;
   tuple3 t(42, "foo", 1);
@@ -331,3 +408,45 @@ TEST(Hash, Strings) {
   EXPECT_EQ(h2(a3), h2(a3.str()));
   EXPECT_EQ(h2(a4), h2(a4.str()));
 }
+
+struct FNVTestParam {
+  std::string in;
+  uint64_t out;
+};
+
+class FNVTest : public ::testing::TestWithParam<FNVTestParam> {};
+
+TEST_P(FNVTest, Fnva64Buf) {
+  EXPECT_EQ(GetParam().out,
+            fnva64_buf(GetParam().in.data(), GetParam().in.size()));
+}
+
+TEST_P(FNVTest, Fnva64) {
+  EXPECT_EQ(GetParam().out, fnva64(GetParam().in));
+}
+
+TEST_P(FNVTest, Fnva64Partial) {
+  size_t partialLen = GetParam().in.size() / 2;
+  auto data = GetParam().in.data();
+  auto partial = fnva64_buf(data, partialLen);
+  EXPECT_EQ(GetParam().out,
+            fnva64_buf(
+                data + partialLen, GetParam().in.size() - partialLen, partial));
+}
+
+// Taken from http://www.isthe.com/chongo/src/fnv/test_fnv.c
+INSTANTIATE_TEST_CASE_P(
+    FNVTesting,
+    FNVTest,
+    ::testing::Values(
+        (FNVTestParam){"foobar", // 11
+                       0x85944171f73967e8},
+        (FNVTestParam){"chongo was here!\n", // 39
+                       0x46810940eff5f915},
+        (FNVTestParam){"127.0.0.3", // 106,
+                       0xaabafc7104d91158},
+        (FNVTestParam){
+            "http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash", // 126
+            0xd9b957fb7fe794c5},
+        (FNVTestParam){"http://norvig.com/21-days.html", // 136
+                       0x07aaa640476e0b9a}));