Partial revert of r330042 "Draw the offscreen texture to reflector's surface without...
[chromium-blink-merge.git] / net / url_request / url_request_http_job_unittest.cc
blob96e82bf6ae46c830a13f36e5dbee293f765e98a1
1 // Copyright (c) 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 "net/url_request/url_request_http_job.h"
7 #include <cstddef>
9 #include "base/compiler_specific.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/run_loop.h"
13 #include "base/strings/string_split.h"
14 #include "net/base/auth.h"
15 #include "net/base/request_priority.h"
16 #include "net/base/test_data_directory.h"
17 #include "net/cookies/cookie_store_test_helpers.h"
18 #include "net/http/http_transaction_factory.h"
19 #include "net/http/http_transaction_test_util.h"
20 #include "net/socket/socket_test_util.h"
21 #include "net/test/cert_test_util.h"
22 #include "net/url_request/url_request.h"
23 #include "net/url_request/url_request_status.h"
24 #include "net/url_request/url_request_test_util.h"
25 #include "net/websockets/websocket_handshake_stream_base.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "url/gurl.h"
30 namespace net {
32 namespace {
34 using ::testing::Return;
36 // Inherit from URLRequestHttpJob to expose the priority and some
37 // other hidden functions.
38 class TestURLRequestHttpJob : public URLRequestHttpJob {
39 public:
40 explicit TestURLRequestHttpJob(URLRequest* request)
41 : URLRequestHttpJob(request, request->context()->network_delegate(),
42 request->context()->http_user_agent_settings()) {}
44 using URLRequestHttpJob::SetPriority;
45 using URLRequestHttpJob::Start;
46 using URLRequestHttpJob::Kill;
47 using URLRequestHttpJob::priority;
49 protected:
50 ~TestURLRequestHttpJob() override {}
53 class URLRequestHttpJobTest : public ::testing::Test {
54 protected:
55 URLRequestHttpJobTest()
56 : req_(context_.CreateRequest(GURL("http://www.example.com"),
57 DEFAULT_PRIORITY,
58 &delegate_)) {
59 context_.set_http_transaction_factory(&network_layer_);
62 bool TransactionAcceptsSdchEncoding() {
63 base::WeakPtr<MockNetworkTransaction> transaction(
64 network_layer_.last_transaction());
65 EXPECT_TRUE(transaction);
66 if (!transaction) return false;
68 const HttpRequestInfo* request_info = transaction->request();
69 EXPECT_TRUE(request_info);
70 if (!request_info) return false;
72 std::string encoding_headers;
73 bool get_success = request_info->extra_headers.GetHeader(
74 "Accept-Encoding", &encoding_headers);
75 EXPECT_TRUE(get_success);
76 if (!get_success) return false;
78 // This check isn't wrapped with EXPECT* macros because different
79 // results from this function may be expected in different tests.
80 for (const std::string& token :
81 base::SplitString(encoding_headers, ", ", base::KEEP_WHITESPACE,
82 base::SPLIT_WANT_NONEMPTY)) {
83 if (base::EqualsCaseInsensitiveASCII(token, "sdch"))
84 return true;
86 return false;
89 void EnableSdch() {
90 context_.SetSdchManager(scoped_ptr<SdchManager>(new SdchManager).Pass());
93 MockNetworkLayer network_layer_;
94 TestURLRequestContext context_;
95 TestDelegate delegate_;
96 scoped_ptr<URLRequest> req_;
99 class URLRequestHttpJobWithMockSocketsTest : public ::testing::Test {
100 protected:
101 URLRequestHttpJobWithMockSocketsTest()
102 : context_(new TestURLRequestContext(true)) {
103 context_->set_client_socket_factory(&socket_factory_);
104 context_->set_network_delegate(&network_delegate_);
105 context_->set_backoff_manager(&manager_);
106 context_->Init();
109 MockClientSocketFactory socket_factory_;
110 TestNetworkDelegate network_delegate_;
111 URLRequestBackoffManager manager_;
112 scoped_ptr<TestURLRequestContext> context_;
115 TEST_F(URLRequestHttpJobWithMockSocketsTest,
116 TestContentLengthSuccessfulRequest) {
117 MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n"
118 "Content-Length: 12\r\n\r\n"),
119 MockRead("Test Content")};
121 StaticSocketDataProvider socket_data(reads, arraysize(reads), nullptr, 0);
122 socket_factory_.AddSocketDataProvider(&socket_data);
124 TestDelegate delegate;
125 scoped_ptr<URLRequest> request =
126 context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY,
127 &delegate)
128 .Pass();
130 request->Start();
131 ASSERT_TRUE(request->is_pending());
132 base::RunLoop().Run();
134 EXPECT_TRUE(request->status().is_success());
135 EXPECT_EQ(12, request->received_response_content_length());
138 TEST_F(URLRequestHttpJobWithMockSocketsTest, TestContentLengthAbortedRequest) {
139 MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n"
140 "Content-Length: 20\r\n\r\n"),
141 MockRead("Test Content"),
142 MockRead(net::SYNCHRONOUS, net::ERR_FAILED)};
144 StaticSocketDataProvider socket_data(reads, arraysize(reads), nullptr, 0);
145 socket_factory_.AddSocketDataProvider(&socket_data);
147 TestDelegate delegate;
148 scoped_ptr<URLRequest> request =
149 context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY,
150 &delegate)
151 .Pass();
153 request->Start();
154 ASSERT_TRUE(request->is_pending());
155 base::RunLoop().Run();
157 EXPECT_EQ(URLRequestStatus::FAILED, request->status().status());
158 EXPECT_EQ(12, request->received_response_content_length());
161 TEST_F(URLRequestHttpJobWithMockSocketsTest,
162 TestContentLengthCancelledRequest) {
163 MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n"
164 "Content-Length: 20\r\n\r\n"),
165 MockRead("Test Content"),
166 MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
168 StaticSocketDataProvider socket_data(reads, arraysize(reads), nullptr, 0);
169 socket_factory_.AddSocketDataProvider(&socket_data);
171 TestDelegate delegate;
172 scoped_ptr<URLRequest> request =
173 context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY,
174 &delegate)
175 .Pass();
177 request->Start();
178 base::RunLoop().RunUntilIdle();
179 request->Cancel();
180 base::RunLoop().Run();
182 EXPECT_EQ(URLRequestStatus::CANCELED, request->status().status());
183 EXPECT_EQ(12, request->received_response_content_length());
186 TEST_F(URLRequestHttpJobWithMockSocketsTest, BackoffHeader) {
187 MockWrite writes[] = {MockWrite(
188 "GET / HTTP/1.1\r\n"
189 "Host: www.example.com\r\n"
190 "Connection: keep-alive\r\n"
191 "User-Agent:\r\n"
192 "Accept-Encoding: gzip, deflate\r\n"
193 "Accept-Language: en-us,fr\r\n\r\n")};
195 MockRead reads[] = {MockRead(
196 "HTTP/1.1 200 OK\r\n"
197 "Backoff: 3600\r\n"
198 "Content-Length: 9\r\n\r\n"),
199 MockRead("test.html")};
201 net::SSLSocketDataProvider ssl_socket_data_provider(net::ASYNC, net::OK);
202 ssl_socket_data_provider.SetNextProto(kProtoHTTP11);
203 ssl_socket_data_provider.cert =
204 ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der");
205 socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data_provider);
207 StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
208 arraysize(writes));
209 socket_factory_.AddSocketDataProvider(&socket_data);
211 TestDelegate delegate1;
212 scoped_ptr<URLRequest> request1 =
213 context_->CreateRequest(GURL("https://www.example.com"), DEFAULT_PRIORITY,
214 &delegate1).Pass();
216 request1->Start();
217 ASSERT_TRUE(request1->is_pending());
218 base::RunLoop().Run();
220 EXPECT_TRUE(request1->status().is_success());
221 EXPECT_EQ("test.html", delegate1.data_received());
222 EXPECT_EQ(1, delegate1.received_before_network_start_count());
223 EXPECT_EQ(1, manager_.GetNumberOfEntriesForTests());
225 // Issue another request, and backoff logic should apply.
226 TestDelegate delegate2;
227 scoped_ptr<URLRequest> request2 =
228 context_->CreateRequest(GURL("https://www.example.com"), DEFAULT_PRIORITY,
229 &delegate2).Pass();
231 request2->Start();
232 ASSERT_TRUE(request2->is_pending());
233 base::RunLoop().Run();
235 EXPECT_FALSE(request2->status().is_success());
236 EXPECT_EQ(ERR_TEMPORARY_BACKOFF, request2->status().error());
237 EXPECT_EQ(0, delegate2.received_before_network_start_count());
240 TEST_F(URLRequestHttpJobWithMockSocketsTest, BackoffHeaderNotSecure) {
241 MockWrite writes[] = {MockWrite(
242 "GET / HTTP/1.1\r\n"
243 "Host: www.example.com\r\n"
244 "Connection: keep-alive\r\n"
245 "User-Agent:\r\n"
246 "Accept-Encoding: gzip, deflate\r\n"
247 "Accept-Language: en-us,fr\r\n\r\n")};
248 MockRead reads[] = {MockRead(
249 "HTTP/1.1 200 OK\r\n"
250 "Backoff: 3600\r\n"
251 "Content-Length: 9\r\n\r\n"),
252 MockRead("test.html")};
254 StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
255 arraysize(writes));
256 socket_factory_.AddSocketDataProvider(&socket_data);
258 TestDelegate delegate;
259 scoped_ptr<URLRequest> request =
260 context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY,
261 &delegate).Pass();
263 request->Start();
264 ASSERT_TRUE(request->is_pending());
265 base::RunLoop().Run();
267 EXPECT_TRUE(request->status().is_success());
268 EXPECT_EQ("test.html", delegate.data_received());
269 EXPECT_EQ(1, delegate.received_before_network_start_count());
270 // Backoff logic does not apply to plain HTTP request.
271 EXPECT_EQ(0, manager_.GetNumberOfEntriesForTests());
274 TEST_F(URLRequestHttpJobWithMockSocketsTest, BackoffHeaderCachedResponse) {
275 MockWrite writes[] = {MockWrite(
276 "GET / HTTP/1.1\r\n"
277 "Host: www.example.com\r\n"
278 "Connection: keep-alive\r\n"
279 "User-Agent:\r\n"
280 "Accept-Encoding: gzip, deflate\r\n"
281 "Accept-Language: en-us,fr\r\n\r\n")};
282 MockRead reads[] = {MockRead(
283 "HTTP/1.1 200 OK\r\n"
284 "Backoff: 3600\r\n"
285 "Cache-Control: max-age=120\r\n"
286 "Content-Length: 9\r\n\r\n"),
287 MockRead("test.html")};
289 net::SSLSocketDataProvider ssl_socket_data_provider(net::ASYNC, net::OK);
290 ssl_socket_data_provider.SetNextProto(kProtoHTTP11);
291 ssl_socket_data_provider.cert =
292 ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der");
293 socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data_provider);
295 StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
296 arraysize(writes));
297 socket_factory_.AddSocketDataProvider(&socket_data);
299 TestDelegate delegate1;
300 scoped_ptr<URLRequest> request1 =
301 context_->CreateRequest(GURL("https://www.example.com"), DEFAULT_PRIORITY,
302 &delegate1).Pass();
304 request1->Start();
305 ASSERT_TRUE(request1->is_pending());
306 base::RunLoop().Run();
308 EXPECT_TRUE(request1->status().is_success());
309 EXPECT_EQ("test.html", delegate1.data_received());
310 EXPECT_EQ(1, delegate1.received_before_network_start_count());
311 EXPECT_EQ(1, manager_.GetNumberOfEntriesForTests());
313 // Backoff logic does not apply to a second request, since it is fetched
314 // from cache.
315 TestDelegate delegate2;
316 scoped_ptr<URLRequest> request2 =
317 context_->CreateRequest(GURL("https://www.example.com"), DEFAULT_PRIORITY,
318 &delegate2).Pass();
320 request2->Start();
321 ASSERT_TRUE(request2->is_pending());
322 base::RunLoop().Run();
323 EXPECT_TRUE(request2->was_cached());
324 EXPECT_TRUE(request2->status().is_success());
325 EXPECT_EQ(0, delegate2.received_before_network_start_count());
328 TEST_F(URLRequestHttpJobTest, TestCancelWhileReadingCookies) {
329 context_.set_cookie_store(new DelayedCookieMonster());
331 TestDelegate delegate;
332 scoped_ptr<URLRequest> request =
333 context_.CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY,
334 &delegate)
335 .Pass();
337 request->Start();
338 request->Cancel();
339 base::RunLoop().Run();
341 DCHECK_EQ(0, delegate.received_before_network_start_count());
342 EXPECT_EQ(URLRequestStatus::CANCELED, request->status().status());
345 // Make sure that SetPriority actually sets the URLRequestHttpJob's
346 // priority, both before and after start.
347 TEST_F(URLRequestHttpJobTest, SetPriorityBasic) {
348 scoped_refptr<TestURLRequestHttpJob> job(
349 new TestURLRequestHttpJob(req_.get()));
350 EXPECT_EQ(DEFAULT_PRIORITY, job->priority());
352 job->SetPriority(LOWEST);
353 EXPECT_EQ(LOWEST, job->priority());
355 job->SetPriority(LOW);
356 EXPECT_EQ(LOW, job->priority());
358 job->Start();
359 EXPECT_EQ(LOW, job->priority());
361 job->SetPriority(MEDIUM);
362 EXPECT_EQ(MEDIUM, job->priority());
365 // Make sure that URLRequestHttpJob passes on its priority to its
366 // transaction on start.
367 TEST_F(URLRequestHttpJobTest, SetTransactionPriorityOnStart) {
368 scoped_refptr<TestURLRequestHttpJob> job(
369 new TestURLRequestHttpJob(req_.get()));
370 job->SetPriority(LOW);
372 EXPECT_FALSE(network_layer_.last_transaction());
374 job->Start();
376 ASSERT_TRUE(network_layer_.last_transaction());
377 EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
380 // Make sure that URLRequestHttpJob passes on its priority updates to
381 // its transaction.
382 TEST_F(URLRequestHttpJobTest, SetTransactionPriority) {
383 scoped_refptr<TestURLRequestHttpJob> job(
384 new TestURLRequestHttpJob(req_.get()));
385 job->SetPriority(LOW);
386 job->Start();
387 ASSERT_TRUE(network_layer_.last_transaction());
388 EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
390 job->SetPriority(HIGHEST);
391 EXPECT_EQ(HIGHEST, network_layer_.last_transaction()->priority());
394 // Confirm we do advertise SDCH encoding in the case of a GET.
395 TEST_F(URLRequestHttpJobTest, SdchAdvertisementGet) {
396 EnableSdch();
397 req_->set_method("GET"); // Redundant with default.
398 scoped_refptr<TestURLRequestHttpJob> job(
399 new TestURLRequestHttpJob(req_.get()));
400 job->Start();
401 EXPECT_TRUE(TransactionAcceptsSdchEncoding());
404 // Confirm we don't advertise SDCH encoding in the case of a POST.
405 TEST_F(URLRequestHttpJobTest, SdchAdvertisementPost) {
406 EnableSdch();
407 req_->set_method("POST");
408 scoped_refptr<TestURLRequestHttpJob> job(
409 new TestURLRequestHttpJob(req_.get()));
410 job->Start();
411 EXPECT_FALSE(TransactionAcceptsSdchEncoding());
414 // This base class just serves to set up some things before the TestURLRequest
415 // constructor is called.
416 class URLRequestHttpJobWebSocketTestBase : public ::testing::Test {
417 protected:
418 URLRequestHttpJobWebSocketTestBase() : socket_data_(nullptr, 0, nullptr, 0),
419 context_(true) {
420 // A Network Delegate is required for the WebSocketHandshakeStreamBase
421 // object to be passed on to the HttpNetworkTransaction.
422 context_.set_network_delegate(&network_delegate_);
424 // Attempting to create real ClientSocketHandles is not going to work out so
425 // well. Set up a fake socket factory.
426 socket_factory_.AddSocketDataProvider(&socket_data_);
427 context_.set_client_socket_factory(&socket_factory_);
428 context_.Init();
431 StaticSocketDataProvider socket_data_;
432 TestNetworkDelegate network_delegate_;
433 MockClientSocketFactory socket_factory_;
434 TestURLRequestContext context_;
437 class URLRequestHttpJobWebSocketTest
438 : public URLRequestHttpJobWebSocketTestBase {
439 protected:
440 URLRequestHttpJobWebSocketTest()
441 : req_(context_.CreateRequest(GURL("ws://www.example.com"),
442 DEFAULT_PRIORITY,
443 &delegate_)) {
444 // The TestNetworkDelegate expects a call to NotifyBeforeURLRequest before
445 // anything else happens.
446 GURL url("ws://localhost/");
447 TestCompletionCallback dummy;
448 network_delegate_.NotifyBeforeURLRequest(
449 req_.get(), dummy.callback(), &url);
452 TestDelegate delegate_;
453 scoped_ptr<URLRequest> req_;
456 class MockCreateHelper : public WebSocketHandshakeStreamBase::CreateHelper {
457 public:
458 // GoogleMock does not appear to play nicely with move-only types like
459 // scoped_ptr, so this forwarding method acts as a workaround.
460 WebSocketHandshakeStreamBase* CreateBasicStream(
461 scoped_ptr<ClientSocketHandle> connection,
462 bool using_proxy) override {
463 // Discard the arguments since we don't need them anyway.
464 return CreateBasicStreamMock();
467 MOCK_METHOD0(CreateBasicStreamMock,
468 WebSocketHandshakeStreamBase*());
470 MOCK_METHOD2(CreateSpdyStream,
471 WebSocketHandshakeStreamBase*(const base::WeakPtr<SpdySession>&,
472 bool));
475 class FakeWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
476 public:
477 FakeWebSocketHandshakeStream() : initialize_stream_was_called_(false) {}
479 bool initialize_stream_was_called() const {
480 return initialize_stream_was_called_;
483 // Fake implementation of HttpStreamBase methods.
484 int InitializeStream(const HttpRequestInfo* request_info,
485 RequestPriority priority,
486 const BoundNetLog& net_log,
487 const CompletionCallback& callback) override {
488 initialize_stream_was_called_ = true;
489 return ERR_IO_PENDING;
492 int SendRequest(const HttpRequestHeaders& request_headers,
493 HttpResponseInfo* response,
494 const CompletionCallback& callback) override {
495 return ERR_IO_PENDING;
498 int ReadResponseHeaders(const CompletionCallback& callback) override {
499 return ERR_IO_PENDING;
502 int ReadResponseBody(IOBuffer* buf,
503 int buf_len,
504 const CompletionCallback& callback) override {
505 return ERR_IO_PENDING;
508 void Close(bool not_reusable) override {}
510 bool IsResponseBodyComplete() const override { return false; }
512 bool CanFindEndOfResponse() const override { return false; }
514 bool IsConnectionReused() const override { return false; }
515 void SetConnectionReused() override {}
517 bool IsConnectionReusable() const override { return false; }
519 int64 GetTotalReceivedBytes() const override { return 0; }
521 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
522 return false;
525 void GetSSLInfo(SSLInfo* ssl_info) override {}
527 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {}
529 bool IsSpdyHttpStream() const override { return false; }
531 void Drain(HttpNetworkSession* session) override {}
533 void SetPriority(RequestPriority priority) override {}
535 UploadProgress GetUploadProgress() const override {
536 return UploadProgress();
539 HttpStream* RenewStreamForAuth() override { return nullptr; }
541 // Fake implementation of WebSocketHandshakeStreamBase method(s)
542 scoped_ptr<WebSocketStream> Upgrade() override {
543 return scoped_ptr<WebSocketStream>();
546 private:
547 bool initialize_stream_was_called_;
550 TEST_F(URLRequestHttpJobWebSocketTest, RejectedWithoutCreateHelper) {
551 scoped_refptr<TestURLRequestHttpJob> job(
552 new TestURLRequestHttpJob(req_.get()));
553 job->Start();
554 base::RunLoop().RunUntilIdle();
555 EXPECT_EQ(URLRequestStatus::FAILED, req_->status().status());
556 EXPECT_EQ(ERR_DISALLOWED_URL_SCHEME, req_->status().error());
559 TEST_F(URLRequestHttpJobWebSocketTest, CreateHelperPassedThrough) {
560 scoped_refptr<TestURLRequestHttpJob> job(
561 new TestURLRequestHttpJob(req_.get()));
562 scoped_ptr<MockCreateHelper> create_helper(
563 new ::testing::StrictMock<MockCreateHelper>());
564 FakeWebSocketHandshakeStream* fake_handshake_stream(
565 new FakeWebSocketHandshakeStream);
566 // Ownership of fake_handshake_stream is transferred when CreateBasicStream()
567 // is called.
568 EXPECT_CALL(*create_helper, CreateBasicStreamMock())
569 .WillOnce(Return(fake_handshake_stream));
570 req_->SetUserData(WebSocketHandshakeStreamBase::CreateHelper::DataKey(),
571 create_helper.release());
572 req_->SetLoadFlags(LOAD_DISABLE_CACHE);
573 job->Start();
574 base::RunLoop().RunUntilIdle();
575 EXPECT_EQ(URLRequestStatus::IO_PENDING, req_->status().status());
576 EXPECT_TRUE(fake_handshake_stream->initialize_stream_was_called());
579 } // namespace
581 } // namespace net