// Copyright 2014 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/hash/hash.h" #include #include #include #include #include "base/containers/span.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { TEST(HashTest, DeprecatedHashFromString) { std::string str; // Empty string (should hash to 0). str = ""; EXPECT_EQ(0u, Hash(str)); // Simple test. str = "hello world"; EXPECT_EQ(2794219650u, Hash(str)); // Change one bit. str = "helmo world"; EXPECT_EQ(1006697176u, Hash(str)); // Insert a null byte. str = "hello world"; str[5] = '\0'; EXPECT_EQ(2319902537u, Hash(str)); // Test that the bytes after the null contribute to the hash. str = "hello worle"; str[5] = '\0'; EXPECT_EQ(553904462u, Hash(str)); // Extremely long string. // Also tests strings with high bit set, and null byte. std::vector long_string_buffer; for (int i = 0; i < 4096; ++i) long_string_buffer.push_back((i % 256) - 128); str.assign(&long_string_buffer.front(), long_string_buffer.size()); EXPECT_EQ(2797962408u, Hash(str)); // All possible lengths (mod 4). Tests separate code paths. Also test with // final byte high bit set (regression test for http://crbug.com/90659). // Note that the 1 and 3 cases have a weird bug where the final byte is // treated as a signed char. It was decided on the above bug discussion to // enshrine that behaviour as "correct" to avoid invalidating existing hashes. // Length mod 4 == 0. str = "hello w\xab"; EXPECT_EQ(615571198u, Hash(str)); // Length mod 4 == 1. str = "hello wo\xab"; EXPECT_EQ(623474296u, Hash(str)); // Length mod 4 == 2. str = "hello wor\xab"; EXPECT_EQ(4278562408u, Hash(str)); // Length mod 4 == 3. str = "hello worl\xab"; EXPECT_EQ(3224633008u, Hash(str)); } TEST(HashTest, DeprecatedHashFromCString) { const char* str; // Empty string (should hash to 0). str = ""; EXPECT_EQ(0u, Hash(str)); // Simple test. str = "hello world"; EXPECT_EQ(2794219650u, Hash(str)); } TEST(HashTest, PersistentHashFromSpan) { // Empty span (should hash to 0). EXPECT_EQ(0u, PersistentHash(base::span())); // The hash loads four bytes at a time, and is sensitive to the high bit of // the last few bytes. Test hashes of various lengths, and with and without // the high bit set, to confirm the persistent hash remains persistent. const std::string_view str1 = "hello world"; const std::array kHashesByLength1 = { 0u, 1213478405u, 2371107848u, 2412215855u, 2296013106u, 2963130491u, 342812795u, 1345887711u, 2394271580u, 2806845956u, 2484860346u, 2794219650u}; for (size_t i = 0; i <= str1.size(); i++) { SCOPED_TRACE(i); EXPECT_EQ(kHashesByLength1[i], PersistentHash(as_byte_span(str1.substr(0, i)))); } const std::string_view str2 = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa"; const std::array kHashesByLength2 = { 0u, 2524495555u, 901867827u, 52332316u, 1053305007u, 4170027104u, 1891345481u, 2246421829u, 1241531838u, 4191939542u, 4100345281u, 896950651u}; for (size_t i = 0; i <= str2.size(); i++) { SCOPED_TRACE(i); EXPECT_EQ(kHashesByLength2[i], PersistentHash(as_byte_span(str2.substr(0, i)))); } } TEST(HashTest, FastHash) { std::string s; constexpr char kEmptyString[] = ""; EXPECT_EQ(FastHash(s), FastHash(kEmptyString)); } } // namespace base