Fix nullptr crash in OnEmbed
[chromium-blink-merge.git] / net / http / http_transaction_test_util.cc
blob1b2960bb250e12fff7d9f10cc8fd4705b0bc6606
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 socket_log_id_(NetLog::Source::kInvalidId),
246 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 void MockNetworkTransaction::DoneReading() {
333 if (transaction_factory_.get())
334 transaction_factory_->TransactionDoneReading();
337 const HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const {
338 return &response_;
341 LoadState MockNetworkTransaction::GetLoadState() const {
342 if (data_cursor_)
343 return LOAD_STATE_READING_RESPONSE;
344 return LOAD_STATE_IDLE;
347 UploadProgress MockNetworkTransaction::GetUploadProgress() const {
348 return UploadProgress();
351 void MockNetworkTransaction::SetQuicServerInfo(
352 QuicServerInfo* quic_server_info) {
355 bool MockNetworkTransaction::GetLoadTimingInfo(
356 LoadTimingInfo* load_timing_info) const {
357 if (socket_log_id_ != NetLog::Source::kInvalidId) {
358 // The minimal set of times for a request that gets a response, assuming it
359 // gets a new socket.
360 load_timing_info->socket_reused = false;
361 load_timing_info->socket_log_id = socket_log_id_;
362 load_timing_info->connect_timing.connect_start = base::TimeTicks::Now();
363 load_timing_info->connect_timing.connect_end = base::TimeTicks::Now();
364 load_timing_info->send_start = base::TimeTicks::Now();
365 load_timing_info->send_end = base::TimeTicks::Now();
366 } else {
367 // If there's no valid socket ID, just use the generic socket reused values.
368 // No tests currently depend on this, just should not match the values set
369 // by a cache hit.
370 load_timing_info->socket_reused = true;
371 load_timing_info->send_start = base::TimeTicks::Now();
372 load_timing_info->send_end = base::TimeTicks::Now();
374 return true;
377 void MockNetworkTransaction::SetPriority(RequestPriority priority) {
378 priority_ = priority;
381 void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
382 WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
383 websocket_handshake_stream_create_helper_ = create_helper;
386 int MockNetworkTransaction::StartInternal(const HttpRequestInfo* request,
387 const CompletionCallback& callback,
388 const BoundNetLog& net_log) {
389 const MockTransaction* t = FindMockTransaction(request->url);
390 if (!t)
391 return ERR_FAILED;
393 test_mode_ = t->test_mode;
395 // Return immediately if we're returning an error.
396 if (OK != t->return_code) {
397 if (test_mode_ & TEST_MODE_SYNC_NET_START)
398 return t->return_code;
399 CallbackLater(callback, t->return_code);
400 return ERR_IO_PENDING;
403 std::string resp_status = t->status;
404 std::string resp_headers = t->response_headers;
405 std::string resp_data = t->data;
406 received_bytes_ = resp_status.size() + resp_headers.size() + resp_data.size();
407 if (t->handler)
408 (t->handler)(request, &resp_status, &resp_headers, &resp_data);
410 std::string header_data = base::StringPrintf(
411 "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
412 std::replace(header_data.begin(), header_data.end(), '\n', '\0');
414 response_.request_time = transaction_factory_->Now();
415 if (!t->request_time.is_null())
416 response_.request_time = t->request_time;
418 response_.was_cached = false;
419 response_.network_accessed = true;
421 response_.response_time = transaction_factory_->Now();
422 if (!t->response_time.is_null())
423 response_.response_time = t->response_time;
425 response_.headers = new HttpResponseHeaders(header_data);
426 response_.vary_data.Init(*request, *response_.headers.get());
427 response_.ssl_info.cert = t->cert;
428 response_.ssl_info.cert_status = t->cert_status;
429 response_.ssl_info.connection_status = t->ssl_connection_status;
430 data_ = resp_data;
432 if (net_log.net_log())
433 socket_log_id_ = net_log.net_log()->NextID();
435 if (request_->load_flags & LOAD_PREFETCH)
436 response_.unused_since_prefetch = true;
438 if (test_mode_ & TEST_MODE_SYNC_NET_START)
439 return OK;
441 CallbackLater(callback, OK);
442 return ERR_IO_PENDING;
445 void MockNetworkTransaction::SetBeforeNetworkStartCallback(
446 const BeforeNetworkStartCallback& callback) {
449 void MockNetworkTransaction::SetBeforeProxyHeadersSentCallback(
450 const BeforeProxyHeadersSentCallback& callback) {
453 int MockNetworkTransaction::ResumeNetworkStart() {
454 // Should not get here.
455 return ERR_FAILED;
458 void MockNetworkTransaction::GetConnectionAttempts(
459 ConnectionAttempts* out) const {
460 NOTIMPLEMENTED();
463 void MockNetworkTransaction::CallbackLater(const CompletionCallback& callback,
464 int result) {
465 base::ThreadTaskRunnerHandle::Get()->PostTask(
466 FROM_HERE, base::Bind(&MockNetworkTransaction::RunCallback,
467 weak_factory_.GetWeakPtr(), callback, result));
470 void MockNetworkTransaction::RunCallback(const CompletionCallback& callback,
471 int result) {
472 callback.Run(result);
475 MockNetworkLayer::MockNetworkLayer()
476 : transaction_count_(0),
477 done_reading_called_(false),
478 stop_caching_called_(false),
479 last_create_transaction_priority_(DEFAULT_PRIORITY),
480 clock_(nullptr) {
483 MockNetworkLayer::~MockNetworkLayer() {}
485 void MockNetworkLayer::TransactionDoneReading() {
486 done_reading_called_ = true;
489 void MockNetworkLayer::TransactionStopCaching() {
490 stop_caching_called_ = true;
493 int MockNetworkLayer::CreateTransaction(RequestPriority priority,
494 scoped_ptr<HttpTransaction>* trans) {
495 transaction_count_++;
496 last_create_transaction_priority_ = priority;
497 scoped_ptr<MockNetworkTransaction> mock_transaction(
498 new MockNetworkTransaction(priority, this));
499 last_transaction_ = mock_transaction->AsWeakPtr();
500 *trans = mock_transaction.Pass();
501 return OK;
504 HttpCache* MockNetworkLayer::GetCache() {
505 return NULL;
508 HttpNetworkSession* MockNetworkLayer::GetSession() {
509 return NULL;
512 void MockNetworkLayer::SetClock(base::Clock* clock) {
513 DCHECK(!clock_);
514 clock_ = clock;
517 base::Time MockNetworkLayer::Now() {
518 if (clock_)
519 return clock_->Now();
520 return base::Time::Now();
523 //-----------------------------------------------------------------------------
524 // helpers
526 int ReadTransaction(HttpTransaction* trans, std::string* result) {
527 int rv;
529 TestCompletionCallback callback;
531 std::string content;
532 do {
533 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
534 rv = trans->Read(buf.get(), 256, callback.callback());
535 if (rv == ERR_IO_PENDING)
536 rv = callback.WaitForResult();
538 if (rv > 0)
539 content.append(buf->data(), rv);
540 else if (rv < 0)
541 return rv;
542 } while (rv > 0);
544 result->swap(content);
545 return OK;
548 } // namespace net