/*
- * Copyright 2013 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#include "folly/Hash.h"
-#include "folly/MapUtil.h"
+#include <folly/Hash.h>
+#include <folly/MapUtil.h>
#include <gtest/gtest.h>
#include <stdint.h>
#include <unordered_map>
TEST(Hash, Fnv32) {
const char* s1 = "hello, world!";
- const uint32_t s1_res = 3180823791ul;
+ const uint32_t s1_res = 3605494790UL;
EXPECT_EQ(fnv32(s1), s1_res);
EXPECT_EQ(fnv32(s1), fnv32_buf(s1, strlen(s1)));
const char* s2 = "monkeys! m0nk3yz! ev3ry \\/\\/here~~~~";
- const uint32_t s2_res = 194407565ul;
+ const uint32_t s2_res = 1270448334UL;
EXPECT_EQ(fnv32(s2), s2_res);
EXPECT_EQ(fnv32(s2), fnv32_buf(s2, strlen(s2)));
const char* s3 = "";
- const uint32_t s3_res = 216613626ul;
+ const uint32_t s3_res = 2166136261UL;
EXPECT_EQ(fnv32(s3), s3_res);
EXPECT_EQ(fnv32(s3), fnv32_buf(s3, strlen(s3)));
}
m[t] = "bar";
EXPECT_EQ("bar", m[t]);
}
+
+TEST(Hash, enum_type) {
+ const auto hash = folly::Hash();
+
+ enum class Enum32 : int32_t { Foo, Bar };
+ EXPECT_EQ(hash(static_cast<int32_t>(Enum32::Foo)), hash(Enum32::Foo));
+ EXPECT_EQ(hash(static_cast<int32_t>(Enum32::Bar)), hash(Enum32::Bar));
+ EXPECT_NE(hash(Enum32::Foo), hash(Enum32::Bar));
+
+ std::unordered_map<Enum32, std::string, folly::Hash> m32;
+ m32[Enum32::Foo] = "foo";
+ EXPECT_EQ("foo", m32[Enum32::Foo]);
+
+ enum class Enum64 : int64_t { Foo, Bar };
+ EXPECT_EQ(hash(static_cast<int64_t>(Enum64::Foo)), hash(Enum64::Foo));
+ EXPECT_EQ(hash(static_cast<int64_t>(Enum64::Bar)), hash(Enum64::Bar));
+ EXPECT_NE(hash(Enum64::Foo), hash(Enum64::Bar));
+
+ std::unordered_map<Enum64, std::string, folly::Hash> m64;
+ m64[Enum64::Foo] = "foo";
+ EXPECT_EQ("foo", m64[Enum64::Foo]);
+}
+
+TEST(Hash, pair_folly_hash) {
+ typedef std::pair<int64_t, int32_t> pair2;
+ pair2 p(42, 1);
+
+ std::unordered_map<pair2, std::string, folly::Hash> m;
+ m[p] = "bar";
+ EXPECT_EQ("bar", m[p]);
+}
+
+TEST(Hash, tuple_folly_hash) {
+ typedef std::tuple<int64_t, int32_t, int32_t> tuple3;
+ tuple3 t(42, 1, 1);
+
+ std::unordered_map<tuple3, std::string, folly::Hash> m;
+ m[t] = "bar";
+ EXPECT_EQ("bar", m[t]);
+}
+
+namespace {
+template <class T>
+size_t hash_vector(const std::vector<T>& v) {
+ return hash_range(v.begin(), v.end());
+}
+}
+
+TEST(Hash, hash_range) {
+ EXPECT_EQ(hash_vector<int32_t>({1, 2}), hash_vector<int16_t>({1, 2}));
+ EXPECT_NE(hash_vector<int>({2, 1}), hash_vector<int>({1, 2}));
+ EXPECT_EQ(hash_vector<int>({}), hash_vector<float>({}));
+}
+
+TEST(Hash, std_tuple_different_hash) {
+ typedef std::tuple<int64_t, std::string, int32_t> tuple3;
+ tuple3 t1(42, "foo", 1);
+ tuple3 t2(9, "bar", 3);
+ tuple3 t3(42, "foo", 3);
+
+ EXPECT_NE(std::hash<tuple3>()(t1),
+ std::hash<tuple3>()(t2));
+ EXPECT_NE(std::hash<tuple3>()(t1),
+ std::hash<tuple3>()(t3));
+}
+
+TEST(Hash, Strings) {
+ using namespace folly;
+
+ StringPiece a1 = "10050517", b1 = "51107032",
+ a2 = "10050518", b2 = "51107033",
+ a3 = "10050519", b3 = "51107034",
+ a4 = "10050525", b4 = "51107040";
+ Range<const wchar_t*> w1 = range(L"10050517"), w2 = range(L"51107032"),
+ w3 = range(L"10050518"), w4 = range(L"51107033");
+ StringPieceHash h1;
+ Hash h2;
+ EXPECT_EQ(h1(a1), h1(b1));
+ EXPECT_EQ(h1(a2), h1(b2));
+ EXPECT_EQ(h1(a3), h1(b3));
+ EXPECT_EQ(h1(a4), h1(b4));
+ EXPECT_NE(h2(a1), h2(b1));
+ EXPECT_NE(h2(a1), h2(b1));
+ EXPECT_NE(h2(a2), h2(b2));
+ EXPECT_NE(h2(a3), h2(b3));
+ EXPECT_NE(h2(ByteRange(a1)), h2(ByteRange(b1)));
+ EXPECT_NE(h2(ByteRange(a2)), h2(ByteRange(b2)));
+ EXPECT_NE(h2(ByteRange(a3)), h2(ByteRange(b3)));
+ EXPECT_NE(h2(ByteRange(a4)), h2(ByteRange(b4)));
+ EXPECT_NE(h2(w1), h2(w2));
+ EXPECT_NE(h2(w1), h2(w3));
+ EXPECT_NE(h2(w2), h2(w4));
+
+ // Check compatibility with std::string.
+ EXPECT_EQ(h2(a1), h2(a1.str()));
+ EXPECT_EQ(h2(a2), h2(a2.str()));
+ EXPECT_EQ(h2(a3), h2(a3.str()));
+ EXPECT_EQ(h2(a4), h2(a4.str()));
+}