Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc

Issue 2519963002: predictors: Add browsertest that checks redirects. (Closed)
Patch Set: Nits. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/command_line.h" 5 #include "base/command_line.h"
6 #include "chrome/browser/predictors/resource_prefetch_predictor.h" 6 #include "chrome/browser/predictors/resource_prefetch_predictor.h"
7 #include "chrome/browser/predictors/resource_prefetch_predictor_factory.h" 7 #include "chrome/browser/predictors/resource_prefetch_predictor_factory.h"
8 #include "chrome/browser/predictors/resource_prefetch_predictor_test_util.h" 8 #include "chrome/browser/predictors/resource_prefetch_predictor_test_util.h"
9 #include "chrome/browser/profiles/profile.h" 9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ui/browser.h" 10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h" 11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/common/chrome_switches.h" 12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/test/base/in_process_browser_test.h" 13 #include "chrome/test/base/in_process_browser_test.h"
14 #include "chrome/test/base/ui_test_utils.h" 14 #include "chrome/test/base/ui_test_utils.h"
15 #include "content/public/browser/render_frame_host.h" 15 #include "content/public/browser/render_frame_host.h"
16 #include "content/public/browser/render_process_host.h" 16 #include "content/public/browser/render_process_host.h"
17 #include "net/test/embedded_test_server/http_request.h" 17 #include "net/test/embedded_test_server/http_request.h"
18 #include "net/test/embedded_test_server/http_response.h" 18 #include "net/test/embedded_test_server/http_response.h"
19 #include "testing/gmock/include/gmock/gmock.h" 19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
21 21
22 namespace predictors { 22 namespace predictors {
23 23
24 static const char kImageUrl[] = "/predictors/image.png"; 24 static const char kImagePath[] = "/predictors/image.png";
25 static const char kStyleUrl[] = "/predictors/style.css"; 25 static const char kStylePath[] = "/predictors/style.css";
26 static const char kScriptUrl[] = "/predictors/script.js"; 26 static const char kScriptPath[] = "/predictors/script.js";
27 static const char kFontUrl[] = "/predictors/font.ttf"; 27 static const char kFontPath[] = "/predictors/font.ttf";
28 static const char kHtmlSubresourcesUrl[] = "/predictors/html_subresources.html"; 28 static const char kHtmlSubresourcesPath[] =
29 "/predictors/html_subresources.html";
30 static const char kRedirectPath[] = "/predictors/redirect.html";
31 static const char kRedirectPath2[] = "/predictors/redirect2.html";
32 static const char kRedirectPath3[] = "/predictors/redirect3.html";
29 33
30 struct ResourceSummary { 34 struct ResourceSummary {
31 ResourceSummary() : is_no_store(false), version(0) {} 35 ResourceSummary() : is_no_store(false), version(0) {}
32 36
33 ResourcePrefetchPredictor::URLRequestSummary request; 37 ResourcePrefetchPredictor::URLRequestSummary request;
34 std::string content; 38 std::string content;
35 bool is_no_store; 39 bool is_no_store;
36 size_t version; 40 size_t version;
37 }; 41 };
38 42
43 struct RedirectEdge {
44 // This response code should be returned by previous url in the chain.
45 net::HttpStatusCode code;
46 GURL url;
47 };
48
39 class InitializationObserver : public TestObserver { 49 class InitializationObserver : public TestObserver {
40 public: 50 public:
41 explicit InitializationObserver(ResourcePrefetchPredictor* predictor) 51 explicit InitializationObserver(ResourcePrefetchPredictor* predictor)
42 : TestObserver(predictor) {} 52 : TestObserver(predictor) {}
43 53
44 void OnPredictorInitialized() override { run_loop_.Quit(); } 54 void OnPredictorInitialized() override { run_loop_.Quit(); }
45 55
46 void Wait() { run_loop_.Run(); } 56 void Wait() { run_loop_.Run(); }
47 57
48 private: 58 private:
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 92
83 private: 93 private:
84 base::RunLoop run_loop_; 94 base::RunLoop run_loop_;
85 size_t url_visit_count_; 95 size_t url_visit_count_;
86 PageRequestSummary summary_; 96 PageRequestSummary summary_;
87 97
88 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetchPredictorTestObserver); 98 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetchPredictorTestObserver);
89 }; 99 };
90 100
91 class ResourcePrefetchPredictorBrowserTest : public InProcessBrowserTest { 101 class ResourcePrefetchPredictorBrowserTest : public InProcessBrowserTest {
92 public: 102 protected:
93 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; 103 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
94 104
95 void SetUpCommandLine(base::CommandLine* command_line) override { 105 void SetUpCommandLine(base::CommandLine* command_line) override {
96 command_line->AppendSwitchASCII( 106 command_line->AppendSwitchASCII(
97 switches::kSpeculativeResourcePrefetching, 107 switches::kSpeculativeResourcePrefetching,
98 switches::kSpeculativeResourcePrefetchingEnabled); 108 switches::kSpeculativeResourcePrefetchingEnabled);
99 } 109 }
100 110
101 void SetUpOnMainThread() override { 111 void SetUpOnMainThread() override {
102 embedded_test_server()->RegisterRequestHandler( 112 embedded_test_server()->RegisterRequestHandler(base::Bind(
103 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleRequest, 113 &ResourcePrefetchPredictorBrowserTest::HandleRedirectRequest,
104 base::Unretained(this))); 114 base::Unretained(this), base::Unretained(embedded_test_server())));
115 embedded_test_server()->RegisterRequestHandler(base::Bind(
116 &ResourcePrefetchPredictorBrowserTest::HandleResourceRequest,
117 base::Unretained(this), base::Unretained(embedded_test_server())));
105 ASSERT_TRUE(embedded_test_server()->Start()); 118 ASSERT_TRUE(embedded_test_server()->Start());
106 predictor_ = 119 predictor_ =
107 ResourcePrefetchPredictorFactory::GetForProfile(browser()->profile()); 120 ResourcePrefetchPredictorFactory::GetForProfile(browser()->profile());
108 ASSERT_TRUE(predictor_); 121 ASSERT_TRUE(predictor_);
109 EnsurePredictorInitialized(); 122 EnsurePredictorInitialized();
110 } 123 }
111 124
112 void NavigateToURLAndCheckSubresources( 125 void NavigateToURLAndCheckSubresources(const GURL& main_frame_url) {
113 const std::string& main_frame_relative) { 126 GURL endpoint_url = GetRedirectEndpoint(main_frame_url);
114 GURL main_frame_absolute =
115 embedded_test_server()->GetURL(main_frame_relative);
116 std::vector<URLRequestSummary> url_request_summaries; 127 std::vector<URLRequestSummary> url_request_summaries;
117 for (const auto& kv : resources_) { 128 for (const auto& kv : resources_) {
118 if (kv.second.is_no_store) 129 if (kv.second.is_no_store)
119 continue; 130 continue;
120 url_request_summaries.push_back( 131 url_request_summaries.push_back(
121 GetURLRequestSummaryForResource(main_frame_absolute, kv.second)); 132 GetURLRequestSummaryForResource(endpoint_url, kv.second));
122 } 133 }
123 ResourcePrefetchPredictorTestObserver observer( 134 ResourcePrefetchPredictorTestObserver observer(
124 predictor_, UpdateAndGetVisitCount(main_frame_relative), 135 predictor_, UpdateAndGetVisitCount(main_frame_url),
125 CreatePageRequestSummary(main_frame_absolute.spec(), 136 CreatePageRequestSummary(endpoint_url.spec(), main_frame_url.spec(),
126 main_frame_absolute.spec(),
127 url_request_summaries)); 137 url_request_summaries));
128 ui_test_utils::NavigateToURL(browser(), main_frame_absolute); 138 ui_test_utils::NavigateToURL(browser(), main_frame_url);
129 observer.Wait(); 139 observer.Wait();
130 } 140 }
131 141
132 ResourceSummary* AddResource(const std::string& relative_url, 142 ResourceSummary* AddResource(const GURL& resource_url,
133 content::ResourceType resource_type, 143 content::ResourceType resource_type,
134 net::RequestPriority priority) { 144 net::RequestPriority priority) {
135 ResourceSummary resource; 145 auto pair_and_whether_inserted =
136 resource.request.resource_url = 146 resources_.insert(std::make_pair(resource_url, ResourceSummary()));
137 embedded_test_server()->GetURL(relative_url); 147 EXPECT_TRUE(pair_and_whether_inserted.second) << resource_url
138 resource.request.resource_type = resource_type; 148 << " was inserted twice";
139 resource.request.priority = priority; 149 ResourceSummary* resource = &pair_and_whether_inserted.first->second;
140 auto result = resources_.insert(std::make_pair(relative_url, resource)); 150 resource->request.resource_url = resource_url;
141 return &(result.first->second); 151 resource->request.resource_type = resource_type;
152 resource->request.priority = priority;
153 resource->request.has_validators = true;
154 return resource;
142 } 155 }
143 156
157 void AddRedirectChain(const GURL& initial_url,
158 const std::vector<RedirectEdge>& redirect_chain) {
159 ASSERT_FALSE(redirect_chain.empty());
160 GURL current = initial_url;
161 for (const auto& edge : redirect_chain) {
162 auto result = redirects_.insert(std::make_pair(current, edge));
163 EXPECT_TRUE(result.second) << current << " already has a redirect.";
164 current = edge.url;
165 }
166 }
167
168 // Shortcut for convenience.
169 GURL GetURL(const std::string& path) const {
170 return embedded_test_server()->GetURL(path);
171 }
172
173 void EnableHttpsServer() {
174 ASSERT_FALSE(https_server_);
175 https_server_ = base::MakeUnique<net::EmbeddedTestServer>(
176 net::EmbeddedTestServer::TYPE_HTTPS);
177 https_server()->AddDefaultHandlers(
178 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
179 https_server()->RegisterRequestHandler(
180 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleRedirectRequest,
181 base::Unretained(this), base::Unretained(https_server())));
182 https_server()->RegisterRequestHandler(
183 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleResourceRequest,
184 base::Unretained(this), base::Unretained(https_server())));
185 ASSERT_TRUE(https_server()->Start());
186 }
187
188 // Returns the embedded test server working over HTTPS. Must be enabled by
189 // calling EnableHttpsServer() before use.
190 const net::EmbeddedTestServer* https_server() const {
191 return https_server_.get();
192 }
193
194 net::EmbeddedTestServer* https_server() { return https_server_.get(); }
195
144 private: 196 private:
145 // ResourcePrefetchPredictor needs to be initialized before the navigation 197 // ResourcePrefetchPredictor needs to be initialized before the navigation
146 // happens otherwise this navigation will be ignored by predictor. 198 // happens otherwise this navigation will be ignored by predictor.
147 void EnsurePredictorInitialized() { 199 void EnsurePredictorInitialized() {
148 if (predictor_->initialization_state_ == 200 if (predictor_->initialization_state_ ==
149 ResourcePrefetchPredictor::INITIALIZED) { 201 ResourcePrefetchPredictor::INITIALIZED) {
150 return; 202 return;
151 } 203 }
152 204
153 InitializationObserver observer(predictor_); 205 InitializationObserver observer(predictor_);
154 if (predictor_->initialization_state_ == 206 if (predictor_->initialization_state_ ==
155 ResourcePrefetchPredictor::NOT_INITIALIZED) { 207 ResourcePrefetchPredictor::NOT_INITIALIZED) {
156 predictor_->StartInitialization(); 208 predictor_->StartInitialization();
157 } 209 }
158 observer.Wait(); 210 observer.Wait();
159 } 211 }
160 212
161 URLRequestSummary GetURLRequestSummaryForResource( 213 URLRequestSummary GetURLRequestSummaryForResource(
162 const GURL& main_frame_url, 214 const GURL& main_frame_url,
163 const ResourceSummary& resource_summary) { 215 const ResourceSummary& resource_summary) const {
164 URLRequestSummary summary(resource_summary.request); 216 URLRequestSummary summary(resource_summary.request);
165 content::WebContents* web_contents = 217 content::WebContents* web_contents =
166 browser()->tab_strip_model()->GetActiveWebContents(); 218 browser()->tab_strip_model()->GetActiveWebContents();
167 int process_id = web_contents->GetRenderProcessHost()->GetID(); 219 int process_id = web_contents->GetRenderProcessHost()->GetID();
168 int frame_id = web_contents->GetMainFrame()->GetRoutingID(); 220 int frame_id = web_contents->GetMainFrame()->GetRoutingID();
169 summary.navigation_id = 221 summary.navigation_id =
170 CreateNavigationID(process_id, frame_id, main_frame_url.spec()); 222 CreateNavigationID(process_id, frame_id, main_frame_url.spec());
171 return summary; 223 return summary;
172 } 224 }
173 225
174 std::unique_ptr<net::test_server::HttpResponse> HandleRequest( 226 GURL GetRedirectEndpoint(const GURL& initial_url) const {
175 const net::test_server::HttpRequest& request) { 227 GURL current = initial_url;
176 auto resource_it = resources_.find(request.relative_url); 228 while (true) {
229 auto it = redirects_.find(current);
230 if (it == redirects_.end())
231 break;
232 current = it->second.url;
233 }
234 return current;
235 }
236
237 std::unique_ptr<net::test_server::HttpResponse> HandleResourceRequest(
238 const net::test_server::EmbeddedTestServer* server,
239 const net::test_server::HttpRequest& request) const {
240 auto resource_it = resources_.find(server->GetURL(request.relative_url));
177 if (resource_it == resources_.end()) 241 if (resource_it == resources_.end())
178 return nullptr; 242 return nullptr;
179 243
180 const ResourceSummary& summary = resource_it->second; 244 const ResourceSummary& summary = resource_it->second;
181 auto http_response = 245 auto http_response =
182 base::MakeUnique<net::test_server::BasicHttpResponse>(); 246 base::MakeUnique<net::test_server::BasicHttpResponse>();
183 http_response->set_code(net::HTTP_OK); 247 http_response->set_code(net::HTTP_OK);
184 if (!summary.request.mime_type.empty()) 248 if (!summary.request.mime_type.empty())
185 http_response->set_content_type(summary.request.mime_type); 249 http_response->set_content_type(summary.request.mime_type);
186 http_response->set_content(summary.content); 250 if (!summary.content.empty())
251 http_response->set_content(summary.content);
187 if (summary.is_no_store) 252 if (summary.is_no_store)
188 http_response->AddCustomHeader("Cache-Control", "no-store"); 253 http_response->AddCustomHeader("Cache-Control", "no-store");
189 if (summary.request.has_validators) { 254 if (summary.request.has_validators) {
190 http_response->AddCustomHeader( 255 http_response->AddCustomHeader(
191 "ETag", base::StringPrintf("'%zu%s'", summary.version, 256 "ETag", base::StringPrintf("'%zu%s'", summary.version,
192 request.relative_url.c_str())); 257 request.relative_url.c_str()));
193 } 258 }
194 if (summary.request.always_revalidate) 259 if (summary.request.always_revalidate)
195 http_response->AddCustomHeader("Cache-Control", "no-cache"); 260 http_response->AddCustomHeader("Cache-Control", "no-cache");
196 else 261 else
197 http_response->AddCustomHeader("Cache-Control", "max-age=2147483648"); 262 http_response->AddCustomHeader("Cache-Control", "max-age=2147483648");
198 return std::move(http_response); 263 return std::move(http_response);
199 } 264 }
200 265
201 size_t UpdateAndGetVisitCount(const std::string& main_frame_relative) { 266 std::unique_ptr<net::test_server::HttpResponse> HandleRedirectRequest(
202 return ++visit_count_[main_frame_relative]; 267 const net::test_server::EmbeddedTestServer* server,
268 const net::test_server::HttpRequest& request) const {
269 auto redirect_it = redirects_.find(server->GetURL(request.relative_url));
270 if (redirect_it == redirects_.end())
271 return nullptr;
272
273 auto http_response =
274 base::MakeUnique<net::test_server::BasicHttpResponse>();
275 http_response->set_code(redirect_it->second.code);
276 http_response->AddCustomHeader("Location", redirect_it->second.url.spec());
277 return std::move(http_response);
278 }
279
280 size_t UpdateAndGetVisitCount(const GURL& main_frame_url) {
281 return ++visit_count_[main_frame_url];
203 } 282 }
204 283
205 ResourcePrefetchPredictor* predictor_; 284 ResourcePrefetchPredictor* predictor_;
206 std::map<std::string, ResourceSummary> resources_; 285 std::unique_ptr<net::EmbeddedTestServer> https_server_;
207 std::map<std::string, size_t> visit_count_; 286 std::map<GURL, ResourceSummary> resources_;
287 std::map<GURL, RedirectEdge> redirects_;
288 std::map<GURL, size_t> visit_count_;
208 }; 289 };
209 290
210 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, LearningSimple) { 291 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, LearningSimple) {
211 // These resources have default priorities that correspond to 292 // These resources have default priorities that correspond to
212 // blink::typeToPriority function. 293 // blink::typeToPriority function.
213 AddResource(kImageUrl, content::RESOURCE_TYPE_IMAGE, net::LOWEST); 294 AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, net::LOWEST);
214 AddResource(kStyleUrl, content::RESOURCE_TYPE_STYLESHEET, net::HIGHEST); 295 AddResource(GetURL(kStylePath), content::RESOURCE_TYPE_STYLESHEET,
215 AddResource(kScriptUrl, content::RESOURCE_TYPE_SCRIPT, net::MEDIUM); 296 net::HIGHEST);
216 AddResource(kFontUrl, content::RESOURCE_TYPE_FONT_RESOURCE, net::HIGHEST); 297 AddResource(GetURL(kScriptPath), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM);
217 NavigateToURLAndCheckSubresources(kHtmlSubresourcesUrl); 298 AddResource(GetURL(kFontPath), content::RESOURCE_TYPE_FONT_RESOURCE,
299 net::HIGHEST);
300 NavigateToURLAndCheckSubresources(GetURL(kHtmlSubresourcesPath));
301 }
302
303 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest,
304 LearningAfterRedirect) {
305 AddRedirectChain(GetURL(kRedirectPath), {{net::HTTP_MOVED_PERMANENTLY,
306 GetURL(kHtmlSubresourcesPath)}});
307 AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, net::LOWEST);
308 AddResource(GetURL(kStylePath), content::RESOURCE_TYPE_STYLESHEET,
309 net::HIGHEST);
310 AddResource(GetURL(kScriptPath), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM);
311 AddResource(GetURL(kFontPath), content::RESOURCE_TYPE_FONT_RESOURCE,
312 net::HIGHEST);
313 NavigateToURLAndCheckSubresources(GetURL(kRedirectPath));
314 }
315
316 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest,
317 LearningAfterRedirectChain) {
318 AddRedirectChain(GetURL(kRedirectPath),
319 {{net::HTTP_FOUND, GetURL(kRedirectPath2)},
320 {net::HTTP_MOVED_PERMANENTLY, GetURL(kRedirectPath3)},
321 {net::HTTP_FOUND, GetURL(kHtmlSubresourcesPath)}});
322 AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, net::LOWEST);
323 AddResource(GetURL(kStylePath), content::RESOURCE_TYPE_STYLESHEET,
324 net::HIGHEST);
325 AddResource(GetURL(kScriptPath), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM);
326 AddResource(GetURL(kFontPath), content::RESOURCE_TYPE_FONT_RESOURCE,
327 net::HIGHEST);
328 NavigateToURLAndCheckSubresources(GetURL(kRedirectPath));
329 }
330
331 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest,
332 LearningAfterHttpToHttpsRedirect) {
333 EnableHttpsServer();
334 AddRedirectChain(GetURL(kRedirectPath),
335 {{net::HTTP_FOUND, https_server()->GetURL(kRedirectPath2)},
336 {net::HTTP_MOVED_PERMANENTLY,
337 https_server()->GetURL(kHtmlSubresourcesPath)}});
338 AddResource(https_server()->GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE,
339 net::LOWEST);
340 AddResource(https_server()->GetURL(kStylePath),
341 content::RESOURCE_TYPE_STYLESHEET, net::HIGHEST);
342 AddResource(https_server()->GetURL(kScriptPath),
343 content::RESOURCE_TYPE_SCRIPT, net::MEDIUM);
344 AddResource(https_server()->GetURL(kFontPath),
345 content::RESOURCE_TYPE_FONT_RESOURCE, net::HIGHEST);
346 NavigateToURLAndCheckSubresources(GetURL(kRedirectPath));
218 } 347 }
219 348
220 } // namespace predictors 349 } // namespace predictors
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698