blob: 1e9f6aade3c726950ad1a78a888928a3e6e29856 [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);
[email protected]d1ec59082009-02-11 02:48:15210 return net::ProxyService::Create(&proxy_info);
[email protected]51fff29d2008-12-19 22:17:53211}
212
213
[email protected]db8f44c2008-12-13 04:52:01214net::HttpNetworkSession* CreateSession(net::ProxyService* proxy_service) {
215 return new net::HttpNetworkSession(proxy_service);
[email protected]e8d536192008-10-17 22:21:14216}
217
[email protected]89836e22008-09-25 20:33:42218class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52219 public:
220 virtual void SetUp() {
[email protected]89836e22008-09-25 20:33:42221 PlatformTest::SetUp();
initial.commit586acc5fe2008-07-26 22:42:52222 mock_sockets[0] = NULL;
223 mock_sockets_index = 0;
224 }
[email protected]3d2a59b2008-09-26 19:44:25225
[email protected]0e75a732008-10-16 20:36:09226 virtual void TearDown() {
227 // Empty the current queue.
228 MessageLoop::current()->RunAllPending();
229 PlatformTest::TearDown();
230 }
231
[email protected]3d2a59b2008-09-26 19:44:25232 protected:
233 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52234};
235
[email protected]231d5a32008-09-13 00:45:27236struct SimpleGetHelperResult {
[email protected]aecfbf22008-10-16 02:02:47237 int rv;
[email protected]231d5a32008-09-13 00:45:27238 std::string status_line;
239 std::string response_data;
240};
initial.commit586acc5fe2008-07-26 22:42:52241
[email protected]231d5a32008-09-13 00:45:27242SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
243 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52244
[email protected]db8f44c2008-12-13 04:52:01245 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]af4876d2008-10-21 23:10:57246 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01247 CreateSession(proxy_service.get()), &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52248
249 net::HttpRequestInfo request;
250 request.method = "GET";
251 request.url = GURL("http://www.google.com/");
252 request.load_flags = 0;
253
initial.commit586acc5fe2008-07-26 22:42:52254 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52255 data.reads = data_reads;
256 mock_sockets[0] = &data;
257 mock_sockets[1] = NULL;
258
259 TestCompletionCallback callback;
260
261 int rv = trans->Start(&request, &callback);
262 EXPECT_EQ(net::ERR_IO_PENDING, rv);
263
[email protected]aecfbf22008-10-16 02:02:47264 out.rv = callback.WaitForResult();
[email protected]af4876d2008-10-21 23:10:57265 if (out.rv != net::OK)
[email protected]aecfbf22008-10-16 02:02:47266 return out;
initial.commit586acc5fe2008-07-26 22:42:52267
268 const net::HttpResponseInfo* response = trans->GetResponseInfo();
269 EXPECT_TRUE(response != NULL);
270
271 EXPECT_TRUE(response->headers != NULL);
[email protected]231d5a32008-09-13 00:45:27272 out.status_line = response->headers->GetStatusLine();
initial.commit586acc5fe2008-07-26 22:42:52273
[email protected]af4876d2008-10-21 23:10:57274 rv = ReadTransaction(trans.get(), &out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52275 EXPECT_EQ(net::OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52276
[email protected]231d5a32008-09-13 00:45:27277 return out;
278}
279
[email protected]15a5ccf82008-10-23 19:57:43280// Fill |str| with a long header list that consumes >= |size| bytes.
281void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19282 const char* row =
283 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
284 const int sizeof_row = strlen(row);
285 const int num_rows = static_cast<int>(
286 ceil(static_cast<float>(size) / sizeof_row));
287 const int sizeof_data = num_rows * sizeof_row;
288 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43289 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51290
[email protected]4ddaf2502008-10-23 18:26:19291 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43292 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19293}
294
[email protected]231d5a32008-09-13 00:45:27295//-----------------------------------------------------------------------------
296
297TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]db8f44c2008-12-13 04:52:01298 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]af4876d2008-10-21 23:10:57299 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01300 CreateSession(proxy_service.get()), &mock_socket_factory));
[email protected]231d5a32008-09-13 00:45:27301}
302
303TEST_F(HttpNetworkTransactionTest, SimpleGET) {
304 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35305 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
306 MockRead("hello world"),
307 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27308 };
[email protected]231d5a32008-09-13 00:45:27309 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47310 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27311 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
312 EXPECT_EQ("hello world", out.response_data);
313}
314
315// Response with no status line.
316TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
317 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35318 MockRead("hello world"),
319 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27320 };
[email protected]231d5a32008-09-13 00:45:27321 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47322 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27323 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
324 EXPECT_EQ("hello world", out.response_data);
325}
326
327// Allow up to 4 bytes of junk to precede status line.
328TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
329 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35330 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
331 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27332 };
333 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47334 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27335 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
336 EXPECT_EQ("DATA", out.response_data);
337}
338
339// Allow up to 4 bytes of junk to precede status line.
340TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
341 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35342 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
343 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27344 };
345 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47346 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27347 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
348 EXPECT_EQ("DATA", out.response_data);
349}
350
351// Beyond 4 bytes of slop and it should fail to find a status line.
352TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
353 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35354 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
355 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27356 };
357 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47358 EXPECT_EQ(net::OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25359 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
360 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27361}
362
363// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
364TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
365 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35366 MockRead("\n"),
367 MockRead("\n"),
368 MockRead("Q"),
369 MockRead("J"),
370 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
371 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27372 };
373 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47374 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27375 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
376 EXPECT_EQ("DATA", out.response_data);
377}
378
379// Close the connection before enough bytes to have a status line.
380TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
381 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35382 MockRead("HTT"),
383 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27384 };
385 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47386 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27387 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
388 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52389}
390
[email protected]f9d44aa2008-09-23 23:57:17391// Simulate a 204 response, lacking a Content-Length header, sent over a
392// persistent connection. The response should still terminate since a 204
393// cannot have a response body.
394TEST_F(HttpNetworkTransactionTest, StopsReading204) {
395 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35396 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
397 MockRead("junk"), // Should not be read!!
398 MockRead(false, net::OK),
[email protected]f9d44aa2008-09-23 23:57:17399 };
400 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47401 EXPECT_EQ(net::OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17402 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
403 EXPECT_EQ("", out.response_data);
404}
405
initial.commit586acc5fe2008-07-26 22:42:52406TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]db8f44c2008-12-13 04:52:01407 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
408 scoped_refptr<net::HttpNetworkSession> session =
409 CreateSession(proxy_service.get());
initial.commit586acc5fe2008-07-26 22:42:52410
411 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35412 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
413 MockRead("hello"),
414 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
415 MockRead("world"),
416 MockRead(false, net::OK),
initial.commit586acc5fe2008-07-26 22:42:52417 };
418 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52419 data.reads = data_reads;
420 mock_sockets[0] = &data;
421 mock_sockets[1] = NULL;
422
423 const char* kExpectedResponseData[] = {
424 "hello", "world"
425 };
426
427 for (int i = 0; i < 2; ++i) {
[email protected]af4876d2008-10-21 23:10:57428 scoped_ptr<net::HttpTransaction> trans(
429 new net::HttpNetworkTransaction(session, &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52430
431 net::HttpRequestInfo request;
432 request.method = "GET";
433 request.url = GURL("http://www.google.com/");
434 request.load_flags = 0;
435
436 TestCompletionCallback callback;
437
438 int rv = trans->Start(&request, &callback);
439 EXPECT_EQ(net::ERR_IO_PENDING, rv);
440
441 rv = callback.WaitForResult();
442 EXPECT_EQ(net::OK, rv);
443
444 const net::HttpResponseInfo* response = trans->GetResponseInfo();
445 EXPECT_TRUE(response != NULL);
446
447 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25448 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52449
450 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57451 rv = ReadTransaction(trans.get(), &response_data);
initial.commit586acc5fe2008-07-26 22:42:52452 EXPECT_EQ(net::OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25453 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52454 }
455}
456
457TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]db8f44c2008-12-13 04:52:01458 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]af4876d2008-10-21 23:10:57459 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01460 CreateSession(proxy_service.get()), &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52461
462 net::HttpRequestInfo request;
463 request.method = "POST";
464 request.url = GURL("http://www.foo.com/");
465 request.upload_data = new net::UploadData;
466 request.upload_data->AppendBytes("foo", 3);
467 request.load_flags = 0;
468
469 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35470 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
471 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
472 MockRead("hello world"),
473 MockRead(false, net::OK),
initial.commit586acc5fe2008-07-26 22:42:52474 };
475 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52476 data.reads = data_reads;
477 mock_sockets[0] = &data;
478 mock_sockets[1] = NULL;
479
480 TestCompletionCallback callback;
481
482 int rv = trans->Start(&request, &callback);
483 EXPECT_EQ(net::ERR_IO_PENDING, rv);
484
485 rv = callback.WaitForResult();
486 EXPECT_EQ(net::OK, rv);
487
488 const net::HttpResponseInfo* response = trans->GetResponseInfo();
489 EXPECT_TRUE(response != NULL);
490
491 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25492 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52493
494 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57495 rv = ReadTransaction(trans.get(), &response_data);
initial.commit586acc5fe2008-07-26 22:42:52496 EXPECT_EQ(net::OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25497 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52498}
499
[email protected]3d2a59b2008-09-26 19:44:25500// read_failure specifies a read failure that should cause the network
501// transaction to resend the request.
502void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
503 const MockRead& read_failure) {
[email protected]db8f44c2008-12-13 04:52:01504 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
505 scoped_refptr<net::HttpNetworkSession> session =
506 CreateSession(proxy_service.get());
initial.commit586acc5fe2008-07-26 22:42:52507
508 net::HttpRequestInfo request;
509 request.method = "GET";
510 request.url = GURL("http://www.foo.com/");
511 request.load_flags = 0;
512
513 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35514 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
515 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25516 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52517 };
518 MockSocket data1;
initial.commit586acc5fe2008-07-26 22:42:52519 data1.reads = data1_reads;
520 mock_sockets[0] = &data1;
521
522 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35523 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
524 MockRead("world"),
525 MockRead(true, net::OK),
initial.commit586acc5fe2008-07-26 22:42:52526 };
527 MockSocket data2;
initial.commit586acc5fe2008-07-26 22:42:52528 data2.reads = data2_reads;
529 mock_sockets[1] = &data2;
530
531 const char* kExpectedResponseData[] = {
532 "hello", "world"
533 };
534
535 for (int i = 0; i < 2; ++i) {
536 TestCompletionCallback callback;
537
[email protected]af4876d2008-10-21 23:10:57538 scoped_ptr<net::HttpTransaction> trans(
539 new net::HttpNetworkTransaction(session, &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52540
541 int rv = trans->Start(&request, &callback);
542 EXPECT_EQ(net::ERR_IO_PENDING, rv);
543
544 rv = callback.WaitForResult();
545 EXPECT_EQ(net::OK, rv);
546
547 const net::HttpResponseInfo* response = trans->GetResponseInfo();
548 EXPECT_TRUE(response != NULL);
549
550 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25551 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52552
553 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57554 rv = ReadTransaction(trans.get(), &response_data);
initial.commit586acc5fe2008-07-26 22:42:52555 EXPECT_EQ(net::OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25556 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52557 }
558}
[email protected]3d2a59b2008-09-26 19:44:25559
560TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]217e6022008-09-29 18:18:35561 MockRead read_failure(true, net::ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25562 KeepAliveConnectionResendRequestTest(read_failure);
563}
564
565TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]217e6022008-09-29 18:18:35566 MockRead read_failure(false, net::OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25567 KeepAliveConnectionResendRequestTest(read_failure);
568}
569
570TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]db8f44c2008-12-13 04:52:01571 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]af4876d2008-10-21 23:10:57572 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01573 CreateSession(proxy_service.get()), &mock_socket_factory));
[email protected]3d2a59b2008-09-26 19:44:25574
575 net::HttpRequestInfo request;
576 request.method = "GET";
577 request.url = GURL("http://www.google.com/");
578 request.load_flags = 0;
579
580 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35581 MockRead(true, net::ERR_CONNECTION_RESET),
582 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
583 MockRead("hello world"),
584 MockRead(false, net::OK),
[email protected]3d2a59b2008-09-26 19:44:25585 };
586 MockSocket data;
[email protected]3d2a59b2008-09-26 19:44:25587 data.reads = data_reads;
588 mock_sockets[0] = &data;
589 mock_sockets[1] = NULL;
590
591 TestCompletionCallback callback;
592
593 int rv = trans->Start(&request, &callback);
594 EXPECT_EQ(net::ERR_IO_PENDING, rv);
595
596 rv = callback.WaitForResult();
597 EXPECT_EQ(net::ERR_CONNECTION_RESET, rv);
598
599 const net::HttpResponseInfo* response = trans->GetResponseInfo();
600 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25601}
602
603// What do various browsers do when the server closes a non-keepalive
604// connection without sending any response header or body?
605//
606// IE7: error page
607// Safari 3.1.2 (Windows): error page
608// Firefox 3.0.1: blank page
609// Opera 9.52: after five attempts, blank page
610// Us with WinHTTP: error page (net::ERR_INVALID_RESPONSE)
[email protected]aecfbf22008-10-16 02:02:47611// Us: error page (net::EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25612TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
613 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35614 MockRead(false, net::OK), // EOF
615 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
616 MockRead("hello world"),
617 MockRead(false, net::OK),
[email protected]3d2a59b2008-09-26 19:44:25618 };
619 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]0e75a732008-10-16 20:36:09620 EXPECT_EQ(net::ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25621}
[email protected]038e9a32008-10-08 22:40:16622
623// Test the request-challenge-retry sequence for basic auth.
624// (basic auth is the easiest to mock, because it has no randomness).
625TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]db8f44c2008-12-13 04:52:01626 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]af4876d2008-10-21 23:10:57627 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01628 CreateSession(proxy_service.get()), &mock_socket_factory));
[email protected]038e9a32008-10-08 22:40:16629
630 net::HttpRequestInfo request;
631 request.method = "GET";
632 request.url = GURL("http://www.google.com/");
633 request.load_flags = 0;
634
[email protected]f9ee6b52008-11-08 06:46:23635 MockWrite data_writes1[] = {
636 MockWrite("GET / HTTP/1.1\r\n"
637 "Host: www.google.com\r\n"
638 "Connection: keep-alive\r\n\r\n"),
639 };
640
[email protected]038e9a32008-10-08 22:40:16641 MockRead data_reads1[] = {
642 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
643 // Give a couple authenticate options (only the middle one is actually
644 // supported).
[email protected]aaead502008-10-15 00:20:11645 MockRead("WWW-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16646 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
647 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
648 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
649 // Large content-length -- won't matter, as connection will be reset.
650 MockRead("Content-Length: 10000\r\n\r\n"),
651 MockRead(false, net::ERR_FAILED),
652 };
653
654 // After calling trans->RestartWithAuth(), this is the request we should
655 // be issuing -- the final header line contains the credentials.
656 MockWrite data_writes2[] = {
657 MockWrite("GET / HTTP/1.1\r\n"
658 "Host: www.google.com\r\n"
659 "Connection: keep-alive\r\n"
660 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
661 };
662
663 // Lastly, the server responds with the actual content.
664 MockRead data_reads2[] = {
665 MockRead("HTTP/1.0 200 OK\r\n"),
666 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
667 MockRead("Content-Length: 100\r\n\r\n"),
668 MockRead(false, net::OK),
669 };
670
671 MockSocket data1;
672 data1.reads = data_reads1;
[email protected]f9ee6b52008-11-08 06:46:23673 data1.writes = data_writes1;
[email protected]038e9a32008-10-08 22:40:16674 MockSocket data2;
675 data2.reads = data_reads2;
676 data2.writes = data_writes2;
677 mock_sockets[0] = &data1;
678 mock_sockets[1] = &data2;
679 mock_sockets[2] = NULL;
680
681 TestCompletionCallback callback1;
682
683 int rv = trans->Start(&request, &callback1);
684 EXPECT_EQ(net::ERR_IO_PENDING, rv);
685
686 rv = callback1.WaitForResult();
687 EXPECT_EQ(net::OK, rv);
688
689 const net::HttpResponseInfo* response = trans->GetResponseInfo();
690 EXPECT_FALSE(response == NULL);
691
692 // The password prompt info should have been set in response->auth_challenge.
693 EXPECT_FALSE(response->auth_challenge.get() == NULL);
694
695 // TODO(eroman): this should really include the effective port (80)
696 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
697 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
698 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
699
700 TestCompletionCallback callback2;
701
702 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
703 EXPECT_EQ(net::ERR_IO_PENDING, rv);
704
705 rv = callback2.WaitForResult();
706 EXPECT_EQ(net::OK, rv);
707
708 response = trans->GetResponseInfo();
709 EXPECT_FALSE(response == NULL);
710 EXPECT_TRUE(response->auth_challenge.get() == NULL);
711 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16712}
713
714// Test the flow when both the proxy server AND origin server require
715// authentication. Again, this uses basic auth for both since that is
716// the simplest to mock.
717TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]51fff29d2008-12-19 22:17:53718 scoped_ptr<net::ProxyService> proxy_service(
719 CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:01720
[email protected]038e9a32008-10-08 22:40:16721 // Configure against proxy server "myproxy:70".
[email protected]af4876d2008-10-21 23:10:57722 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]51fff29d2008-12-19 22:17:53723 CreateSession(proxy_service.get()),
[email protected]db8f44c2008-12-13 04:52:01724 &mock_socket_factory));
[email protected]038e9a32008-10-08 22:40:16725
726 net::HttpRequestInfo request;
727 request.method = "GET";
728 request.url = GURL("http://www.google.com/");
729 request.load_flags = 0;
730
[email protected]f9ee6b52008-11-08 06:46:23731 MockWrite data_writes1[] = {
732 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
733 "Host: www.google.com\r\n"
734 "Proxy-Connection: keep-alive\r\n\r\n"),
735 };
736
[email protected]038e9a32008-10-08 22:40:16737 MockRead data_reads1[] = {
738 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
739 // Give a couple authenticate options (only the middle one is actually
740 // supported).
[email protected]aaead502008-10-15 00:20:11741 MockRead("Proxy-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16742 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
743 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
744 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
745 // Large content-length -- won't matter, as connection will be reset.
746 MockRead("Content-Length: 10000\r\n\r\n"),
747 MockRead(false, net::ERR_FAILED),
748 };
749
750 // After calling trans->RestartWithAuth() the first time, this is the
751 // request we should be issuing -- the final header line contains the
752 // proxy's credentials.
753 MockWrite data_writes2[] = {
754 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
755 "Host: www.google.com\r\n"
756 "Proxy-Connection: keep-alive\r\n"
757 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
758 };
759
760 // Now the proxy server lets the request pass through to origin server.
761 // The origin server responds with a 401.
762 MockRead data_reads2[] = {
763 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
764 // Note: We are using the same realm-name as the proxy server. This is
765 // completely valid, as realms are unique across hosts.
766 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
767 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
768 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]aaead502008-10-15 00:20:11769 MockRead(false, net::ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:16770 };
771
772 // After calling trans->RestartWithAuth() the second time, we should send
773 // the credentials for both the proxy and origin server.
774 MockWrite data_writes3[] = {
775 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
776 "Host: www.google.com\r\n"
777 "Proxy-Connection: keep-alive\r\n"
778 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
779 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
780 };
781
782 // Lastly we get the desired content.
783 MockRead data_reads3[] = {
784 MockRead("HTTP/1.0 200 OK\r\n"),
785 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
786 MockRead("Content-Length: 100\r\n\r\n"),
787 MockRead(false, net::OK),
788 };
789
790 MockSocket data1;
791 data1.reads = data_reads1;
[email protected]f9ee6b52008-11-08 06:46:23792 data1.writes = data_writes1;
[email protected]038e9a32008-10-08 22:40:16793 MockSocket data2;
794 data2.reads = data_reads2;
795 data2.writes = data_writes2;
796 MockSocket data3;
797 data3.reads = data_reads3;
798 data3.writes = data_writes3;
799 mock_sockets[0] = &data1;
800 mock_sockets[1] = &data2;
801 mock_sockets[2] = &data3;
802 mock_sockets[3] = NULL;
803
804 TestCompletionCallback callback1;
805
806 int rv = trans->Start(&request, &callback1);
807 EXPECT_EQ(net::ERR_IO_PENDING, rv);
808
809 rv = callback1.WaitForResult();
810 EXPECT_EQ(net::OK, rv);
811
812 const net::HttpResponseInfo* response = trans->GetResponseInfo();
813 EXPECT_FALSE(response == NULL);
814
815 // The password prompt info should have been set in response->auth_challenge.
816 EXPECT_FALSE(response->auth_challenge.get() == NULL);
817
818 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host);
819 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
820 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
821
822 TestCompletionCallback callback2;
823
824 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
825 EXPECT_EQ(net::ERR_IO_PENDING, rv);
826
827 rv = callback2.WaitForResult();
828 EXPECT_EQ(net::OK, rv);
829
830 response = trans->GetResponseInfo();
831 EXPECT_FALSE(response == NULL);
832 EXPECT_FALSE(response->auth_challenge.get() == NULL);
833
834 // TODO(eroman): this should really include the effective port (80)
835 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
836 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
837 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
838
839 TestCompletionCallback callback3;
840
841 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
842 EXPECT_EQ(net::ERR_IO_PENDING, rv);
843
844 rv = callback3.WaitForResult();
845 EXPECT_EQ(net::OK, rv);
846
847 response = trans->GetResponseInfo();
848 EXPECT_TRUE(response->auth_challenge.get() == NULL);
849 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16850}
[email protected]4ddaf2502008-10-23 18:26:19851
852// Test reading a server response which has only headers, and no body.
853// After some maximum number of bytes is consumed, the transaction should
854// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
855TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]db8f44c2008-12-13 04:52:01856 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]4ddaf2502008-10-23 18:26:19857 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:01858 CreateSession(proxy_service.get()), &mock_socket_factory));
[email protected]4ddaf2502008-10-23 18:26:19859
860 net::HttpRequestInfo request;
861 request.method = "GET";
862 request.url = GURL("http://www.google.com/");
863 request.load_flags = 0;
864
865 // Respond with 50 kb of headers (we should fail after 32 kb).
[email protected]15a5ccf82008-10-23 19:57:43866 std::string large_headers_string;
867 FillLargeHeadersString(&large_headers_string, 50 * 1024);
[email protected]4ddaf2502008-10-23 18:26:19868
869 MockRead data_reads[] = {
870 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:43871 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:19872 MockRead("\r\nBODY"),
873 MockRead(false, net::OK),
874 };
875 MockSocket data;
876 data.reads = data_reads;
877 mock_sockets[0] = &data;
878 mock_sockets[1] = NULL;
879
880 TestCompletionCallback callback;
881
882 int rv = trans->Start(&request, &callback);
883 EXPECT_EQ(net::ERR_IO_PENDING, rv);
884
885 rv = callback.WaitForResult();
886 EXPECT_EQ(net::ERR_RESPONSE_HEADERS_TOO_BIG, rv);
887
888 const net::HttpResponseInfo* response = trans->GetResponseInfo();
889 EXPECT_TRUE(response == NULL);
890}
[email protected]f4e426b2008-11-05 00:24:49891
892// Make sure that we don't try to reuse a TCPClientSocket when failing to
893// establish tunnel.
894// http://code.google.com/p/chromium/issues/detail?id=3772
895TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
896 // Configure against proxy server "myproxy:70".
[email protected]51fff29d2008-12-19 22:17:53897 scoped_ptr<net::ProxyService> proxy_service(
898 CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:01899
[email protected]f4e426b2008-11-05 00:24:49900 scoped_refptr<net::HttpNetworkSession> session(
[email protected]51fff29d2008-12-19 22:17:53901 CreateSession(proxy_service.get()));
[email protected]f4e426b2008-11-05 00:24:49902
903 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
904 session.get(), &mock_socket_factory));
905
906 net::HttpRequestInfo request;
907 request.method = "GET";
908 request.url = GURL("https://www.google.com/");
909 request.load_flags = 0;
910
911 // Since we have proxy, should try to establish tunnel.
912 MockWrite data_writes1[] = {
913 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
914 "Host: www.google.com\r\n\r\n"),
915 };
916
[email protected]77848d12008-11-14 00:00:22917 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:49918 // connection. Usually a proxy would return 501 (not implemented),
919 // or 200 (tunnel established).
920 MockRead data_reads1[] = {
921 MockRead("HTTP/1.1 404 Not Found\r\n"),
922 MockRead("Content-Length: 10\r\n\r\n"),
923 MockRead("0123456789"),
[email protected]77848d12008-11-14 00:00:22924 MockRead(false, net::ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:49925 };
926
927 MockSocket data1;
928 data1.writes = data_writes1;
929 data1.reads = data_reads1;
930 mock_sockets[0] = &data1;
931 mock_sockets[1] = NULL;
932
933 TestCompletionCallback callback1;
934
935 int rv = trans->Start(&request, &callback1);
936 EXPECT_EQ(net::ERR_IO_PENDING, rv);
937
938 rv = callback1.WaitForResult();
939 EXPECT_EQ(net::OK, rv);
940
941 const net::HttpResponseInfo* response = trans->GetResponseInfo();
942 EXPECT_FALSE(response == NULL);
943
944 EXPECT_TRUE(response->headers->IsKeepAlive());
945 EXPECT_EQ(404, response->headers->response_code());
946 EXPECT_EQ(10, response->headers->GetContentLength());
947 EXPECT_TRUE(net::HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]77848d12008-11-14 00:00:22948
[email protected]f4e426b2008-11-05 00:24:49949 std::string response_data;
950 rv = ReadTransaction(trans.get(), &response_data);
951 EXPECT_STREQ("0123456789", response_data.c_str());
952
953 // We now check to make sure the TCPClientSocket was not added back to
954 // the pool.
955 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
956 trans.reset();
957 // Make sure that the socket didn't get recycled after calling the destructor.
958 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
959}
[email protected]372d34a2008-11-05 21:30:51960
961TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
962 net::HttpRequestInfo request[2];
963 // Transaction 1: a GET request that succeeds. The socket is recycled
964 // after use.
965 request[0].method = "GET";
966 request[0].url = GURL("http://www.google.com/");
967 request[0].load_flags = 0;
968 // Transaction 2: a POST request. Reuses the socket kept alive from
969 // transaction 1. The first attempts fails when writing the POST data.
970 // This causes the transaction to retry with a new socket. The second
971 // attempt succeeds.
972 request[1].method = "POST";
973 request[1].url = GURL("http://www.google.com/login.cgi");
974 request[1].upload_data = new net::UploadData;
975 request[1].upload_data->AppendBytes("foo", 3);
976 request[1].load_flags = 0;
977
[email protected]db8f44c2008-12-13 04:52:01978 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
979 scoped_refptr<net::HttpNetworkSession> session =
980 CreateSession(proxy_service.get());
[email protected]372d34a2008-11-05 21:30:51981
982 // The first socket is used for transaction 1 and the first attempt of
983 // transaction 2.
984
985 // The response of transaction 1.
986 MockRead data_reads1[] = {
987 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
988 MockRead("hello world"),
989 MockRead(false, net::OK),
990 };
991 // The mock write results of transaction 1 and the first attempt of
992 // transaction 2.
993 MockWrite data_writes1[] = {
994 MockWrite(false, 64), // GET
995 MockWrite(false, 93), // POST
996 MockWrite(false, net::ERR_CONNECTION_ABORTED), // POST data
997 };
998 MockSocket data1;
999 data1.reads = data_reads1;
1000 data1.writes = data_writes1;
1001
1002 // The second socket is used for the second attempt of transaction 2.
1003
1004 // The response of transaction 2.
1005 MockRead data_reads2[] = {
1006 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
1007 MockRead("welcome"),
1008 MockRead(false, net::OK),
1009 };
1010 // The mock write results of the second attempt of transaction 2.
1011 MockWrite data_writes2[] = {
1012 MockWrite(false, 93), // POST
1013 MockWrite(false, 3), // POST data
1014 };
1015 MockSocket data2;
1016 data2.reads = data_reads2;
1017 data2.writes = data_writes2;
1018
1019 mock_sockets[0] = &data1;
1020 mock_sockets[1] = &data2;
1021 mock_sockets[2] = NULL;
1022
1023 const char* kExpectedResponseData[] = {
1024 "hello world", "welcome"
1025 };
1026
1027 for (int i = 0; i < 2; ++i) {
1028 scoped_ptr<net::HttpTransaction> trans(
1029 new net::HttpNetworkTransaction(session, &mock_socket_factory));
1030
1031 TestCompletionCallback callback;
1032
1033 int rv = trans->Start(&request[i], &callback);
1034 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1035
1036 rv = callback.WaitForResult();
1037 EXPECT_EQ(net::OK, rv);
1038
1039 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1040 EXPECT_TRUE(response != NULL);
1041
1042 EXPECT_TRUE(response->headers != NULL);
1043 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1044
1045 std::string response_data;
1046 rv = ReadTransaction(trans.get(), &response_data);
1047 EXPECT_EQ(net::OK, rv);
1048 EXPECT_EQ(kExpectedResponseData[i], response_data);
1049 }
1050}
[email protected]f9ee6b52008-11-08 06:46:231051
1052// Test the request-challenge-retry sequence for basic auth when there is
1053// an identity in the URL. The request should be sent as normal, but when
1054// it fails the identity from the URL is used to answer the challenge.
1055TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) {
[email protected]db8f44c2008-12-13 04:52:011056 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
[email protected]f9ee6b52008-11-08 06:46:231057 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]db8f44c2008-12-13 04:52:011058 CreateSession(proxy_service.get()), &mock_socket_factory));
[email protected]f9ee6b52008-11-08 06:46:231059
1060 net::HttpRequestInfo request;
1061 request.method = "GET";
1062 // Note: the URL has a username:password in it.
1063 request.url = GURL("http://foo:[email protected]/");
1064 request.load_flags = 0;
1065
1066 MockWrite data_writes1[] = {
1067 MockWrite("GET / HTTP/1.1\r\n"
1068 "Host: www.google.com\r\n"
1069 "Connection: keep-alive\r\n\r\n"),
1070 };
1071
1072 MockRead data_reads1[] = {
1073 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1074 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1075 MockRead("Content-Length: 10\r\n\r\n"),
1076 MockRead(false, net::ERR_FAILED),
1077 };
1078
1079 // After the challenge above, the transaction will be restarted using the
1080 // identity from the url (foo, bar) to answer the challenge.
1081 MockWrite data_writes2[] = {
1082 MockWrite("GET / HTTP/1.1\r\n"
1083 "Host: www.google.com\r\n"
1084 "Connection: keep-alive\r\n"
1085 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1086 };
1087
1088 MockRead data_reads2[] = {
1089 MockRead("HTTP/1.0 200 OK\r\n"),
1090 MockRead("Content-Length: 100\r\n\r\n"),
1091 MockRead(false, net::OK),
1092 };
1093
1094 MockSocket data1;
1095 data1.reads = data_reads1;
1096 data1.writes = data_writes1;
1097 MockSocket data2;
1098 data2.reads = data_reads2;
1099 data2.writes = data_writes2;
1100 mock_sockets[0] = &data1;
1101 mock_sockets[1] = &data2;
1102 mock_sockets[2] = NULL;
1103
1104 TestCompletionCallback callback1;
1105
1106 int rv = trans->Start(&request, &callback1);
1107 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1108
1109 rv = callback1.WaitForResult();
1110 EXPECT_EQ(net::OK, rv);
1111
1112 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1113 EXPECT_FALSE(response == NULL);
1114
1115 // There is no challenge info, since the identity in URL worked.
1116 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1117
1118 EXPECT_EQ(100, response->headers->GetContentLength());
1119
1120 // Empty the current queue.
1121 MessageLoop::current()->RunAllPending();
1122}
1123
1124// Test that previously tried username/passwords for a realm get re-used.
1125TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]db8f44c2008-12-13 04:52:011126 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService());
1127 scoped_refptr<net::HttpNetworkSession> session =
1128 CreateSession(proxy_service.get());
[email protected]f9ee6b52008-11-08 06:46:231129
1130 // Transaction 1: authenticate (foo, bar) on MyRealm1
1131 {
1132 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
1133 session, &mock_socket_factory));
1134
1135 net::HttpRequestInfo request;
1136 request.method = "GET";
1137 request.url = GURL("http://www.google.com/x/y/z");
1138 request.load_flags = 0;
1139
1140 MockWrite data_writes1[] = {
1141 MockWrite("GET /x/y/z HTTP/1.1\r\n"
1142 "Host: www.google.com\r\n"
1143 "Connection: keep-alive\r\n\r\n"),
1144 };
1145
1146 MockRead data_reads1[] = {
1147 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1148 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1149 MockRead("Content-Length: 10000\r\n\r\n"),
1150 MockRead(false, net::ERR_FAILED),
1151 };
1152
1153 // Resend with authorization (username=foo, password=bar)
1154 MockWrite data_writes2[] = {
1155 MockWrite("GET /x/y/z HTTP/1.1\r\n"
1156 "Host: www.google.com\r\n"
1157 "Connection: keep-alive\r\n"
1158 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1159 };
1160
1161 // Sever accepts the authorization.
1162 MockRead data_reads2[] = {
1163 MockRead("HTTP/1.0 200 OK\r\n"),
1164 MockRead("Content-Length: 100\r\n\r\n"),
1165 MockRead(false, net::OK),
1166 };
1167
1168 MockSocket data1;
1169 data1.reads = data_reads1;
1170 data1.writes = data_writes1;
1171 MockSocket data2;
1172 data2.reads = data_reads2;
1173 data2.writes = data_writes2;
1174 mock_sockets_index = 0;
1175 mock_sockets[0] = &data1;
1176 mock_sockets[1] = &data2;
1177 mock_sockets[2] = NULL;
1178
1179 TestCompletionCallback callback1;
1180
1181 int rv = trans->Start(&request, &callback1);
1182 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1183
1184 rv = callback1.WaitForResult();
1185 EXPECT_EQ(net::OK, rv);
1186
1187 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1188 EXPECT_FALSE(response == NULL);
1189
1190 // The password prompt info should have been set in
1191 // response->auth_challenge.
1192 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1193
1194 // TODO(eroman): this should really include the effective port (80)
1195 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
1196 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1197 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1198
1199 TestCompletionCallback callback2;
1200
1201 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1202 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1203
1204 rv = callback2.WaitForResult();
1205 EXPECT_EQ(net::OK, rv);
1206
1207 response = trans->GetResponseInfo();
1208 EXPECT_FALSE(response == NULL);
1209 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1210 EXPECT_EQ(100, response->headers->GetContentLength());
1211 }
1212
1213 // ------------------------------------------------------------------------
1214
1215 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
1216 {
1217 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
1218 session, &mock_socket_factory));
1219
1220 net::HttpRequestInfo request;
1221 request.method = "GET";
1222 // Note that Transaction 1 was at /x/y/z, so this is in the same
1223 // protection space as MyRealm1.
1224 request.url = GURL("http://www.google.com/x/y/a/b");
1225 request.load_flags = 0;
1226
1227 MockWrite data_writes1[] = {
1228 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
1229 "Host: www.google.com\r\n"
1230 "Connection: keep-alive\r\n"
1231 // Send preemptive authorization for MyRealm1
1232 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1233 };
1234
1235 // The server didn't like the preemptive authorization, and
1236 // challenges us for a different realm (MyRealm2).
1237 MockRead data_reads1[] = {
1238 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1239 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
1240 MockRead("Content-Length: 10000\r\n\r\n"),
1241 MockRead(false, net::ERR_FAILED),
1242 };
1243
1244 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
1245 MockWrite data_writes2[] = {
1246 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
1247 "Host: www.google.com\r\n"
1248 "Connection: keep-alive\r\n"
1249 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1250 };
1251
1252 // Sever accepts the authorization.
1253 MockRead data_reads2[] = {
1254 MockRead("HTTP/1.0 200 OK\r\n"),
1255 MockRead("Content-Length: 100\r\n\r\n"),
1256 MockRead(false, net::OK),
1257 };
1258
1259 MockSocket data1;
1260 data1.reads = data_reads1;
1261 data1.writes = data_writes1;
1262 MockSocket data2;
1263 data2.reads = data_reads2;
1264 data2.writes = data_writes2;
1265 mock_sockets_index = 0;
1266 mock_sockets[0] = &data1;
1267 mock_sockets[1] = &data2;
1268 mock_sockets[2] = NULL;
1269
1270 TestCompletionCallback callback1;
1271
1272 int rv = trans->Start(&request, &callback1);
1273 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1274
1275 rv = callback1.WaitForResult();
1276 EXPECT_EQ(net::OK, rv);
1277
1278 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1279 EXPECT_FALSE(response == NULL);
1280
1281 // The password prompt info should have been set in
1282 // response->auth_challenge.
1283 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1284
1285 // TODO(eroman): this should really include the effective port (80)
1286 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
1287 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
1288 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1289
1290 TestCompletionCallback callback2;
1291
1292 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
1293 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1294
1295 rv = callback2.WaitForResult();
1296 EXPECT_EQ(net::OK, rv);
1297
1298 response = trans->GetResponseInfo();
1299 EXPECT_FALSE(response == NULL);
1300 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1301 EXPECT_EQ(100, response->headers->GetContentLength());
1302 }
1303
1304 // ------------------------------------------------------------------------
1305
1306 // Transaction 3: Resend a request in MyRealm's protection space --
1307 // succeed with preemptive authorization.
1308 {
1309 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
1310 session, &mock_socket_factory));
1311
1312 net::HttpRequestInfo request;
1313 request.method = "GET";
1314 request.url = GURL("http://www.google.com/x/y/z2");
1315 request.load_flags = 0;
1316
1317 MockWrite data_writes1[] = {
1318 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
1319 "Host: www.google.com\r\n"
1320 "Connection: keep-alive\r\n"
1321 // The authorization for MyRealm1 gets sent preemptively
1322 // (since the url is in the same protection space)
1323 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1324 };
1325
1326 // Sever accepts the preemptive authorization
1327 MockRead data_reads1[] = {
1328 MockRead("HTTP/1.0 200 OK\r\n"),
1329 MockRead("Content-Length: 100\r\n\r\n"),
1330 MockRead(false, net::OK),
1331 };
1332
1333 MockSocket data1;
1334 data1.reads = data_reads1;
1335 data1.writes = data_writes1;
1336 mock_sockets_index = 0;
1337 mock_sockets[0] = &data1;
1338 mock_sockets[1] = NULL;
1339
1340 TestCompletionCallback callback1;
1341
1342 int rv = trans->Start(&request, &callback1);
1343 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1344
1345 rv = callback1.WaitForResult();
1346 EXPECT_EQ(net::OK, rv);
1347
1348 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1349 EXPECT_FALSE(response == NULL);
1350
1351 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1352 EXPECT_EQ(100, response->headers->GetContentLength());
1353 }
1354
1355 // ------------------------------------------------------------------------
1356
1357 // Transaction 4: request another URL in MyRealm (however the
1358 // url is not known to belong to the protection space, so no pre-auth).
1359 {
1360 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
1361 session, &mock_socket_factory));
1362
1363 net::HttpRequestInfo request;
1364 request.method = "GET";
1365 request.url = GURL("http://www.google.com/x/1");
1366 request.load_flags = 0;
1367
1368 MockWrite data_writes1[] = {
1369 MockWrite("GET /x/1 HTTP/1.1\r\n"
1370 "Host: www.google.com\r\n"
1371 "Connection: keep-alive\r\n\r\n"),
1372 };
1373
1374 MockRead data_reads1[] = {
1375 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1376 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1377 MockRead("Content-Length: 10000\r\n\r\n"),
1378 MockRead(false, net::ERR_FAILED),
1379 };
1380
1381 // Resend with authorization from MyRealm's cache.
1382 MockWrite data_writes2[] = {
1383 MockWrite("GET /x/1 HTTP/1.1\r\n"
1384 "Host: www.google.com\r\n"
1385 "Connection: keep-alive\r\n"
1386 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1387 };
1388
1389 // Sever accepts the authorization.
1390 MockRead data_reads2[] = {
1391 MockRead("HTTP/1.0 200 OK\r\n"),
1392 MockRead("Content-Length: 100\r\n\r\n"),
1393 MockRead(false, net::OK),
1394 };
1395
1396 MockSocket data1;
1397 data1.reads = data_reads1;
1398 data1.writes = data_writes1;
1399 MockSocket data2;
1400 data2.reads = data_reads2;
1401 data2.writes = data_writes2;
1402 mock_sockets_index = 0;
1403 mock_sockets[0] = &data1;
1404 mock_sockets[1] = &data2;
1405 mock_sockets[2] = NULL;
1406
1407 TestCompletionCallback callback1;
1408
1409 int rv = trans->Start(&request, &callback1);
1410 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1411
1412 rv = callback1.WaitForResult();
1413 EXPECT_EQ(net::OK, rv);
1414
1415 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1416 EXPECT_FALSE(response == NULL);
1417 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1418 EXPECT_EQ(100, response->headers->GetContentLength());
1419 }
1420
1421 // ------------------------------------------------------------------------
1422
1423 // Transaction 5: request a URL in MyRealm, but the server rejects the
1424 // cached identity. Should invalidate and re-prompt.
1425 {
1426 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
1427 session, &mock_socket_factory));
1428
1429 net::HttpRequestInfo request;
1430 request.method = "GET";
1431 request.url = GURL("http://www.google.com/p/q/t");
1432 request.load_flags = 0;
1433
1434 MockWrite data_writes1[] = {
1435 MockWrite("GET /p/q/t HTTP/1.1\r\n"
1436 "Host: www.google.com\r\n"
1437 "Connection: keep-alive\r\n\r\n"),
1438 };
1439
1440 MockRead data_reads1[] = {
1441 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1442 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1443 MockRead("Content-Length: 10000\r\n\r\n"),
1444 MockRead(false, net::ERR_FAILED),
1445 };
1446
1447 // Resend with authorization from cache for MyRealm.
1448 MockWrite data_writes2[] = {
1449 MockWrite("GET /p/q/t HTTP/1.1\r\n"
1450 "Host: www.google.com\r\n"
1451 "Connection: keep-alive\r\n"
1452 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1453 };
1454
1455 // Sever rejects the authorization.
1456 MockRead data_reads2[] = {
1457 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1458 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1459 MockRead("Content-Length: 10000\r\n\r\n"),
1460 MockRead(false, net::ERR_FAILED),
1461 };
1462
1463 // At this point we should prompt for new credentials for MyRealm.
1464 // Restart with username=foo3, password=foo4.
1465 MockWrite data_writes3[] = {
1466 MockWrite("GET /p/q/t HTTP/1.1\r\n"
1467 "Host: www.google.com\r\n"
1468 "Connection: keep-alive\r\n"
1469 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
1470 };
1471
1472 // Sever accepts the authorization.
1473 MockRead data_reads3[] = {
1474 MockRead("HTTP/1.0 200 OK\r\n"),
1475 MockRead("Content-Length: 100\r\n\r\n"),
1476 MockRead(false, net::OK),
1477 };
1478
1479 MockSocket data1;
1480 data1.reads = data_reads1;
1481 data1.writes = data_writes1;
1482 MockSocket data2;
1483 data2.reads = data_reads2;
1484 data2.writes = data_writes2;
1485 MockSocket data3;
1486 data3.reads = data_reads3;
1487 data3.writes = data_writes3;
1488 mock_sockets_index = 0;
1489 mock_sockets[0] = &data1;
1490 mock_sockets[1] = &data2;
1491 mock_sockets[2] = &data3;
1492 mock_sockets[3] = NULL;
1493
1494 TestCompletionCallback callback1;
1495
1496 int rv = trans->Start(&request, &callback1);
1497 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1498
1499 rv = callback1.WaitForResult();
1500 EXPECT_EQ(net::OK, rv);
1501
1502 const net::HttpResponseInfo* response = trans->GetResponseInfo();
1503 EXPECT_FALSE(response == NULL);
1504
1505 // The password prompt info should have been set in
1506 // response->auth_challenge.
1507 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1508
1509 // TODO(eroman): this should really include the effective port (80)
1510 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
1511 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1512 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1513
1514 TestCompletionCallback callback2;
1515
1516 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback2);
1517 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1518
1519 rv = callback2.WaitForResult();
1520 EXPECT_EQ(net::OK, rv);
1521
1522 response = trans->GetResponseInfo();
1523 EXPECT_FALSE(response == NULL);
1524 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1525 EXPECT_EQ(100, response->headers->GetContentLength());
1526 }
1527}