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/core/precache_fetcher.h"
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/message_loop/message_loop.h"
17 #include "components/precache/core/precache_switches.h"
18 #include "components/precache/core/proto/precache.pb.h"
19 #include "net/http/http_response_headers.h"
20 #include "net/http/http_status_code.h"
21 #include "net/url_request/test_url_fetcher_factory.h"
22 #include "net/url_request/url_request_test_util.h"
23 #include "testing/gtest/include/gtest/gtest.h"
29 class TestURLFetcherCallback {
31 scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
32 const GURL& url, net::URLFetcherDelegate* delegate,
33 const std::string& response_data, net::HttpStatusCode response_code) {
34 scoped_ptr<net::FakeURLFetcher> fetcher(
35 new net::FakeURLFetcher(url, delegate, response_data, response_code));
37 if (response_code == net::HTTP_OK) {
38 scoped_refptr<net::HttpResponseHeaders> download_headers =
39 new net::HttpResponseHeaders("");
40 download_headers->AddHeader("Content-Type: text/html");
41 fetcher->set_response_headers(download_headers);
44 requested_urls_.insert(url);
45 return fetcher.Pass();
48 const std::multiset<GURL>& requested_urls() const {
49 return requested_urls_;
53 // Multiset with one entry for each URL requested.
54 std::multiset<GURL> requested_urls_;
57 class TestPrecacheDelegate : public PrecacheFetcher::PrecacheDelegate {
59 TestPrecacheDelegate() : was_on_done_called_(false) {}
61 virtual void OnDone() OVERRIDE {
62 was_on_done_called_ = true;
65 bool was_on_done_called() const {
66 return was_on_done_called_;
70 bool was_on_done_called_;
73 class PrecacheFetcherTest : public testing::Test {
76 : request_context_(new net::TestURLRequestContextGetter(
77 base::MessageLoopProxy::current())),
78 factory_(NULL, base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
79 base::Unretained(&url_callback_))) {}
82 base::MessageLoopForUI loop_;
83 scoped_refptr<net::TestURLRequestContextGetter> request_context_;
84 TestURLFetcherCallback url_callback_;
85 net::FakeURLFetcherFactory factory_;
86 TestPrecacheDelegate precache_delegate_;
89 const char kConfigURL[] = "http://config-url.com";
90 const char kManfiestURLPrefix[] = "http://manifest-url-prefix.com/";
91 const char kManifestFetchFailureURL[] =
92 "http://manifest-url-prefix.com/"
93 "http%253A%252F%252Fmanifest-fetch-failure.com%252F";
94 const char kBadManifestURL[] =
95 "http://manifest-url-prefix.com/http%253A%252F%252Fbad-manifest.com%252F";
96 const char kGoodManifestURL[] =
97 "http://manifest-url-prefix.com/http%253A%252F%252Fgood-manifest.com%252F";
98 const char kResourceFetchFailureURL[] = "http://resource-fetch-failure.com";
99 const char kGoodResourceURL[] = "http://good-resource.com";
101 TEST_F(PrecacheFetcherTest, FullPrecache) {
102 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
103 switches::kPrecacheConfigSettingsURL, kConfigURL);
104 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
105 switches::kPrecacheManifestURLPrefix, kManfiestURLPrefix);
107 std::list<GURL> starting_urls;
108 starting_urls.push_back(GURL("http://not-whitelisted.com"));
109 starting_urls.push_back(GURL("http://manifest-fetch-failure.com"));
110 starting_urls.push_back(GURL("http://bad-manifest.com"));
111 starting_urls.push_back(GURL("http://good-manifest.com"));
112 starting_urls.push_back(GURL("http://not-in-top-4.com"));
114 PrecacheConfigurationSettings config;
115 config.add_whitelisted_starting_url("http://whitelisted-unused.com");
116 config.add_whitelisted_starting_url("http://manifest-fetch-failure.com");
117 config.add_whitelisted_starting_url("http://bad-manifest.com");
118 config.add_whitelisted_starting_url("http://good-manifest.com");
119 config.add_whitelisted_starting_url("http://not-in-top-4.com");
120 config.set_maximum_rank_starting_url(4);
122 PrecacheManifest good_manifest;
123 good_manifest.add_resource()->set_url(kResourceFetchFailureURL);
124 good_manifest.add_resource(); // Resource with no URL, should not be fetched.
125 good_manifest.add_resource()->set_url(kGoodResourceURL);
127 factory_.SetFakeResponse(GURL(kConfigURL),
128 config.SerializeAsString(),
130 factory_.SetFakeResponse(GURL(kManifestFetchFailureURL),
132 net::HTTP_INTERNAL_SERVER_ERROR);
133 factory_.SetFakeResponse(GURL(kBadManifestURL), "bad protobuf", net::HTTP_OK);
134 factory_.SetFakeResponse(GURL(kGoodManifestURL),
135 good_manifest.SerializeAsString(), net::HTTP_OK);
136 factory_.SetFakeResponse(GURL(kResourceFetchFailureURL),
138 net::HTTP_INTERNAL_SERVER_ERROR);
139 factory_.SetFakeResponse(GURL(kGoodResourceURL), "good", net::HTTP_OK);
141 PrecacheFetcher precache_fetcher(starting_urls, request_context_.get(),
142 &precache_delegate_);
143 precache_fetcher.Start();
145 base::MessageLoop::current()->RunUntilIdle();
147 std::multiset<GURL> expected_requested_urls;
148 expected_requested_urls.insert(GURL(kConfigURL));
149 expected_requested_urls.insert(GURL(kManifestFetchFailureURL));
150 expected_requested_urls.insert(GURL(kBadManifestURL));
151 expected_requested_urls.insert(GURL(kGoodManifestURL));
152 expected_requested_urls.insert(GURL(kResourceFetchFailureURL));
153 expected_requested_urls.insert(GURL(kGoodResourceURL));
155 EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
157 EXPECT_TRUE(precache_delegate_.was_on_done_called());
160 TEST_F(PrecacheFetcherTest, ConfigFetchFailure) {
161 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
162 switches::kPrecacheConfigSettingsURL, kConfigURL);
164 std::list<GURL> starting_urls(1, GURL("http://starting-url.com"));
166 factory_.SetFakeResponse(GURL(kConfigURL),
168 net::HTTP_INTERNAL_SERVER_ERROR);
170 PrecacheFetcher precache_fetcher(starting_urls, request_context_.get(),
171 &precache_delegate_);
172 precache_fetcher.Start();
174 base::MessageLoop::current()->RunUntilIdle();
176 std::multiset<GURL> expected_requested_urls;
177 expected_requested_urls.insert(GURL(kConfigURL));
178 EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
180 EXPECT_TRUE(precache_delegate_.was_on_done_called());
183 TEST_F(PrecacheFetcherTest, BadConfig) {
184 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
185 switches::kPrecacheConfigSettingsURL, kConfigURL);
187 std::list<GURL> starting_urls(1, GURL("http://starting-url.com"));
189 factory_.SetFakeResponse(GURL(kConfigURL), "bad protobuf", net::HTTP_OK);
191 PrecacheFetcher precache_fetcher(starting_urls, request_context_.get(),
192 &precache_delegate_);
193 precache_fetcher.Start();
195 base::MessageLoop::current()->RunUntilIdle();
197 std::multiset<GURL> expected_requested_urls;
198 expected_requested_urls.insert(GURL(kConfigURL));
199 EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
201 EXPECT_TRUE(precache_delegate_.was_on_done_called());
204 TEST_F(PrecacheFetcherTest, Cancel) {
205 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
206 switches::kPrecacheConfigSettingsURL, kConfigURL);
208 std::list<GURL> starting_urls(1, GURL("http://starting-url.com"));
210 PrecacheConfigurationSettings config;
211 config.add_whitelisted_starting_url("http://starting-url.com");
212 config.set_maximum_rank_starting_url(1);
214 factory_.SetFakeResponse(GURL(kConfigURL),
215 config.SerializeAsString(),
218 scoped_ptr<PrecacheFetcher> precache_fetcher(new PrecacheFetcher(
219 starting_urls, request_context_.get(), &precache_delegate_));
220 precache_fetcher->Start();
222 // Destroy the PrecacheFetcher to cancel precaching. This should not cause
223 // OnDone to be called on the precache delegate.
224 precache_fetcher.reset();
226 base::MessageLoop::current()->RunUntilIdle();
228 std::multiset<GURL> expected_requested_urls;
229 expected_requested_urls.insert(GURL(kConfigURL));
230 EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
232 EXPECT_FALSE(precache_delegate_.was_on_done_called());
235 #if defined(PRECACHE_CONFIG_SETTINGS_URL)
237 // If the default precache configuration settings URL is defined, then test that
238 // it works with the PrecacheFetcher.
239 TEST_F(PrecacheFetcherTest, PrecacheUsingDefaultConfigSettingsURL) {
240 std::list<GURL> starting_urls(1, GURL("http://starting-url.com"));
242 factory_.SetFakeResponse(GURL(PRECACHE_CONFIG_SETTINGS_URL),
243 PrecacheConfigurationSettings().SerializeAsString(),
246 PrecacheFetcher precache_fetcher(starting_urls, request_context_.get(),
247 &precache_delegate_);
248 precache_fetcher.Start();
250 base::MessageLoop::current()->RunUntilIdle();
252 std::multiset<GURL> expected_requested_urls;
253 expected_requested_urls.insert(GURL(PRECACHE_CONFIG_SETTINGS_URL));
254 EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
256 EXPECT_TRUE(precache_delegate_.was_on_done_called());
259 #endif // PRECACHE_CONFIG_SETTINGS_URL
261 #if defined(PRECACHE_MANIFEST_URL_PREFIX)
263 // If the default precache manifest URL prefix is defined, then test that it
264 // works with the PrecacheFetcher.
265 TEST_F(PrecacheFetcherTest, PrecacheUsingDefaultManifestURLPrefix) {
266 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
267 switches::kPrecacheConfigSettingsURL, kConfigURL);
269 std::list<GURL> starting_urls(1, GURL("http://starting-url.com"));
271 PrecacheConfigurationSettings config;
272 config.add_whitelisted_starting_url("http://starting-url.com");
273 config.set_maximum_rank_starting_url(1);
275 GURL manifest_url(PRECACHE_MANIFEST_URL_PREFIX
276 "http%253A%252F%252Fstarting-url.com%252F");
278 factory_.SetFakeResponse(GURL(kConfigURL),
279 config.SerializeAsString(),
281 factory_.SetFakeResponse(manifest_url,
282 PrecacheManifest().SerializeAsString(),
285 PrecacheFetcher precache_fetcher(starting_urls, request_context_.get(),
286 &precache_delegate_);
287 precache_fetcher.Start();
289 base::MessageLoop::current()->RunUntilIdle();
291 std::multiset<GURL> expected_requested_urls;
292 expected_requested_urls.insert(GURL(kConfigURL));
293 expected_requested_urls.insert(manifest_url);
294 EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
296 EXPECT_TRUE(precache_delegate_.was_on_done_called());
299 #endif // PRECACHE_MANIFEST_URL_PREFIX
303 } // namespace precache