blob: 375d62d9e5b95cc13cbe9eb92e2ad35e3af172f5 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]77848d12008-11-14 00:00:225#include <math.h> // ceil
6
[email protected]68bf9152008-09-25 19:47:307#include "base/compiler_specific.h"
initial.commit586acc5fe2008-07-26 22:42:528#include "net/base/client_socket_factory.h"
9#include "net/base/test_completion_callback.h"
10#include "net/base/upload_data.h"
11#include "net/http/http_network_session.h"
12#include "net/http/http_network_transaction.h"
13#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5314#include "net/proxy/proxy_config_service_fixed.h"
initial.commit586acc5fe2008-07-26 22:42:5215#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1516#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5217
18//-----------------------------------------------------------------------------
19
initial.commit586acc5fe2008-07-26 22:42:5220
21struct MockConnect {
[email protected]217e6022008-09-29 18:18:3522 // Asynchronous connection success.
23 MockConnect() : async(true), result(net::OK) { }
[email protected]038e9a32008-10-08 22:40:1624
25 bool async;
26 int result;
initial.commit586acc5fe2008-07-26 22:42:5227};
28
29struct MockRead {
[email protected]217e6022008-09-29 18:18:3530 // Read failure (no data).
31 MockRead(bool async, int result) : async(async) , result(result), data(NULL),
32 data_len(0) { }
33
34 // Asynchronous read success (inferred data length).
[email protected]372d34a2008-11-05 21:30:5135 explicit MockRead(const char* data) : async(true), result(0), data(data),
[email protected]b5462e02008-09-29 18:32:1936 data_len(strlen(data)) { }
[email protected]217e6022008-09-29 18:18:3537
38 // Read success (inferred data length).
[email protected]b5462e02008-09-29 18:32:1939 MockRead(bool async, const char* data) : async(async), result(0), data(data),
40 data_len(strlen(data)) { }
[email protected]217e6022008-09-29 18:18:3541
42 // Read success.
43 MockRead(bool async, const char* data, int data_len) : async(async),
[email protected]b5462e02008-09-29 18:32:1944 result(0), data(data), data_len(data_len) { }
[email protected]217e6022008-09-29 18:18:3545
initial.commit586acc5fe2008-07-26 22:42:5246 bool async;
[email protected]217e6022008-09-29 18:18:3547 int result;
initial.commit586acc5fe2008-07-26 22:42:5248 const char* data;
[email protected]217e6022008-09-29 18:18:3549 int data_len;
initial.commit586acc5fe2008-07-26 22:42:5250};
51
[email protected]038e9a32008-10-08 22:40:1652// MockWrite uses the same member fields as MockRead, but with different
53// meanings. The expected input to MockTCPClientSocket::Write() is given
54// by {data, data_len}, and the return value of Write() is controlled by
55// {async, result}.
56typedef MockRead MockWrite;
57
initial.commit586acc5fe2008-07-26 22:42:5258struct MockSocket {
[email protected]038e9a32008-10-08 22:40:1659 MockSocket() : reads(NULL), writes(NULL) { }
[email protected]217e6022008-09-29 18:18:3560
initial.commit586acc5fe2008-07-26 22:42:5261 MockConnect connect;
[email protected]217e6022008-09-29 18:18:3562 MockRead* reads;
[email protected]038e9a32008-10-08 22:40:1663 MockWrite* writes;
initial.commit586acc5fe2008-07-26 22:42:5264};
65
66// Holds an array of MockSocket elements. As MockTCPClientSocket objects get
67// instantiated, they take their data from the i'th element of this array.
68//
69// Tests should assign the first N entries of mock_sockets to point to valid
70// MockSocket objects. The first unused entry should be NULL'd.
71//
72MockSocket* mock_sockets[10];
73
74// Index of the next mock_sockets element to use.
75int mock_sockets_index;
76
77class MockTCPClientSocket : public net::ClientSocket {
78 public:
[email protected]372d34a2008-11-05 21:30:5179 explicit MockTCPClientSocket(const net::AddressList& addresses)
initial.commit586acc5fe2008-07-26 22:42:5280 : data_(mock_sockets[mock_sockets_index++]),
[email protected]68bf9152008-09-25 19:47:3081 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
initial.commit586acc5fe2008-07-26 22:42:5282 callback_(NULL),
83 read_index_(0),
84 read_offset_(0),
[email protected]038e9a32008-10-08 22:40:1685 write_index_(0),
initial.commit586acc5fe2008-07-26 22:42:5286 connected_(false) {
87 DCHECK(data_) << "overran mock_sockets array";
88 }
89 // ClientSocket methods:
90 virtual int Connect(net::CompletionCallback* callback) {
91 DCHECK(!callback_);
92 if (connected_)
93 return net::OK;
94 connected_ = true;
95 if (data_->connect.async) {
96 RunCallbackAsync(callback, data_->connect.result);
97 return net::ERR_IO_PENDING;
98 }
99 return data_->connect.result;
100 }
101 virtual int ReconnectIgnoringLastError(net::CompletionCallback* callback) {
102 NOTREACHED();
103 return net::ERR_FAILED;
104 }
105 virtual void Disconnect() {
106 connected_ = false;
107 callback_ = NULL;
108 }
109 virtual bool IsConnected() const {
110 return connected_;
111 }
112 // Socket methods:
113 virtual int Read(char* buf, int buf_len, net::CompletionCallback* callback) {
114 DCHECK(!callback_);
115 MockRead& r = data_->reads[read_index_];
[email protected]038e9a32008-10-08 22:40:16116 int result = r.result;
initial.commit586acc5fe2008-07-26 22:42:52117 if (r.data) {
initial.commit586acc5fe2008-07-26 22:42:52118 if (r.data_len - read_offset_ > 0) {
119 result = std::min(buf_len, r.data_len - read_offset_);
120 memcpy(buf, r.data + read_offset_, result);
121 read_offset_ += result;
122 if (read_offset_ == r.data_len) {
123 read_index_++;
124 read_offset_ = 0;
125 }
126 } else {
127 result = 0; // EOF
128 }
initial.commit586acc5fe2008-07-26 22:42:52129 }
130 if (r.async) {
131 RunCallbackAsync(callback, result);
132 return net::ERR_IO_PENDING;
133 }
134 return result;
135 }
136 virtual int Write(const char* buf, int buf_len,
137 net::CompletionCallback* callback) {
[email protected]372d34a2008-11-05 21:30:51138 DCHECK(buf);
139 DCHECK(buf_len > 0);
initial.commit586acc5fe2008-07-26 22:42:52140 DCHECK(!callback_);
[email protected]038e9a32008-10-08 22:40:16141 // Not using mock writes; succeed synchronously.
142 if (!data_->writes)
143 return buf_len;
[email protected]aaead502008-10-15 00:20:11144
[email protected]038e9a32008-10-08 22:40:16145 // Check that what we are writing matches the expectation.
146 // Then give the mocked return value.
[email protected]372d34a2008-11-05 21:30:51147 MockWrite& w = data_->writes[write_index_++];
[email protected]038e9a32008-10-08 22:40:16148 int result = w.result;
149 if (w.data) {
150 std::string expected_data(w.data, w.data_len);
151 std::string actual_data(buf, buf_len);
152 EXPECT_EQ(expected_data, actual_data);
153 if (expected_data != actual_data)
154 return net::ERR_UNEXPECTED;
155 if (result == net::OK)
156 result = w.data_len;
157 }
158 if (w.async) {
159 RunCallbackAsync(callback, result);
160 return net::ERR_IO_PENDING;
161 }
162 return result;
initial.commit586acc5fe2008-07-26 22:42:52163 }
164 private:
165 void RunCallbackAsync(net::CompletionCallback* callback, int result) {
166 callback_ = callback;
167 MessageLoop::current()->PostTask(FROM_HERE,
168 method_factory_.NewRunnableMethod(
169 &MockTCPClientSocket::RunCallback, result));
170 }
171 void RunCallback(int result) {
172 net::CompletionCallback* c = callback_;
173 callback_ = NULL;
174 if (c)
175 c->Run(result);
176 }
177 MockSocket* data_;
178 ScopedRunnableMethodFactory<MockTCPClientSocket> method_factory_;
179 net::CompletionCallback* callback_;
180 int read_index_;
181 int read_offset_;
[email protected]038e9a32008-10-08 22:40:16182 int write_index_;
initial.commit586acc5fe2008-07-26 22:42:52183 bool connected_;
184};
185
186class MockClientSocketFactory : public net::ClientSocketFactory {
187 public:
188 virtual net::ClientSocket* CreateTCPClientSocket(
189 const net::AddressList& addresses) {
190 return new MockTCPClientSocket(addresses);
191 }
[email protected]aaead502008-10-15 00:20:11192 virtual net::SSLClientSocket* CreateSSLClientSocket(
initial.commit586acc5fe2008-07-26 22:42:52193 net::ClientSocket* transport_socket,
[email protected]c5949a32008-10-08 17:28:23194 const std::string& hostname,
[email protected]aaead502008-10-15 00:20:11195 const net::SSLConfig& ssl_config) {
initial.commit586acc5fe2008-07-26 22:42:52196 return NULL;
197 }
198};
199
200MockClientSocketFactory mock_socket_factory;
201
[email protected]db8f44c2008-12-13 04:52:01202// Create a proxy service which fails on all requests (falls back to direct).
203net::ProxyService* CreateNullProxyService() {
[email protected]51fff29d2008-12-19 22:17:53204 return net::ProxyService::CreateNull();
initial.commit586acc5fe2008-07-26 22:42:52205}
206
[email protected]51fff29d2008-12-19 22:17:53207net::ProxyService* CreateFixedProxyService(const std::string& proxy) {
208 net::ProxyInfo proxy_info;
209 proxy_info.UseNamedProxy(proxy);
210 return new net::ProxyService(
211 new net::ProxyConfigServiceFixed(proxy_info), NULL);
212}
213
214
[email protected]db8f44c2008-12-13 04:52:01215net::HttpNetworkSession* CreateSession(net::ProxyService* proxy_service) {
216 return new net::HttpNetworkSession(proxy_service);
[email protected]e8d536192008-10-17 22:21:14217}
218
[email protected]89836e22008-09-25 20:33:42219class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52220 public:
221 virtual void SetUp() {
[email protected]89836e22008-09-25 20:33:42222 PlatformTest::SetUp();
initial.commit586acc5fe2008-07-26 22:42:52223 mock_sockets[0] = NULL;
224 mock_sockets_index = 0;
225 }
[email protected]3d2a59b2008-09-26 19:44:25226
[email protected]0e75a732008-10-16 20:36:09227 virtual void TearDown() {
228 // Empty the current queue.
229 MessageLoop::current()->RunAllPending();
230 PlatformTest::TearDown();
231 }
232
[email protected]3d2a59b2008-09-26 19:44:25233 protected:
234 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52235};
236
[email protected]231d5a32008-09-13 00:45:27237struct SimpleGetHelperResult {
[email protected]aecfbf22008-10-16 02:02:47238 int rv;
[email protected]231d5a32008-09-13 00:45:27239 std::string status_line;
240 std::string response_data;
241};
initial.commit586acc5fe2008-07-26 22:42:52242
[email protected]231d5a32008-09-13 00:45:27243SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
244 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52245
[email protected]db8f44c2008-12-13 04:52:01246 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]af4876d2008-10-21 23:10:57247 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01248 CreateSession(proxy_service.get()), &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52249
250 net::HttpRequestInfo request;
251 request.method = "GET";
252 request.url = GURL("http://www.google.com/");
253 request.load_flags = 0;
254
initial.commit586acc5fe2008-07-26 22:42:52255 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52256 data.reads = data_reads;
257 mock_sockets[0] = &data;
258 mock_sockets[1] = NULL;
259
260 TestCompletionCallback callback;
261
262 int rv = trans->Start(&request, &callback);
263 EXPECT_EQ(net::ERR_IO_PENDING, rv);
264
[email protected]aecfbf22008-10-16 02:02:47265 out.rv = callback.WaitForResult();
[email protected]af4876d2008-10-21 23:10:57266 if (out.rv != net::OK)
[email protected]aecfbf22008-10-16 02:02:47267 return out;
initial.commit586acc5fe2008-07-26 22:42:52268
269 const net::HttpResponseInfo* response = trans->GetResponseInfo();
270 EXPECT_TRUE(response != NULL);
271
272 EXPECT_TRUE(response->headers != NULL);
[email protected]231d5a32008-09-13 00:45:27273 out.status_line = response->headers->GetStatusLine();
initial.commit586acc5fe2008-07-26 22:42:52274
[email protected]af4876d2008-10-21 23:10:57275 rv = ReadTransaction(trans.get(), &out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52276 EXPECT_EQ(net::OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52277
[email protected]231d5a32008-09-13 00:45:27278 return out;
279}
280
[email protected]15a5ccf82008-10-23 19:57:43281// Fill |str| with a long header list that consumes >= |size| bytes.
282void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19283 const char* row =
284 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
285 const int sizeof_row = strlen(row);
286 const int num_rows = static_cast<int>(
287 ceil(static_cast<float>(size) / sizeof_row));
288 const int sizeof_data = num_rows * sizeof_row;
289 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43290 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51291
[email protected]4ddaf2502008-10-23 18:26:19292 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43293 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19294}
295
[email protected]231d5a32008-09-13 00:45:27296//-----------------------------------------------------------------------------
297
298TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]db8f44c2008-12-13 04:52:01299 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]af4876d2008-10-21 23:10:57300 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01301 CreateSession(proxy_service.get()), &mock_socket_factory));
[email protected]231d5a32008-09-13 00:45:27302}
303
304TEST_F(HttpNetworkTransactionTest, SimpleGET) {
305 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35306 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
307 MockRead("hello world"),
308 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27309 };
[email protected]231d5a32008-09-13 00:45:27310 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47311 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27312 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
313 EXPECT_EQ("hello world", out.response_data);
314}
315
316// Response with no status line.
317TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
318 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35319 MockRead("hello world"),
320 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27321 };
[email protected]231d5a32008-09-13 00:45:27322 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47323 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27324 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
325 EXPECT_EQ("hello world", out.response_data);
326}
327
328// Allow up to 4 bytes of junk to precede status line.
329TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
330 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35331 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
332 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27333 };
334 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47335 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27336 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
337 EXPECT_EQ("DATA", out.response_data);
338}
339
340// Allow up to 4 bytes of junk to precede status line.
341TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
342 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35343 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
344 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27345 };
346 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47347 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27348 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
349 EXPECT_EQ("DATA", out.response_data);
350}
351
352// Beyond 4 bytes of slop and it should fail to find a status line.
353TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
354 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35355 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
356 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27357 };
358 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47359 EXPECT_EQ(net::OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25360 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
361 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27362}
363
364// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
365TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
366 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35367 MockRead("\n"),
368 MockRead("\n"),
369 MockRead("Q"),
370 MockRead("J"),
371 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
372 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27373 };
374 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47375 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27376 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
377 EXPECT_EQ("DATA", out.response_data);
378}
379
380// Close the connection before enough bytes to have a status line.
381TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
382 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35383 MockRead("HTT"),
384 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27385 };
386 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47387 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27388 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
389 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52390}
391
[email protected]f9d44aa2008-09-23 23:57:17392// Simulate a 204 response, lacking a Content-Length header, sent over a
393// persistent connection. The response should still terminate since a 204
394// cannot have a response body.
395TEST_F(HttpNetworkTransactionTest, StopsReading204) {
396 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35397 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
398 MockRead("junk"), // Should not be read!!
399 MockRead(false, net::OK),
[email protected]f9d44aa2008-09-23 23:57:17400 };
401 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47402 EXPECT_EQ(net::OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17403 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
404 EXPECT_EQ("", out.response_data);
405}
406
initial.commit586acc5fe2008-07-26 22:42:52407TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]db8f44c2008-12-13 04:52:01408 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
409 scoped_refptr<net::HttpNetworkSession> session =
410 CreateSession(proxy_service.get());
initial.commit586acc5fe2008-07-26 22:42:52411
412 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35413 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
414 MockRead("hello"),
415 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
416 MockRead("world"),
417 MockRead(false, net::OK),
initial.commit586acc5fe2008-07-26 22:42:52418 };
419 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52420 data.reads = data_reads;
421 mock_sockets[0] = &data;
422 mock_sockets[1] = NULL;
423
424 const char* kExpectedResponseData[] = {
425 "hello", "world"
426 };
427
428 for (int i = 0; i < 2; ++i) {
[email protected]af4876d2008-10-21 23:10:57429 scoped_ptr<net::HttpTransaction> trans(
430 new net::HttpNetworkTransaction(session, &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52431
432 net::HttpRequestInfo request;
433 request.method = "GET";
434 request.url = GURL("http://www.google.com/");
435 request.load_flags = 0;
436
437 TestCompletionCallback callback;
438
439 int rv = trans->Start(&request, &callback);
440 EXPECT_EQ(net::ERR_IO_PENDING, rv);
441
442 rv = callback.WaitForResult();
443 EXPECT_EQ(net::OK, rv);
444
445 const net::HttpResponseInfo* response = trans->GetResponseInfo();
446 EXPECT_TRUE(response != NULL);
447
448 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25449 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52450
451 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57452 rv = ReadTransaction(trans.get(), &response_data);
initial.commit586acc5fe2008-07-26 22:42:52453 EXPECT_EQ(net::OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25454 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52455 }
456}
457
458TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]db8f44c2008-12-13 04:52:01459 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]af4876d2008-10-21 23:10:57460 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01461 CreateSession(proxy_service.get()), &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52462
463 net::HttpRequestInfo request;
464 request.method = "POST";
465 request.url = GURL("http://www.foo.com/");
466 request.upload_data = new net::UploadData;
467 request.upload_data->AppendBytes("foo", 3);
468 request.load_flags = 0;
469
470 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35471 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
472 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
473 MockRead("hello world"),
474 MockRead(false, net::OK),
initial.commit586acc5fe2008-07-26 22:42:52475 };
476 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52477 data.reads = data_reads;
478 mock_sockets[0] = &data;
479 mock_sockets[1] = NULL;
480
481 TestCompletionCallback callback;
482
483 int rv = trans->Start(&request, &callback);
484 EXPECT_EQ(net::ERR_IO_PENDING, rv);
485
486 rv = callback.WaitForResult();
487 EXPECT_EQ(net::OK, rv);
488
489 const net::HttpResponseInfo* response = trans->GetResponseInfo();
490 EXPECT_TRUE(response != NULL);
491
492 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25493 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52494
495 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57496 rv = ReadTransaction(trans.get(), &response_data);
initial.commit586acc5fe2008-07-26 22:42:52497 EXPECT_EQ(net::OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25498 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52499}
500
[email protected]3d2a59b2008-09-26 19:44:25501// read_failure specifies a read failure that should cause the network
502// transaction to resend the request.
503void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
504 const MockRead& read_failure) {
[email protected]db8f44c2008-12-13 04:52:01505 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
506 scoped_refptr<net::HttpNetworkSession> session =
507 CreateSession(proxy_service.get());
initial.commit586acc5fe2008-07-26 22:42:52508
509 net::HttpRequestInfo request;
510 request.method = "GET";
511 request.url = GURL("http://www.foo.com/");
512 request.load_flags = 0;
513
514 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35515 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
516 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25517 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52518 };
519 MockSocket data1;
initial.commit586acc5fe2008-07-26 22:42:52520 data1.reads = data1_reads;
521 mock_sockets[0] = &data1;
522
523 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35524 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
525 MockRead("world"),
526 MockRead(true, net::OK),
initial.commit586acc5fe2008-07-26 22:42:52527 };
528 MockSocket data2;
initial.commit586acc5fe2008-07-26 22:42:52529 data2.reads = data2_reads;
530 mock_sockets[1] = &data2;
531
532 const char* kExpectedResponseData[] = {
533 "hello", "world"
534 };
535
536 for (int i = 0; i < 2; ++i) {
537 TestCompletionCallback callback;
538
[email protected]af4876d2008-10-21 23:10:57539 scoped_ptr<net::HttpTransaction> trans(
540 new net::HttpNetworkTransaction(session, &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52541
542 int rv = trans->Start(&request, &callback);
543 EXPECT_EQ(net::ERR_IO_PENDING, rv);
544
545 rv = callback.WaitForResult();
546 EXPECT_EQ(net::OK, rv);
547
548 const net::HttpResponseInfo* response = trans->GetResponseInfo();
549 EXPECT_TRUE(response != NULL);
550
551 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25552 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52553
554 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57555 rv = ReadTransaction(trans.get(), &response_data);
initial.commit586acc5fe2008-07-26 22:42:52556 EXPECT_EQ(net::OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25557 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52558 }
559}
[email protected]3d2a59b2008-09-26 19:44:25560
561TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]217e6022008-09-29 18:18:35562 MockRead read_failure(true, net::ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25563 KeepAliveConnectionResendRequestTest(read_failure);
564}
565
566TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]217e6022008-09-29 18:18:35567 MockRead read_failure(false, net::OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25568 KeepAliveConnectionResendRequestTest(read_failure);
569}
570
571TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]db8f44c2008-12-13 04:52:01572 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]af4876d2008-10-21 23:10:57573 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01574 CreateSession(proxy_service.get()), &mock_socket_factory));
[email protected]3d2a59b2008-09-26 19:44:25575
576 net::HttpRequestInfo request;
577 request.method = "GET";
578 request.url = GURL("http://www.google.com/");
579 request.load_flags = 0;
580
581 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35582 MockRead(true, net::ERR_CONNECTION_RESET),
583 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
584 MockRead("hello world"),
585 MockRead(false, net::OK),
[email protected]3d2a59b2008-09-26 19:44:25586 };
587 MockSocket data;
[email protected]3d2a59b2008-09-26 19:44:25588 data.reads = data_reads;
589 mock_sockets[0] = &data;
590 mock_sockets[1] = NULL;
591
592 TestCompletionCallback callback;
593
594 int rv = trans->Start(&request, &callback);
595 EXPECT_EQ(net::ERR_IO_PENDING, rv);
596
597 rv = callback.WaitForResult();
598 EXPECT_EQ(net::ERR_CONNECTION_RESET, rv);
599
600 const net::HttpResponseInfo* response = trans->GetResponseInfo();
601 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25602}
603
604// What do various browsers do when the server closes a non-keepalive
605// connection without sending any response header or body?
606//
607// IE7: error page
608// Safari 3.1.2 (Windows): error page
609// Firefox 3.0.1: blank page
610// Opera 9.52: after five attempts, blank page
611// Us with WinHTTP: error page (net::ERR_INVALID_RESPONSE)
[email protected]aecfbf22008-10-16 02:02:47612// Us: error page (net::EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25613TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
614 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35615 MockRead(false, net::OK), // EOF
616 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
617 MockRead("hello world"),
618 MockRead(false, net::OK),
[email protected]3d2a59b2008-09-26 19:44:25619 };
620 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]0e75a732008-10-16 20:36:09621 EXPECT_EQ(net::ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25622}
[email protected]038e9a32008-10-08 22:40:16623
624// Test the request-challenge-retry sequence for basic auth.
625// (basic auth is the easiest to mock, because it has no randomness).
626TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]db8f44c2008-12-13 04:52:01627 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]af4876d2008-10-21 23:10:57628 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01629 CreateSession(proxy_service.get()), &mock_socket_factory));
[email protected]038e9a32008-10-08 22:40:16630
631 net::HttpRequestInfo request;
632 request.method = "GET";
633 request.url = GURL("http://www.google.com/");
634 request.load_flags = 0;
635
[email protected]f9ee6b52008-11-08 06:46:23636 MockWrite data_writes1[] = {
637 MockWrite("GET / HTTP/1.1\r\n"
638 "Host: www.google.com\r\n"
639 "Connection: keep-alive\r\n\r\n"),
640 };
641
[email protected]038e9a32008-10-08 22:40:16642 MockRead data_reads1[] = {
643 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
644 // Give a couple authenticate options (only the middle one is actually
645 // supported).
[email protected]aaead502008-10-15 00:20:11646 MockRead("WWW-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16647 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
648 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
649 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
650 // Large content-length -- won't matter, as connection will be reset.
651 MockRead("Content-Length: 10000\r\n\r\n"),
652 MockRead(false, net::ERR_FAILED),
653 };
654
655 // After calling trans->RestartWithAuth(), this is the request we should
656 // be issuing -- the final header line contains the credentials.
657 MockWrite data_writes2[] = {
658 MockWrite("GET / HTTP/1.1\r\n"
659 "Host: www.google.com\r\n"
660 "Connection: keep-alive\r\n"
661 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
662 };
663
664 // Lastly, the server responds with the actual content.
665 MockRead data_reads2[] = {
666 MockRead("HTTP/1.0 200 OK\r\n"),
667 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
668 MockRead("Content-Length: 100\r\n\r\n"),
669 MockRead(false, net::OK),
670 };
671
672 MockSocket data1;
673 data1.reads = data_reads1;
[email protected]f9ee6b52008-11-08 06:46:23674 data1.writes = data_writes1;
[email protected]038e9a32008-10-08 22:40:16675 MockSocket data2;
676 data2.reads = data_reads2;
677 data2.writes = data_writes2;
678 mock_sockets[0] = &data1;
679 mock_sockets[1] = &data2;
680 mock_sockets[2] = NULL;
681
682 TestCompletionCallback callback1;
683
684 int rv = trans->Start(&request, &callback1);
685 EXPECT_EQ(net::ERR_IO_PENDING, rv);
686
687 rv = callback1.WaitForResult();
688 EXPECT_EQ(net::OK, rv);
689
690 const net::HttpResponseInfo* response = trans->GetResponseInfo();
691 EXPECT_FALSE(response == NULL);
692
693 // The password prompt info should have been set in response->auth_challenge.
694 EXPECT_FALSE(response->auth_challenge.get() == NULL);
695
696 // TODO(eroman): this should really include the effective port (80)
697 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
698 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
699 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
700
701 TestCompletionCallback callback2;
702
703 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
704 EXPECT_EQ(net::ERR_IO_PENDING, rv);
705
706 rv = callback2.WaitForResult();
707 EXPECT_EQ(net::OK, rv);
708
709 response = trans->GetResponseInfo();
710 EXPECT_FALSE(response == NULL);
711 EXPECT_TRUE(response->auth_challenge.get() == NULL);
712 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16713}
714
715// Test the flow when both the proxy server AND origin server require
716// authentication. Again, this uses basic auth for both since that is
717// the simplest to mock.
718TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]51fff29d2008-12-19 22:17:53719 scoped_ptr<net::ProxyService> proxy_service(
720 CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:01721
[email protected]038e9a32008-10-08 22:40:16722 // Configure against proxy server "myproxy:70".
[email protected]af4876d2008-10-21 23:10:57723 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]51fff29d2008-12-19 22:17:53724 CreateSession(proxy_service.get()),
[email protected]db8f44c2008-12-13 04:52:01725 &mock_socket_factory));
[email protected]038e9a32008-10-08 22:40:16726
727 net::HttpRequestInfo request;
728 request.method = "GET";
729 request.url = GURL("http://www.google.com/");
730 request.load_flags = 0;
731
[email protected]f9ee6b52008-11-08 06:46:23732 MockWrite data_writes1[] = {
733 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
734 "Host: www.google.com\r\n"
735 "Proxy-Connection: keep-alive\r\n\r\n"),
736 };
737
[email protected]038e9a32008-10-08 22:40:16738 MockRead data_reads1[] = {
739 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
740 // Give a couple authenticate options (only the middle one is actually
741 // supported).
[email protected]aaead502008-10-15 00:20:11742 MockRead("Proxy-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16743 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
744 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
745 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
746 // Large content-length -- won't matter, as connection will be reset.
747 MockRead("Content-Length: 10000\r\n\r\n"),
748 MockRead(false, net::ERR_FAILED),
749 };
750
751 // After calling trans->RestartWithAuth() the first time, this is the
752 // request we should be issuing -- the final header line contains the
753 // proxy's credentials.
754 MockWrite data_writes2[] = {
755 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
756 "Host: www.google.com\r\n"
757 "Proxy-Connection: keep-alive\r\n"
758 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
759 };
760
761 // Now the proxy server lets the request pass through to origin server.
762 // The origin server responds with a 401.
763 MockRead data_reads2[] = {
764 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
765 // Note: We are using the same realm-name as the proxy server. This is
766 // completely valid, as realms are unique across hosts.
767 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
768 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
769 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]aaead502008-10-15 00:20:11770 MockRead(false, net::ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:16771 };
772
773 // After calling trans->RestartWithAuth() the second time, we should send
774 // the credentials for both the proxy and origin server.
775 MockWrite data_writes3[] = {
776 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
777 "Host: www.google.com\r\n"
778 "Proxy-Connection: keep-alive\r\n"
779 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
780 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
781 };
782
783 // Lastly we get the desired content.
784 MockRead data_reads3[] = {
785 MockRead("HTTP/1.0 200 OK\r\n"),
786 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
787 MockRead("Content-Length: 100\r\n\r\n"),
788 MockRead(false, net::OK),
789 };
790
791 MockSocket data1;
792 data1.reads = data_reads1;
[email protected]f9ee6b52008-11-08 06:46:23793 data1.writes = data_writes1;
[email protected]038e9a32008-10-08 22:40:16794 MockSocket data2;
795 data2.reads = data_reads2;
796 data2.writes = data_writes2;
797 MockSocket data3;
798 data3.reads = data_reads3;
799 data3.writes = data_writes3;
800 mock_sockets[0] = &data1;
801 mock_sockets[1] = &data2;
802 mock_sockets[2] = &data3;
803 mock_sockets[3] = NULL;
804
805 TestCompletionCallback callback1;
806
807 int rv = trans->Start(&request, &callback1);
808 EXPECT_EQ(net::ERR_IO_PENDING, rv);
809
810 rv = callback1.WaitForResult();
811 EXPECT_EQ(net::OK, rv);
812
813 const net::HttpResponseInfo* response = trans->GetResponseInfo();
814 EXPECT_FALSE(response == NULL);
815
816 // The password prompt info should have been set in response->auth_challenge.
817 EXPECT_FALSE(response->auth_challenge.get() == NULL);
818
819 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host);
820 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
821 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
822
823 TestCompletionCallback callback2;
824
825 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
826 EXPECT_EQ(net::ERR_IO_PENDING, rv);
827
828 rv = callback2.WaitForResult();
829 EXPECT_EQ(net::OK, rv);
830
831 response = trans->GetResponseInfo();
832 EXPECT_FALSE(response == NULL);
833 EXPECT_FALSE(response->auth_challenge.get() == NULL);
834
835 // TODO(eroman): this should really include the effective port (80)
836 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
837 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
838 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
839
840 TestCompletionCallback callback3;
841
842 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
843 EXPECT_EQ(net::ERR_IO_PENDING, rv);
844
845 rv = callback3.WaitForResult();
846 EXPECT_EQ(net::OK, rv);
847
848 response = trans->GetResponseInfo();
849 EXPECT_TRUE(response->auth_challenge.get() == NULL);
850 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16851}
[email protected]4ddaf2502008-10-23 18:26:19852
853// Test reading a server response which has only headers, and no body.
854// After some maximum number of bytes is consumed, the transaction should
855// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
856TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]db8f44c2008-12-13 04:52:01857 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]4ddaf2502008-10-23 18:26:19858 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01859 CreateSession(proxy_service.get()), &mock_socket_factory));
[email protected]4ddaf2502008-10-23 18:26:19860
861 net::HttpRequestInfo request;
862 request.method = "GET";
863 request.url = GURL("http://www.google.com/");
864 request.load_flags = 0;
865
866 // Respond with 50 kb of headers (we should fail after 32 kb).
[email protected]15a5ccf82008-10-23 19:57:43867 std::string large_headers_string;
868 FillLargeHeadersString(&large_headers_string, 50 * 1024);
[email protected]4ddaf2502008-10-23 18:26:19869
870 MockRead data_reads[] = {
871 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:43872 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:19873 MockRead("\r\nBODY"),
874 MockRead(false, net::OK),
875 };
876 MockSocket data;
877 data.reads = data_reads;
878 mock_sockets[0] = &data;
879 mock_sockets[1] = NULL;
880
881 TestCompletionCallback callback;
882
883 int rv = trans->Start(&request, &callback);
884 EXPECT_EQ(net::ERR_IO_PENDING, rv);
885
886 rv = callback.WaitForResult();
887 EXPECT_EQ(net::ERR_RESPONSE_HEADERS_TOO_BIG, rv);
888
889 const net::HttpResponseInfo* response = trans->GetResponseInfo();
890 EXPECT_TRUE(response == NULL);
891}
[email protected]f4e426b2008-11-05 00:24:49892
893// Make sure that we don't try to reuse a TCPClientSocket when failing to
894// establish tunnel.
895// http://code.google.com/p/chromium/issues/detail?id=3772
896TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
897 // Configure against proxy server "myproxy:70".
[email protected]51fff29d2008-12-19 22:17:53898 scoped_ptr<net::ProxyService> proxy_service(
899 CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:01900
[email protected]f4e426b2008-11-05 00:24:49901 scoped_refptr<net::HttpNetworkSession> session(
[email protected]51fff29d2008-12-19 22:17:53902 CreateSession(proxy_service.get()));
[email protected]f4e426b2008-11-05 00:24:49903
904 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
905 session.get(), &mock_socket_factory));
906
907 net::HttpRequestInfo request;
908 request.method = "GET";
909 request.url = GURL("https://www.google.com/");
910 request.load_flags = 0;
911
912 // Since we have proxy, should try to establish tunnel.
913 MockWrite data_writes1[] = {
914 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
915 "Host: www.google.com\r\n\r\n"),
916 };
917
[email protected]77848d12008-11-14 00:00:22918 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:49919 // connection. Usually a proxy would return 501 (not implemented),
920 // or 200 (tunnel established).
921 MockRead data_reads1[] = {
922 MockRead("HTTP/1.1 404 Not Found\r\n"),
923 MockRead("Content-Length: 10\r\n\r\n"),
924 MockRead("0123456789"),
[email protected]77848d12008-11-14 00:00:22925 MockRead(false, net::ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:49926 };
927
928 MockSocket data1;
929 data1.writes = data_writes1;
930 data1.reads = data_reads1;
931 mock_sockets[0] = &data1;
932 mock_sockets[1] = NULL;
933
934 TestCompletionCallback callback1;
935
936 int rv = trans->Start(&request, &callback1);
937 EXPECT_EQ(net::ERR_IO_PENDING, rv);
938
939 rv = callback1.WaitForResult();
940 EXPECT_EQ(net::OK, rv);
941
942 const net::HttpResponseInfo* response = trans->GetResponseInfo();
943 EXPECT_FALSE(response == NULL);
944
945 EXPECT_TRUE(response->headers->IsKeepAlive());
946 EXPECT_EQ(404, response->headers->response_code());
947 EXPECT_EQ(10, response->headers->GetContentLength());
948 EXPECT_TRUE(net::HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]77848d12008-11-14 00:00:22949
[email protected]f4e426b2008-11-05 00:24:49950 std::string response_data;
951 rv = ReadTransaction(trans.get(), &response_data);
952 EXPECT_STREQ("0123456789", response_data.c_str());
953
954 // We now check to make sure the TCPClientSocket was not added back to
955 // the pool.
956 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
957 trans.reset();
958 // Make sure that the socket didn't get recycled after calling the destructor.
959 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
960}
[email protected]372d34a2008-11-05 21:30:51961
962TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
963 net::HttpRequestInfo request[2];
964 // Transaction 1: a GET request that succeeds. The socket is recycled
965 // after use.
966 request[0].method = "GET";
967 request[0].url = GURL("http://www.google.com/");
968 request[0].load_flags = 0;
969 // Transaction 2: a POST request. Reuses the socket kept alive from
970 // transaction 1. The first attempts fails when writing the POST data.
971 // This causes the transaction to retry with a new socket. The second
972 // attempt succeeds.
973 request[1].method = "POST";
974 request[1].url = GURL("http://www.google.com/login.cgi");
975 request[1].upload_data = new net::UploadData;
976 request[1].upload_data->AppendBytes("foo", 3);
977 request[1].load_flags = 0;
978
[email protected]db8f44c2008-12-13 04:52:01979 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
980 scoped_refptr<net::HttpNetworkSession> session =
981 CreateSession(proxy_service.get());
[email protected]372d34a2008-11-05 21:30:51982
983 // The first socket is used for transaction 1 and the first attempt of
984 // transaction 2.
985
986 // The response of transaction 1.
987 MockRead data_reads1[] = {
988 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
989 MockRead("hello world"),
990 MockRead(false, net::OK),
991 };
992 // The mock write results of transaction 1 and the first attempt of
993 // transaction 2.
994 MockWrite data_writes1[] = {
995 MockWrite(false, 64), // GET
996 MockWrite(false, 93), // POST
997 MockWrite(false, net::ERR_CONNECTION_ABORTED), // POST data
998 };
999 MockSocket data1;
1000 data1.reads = data_reads1;
1001 data1.writes = data_writes1;
1002
1003 // The second socket is used for the second attempt of transaction 2.
1004
1005 // The response of transaction 2.
1006 MockRead data_reads2[] = {
1007 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
1008 MockRead("welcome"),
1009 MockRead(false, net::OK),
1010 };
1011 // The mock write results of the second attempt of transaction 2.
1012 MockWrite data_writes2[] = {
1013 MockWrite(false, 93), // POST
1014 MockWrite(false, 3), // POST data
1015 };
1016 MockSocket data2;
1017 data2.reads = data_reads2;
1018 data2.writes = data_writes2;
1019
1020 mock_sockets[0] = &data1;
1021 mock_sockets[1] = &data2;
1022 mock_sockets[2] = NULL;
1023
1024 const char* kExpectedResponseData[] = {
1025 "hello world", "welcome"
1026 };
1027
1028 for (int i = 0; i < 2; ++i) {
1029 scoped_ptr<net::HttpTransaction> trans(
1030 new net::HttpNetworkTransaction(session, &mock_socket_factory));
1031
1032 TestCompletionCallback callback;
1033
1034 int rv = trans->Start(&request[i], &callback);
1035 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1036
1037 rv = callback.WaitForResult();
1038 EXPECT_EQ(net::OK, rv);
1039
1040 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1041 EXPECT_TRUE(response != NULL);
1042
1043 EXPECT_TRUE(response->headers != NULL);
1044 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1045
1046 std::string response_data;
1047 rv = ReadTransaction(trans.get(), &response_data);
1048 EXPECT_EQ(net::OK, rv);
1049 EXPECT_EQ(kExpectedResponseData[i], response_data);
1050 }
1051}
[email protected]f9ee6b52008-11-08 06:46:231052
1053// Test the request-challenge-retry sequence for basic auth when there is
1054// an identity in the URL. The request should be sent as normal, but when
1055// it fails the identity from the URL is used to answer the challenge.
1056TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) {
[email protected]db8f44c2008-12-13 04:52:011057 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]f9ee6b52008-11-08 06:46:231058 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:011059 CreateSession(proxy_service.get()), &mock_socket_factory));
[email protected]f9ee6b52008-11-08 06:46:231060
1061 net::HttpRequestInfo request;
1062 request.method = "GET";
1063 // Note: the URL has a username:password in it.
1064 request.url = GURL("http://foo:[email protected]/");
1065 request.load_flags = 0;
1066
1067 MockWrite data_writes1[] = {
1068 MockWrite("GET / HTTP/1.1\r\n"
1069 "Host: www.google.com\r\n"
1070 "Connection: keep-alive\r\n\r\n"),
1071 };
1072
1073 MockRead data_reads1[] = {
1074 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1075 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1076 MockRead("Content-Length: 10\r\n\r\n"),
1077 MockRead(false, net::ERR_FAILED),
1078 };
1079
1080 // After the challenge above, the transaction will be restarted using the
1081 // identity from the url (foo, bar) to answer the challenge.
1082 MockWrite data_writes2[] = {
1083 MockWrite("GET / HTTP/1.1\r\n"
1084 "Host: www.google.com\r\n"
1085 "Connection: keep-alive\r\n"
1086 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1087 };
1088
1089 MockRead data_reads2[] = {
1090 MockRead("HTTP/1.0 200 OK\r\n"),
1091 MockRead("Content-Length: 100\r\n\r\n"),
1092 MockRead(false, net::OK),
1093 };
1094
1095 MockSocket data1;
1096 data1.reads = data_reads1;
1097 data1.writes = data_writes1;
1098 MockSocket data2;
1099 data2.reads = data_reads2;
1100 data2.writes = data_writes2;
1101 mock_sockets[0] = &data1;
1102 mock_sockets[1] = &data2;
1103 mock_sockets[2] = NULL;
1104
1105 TestCompletionCallback callback1;
1106
1107 int rv = trans->Start(&request, &callback1);
1108 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1109
1110 rv = callback1.WaitForResult();
1111 EXPECT_EQ(net::OK, rv);
1112
1113 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1114 EXPECT_FALSE(response == NULL);
1115
1116 // There is no challenge info, since the identity in URL worked.
1117 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1118
1119 EXPECT_EQ(100, response->headers->GetContentLength());
1120
1121 // Empty the current queue.
1122 MessageLoop::current()->RunAllPending();
1123}
1124
1125// Test that previously tried username/passwords for a realm get re-used.
1126TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]db8f44c2008-12-13 04:52:011127 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
1128 scoped_refptr<net::HttpNetworkSession> session =
1129 CreateSession(proxy_service.get());
[email protected]f9ee6b52008-11-08 06:46:231130
1131 // Transaction 1: authenticate (foo, bar) on MyRealm1
1132 {
1133 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
1134 session, &mock_socket_factory));
1135
1136 net::HttpRequestInfo request;
1137 request.method = "GET";
1138 request.url = GURL("http://www.google.com/x/y/z");
1139 request.load_flags = 0;
1140
1141 MockWrite data_writes1[] = {
1142 MockWrite("GET /x/y/z HTTP/1.1\r\n"
1143 "Host: www.google.com\r\n"
1144 "Connection: keep-alive\r\n\r\n"),
1145 };
1146
1147 MockRead data_reads1[] = {
1148 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1149 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1150 MockRead("Content-Length: 10000\r\n\r\n"),
1151 MockRead(false, net::ERR_FAILED),
1152 };
1153
1154 // Resend with authorization (username=foo, password=bar)
1155 MockWrite data_writes2[] = {
1156 MockWrite("GET /x/y/z HTTP/1.1\r\n"
1157 "Host: www.google.com\r\n"
1158 "Connection: keep-alive\r\n"
1159 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1160 };
1161
1162 // Sever accepts the authorization.
1163 MockRead data_reads2[] = {
1164 MockRead("HTTP/1.0 200 OK\r\n"),
1165 MockRead("Content-Length: 100\r\n\r\n"),
1166 MockRead(false, net::OK),
1167 };
1168
1169 MockSocket data1;
1170 data1.reads = data_reads1;
1171 data1.writes = data_writes1;
1172 MockSocket data2;
1173 data2.reads = data_reads2;
1174 data2.writes = data_writes2;
1175 mock_sockets_index = 0;
1176 mock_sockets[0] = &data1;
1177 mock_sockets[1] = &data2;
1178 mock_sockets[2] = NULL;
1179
1180 TestCompletionCallback callback1;
1181
1182 int rv = trans->Start(&request, &callback1);
1183 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1184
1185 rv = callback1.WaitForResult();
1186 EXPECT_EQ(net::OK, rv);
1187
1188 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1189 EXPECT_FALSE(response == NULL);
1190
1191 // The password prompt info should have been set in
1192 // response->auth_challenge.
1193 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1194
1195 // TODO(eroman): this should really include the effective port (80)
1196 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
1197 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1198 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1199
1200 TestCompletionCallback callback2;
1201
1202 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1203 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1204
1205 rv = callback2.WaitForResult();
1206 EXPECT_EQ(net::OK, rv);
1207
1208 response = trans->GetResponseInfo();
1209 EXPECT_FALSE(response == NULL);
1210 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1211 EXPECT_EQ(100, response->headers->GetContentLength());
1212 }
1213
1214 // ------------------------------------------------------------------------
1215
1216 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
1217 {
1218 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
1219 session, &mock_socket_factory));
1220
1221 net::HttpRequestInfo request;
1222 request.method = "GET";
1223 // Note that Transaction 1 was at /x/y/z, so this is in the same
1224 // protection space as MyRealm1.
1225 request.url = GURL("http://www.google.com/x/y/a/b");
1226 request.load_flags = 0;
1227
1228 MockWrite data_writes1[] = {
1229 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
1230 "Host: www.google.com\r\n"
1231 "Connection: keep-alive\r\n"
1232 // Send preemptive authorization for MyRealm1
1233 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1234 };
1235
1236 // The server didn't like the preemptive authorization, and
1237 // challenges us for a different realm (MyRealm2).
1238 MockRead data_reads1[] = {
1239 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1240 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
1241 MockRead("Content-Length: 10000\r\n\r\n"),
1242 MockRead(false, net::ERR_FAILED),
1243 };
1244
1245 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
1246 MockWrite data_writes2[] = {
1247 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
1248 "Host: www.google.com\r\n"
1249 "Connection: keep-alive\r\n"
1250 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1251 };
1252
1253 // Sever accepts the authorization.
1254 MockRead data_reads2[] = {
1255 MockRead("HTTP/1.0 200 OK\r\n"),
1256 MockRead("Content-Length: 100\r\n\r\n"),
1257 MockRead(false, net::OK),
1258 };
1259
1260 MockSocket data1;
1261 data1.reads = data_reads1;
1262 data1.writes = data_writes1;
1263 MockSocket data2;
1264 data2.reads = data_reads2;
1265 data2.writes = data_writes2;
1266 mock_sockets_index = 0;
1267 mock_sockets[0] = &data1;
1268 mock_sockets[1] = &data2;
1269 mock_sockets[2] = NULL;
1270
1271 TestCompletionCallback callback1;
1272
1273 int rv = trans->Start(&request, &callback1);
1274 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1275
1276 rv = callback1.WaitForResult();
1277 EXPECT_EQ(net::OK, rv);
1278
1279 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1280 EXPECT_FALSE(response == NULL);
1281
1282 // The password prompt info should have been set in
1283 // response->auth_challenge.
1284 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1285
1286 // TODO(eroman): this should really include the effective port (80)
1287 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
1288 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
1289 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1290
1291 TestCompletionCallback callback2;
1292
1293 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
1294 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1295
1296 rv = callback2.WaitForResult();
1297 EXPECT_EQ(net::OK, rv);
1298
1299 response = trans->GetResponseInfo();
1300 EXPECT_FALSE(response == NULL);
1301 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1302 EXPECT_EQ(100, response->headers->GetContentLength());
1303 }
1304
1305 // ------------------------------------------------------------------------
1306
1307 // Transaction 3: Resend a request in MyRealm's protection space --
1308 // succeed with preemptive authorization.
1309 {
1310 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
1311 session, &mock_socket_factory));
1312
1313 net::HttpRequestInfo request;
1314 request.method = "GET";
1315 request.url = GURL("http://www.google.com/x/y/z2");
1316 request.load_flags = 0;
1317
1318 MockWrite data_writes1[] = {
1319 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
1320 "Host: www.google.com\r\n"
1321 "Connection: keep-alive\r\n"
1322 // The authorization for MyRealm1 gets sent preemptively
1323 // (since the url is in the same protection space)
1324 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1325 };
1326
1327 // Sever accepts the preemptive authorization
1328 MockRead data_reads1[] = {
1329 MockRead("HTTP/1.0 200 OK\r\n"),
1330 MockRead("Content-Length: 100\r\n\r\n"),
1331 MockRead(false, net::OK),
1332 };
1333
1334 MockSocket data1;
1335 data1.reads = data_reads1;
1336 data1.writes = data_writes1;
1337 mock_sockets_index = 0;
1338 mock_sockets[0] = &data1;
1339 mock_sockets[1] = NULL;
1340
1341 TestCompletionCallback callback1;
1342
1343 int rv = trans->Start(&request, &callback1);
1344 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1345
1346 rv = callback1.WaitForResult();
1347 EXPECT_EQ(net::OK, rv);
1348
1349 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1350 EXPECT_FALSE(response == NULL);
1351
1352 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1353 EXPECT_EQ(100, response->headers->GetContentLength());
1354 }
1355
1356 // ------------------------------------------------------------------------
1357
1358 // Transaction 4: request another URL in MyRealm (however the
1359 // url is not known to belong to the protection space, so no pre-auth).
1360 {
1361 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
1362 session, &mock_socket_factory));
1363
1364 net::HttpRequestInfo request;
1365 request.method = "GET";
1366 request.url = GURL("http://www.google.com/x/1");
1367 request.load_flags = 0;
1368
1369 MockWrite data_writes1[] = {
1370 MockWrite("GET /x/1 HTTP/1.1\r\n"
1371 "Host: www.google.com\r\n"
1372 "Connection: keep-alive\r\n\r\n"),
1373 };
1374
1375 MockRead data_reads1[] = {
1376 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1377 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1378 MockRead("Content-Length: 10000\r\n\r\n"),
1379 MockRead(false, net::ERR_FAILED),
1380 };
1381
1382 // Resend with authorization from MyRealm's cache.
1383 MockWrite data_writes2[] = {
1384 MockWrite("GET /x/1 HTTP/1.1\r\n"
1385 "Host: www.google.com\r\n"
1386 "Connection: keep-alive\r\n"
1387 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1388 };
1389
1390 // Sever accepts the authorization.
1391 MockRead data_reads2[] = {
1392 MockRead("HTTP/1.0 200 OK\r\n"),
1393 MockRead("Content-Length: 100\r\n\r\n"),
1394 MockRead(false, net::OK),
1395 };
1396
1397 MockSocket data1;
1398 data1.reads = data_reads1;
1399 data1.writes = data_writes1;
1400 MockSocket data2;
1401 data2.reads = data_reads2;
1402 data2.writes = data_writes2;
1403 mock_sockets_index = 0;
1404 mock_sockets[0] = &data1;
1405 mock_sockets[1] = &data2;
1406 mock_sockets[2] = NULL;
1407
1408 TestCompletionCallback callback1;
1409
1410 int rv = trans->Start(&request, &callback1);
1411 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1412
1413 rv = callback1.WaitForResult();
1414 EXPECT_EQ(net::OK, rv);
1415
1416 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1417 EXPECT_FALSE(response == NULL);
1418 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1419 EXPECT_EQ(100, response->headers->GetContentLength());
1420 }
1421
1422 // ------------------------------------------------------------------------
1423
1424 // Transaction 5: request a URL in MyRealm, but the server rejects the
1425 // cached identity. Should invalidate and re-prompt.
1426 {
1427 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
1428 session, &mock_socket_factory));
1429
1430 net::HttpRequestInfo request;
1431 request.method = "GET";
1432 request.url = GURL("http://www.google.com/p/q/t");
1433 request.load_flags = 0;
1434
1435 MockWrite data_writes1[] = {
1436 MockWrite("GET /p/q/t HTTP/1.1\r\n"
1437 "Host: www.google.com\r\n"
1438 "Connection: keep-alive\r\n\r\n"),
1439 };
1440
1441 MockRead data_reads1[] = {
1442 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1443 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1444 MockRead("Content-Length: 10000\r\n\r\n"),
1445 MockRead(false, net::ERR_FAILED),
1446 };
1447
1448 // Resend with authorization from cache for MyRealm.
1449 MockWrite data_writes2[] = {
1450 MockWrite("GET /p/q/t HTTP/1.1\r\n"
1451 "Host: www.google.com\r\n"
1452 "Connection: keep-alive\r\n"
1453 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1454 };
1455
1456 // Sever rejects the authorization.
1457 MockRead data_reads2[] = {
1458 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1459 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1460 MockRead("Content-Length: 10000\r\n\r\n"),
1461 MockRead(false, net::ERR_FAILED),
1462 };
1463
1464 // At this point we should prompt for new credentials for MyRealm.
1465 // Restart with username=foo3, password=foo4.
1466 MockWrite data_writes3[] = {
1467 MockWrite("GET /p/q/t HTTP/1.1\r\n"
1468 "Host: www.google.com\r\n"
1469 "Connection: keep-alive\r\n"
1470 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
1471 };
1472
1473 // Sever accepts the authorization.
1474 MockRead data_reads3[] = {
1475 MockRead("HTTP/1.0 200 OK\r\n"),
1476 MockRead("Content-Length: 100\r\n\r\n"),
1477 MockRead(false, net::OK),
1478 };
1479
1480 MockSocket data1;
1481 data1.reads = data_reads1;
1482 data1.writes = data_writes1;
1483 MockSocket data2;
1484 data2.reads = data_reads2;
1485 data2.writes = data_writes2;
1486 MockSocket data3;
1487 data3.reads = data_reads3;
1488 data3.writes = data_writes3;
1489 mock_sockets_index = 0;
1490 mock_sockets[0] = &data1;
1491 mock_sockets[1] = &data2;
1492 mock_sockets[2] = &data3;
1493 mock_sockets[3] = NULL;
1494
1495 TestCompletionCallback callback1;
1496
1497 int rv = trans->Start(&request, &callback1);
1498 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1499
1500 rv = callback1.WaitForResult();
1501 EXPECT_EQ(net::OK, rv);
1502
1503 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1504 EXPECT_FALSE(response == NULL);
1505
1506 // The password prompt info should have been set in
1507 // response->auth_challenge.
1508 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1509
1510 // TODO(eroman): this should really include the effective port (80)
1511 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
1512 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1513 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1514
1515 TestCompletionCallback callback2;
1516
1517 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback2);
1518 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1519
1520 rv = callback2.WaitForResult();
1521 EXPECT_EQ(net::OK, rv);
1522
1523 response = trans->GetResponseInfo();
1524 EXPECT_FALSE(response == NULL);
1525 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1526 EXPECT_EQ(100, response->headers->GetContentLength());
1527 }
1528}