Revert "Fix broken channel icon in chrome://help on CrOS" and try again
[chromium-blink-merge.git] / components / precache / content / precache_manager_unittest.cc
blob72167d3fac8d2ad03b9ea65f0536387a21cea31a
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 <map>
8 #include <set>
9 #include <string>
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/command_line.h"
15 #include "base/compiler_specific.h"
16 #include "base/location.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/test/histogram_tester.h"
19 #include "base/thread_task_runner_handle.h"
20 #include "components/history/core/browser/history_constants.h"
21 #include "components/history/core/browser/history_service.h"
22 #include "components/history/core/browser/history_types.h"
23 #include "components/precache/core/precache_switches.h"
24 #include "content/public/test/test_browser_context.h"
25 #include "content/public/test/test_browser_thread_bundle.h"
26 #include "net/http/http_status_code.h"
27 #include "net/url_request/test_url_fetcher_factory.h"
28 #include "net/url_request/url_request_status.h"
29 #include "net/url_request/url_request_test_util.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "url/gurl.h"
34 namespace precache {
36 namespace {
38 using ::testing::_;
39 using ::testing::ContainerEq;
40 using ::testing::ElementsAre;
41 using ::testing::Invoke;
42 using ::testing::IsEmpty;
43 using ::testing::Pair;
44 using ::testing::SaveArg;
46 const char kConfigURL[] = "http://config-url.com";
47 const char kManifestURLPrefix[] = "http://manifest-url-prefix.com/";
48 const char kGoodManifestURL[] =
49 "http://manifest-url-prefix.com/good-manifest.com";
51 class TestURLFetcherCallback {
52 public:
53 scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
54 const GURL& url, net::URLFetcherDelegate* delegate,
55 const std::string& response_data, net::HttpStatusCode response_code,
56 net::URLRequestStatus::Status status) {
57 scoped_ptr<net::FakeURLFetcher> fetcher(new net::FakeURLFetcher(
58 url, delegate, response_data, response_code, status));
60 requested_urls_.insert(url);
61 return fetcher.Pass();
64 const std::multiset<GURL>& requested_urls() const {
65 return requested_urls_;
68 private:
69 // Multiset with one entry for each URL requested.
70 std::multiset<GURL> requested_urls_;
73 class MockHistoryService : public history::HistoryService {
74 public:
75 MockHistoryService() {
76 ON_CALL(*this, HostRankIfAvailable(_, _))
77 .WillByDefault(Invoke(
78 [](const GURL& url, const base::Callback<void(int)>& callback) {
79 callback.Run(history::kMaxTopHosts);
80 }));
83 MOCK_CONST_METHOD2(TopHosts,
84 void(int num_hosts, const TopHostsCallback& callback));
86 MOCK_CONST_METHOD2(HostRankIfAvailable,
87 void(const GURL& url,
88 const base::Callback<void(int)>& callback));
91 ACTION_P(ReturnHosts, starting_hosts) {
92 arg1.Run(starting_hosts);
95 class TestPrecacheCompletionCallback {
96 public:
97 TestPrecacheCompletionCallback() : was_on_done_called_(false) {}
99 void OnDone(bool precaching_started) { was_on_done_called_ = true; }
101 PrecacheManager::PrecacheCompletionCallback GetCallback() {
102 return base::Bind(&TestPrecacheCompletionCallback::OnDone,
103 base::Unretained(this));
106 bool was_on_done_called() const {
107 return was_on_done_called_;
110 private:
111 bool was_on_done_called_;
114 class PrecacheManagerUnderTest : public PrecacheManager {
115 public:
116 PrecacheManagerUnderTest(content::BrowserContext* browser_context,
117 const sync_driver::SyncService* const sync_service,
118 const history::HistoryService* const history_service)
119 : PrecacheManager(browser_context, sync_service, history_service) {}
120 bool ShouldRun() const override { return true; }
121 bool WouldRun() const override { return true; }
124 class PrecacheManagerTest : public testing::Test {
125 public:
126 PrecacheManagerTest()
127 : precache_manager_(&browser_context_,
128 nullptr /* sync_service */,
129 &history_service_),
130 factory_(nullptr,
131 base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
132 base::Unretained(&url_callback_))) {}
134 protected:
135 void SetUp() override {
136 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
137 switches::kPrecacheConfigSettingsURL, kConfigURL);
138 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
139 switches::kPrecacheManifestURLPrefix, kManifestURLPrefix);
141 // Make the fetch of the precache configuration settings fail. Precaching
142 // should still complete normally in this case.
143 factory_.SetFakeResponse(GURL(kConfigURL), "",
144 net::HTTP_INTERNAL_SERVER_ERROR,
145 net::URLRequestStatus::FAILED);
148 content::TestBrowserThreadBundle test_browser_thread_bundle_;
149 content::TestBrowserContext browser_context_;
150 PrecacheManagerUnderTest precache_manager_;
151 TestURLFetcherCallback url_callback_;
152 net::FakeURLFetcherFactory factory_;
153 TestPrecacheCompletionCallback precache_callback_;
154 testing::NiceMock<MockHistoryService> history_service_;
155 base::HistogramTester histograms_;
158 TEST_F(PrecacheManagerTest, StartAndFinishPrecaching) {
159 EXPECT_FALSE(precache_manager_.IsPrecaching());
161 MockHistoryService::TopHostsCallback top_hosts_callback;
162 EXPECT_CALL(history_service_, TopHosts(NumTopHosts(), _))
163 .WillOnce(SaveArg<1>(&top_hosts_callback));
165 factory_.SetFakeResponse(GURL(kGoodManifestURL), "", net::HTTP_OK,
166 net::URLRequestStatus::SUCCESS);
168 precache_manager_.StartPrecaching(precache_callback_.GetCallback());
170 EXPECT_TRUE(precache_manager_.IsPrecaching());
172 top_hosts_callback.Run(
173 history::TopHostsList(1, std::make_pair("good-manifest.com", 1)));
174 base::MessageLoop::current()->RunUntilIdle(); // For PrecacheFetcher.
175 EXPECT_FALSE(precache_manager_.IsPrecaching());
176 EXPECT_TRUE(precache_callback_.was_on_done_called());
178 std::multiset<GURL> expected_requested_urls;
179 expected_requested_urls.insert(GURL(kConfigURL));
180 expected_requested_urls.insert(GURL(kGoodManifestURL));
181 EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
184 TEST_F(PrecacheManagerTest, StartAndCancelPrecachingBeforeURLsReceived) {
185 EXPECT_FALSE(precache_manager_.IsPrecaching());
187 MockHistoryService::TopHostsCallback top_hosts_callback;
188 EXPECT_CALL(history_service_, TopHosts(NumTopHosts(), _))
189 .WillOnce(SaveArg<1>(&top_hosts_callback));
191 precache_manager_.StartPrecaching(precache_callback_.GetCallback());
192 EXPECT_TRUE(precache_manager_.IsPrecaching());
194 precache_manager_.CancelPrecaching();
195 EXPECT_FALSE(precache_manager_.IsPrecaching());
197 top_hosts_callback.Run(
198 history::TopHostsList(1, std::make_pair("starting-url.com", 1)));
199 base::MessageLoop::current()->RunUntilIdle(); // For PrecacheFetcher.
200 EXPECT_FALSE(precache_manager_.IsPrecaching());
201 EXPECT_FALSE(precache_callback_.was_on_done_called());
202 EXPECT_TRUE(url_callback_.requested_urls().empty());
205 TEST_F(PrecacheManagerTest, StartAndCancelPrecachingAfterURLsReceived) {
206 EXPECT_FALSE(precache_manager_.IsPrecaching());
208 EXPECT_CALL(history_service_, TopHosts(NumTopHosts(), _))
209 .WillOnce(ReturnHosts(
210 history::TopHostsList(1, std::make_pair("starting-url.com", 1))));
212 precache_manager_.StartPrecaching(precache_callback_.GetCallback());
214 // Since the |history_service_| ran the callback immediately, Start() has
215 // been called on the PrecacheFetcher, and the precache config settings have
216 // been requested. The response has not yet been received though, so
217 // precaching is still in progress.
218 EXPECT_TRUE(precache_manager_.IsPrecaching());
220 precache_manager_.CancelPrecaching();
221 EXPECT_FALSE(precache_manager_.IsPrecaching());
223 base::MessageLoop::current()->RunUntilIdle(); // For PrecacheFetcher.
224 EXPECT_FALSE(precache_manager_.IsPrecaching());
225 EXPECT_FALSE(precache_callback_.was_on_done_called());
227 // Even though the response for the precache config settings should not have
228 // been received, the request should still have been made.
229 std::multiset<GURL> expected_requested_urls;
230 expected_requested_urls.insert(GURL(kConfigURL));
231 EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
234 TEST_F(PrecacheManagerTest, RecordStatsForFetchWithSizeZero) {
235 // Fetches with size 0 should be ignored.
236 precache_manager_.RecordStatsForFetch(GURL("http://url.com"), GURL(),
237 base::TimeDelta(), base::Time(), 0,
238 false);
239 base::MessageLoop::current()->RunUntilIdle();
240 EXPECT_THAT(histograms_.GetTotalCountsForPrefix("Precache."), IsEmpty());
243 TEST_F(PrecacheManagerTest, RecordStatsForFetchWithNonHTTP) {
244 // Fetches for URLs with schemes other than HTTP or HTTPS should be ignored.
245 precache_manager_.RecordStatsForFetch(GURL("ftp://ftp.com"), GURL(),
246 base::TimeDelta(), base::Time(), 1000,
247 false);
248 base::MessageLoop::current()->RunUntilIdle();
249 EXPECT_THAT(histograms_.GetTotalCountsForPrefix("Precache."), IsEmpty());
252 TEST_F(PrecacheManagerTest, RecordStatsForFetchWithEmptyURL) {
253 // Fetches for empty URLs should be ignored.
254 precache_manager_.RecordStatsForFetch(GURL(), GURL(), base::TimeDelta(),
255 base::Time(), 1000, false);
256 base::MessageLoop::current()->RunUntilIdle();
257 EXPECT_THAT(histograms_.GetTotalCountsForPrefix("Precache."), IsEmpty());
260 TEST_F(PrecacheManagerTest, RecordStatsForFetchDuringPrecaching) {
261 EXPECT_CALL(history_service_, TopHosts(NumTopHosts(), _))
262 .WillOnce(ReturnHosts(history::TopHostsList()));
264 precache_manager_.StartPrecaching(precache_callback_.GetCallback());
266 EXPECT_TRUE(precache_manager_.IsPrecaching());
267 precache_manager_.RecordStatsForFetch(GURL("http://url.com"), GURL(),
268 base::TimeDelta(), base::Time(), 1000,
269 false);
271 precache_manager_.CancelPrecaching();
273 // For PrecacheFetcher and RecordURLPrecached.
274 base::MessageLoop::current()->RunUntilIdle();
275 EXPECT_THAT(histograms_.GetTotalCountsForPrefix("Precache."),
276 ElementsAre(Pair("Precache.DownloadedPrecacheMotivated", 1),
277 Pair("Precache.Fetch.PercentCompleted", 1),
278 Pair("Precache.Fetch.ResponseBytes.Network", 1),
279 Pair("Precache.Fetch.ResponseBytes.Total", 1),
280 Pair("Precache.Latency.Prefetch", 1)));
283 TEST_F(PrecacheManagerTest, RecordStatsForFetchHTTP) {
284 precache_manager_.RecordStatsForFetch(GURL("http://http-url.com"), GURL(),
285 base::TimeDelta(), base::Time(), 1000,
286 false);
287 base::MessageLoop::current()->RunUntilIdle();
289 EXPECT_THAT(histograms_.GetTotalCountsForPrefix("Precache."),
290 ElementsAre(Pair("Precache.DownloadedNonPrecache", 1),
291 Pair("Precache.Latency.NonPrefetch", 1),
292 Pair("Precache.Latency.NonPrefetch.NonTopHosts", 1)));
295 TEST_F(PrecacheManagerTest, RecordStatsForFetchHTTPS) {
296 precache_manager_.RecordStatsForFetch(GURL("https://https-url.com"), GURL(),
297 base::TimeDelta(), base::Time(), 1000,
298 false);
299 base::MessageLoop::current()->RunUntilIdle();
301 EXPECT_THAT(histograms_.GetTotalCountsForPrefix("Precache."),
302 ElementsAre(Pair("Precache.DownloadedNonPrecache", 1),
303 Pair("Precache.Latency.NonPrefetch", 1),
304 Pair("Precache.Latency.NonPrefetch.NonTopHosts", 1)));
307 TEST_F(PrecacheManagerTest, RecordStatsForFetchInTopHosts) {
308 EXPECT_CALL(history_service_,
309 HostRankIfAvailable(GURL("http://referrer.com"), _))
310 .WillOnce(Invoke(
311 [](const GURL& url, const base::Callback<void(int)>& callback) {
312 callback.Run(0);
313 }));
314 precache_manager_.RecordStatsForFetch(
315 GURL("http://http-url.com"), GURL("http://referrer.com"),
316 base::TimeDelta(), base::Time(), 1000, false);
317 base::MessageLoop::current()->RunUntilIdle();
319 EXPECT_THAT(histograms_.GetTotalCountsForPrefix("Precache."),
320 ElementsAre(Pair("Precache.DownloadedNonPrecache", 1),
321 Pair("Precache.Latency.NonPrefetch", 1),
322 Pair("Precache.Latency.NonPrefetch.TopHosts", 1)));
325 TEST_F(PrecacheManagerTest, DeleteExpiredPrecacheHistory) {
326 // TODO(twifkak): Split this into multiple tests.
327 base::HistogramTester::CountsMap expected_histogram_count_map;
329 // This test has to use Time::Now() because StartPrecaching uses Time::Now().
330 const base::Time kCurrentTime = base::Time::Now();
331 EXPECT_CALL(history_service_, TopHosts(NumTopHosts(), _))
332 .Times(2)
333 .WillRepeatedly(ReturnHosts(history::TopHostsList()));
335 precache_manager_.StartPrecaching(precache_callback_.GetCallback());
336 EXPECT_TRUE(precache_manager_.IsPrecaching());
338 // Precache a bunch of URLs, with different fetch times.
339 precache_manager_.RecordStatsForFetch(
340 GURL("http://old-fetch.com"), GURL(), base::TimeDelta(),
341 kCurrentTime - base::TimeDelta::FromDays(61), 1000, false);
342 precache_manager_.RecordStatsForFetch(
343 GURL("http://recent-fetch.com"), GURL(), base::TimeDelta(),
344 kCurrentTime - base::TimeDelta::FromDays(59), 1000, false);
345 precache_manager_.RecordStatsForFetch(
346 GURL("http://yesterday-fetch.com"), GURL(), base::TimeDelta(),
347 kCurrentTime - base::TimeDelta::FromDays(1), 1000, false);
348 expected_histogram_count_map["Precache.DownloadedPrecacheMotivated"] += 3;
349 expected_histogram_count_map["Precache.Fetch.PercentCompleted"]++;
350 expected_histogram_count_map["Precache.Fetch.ResponseBytes.Network"]++;
351 expected_histogram_count_map["Precache.Fetch.ResponseBytes.Total"]++;
352 expected_histogram_count_map["Precache.Latency.Prefetch"] += 3;
354 precache_manager_.CancelPrecaching();
355 // For PrecacheFetcher and RecordURLPrecached.
356 base::MessageLoop::current()->RunUntilIdle();
357 EXPECT_THAT(histograms_.GetTotalCountsForPrefix("Precache."),
358 ContainerEq(expected_histogram_count_map));
360 // The expired precache will be deleted during precaching this time.
361 precache_manager_.StartPrecaching(precache_callback_.GetCallback());
362 EXPECT_TRUE(precache_manager_.IsPrecaching());
363 expected_histogram_count_map["Precache.Fetch.PercentCompleted"]++;
364 expected_histogram_count_map["Precache.Fetch.ResponseBytes.Network"]++;
365 expected_histogram_count_map["Precache.Fetch.ResponseBytes.Total"]++;
367 precache_manager_.CancelPrecaching();
368 // For PrecacheFetcher and RecordURLPrecached.
369 base::MessageLoop::current()->RunUntilIdle();
370 EXPECT_FALSE(precache_manager_.IsPrecaching());
372 // A fetch for the same URL as the expired precache was served from the cache,
373 // but it isn't reported as saved bytes because it had expired in the precache
374 // history.
375 precache_manager_.RecordStatsForFetch(GURL("http://old-fetch.com"), GURL(),
376 base::TimeDelta(), kCurrentTime, 1000,
377 true);
378 expected_histogram_count_map["Precache.Latency.NonPrefetch"]++;
379 expected_histogram_count_map["Precache.Latency.NonPrefetch.NonTopHosts"]++;
381 base::MessageLoop::current()->RunUntilIdle();
382 EXPECT_THAT(histograms_.GetTotalCountsForPrefix("Precache."),
383 ContainerEq(expected_histogram_count_map));
385 // The other precaches should not have expired, so the following fetches from
386 // the cache should count as saved bytes.
387 precache_manager_.RecordStatsForFetch(GURL("http://recent-fetch.com"), GURL(),
388 base::TimeDelta(), kCurrentTime, 1000,
389 true);
390 precache_manager_.RecordStatsForFetch(GURL("http://yesterday-fetch.com"),
391 GURL(), base::TimeDelta(), kCurrentTime,
392 1000, true);
393 expected_histogram_count_map["Precache.Latency.NonPrefetch"] += 2;
394 expected_histogram_count_map["Precache.Latency.NonPrefetch.NonTopHosts"] += 2;
395 expected_histogram_count_map["Precache.Saved"] += 2;
397 base::MessageLoop::current()->RunUntilIdle();
398 EXPECT_THAT(histograms_.GetTotalCountsForPrefix("Precache."),
399 ContainerEq(expected_histogram_count_map));
402 } // namespace
404 } // namespace precache