Add abhijeet.k@samsung.com to AUTHORS list.
[chromium-blink-merge.git] / components / precache / content / precache_manager_unittest.cc
blob949ef43c36090073220dd3f557abd90399c4ee86
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/precache/content/precache_manager.h"
7 #include <list>
8 #include <map>
9 #include <set>
10 #include <string>
12 #include "base/basictypes.h"
13 #include "base/bind.h"
14 #include "base/callback.h"
15 #include "base/command_line.h"
16 #include "base/compiler_specific.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/metrics/histogram.h"
19 #include "base/metrics/histogram_samples.h"
20 #include "base/metrics/statistics_recorder.h"
21 #include "components/precache/core/precache_switches.h"
22 #include "components/precache/core/url_list_provider.h"
23 #include "content/public/test/test_browser_context.h"
24 #include "content/public/test/test_browser_thread_bundle.h"
25 #include "net/http/http_status_code.h"
26 #include "net/url_request/test_url_fetcher_factory.h"
27 #include "net/url_request/url_request_status.h"
28 #include "net/url_request/url_request_test_util.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "url/gurl.h"
32 namespace precache {
34 namespace {
36 // A map of histogram names to the total sample counts.
37 typedef std::map<std::string, base::HistogramBase::Count> HistogramCountMap;
39 const char kConfigURL[] = "http://config-url.com";
40 const char kManifestURLPrefix[] = "http://manifest-url-prefix.com/";
42 base::HistogramBase::Count GetHistogramTotalCount(const char* histogram_name) {
43 base::HistogramBase* histogram =
44 base::StatisticsRecorder::FindHistogram(histogram_name);
45 return histogram ? histogram->SnapshotSamples()->TotalCount() : 0;
48 HistogramCountMap GetHistogramCountMap() {
49 // Note that the PrecacheManager tests don't care about the ".Cellular"
50 // histograms.
51 const char* kHistogramNames[] = {"Precache.DownloadedPrecacheMotivated",
52 "Precache.DownloadedNonPrecache",
53 "Precache.Saved"};
55 HistogramCountMap histogram_count_map;
56 for (size_t i = 0; i < arraysize(kHistogramNames); ++i) {
57 histogram_count_map[kHistogramNames[i]] =
58 GetHistogramTotalCount(kHistogramNames[i]);
60 return histogram_count_map;
63 class TestURLFetcherCallback {
64 public:
65 scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
66 const GURL& url, net::URLFetcherDelegate* delegate,
67 const std::string& response_data, net::HttpStatusCode response_code,
68 net::URLRequestStatus::Status status) {
69 scoped_ptr<net::FakeURLFetcher> fetcher(new net::FakeURLFetcher(
70 url, delegate, response_data, response_code, status));
72 requested_urls_.insert(url);
73 return fetcher.Pass();
76 const std::multiset<GURL>& requested_urls() const {
77 return requested_urls_;
80 private:
81 // Multiset with one entry for each URL requested.
82 std::multiset<GURL> requested_urls_;
85 class FakeURLListProvider : public URLListProvider {
86 public:
87 FakeURLListProvider(const std::list<GURL>& urls, bool run_immediately)
88 : urls_(urls),
89 run_immediately_(run_immediately),
90 was_get_urls_called_(false) {}
92 void GetURLs(const GetURLsCallback& callback) override {
93 was_get_urls_called_ = true;
95 if (run_immediately_) {
96 callback.Run(urls_);
97 } else {
98 // Post the callback to be run later in the message loop.
99 base::MessageLoop::current()->PostTask(FROM_HERE,
100 base::Bind(callback, urls_));
104 bool was_get_urls_called() const {
105 return was_get_urls_called_;
108 private:
109 const std::list<GURL> urls_;
110 const bool run_immediately_;
111 bool was_get_urls_called_;
114 class TestPrecacheCompletionCallback {
115 public:
116 TestPrecacheCompletionCallback() : was_on_done_called_(false) {}
118 void OnDone() {
119 was_on_done_called_ = true;
122 PrecacheManager::PrecacheCompletionCallback GetCallback() {
123 return base::Bind(&TestPrecacheCompletionCallback::OnDone,
124 base::Unretained(this));
127 bool was_on_done_called() const {
128 return was_on_done_called_;
131 private:
132 bool was_on_done_called_;
135 class PrecacheManagerTest : public testing::Test {
136 public:
137 PrecacheManagerTest()
138 : precache_manager_(&browser_context_),
139 factory_(NULL, base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
140 base::Unretained(&url_callback_))) {}
142 protected:
143 void SetUp() override {
144 base::StatisticsRecorder::Initialize();
146 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
147 switches::kPrecacheConfigSettingsURL, kConfigURL);
148 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
149 switches::kPrecacheManifestURLPrefix, kManifestURLPrefix);
151 // Make the fetch of the precache configuration settings fail. Precaching
152 // should still complete normally in this case.
153 factory_.SetFakeResponse(GURL(kConfigURL), "",
154 net::HTTP_INTERNAL_SERVER_ERROR,
155 net::URLRequestStatus::FAILED);
158 content::TestBrowserThreadBundle test_browser_thread_bundle_;
159 content::TestBrowserContext browser_context_;
160 PrecacheManager precache_manager_;
161 TestURLFetcherCallback url_callback_;
162 net::FakeURLFetcherFactory factory_;
163 TestPrecacheCompletionCallback precache_callback_;
166 TEST_F(PrecacheManagerTest, StartAndFinishPrecaching) {
167 EXPECT_FALSE(precache_manager_.IsPrecaching());
169 FakeURLListProvider url_list_provider(
170 std::list<GURL>(1, GURL("http://starting-url.com")), false);
171 precache_manager_.StartPrecaching(precache_callback_.GetCallback(),
172 &url_list_provider);
174 EXPECT_TRUE(precache_manager_.IsPrecaching());
176 base::MessageLoop::current()->RunUntilIdle();
177 EXPECT_FALSE(precache_manager_.IsPrecaching());
178 EXPECT_TRUE(url_list_provider.was_get_urls_called());
179 EXPECT_TRUE(precache_callback_.was_on_done_called());
181 std::multiset<GURL> expected_requested_urls;
182 expected_requested_urls.insert(GURL(kConfigURL));
183 EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
186 TEST_F(PrecacheManagerTest, StartAndCancelPrecachingBeforeURLsReceived) {
187 EXPECT_FALSE(precache_manager_.IsPrecaching());
189 FakeURLListProvider url_list_provider(
190 std::list<GURL>(1, GURL("http://starting-url.com")), false);
192 precache_manager_.StartPrecaching(precache_callback_.GetCallback(),
193 &url_list_provider);
194 EXPECT_TRUE(precache_manager_.IsPrecaching());
196 precache_manager_.CancelPrecaching();
197 EXPECT_FALSE(precache_manager_.IsPrecaching());
199 base::MessageLoop::current()->RunUntilIdle();
200 EXPECT_FALSE(precache_manager_.IsPrecaching());
201 EXPECT_TRUE(url_list_provider.was_get_urls_called());
202 EXPECT_FALSE(precache_callback_.was_on_done_called());
203 EXPECT_TRUE(url_callback_.requested_urls().empty());
206 TEST_F(PrecacheManagerTest, StartAndCancelPrecachingAfterURLsReceived) {
207 EXPECT_FALSE(precache_manager_.IsPrecaching());
209 FakeURLListProvider url_list_provider(
210 std::list<GURL>(1, GURL("http://starting-url.com")), true);
212 precache_manager_.StartPrecaching(precache_callback_.GetCallback(),
213 &url_list_provider);
215 // Since the |url_list_provider| ran the callback immediately, Start() has
216 // been called on the PrecacheFetcher, and the precache config settings have
217 // been requested. The response has not yet been received though, so
218 // precaching is still in progress.
219 EXPECT_TRUE(precache_manager_.IsPrecaching());
221 precache_manager_.CancelPrecaching();
222 EXPECT_FALSE(precache_manager_.IsPrecaching());
224 base::MessageLoop::current()->RunUntilIdle();
225 EXPECT_FALSE(precache_manager_.IsPrecaching());
226 EXPECT_TRUE(url_list_provider.was_get_urls_called());
227 EXPECT_FALSE(precache_callback_.was_on_done_called());
229 // Even though the response for the precache config settings should not have
230 // been received, the request should still have been made.
231 std::multiset<GURL> expected_requested_urls;
232 expected_requested_urls.insert(GURL(kConfigURL));
233 EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
236 TEST_F(PrecacheManagerTest, RecordStatsForFetchWithIrrelevantFetches) {
237 HistogramCountMap expected_histogram_count_map = GetHistogramCountMap();
239 // Fetches with size 0 should be ignored.
240 precache_manager_.RecordStatsForFetch(GURL("http://url.com"), base::Time(), 0,
241 false);
242 base::MessageLoop::current()->RunUntilIdle();
243 EXPECT_EQ(expected_histogram_count_map, GetHistogramCountMap());
245 // Fetches for URLs with schemes other than HTTP or HTTPS should be ignored.
246 precache_manager_.RecordStatsForFetch(GURL("ftp://ftp.com"), base::Time(),
247 1000, false);
248 base::MessageLoop::current()->RunUntilIdle();
249 EXPECT_EQ(expected_histogram_count_map, GetHistogramCountMap());
251 // Fetches for empty URLs should be ignored.
252 precache_manager_.RecordStatsForFetch(GURL(), base::Time(), 1000, false);
253 base::MessageLoop::current()->RunUntilIdle();
254 EXPECT_EQ(expected_histogram_count_map, GetHistogramCountMap());
257 TEST_F(PrecacheManagerTest, RecordStatsForFetchDuringPrecaching) {
258 HistogramCountMap expected_histogram_count_map = GetHistogramCountMap();
260 FakeURLListProvider url_list_provider(std::list<GURL>(), false);
261 precache_manager_.StartPrecaching(precache_callback_.GetCallback(),
262 &url_list_provider);
264 EXPECT_TRUE(precache_manager_.IsPrecaching());
265 precache_manager_.RecordStatsForFetch(GURL("http://url.com"), base::Time(),
266 1000, false);
268 precache_manager_.CancelPrecaching();
270 base::MessageLoop::current()->RunUntilIdle();
271 expected_histogram_count_map["Precache.DownloadedPrecacheMotivated"]++;
272 EXPECT_EQ(expected_histogram_count_map, GetHistogramCountMap());
275 TEST_F(PrecacheManagerTest, RecordStatsForFetchHTTP) {
276 HistogramCountMap expected_histogram_count_map = GetHistogramCountMap();
278 precache_manager_.RecordStatsForFetch(GURL("http://http-url.com"),
279 base::Time(), 1000, false);
280 base::MessageLoop::current()->RunUntilIdle();
282 expected_histogram_count_map["Precache.DownloadedNonPrecache"]++;
283 EXPECT_EQ(expected_histogram_count_map, GetHistogramCountMap());
286 TEST_F(PrecacheManagerTest, RecordStatsForFetchHTTPS) {
287 HistogramCountMap expected_histogram_count_map = GetHistogramCountMap();
289 precache_manager_.RecordStatsForFetch(GURL("https://https-url.com"),
290 base::Time(), 1000, false);
291 base::MessageLoop::current()->RunUntilIdle();
293 expected_histogram_count_map["Precache.DownloadedNonPrecache"]++;
294 EXPECT_EQ(expected_histogram_count_map, GetHistogramCountMap());
297 TEST_F(PrecacheManagerTest, DeleteExpiredPrecacheHistory) {
298 // This test has to use Time::Now() because StartPrecaching uses Time::Now().
299 const base::Time kCurrentTime = base::Time::Now();
300 HistogramCountMap expected_histogram_count_map = GetHistogramCountMap();
302 FakeURLListProvider url_list_provider(std::list<GURL>(), false);
303 precache_manager_.StartPrecaching(precache_callback_.GetCallback(),
304 &url_list_provider);
305 EXPECT_TRUE(precache_manager_.IsPrecaching());
307 // Precache a bunch of URLs, with different fetch times.
308 precache_manager_.RecordStatsForFetch(
309 GURL("http://old-fetch.com"),
310 kCurrentTime - base::TimeDelta::FromDays(61), 1000, false);
311 precache_manager_.RecordStatsForFetch(
312 GURL("http://recent-fetch.com"),
313 kCurrentTime - base::TimeDelta::FromDays(59), 1000, false);
314 precache_manager_.RecordStatsForFetch(
315 GURL("http://yesterday-fetch.com"),
316 kCurrentTime - base::TimeDelta::FromDays(1), 1000, false);
317 expected_histogram_count_map["Precache.DownloadedPrecacheMotivated"] += 3;
319 precache_manager_.CancelPrecaching();
320 base::MessageLoop::current()->RunUntilIdle();
321 EXPECT_EQ(expected_histogram_count_map, GetHistogramCountMap());
323 // The expired precache will be deleted during precaching this time.
324 precache_manager_.StartPrecaching(precache_callback_.GetCallback(),
325 &url_list_provider);
326 EXPECT_TRUE(precache_manager_.IsPrecaching());
328 precache_manager_.CancelPrecaching();
329 base::MessageLoop::current()->RunUntilIdle();
330 EXPECT_FALSE(precache_manager_.IsPrecaching());
332 // A fetch for the same URL as the expired precache was served from the cache,
333 // but it isn't reported as saved bytes because it had expired in the precache
334 // history.
335 precache_manager_.RecordStatsForFetch(
336 GURL("http://old-fetch.com"),
337 kCurrentTime, 1000, true);
339 base::MessageLoop::current()->RunUntilIdle();
340 EXPECT_EQ(expected_histogram_count_map, GetHistogramCountMap());
342 // The other precaches should not have expired, so the following fetches from
343 // the cache should count as saved bytes.
344 precache_manager_.RecordStatsForFetch(
345 GURL("http://recent-fetch.com"),
346 kCurrentTime, 1000, true);
347 precache_manager_.RecordStatsForFetch(
348 GURL("http://yesterday-fetch.com"),
349 kCurrentTime, 1000, true);
350 expected_histogram_count_map["Precache.Saved"] += 2;
352 base::MessageLoop::current()->RunUntilIdle();
353 EXPECT_EQ(expected_histogram_count_map, GetHistogramCountMap());
356 } // namespace
358 } // namespace precache