blob: e87ce34327059a73528c018a6d8a1561d23d7743 [file] [log] [blame]
// Copyright 2017 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/cronet/host_cache_persistence_manager.h"
#include "base/test/scoped_mock_time_message_loop_task_runner.h"
#include "base/test/scoped_task_environment.h"
#include "base/values.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "net/base/net_errors.h"
#include "net/dns/host_cache.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cronet {
class HostCachePersistenceManagerTest : public testing::Test {
protected:
void SetUp() override {
cache_ = net::HostCache::CreateDefaultCache();
pref_service_ = std::make_unique<TestingPrefServiceSimple>();
pref_service_->registry()->RegisterListPref(kPrefName);
}
void MakePersistenceManager(base::TimeDelta delay) {
persistence_manager_ = std::make_unique<HostCachePersistenceManager>(
cache_.get(), pref_service_.get(), kPrefName, delay, nullptr);
}
// Sets an entry in the HostCache in order to trigger a pref write. The
// caller is responsible for making sure this is a change that will trigger
// a write, and the HostCache's interaction with its PersistenceDelegate is
// assumed to work (it's tested in net/dns/host_cache_unittest.cc).
void WriteToCache(const std::string& host) {
net::HostCache::Key key(host, net::ADDRESS_FAMILY_UNSPECIFIED, 0);
net::HostCache::Entry entry(net::OK, net::AddressList(),
net::HostCache::Entry::SOURCE_UNKNOWN);
cache_->Set(key, entry, base::TimeTicks::Now(),
base::TimeDelta::FromSeconds(1));
}
// Reads the current value of the pref from the TestingPrefServiceSimple
// and deserializes it into a temporary new HostCache. Only checks the size,
// not the full contents, since the tests in this file are only intended
// to test that writes happen when they're supposed to, not serialization
// correctness.
void CheckPref(size_t size) {
const base::Value* value = pref_service_->GetUserPref(kPrefName);
base::ListValue list;
if (value)
list = base::ListValue(value->GetList());
net::HostCache temp_cache(10);
temp_cache.RestoreFromListValue(list);
ASSERT_EQ(size, temp_cache.size());
}
// Generates a temporary HostCache with a few entries and uses it to
// initialize the value in prefs.
void InitializePref() {
net::HostCache temp_cache(10);
net::HostCache::Key key1("1", net::ADDRESS_FAMILY_UNSPECIFIED, 0);
net::HostCache::Key key2("2", net::ADDRESS_FAMILY_UNSPECIFIED, 0);
net::HostCache::Key key3("3", net::ADDRESS_FAMILY_UNSPECIFIED, 0);
net::HostCache::Entry entry(net::OK, net::AddressList(),
net::HostCache::Entry::SOURCE_UNKNOWN);
temp_cache.Set(key1, entry, base::TimeTicks::Now(),
base::TimeDelta::FromSeconds(1));
temp_cache.Set(key2, entry, base::TimeTicks::Now(),
base::TimeDelta::FromSeconds(1));
temp_cache.Set(key3, entry, base::TimeTicks::Now(),
base::TimeDelta::FromSeconds(1));
base::ListValue value;
temp_cache.GetAsListValue(&value, false);
pref_service_->Set(kPrefName, value);
}
static const char kPrefName[];
base::test::ScopedTaskEnvironment scoped_task_environment_;
base::ScopedMockTimeMessageLoopTaskRunner task_runner_;
// The HostCache and PrefService have to outlive the
// HostCachePersistenceManager.
std::unique_ptr<net::HostCache> cache_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
std::unique_ptr<HostCachePersistenceManager> persistence_manager_;
};
const char HostCachePersistenceManagerTest::kPrefName[] = "net.test";
// Make a single change to the HostCache and make sure that it's written
// when the timer expires. Then repeat.
TEST_F(HostCachePersistenceManagerTest, SeparateWrites) {
MakePersistenceManager(base::TimeDelta::FromSeconds(60));
WriteToCache("1");
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(59));
CheckPref(0);
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
CheckPref(1);
WriteToCache("2");
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(59));
CheckPref(1);
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
CheckPref(2);
}
// Write to the HostCache multiple times and make sure that all changes
// are written to prefs at the appropriate times.
TEST_F(HostCachePersistenceManagerTest, MultipleWrites) {
MakePersistenceManager(base::TimeDelta::FromSeconds(300));
WriteToCache("1");
WriteToCache("2");
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(299));
CheckPref(0);
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
CheckPref(2);
WriteToCache("3");
WriteToCache("4");
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(299));
CheckPref(2);
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
CheckPref(4);
}
// Make changes to the HostCache at different times and ensure that the writes
// to prefs are batched as expected.
TEST_F(HostCachePersistenceManagerTest, BatchedWrites) {
MakePersistenceManager(base::TimeDelta::FromMilliseconds(100));
WriteToCache("1");
task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(30));
WriteToCache("2");
task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(30));
WriteToCache("3");
CheckPref(0);
task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(40));
CheckPref(3);
// Add a delay in between batches.
task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(50));
WriteToCache("4");
task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(30));
WriteToCache("5");
task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(30));
WriteToCache("6");
CheckPref(3);
task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(40));
CheckPref(6);
}
// Set the pref before the HostCachePersistenceManager is created, and make
// sure it gets picked up by the HostCache.
TEST_F(HostCachePersistenceManagerTest, InitAfterPrefs) {
CheckPref(0);
InitializePref();
CheckPref(3);
MakePersistenceManager(base::TimeDelta::FromSeconds(1));
task_runner_->RunUntilIdle();
ASSERT_EQ(3u, cache_->size());
}
// Set the pref after the HostCachePersistenceManager is created, and make
// sure it gets picked up by the HostCache.
TEST_F(HostCachePersistenceManagerTest, InitBeforePrefs) {
MakePersistenceManager(base::TimeDelta::FromSeconds(1));
ASSERT_EQ(0u, cache_->size());
CheckPref(0);
InitializePref();
CheckPref(3);
ASSERT_EQ(3u, cache_->size());
}
} // namespace cronet