Chromium Code Reviews| Index: components/precache/core/precache_database_unittest.cc |
| diff --git a/components/precache/core/precache_database_unittest.cc b/components/precache/core/precache_database_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..1e57e231192a347c9f7d6362004bfd74e2f84b49 |
| --- /dev/null |
| +++ b/components/precache/core/precache_database_unittest.cc |
| @@ -0,0 +1,452 @@ |
| +// Copyright 2013 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/precache/core/precache_database.h" |
| + |
| +#include <map> |
| + |
| +#include "base/basictypes.h" |
| +#include "base/metrics/histogram.h" |
| +#include "base/metrics/histogram_samples.h" |
| +#include "base/metrics/statistics_recorder.h" |
| +#include "base/time/time.h" |
| +#include "components/precache/core/precache_statistics_table.h" |
| +#include "components/precache/core/precache_url_table.h" |
| +#include "sql/connection.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "url/gurl.h" |
| + |
| +namespace { |
| + |
| +typedef precache::PrecacheStatisticsTable::PrecacheStatistics |
| + PrecacheStatistics; |
| +typedef precache::PrecacheStatisticsTable::PrecacheStatisticsMap |
| + PrecacheStatisticsMap; |
| + |
| +base::Time GetTimeFromString(const char* time_string) { |
| + base::Time time; |
| + EXPECT_TRUE(base::Time::FromString(time_string, &time)); |
| + return time; |
| +} |
| + |
| +std::map<GURL, base::Time> BuildURLTableMap(const GURL& url, |
| + const base::Time& precache_time) { |
| + std::map<GURL, base::Time> url_table_map; |
| + url_table_map[url] = precache_time; |
| + return url_table_map; |
| +} |
| + |
| +PrecacheStatisticsMap BuildStatsMap(const base::Time& day, |
| + const PrecacheStatistics& stats) { |
| + PrecacheStatisticsMap stats_map; |
| + stats_map[day] = stats; |
| + return stats_map; |
| +} |
| + |
| +scoped_ptr<base::HistogramSamples> GetHistogramSamples( |
| + const char* histogram_name) { |
| + base::HistogramBase* histogram = |
| + base::StatisticsRecorder::FindHistogram(histogram_name); |
| + |
| + EXPECT_NE(static_cast<base::HistogramBase*>(NULL), histogram); |
| + |
| + return histogram->SnapshotSamples().Pass(); |
| +} |
| + |
| +void ExpectHistogramSamples(const char* histogram_name, int64 sample1, |
| + int64 sample2) { |
| + scoped_ptr<base::HistogramSamples> samples( |
| + GetHistogramSamples(histogram_name)); |
| + |
| + EXPECT_EQ(2, samples->TotalCount()); |
| + |
| + if (sample1 == sample2) { |
| + EXPECT_EQ(2, samples->GetCount(sample1)); |
| + return; |
| + } |
| + |
| + EXPECT_EQ(1, samples->GetCount(sample1)); |
| + EXPECT_EQ(1, samples->GetCount(sample2)); |
| +} |
| + |
| +const GURL kURL("http://url.com"); |
| +const base::Time kFetchTime = GetTimeFromString("11 Oct 2013, 12:34:56"); |
| +const base::Time kFetchDay = kFetchTime.LocalMidnight(); |
| +const base::Time kOldFetchTime = GetTimeFromString("10 Oct 2013, 12:34:56"); |
| +const int64 kSize = 5000; |
| + |
| +} // namespace |
| + |
| +namespace precache { |
| + |
| +class PrecacheDatabaseTest : public testing::Test { |
| + public: |
| + PrecacheDatabaseTest() {} |
| + virtual ~PrecacheDatabaseTest() {} |
| + |
| + protected: |
| + virtual void SetUp() OVERRIDE { |
| + precache_database_ = new PrecacheDatabase(); |
| + scoped_ptr<sql::Connection> db(new sql::Connection()); |
| + ASSERT_TRUE(db->OpenInMemory()); |
| + precache_database_->Init(db.Pass()); |
| + } |
| + |
| + std::map<GURL, base::Time> GetActualURLTableMap() { |
| + std::map<GURL, base::Time> url_table_map; |
| + precache_database_->precache_url_table_->GetAllDataForTesting( |
| + &url_table_map); |
| + return url_table_map; |
| + } |
| + |
| + PrecacheStatisticsMap GetActualStatsMap() { |
| + PrecacheStatisticsMap stats_map; |
| + precache_database_->precache_statistics_table_->GetAllStatsUntil( |
| + base::Time::Max(), &stats_map); |
| + return stats_map; |
| + } |
| + |
| + PrecacheURLTable* precache_url_table() { |
| + return precache_database_->precache_url_table_.get(); |
| + } |
| + |
| + PrecacheStatisticsTable* precache_statistics_table() { |
| + return precache_database_->precache_statistics_table_.get(); |
| + } |
| + |
| + // Convenience methods for recording different types of URL fetches. These |
| + // exist to improve the readability of the sample interaction test. |
| + void RecordPrecacheFromNetwork(const GURL& url, const base::Time& fetch_time, |
| + int64 size); |
| + void RecordPrecacheFromCache(const GURL& url, const base::Time& fetch_time, |
| + int64 size); |
| + void RecordFetchFromNetwork(const GURL& url, const base::Time& fetch_time, |
| + int64 size); |
| + void RecordFetchFromNetworkCellular(const GURL& url, |
| + const base::Time& fetch_time, int64 size); |
| + void RecordFetchFromCache(const GURL& url, const base::Time& fetch_time, |
| + int64 size); |
| + void RecordFetchFromCacheCellular(const GURL& url, |
| + const base::Time& fetch_time, int64 size); |
| + |
| + scoped_refptr<PrecacheDatabase> precache_database_; |
| +}; |
| + |
| +void PrecacheDatabaseTest::RecordPrecacheFromNetwork( |
| + const GURL& url, const base::Time& fetch_time, int64 size) { |
| + precache_database_->RecordURLFetched( |
| + url, fetch_time, size, false /* was_cached */, true /* is_precache */, |
| + false /* is_connection_cellular */); |
| +} |
| + |
| +void PrecacheDatabaseTest::RecordPrecacheFromCache(const GURL& url, |
| + const base::Time& fetch_time, |
| + int64 size) { |
| + precache_database_->RecordURLFetched( |
| + url, fetch_time, size, true /* was_cached */, true /* is_precache */, |
| + false /* is_connection_cellular */); |
| +} |
| + |
| +void PrecacheDatabaseTest::RecordFetchFromNetwork(const GURL& url, |
| + const base::Time& fetch_time, |
| + int64 size) { |
| + precache_database_->RecordURLFetched( |
| + url, fetch_time, size, false /* was_cached */, false /* is_precache */, |
| + false /* is_connection_cellular */); |
| +} |
| + |
| +void PrecacheDatabaseTest::RecordFetchFromNetworkCellular( |
| + const GURL& url, const base::Time& fetch_time, int64 size) { |
| + precache_database_->RecordURLFetched( |
| + url, fetch_time, size, false /* was_cached */, false /* is_precache */, |
| + true /* is_connection_cellular */); |
| +} |
| + |
| +void PrecacheDatabaseTest::RecordFetchFromCache(const GURL& url, |
| + const base::Time& fetch_time, |
| + int64 size) { |
| + precache_database_->RecordURLFetched( |
| + url, fetch_time, size, true /* was_cached */, false /* is_precache */, |
| + false /* is_connection_cellular */); |
| +} |
| + |
| +void PrecacheDatabaseTest::RecordFetchFromCacheCellular( |
| + const GURL& url, const base::Time& fetch_time, int64 size) { |
| + precache_database_->RecordURLFetched( |
| + url, fetch_time, size, true /* was_cached */, false /* is_precache */, |
| + true /* is_connection_cellular */); |
| +} |
| + |
| +namespace { |
| + |
| +TEST_F(PrecacheDatabaseTest, PrecacheOverNetwork) { |
| + precache_database_->RecordURLFetched( |
| + kURL, kFetchTime, kSize, false /* was_cached */, true /* is_precache */, |
| + false /* is_connection_cellular */); |
|
davidben
2013/11/06 23:50:53
Any reason not to use your various helper function
sclittle
2013/11/09 01:07:58
Changed to use helper functions.
|
| + |
| + EXPECT_EQ(BuildURLTableMap(kURL, kFetchTime), GetActualURLTableMap()); |
| + |
| + PrecacheStatisticsMap expected_stats_map; |
| + expected_stats_map[kFetchDay].downloaded_precache_motivated_bytes = kSize; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| +} |
| + |
| +TEST_F(PrecacheDatabaseTest, PrecacheFromCacheWithURLTableEntry) { |
| + precache_url_table()->AddURL(kURL, kOldFetchTime); |
| + |
| + precache_database_->RecordURLFetched( |
| + kURL, kFetchTime, kSize, true /* was_cached */, true /* is_precache */, |
| + false /* is_connection_cellular */); |
| + |
| + // The URL table entry should have been updated to have |kFetchTime| as the |
| + // timestamp. |
| + EXPECT_EQ(BuildURLTableMap(kURL, kFetchTime), GetActualURLTableMap()); |
| + EXPECT_TRUE(GetActualStatsMap().empty()); |
| +} |
| + |
| +TEST_F(PrecacheDatabaseTest, PrecacheFromCacheWithoutURLTableEntry) { |
| + precache_database_->RecordURLFetched( |
| + kURL, kFetchTime, kSize, true /* was_cached */, true /* is_precache */, |
| + false /* is_connection_cellular */); |
| + |
| + EXPECT_TRUE(GetActualURLTableMap().empty()); |
| + EXPECT_TRUE(GetActualStatsMap().empty()); |
| +} |
| + |
| +TEST_F(PrecacheDatabaseTest, FetchOverNetwork_NonCellular) { |
| + precache_database_->RecordURLFetched( |
| + kURL, kFetchTime, kSize, false /* was_cached */, false /* is_precache */, |
| + false /* is_connection_cellular */); |
| + |
| + EXPECT_TRUE(GetActualURLTableMap().empty()); |
| + |
| + PrecacheStatisticsMap expected_stats_map; |
| + expected_stats_map[kFetchDay].downloaded_non_precache_bytes = kSize; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| +} |
| + |
| +TEST_F(PrecacheDatabaseTest, FetchOverNetwork_Cellular) { |
| + precache_database_->RecordURLFetched( |
| + kURL, kFetchTime, kSize, false /* was_cached */, false /* is_precache */, |
| + true /* is_connection_cellular */); |
| + |
| + EXPECT_TRUE(GetActualURLTableMap().empty()); |
| + |
| + PrecacheStatisticsMap expected_stats_map; |
| + expected_stats_map[kFetchDay].downloaded_non_precache_bytes = kSize; |
| + expected_stats_map[kFetchDay].downloaded_non_precache_bytes_cellular = kSize; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| +} |
| + |
| +TEST_F(PrecacheDatabaseTest, FetchOverNetworkWithURLTableEntry) { |
| + precache_url_table()->AddURL(kURL, kOldFetchTime); |
| + |
| + precache_database_->RecordURLFetched( |
| + kURL, kFetchTime, kSize, false /* was_cached */, false /* is_precache */, |
| + false /* is_connection_cellular */); |
| + |
| + // The URL table entry should have been deleted. |
| + EXPECT_TRUE(GetActualURLTableMap().empty()); |
| + |
| + PrecacheStatisticsMap expected_stats_map; |
| + expected_stats_map[kFetchDay].downloaded_non_precache_bytes = kSize; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| +} |
| + |
| +TEST_F(PrecacheDatabaseTest, FetchFromCacheWithURLTableEntry_NonCellular) { |
| + precache_url_table()->AddURL(kURL, kOldFetchTime); |
| + |
| + precache_database_->RecordURLFetched( |
| + kURL, kFetchTime, kSize, true /* was_cached */, false /* is_precache */, |
| + false /* is_connection_cellular */); |
| + |
| + // The URL table entry should have been deleted. |
| + EXPECT_TRUE(GetActualURLTableMap().empty()); |
| + |
| + PrecacheStatisticsMap expected_stats_map; |
| + expected_stats_map[kFetchDay].saved_bytes = kSize; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| +} |
| + |
| +TEST_F(PrecacheDatabaseTest, FetchFromCacheWithURLTableEntry_Cellular) { |
| + precache_url_table()->AddURL(kURL, kOldFetchTime); |
| + |
| + precache_database_->RecordURLFetched( |
| + kURL, kFetchTime, kSize, true /* was_cached */, false /* is_precache */, |
| + true /* is_connection_cellular */); |
| + |
| + // The URL table entry should have been deleted. |
| + EXPECT_TRUE(GetActualURLTableMap().empty()); |
| + |
| + PrecacheStatisticsMap expected_stats_map; |
| + expected_stats_map[kFetchDay].saved_bytes = kSize; |
| + expected_stats_map[kFetchDay].saved_bytes_cellular = kSize; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| +} |
| + |
| +TEST_F(PrecacheDatabaseTest, FetchFromCacheWithoutURLTableEntry) { |
| + precache_database_->RecordURLFetched( |
| + kURL, kFetchTime, kSize, true /* was_cached */, false /* is_precache */, |
| + false /* is_connection_cellular */); |
| + |
| + EXPECT_TRUE(GetActualURLTableMap().empty()); |
| + EXPECT_TRUE(GetActualStatsMap().empty()); |
| +} |
| + |
| +TEST_F(PrecacheDatabaseTest, ReportAndDeleteOldStats) { |
| + base::StatisticsRecorder::Initialize(); |
| + |
| + const base::Time kToday = GetTimeFromString("12 Oct 2013, 00:00:00"); |
| + const base::Time kYesterday = GetTimeFromString("11 Oct 2013, 00:00:00"); |
| + const base::Time kLastWeek = GetTimeFromString("04 Oct 2013, 00:00:00"); |
| + const base::Time k59DaysAgo = GetTimeFromString("13 Aug 2013, 00:00:00"); |
| + const base::Time k61DaysAgo = GetTimeFromString("11 Aug 2013, 00:00:00"); |
| + |
| + precache_url_table()->AddURL(GURL("http://expired-precache.com"), k61DaysAgo); |
| + precache_url_table()->AddURL(GURL("http://old-precache.com"), k59DaysAgo); |
| + |
| + const PrecacheStatistics kWeekOldStats(5000, 4000, 3000, 2000, 1000); |
| + const PrecacheStatistics kDayOldStats(10000, 8000, 6000, 4000, 2000); |
| + const PrecacheStatistics kCurrentStats(50000, 40000, 30000, 20000, 10000); |
| + |
| + precache_statistics_table()->IncreaseDailyStats(kLastWeek, kWeekOldStats); |
| + precache_statistics_table()->IncreaseDailyStats(kYesterday, kDayOldStats); |
| + precache_statistics_table()->IncreaseDailyStats(kToday, kCurrentStats); |
| + |
| + precache_database_->ReportAndDeleteOldStats(kYesterday); |
| + |
| + EXPECT_EQ(BuildURLTableMap(GURL("http://old-precache.com"), k59DaysAgo), |
| + GetActualURLTableMap()); |
| + EXPECT_EQ(BuildStatsMap(kToday, kCurrentStats), GetActualStatsMap()); |
| + |
| + ExpectHistogramSamples( |
| + "Precache.DailyDownloadedPrecacheMotivatedKB", |
| + kWeekOldStats.downloaded_precache_motivated_bytes / 1024, |
| + kDayOldStats.downloaded_precache_motivated_bytes / 1024); |
| + ExpectHistogramSamples("Precache.DailyDownloadedNonPrecacheKB", |
| + kWeekOldStats.downloaded_non_precache_bytes / 1024, |
| + kDayOldStats.downloaded_non_precache_bytes / 1024); |
| + ExpectHistogramSamples( |
| + "Precache.DailyDownloadedNonPrecacheKB.Cellular", |
| + kWeekOldStats.downloaded_non_precache_bytes_cellular / 1024, |
| + kDayOldStats.downloaded_non_precache_bytes_cellular / 1024); |
| + ExpectHistogramSamples("Precache.DailySavedKB", |
| + kWeekOldStats.saved_bytes / 1024, |
| + kDayOldStats.saved_bytes / 1024); |
| + ExpectHistogramSamples("Precache.DailySavedKB.Cellular", |
| + kWeekOldStats.saved_bytes_cellular / 1024, |
| + kDayOldStats.saved_bytes_cellular / 1024); |
| + ExpectHistogramSamples("Precache.DailySavingsPercentage", 33, 33); |
| + ExpectHistogramSamples("Precache.DailySavingsPercentage.Cellular", 25, 25); |
| +} |
| + |
| +TEST_F(PrecacheDatabaseTest, SampleInteraction) { |
| + const GURL kURL1("http://url1.com"); |
| + const int64 kSize1 = 1000; |
| + const GURL kURL2("http://url2.com"); |
| + const int64 kSize2 = 2000; |
| + const GURL kURL3("http://url3.com"); |
| + const int64 kSize3 = 3000; |
| + const GURL kURL4("http://url4.com"); |
| + const int64 kSize4 = 4000; |
| + const GURL kURL5("http://url5.com"); |
| + const int64 kSize5 = 5000; |
| + |
| + const base::Time kDay1 = GetTimeFromString("11 Oct 2013, 00:00:00"); |
| + const base::Time kDay2 = GetTimeFromString("12 Oct 2013, 00:00:00"); |
| + const base::TimeDelta kFetchPeriod = base::TimeDelta::FromMilliseconds(100); |
| + |
| + PrecacheStatisticsMap expected_stats_map; |
| + |
| + // Start of day 1. |
| + base::Time fetch_time = kDay1; |
| + |
| + // Precache URL 1 from network. |
| + RecordPrecacheFromNetwork(kURL1, fetch_time += kFetchPeriod, kSize1); |
|
davidben
2013/11/06 23:50:53
Nit: I don't think we tend put += in the middle of
sclittle
2013/11/09 01:07:58
Done.
|
| + expected_stats_map[kDay1].downloaded_precache_motivated_bytes += kSize1; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Precache URL 2 from network. |
| + RecordPrecacheFromNetwork(kURL2, fetch_time += kFetchPeriod, kSize2); |
| + expected_stats_map[kDay1].downloaded_precache_motivated_bytes += kSize2; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Precache URL 3 from network. |
| + RecordPrecacheFromNetwork(kURL3, fetch_time += kFetchPeriod, kSize3); |
| + expected_stats_map[kDay1].downloaded_precache_motivated_bytes += kSize3; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Precache URL 4 from network. |
| + RecordPrecacheFromNetwork(kURL4, fetch_time += kFetchPeriod, kSize4); |
| + expected_stats_map[kDay1].downloaded_precache_motivated_bytes += kSize4; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Fetch URL 1 from cache when on a cellular network. |
| + RecordFetchFromCacheCellular(kURL1, fetch_time += kFetchPeriod, kSize1); |
| + expected_stats_map[kDay1].saved_bytes += kSize1; |
| + expected_stats_map[kDay1].saved_bytes_cellular += kSize1; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Fetch URL 1 from cache when on a cellular network. |
| + RecordFetchFromCacheCellular(kURL1, fetch_time += kFetchPeriod, kSize1); |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Fetch URL 2 from network when on a cellular network. |
| + RecordFetchFromNetworkCellular(kURL2, fetch_time += kFetchPeriod, kSize2); |
| + expected_stats_map[kDay1].downloaded_non_precache_bytes += kSize2; |
| + expected_stats_map[kDay1].downloaded_non_precache_bytes_cellular += kSize2; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Fetch URL 5 from network when on a cellular network. |
| + RecordFetchFromNetworkCellular(kURL5, fetch_time += kFetchPeriod, kSize5); |
| + expected_stats_map[kDay1].downloaded_non_precache_bytes += kSize5; |
| + expected_stats_map[kDay1].downloaded_non_precache_bytes_cellular += kSize5; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Fetch URL 5 from cache when on a cellular network. |
| + RecordFetchFromCacheCellular(kURL5, fetch_time += kFetchPeriod, kSize5); |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Day 1 ends, day 2 begins. |
| + fetch_time = kDay2; |
| + |
| + // Precache URL 1 from cache. |
| + RecordPrecacheFromCache(kURL1, fetch_time += kFetchPeriod, kSize1); |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Precache URL 2 from network. |
| + RecordPrecacheFromNetwork(kURL2, fetch_time += kFetchPeriod, kSize2); |
| + expected_stats_map[kDay2].downloaded_precache_motivated_bytes += kSize2; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Precache URL 3 from cache. |
| + RecordPrecacheFromCache(kURL3, fetch_time += kFetchPeriod, kSize3); |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Precache URL 4 from cache. |
| + RecordPrecacheFromCache(kURL4, fetch_time += kFetchPeriod, kSize4); |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Fetch URL 1 from cache. |
| + RecordFetchFromCache(kURL1, fetch_time += kFetchPeriod, kSize1); |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Fetch URL 2 from network. |
| + RecordFetchFromNetwork(kURL2, fetch_time += kFetchPeriod, kSize2); |
| + expected_stats_map[kDay2].downloaded_non_precache_bytes += kSize2; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Fetch URL 3 from cache. |
| + RecordFetchFromCache(kURL3, fetch_time += kFetchPeriod, kSize3); |
| + expected_stats_map[kDay2].saved_bytes += kSize3; |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| + |
| + // Fetch URL 5 from cache. |
| + RecordFetchFromCache(kURL5, fetch_time += kFetchPeriod, kSize5); |
| + EXPECT_EQ(expected_stats_map, GetActualStatsMap()); |
| +} |
| + |
| +} // namespace |
| + |
| +} // namespace precache |