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

Side by Side Diff: content/browser/loader/async_revalidation_driver_unittest.cc

Issue 1041993004: content::ResourceDispatcherHostImpl changes for stale-while-revalidate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@s-w-r-yhirano-patch
Patch Set: Functional change: An initial redirect leg is now async revalidated. s-w-r is still ignored after t… Created 5 years 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 2015 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 "content/browser/loader/async_revalidation_driver.h"
6
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/location.h"
13 #include "base/macros.h"
14 #include "base/run_loop.h"
15 #include "content/public/test/test_browser_thread_bundle.h"
16 #include "ipc/ipc_message.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/request_priority.h"
19 #include "net/ssl/ssl_cert_request_info.h"
20 #include "net/url_request/url_request_job_factory.h"
21 #include "net/url_request/url_request_job_factory_impl.h"
22 #include "net/url_request/url_request_status.h"
23 #include "net/url_request/url_request_test_job.h"
24 #include "net/url_request/url_request_test_util.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 namespace content {
28 namespace {
29
30 // A mock URLRequestJob which simulates an SSL client auth request.
31 class MockClientCertURLRequestJob : public net::URLRequestTestJob {
32 public:
33 MockClientCertURLRequestJob(net::URLRequest* request,
34 net::NetworkDelegate* network_delegate)
35 : net::URLRequestTestJob(request, network_delegate, true) {}
36
37 static std::vector<std::string> test_authorities() {
davidben 2015/11/23 23:40:41 You needn't bother with this field.
Adam Rice 2015/11/25 19:39:39 Removed, thanks.
38 return std::vector<std::string>(1, "dummy");
39 }
40
41 // net::URLRequestTestJob implementation:
42 void Start() override {
43 scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
44 new net::SSLCertRequestInfo);
45 cert_request_info->cert_authorities = test_authorities();
46 base::ThreadTaskRunnerHandle::Get()->PostTask(
47 FROM_HERE,
48 base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
49 this, cert_request_info));
davidben 2015/11/23 23:40:42 This is really obnoxious (we need to unrefcount th
Adam Rice 2015/11/25 19:39:39 I now have a hierarchy with three layers of WeakPt
50 }
51
52 void ContinueWithCertificate(net::X509Certificate* cert) override {
53 ADD_FAILURE() << "Certificate supplied.";
54 }
55
56 private:
57 ~MockClientCertURLRequestJob() override {}
58
59 DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob);
60 };
61
62 class MockClientCertJobProtocolHandler
63 : public net::URLRequestJobFactory::ProtocolHandler {
64 public:
65 // URLRequestJobFactory::ProtocolHandler implementation:
66 net::URLRequestJob* MaybeCreateJob(
67 net::URLRequest* request,
68 net::NetworkDelegate* network_delegate) const override {
69 return new MockClientCertURLRequestJob(request, network_delegate);
70 }
71 };
72
73 // A mock URLRequestJob which simulates an SSL certificate error.
74 class MockSSLErrorURLRequestJob : public net::URLRequestTestJob {
75 public:
76 MockSSLErrorURLRequestJob(net::URLRequest* request,
77 net::NetworkDelegate* network_delegate)
78 : net::URLRequestTestJob(request, network_delegate, true) {}
79
80 // net::URLRequestTestJob implementation:
81 void Start() override {
82 // This SSLInfo isn't really valid, but it is good enough for testing.
83 net::SSLInfo ssl_info;
84 ssl_info.SetCertError(net::ERR_CERT_DATE_INVALID);
85 base::ThreadTaskRunnerHandle::Get()->PostTask(
86 FROM_HERE,
87 base::Bind(&MockSSLErrorURLRequestJob::NotifySSLCertificateError, this,
88 ssl_info, false));
89 }
90
91 void ContinueDespiteLastError() override {
92 ADD_FAILURE() << "ContinueDespiteLastError called.";
93 }
94
95 private:
96 ~MockSSLErrorURLRequestJob() override {}
97
98 DISALLOW_COPY_AND_ASSIGN(MockSSLErrorURLRequestJob);
99 };
100
101 class MockSSLErrorJobProtocolHandler
102 : public net::URLRequestJobFactory::ProtocolHandler {
103 public:
104 // URLRequestJobFactory::ProtocolHandler implementation:
105 net::URLRequestJob* MaybeCreateJob(
106 net::URLRequest* request,
107 net::NetworkDelegate* network_delegate) const override {
108 return new MockSSLErrorURLRequestJob(request, network_delegate);
109 }
110 };
111
112 // Dummy implementation of ResourceThrottle, an instance of which is needed to
113 // initialize AsyncRevalidationDriver.
114 class ResourceThrottleStub : public ResourceThrottle {
115 public:
116 ResourceThrottleStub() {}
117
118 // If true, defers the request in WillStartRequest.
119 void set_defer_request_on_will_start_request(
120 bool defer_request_on_will_start_request) {
121 defer_request_on_will_start_request_ = defer_request_on_will_start_request;
122 }
123
124 // If true, defers the request in WillStartUsingNetwork.
125 void set_defer_request_on_will_start_using_network(
davidben 2015/11/23 23:40:41 Unused
Adam Rice 2015/11/25 19:39:39 Removed, thanks.
126 bool defer_request_on_will_start_using_network) {
127 defer_request_on_will_start_using_network_ =
128 defer_request_on_will_start_using_network;
129 }
130
131 // If true, defers the request in WillProcessResponse.
132 void set_defer_request_on_will_process_response(
davidben 2015/11/23 23:40:41 Unused
Adam Rice 2015/11/25 19:39:39 Removed.
133 bool defer_request_on_will_process_response) {
134 defer_request_on_will_process_response_ =
135 defer_request_on_will_process_response;
136 }
137
138 bool will_redirect_request_called() const {
davidben 2015/11/23 23:40:41 Unused
Adam Rice 2015/11/25 19:39:39 Removed.
139 return will_redirect_request_called_;
140 }
141
142 // ResourceThrottler implementation:
143 void WillStartRequest(bool* defer) override {
144 *defer = defer_request_on_will_start_request_;
145 }
146
147 void WillStartUsingNetwork(bool* defer) override {
148 *defer = defer_request_on_will_start_using_network_;
149 }
150
151 void WillRedirectRequest(const net::RedirectInfo& redirect_info,
152 bool* defer) override {
153 will_redirect_request_called_ = true;
154 }
155
156 void WillProcessResponse(bool* defer) override {
157 *defer = defer_request_on_will_process_response_;
158 }
159
160 const char* GetNameForLogging() const override {
161 return "ResourceThrottleStub";
162 }
163
164 private:
165 bool defer_request_on_will_start_request_ = false;
166 bool defer_request_on_will_start_using_network_ = false;
167 bool will_redirect_request_called_ = false;
168 bool defer_request_on_will_process_response_ = false;
169
170 DISALLOW_COPY_AND_ASSIGN(ResourceThrottleStub);
171 };
172
173 } // namespace
174
175 class AsyncRevalidationDriverTest : public testing::Test {
176 protected:
177 AsyncRevalidationDriverTest()
178 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
179 raw_ptr_resource_throttle_(nullptr),
180 raw_ptr_request_(nullptr) {
181 test_url_request_context_.set_job_factory(&job_factory_);
182 }
183
184 GURL test_url() const { return net::URLRequestTestJob::test_url_1(); }
185
186 std::string test_data() const {
187 return net::URLRequestTestJob::test_data_1();
188 }
189
190 bool async_revalidation_complete_called() const {
191 return async_revalidation_complete_called_;
192 }
193
194 virtual scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>
195 CreateProtocolHandler() {
196 return net::URLRequestTestJob::CreateProtocolHandler();
197 }
198
199 void SetUpAsyncRevalidationDriverWithRequest(
200 scoped_ptr<net::URLRequest> request) {
201 raw_ptr_request_ = request.get();
202 raw_ptr_resource_throttle_ = new ResourceThrottleStub();
203 // This use of base::Unretained() is safe because |driver_|, and the closure
204 // passed to it, will be destroyed before this object is.
205 driver_.reset(new AsyncRevalidationDriver(
206 std::move(request), make_scoped_ptr(raw_ptr_resource_throttle_),
207 base::Bind(&AsyncRevalidationDriverTest::OnAsyncRevalidationComplete,
208 base::Unretained(this))));
209 }
210
211 void SetUp() override {
212 job_factory_.SetProtocolHandler("test", CreateProtocolHandler());
213
214 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
215 test_url(), net::DEFAULT_PRIORITY, nullptr /* delegate */));
216 SetUpAsyncRevalidationDriverWithRequest(std::move(request));
217 }
218
219 void OnAsyncRevalidationComplete() {
220 EXPECT_FALSE(async_revalidation_complete_called_);
221 async_revalidation_complete_called_ = true;
222 }
223
224 TestBrowserThreadBundle thread_bundle_;
225 net::URLRequestJobFactoryImpl job_factory_;
226 net::TestURLRequestContext test_url_request_context_;
227
228 // The AsyncRevalidationDriver owns the URLRequest and the ResourceThrottle.
229 ResourceThrottleStub* raw_ptr_resource_throttle_;
230 net::URLRequest* raw_ptr_request_;
231 scoped_ptr<AsyncRevalidationDriver> driver_;
232 bool async_revalidation_complete_called_ = false;
233 };
234
235 TEST_F(AsyncRevalidationDriverTest, NormalRequestCompletes) {
236 driver_->StartRequest();
237 base::RunLoop().RunUntilIdle();
238 EXPECT_TRUE(async_revalidation_complete_called());
239 }
240
241 class AsyncRevalidationDriverClientCertTest
242 : public AsyncRevalidationDriverTest {
243 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> CreateProtocolHandler()
244 override {
245 return make_scoped_ptr(new MockClientCertJobProtocolHandler());
246 }
247 };
248
249 // Verifies that async revalidation requests do not attempt to provide client
250 // certificates.
251 TEST_F(AsyncRevalidationDriverClientCertTest, RequestRejected) {
252 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
253 test_url(), net::LOW, nullptr /* delegate */));
254
255 SetUpAsyncRevalidationDriverWithRequest(std::move(request));
256
257 // Start the request and wait for it to pause.
258 driver_->StartRequest();
259 base::RunLoop().RunUntilIdle();
260
261 // Check that SelectClientCertificate wasn't called and the request aborted.
davidben 2015/11/23 23:40:41 Huh? You aren't checking that SelectClientCertific
Adam Rice 2015/11/25 19:39:39 Good point. Fixed.
262 const net::URLRequestStatus& status = raw_ptr_request_->status();
263 EXPECT_FALSE(status.is_success());
264 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, status.error());
265 EXPECT_TRUE(async_revalidation_complete_called());
266 }
267
268 class AsyncRevalidationDriverSSLErrorTest : public AsyncRevalidationDriverTest {
269 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> CreateProtocolHandler()
270 override {
271 return make_scoped_ptr(new MockSSLErrorJobProtocolHandler());
272 }
273 };
274
275 // Verifies that async revalidation requests do not attempt to recover from SSL
276 // certificate errors.
277 TEST_F(AsyncRevalidationDriverSSLErrorTest, RequestWithSSLErrorRejected) {
278 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
279 test_url(), net::LOW, nullptr /* delegate */));
280
281 SetUpAsyncRevalidationDriverWithRequest(std::move(request));
282
283 // Start the request and wait for it to pause.
284 driver_->StartRequest();
285 base::RunLoop().RunUntilIdle();
286
287 // Check that the request has been aborted.
288 const net::URLRequestStatus& status = raw_ptr_request_->status();
289 EXPECT_FALSE(status.is_success());
290 EXPECT_EQ(net::ERR_ABORTED, status.error());
291 EXPECT_TRUE(async_revalidation_complete_called());
292 }
293
294 // Verifies that resuming a cancelled request does not start it again.
295 TEST_F(AsyncRevalidationDriverTest, ResumeCancelledRequest) {
296 raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
297
298 driver_->StartRequest();
299 driver_->CancelRequest();
300 ResourceController* driver_as_resource_controller = driver_.get();
301 driver_as_resource_controller->Resume();
302 base::RunLoop().RunUntilIdle();
303 EXPECT_TRUE(async_revalidation_complete_called());
304 EXPECT_FALSE(raw_ptr_request_->status().is_success());
305 }
306
307 // Verify that a cancelled request calls |completion_callback|.
308 TEST_F(AsyncRevalidationDriverTest, CancelledRequestCallsCompleteCallback) {
309 driver_->StartRequest();
310 driver_->CancelRequest();
311 base::RunLoop().RunUntilIdle();
312 EXPECT_TRUE(async_revalidation_complete_called());
313 }
314
315 // Verifies that request that should be deferred at start is deferred.
316 TEST_F(AsyncRevalidationDriverTest, DeferOnStart) {
davidben 2015/11/23 23:40:41 I don't think you ever test that resuming a revali
Adam Rice 2015/11/25 19:39:39 You're right. I have added one. And it found a bug
317 raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
318
319 driver_->StartRequest();
320 base::RunLoop().RunUntilIdle();
321 EXPECT_FALSE(raw_ptr_request_->is_pending());
322 EXPECT_FALSE(async_revalidation_complete_called());
323 }
324
325 // Verifies that redirects are not followed.
326 TEST_F(AsyncRevalidationDriverTest, RedirectsAreNotFollowed) {
327 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
328 net::URLRequestTestJob::test_url_redirect_to_url_2(),
329 net::DEFAULT_PRIORITY, nullptr /* delegate */));
330 SetUpAsyncRevalidationDriverWithRequest(std::move(request));
331
332 driver_->StartRequest();
333 while (net::URLRequestTestJob::ProcessOnePendingMessage())
334 base::RunLoop().RunUntilIdle();
335 base::RunLoop().RunUntilIdle();
336 const net::URLRequestStatus& status = raw_ptr_request_->status();
337 EXPECT_FALSE(status.is_success());
338 EXPECT_EQ(net::ERR_ABORTED, status.error());
339 EXPECT_TRUE(async_revalidation_complete_called());
340 }
341
342 // A URLRequestTestJob that sets |request_time| and |was_cached| on their
343 // response_info, and causes the test to fail if Read() is called.
344 class FromCacheURLRequestJob : public net::URLRequestTestJob {
345 public:
346 FromCacheURLRequestJob(net::URLRequest* request,
347 net::NetworkDelegate* network_delegate)
348 : net::URLRequestTestJob(request, network_delegate, true) {}
349
350 void GetResponseInfo(net::HttpResponseInfo* info) override {
351 URLRequestTestJob::GetResponseInfo(info);
352 info->request_time = base::Time::Now();
353 info->was_cached = true;
354 }
355
356 bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override {
357 ADD_FAILURE() << "ReadRawData() was called.";
358 return URLRequestTestJob::ReadRawData(buf, buf_size, bytes_read);
359 }
360
361 private:
362 ~FromCacheURLRequestJob() override {}
363
364 DISALLOW_COPY_AND_ASSIGN(FromCacheURLRequestJob);
365 };
366
367 class FromCacheProtocolHandler
368 : public net::URLRequestJobFactory::ProtocolHandler {
davidben 2015/11/23 23:40:41 This isn't in the anonymous namespace. Though you
Adam Rice 2015/11/25 19:39:39 Both conventions are used, and both sides claim th
369 public:
370 // URLRequestJobFactory::ProtocolHandler implementation:
371 net::URLRequestJob* MaybeCreateJob(
372 net::URLRequest* request,
373 net::NetworkDelegate* network_delegate) const override {
374 return new FromCacheURLRequestJob(request, network_delegate);
375 }
376 };
377
378 class AsyncRevalidationDriverFromCacheTest
379 : public AsyncRevalidationDriverTest {
380 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> CreateProtocolHandler()
381 override {
382 return make_scoped_ptr(new FromCacheProtocolHandler());
383 }
384 };
385
386 TEST_F(AsyncRevalidationDriverFromCacheTest,
387 CacheNotReadOnSuccessfulRevalidation) {
388 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
389 test_url(), net::LOW, nullptr /* delegate */));
390
391 SetUpAsyncRevalidationDriverWithRequest(std::move(request));
392
393 driver_->StartRequest();
394 base::RunLoop().RunUntilIdle();
395
396 EXPECT_TRUE(async_revalidation_complete_called());
397 }
398
399 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698