Implement NormalizedMurmurHashEntropyProvider

Design document:
https://docs.google.com/document/d/1cPF5PruriWNP2Z5gSkq4MBTm0wSZqLyIJkUO9ekibeo

BUG=890413

Change-Id: Ib372a573b1a0f68467f785ce74ef7821c9d48614
Reviewed-on: https://chromium-review.googlesource.com/c/1322350
Reviewed-by: Grace Kloba <[email protected]>
Reviewed-by: Alexei Svitkine <[email protected]>
Commit-Queue: Paul Miller <[email protected]>
Cr-Commit-Position: refs/heads/master@{#607816}
diff --git a/components/variations/variations_murmur_hash_unittest.cc b/components/variations/variations_murmur_hash_unittest.cc
new file mode 100644
index 0000000..3059cd3
--- /dev/null
+++ b/components/variations/variations_murmur_hash_unittest.cc
@@ -0,0 +1,82 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/variations/variations_murmur_hash.h"
+
+#include <limits>
+#include <vector>
+
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/smhasher/src/MurmurHash3.h"
+
+namespace variations {
+namespace internal {
+
+TEST(VariationsMurmurHashTest, StringToLE32) {
+  EXPECT_EQ(std::vector<uint32_t>(),
+            VariationsMurmurHash::StringToLE32(""));
+  EXPECT_EQ(std::vector<uint32_t>({0x00000061}),
+            VariationsMurmurHash::StringToLE32("a"));
+  EXPECT_EQ(std::vector<uint32_t>({0x00006261}),
+            VariationsMurmurHash::StringToLE32("ab"));
+  EXPECT_EQ(std::vector<uint32_t>({0x00636261}),
+            VariationsMurmurHash::StringToLE32("abc"));
+  EXPECT_EQ(std::vector<uint32_t>({0x64636261}),
+            VariationsMurmurHash::StringToLE32("abcd"));
+  EXPECT_EQ(std::vector<uint32_t>({0x64636261, 0x00000065}),
+            VariationsMurmurHash::StringToLE32("abcde"));
+  EXPECT_EQ(std::vector<uint32_t>({0x64636261, 0x00006665}),
+            VariationsMurmurHash::StringToLE32("abcdef"));
+}
+
+// The tests inside this #if compare VariationsMurmurHash to the reference
+// implementation, MurmurHash3_x86_32, which only works on little-endian.
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+
+// Compare VariationsMurmurHash::Hash to MurmurHash3_x86_32 for every prefix of
+// |data|, from the empty string to all of |data|.
+TEST(VariationsMurmurHashTest, Hash) {
+  // Random bytes generated manually and hard-coded for reproducability
+  const std::vector<uint32_t> data({
+      2704264845, 2929902289, 1679431515, 1427187834, 1300338468,
+       576307953, 1209988079, 1918627109, 3926412991,   74087765});
+
+  size_t max_size = data.size() * sizeof(uint32_t);
+  for (size_t size = 0; size <= max_size; size++) {
+    uint32_t expected;
+    MurmurHash3_x86_32(data.data(), size, /*seed=*/0, &expected);
+    EXPECT_EQ(expected, VariationsMurmurHash::Hash(data, size))
+        << "size=" << size;
+  }
+}
+
+TEST(VariationsMurmurHashTest, Hash16) {
+  // Pick some likely edge case values.
+  constexpr uint32_t max32 = std::numeric_limits<uint32_t>::max();
+  uint32_t seeds[] = {
+    0, max32 / 2 - 1, max32 - 2,
+    1, max32 / 2,     max32 - 1,
+    2, max32 / 2 + 1, max32};
+
+  constexpr uint16_t max16 = std::numeric_limits<uint16_t>::max();
+  uint16_t data[] = {
+    0, max16 / 2 - 1, max16 - 2,
+    1, max16 / 2,     max16 - 1,
+    2, max16 / 2 + 1, max16};
+
+  for (uint32_t seed : seeds) {
+    for (uint16_t datum : data) {
+      uint32_t expected;
+      MurmurHash3_x86_32(&datum, sizeof(datum), seed, &expected);
+      EXPECT_EQ(expected, VariationsMurmurHash::Hash16(seed, datum))
+          << "seed=" << seed << ", datum=" << datum;
+    }
+  }
+}
+
+#endif  // defined(ARCH_CPU_LITTLE_ENDIAN)
+
+}  // namespace internal
+}  // namespace variations