#include "services/proxy_resolver/proxy_host_resolver_cache.h"
#include "base/test/task_environment.h"
#include "net/base/ip_address.h"
#include "net/base/network_anonymization_key.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace proxy_resolver {
namespace {
class ProxyHostResolverCacheTest : public testing::Test {
protected:
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
ProxyHostResolverCache cache_;
};
TEST_F(ProxyHostResolverCacheTest, SimpleNegativeLookup) {
ASSERT_EQ(cache_.GetSizeForTesting(), 0u);
EXPECT_FALSE(cache_.LookupEntry("host.test", net::NetworkAnonymizationKey(),
false));
}
TEST_F(ProxyHostResolverCacheTest, SimpleCachedLookup) {
const net::IPAddress kResult(1, 2, 3, 4);
cache_.StoreEntry("host.test", net::NetworkAnonymizationKey(),
false, {kResult});
EXPECT_EQ(cache_.GetSizeForTesting(), 1u);
EXPECT_THAT(cache_.LookupEntry("host.test", net::NetworkAnonymizationKey(),
false),
testing::Pointee(testing::ElementsAre(kResult)));
}
TEST_F(ProxyHostResolverCacheTest, NoResultWithNonMatchingKeyFields) {
cache_.StoreEntry("host.test", net::NetworkAnonymizationKey(),
false, {net::IPAddress(1, 2, 3, 5)});
ASSERT_EQ(cache_.GetSizeForTesting(), 1u);
EXPECT_FALSE(cache_.LookupEntry("host1.test", net::NetworkAnonymizationKey(),
false));
EXPECT_FALSE(cache_.LookupEntry(
"host.test", net::NetworkAnonymizationKey::CreateTransient(),
false));
EXPECT_FALSE(cache_.LookupEntry("host.test", net::NetworkAnonymizationKey(),
true));
}
TEST_F(ProxyHostResolverCacheTest, NoResultForExpiredLookup) {
const net::IPAddress kResult(1, 2, 3, 6);
cache_.StoreEntry("host.test", net::NetworkAnonymizationKey(),
false, {kResult});
task_environment_.FastForwardBy(ProxyHostResolverCache::kTtl -
base::Milliseconds(5));
EXPECT_EQ(cache_.GetSizeForTesting(), 1u);
ASSERT_THAT(cache_.LookupEntry("host.test", net::NetworkAnonymizationKey(),
false),
testing::Pointee(testing::ElementsAre(kResult)));
task_environment_.FastForwardBy(base::Milliseconds(10));
EXPECT_FALSE(cache_.LookupEntry("host.test", net::NetworkAnonymizationKey(),
false));
EXPECT_EQ(cache_.GetSizeForTesting(), 0u);
}
TEST_F(ProxyHostResolverCacheTest, EvictsOldestEntriesWhenFull) {
ProxyHostResolverCache cache(3u);
cache.StoreEntry("to-be-deleted.test", net::NetworkAnonymizationKey(),
false, {});
task_environment_.FastForwardBy(base::Milliseconds(5));
cache.StoreEntry("other1.test", net::NetworkAnonymizationKey(),
false, {});
cache.StoreEntry("other2.test", net::NetworkAnonymizationKey(),
false, {});
EXPECT_EQ(cache.GetSizeForTesting(), 3u);
EXPECT_TRUE(cache.LookupEntry("to-be-deleted.test",
net::NetworkAnonymizationKey(),
false));
EXPECT_TRUE(cache.LookupEntry("other1.test", net::NetworkAnonymizationKey(),
false));
EXPECT_TRUE(cache.LookupEntry("other2.test", net::NetworkAnonymizationKey(),
false));
cache.StoreEntry("evictor.test", net::NetworkAnonymizationKey(),
false, {});
EXPECT_EQ(cache.GetSizeForTesting(), 3u);
EXPECT_FALSE(cache.LookupEntry("to-be-deleted.test",
net::NetworkAnonymizationKey(),
false));
EXPECT_TRUE(cache.LookupEntry("other1.test", net::NetworkAnonymizationKey(),
false));
EXPECT_TRUE(cache.LookupEntry("other2.test", net::NetworkAnonymizationKey(),
false));
EXPECT_TRUE(cache.LookupEntry("evictor.test", net::NetworkAnonymizationKey(),
false));
}
TEST_F(ProxyHostResolverCacheTest, UpdatesAlreadyExistingEntryWithSameKey) {
cache_.StoreEntry("host.test", net::NetworkAnonymizationKey(),
false, {});
ASSERT_EQ(cache_.GetSizeForTesting(), 1u);
const net::IPAddress kResult(1, 2, 3, 7);
cache_.StoreEntry("host.test", net::NetworkAnonymizationKey(),
false, {kResult});
EXPECT_EQ(cache_.GetSizeForTesting(), 1u);
EXPECT_THAT(cache_.LookupEntry("host.test", net::NetworkAnonymizationKey(),
false),
testing::Pointee(testing::ElementsAre(kResult)));
}
TEST_F(ProxyHostResolverCacheTest, EntryUpdateRefreshesExpiration) {
ProxyHostResolverCache cache(2u);
cache.StoreEntry("to-be-refreshed.test", net::NetworkAnonymizationKey(),
false, {});
task_environment_.FastForwardBy(base::Milliseconds(5));
cache.StoreEntry("to-be-evicted.test", net::NetworkAnonymizationKey(),
false, {});
ASSERT_EQ(cache.GetSizeForTesting(), 2u);
task_environment_.FastForwardBy(base::Milliseconds(5));
cache.StoreEntry("to-be-refreshed.test", net::NetworkAnonymizationKey(),
false, {});
ASSERT_EQ(cache.GetSizeForTesting(), 2u);
cache.StoreEntry("evictor.test", net::NetworkAnonymizationKey(),
false, {});
EXPECT_EQ(cache.GetSizeForTesting(), 2u);
EXPECT_FALSE(cache.LookupEntry("to-be-evicted.test",
net::NetworkAnonymizationKey(),
false));
EXPECT_TRUE(cache.LookupEntry("to-be-refreshed.test",
net::NetworkAnonymizationKey(),
false));
EXPECT_TRUE(cache.LookupEntry("evictor.test", net::NetworkAnonymizationKey(),
false));
}
TEST_F(ProxyHostResolverCacheTest, EntryCanBeEvictedAfterUpdate) {
ProxyHostResolverCache cache(1u);
cache.StoreEntry("host.test", net::NetworkAnonymizationKey(),
false, {});
ASSERT_EQ(cache.GetSizeForTesting(), 1u);
task_environment_.FastForwardBy(base::Milliseconds(5));
cache.StoreEntry("host.test", net::NetworkAnonymizationKey(),
false, {});
ASSERT_EQ(cache.GetSizeForTesting(), 1u);
task_environment_.FastForwardBy(base::Milliseconds(5));
cache.StoreEntry("evictor.test", net::NetworkAnonymizationKey(),
false, {});
EXPECT_EQ(cache.GetSizeForTesting(), 1u);
EXPECT_FALSE(cache.LookupEntry("host.test", net::NetworkAnonymizationKey(),
false));
EXPECT_TRUE(cache.LookupEntry("evictor.test", net::NetworkAnonymizationKey(),
false));
}
}
}