910e62b5创建于 1月15日历史提交
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/disk_cache/sql/cache_entry_key.h"

#include <string>
#include <unordered_set>
#include <utility>

#include "testing/gtest/include/gtest/gtest.h"

namespace disk_cache {
namespace {

TEST(CacheEntryKeyTest, DefaultConstructor) {
  CacheEntryKey key;
  EXPECT_EQ(key.string(), "");
}

TEST(CacheEntryKeyTest, ValueConstructor) {
  const std::string kValue = "my_key";
  CacheEntryKey key(kValue);
  EXPECT_EQ(key.string(), kValue);
}

TEST(CacheEntryKeyTest, CopyConstructor) {
  const std::string kValue = "my_key";
  CacheEntryKey key1(kValue);
  CacheEntryKey key2(key1);

  EXPECT_EQ(key1.string(), kValue);
  EXPECT_EQ(key2.string(), kValue);
  // The copy should be equal, and this also tests the fast-path where the
  // underlying RefCountedString pointers are identical.
  EXPECT_EQ(key1, key2);
}

TEST(CacheEntryKeyTest, MoveConstructor) {
  const std::string kValue = "my_key";
  CacheEntryKey key1(kValue);
  CacheEntryKey key2(std::move(key1));

  // The moved-to key should have the original value.
  EXPECT_EQ(key2.string(), kValue);
}

TEST(CacheEntryKeyTest, CopyAssignment) {
  const std::string kValue1 = "key1";
  const std::string kValue2 = "key2";
  CacheEntryKey key1(kValue1);
  CacheEntryKey key2(kValue2);

  EXPECT_NE(key1, key2);

  key2 = key1;
  EXPECT_EQ(key1.string(), kValue1);
  EXPECT_EQ(key2.string(), kValue1);
  EXPECT_EQ(key1, key2);
}

TEST(CacheEntryKeyTest, MoveAssignment) {
  const std::string kValue1 = "key1";
  const std::string kValue2 = "key2";
  CacheEntryKey key1(kValue1);
  CacheEntryKey key2(kValue2);

  EXPECT_NE(key1, key2);

  key2 = std::move(key1);
  // The moved-to key should have the original value.
  EXPECT_EQ(key2.string(), kValue1);
}

TEST(CacheEntryKeyTest, ComparisonOperators) {
  CacheEntryKey key_a("a");
  CacheEntryKey key_a_copy("a");
  CacheEntryKey key_b("b");
  CacheEntryKey empty_key("");

  // Operator==
  EXPECT_EQ(key_a, key_a_copy);
  EXPECT_FALSE(key_a == key_b);
  EXPECT_FALSE(key_a == empty_key);
  EXPECT_EQ(CacheEntryKey(), empty_key);

  // Operator<
  EXPECT_LT(key_a, key_b);
  EXPECT_LT(empty_key, key_a);
  EXPECT_FALSE(key_b < key_a);
  EXPECT_FALSE(key_a < key_a);
  EXPECT_FALSE(key_a < key_a_copy);
}

TEST(CacheEntryKeyTest, LessThanOperatorFastPath) {
  // 1. Test with two keys sharing the exact same underlying data object.
  // The new `data_ != other.data_` check should short-circuit to false.
  const std::string kValue = "my_key";
  CacheEntryKey key1(kValue);
  CacheEntryKey key2(key1);

  ASSERT_EQ(key1, key2);
  // An object cannot be less than itself.
  EXPECT_FALSE(key1 < key2);
  EXPECT_FALSE(key2 < key1);

  // 2. Test with two keys having different data objects but the same string
  // value. The `data_ != other.data_` check passes, but the string
  // comparison 'kValue < kValue' is correctly false.
  CacheEntryKey key3(kValue);

  ASSERT_EQ(key1, key3);
  // The pointers are different, but the strings are equal.
  EXPECT_FALSE(key1 < key3);
  EXPECT_FALSE(key3 < key1);
}

TEST(CacheEntryKeyTest, StdHash) {
  std::unordered_set<CacheEntryKey> key_set;

  CacheEntryKey key1("key1");
  CacheEntryKey key2("key2");
  CacheEntryKey key1_copy("key1");

  // Insert keys.
  auto result1 = key_set.insert(key1);
  EXPECT_TRUE(result1.second);  // Insertion should succeed.
  EXPECT_EQ(key_set.size(), 1u);

  auto result2 = key_set.insert(key2);
  EXPECT_TRUE(result2.second);
  EXPECT_EQ(key_set.size(), 2u);

  // Try inserting a duplicate.
  auto result3 = key_set.insert(key1_copy);
  EXPECT_FALSE(result3.second);  // Insertion should fail.
  EXPECT_EQ(key_set.size(), 2u);

  // Find keys.
  EXPECT_EQ(key_set.count(key1), 1u);
  EXPECT_EQ(key_set.count(key2), 1u);
  EXPECT_EQ(key_set.count(key1_copy), 1u);
  EXPECT_EQ(key_set.count(CacheEntryKey("non_existent_key")), 0u);
}

}  // namespace
}  // namespace disk_cache