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"
9 #include "base/compiler_specific.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/run_loop.h"
12 #include "net/base/auth.h"
13 #include "net/base/request_priority.h"
14 #include "net/http/http_transaction_factory.h"
15 #include "net/http/http_transaction_test_util.h"
16 #include "net/socket/socket_test_util.h"
17 #include "net/url_request/url_request_status.h"
18 #include "net/url_request/url_request_test_util.h"
19 #include "net/websockets/websocket_handshake_stream_base.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
28 using ::testing::Return
;
30 // Inherit from URLRequestHttpJob to expose the priority and some
31 // other hidden functions.
32 class TestURLRequestHttpJob
: public URLRequestHttpJob
{
34 explicit TestURLRequestHttpJob(URLRequest
* request
)
35 : URLRequestHttpJob(request
, request
->context()->network_delegate(),
36 request
->context()->http_user_agent_settings()) {}
38 using URLRequestHttpJob::SetPriority
;
39 using URLRequestHttpJob::Start
;
40 using URLRequestHttpJob::Kill
;
41 using URLRequestHttpJob::priority
;
44 virtual ~TestURLRequestHttpJob() {}
47 class URLRequestHttpJobTest
: public ::testing::Test
{
49 URLRequestHttpJobTest()
50 : req_(GURL("http://www.example.com"),
54 context_
.set_http_transaction_factory(&network_layer_
);
57 MockNetworkLayer network_layer_
;
58 TestURLRequestContext context_
;
59 TestDelegate delegate_
;
63 // Make sure that SetPriority actually sets the URLRequestHttpJob's
64 // priority, both before and after start.
65 TEST_F(URLRequestHttpJobTest
, SetPriorityBasic
) {
66 scoped_refptr
<TestURLRequestHttpJob
> job(new TestURLRequestHttpJob(&req_
));
67 EXPECT_EQ(DEFAULT_PRIORITY
, job
->priority());
69 job
->SetPriority(LOWEST
);
70 EXPECT_EQ(LOWEST
, job
->priority());
72 job
->SetPriority(LOW
);
73 EXPECT_EQ(LOW
, job
->priority());
76 EXPECT_EQ(LOW
, job
->priority());
78 job
->SetPriority(MEDIUM
);
79 EXPECT_EQ(MEDIUM
, job
->priority());
82 // Make sure that URLRequestHttpJob passes on its priority to its
83 // transaction on start.
84 TEST_F(URLRequestHttpJobTest
, SetTransactionPriorityOnStart
) {
85 scoped_refptr
<TestURLRequestHttpJob
> job(new TestURLRequestHttpJob(&req_
));
86 job
->SetPriority(LOW
);
88 EXPECT_FALSE(network_layer_
.last_transaction());
92 ASSERT_TRUE(network_layer_
.last_transaction());
93 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
96 // Make sure that URLRequestHttpJob passes on its priority updates to
98 TEST_F(URLRequestHttpJobTest
, SetTransactionPriority
) {
99 scoped_refptr
<TestURLRequestHttpJob
> job(new TestURLRequestHttpJob(&req_
));
100 job
->SetPriority(LOW
);
102 ASSERT_TRUE(network_layer_
.last_transaction());
103 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
105 job
->SetPriority(HIGHEST
);
106 EXPECT_EQ(HIGHEST
, network_layer_
.last_transaction()->priority());
109 // Make sure that URLRequestHttpJob passes on its priority updates to
110 // newly-created transactions after the first one.
111 TEST_F(URLRequestHttpJobTest
, SetSubsequentTransactionPriority
) {
112 scoped_refptr
<TestURLRequestHttpJob
> job(new TestURLRequestHttpJob(&req_
));
115 job
->SetPriority(LOW
);
116 ASSERT_TRUE(network_layer_
.last_transaction());
117 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
120 network_layer_
.ClearLastTransaction();
122 // Creates a second transaction.
124 ASSERT_TRUE(network_layer_
.last_transaction());
125 EXPECT_EQ(LOW
, network_layer_
.last_transaction()->priority());
128 // This base class just serves to set up some things before the TestURLRequest
129 // constructor is called.
130 class URLRequestHttpJobWebSocketTestBase
: public ::testing::Test
{
132 URLRequestHttpJobWebSocketTestBase() : socket_data_(NULL
, 0, NULL
, 0),
134 // A Network Delegate is required for the WebSocketHandshakeStreamBase
135 // object to be passed on to the HttpNetworkTransaction.
136 context_
.set_network_delegate(&network_delegate_
);
138 // Attempting to create real ClientSocketHandles is not going to work out so
139 // well. Set up a fake socket factory.
140 socket_factory_
.AddSocketDataProvider(&socket_data_
);
141 context_
.set_client_socket_factory(&socket_factory_
);
145 StaticSocketDataProvider socket_data_
;
146 TestNetworkDelegate network_delegate_
;
147 MockClientSocketFactory socket_factory_
;
148 TestURLRequestContext context_
;
151 class URLRequestHttpJobWebSocketTest
152 : public URLRequestHttpJobWebSocketTestBase
{
154 URLRequestHttpJobWebSocketTest()
155 : req_(GURL("ws://www.example.com"),
159 // The TestNetworkDelegate expects a call to NotifyBeforeURLRequest before
160 // anything else happens.
161 GURL
url("ws://localhost/");
162 TestCompletionCallback dummy
;
163 network_delegate_
.NotifyBeforeURLRequest(&req_
, dummy
.callback(), &url
);
166 TestDelegate delegate_
;
170 class MockCreateHelper
: public WebSocketHandshakeStreamBase::CreateHelper
{
172 // GoogleMock does not appear to play nicely with move-only types like
173 // scoped_ptr, so this forwarding method acts as a workaround.
174 virtual WebSocketHandshakeStreamBase
* CreateBasicStream(
175 scoped_ptr
<ClientSocketHandle
> connection
,
176 bool using_proxy
) OVERRIDE
{
177 // Discard the arguments since we don't need them anyway.
178 return CreateBasicStreamMock();
181 MOCK_METHOD0(CreateBasicStreamMock
,
182 WebSocketHandshakeStreamBase
*());
184 MOCK_METHOD2(CreateSpdyStream
,
185 WebSocketHandshakeStreamBase
*(const base::WeakPtr
<SpdySession
>&,
189 class FakeWebSocketHandshakeStream
: public WebSocketHandshakeStreamBase
{
191 FakeWebSocketHandshakeStream() : initialize_stream_was_called_(false) {}
193 bool initialize_stream_was_called() const {
194 return initialize_stream_was_called_
;
197 // Fake implementation of HttpStreamBase methods.
198 virtual int InitializeStream(const HttpRequestInfo
* request_info
,
199 RequestPriority priority
,
200 const BoundNetLog
& net_log
,
201 const CompletionCallback
& callback
) OVERRIDE
{
202 initialize_stream_was_called_
= true;
203 return ERR_IO_PENDING
;
206 virtual int SendRequest(const HttpRequestHeaders
& request_headers
,
207 HttpResponseInfo
* response
,
208 const CompletionCallback
& callback
) OVERRIDE
{
209 return ERR_IO_PENDING
;
212 virtual int ReadResponseHeaders(const CompletionCallback
& callback
) OVERRIDE
{
213 return ERR_IO_PENDING
;
216 virtual int ReadResponseBody(IOBuffer
* buf
,
218 const CompletionCallback
& callback
) OVERRIDE
{
219 return ERR_IO_PENDING
;
222 virtual void Close(bool not_reusable
) OVERRIDE
{}
224 virtual bool IsResponseBodyComplete() const OVERRIDE
{ return false; }
226 virtual bool CanFindEndOfResponse() const OVERRIDE
{ return false; }
228 virtual bool IsConnectionReused() const OVERRIDE
{ return false; }
229 virtual void SetConnectionReused() OVERRIDE
{}
231 virtual bool IsConnectionReusable() const OVERRIDE
{ return false; }
233 virtual int64
GetTotalReceivedBytes() const OVERRIDE
{ return 0; }
235 virtual bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const
240 virtual void GetSSLInfo(SSLInfo
* ssl_info
) OVERRIDE
{}
242 virtual void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
)
245 virtual bool IsSpdyHttpStream() const OVERRIDE
{ return false; }
247 virtual void Drain(HttpNetworkSession
* session
) OVERRIDE
{}
249 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{}
251 // Fake implementation of WebSocketHandshakeStreamBase method(s)
252 virtual scoped_ptr
<WebSocketStream
> Upgrade() OVERRIDE
{
253 return scoped_ptr
<WebSocketStream
>();
257 bool initialize_stream_was_called_
;
260 TEST_F(URLRequestHttpJobWebSocketTest
, RejectedWithoutCreateHelper
) {
261 scoped_refptr
<TestURLRequestHttpJob
> job(new TestURLRequestHttpJob(&req_
));
263 base::RunLoop().RunUntilIdle();
264 EXPECT_EQ(URLRequestStatus::FAILED
, req_
.status().status());
265 EXPECT_EQ(ERR_DISALLOWED_URL_SCHEME
, req_
.status().error());
268 TEST_F(URLRequestHttpJobWebSocketTest
, CreateHelperPassedThrough
) {
269 scoped_refptr
<TestURLRequestHttpJob
> job(new TestURLRequestHttpJob(&req_
));
270 scoped_ptr
<MockCreateHelper
> create_helper(
271 new ::testing::StrictMock
<MockCreateHelper
>());
272 FakeWebSocketHandshakeStream
* fake_handshake_stream(
273 new FakeWebSocketHandshakeStream
);
274 // Ownership of fake_handshake_stream is transferred when CreateBasicStream()
276 EXPECT_CALL(*create_helper
, CreateBasicStreamMock())
277 .WillOnce(Return(fake_handshake_stream
));
278 req_
.SetUserData(WebSocketHandshakeStreamBase::CreateHelper::DataKey(),
279 create_helper
.release());
280 req_
.SetLoadFlags(LOAD_DISABLE_CACHE
);
282 base::RunLoop().RunUntilIdle();
283 EXPECT_EQ(URLRequestStatus::IO_PENDING
, req_
.status().status());
284 EXPECT_TRUE(fake_handshake_stream
->initialize_stream_was_called());