Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / net / http / http_transaction_test_util.cc
blob5951a5c7950360a5c71639733436d650ac8ee1fd
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/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"
24 namespace net {
26 namespace {
27 typedef base::hash_map<std::string, const MockTransaction*> MockTransactionMap;
28 static MockTransactionMap mock_transactions;
29 } // namespace
31 //-----------------------------------------------------------------------------
32 // mock transaction data
34 const MockTransaction kSimpleGET_Transaction = {
35 "http://www.google.com/",
36 "GET",
37 base::Time(),
38 "",
39 LOAD_NORMAL,
40 "HTTP/1.1 200 OK",
41 "Cache-Control: max-age=10000\n",
42 base::Time(),
43 "<html><body>Google Blah Blah</body></html>",
44 TEST_MODE_NORMAL,
45 NULL,
47 OK};
49 const MockTransaction kSimplePOST_Transaction = {
50 "http://bugdatabase.com/edit",
51 "POST",
52 base::Time(),
53 "",
54 LOAD_NORMAL,
55 "HTTP/1.1 200 OK",
56 "",
57 base::Time(),
58 "<html><body>Google Blah Blah</body></html>",
59 TEST_MODE_NORMAL,
60 NULL,
62 OK};
64 const MockTransaction kTypicalGET_Transaction = {
65 "http://www.example.com/~foo/bar.html",
66 "GET",
67 base::Time(),
68 "",
69 LOAD_NORMAL,
70 "HTTP/1.1 200 OK",
71 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
72 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n",
73 base::Time(),
74 "<html><body>Google Blah Blah</body></html>",
75 TEST_MODE_NORMAL,
76 NULL,
78 OK};
80 const MockTransaction kETagGET_Transaction = {
81 "http://www.google.com/foopy",
82 "GET",
83 base::Time(),
84 "",
85 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,
94 OK};
96 const MockTransaction kRangeGET_Transaction = {
97 "http://www.google.com/",
98 "GET",
99 base::Time(),
100 "Range: 0-100\r\n",
101 LOAD_NORMAL,
102 "HTTP/1.1 200 OK",
103 "Cache-Control: max-age=10000\n",
104 base::Time(),
105 "<html><body>Google Blah Blah</body></html>",
106 TEST_MODE_NORMAL,
107 NULL,
109 OK};
111 static const MockTransaction* const kBuiltinMockTransactions[] = {
112 &kSimpleGET_Transaction,
113 &kSimplePOST_Transaction,
114 &kTypicalGET_Transaction,
115 &kETagGET_Transaction,
116 &kRangeGET_Transaction
119 const MockTransaction* FindMockTransaction(const GURL& url) {
120 // look for overrides:
121 MockTransactionMap::const_iterator it = mock_transactions.find(url.spec());
122 if (it != mock_transactions.end())
123 return it->second;
125 // look for builtins:
126 for (size_t i = 0; i < arraysize(kBuiltinMockTransactions); ++i) {
127 if (url == GURL(kBuiltinMockTransactions[i]->url))
128 return kBuiltinMockTransactions[i];
130 return NULL;
133 void AddMockTransaction(const MockTransaction* trans) {
134 mock_transactions[GURL(trans->url).spec()] = trans;
137 void RemoveMockTransaction(const MockTransaction* trans) {
138 mock_transactions.erase(GURL(trans->url).spec());
141 MockHttpRequest::MockHttpRequest(const MockTransaction& t) {
142 url = GURL(t.url);
143 method = t.method;
144 extra_headers.AddHeadersFromString(t.request_headers);
145 load_flags = t.load_flags;
148 //-----------------------------------------------------------------------------
150 // static
151 int TestTransactionConsumer::quit_counter_ = 0;
153 TestTransactionConsumer::TestTransactionConsumer(
154 RequestPriority priority,
155 HttpTransactionFactory* factory)
156 : state_(IDLE), error_(OK) {
157 // Disregard the error code.
158 factory->CreateTransaction(priority, &trans_);
159 ++quit_counter_;
162 TestTransactionConsumer::~TestTransactionConsumer() {
165 void TestTransactionConsumer::Start(const HttpRequestInfo* request,
166 const BoundNetLog& net_log) {
167 state_ = STARTING;
168 int result = trans_->Start(
169 request, base::Bind(&TestTransactionConsumer::OnIOComplete,
170 base::Unretained(this)), net_log);
171 if (result != ERR_IO_PENDING)
172 DidStart(result);
175 void TestTransactionConsumer::DidStart(int result) {
176 if (result != OK) {
177 DidFinish(result);
178 } else {
179 Read();
183 void TestTransactionConsumer::DidRead(int result) {
184 if (result <= 0) {
185 DidFinish(result);
186 } else {
187 content_.append(read_buf_->data(), result);
188 Read();
192 void TestTransactionConsumer::DidFinish(int result) {
193 state_ = DONE;
194 error_ = result;
195 if (--quit_counter_ == 0)
196 base::MessageLoop::current()->Quit();
199 void TestTransactionConsumer::Read() {
200 state_ = READING;
201 read_buf_ = new IOBuffer(1024);
202 int result = trans_->Read(read_buf_.get(),
203 1024,
204 base::Bind(&TestTransactionConsumer::OnIOComplete,
205 base::Unretained(this)));
206 if (result != ERR_IO_PENDING)
207 DidRead(result);
210 void TestTransactionConsumer::OnIOComplete(int result) {
211 switch (state_) {
212 case STARTING:
213 DidStart(result);
214 break;
215 case READING:
216 DidRead(result);
217 break;
218 default:
219 NOTREACHED();
223 MockNetworkTransaction::MockNetworkTransaction(RequestPriority priority,
224 MockNetworkLayer* factory)
225 : request_(NULL),
226 data_cursor_(0),
227 priority_(priority),
228 websocket_handshake_stream_create_helper_(NULL),
229 transaction_factory_(factory->AsWeakPtr()),
230 received_bytes_(0),
231 socket_log_id_(NetLog::Source::kInvalidId),
232 weak_factory_(this) {
235 MockNetworkTransaction::~MockNetworkTransaction() {}
237 int MockNetworkTransaction::Start(const HttpRequestInfo* request,
238 const CompletionCallback& callback,
239 const BoundNetLog& net_log) {
240 if (request_)
241 return ERR_FAILED;
243 request_ = request;
244 return StartInternal(request, callback, net_log);
247 int MockNetworkTransaction::RestartIgnoringLastError(
248 const CompletionCallback& callback) {
249 return ERR_FAILED;
252 int MockNetworkTransaction::RestartWithCertificate(
253 X509Certificate* client_cert,
254 const CompletionCallback& callback) {
255 return ERR_FAILED;
258 int MockNetworkTransaction::RestartWithAuth(
259 const AuthCredentials& credentials,
260 const CompletionCallback& callback) {
261 if (!IsReadyToRestartForAuth())
262 return ERR_FAILED;
264 HttpRequestInfo auth_request_info = *request_;
265 auth_request_info.extra_headers.AddHeaderFromString("Authorization: Bar");
267 // Let the MockTransactionHandler worry about this: the only way for this
268 // test to succeed is by using an explicit handler for the transaction so
269 // that server behavior can be simulated.
270 return StartInternal(&auth_request_info, callback, BoundNetLog());
273 bool MockNetworkTransaction::IsReadyToRestartForAuth() {
274 if (!request_)
275 return false;
277 if (!request_->extra_headers.HasHeader("X-Require-Mock-Auth"))
278 return false;
280 // Allow the mock server to decide whether authentication is required or not.
281 std::string status_line = response_.headers->GetStatusLine();
282 return status_line.find(" 401 ") != std::string::npos ||
283 status_line.find(" 407 ") != std::string::npos;
286 int MockNetworkTransaction::Read(IOBuffer* buf,
287 int buf_len,
288 const CompletionCallback& callback) {
289 int data_len = static_cast<int>(data_.size());
290 int num = std::min(buf_len, data_len - data_cursor_);
291 if (test_mode_ & TEST_MODE_SLOW_READ)
292 num = std::min(num, 1);
293 if (num) {
294 memcpy(buf->data(), data_.data() + data_cursor_, num);
295 data_cursor_ += num;
297 if (test_mode_ & TEST_MODE_SYNC_NET_READ)
298 return num;
300 CallbackLater(callback, num);
301 return ERR_IO_PENDING;
304 void MockNetworkTransaction::StopCaching() {
305 if (transaction_factory_.get())
306 transaction_factory_->TransactionStopCaching();
309 bool MockNetworkTransaction::GetFullRequestHeaders(
310 HttpRequestHeaders* headers) const {
311 return false;
314 int64 MockNetworkTransaction::GetTotalReceivedBytes() const {
315 return received_bytes_;
318 void MockNetworkTransaction::DoneReading() {
319 if (transaction_factory_.get())
320 transaction_factory_->TransactionDoneReading();
323 const HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const {
324 return &response_;
327 LoadState MockNetworkTransaction::GetLoadState() const {
328 if (data_cursor_)
329 return LOAD_STATE_READING_RESPONSE;
330 return LOAD_STATE_IDLE;
333 UploadProgress MockNetworkTransaction::GetUploadProgress() const {
334 return UploadProgress();
337 void MockNetworkTransaction::SetQuicServerInfo(
338 QuicServerInfo* quic_server_info) {
341 bool MockNetworkTransaction::GetLoadTimingInfo(
342 LoadTimingInfo* load_timing_info) const {
343 if (socket_log_id_ != NetLog::Source::kInvalidId) {
344 // The minimal set of times for a request that gets a response, assuming it
345 // gets a new socket.
346 load_timing_info->socket_reused = false;
347 load_timing_info->socket_log_id = socket_log_id_;
348 load_timing_info->connect_timing.connect_start = base::TimeTicks::Now();
349 load_timing_info->connect_timing.connect_end = base::TimeTicks::Now();
350 load_timing_info->send_start = base::TimeTicks::Now();
351 load_timing_info->send_end = base::TimeTicks::Now();
352 } else {
353 // If there's no valid socket ID, just use the generic socket reused values.
354 // No tests currently depend on this, just should not match the values set
355 // by a cache hit.
356 load_timing_info->socket_reused = true;
357 load_timing_info->send_start = base::TimeTicks::Now();
358 load_timing_info->send_end = base::TimeTicks::Now();
360 return true;
363 void MockNetworkTransaction::SetPriority(RequestPriority priority) {
364 priority_ = priority;
367 void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
368 WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
369 websocket_handshake_stream_create_helper_ = create_helper;
372 int MockNetworkTransaction::StartInternal(const HttpRequestInfo* request,
373 const CompletionCallback& callback,
374 const BoundNetLog& net_log) {
375 const MockTransaction* t = FindMockTransaction(request->url);
376 if (!t)
377 return ERR_FAILED;
379 test_mode_ = t->test_mode;
381 // Return immediately if we're returning an error.
382 if (OK != t->return_code) {
383 if (test_mode_ & TEST_MODE_SYNC_NET_START)
384 return t->return_code;
385 CallbackLater(callback, t->return_code);
386 return ERR_IO_PENDING;
389 std::string resp_status = t->status;
390 std::string resp_headers = t->response_headers;
391 std::string resp_data = t->data;
392 received_bytes_ = resp_status.size() + resp_headers.size() + resp_data.size();
393 if (t->handler)
394 (t->handler)(request, &resp_status, &resp_headers, &resp_data);
396 std::string header_data = base::StringPrintf(
397 "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
398 std::replace(header_data.begin(), header_data.end(), '\n', '\0');
400 response_.request_time = transaction_factory_->Now();
401 if (!t->request_time.is_null())
402 response_.request_time = t->request_time;
404 response_.was_cached = false;
405 response_.network_accessed = true;
407 response_.response_time = transaction_factory_->Now();
408 if (!t->response_time.is_null())
409 response_.response_time = t->response_time;
411 response_.headers = new HttpResponseHeaders(header_data);
412 response_.vary_data.Init(*request, *response_.headers.get());
413 response_.ssl_info.cert_status = t->cert_status;
414 data_ = resp_data;
416 if (net_log.net_log())
417 socket_log_id_ = net_log.net_log()->NextID();
419 if (request_->load_flags & LOAD_PREFETCH)
420 response_.unused_since_prefetch = true;
422 if (test_mode_ & TEST_MODE_SYNC_NET_START)
423 return OK;
425 CallbackLater(callback, OK);
426 return ERR_IO_PENDING;
429 void MockNetworkTransaction::SetBeforeNetworkStartCallback(
430 const BeforeNetworkStartCallback& callback) {
433 void MockNetworkTransaction::SetBeforeProxyHeadersSentCallback(
434 const BeforeProxyHeadersSentCallback& callback) {
437 int MockNetworkTransaction::ResumeNetworkStart() {
438 // Should not get here.
439 return ERR_FAILED;
442 void MockNetworkTransaction::CallbackLater(const CompletionCallback& callback,
443 int result) {
444 base::MessageLoop::current()->PostTask(
445 FROM_HERE, base::Bind(&MockNetworkTransaction::RunCallback,
446 weak_factory_.GetWeakPtr(), callback, result));
449 void MockNetworkTransaction::RunCallback(const CompletionCallback& callback,
450 int result) {
451 callback.Run(result);
454 MockNetworkLayer::MockNetworkLayer()
455 : transaction_count_(0),
456 done_reading_called_(false),
457 stop_caching_called_(false),
458 last_create_transaction_priority_(DEFAULT_PRIORITY),
459 clock_(nullptr) {
462 MockNetworkLayer::~MockNetworkLayer() {}
464 void MockNetworkLayer::TransactionDoneReading() {
465 done_reading_called_ = true;
468 void MockNetworkLayer::TransactionStopCaching() {
469 stop_caching_called_ = true;
472 int MockNetworkLayer::CreateTransaction(RequestPriority priority,
473 scoped_ptr<HttpTransaction>* trans) {
474 transaction_count_++;
475 last_create_transaction_priority_ = priority;
476 scoped_ptr<MockNetworkTransaction> mock_transaction(
477 new MockNetworkTransaction(priority, this));
478 last_transaction_ = mock_transaction->AsWeakPtr();
479 *trans = mock_transaction.Pass();
480 return OK;
483 HttpCache* MockNetworkLayer::GetCache() {
484 return NULL;
487 HttpNetworkSession* MockNetworkLayer::GetSession() {
488 return NULL;
491 void MockNetworkLayer::SetClock(base::Clock* clock) {
492 DCHECK(!clock_);
493 clock_ = clock;
496 base::Time MockNetworkLayer::Now() {
497 if (clock_)
498 return clock_->Now();
499 return base::Time::Now();
502 //-----------------------------------------------------------------------------
503 // helpers
505 int ReadTransaction(HttpTransaction* trans, std::string* result) {
506 int rv;
508 TestCompletionCallback callback;
510 std::string content;
511 do {
512 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
513 rv = trans->Read(buf.get(), 256, callback.callback());
514 if (rv == ERR_IO_PENDING)
515 rv = callback.WaitForResult();
517 if (rv > 0)
518 content.append(buf->data(), rv);
519 else if (rv < 0)
520 return rv;
521 } while (rv > 0);
523 result->swap(content);
524 return OK;
527 } // namespace net