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

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: AsyncRevalidationDriver test reorganisation. Comment nits. 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 <type_traits>
9 #include <utility>
10 #include <vector>
11
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/location.h"
15 #include "base/macros.h"
16 #include "base/run_loop.h"
17 #include "content/public/browser/client_certificate_delegate.h"
18 #include "content/public/common/content_client.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "content/test/test_content_browser_client.h"
21 #include "ipc/ipc_message.h"
22 #include "net/base/net_errors.h"
23 #include "net/base/request_priority.h"
24 #include "net/ssl/ssl_cert_request_info.h"
25 #include "net/url_request/url_request_job_factory.h"
26 #include "net/url_request/url_request_job_factory_impl.h"
27 #include "net/url_request/url_request_status.h"
28 #include "net/url_request/url_request_test_job.h"
29 #include "net/url_request/url_request_test_util.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 namespace content {
33 namespace {
34
35 // Dummy implementation of ResourceThrottle, an instance of which is needed to
36 // initialize AsyncRevalidationDriver.
37 class ResourceThrottleStub : public ResourceThrottle {
38 public:
39 ResourceThrottleStub() {}
40
41 // If true, defers the request in WillStartRequest.
42 void set_defer_request_on_will_start_request(
43 bool defer_request_on_will_start_request) {
44 defer_request_on_will_start_request_ = defer_request_on_will_start_request;
45 }
46
47 // ResourceThrottler implementation:
48 void WillStartRequest(bool* defer) override {
49 *defer = defer_request_on_will_start_request_;
50 }
51
52 const char* GetNameForLogging() const override {
53 return "ResourceThrottleStub";
54 }
55
56 private:
57 bool defer_request_on_will_start_request_ = false;
58
59 DISALLOW_COPY_AND_ASSIGN(ResourceThrottleStub);
60 };
61
62 // There are multiple layers of boilerplate needed to use a URLRequestTestJob
63 // subclass. Subclasses of AsyncRevalidationDriverTest can use
64 // BindCreateProtocolHandlerCallback() to bypass most of that boilerplate.
65 using CreateProtocolHandlerCallback =
66 base::Callback<scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>()>;
67
68 template <typename T>
69 CreateProtocolHandlerCallback BindCreateProtocolHandlerCallback() {
70 static_assert(std::is_base_of<net::URLRequestJob, T>::value,
71 "Template argument to BindCreateProtocolHandlerCallback() must "
72 "be a subclass of URLRequestJob.");
73
74 class TemplatedProtocolHandler
75 : public net::URLRequestJobFactory::ProtocolHandler {
76 public:
77 static scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> Create() {
78 return make_scoped_ptr(new TemplatedProtocolHandler());
79 }
80
81 // URLRequestJobFactory::ProtocolHandler implementation:
82 net::URLRequestJob* MaybeCreateJob(
83 net::URLRequest* request,
84 net::NetworkDelegate* network_delegate) const override {
85 return new T(request, network_delegate);
86 }
87 };
88
89 return base::Bind(&TemplatedProtocolHandler::Create);
90 }
davidben 2015/12/07 23:56:04 [ Haha. I suppose that's one way to do it. :-) ]
Adam Rice 2015/12/08 18:05:35 I considered making the test fixture itself templa
91
92 class AsyncRevalidationDriverTest : public testing::Test {
93 protected:
94 // Constructor for test fixtures that subclass this one.
95 AsyncRevalidationDriverTest(
96 const CreateProtocolHandlerCallback& create_protocol_handler_callback)
97 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
98 create_protocol_handler_callback_(create_protocol_handler_callback),
99 raw_ptr_resource_throttle_(nullptr),
100 raw_ptr_request_(nullptr) {
101 test_url_request_context_.set_job_factory(&job_factory_);
102 }
103
104 // Constructor for tests that use this fixture directly.
105 AsyncRevalidationDriverTest()
106 : AsyncRevalidationDriverTest(
107 base::Bind(net::URLRequestTestJob::CreateProtocolHandler)) {}
108
109 GURL test_url() const { return net::URLRequestTestJob::test_url_1(); }
110
111 std::string test_data() const {
112 return net::URLRequestTestJob::test_data_1();
113 }
114
115 bool async_revalidation_complete_called() const {
116 return async_revalidation_complete_called_;
117 }
118
119 void
120 SetUpAsyncRevalidationDriverWithRequest(scoped_ptr<net::URLRequest> request) {
121 raw_ptr_request_ = request.get();
122 raw_ptr_resource_throttle_ = new ResourceThrottleStub();
123 // This use of base::Unretained() is safe because |driver_|, and the closure
124 // passed to it, will be destroyed before this object is.
125 driver_.reset(new AsyncRevalidationDriver(
126 std::move(request), make_scoped_ptr(raw_ptr_resource_throttle_),
127 base::Bind(&AsyncRevalidationDriverTest::OnAsyncRevalidationComplete,
128 base::Unretained(this))));
129 }
130
131 void SetUp() override {
132 job_factory_.SetProtocolHandler("test",
133 create_protocol_handler_callback_.Run());
134
135 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
136 test_url(), net::DEFAULT_PRIORITY, nullptr /* delegate */));
137 SetUpAsyncRevalidationDriverWithRequest(std::move(request));
138 }
139
140 void OnAsyncRevalidationComplete() {
141 EXPECT_FALSE(async_revalidation_complete_called_);
142 async_revalidation_complete_called_ = true;
143 }
144
145 TestBrowserThreadBundle thread_bundle_;
146 net::URLRequestJobFactoryImpl job_factory_;
147 net::TestURLRequestContext test_url_request_context_;
148 CreateProtocolHandlerCallback create_protocol_handler_callback_;
149
150 // The AsyncRevalidationDriver owns the URLRequest and the ResourceThrottle.
151 ResourceThrottleStub* raw_ptr_resource_throttle_;
152 net::URLRequest* raw_ptr_request_;
153 scoped_ptr<AsyncRevalidationDriver> driver_;
154 bool async_revalidation_complete_called_ = false;
155 };
156
157 TEST_F(AsyncRevalidationDriverTest, NormalRequestCompletes) {
158 driver_->StartRequest();
159 base::RunLoop().RunUntilIdle();
160 EXPECT_TRUE(async_revalidation_complete_called());
161 }
162
163 // Verifies that resuming a cancelled request does not start it again.
davidben 2015/12/07 23:56:03 If you make cancel the same as destruction, this s
Adam Rice 2015/12/08 18:05:35 Yes, thank you. The test has gone away.
164 TEST_F(AsyncRevalidationDriverTest, ResumeCancelledRequest) {
165 raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
166
167 driver_->StartRequest();
168 driver_->CancelRequest();
169 ResourceController* driver_as_resource_controller = driver_.get();
170 driver_as_resource_controller->Resume();
171 base::RunLoop().RunUntilIdle();
172 EXPECT_TRUE(async_revalidation_complete_called());
173 EXPECT_FALSE(raw_ptr_request_->status().is_success());
174 }
175
176 // Verifies that a cancelled request calls |completion_callback|.
177 TEST_F(AsyncRevalidationDriverTest, CancelledRequestCallsCompleteCallback) {
178 driver_->StartRequest();
179 driver_->CancelRequest();
180 base::RunLoop().RunUntilIdle();
181 EXPECT_TRUE(async_revalidation_complete_called());
182 }
183
184 // Verifies that request that should be deferred at start is deferred.
185 TEST_F(AsyncRevalidationDriverTest, DeferOnStart) {
186 raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
187
188 driver_->StartRequest();
189 base::RunLoop().RunUntilIdle();
190 EXPECT_FALSE(raw_ptr_request_->is_pending());
191 EXPECT_FALSE(async_revalidation_complete_called());
192 }
193
194 // Verifies that resuming a deferred request works. Assumes that DeferOnStart
195 // passes.
196 TEST_F(AsyncRevalidationDriverTest, ResumeDeferredRequestWorks) {
197 raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);
198
199 driver_->StartRequest();
200 base::RunLoop().RunUntilIdle();
201
202 ResourceController* driver_as_resource_controller = driver_.get();
203 driver_as_resource_controller->Resume();
204 base::RunLoop().RunUntilIdle();
205 EXPECT_TRUE(async_revalidation_complete_called());
206 }
207
208 // Verifies that redirects are not followed.
209 TEST_F(AsyncRevalidationDriverTest, RedirectsAreNotFollowed) {
210 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
211 net::URLRequestTestJob::test_url_redirect_to_url_2(),
212 net::DEFAULT_PRIORITY, nullptr /* delegate */));
213 SetUpAsyncRevalidationDriverWithRequest(std::move(request));
214
215 driver_->StartRequest();
216 while (net::URLRequestTestJob::ProcessOnePendingMessage())
217 base::RunLoop().RunUntilIdle();
218 base::RunLoop().RunUntilIdle();
219 const net::URLRequestStatus& status = raw_ptr_request_->status();
220 EXPECT_FALSE(status.is_success());
221 EXPECT_EQ(net::ERR_ABORTED, status.error());
222 EXPECT_TRUE(async_revalidation_complete_called());
223 }
224
225 // A mock URLRequestJob which simulates an SSL client auth request.
226 class MockClientCertURLRequestJob : public net::URLRequestTestJob {
227 public:
228 MockClientCertURLRequestJob(net::URLRequest* request,
229 net::NetworkDelegate* network_delegate)
230 : net::URLRequestTestJob(request, network_delegate, true),
231 weak_factory_(this) {}
232
233 // net::URLRequestTestJob implementation:
234 void Start() override {
235 scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
236 new net::SSLCertRequestInfo);
237 base::ThreadTaskRunnerHandle::Get()->PostTask(
238 FROM_HERE,
239 base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
240 weak_factory_.GetWeakPtr(), cert_request_info));
241 }
242
243 void ContinueWithCertificate(
244 net::X509Certificate* cert,
245 net::SSLPrivateKey* client_private_key) override {
246 ADD_FAILURE() << "Certificate supplied.";
247 }
248
249 void Kill() override {
250 weak_factory_.InvalidateWeakPtrs();
251 URLRequestJob::Kill();
252 }
253
254 private:
255 ~MockClientCertURLRequestJob() override {}
256
257 base::WeakPtrFactory<MockClientCertURLRequestJob> weak_factory_;
258
259 DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob);
260 };
261
262 class AsyncRevalidationDriverClientCertTest
263 : public AsyncRevalidationDriverTest {
264 protected:
265 AsyncRevalidationDriverClientCertTest()
266 : AsyncRevalidationDriverTest(
267 BindCreateProtocolHandlerCallback<MockClientCertURLRequestJob>()) {}
268 };
269
270 // Test browser client that causes the test to fail if SelectClientCertificate()
271 // is called. Automatically sets itself as the browser client when constructed
272 // and restores the old browser client in the destructor.
273 class ScopedDontSelectCertificateBrowserClient
274 : public TestContentBrowserClient {
275 public:
276 ScopedDontSelectCertificateBrowserClient() {
277 old_client_ = SetBrowserClientForTesting(this);
278 }
279
280 ~ScopedDontSelectCertificateBrowserClient() override {
281 SetBrowserClientForTesting(old_client_);
282 }
283
284 void SelectClientCertificate(WebContents* web_contents,
285 net::SSLCertRequestInfo* cert_request_info,
286 scoped_ptr<ClientCertificateDelegate>
287 delegate) override {
288 ADD_FAILURE() << "SelectClientCertificate was called.";
289 }
290
291 private:
292 ContentBrowserClient* old_client_;
293
294 DISALLOW_COPY_AND_ASSIGN(ScopedDontSelectCertificateBrowserClient);
295 };
296
297 // Verifies that async revalidation requests do not attempt to provide client
298 // certificates.
299 TEST_F(AsyncRevalidationDriverClientCertTest, RequestRejected) {
300 // Ensure that SelectClientCertificate is not called during this test.
301 ScopedDontSelectCertificateBrowserClient test_client;
302 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
303 test_url(), net::LOW, nullptr /* delegate */));
304
305 SetUpAsyncRevalidationDriverWithRequest(std::move(request));
306
307 // Start the request and wait for it to pause.
308 driver_->StartRequest();
309
310 // Because TestBrowserThreadBundle only uses one real thread, this is
311 // sufficient to ensure that tasks posted to the "UI thread" have run.
312 base::RunLoop().RunUntilIdle();
313
314 // Check that the request aborted.
315 const net::URLRequestStatus& status = raw_ptr_request_->status();
316 EXPECT_FALSE(status.is_success());
317 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, status.error());
318 EXPECT_TRUE(async_revalidation_complete_called());
319 }
320
321 // A mock URLRequestJob which simulates an SSL certificate error.
322 class MockSSLErrorURLRequestJob : public net::URLRequestTestJob {
323 public:
324 MockSSLErrorURLRequestJob(net::URLRequest* request,
325 net::NetworkDelegate* network_delegate)
326 : net::URLRequestTestJob(request, network_delegate, true) {}
327
328 // net::URLRequestTestJob implementation:
329 void Start() override {
330 // This SSLInfo isn't really valid, but it is good enough for testing.
331 net::SSLInfo ssl_info;
332 ssl_info.SetCertError(net::ERR_CERT_DATE_INVALID);
333 base::ThreadTaskRunnerHandle::Get()->PostTask(
334 FROM_HERE,
335 base::Bind(&MockSSLErrorURLRequestJob::NotifySSLCertificateError, this,
336 ssl_info, false));
337 }
338
339 void ContinueDespiteLastError() override {
340 ADD_FAILURE() << "ContinueDespiteLastError called.";
341 }
342
343 private:
344 ~MockSSLErrorURLRequestJob() override {}
345
346 DISALLOW_COPY_AND_ASSIGN(MockSSLErrorURLRequestJob);
347 };
348
349 class AsyncRevalidationDriverSSLErrorTest : public AsyncRevalidationDriverTest {
350 protected:
351 AsyncRevalidationDriverSSLErrorTest()
352 : AsyncRevalidationDriverTest(
353 BindCreateProtocolHandlerCallback<MockSSLErrorURLRequestJob>()) {}
354 };
355
356 // Verifies that async revalidation requests do not attempt to recover from SSL
357 // certificate errors.
358 TEST_F(AsyncRevalidationDriverSSLErrorTest, RequestWithSSLErrorRejected) {
359 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
360 test_url(), net::LOW, nullptr /* delegate */));
361
362 SetUpAsyncRevalidationDriverWithRequest(std::move(request));
363
364 // Start the request and wait for it to pause.
365 driver_->StartRequest();
366 base::RunLoop().RunUntilIdle();
367
368 // Check that the request has been aborted.
369 const net::URLRequestStatus& status = raw_ptr_request_->status();
370 EXPECT_FALSE(status.is_success());
371 EXPECT_EQ(net::ERR_ABORTED, status.error());
372 EXPECT_TRUE(async_revalidation_complete_called());
373 }
374
375 // A URLRequestTestJob that sets |request_time| and |was_cached| on their
376 // response_info, and causes the test to fail if Read() is called.
377 class FromCacheURLRequestJob : public net::URLRequestTestJob {
378 public:
379 FromCacheURLRequestJob(net::URLRequest* request,
380 net::NetworkDelegate* network_delegate)
381 : net::URLRequestTestJob(request, network_delegate, true) {}
382
383 void GetResponseInfo(net::HttpResponseInfo* info) override {
384 URLRequestTestJob::GetResponseInfo(info);
385 info->request_time = base::Time::Now();
386 info->was_cached = true;
387 }
388
389 int ReadRawData(net::IOBuffer* buf, int buf_size) override {
390 ADD_FAILURE() << "ReadRawData() was called.";
391 return URLRequestTestJob::ReadRawData(buf, buf_size);
392 }
393
394 private:
395 ~FromCacheURLRequestJob() override {}
396
397 DISALLOW_COPY_AND_ASSIGN(FromCacheURLRequestJob);
398 };
399
400 class AsyncRevalidationDriverFromCacheTest
401 : public AsyncRevalidationDriverTest {
402 protected:
403 AsyncRevalidationDriverFromCacheTest()
404 : AsyncRevalidationDriverTest(
405 BindCreateProtocolHandlerCallback<FromCacheURLRequestJob>()) {}
406 };
407
408 TEST_F(AsyncRevalidationDriverFromCacheTest,
409 CacheNotReadOnSuccessfulRevalidation) {
410 scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
411 test_url(), net::LOW, nullptr /* delegate */));
412
413 SetUpAsyncRevalidationDriverWithRequest(std::move(request));
414
415 driver_->StartRequest();
416 base::RunLoop().RunUntilIdle();
417
418 EXPECT_TRUE(async_revalidation_complete_called());
419 }
420
421 } // namespace
422 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698