1 // Copyright 2014 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/http/http_transaction_test_util.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/time/clock.h"
13 #include "base/time/time.h"
14 #include "net/base/load_flags.h"
15 #include "net/base/load_timing_info.h"
16 #include "net/base/net_errors.h"
17 #include "net/disk_cache/disk_cache.h"
18 #include "net/http/http_cache.h"
19 #include "net/http/http_request_info.h"
20 #include "net/http/http_response_info.h"
21 #include "net/http/http_transaction.h"
22 #include "testing/gtest/include/gtest/gtest.h"
25 typedef base::hash_map
<std::string
, const MockTransaction
*> MockTransactionMap
;
26 static MockTransactionMap mock_transactions
;
29 //-----------------------------------------------------------------------------
30 // mock transaction data
32 const MockTransaction kSimpleGET_Transaction
= {
33 "http://www.google.com/",
39 "Cache-Control: max-age=10000\n",
41 "<html><body>Google Blah Blah</body></html>",
48 const MockTransaction kSimplePOST_Transaction
= {
49 "http://bugdatabase.com/edit",
57 "<html><body>Google Blah Blah</body></html>",
64 const MockTransaction kTypicalGET_Transaction
= {
65 "http://www.example.com/~foo/bar.html",
71 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
72 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n",
74 "<html><body>Google Blah Blah</body></html>",
81 const MockTransaction kETagGET_Transaction
= {
82 "http://www.google.com/foopy",
88 "Cache-Control: max-age=10000\n"
91 "<html><body>Google Blah Blah</body></html>",
98 const MockTransaction kRangeGET_Transaction
= {
99 "http://www.google.com/",
105 "Cache-Control: max-age=10000\n",
107 "<html><body>Google Blah Blah</body></html>",
114 static const MockTransaction
* const kBuiltinMockTransactions
[] = {
115 &kSimpleGET_Transaction
,
116 &kSimplePOST_Transaction
,
117 &kTypicalGET_Transaction
,
118 &kETagGET_Transaction
,
119 &kRangeGET_Transaction
122 const MockTransaction
* FindMockTransaction(const GURL
& url
) {
123 // look for overrides:
124 MockTransactionMap::const_iterator it
= mock_transactions
.find(url
.spec());
125 if (it
!= mock_transactions
.end())
128 // look for builtins:
129 for (size_t i
= 0; i
< arraysize(kBuiltinMockTransactions
); ++i
) {
130 if (url
== GURL(kBuiltinMockTransactions
[i
]->url
))
131 return kBuiltinMockTransactions
[i
];
136 void AddMockTransaction(const MockTransaction
* trans
) {
137 mock_transactions
[GURL(trans
->url
).spec()] = trans
;
140 void RemoveMockTransaction(const MockTransaction
* trans
) {
141 mock_transactions
.erase(GURL(trans
->url
).spec());
144 MockHttpRequest::MockHttpRequest(const MockTransaction
& t
) {
147 extra_headers
.AddHeadersFromString(t
.request_headers
);
148 load_flags
= t
.load_flags
;
151 //-----------------------------------------------------------------------------
154 int TestTransactionConsumer::quit_counter_
= 0;
156 TestTransactionConsumer::TestTransactionConsumer(
157 net::RequestPriority priority
,
158 net::HttpTransactionFactory
* factory
)
159 : state_(IDLE
), error_(net::OK
) {
160 // Disregard the error code.
161 factory
->CreateTransaction(priority
, &trans_
);
165 TestTransactionConsumer::~TestTransactionConsumer() {
168 void TestTransactionConsumer::Start(const net::HttpRequestInfo
* request
,
169 const net::BoundNetLog
& net_log
) {
171 int result
= trans_
->Start(
172 request
, base::Bind(&TestTransactionConsumer::OnIOComplete
,
173 base::Unretained(this)), net_log
);
174 if (result
!= net::ERR_IO_PENDING
)
178 void TestTransactionConsumer::DidStart(int result
) {
179 if (result
!= net::OK
) {
186 void TestTransactionConsumer::DidRead(int result
) {
190 content_
.append(read_buf_
->data(), result
);
195 void TestTransactionConsumer::DidFinish(int result
) {
198 if (--quit_counter_
== 0)
199 base::MessageLoop::current()->Quit();
202 void TestTransactionConsumer::Read() {
204 read_buf_
= new net::IOBuffer(1024);
205 int result
= trans_
->Read(read_buf_
.get(),
207 base::Bind(&TestTransactionConsumer::OnIOComplete
,
208 base::Unretained(this)));
209 if (result
!= net::ERR_IO_PENDING
)
213 void TestTransactionConsumer::OnIOComplete(int result
) {
226 MockNetworkTransaction::MockNetworkTransaction(
227 net::RequestPriority priority
,
228 MockNetworkLayer
* factory
)
232 websocket_handshake_stream_create_helper_(NULL
),
233 transaction_factory_(factory
->AsWeakPtr()),
235 socket_log_id_(net::NetLog::Source::kInvalidId
),
236 weak_factory_(this) {
239 MockNetworkTransaction::~MockNetworkTransaction() {}
241 int MockNetworkTransaction::Start(const net::HttpRequestInfo
* request
,
242 const net::CompletionCallback
& callback
,
243 const net::BoundNetLog
& net_log
) {
245 return net::ERR_FAILED
;
248 return StartInternal(request
, callback
, net_log
);
251 int MockNetworkTransaction::RestartIgnoringLastError(
252 const net::CompletionCallback
& callback
) {
253 return net::ERR_FAILED
;
256 int MockNetworkTransaction::RestartWithCertificate(
257 net::X509Certificate
* client_cert
,
258 const net::CompletionCallback
& callback
) {
259 return net::ERR_FAILED
;
262 int MockNetworkTransaction::RestartWithAuth(
263 const net::AuthCredentials
& credentials
,
264 const net::CompletionCallback
& callback
) {
265 if (!IsReadyToRestartForAuth())
266 return net::ERR_FAILED
;
268 net::HttpRequestInfo auth_request_info
= *request_
;
269 auth_request_info
.extra_headers
.AddHeaderFromString("Authorization: Bar");
271 // Let the MockTransactionHandler worry about this: the only way for this
272 // test to succeed is by using an explicit handler for the transaction so
273 // that server behavior can be simulated.
274 return StartInternal(&auth_request_info
, callback
, net::BoundNetLog());
277 bool MockNetworkTransaction::IsReadyToRestartForAuth() {
281 if (!request_
->extra_headers
.HasHeader("X-Require-Mock-Auth"))
284 // Allow the mock server to decide whether authentication is required or not.
285 std::string status_line
= response_
.headers
->GetStatusLine();
286 return status_line
.find(" 401 ") != std::string::npos
||
287 status_line
.find(" 407 ") != std::string::npos
;
290 int MockNetworkTransaction::Read(net::IOBuffer
* buf
, int buf_len
,
291 const net::CompletionCallback
& callback
) {
292 int data_len
= static_cast<int>(data_
.size());
293 int num
= std::min(buf_len
, data_len
- data_cursor_
);
294 if (test_mode_
& TEST_MODE_SLOW_READ
)
295 num
= std::min(num
, 1);
297 memcpy(buf
->data(), data_
.data() + data_cursor_
, num
);
300 if (test_mode_
& TEST_MODE_SYNC_NET_READ
)
303 CallbackLater(callback
, num
);
304 return net::ERR_IO_PENDING
;
307 void MockNetworkTransaction::StopCaching() {
308 if (transaction_factory_
.get())
309 transaction_factory_
->TransactionStopCaching();
312 bool MockNetworkTransaction::GetFullRequestHeaders(
313 net::HttpRequestHeaders
* headers
) const {
317 int64
MockNetworkTransaction::GetTotalReceivedBytes() const {
318 return received_bytes_
;
321 void MockNetworkTransaction::DoneReading() {
322 if (transaction_factory_
.get())
323 transaction_factory_
->TransactionDoneReading();
326 const net::HttpResponseInfo
* MockNetworkTransaction::GetResponseInfo() const {
330 net::LoadState
MockNetworkTransaction::GetLoadState() const {
332 return net::LOAD_STATE_READING_RESPONSE
;
333 return net::LOAD_STATE_IDLE
;
336 net::UploadProgress
MockNetworkTransaction::GetUploadProgress() const {
337 return net::UploadProgress();
340 void MockNetworkTransaction::SetQuicServerInfo(
341 net::QuicServerInfo
* quic_server_info
) {}
343 bool MockNetworkTransaction::GetLoadTimingInfo(
344 net::LoadTimingInfo
* load_timing_info
) const {
345 if (socket_log_id_
!= net::NetLog::Source::kInvalidId
) {
346 // The minimal set of times for a request that gets a response, assuming it
347 // gets a new socket.
348 load_timing_info
->socket_reused
= false;
349 load_timing_info
->socket_log_id
= socket_log_id_
;
350 load_timing_info
->connect_timing
.connect_start
= base::TimeTicks::Now();
351 load_timing_info
->connect_timing
.connect_end
= base::TimeTicks::Now();
352 load_timing_info
->send_start
= base::TimeTicks::Now();
353 load_timing_info
->send_end
= base::TimeTicks::Now();
355 // If there's no valid socket ID, just use the generic socket reused values.
356 // No tests currently depend on this, just should not match the values set
358 load_timing_info
->socket_reused
= true;
359 load_timing_info
->send_start
= base::TimeTicks::Now();
360 load_timing_info
->send_end
= base::TimeTicks::Now();
365 void MockNetworkTransaction::SetPriority(net::RequestPriority priority
) {
366 priority_
= priority
;
369 void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
370 net::WebSocketHandshakeStreamBase::CreateHelper
* create_helper
) {
371 websocket_handshake_stream_create_helper_
= create_helper
;
374 int MockNetworkTransaction::StartInternal(
375 const net::HttpRequestInfo
* request
,
376 const net::CompletionCallback
& callback
,
377 const net::BoundNetLog
& net_log
) {
378 const MockTransaction
* t
= FindMockTransaction(request
->url
);
380 return net::ERR_FAILED
;
382 test_mode_
= t
->test_mode
;
384 // Return immediately if we're returning an error.
385 if (net::OK
!= t
->return_code
) {
386 if (test_mode_
& TEST_MODE_SYNC_NET_START
)
387 return t
->return_code
;
388 CallbackLater(callback
, t
->return_code
);
389 return net::ERR_IO_PENDING
;
392 std::string resp_status
= t
->status
;
393 std::string resp_headers
= t
->response_headers
;
394 std::string resp_data
= t
->data
;
395 received_bytes_
= resp_status
.size() + resp_headers
.size() + resp_data
.size();
397 (t
->handler
)(request
, &resp_status
, &resp_headers
, &resp_data
);
399 std::string header_data
= base::StringPrintf(
400 "%s\n%s\n", resp_status
.c_str(), resp_headers
.c_str());
401 std::replace(header_data
.begin(), header_data
.end(), '\n', '\0');
403 response_
.request_time
= transaction_factory_
->Now();
404 if (!t
->request_time
.is_null())
405 response_
.request_time
= t
->request_time
;
407 response_
.was_cached
= false;
408 response_
.network_accessed
= true;
410 response_
.response_time
= transaction_factory_
->Now();
411 if (!t
->response_time
.is_null())
412 response_
.response_time
= t
->response_time
;
414 response_
.headers
= new net::HttpResponseHeaders(header_data
);
415 response_
.vary_data
.Init(*request
, *response_
.headers
.get());
416 response_
.ssl_info
.cert_status
= t
->cert_status
;
419 if (net_log
.net_log())
420 socket_log_id_
= net_log
.net_log()->NextID();
422 if (request_
->load_flags
& net::LOAD_PREFETCH
)
423 response_
.unused_since_prefetch
= true;
425 if (test_mode_
& TEST_MODE_SYNC_NET_START
)
428 CallbackLater(callback
, net::OK
);
429 return net::ERR_IO_PENDING
;
432 void MockNetworkTransaction::SetBeforeNetworkStartCallback(
433 const BeforeNetworkStartCallback
& callback
) {
436 void MockNetworkTransaction::SetBeforeProxyHeadersSentCallback(
437 const BeforeProxyHeadersSentCallback
& callback
) {
440 int MockNetworkTransaction::ResumeNetworkStart() {
441 // Should not get here.
442 return net::ERR_FAILED
;
445 void MockNetworkTransaction::CallbackLater(
446 const net::CompletionCallback
& callback
, int result
) {
447 base::MessageLoop::current()->PostTask(
448 FROM_HERE
, base::Bind(&MockNetworkTransaction::RunCallback
,
449 weak_factory_
.GetWeakPtr(), callback
, result
));
452 void MockNetworkTransaction::RunCallback(
453 const net::CompletionCallback
& callback
, int result
) {
454 callback
.Run(result
);
457 MockNetworkLayer::MockNetworkLayer()
458 : transaction_count_(0),
459 done_reading_called_(false),
460 stop_caching_called_(false),
461 last_create_transaction_priority_(net::DEFAULT_PRIORITY
),
465 MockNetworkLayer::~MockNetworkLayer() {}
467 void MockNetworkLayer::TransactionDoneReading() {
468 done_reading_called_
= true;
471 void MockNetworkLayer::TransactionStopCaching() {
472 stop_caching_called_
= true;
475 int MockNetworkLayer::CreateTransaction(
476 net::RequestPriority priority
,
477 scoped_ptr
<net::HttpTransaction
>* trans
) {
478 transaction_count_
++;
479 last_create_transaction_priority_
= priority
;
480 scoped_ptr
<MockNetworkTransaction
> mock_transaction(
481 new MockNetworkTransaction(priority
, this));
482 last_transaction_
= mock_transaction
->AsWeakPtr();
483 *trans
= mock_transaction
.Pass();
487 net::HttpCache
* MockNetworkLayer::GetCache() {
491 net::HttpNetworkSession
* MockNetworkLayer::GetSession() {
495 void MockNetworkLayer::SetClock(base::Clock
* clock
) {
500 base::Time
MockNetworkLayer::Now() {
502 return clock_
->Now();
503 return base::Time::Now();
506 //-----------------------------------------------------------------------------
509 int ReadTransaction(net::HttpTransaction
* trans
, std::string
* result
) {
512 net::TestCompletionCallback callback
;
516 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
517 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
518 if (rv
== net::ERR_IO_PENDING
)
519 rv
= callback
.WaitForResult();
522 content
.append(buf
->data(), rv
);
527 result
->swap(content
);