Update V8 to version 4.7.53.
[chromium-blink-merge.git] / net / http / http_transaction_test_util.cc
blob926d8c695d63357eb7f85cdfd5afcf58442fdf28
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"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/time/clock.h"
16 #include "base/time/time.h"
17 #include "net/base/load_flags.h"
18 #include "net/base/load_timing_info.h"
19 #include "net/base/net_errors.h"
20 #include "net/cert/x509_certificate.h"
21 #include "net/disk_cache/disk_cache.h"
22 #include "net/http/http_cache.h"
23 #include "net/http/http_request_info.h"
24 #include "net/http/http_response_info.h"
25 #include "net/http/http_transaction.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 namespace net {
30 namespace {
31 typedef base::hash_map<std::string, const MockTransaction*> MockTransactionMap;
32 static MockTransactionMap mock_transactions;
33 } // namespace
35 //-----------------------------------------------------------------------------
36 // mock transaction data
38 const MockTransaction kSimpleGET_Transaction = {
39 "http://www.google.com/",
40 "GET",
41 base::Time(),
42 "",
43 LOAD_NORMAL,
44 "HTTP/1.1 200 OK",
45 "Cache-Control: max-age=10000\n",
46 base::Time(),
47 "<html><body>Google Blah Blah</body></html>",
48 TEST_MODE_NORMAL,
49 nullptr,
50 nullptr,
53 OK};
55 const MockTransaction kSimplePOST_Transaction = {
56 "http://bugdatabase.com/edit",
57 "POST",
58 base::Time(),
59 "",
60 LOAD_NORMAL,
61 "HTTP/1.1 200 OK",
62 "",
63 base::Time(),
64 "<html><body>Google Blah Blah</body></html>",
65 TEST_MODE_NORMAL,
66 nullptr,
67 nullptr,
70 OK};
72 const MockTransaction kTypicalGET_Transaction = {
73 "http://www.example.com/~foo/bar.html",
74 "GET",
75 base::Time(),
76 "",
77 LOAD_NORMAL,
78 "HTTP/1.1 200 OK",
79 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
80 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n",
81 base::Time(),
82 "<html><body>Google Blah Blah</body></html>",
83 TEST_MODE_NORMAL,
84 nullptr,
85 nullptr,
88 OK};
90 const MockTransaction kETagGET_Transaction = {
91 "http://www.google.com/foopy",
92 "GET",
93 base::Time(),
94 "",
95 LOAD_NORMAL,
96 "HTTP/1.1 200 OK",
97 "Cache-Control: max-age=10000\n"
98 "Etag: \"foopy\"\n",
99 base::Time(),
100 "<html><body>Google Blah Blah</body></html>",
101 TEST_MODE_NORMAL,
102 nullptr,
103 nullptr,
106 OK};
108 const MockTransaction kRangeGET_Transaction = {
109 "http://www.google.com/",
110 "GET",
111 base::Time(),
112 "Range: 0-100\r\n",
113 LOAD_NORMAL,
114 "HTTP/1.1 200 OK",
115 "Cache-Control: max-age=10000\n",
116 base::Time(),
117 "<html><body>Google Blah Blah</body></html>",
118 TEST_MODE_NORMAL,
119 nullptr,
120 nullptr,
123 OK};
125 static const MockTransaction* const kBuiltinMockTransactions[] = {
126 &kSimpleGET_Transaction,
127 &kSimplePOST_Transaction,
128 &kTypicalGET_Transaction,
129 &kETagGET_Transaction,
130 &kRangeGET_Transaction
133 const MockTransaction* FindMockTransaction(const GURL& url) {
134 // look for overrides:
135 MockTransactionMap::const_iterator it = mock_transactions.find(url.spec());
136 if (it != mock_transactions.end())
137 return it->second;
139 // look for builtins:
140 for (size_t i = 0; i < arraysize(kBuiltinMockTransactions); ++i) {
141 if (url == GURL(kBuiltinMockTransactions[i]->url))
142 return kBuiltinMockTransactions[i];
144 return NULL;
147 void AddMockTransaction(const MockTransaction* trans) {
148 mock_transactions[GURL(trans->url).spec()] = trans;
151 void RemoveMockTransaction(const MockTransaction* trans) {
152 mock_transactions.erase(GURL(trans->url).spec());
155 MockHttpRequest::MockHttpRequest(const MockTransaction& t) {
156 url = GURL(t.url);
157 method = t.method;
158 extra_headers.AddHeadersFromString(t.request_headers);
159 load_flags = t.load_flags;
162 //-----------------------------------------------------------------------------
164 // static
165 int TestTransactionConsumer::quit_counter_ = 0;
167 TestTransactionConsumer::TestTransactionConsumer(
168 RequestPriority priority,
169 HttpTransactionFactory* factory)
170 : state_(IDLE), error_(OK) {
171 // Disregard the error code.
172 factory->CreateTransaction(priority, &trans_);
173 ++quit_counter_;
176 TestTransactionConsumer::~TestTransactionConsumer() {
179 void TestTransactionConsumer::Start(const HttpRequestInfo* request,
180 const BoundNetLog& net_log) {
181 state_ = STARTING;
182 int result = trans_->Start(
183 request, base::Bind(&TestTransactionConsumer::OnIOComplete,
184 base::Unretained(this)), net_log);
185 if (result != ERR_IO_PENDING)
186 DidStart(result);
189 void TestTransactionConsumer::DidStart(int result) {
190 if (result != OK) {
191 DidFinish(result);
192 } else {
193 Read();
197 void TestTransactionConsumer::DidRead(int result) {
198 if (result <= 0) {
199 DidFinish(result);
200 } else {
201 content_.append(read_buf_->data(), result);
202 Read();
206 void TestTransactionConsumer::DidFinish(int result) {
207 state_ = DONE;
208 error_ = result;
209 if (--quit_counter_ == 0)
210 base::MessageLoop::current()->Quit();
213 void TestTransactionConsumer::Read() {
214 state_ = READING;
215 read_buf_ = new IOBuffer(1024);
216 int result = trans_->Read(read_buf_.get(),
217 1024,
218 base::Bind(&TestTransactionConsumer::OnIOComplete,
219 base::Unretained(this)));
220 if (result != ERR_IO_PENDING)
221 DidRead(result);
224 void TestTransactionConsumer::OnIOComplete(int result) {
225 switch (state_) {
226 case STARTING:
227 DidStart(result);
228 break;
229 case READING:
230 DidRead(result);
231 break;
232 default:
233 NOTREACHED();
237 MockNetworkTransaction::MockNetworkTransaction(RequestPriority priority,
238 MockNetworkLayer* factory)
239 : request_(NULL),
240 data_cursor_(0),
241 priority_(priority),
242 websocket_handshake_stream_create_helper_(NULL),
243 transaction_factory_(factory->AsWeakPtr()),
244 received_bytes_(0),
245 sent_bytes_(0),
246 socket_log_id_(NetLog::Source::kInvalidId),
247 weak_factory_(this) {}
249 MockNetworkTransaction::~MockNetworkTransaction() {}
251 int MockNetworkTransaction::Start(const HttpRequestInfo* request,
252 const CompletionCallback& callback,
253 const BoundNetLog& net_log) {
254 if (request_)
255 return ERR_FAILED;
257 request_ = request;
258 return StartInternal(request, callback, net_log);
261 int MockNetworkTransaction::RestartIgnoringLastError(
262 const CompletionCallback& callback) {
263 return ERR_FAILED;
266 int MockNetworkTransaction::RestartWithCertificate(
267 X509Certificate* client_cert,
268 const CompletionCallback& callback) {
269 return ERR_FAILED;
272 int MockNetworkTransaction::RestartWithAuth(
273 const AuthCredentials& credentials,
274 const CompletionCallback& callback) {
275 if (!IsReadyToRestartForAuth())
276 return ERR_FAILED;
278 HttpRequestInfo auth_request_info = *request_;
279 auth_request_info.extra_headers.AddHeaderFromString("Authorization: Bar");
281 // Let the MockTransactionHandler worry about this: the only way for this
282 // test to succeed is by using an explicit handler for the transaction so
283 // that server behavior can be simulated.
284 return StartInternal(&auth_request_info, callback, BoundNetLog());
287 bool MockNetworkTransaction::IsReadyToRestartForAuth() {
288 if (!request_)
289 return false;
291 if (!request_->extra_headers.HasHeader("X-Require-Mock-Auth"))
292 return false;
294 // Allow the mock server to decide whether authentication is required or not.
295 std::string status_line = response_.headers->GetStatusLine();
296 return status_line.find(" 401 ") != std::string::npos ||
297 status_line.find(" 407 ") != std::string::npos;
300 int MockNetworkTransaction::Read(IOBuffer* buf,
301 int buf_len,
302 const CompletionCallback& callback) {
303 int data_len = static_cast<int>(data_.size());
304 int num = std::min(buf_len, data_len - data_cursor_);
305 if (test_mode_ & TEST_MODE_SLOW_READ)
306 num = std::min(num, 1);
307 if (num) {
308 memcpy(buf->data(), data_.data() + data_cursor_, num);
309 data_cursor_ += num;
311 if (test_mode_ & TEST_MODE_SYNC_NET_READ)
312 return num;
314 CallbackLater(callback, num);
315 return ERR_IO_PENDING;
318 void MockNetworkTransaction::StopCaching() {
319 if (transaction_factory_.get())
320 transaction_factory_->TransactionStopCaching();
323 bool MockNetworkTransaction::GetFullRequestHeaders(
324 HttpRequestHeaders* headers) const {
325 return false;
328 int64 MockNetworkTransaction::GetTotalReceivedBytes() const {
329 return received_bytes_;
332 int64_t MockNetworkTransaction::GetTotalSentBytes() const {
333 return sent_bytes_;
336 void MockNetworkTransaction::DoneReading() {
337 if (transaction_factory_.get())
338 transaction_factory_->TransactionDoneReading();
341 const HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const {
342 return &response_;
345 LoadState MockNetworkTransaction::GetLoadState() const {
346 if (data_cursor_)
347 return LOAD_STATE_READING_RESPONSE;
348 return LOAD_STATE_IDLE;
351 UploadProgress MockNetworkTransaction::GetUploadProgress() const {
352 return UploadProgress();
355 void MockNetworkTransaction::SetQuicServerInfo(
356 QuicServerInfo* quic_server_info) {
359 bool MockNetworkTransaction::GetLoadTimingInfo(
360 LoadTimingInfo* load_timing_info) const {
361 if (socket_log_id_ != NetLog::Source::kInvalidId) {
362 // The minimal set of times for a request that gets a response, assuming it
363 // gets a new socket.
364 load_timing_info->socket_reused = false;
365 load_timing_info->socket_log_id = socket_log_id_;
366 load_timing_info->connect_timing.connect_start = base::TimeTicks::Now();
367 load_timing_info->connect_timing.connect_end = base::TimeTicks::Now();
368 load_timing_info->send_start = base::TimeTicks::Now();
369 load_timing_info->send_end = base::TimeTicks::Now();
370 } else {
371 // If there's no valid socket ID, just use the generic socket reused values.
372 // No tests currently depend on this, just should not match the values set
373 // by a cache hit.
374 load_timing_info->socket_reused = true;
375 load_timing_info->send_start = base::TimeTicks::Now();
376 load_timing_info->send_end = base::TimeTicks::Now();
378 return true;
381 void MockNetworkTransaction::SetPriority(RequestPriority priority) {
382 priority_ = priority;
385 void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
386 WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
387 websocket_handshake_stream_create_helper_ = create_helper;
390 // static
391 const int64_t MockNetworkTransaction::kTotalReceivedBytes = 1000;
393 // static
394 const int64_t MockNetworkTransaction::kTotalSentBytes = 100;
396 int MockNetworkTransaction::StartInternal(const HttpRequestInfo* request,
397 const CompletionCallback& callback,
398 const BoundNetLog& net_log) {
399 const MockTransaction* t = FindMockTransaction(request->url);
400 if (!t)
401 return ERR_FAILED;
403 test_mode_ = t->test_mode;
405 // Return immediately if we're returning an error.
406 if (OK != t->return_code) {
407 if (test_mode_ & TEST_MODE_SYNC_NET_START)
408 return t->return_code;
409 CallbackLater(callback, t->return_code);
410 return ERR_IO_PENDING;
413 sent_bytes_ = kTotalSentBytes;
414 received_bytes_ = kTotalReceivedBytes;
416 std::string resp_status = t->status;
417 std::string resp_headers = t->response_headers;
418 std::string resp_data = t->data;
419 if (t->handler)
420 (t->handler)(request, &resp_status, &resp_headers, &resp_data);
422 std::string header_data = base::StringPrintf(
423 "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
424 std::replace(header_data.begin(), header_data.end(), '\n', '\0');
426 response_.request_time = transaction_factory_->Now();
427 if (!t->request_time.is_null())
428 response_.request_time = t->request_time;
430 response_.was_cached = false;
431 response_.network_accessed = true;
433 response_.response_time = transaction_factory_->Now();
434 if (!t->response_time.is_null())
435 response_.response_time = t->response_time;
437 response_.headers = new HttpResponseHeaders(header_data);
438 response_.vary_data.Init(*request, *response_.headers.get());
439 response_.ssl_info.cert = t->cert;
440 response_.ssl_info.cert_status = t->cert_status;
441 response_.ssl_info.connection_status = t->ssl_connection_status;
442 data_ = resp_data;
444 if (net_log.net_log())
445 socket_log_id_ = net_log.net_log()->NextID();
447 if (request_->load_flags & LOAD_PREFETCH)
448 response_.unused_since_prefetch = true;
450 if (test_mode_ & TEST_MODE_SYNC_NET_START)
451 return OK;
453 CallbackLater(callback, OK);
454 return ERR_IO_PENDING;
457 void MockNetworkTransaction::SetBeforeNetworkStartCallback(
458 const BeforeNetworkStartCallback& callback) {
461 void MockNetworkTransaction::SetBeforeProxyHeadersSentCallback(
462 const BeforeProxyHeadersSentCallback& callback) {
465 int MockNetworkTransaction::ResumeNetworkStart() {
466 // Should not get here.
467 return ERR_FAILED;
470 void MockNetworkTransaction::GetConnectionAttempts(
471 ConnectionAttempts* out) const {
472 NOTIMPLEMENTED();
475 void MockNetworkTransaction::CallbackLater(const CompletionCallback& callback,
476 int result) {
477 base::ThreadTaskRunnerHandle::Get()->PostTask(
478 FROM_HERE, base::Bind(&MockNetworkTransaction::RunCallback,
479 weak_factory_.GetWeakPtr(), callback, result));
482 void MockNetworkTransaction::RunCallback(const CompletionCallback& callback,
483 int result) {
484 callback.Run(result);
487 MockNetworkLayer::MockNetworkLayer()
488 : transaction_count_(0),
489 done_reading_called_(false),
490 stop_caching_called_(false),
491 last_create_transaction_priority_(DEFAULT_PRIORITY),
492 clock_(nullptr) {
495 MockNetworkLayer::~MockNetworkLayer() {}
497 void MockNetworkLayer::TransactionDoneReading() {
498 done_reading_called_ = true;
501 void MockNetworkLayer::TransactionStopCaching() {
502 stop_caching_called_ = true;
505 int MockNetworkLayer::CreateTransaction(RequestPriority priority,
506 scoped_ptr<HttpTransaction>* trans) {
507 transaction_count_++;
508 last_create_transaction_priority_ = priority;
509 scoped_ptr<MockNetworkTransaction> mock_transaction(
510 new MockNetworkTransaction(priority, this));
511 last_transaction_ = mock_transaction->AsWeakPtr();
512 *trans = mock_transaction.Pass();
513 return OK;
516 HttpCache* MockNetworkLayer::GetCache() {
517 return NULL;
520 HttpNetworkSession* MockNetworkLayer::GetSession() {
521 return NULL;
524 void MockNetworkLayer::SetClock(base::Clock* clock) {
525 DCHECK(!clock_);
526 clock_ = clock;
529 base::Time MockNetworkLayer::Now() {
530 if (clock_)
531 return clock_->Now();
532 return base::Time::Now();
535 //-----------------------------------------------------------------------------
536 // helpers
538 int ReadTransaction(HttpTransaction* trans, std::string* result) {
539 int rv;
541 TestCompletionCallback callback;
543 std::string content;
544 do {
545 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
546 rv = trans->Read(buf.get(), 256, callback.callback());
547 if (rv == ERR_IO_PENDING)
548 rv = callback.WaitForResult();
550 if (rv > 0)
551 content.append(buf->data(), rv);
552 else if (rv < 0)
553 return rv;
554 } while (rv > 0);
556 result->swap(content);
557 return OK;
560 } // namespace net