Home | History | Annotate | Download | only in http
      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.
      4 
      5 #include "net/http/http_transaction_test_util.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/bind.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "base/time/time.h"
     13 #include "net/base/load_flags.h"
     14 #include "net/base/load_timing_info.h"
     15 #include "net/base/net_errors.h"
     16 #include "net/disk_cache/disk_cache.h"
     17 #include "net/http/http_cache.h"
     18 #include "net/http/http_request_info.h"
     19 #include "net/http/http_response_info.h"
     20 #include "net/http/http_transaction.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 
     23 namespace {
     24 typedef base::hash_map<std::string, const MockTransaction*> MockTransactionMap;
     25 static MockTransactionMap mock_transactions;
     26 }  // namespace
     27 
     28 //-----------------------------------------------------------------------------
     29 // mock transaction data
     30 
     31 const MockTransaction kSimpleGET_Transaction = {
     32   "http://www.google.com/",
     33   "GET",
     34   base::Time(),
     35   "",
     36   net::LOAD_NORMAL,
     37   "HTTP/1.1 200 OK",
     38   "Cache-Control: max-age=10000\n",
     39   base::Time(),
     40   "<html><body>Google Blah Blah</body></html>",
     41   TEST_MODE_NORMAL,
     42   NULL,
     43   0,
     44   net::OK
     45 };
     46 
     47 const MockTransaction kSimplePOST_Transaction = {
     48   "http://bugdatabase.com/edit",
     49   "POST",
     50   base::Time(),
     51   "",
     52   net::LOAD_NORMAL,
     53   "HTTP/1.1 200 OK",
     54   "",
     55   base::Time(),
     56   "<html><body>Google Blah Blah</body></html>",
     57   TEST_MODE_NORMAL,
     58   NULL,
     59   0,
     60   net::OK
     61 };
     62 
     63 const MockTransaction kTypicalGET_Transaction = {
     64   "http://www.example.com/~foo/bar.html",
     65   "GET",
     66   base::Time(),
     67   "",
     68   net::LOAD_NORMAL,
     69   "HTTP/1.1 200 OK",
     70   "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
     71   "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n",
     72   base::Time(),
     73   "<html><body>Google Blah Blah</body></html>",
     74   TEST_MODE_NORMAL,
     75   NULL,
     76   0,
     77   net::OK
     78 };
     79 
     80 const MockTransaction kETagGET_Transaction = {
     81   "http://www.google.com/foopy",
     82   "GET",
     83   base::Time(),
     84   "",
     85   net::LOAD_NORMAL,
     86   "HTTP/1.1 200 OK",
     87   "Cache-Control: max-age=10000\n"
     88   "Etag: \"foopy\"\n",
     89   base::Time(),
     90   "<html><body>Google Blah Blah</body></html>",
     91   TEST_MODE_NORMAL,
     92   NULL,
     93   0,
     94   net::OK
     95 };
     96 
     97 const MockTransaction kRangeGET_Transaction = {
     98   "http://www.google.com/",
     99   "GET",
    100   base::Time(),
    101   "Range: 0-100\r\n",
    102   net::LOAD_NORMAL,
    103   "HTTP/1.1 200 OK",
    104   "Cache-Control: max-age=10000\n",
    105   base::Time(),
    106   "<html><body>Google Blah Blah</body></html>",
    107   TEST_MODE_NORMAL,
    108   NULL,
    109   0,
    110   net::OK
    111 };
    112 
    113 static const MockTransaction* const kBuiltinMockTransactions[] = {
    114   &kSimpleGET_Transaction,
    115   &kSimplePOST_Transaction,
    116   &kTypicalGET_Transaction,
    117   &kETagGET_Transaction,
    118   &kRangeGET_Transaction
    119 };
    120 
    121 const MockTransaction* FindMockTransaction(const GURL& url) {
    122   // look for overrides:
    123   MockTransactionMap::const_iterator it = mock_transactions.find(url.spec());
    124   if (it != mock_transactions.end())
    125     return it->second;
    126 
    127   // look for builtins:
    128   for (size_t i = 0; i < arraysize(kBuiltinMockTransactions); ++i) {
    129     if (url == GURL(kBuiltinMockTransactions[i]->url))
    130       return kBuiltinMockTransactions[i];
    131   }
    132   return NULL;
    133 }
    134 
    135 void AddMockTransaction(const MockTransaction* trans) {
    136   mock_transactions[GURL(trans->url).spec()] = trans;
    137 }
    138 
    139 void RemoveMockTransaction(const MockTransaction* trans) {
    140   mock_transactions.erase(GURL(trans->url).spec());
    141 }
    142 
    143 MockHttpRequest::MockHttpRequest(const MockTransaction& t) {
    144   url = GURL(t.url);
    145   method = t.method;
    146   extra_headers.AddHeadersFromString(t.request_headers);
    147   load_flags = t.load_flags;
    148 }
    149 
    150 //-----------------------------------------------------------------------------
    151 
    152 // static
    153 int TestTransactionConsumer::quit_counter_ = 0;
    154 
    155 TestTransactionConsumer::TestTransactionConsumer(
    156     net::RequestPriority priority,
    157     net::HttpTransactionFactory* factory)
    158     : state_(IDLE), error_(net::OK) {
    159   // Disregard the error code.
    160   factory->CreateTransaction(priority, &trans_);
    161   ++quit_counter_;
    162 }
    163 
    164 TestTransactionConsumer::~TestTransactionConsumer() {
    165 }
    166 
    167 void TestTransactionConsumer::Start(const net::HttpRequestInfo* request,
    168                                     const net::BoundNetLog& net_log) {
    169   state_ = STARTING;
    170   int result = trans_->Start(
    171       request, base::Bind(&TestTransactionConsumer::OnIOComplete,
    172                           base::Unretained(this)), net_log);
    173   if (result != net::ERR_IO_PENDING)
    174     DidStart(result);
    175 }
    176 
    177 void TestTransactionConsumer::DidStart(int result) {
    178   if (result != net::OK) {
    179     DidFinish(result);
    180   } else {
    181     Read();
    182   }
    183 }
    184 
    185 void TestTransactionConsumer::DidRead(int result) {
    186   if (result <= 0) {
    187     DidFinish(result);
    188   } else {
    189     content_.append(read_buf_->data(), result);
    190     Read();
    191   }
    192 }
    193 
    194 void TestTransactionConsumer::DidFinish(int result) {
    195   state_ = DONE;
    196   error_ = result;
    197   if (--quit_counter_ == 0)
    198     base::MessageLoop::current()->Quit();
    199 }
    200 
    201 void TestTransactionConsumer::Read() {
    202   state_ = READING;
    203   read_buf_ = new net::IOBuffer(1024);
    204   int result = trans_->Read(read_buf_.get(),
    205                             1024,
    206                             base::Bind(&TestTransactionConsumer::OnIOComplete,
    207                                        base::Unretained(this)));
    208   if (result != net::ERR_IO_PENDING)
    209     DidRead(result);
    210 }
    211 
    212 void TestTransactionConsumer::OnIOComplete(int result) {
    213   switch (state_) {
    214     case STARTING:
    215       DidStart(result);
    216       break;
    217     case READING:
    218       DidRead(result);
    219       break;
    220     default:
    221       NOTREACHED();
    222   }
    223 }
    224 
    225 MockNetworkTransaction::MockNetworkTransaction(
    226     net::RequestPriority priority,
    227     MockNetworkLayer* factory)
    228     : request_(NULL),
    229       data_cursor_(0),
    230       priority_(priority),
    231       websocket_handshake_stream_create_helper_(NULL),
    232       transaction_factory_(factory->AsWeakPtr()),
    233       received_bytes_(0),
    234       socket_log_id_(net::NetLog::Source::kInvalidId),
    235       weak_factory_(this) {
    236 }
    237 
    238 MockNetworkTransaction::~MockNetworkTransaction() {}
    239 
    240 int MockNetworkTransaction::Start(const net::HttpRequestInfo* request,
    241                                   const net::CompletionCallback& callback,
    242                                   const net::BoundNetLog& net_log) {
    243   if (request_)
    244     return net::ERR_FAILED;
    245 
    246   request_ = request;
    247   return StartInternal(request, callback, net_log);
    248 }
    249 
    250 int MockNetworkTransaction::RestartIgnoringLastError(
    251     const net::CompletionCallback& callback) {
    252   return net::ERR_FAILED;
    253 }
    254 
    255 int MockNetworkTransaction::RestartWithCertificate(
    256     net::X509Certificate* client_cert,
    257     const net::CompletionCallback& callback) {
    258   return net::ERR_FAILED;
    259 }
    260 
    261 int MockNetworkTransaction::RestartWithAuth(
    262     const net::AuthCredentials& credentials,
    263     const net::CompletionCallback& callback) {
    264   if (!IsReadyToRestartForAuth())
    265     return net::ERR_FAILED;
    266 
    267   net::HttpRequestInfo auth_request_info = *request_;
    268   auth_request_info.extra_headers.AddHeaderFromString("Authorization: Bar");
    269 
    270   // Let the MockTransactionHandler worry about this: the only way for this
    271   // test to succeed is by using an explicit handler for the transaction so
    272   // that server behavior can be simulated.
    273   return StartInternal(&auth_request_info, callback, net::BoundNetLog());
    274 }
    275 
    276 bool MockNetworkTransaction::IsReadyToRestartForAuth() {
    277   if (!request_)
    278     return false;
    279 
    280   // Only mock auth when the test asks for it.
    281   return request_->extra_headers.HasHeader("X-Require-Mock-Auth");
    282 }
    283 
    284 int MockNetworkTransaction::Read(net::IOBuffer* buf, int buf_len,
    285                                  const net::CompletionCallback& callback) {
    286   int data_len = static_cast<int>(data_.size());
    287   int num = std::min(buf_len, data_len - data_cursor_);
    288   if (test_mode_ & TEST_MODE_SLOW_READ)
    289     num = std::min(num, 1);
    290   if (num) {
    291     memcpy(buf->data(), data_.data() + data_cursor_, num);
    292     data_cursor_ += num;
    293   }
    294   if (test_mode_ & TEST_MODE_SYNC_NET_READ)
    295     return num;
    296 
    297   CallbackLater(callback, num);
    298   return net::ERR_IO_PENDING;
    299 }
    300 
    301 void MockNetworkTransaction::StopCaching() {
    302   if (transaction_factory_.get())
    303     transaction_factory_->TransactionStopCaching();
    304 }
    305 
    306 bool MockNetworkTransaction::GetFullRequestHeaders(
    307     net::HttpRequestHeaders* headers) const {
    308   return false;
    309 }
    310 
    311 int64 MockNetworkTransaction::GetTotalReceivedBytes() const {
    312   return received_bytes_;
    313 }
    314 
    315 void MockNetworkTransaction::DoneReading() {
    316   if (transaction_factory_.get())
    317     transaction_factory_->TransactionDoneReading();
    318 }
    319 
    320 const net::HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const {
    321   return &response_;
    322 }
    323 
    324 net::LoadState MockNetworkTransaction::GetLoadState() const {
    325   if (data_cursor_)
    326     return net::LOAD_STATE_READING_RESPONSE;
    327   return net::LOAD_STATE_IDLE;
    328 }
    329 
    330 net::UploadProgress MockNetworkTransaction::GetUploadProgress() const {
    331   return net::UploadProgress();
    332 }
    333 
    334 void MockNetworkTransaction::SetQuicServerInfo(
    335     net::QuicServerInfo* quic_server_info) {}
    336 
    337 bool MockNetworkTransaction::GetLoadTimingInfo(
    338     net::LoadTimingInfo* load_timing_info) const {
    339   if (socket_log_id_ != net::NetLog::Source::kInvalidId) {
    340     // The minimal set of times for a request that gets a response, assuming it
    341     // gets a new socket.
    342     load_timing_info->socket_reused = false;
    343     load_timing_info->socket_log_id = socket_log_id_;
    344     load_timing_info->connect_timing.connect_start = base::TimeTicks::Now();
    345     load_timing_info->connect_timing.connect_end = base::TimeTicks::Now();
    346     load_timing_info->send_start = base::TimeTicks::Now();
    347     load_timing_info->send_end = base::TimeTicks::Now();
    348   } else {
    349     // If there's no valid socket ID, just use the generic socket reused values.
    350     // No tests currently depend on this, just should not match the values set
    351     // by a cache hit.
    352     load_timing_info->socket_reused = true;
    353     load_timing_info->send_start = base::TimeTicks::Now();
    354     load_timing_info->send_end = base::TimeTicks::Now();
    355   }
    356   return true;
    357 }
    358 
    359 void MockNetworkTransaction::SetPriority(net::RequestPriority priority) {
    360   priority_ = priority;
    361 }
    362 
    363 void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
    364     net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
    365   websocket_handshake_stream_create_helper_ = create_helper;
    366 }
    367 
    368 int MockNetworkTransaction::StartInternal(
    369     const net::HttpRequestInfo* request,
    370     const net::CompletionCallback& callback,
    371     const net::BoundNetLog& net_log) {
    372   const MockTransaction* t = FindMockTransaction(request->url);
    373   if (!t)
    374     return net::ERR_FAILED;
    375 
    376   test_mode_ = t->test_mode;
    377 
    378   // Return immediately if we're returning an error.
    379   if (net::OK != t->return_code) {
    380     if (test_mode_ & TEST_MODE_SYNC_NET_START)
    381       return t->return_code;
    382     CallbackLater(callback, t->return_code);
    383     return net::ERR_IO_PENDING;
    384   }
    385 
    386   std::string resp_status = t->status;
    387   std::string resp_headers = t->response_headers;
    388   std::string resp_data = t->data;
    389   received_bytes_ = resp_status.size() + resp_headers.size() + resp_data.size();
    390   if (t->handler)
    391     (t->handler)(request, &resp_status, &resp_headers, &resp_data);
    392 
    393   std::string header_data = base::StringPrintf(
    394       "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
    395   std::replace(header_data.begin(), header_data.end(), '\n', '\0');
    396 
    397   response_.request_time = base::Time::Now();
    398   if (!t->request_time.is_null())
    399     response_.request_time = t->request_time;
    400 
    401   response_.was_cached = false;
    402   response_.network_accessed = true;
    403 
    404   response_.response_time = base::Time::Now();
    405   if (!t->response_time.is_null())
    406     response_.response_time = t->response_time;
    407 
    408   response_.headers = new net::HttpResponseHeaders(header_data);
    409   response_.vary_data.Init(*request, *response_.headers.get());
    410   response_.ssl_info.cert_status = t->cert_status;
    411   data_ = resp_data;
    412 
    413   if (net_log.net_log())
    414     socket_log_id_ = net_log.net_log()->NextID();
    415 
    416   if (test_mode_ & TEST_MODE_SYNC_NET_START)
    417     return net::OK;
    418 
    419   CallbackLater(callback, net::OK);
    420   return net::ERR_IO_PENDING;
    421 }
    422 
    423 void MockNetworkTransaction::SetBeforeNetworkStartCallback(
    424     const BeforeNetworkStartCallback& callback) {
    425 }
    426 
    427 void MockNetworkTransaction::SetBeforeProxyHeadersSentCallback(
    428     const BeforeProxyHeadersSentCallback& callback) {
    429 }
    430 
    431 int MockNetworkTransaction::ResumeNetworkStart() {
    432   // Should not get here.
    433   return net::ERR_FAILED;
    434 }
    435 
    436 void MockNetworkTransaction::CallbackLater(
    437     const net::CompletionCallback& callback, int result) {
    438   base::MessageLoop::current()->PostTask(
    439       FROM_HERE, base::Bind(&MockNetworkTransaction::RunCallback,
    440                             weak_factory_.GetWeakPtr(), callback, result));
    441 }
    442 
    443 void MockNetworkTransaction::RunCallback(
    444     const net::CompletionCallback& callback, int result) {
    445   callback.Run(result);
    446 }
    447 
    448 MockNetworkLayer::MockNetworkLayer()
    449     : transaction_count_(0),
    450       done_reading_called_(false),
    451       stop_caching_called_(false),
    452       last_create_transaction_priority_(net::DEFAULT_PRIORITY) {}
    453 
    454 MockNetworkLayer::~MockNetworkLayer() {}
    455 
    456 void MockNetworkLayer::TransactionDoneReading() {
    457   done_reading_called_ = true;
    458 }
    459 
    460 void MockNetworkLayer::TransactionStopCaching() {
    461   stop_caching_called_ = true;
    462 }
    463 
    464 int MockNetworkLayer::CreateTransaction(
    465     net::RequestPriority priority,
    466     scoped_ptr<net::HttpTransaction>* trans) {
    467   transaction_count_++;
    468   last_create_transaction_priority_ = priority;
    469   scoped_ptr<MockNetworkTransaction> mock_transaction(
    470       new MockNetworkTransaction(priority, this));
    471   last_transaction_ = mock_transaction->AsWeakPtr();
    472   *trans = mock_transaction.Pass();
    473   return net::OK;
    474 }
    475 
    476 net::HttpCache* MockNetworkLayer::GetCache() {
    477   return NULL;
    478 }
    479 
    480 net::HttpNetworkSession* MockNetworkLayer::GetSession() {
    481   return NULL;
    482 }
    483 
    484 //-----------------------------------------------------------------------------
    485 // helpers
    486 
    487 int ReadTransaction(net::HttpTransaction* trans, std::string* result) {
    488   int rv;
    489 
    490   net::TestCompletionCallback callback;
    491 
    492   std::string content;
    493   do {
    494     scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
    495     rv = trans->Read(buf.get(), 256, callback.callback());
    496     if (rv == net::ERR_IO_PENDING)
    497       rv = callback.WaitForResult();
    498 
    499     if (rv > 0)
    500       content.append(buf->data(), rv);
    501     else if (rv < 0)
    502       return rv;
    503   } while (rv > 0);
    504 
    505   result->swap(content);
    506   return net::OK;
    507 }
    508