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

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

Issue 2449323005: predictors: Basic browsertest checks predictor learning. (Closed)
Patch Set: 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "base/command_line.h"
6 #include "chrome/browser/predictors/resource_prefetch_predictor.h"
7 #include "chrome/browser/predictors/resource_prefetch_predictor_factory.h"
8 #include "chrome/browser/predictors/resource_prefetch_predictor_test_util.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/test/base/in_process_browser_test.h"
14 #include "chrome/test/base/ui_test_utils.h"
15 #include "content/public/browser/render_frame_host.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "net/test/embedded_test_server/http_request.h"
18 #include "net/test/embedded_test_server/http_response.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using testing::UnorderedElementsAreArray;
23
24 namespace predictors {
25
26 static const char kImageUrl[] = "/predictors/image.png";
27 static const char kStyleUrl[] = "/predictors/style.css";
28 static const char kScriptUrl[] = "/predictors/script.js";
29 static const char kFontUrl[] = "/predictors/font.ttf";
30 static const char kHtmlSubresourcesUrl[] = "/predictors/html_subresources.html";
31
32 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary;
33 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
34 using net::test_server::HttpRequest;
35 using net::test_server::HttpResponse;
36 using net::test_server::BasicHttpResponse;
37
38 struct ResourceSummary {
Benoit L 2016/11/02 14:03:18 This largely duplicates ResourcePrefetchPredictor:
alexilin 2016/11/02 16:14:47 These structures have mismatched fields. ResourceS
39 ResourceSummary()
40 : resource_type(content::RESOURCE_TYPE_LAST_TYPE),
41 cached(false),
42 has_validators(false),
43 always_revalidate(false),
44 no_store(false),
45 version(0) {}
Benoit L 2016/11/02 14:03:18 Doesn't seem to be used in this CL beyond the Etag
alexilin 2016/11/02 16:14:47 True
46
47 GURL url;
48 content::ResourceType resource_type;
49 std::string mime_type;
50 bool cached;
51 bool has_validators;
52 bool always_revalidate;
53 std::string content;
54 bool no_store;
Benoit L 2016/11/02 14:03:18 tiny nit: I quite like "is_X" for boolean variable
alexilin 2016/11/02 16:14:47 Done.
55 size_t version;
56 };
57
58 net::RequestPriority TypeToPriority(content::ResourceType type) {
Benoit L 2016/11/02 09:56:42 I'm not really sure about the mapping of resource
alexilin 2016/11/02 10:09:14 I'm not sure too. Probably it would be better not
Benoit L 2016/11/02 12:23:12 The actual priority logic is indeed more complex.
alexilin 2016/11/02 13:46:16 I'm not sure that I understood you correctly becau
59 switch (type) {
60 case content::RESOURCE_TYPE_STYLESHEET:
61 case content::RESOURCE_TYPE_FONT_RESOURCE:
62 return net::HIGHEST;
63 case content::RESOURCE_TYPE_SCRIPT:
64 return net::MEDIUM;
65 case content::RESOURCE_TYPE_IMAGE:
66 return net::LOWEST;
67 default:
68 return net::DEFAULT_PRIORITY;
69 }
70 }
71
72 // Helper class to track and allow waiting for ResourcePrefetchPredictor events.
73 class ResourcePrefetchPredictorTestObserver : public TestObserver {
74 public:
75 explicit ResourcePrefetchPredictorTestObserver(
76 ResourcePrefetchPredictor* predictor,
77 const size_t expected_url_visit_count,
78 const PageRequestSummary& expected_summary)
79 : TestObserver(predictor),
80 message_loop_runner_(new content::MessageLoopRunner),
Benoit L 2016/11/02 14:03:18 nit: content::MessageLoopRunner(). That's safer.
alexilin 2016/11/02 16:14:47 Done.
81 url_visit_count_(expected_url_visit_count),
82 summary_(expected_summary) {}
83
84 ~ResourcePrefetchPredictorTestObserver() override {}
85
86 // ResourcePrefetchPredictor::Observer
87 void OnNavigationLearned(size_t url_visit_count,
88 const PageRequestSummary& summary) override {
89 EXPECT_EQ(url_visit_count, url_visit_count_);
90 EXPECT_EQ(summary.main_frame_url, summary_.main_frame_url);
91 EXPECT_EQ(summary.initial_url, summary_.initial_url);
92 EXPECT_THAT(summary.subresource_requests,
93 UnorderedElementsAreArray(summary_.subresource_requests));
94 message_loop_runner_->Quit();
95 }
96
97 void Wait() { message_loop_runner_->Run(); }
98
99 private:
100 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
101 size_t url_visit_count_;
102 PageRequestSummary summary_;
103
104 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetchPredictorTestObserver);
105 };
106
107 class ResourcePrefetchPredictorBrowserTest : public InProcessBrowserTest {
108 public:
109 void SetUpCommandLine(base::CommandLine* command_line) override {
110 command_line->AppendSwitchASCII(
111 switches::kSpeculativeResourcePrefetching,
112 switches::kSpeculativeResourcePrefetchingEnabled);
113 }
114
115 void SetUpOnMainThread() override {
116 embedded_test_server()->RegisterRequestHandler(
117 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleRequest,
118 base::Unretained(this)));
119 ASSERT_TRUE(embedded_test_server()->Start());
120 predictor_ =
121 ResourcePrefetchPredictorFactory::GetForProfile(browser()->profile());
122 ASSERT_TRUE(predictor_);
123 }
124
125 void NavigateToURLAndCheckSubresources(
126 const std::string& main_frame_relative) {
127 GURL main_frame_absolute =
128 embedded_test_server()->GetURL(main_frame_relative);
129 std::vector<URLRequestSummary> url_request_summaries;
130 for (const auto& kv : resources_) {
131 if (kv.second.no_store)
132 continue;
133 url_request_summaries.push_back(
134 GetURLRequestSummaryForResource(main_frame_absolute, kv.second));
135 }
136 ResourcePrefetchPredictorTestObserver observer(
137 predictor_, UpdateAndGetVisitCount(main_frame_relative),
138 CreatePageRequestSummary(main_frame_absolute.spec(),
139 main_frame_absolute.spec(),
140 url_request_summaries));
141 ui_test_utils::NavigateToURL(browser(), main_frame_absolute);
142 observer.Wait();
143 }
144
145 void AddResource(const std::string& relative_url,
146 content::ResourceType resource_type,
147 const std::string& mime_type = std::string(),
148 bool has_validators = true,
149 bool always_revalidate = false,
150 const std::string& content = std::string(),
151 bool no_store = false) {
152 ResourceSummary resource;
153 resource.url = embedded_test_server()->GetURL(relative_url);
154 resource.resource_type = resource_type;
155 resource.mime_type = mime_type;
156 resource.has_validators = has_validators;
157 resource.always_revalidate = always_revalidate;
158 resource.content = content;
159 resource.no_store = no_store;
160 resources_[relative_url] = resource;
161 }
162
163 private:
164 URLRequestSummary GetURLRequestSummaryForResource(
165 const GURL& main_frame_url,
166 const ResourceSummary& summary) {
167 content::WebContents* web_contents =
168 browser()->tab_strip_model()->GetActiveWebContents();
169 int process_id = web_contents->GetRenderProcessHost()->GetID();
170 int frame_id = web_contents->GetMainFrame()->GetRoutingID();
171 return CreateURLRequestSummary(
172 process_id, frame_id, main_frame_url.spec(), summary.url.spec(),
173 summary.resource_type, TypeToPriority(summary.resource_type),
174 summary.mime_type, summary.cached, std::string(),
175 summary.has_validators, summary.always_revalidate);
176 }
177
178 std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
179 auto resource_it = resources_.find(request.relative_url);
180 if (resource_it == resources_.end())
181 return nullptr;
182
183 const ResourceSummary& summary = resource_it->second;
184 std::unique_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
Benoit L 2016/11/02 14:03:18 nit: () Or better: MakeUnique
alexilin 2016/11/02 16:14:47 Done.
185 http_response->set_code(net::HTTP_OK);
186 http_response->set_content_type(summary.mime_type);
187 http_response->set_content(summary.content);
188 if (summary.no_store)
189 http_response->AddCustomHeader("Cache-Control", "no-store");
Benoit L 2016/11/02 14:03:18 It's possible to call this several times, good. Th
alexilin 2016/11/02 16:14:47 Is it good or bad? I had DCHECK checked that no_st
190 if (summary.has_validators) {
191 http_response->AddCustomHeader(
192 "ETag", base::StringPrintf("'%zu%s'", summary.version,
193 request.relative_url.c_str()));
194 }
195 if (summary.always_revalidate)
196 http_response->AddCustomHeader("Cache-Control", "no-cache");
197 else
198 http_response->AddCustomHeader("Cache-Control", "max-age=2147483648");
199 return std::move(http_response);
200 }
201
202 size_t UpdateAndGetVisitCount(const std::string& main_frame_relative) {
203 return ++visit_count_[main_frame_relative];
204 }
205
206 ResourcePrefetchPredictor* predictor_;
207 std::map<std::string, ResourceSummary> resources_;
208 std::map<std::string, size_t> visit_count_;
209 };
210
211 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, ) {
212 AddResource(kImageUrl, content::RESOURCE_TYPE_IMAGE, "image/png");
213 AddResource(kStyleUrl, content::RESOURCE_TYPE_STYLESHEET, "text/css");
214 AddResource(kScriptUrl, content::RESOURCE_TYPE_SCRIPT,
215 "application/javascript");
216 AddResource(kFontUrl, content::RESOURCE_TYPE_FONT_RESOURCE,
217 "application/x-font-truetype");
218 NavigateToURLAndCheckSubresources(kHtmlSubresourcesUrl);
219 }
220
221 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698