blob: d5f0228d13d40c65c370d445c1c7c86a518c8f12 [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]68bf9152008-09-25 19:47:305#include "base/compiler_specific.h"
6#include "base/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:527#include "net/base/client_socket_factory.h"
8#include "net/base/test_completion_callback.h"
9#include "net/base/upload_data.h"
10#include "net/http/http_network_session.h"
11#include "net/http/http_network_transaction.h"
12#include "net/http/http_transaction_unittest.h"
[email protected]038e9a32008-10-08 22:40:1613#include "net/proxy/proxy_resolver_fixed.h"
[email protected]e8d536192008-10-17 22:21:1414#include "net/proxy/proxy_resolver_null.h"
initial.commit586acc5fe2008-07-26 22:42:5215#include "testing/gtest/include/gtest/gtest.h"
16
17//-----------------------------------------------------------------------------
18
initial.commit586acc5fe2008-07-26 22:42:5219
20struct MockConnect {
[email protected]217e6022008-09-29 18:18:3521 // Asynchronous connection success.
22 MockConnect() : async(true), result(net::OK) { }
[email protected]038e9a32008-10-08 22:40:1623
24 bool async;
25 int result;
initial.commit586acc5fe2008-07-26 22:42:5226};
27
28struct MockRead {
[email protected]217e6022008-09-29 18:18:3529 // Read failure (no data).
30 MockRead(bool async, int result) : async(async) , result(result), data(NULL),
31 data_len(0) { }
32
33 // Asynchronous read success (inferred data length).
[email protected]b5462e02008-09-29 18:32:1934 MockRead(const char* data) : async(true), result(0), data(data),
35 data_len(strlen(data)) { }
[email protected]217e6022008-09-29 18:18:3536
37 // Read success (inferred data length).
[email protected]b5462e02008-09-29 18:32:1938 MockRead(bool async, const char* data) : async(async), result(0), data(data),
39 data_len(strlen(data)) { }
[email protected]217e6022008-09-29 18:18:3540
41 // Read success.
42 MockRead(bool async, const char* data, int data_len) : async(async),
[email protected]b5462e02008-09-29 18:32:1943 result(0), data(data), data_len(data_len) { }
[email protected]217e6022008-09-29 18:18:3544
initial.commit586acc5fe2008-07-26 22:42:5245 bool async;
[email protected]217e6022008-09-29 18:18:3546 int result;
initial.commit586acc5fe2008-07-26 22:42:5247 const char* data;
[email protected]217e6022008-09-29 18:18:3548 int data_len;
initial.commit586acc5fe2008-07-26 22:42:5249};
50
[email protected]038e9a32008-10-08 22:40:1651// MockWrite uses the same member fields as MockRead, but with different
52// meanings. The expected input to MockTCPClientSocket::Write() is given
53// by {data, data_len}, and the return value of Write() is controlled by
54// {async, result}.
55typedef MockRead MockWrite;
56
initial.commit586acc5fe2008-07-26 22:42:5257struct MockSocket {
[email protected]038e9a32008-10-08 22:40:1658 MockSocket() : reads(NULL), writes(NULL) { }
[email protected]217e6022008-09-29 18:18:3559
initial.commit586acc5fe2008-07-26 22:42:5260 MockConnect connect;
[email protected]217e6022008-09-29 18:18:3561 MockRead* reads;
[email protected]038e9a32008-10-08 22:40:1662 MockWrite* writes;
initial.commit586acc5fe2008-07-26 22:42:5263};
64
65// Holds an array of MockSocket elements. As MockTCPClientSocket objects get
66// instantiated, they take their data from the i'th element of this array.
67//
68// Tests should assign the first N entries of mock_sockets to point to valid
69// MockSocket objects. The first unused entry should be NULL'd.
70//
71MockSocket* mock_sockets[10];
72
73// Index of the next mock_sockets element to use.
74int mock_sockets_index;
75
76class MockTCPClientSocket : public net::ClientSocket {
77 public:
78 MockTCPClientSocket(const net::AddressList& addresses)
initial.commit586acc5fe2008-07-26 22:42:5279 : data_(mock_sockets[mock_sockets_index++]),
[email protected]68bf9152008-09-25 19:47:3080 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
initial.commit586acc5fe2008-07-26 22:42:5281 callback_(NULL),
82 read_index_(0),
83 read_offset_(0),
[email protected]038e9a32008-10-08 22:40:1684 write_index_(0),
initial.commit586acc5fe2008-07-26 22:42:5285 connected_(false) {
86 DCHECK(data_) << "overran mock_sockets array";
87 }
88 // ClientSocket methods:
89 virtual int Connect(net::CompletionCallback* callback) {
90 DCHECK(!callback_);
91 if (connected_)
92 return net::OK;
93 connected_ = true;
94 if (data_->connect.async) {
95 RunCallbackAsync(callback, data_->connect.result);
96 return net::ERR_IO_PENDING;
97 }
98 return data_->connect.result;
99 }
100 virtual int ReconnectIgnoringLastError(net::CompletionCallback* callback) {
101 NOTREACHED();
102 return net::ERR_FAILED;
103 }
104 virtual void Disconnect() {
105 connected_ = false;
106 callback_ = NULL;
107 }
108 virtual bool IsConnected() const {
109 return connected_;
110 }
111 // Socket methods:
112 virtual int Read(char* buf, int buf_len, net::CompletionCallback* callback) {
113 DCHECK(!callback_);
114 MockRead& r = data_->reads[read_index_];
[email protected]038e9a32008-10-08 22:40:16115 int result = r.result;
initial.commit586acc5fe2008-07-26 22:42:52116 if (r.data) {
initial.commit586acc5fe2008-07-26 22:42:52117 if (r.data_len - read_offset_ > 0) {
118 result = std::min(buf_len, r.data_len - read_offset_);
119 memcpy(buf, r.data + read_offset_, result);
120 read_offset_ += result;
121 if (read_offset_ == r.data_len) {
122 read_index_++;
123 read_offset_ = 0;
124 }
125 } else {
126 result = 0; // EOF
127 }
initial.commit586acc5fe2008-07-26 22:42:52128 }
129 if (r.async) {
130 RunCallbackAsync(callback, result);
131 return net::ERR_IO_PENDING;
132 }
133 return result;
134 }
135 virtual int Write(const char* buf, int buf_len,
136 net::CompletionCallback* callback) {
137 DCHECK(!callback_);
[email protected]038e9a32008-10-08 22:40:16138 // Not using mock writes; succeed synchronously.
139 if (!data_->writes)
140 return buf_len;
[email protected]aaead502008-10-15 00:20:11141
[email protected]038e9a32008-10-08 22:40:16142 // Check that what we are writing matches the expectation.
143 // Then give the mocked return value.
144 MockWrite& w = data_->writes[write_index_];
145 int result = w.result;
146 if (w.data) {
147 std::string expected_data(w.data, w.data_len);
148 std::string actual_data(buf, buf_len);
149 EXPECT_EQ(expected_data, actual_data);
150 if (expected_data != actual_data)
151 return net::ERR_UNEXPECTED;
152 if (result == net::OK)
153 result = w.data_len;
154 }
155 if (w.async) {
156 RunCallbackAsync(callback, result);
157 return net::ERR_IO_PENDING;
158 }
159 return result;
initial.commit586acc5fe2008-07-26 22:42:52160 }
161 private:
162 void RunCallbackAsync(net::CompletionCallback* callback, int result) {
163 callback_ = callback;
164 MessageLoop::current()->PostTask(FROM_HERE,
165 method_factory_.NewRunnableMethod(
166 &MockTCPClientSocket::RunCallback, result));
167 }
168 void RunCallback(int result) {
169 net::CompletionCallback* c = callback_;
170 callback_ = NULL;
171 if (c)
172 c->Run(result);
173 }
174 MockSocket* data_;
175 ScopedRunnableMethodFactory<MockTCPClientSocket> method_factory_;
176 net::CompletionCallback* callback_;
177 int read_index_;
178 int read_offset_;
[email protected]038e9a32008-10-08 22:40:16179 int write_index_;
initial.commit586acc5fe2008-07-26 22:42:52180 bool connected_;
181};
182
183class MockClientSocketFactory : public net::ClientSocketFactory {
184 public:
185 virtual net::ClientSocket* CreateTCPClientSocket(
186 const net::AddressList& addresses) {
187 return new MockTCPClientSocket(addresses);
188 }
[email protected]aaead502008-10-15 00:20:11189 virtual net::SSLClientSocket* CreateSSLClientSocket(
initial.commit586acc5fe2008-07-26 22:42:52190 net::ClientSocket* transport_socket,
[email protected]c5949a32008-10-08 17:28:23191 const std::string& hostname,
[email protected]aaead502008-10-15 00:20:11192 const net::SSLConfig& ssl_config) {
initial.commit586acc5fe2008-07-26 22:42:52193 return NULL;
194 }
195};
196
197MockClientSocketFactory mock_socket_factory;
198
[email protected]e8d536192008-10-17 22:21:14199net::HttpNetworkSession* CreateSession(net::ProxyResolver* proxy_resolver) {
200 if (!proxy_resolver) {
201 proxy_resolver = new net::ProxyResolverNull();
initial.commit586acc5fe2008-07-26 22:42:52202 }
[email protected]038e9a32008-10-08 22:40:16203 return new net::HttpNetworkSession(proxy_resolver);
initial.commit586acc5fe2008-07-26 22:42:52204}
205
[email protected]e8d536192008-10-17 22:21:14206net::HttpNetworkSession* CreateSession() {
207 return CreateSession(NULL);
208}
209
[email protected]89836e22008-09-25 20:33:42210class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52211 public:
212 virtual void SetUp() {
[email protected]89836e22008-09-25 20:33:42213 PlatformTest::SetUp();
initial.commit586acc5fe2008-07-26 22:42:52214 mock_sockets[0] = NULL;
215 mock_sockets_index = 0;
216 }
[email protected]3d2a59b2008-09-26 19:44:25217
[email protected]0e75a732008-10-16 20:36:09218 virtual void TearDown() {
219 // Empty the current queue.
220 MessageLoop::current()->RunAllPending();
221 PlatformTest::TearDown();
222 }
223
[email protected]3d2a59b2008-09-26 19:44:25224 protected:
225 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52226};
227
[email protected]231d5a32008-09-13 00:45:27228struct SimpleGetHelperResult {
[email protected]aecfbf22008-10-16 02:02:47229 int rv;
[email protected]231d5a32008-09-13 00:45:27230 std::string status_line;
231 std::string response_data;
232};
initial.commit586acc5fe2008-07-26 22:42:52233
[email protected]231d5a32008-09-13 00:45:27234SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
235 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52236
[email protected]af4876d2008-10-21 23:10:57237 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
238 CreateSession(), &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52239
240 net::HttpRequestInfo request;
241 request.method = "GET";
242 request.url = GURL("http://www.google.com/");
243 request.load_flags = 0;
244
initial.commit586acc5fe2008-07-26 22:42:52245 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52246 data.reads = data_reads;
247 mock_sockets[0] = &data;
248 mock_sockets[1] = NULL;
249
250 TestCompletionCallback callback;
251
252 int rv = trans->Start(&request, &callback);
253 EXPECT_EQ(net::ERR_IO_PENDING, rv);
254
[email protected]aecfbf22008-10-16 02:02:47255 out.rv = callback.WaitForResult();
[email protected]af4876d2008-10-21 23:10:57256 if (out.rv != net::OK)
[email protected]aecfbf22008-10-16 02:02:47257 return out;
initial.commit586acc5fe2008-07-26 22:42:52258
259 const net::HttpResponseInfo* response = trans->GetResponseInfo();
260 EXPECT_TRUE(response != NULL);
261
262 EXPECT_TRUE(response->headers != NULL);
[email protected]231d5a32008-09-13 00:45:27263 out.status_line = response->headers->GetStatusLine();
initial.commit586acc5fe2008-07-26 22:42:52264
[email protected]af4876d2008-10-21 23:10:57265 rv = ReadTransaction(trans.get(), &out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52266 EXPECT_EQ(net::OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52267
[email protected]231d5a32008-09-13 00:45:27268 return out;
269}
270
[email protected]15a5ccf82008-10-23 19:57:43271// Fill |str| with a long header list that consumes >= |size| bytes.
272void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19273 const char* row =
274 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
275 const int sizeof_row = strlen(row);
276 const int num_rows = static_cast<int>(
277 ceil(static_cast<float>(size) / sizeof_row));
278 const int sizeof_data = num_rows * sizeof_row;
279 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43280 str->reserve(sizeof_data);
281
[email protected]4ddaf2502008-10-23 18:26:19282 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43283 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19284}
285
[email protected]231d5a32008-09-13 00:45:27286//-----------------------------------------------------------------------------
287
288TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]af4876d2008-10-21 23:10:57289 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
290 CreateSession(), &mock_socket_factory));
[email protected]231d5a32008-09-13 00:45:27291}
292
293TEST_F(HttpNetworkTransactionTest, SimpleGET) {
294 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35295 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
296 MockRead("hello world"),
297 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27298 };
[email protected]231d5a32008-09-13 00:45:27299 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47300 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27301 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
302 EXPECT_EQ("hello world", out.response_data);
303}
304
305// Response with no status line.
306TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
307 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35308 MockRead("hello world"),
309 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27310 };
[email protected]231d5a32008-09-13 00:45:27311 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47312 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27313 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
314 EXPECT_EQ("hello world", out.response_data);
315}
316
317// Allow up to 4 bytes of junk to precede status line.
318TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
319 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35320 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
321 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27322 };
323 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47324 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27325 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
326 EXPECT_EQ("DATA", out.response_data);
327}
328
329// Allow up to 4 bytes of junk to precede status line.
330TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
331 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35332 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
333 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27334 };
335 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47336 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27337 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
338 EXPECT_EQ("DATA", out.response_data);
339}
340
341// Beyond 4 bytes of slop and it should fail to find a status line.
342TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
343 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35344 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
345 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27346 };
347 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47348 EXPECT_EQ(net::OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25349 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
350 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27351}
352
353// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
354TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
355 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35356 MockRead("\n"),
357 MockRead("\n"),
358 MockRead("Q"),
359 MockRead("J"),
360 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
361 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27362 };
363 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47364 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27365 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
366 EXPECT_EQ("DATA", out.response_data);
367}
368
369// Close the connection before enough bytes to have a status line.
370TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
371 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35372 MockRead("HTT"),
373 MockRead(false, net::OK),
[email protected]231d5a32008-09-13 00:45:27374 };
375 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47376 EXPECT_EQ(net::OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27377 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
378 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52379}
380
[email protected]f9d44aa2008-09-23 23:57:17381// Simulate a 204 response, lacking a Content-Length header, sent over a
382// persistent connection. The response should still terminate since a 204
383// cannot have a response body.
384TEST_F(HttpNetworkTransactionTest, StopsReading204) {
385 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35386 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
387 MockRead("junk"), // Should not be read!!
388 MockRead(false, net::OK),
[email protected]f9d44aa2008-09-23 23:57:17389 };
390 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]aecfbf22008-10-16 02:02:47391 EXPECT_EQ(net::OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17392 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
393 EXPECT_EQ("", out.response_data);
394}
395
initial.commit586acc5fe2008-07-26 22:42:52396TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
397 scoped_refptr<net::HttpNetworkSession> session = CreateSession();
398
399 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35400 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
401 MockRead("hello"),
402 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
403 MockRead("world"),
404 MockRead(false, net::OK),
initial.commit586acc5fe2008-07-26 22:42:52405 };
406 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52407 data.reads = data_reads;
408 mock_sockets[0] = &data;
409 mock_sockets[1] = NULL;
410
411 const char* kExpectedResponseData[] = {
412 "hello", "world"
413 };
414
415 for (int i = 0; i < 2; ++i) {
[email protected]af4876d2008-10-21 23:10:57416 scoped_ptr<net::HttpTransaction> trans(
417 new net::HttpNetworkTransaction(session, &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52418
419 net::HttpRequestInfo request;
420 request.method = "GET";
421 request.url = GURL("http://www.google.com/");
422 request.load_flags = 0;
423
424 TestCompletionCallback callback;
425
426 int rv = trans->Start(&request, &callback);
427 EXPECT_EQ(net::ERR_IO_PENDING, rv);
428
429 rv = callback.WaitForResult();
430 EXPECT_EQ(net::OK, rv);
431
432 const net::HttpResponseInfo* response = trans->GetResponseInfo();
433 EXPECT_TRUE(response != NULL);
434
435 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25436 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52437
438 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57439 rv = ReadTransaction(trans.get(), &response_data);
initial.commit586acc5fe2008-07-26 22:42:52440 EXPECT_EQ(net::OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25441 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52442 }
443}
444
445TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]af4876d2008-10-21 23:10:57446 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
447 CreateSession(), &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52448
449 net::HttpRequestInfo request;
450 request.method = "POST";
451 request.url = GURL("http://www.foo.com/");
452 request.upload_data = new net::UploadData;
453 request.upload_data->AppendBytes("foo", 3);
454 request.load_flags = 0;
455
456 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35457 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
458 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
459 MockRead("hello world"),
460 MockRead(false, net::OK),
initial.commit586acc5fe2008-07-26 22:42:52461 };
462 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52463 data.reads = data_reads;
464 mock_sockets[0] = &data;
465 mock_sockets[1] = NULL;
466
467 TestCompletionCallback callback;
468
469 int rv = trans->Start(&request, &callback);
470 EXPECT_EQ(net::ERR_IO_PENDING, rv);
471
472 rv = callback.WaitForResult();
473 EXPECT_EQ(net::OK, rv);
474
475 const net::HttpResponseInfo* response = trans->GetResponseInfo();
476 EXPECT_TRUE(response != NULL);
477
478 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25479 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52480
481 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57482 rv = ReadTransaction(trans.get(), &response_data);
initial.commit586acc5fe2008-07-26 22:42:52483 EXPECT_EQ(net::OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25484 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52485}
486
[email protected]3d2a59b2008-09-26 19:44:25487// read_failure specifies a read failure that should cause the network
488// transaction to resend the request.
489void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
490 const MockRead& read_failure) {
initial.commit586acc5fe2008-07-26 22:42:52491 scoped_refptr<net::HttpNetworkSession> session = CreateSession();
492
493 net::HttpRequestInfo request;
494 request.method = "GET";
495 request.url = GURL("http://www.foo.com/");
496 request.load_flags = 0;
497
498 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35499 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
500 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25501 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52502 };
503 MockSocket data1;
initial.commit586acc5fe2008-07-26 22:42:52504 data1.reads = data1_reads;
505 mock_sockets[0] = &data1;
506
507 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35508 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
509 MockRead("world"),
510 MockRead(true, net::OK),
initial.commit586acc5fe2008-07-26 22:42:52511 };
512 MockSocket data2;
initial.commit586acc5fe2008-07-26 22:42:52513 data2.reads = data2_reads;
514 mock_sockets[1] = &data2;
515
516 const char* kExpectedResponseData[] = {
517 "hello", "world"
518 };
519
520 for (int i = 0; i < 2; ++i) {
521 TestCompletionCallback callback;
522
[email protected]af4876d2008-10-21 23:10:57523 scoped_ptr<net::HttpTransaction> trans(
524 new net::HttpNetworkTransaction(session, &mock_socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52525
526 int rv = trans->Start(&request, &callback);
527 EXPECT_EQ(net::ERR_IO_PENDING, rv);
528
529 rv = callback.WaitForResult();
530 EXPECT_EQ(net::OK, rv);
531
532 const net::HttpResponseInfo* response = trans->GetResponseInfo();
533 EXPECT_TRUE(response != NULL);
534
535 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25536 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52537
538 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57539 rv = ReadTransaction(trans.get(), &response_data);
initial.commit586acc5fe2008-07-26 22:42:52540 EXPECT_EQ(net::OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25541 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52542 }
543}
[email protected]3d2a59b2008-09-26 19:44:25544
545TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]217e6022008-09-29 18:18:35546 MockRead read_failure(true, net::ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25547 KeepAliveConnectionResendRequestTest(read_failure);
548}
549
550TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]217e6022008-09-29 18:18:35551 MockRead read_failure(false, net::OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25552 KeepAliveConnectionResendRequestTest(read_failure);
553}
554
555TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]af4876d2008-10-21 23:10:57556 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
557 CreateSession(), &mock_socket_factory));
[email protected]3d2a59b2008-09-26 19:44:25558
559 net::HttpRequestInfo request;
560 request.method = "GET";
561 request.url = GURL("http://www.google.com/");
562 request.load_flags = 0;
563
564 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35565 MockRead(true, net::ERR_CONNECTION_RESET),
566 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
567 MockRead("hello world"),
568 MockRead(false, net::OK),
[email protected]3d2a59b2008-09-26 19:44:25569 };
570 MockSocket data;
[email protected]3d2a59b2008-09-26 19:44:25571 data.reads = data_reads;
572 mock_sockets[0] = &data;
573 mock_sockets[1] = NULL;
574
575 TestCompletionCallback callback;
576
577 int rv = trans->Start(&request, &callback);
578 EXPECT_EQ(net::ERR_IO_PENDING, rv);
579
580 rv = callback.WaitForResult();
581 EXPECT_EQ(net::ERR_CONNECTION_RESET, rv);
582
583 const net::HttpResponseInfo* response = trans->GetResponseInfo();
584 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25585}
586
587// What do various browsers do when the server closes a non-keepalive
588// connection without sending any response header or body?
589//
590// IE7: error page
591// Safari 3.1.2 (Windows): error page
592// Firefox 3.0.1: blank page
593// Opera 9.52: after five attempts, blank page
594// Us with WinHTTP: error page (net::ERR_INVALID_RESPONSE)
[email protected]aecfbf22008-10-16 02:02:47595// Us: error page (net::EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25596TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
597 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35598 MockRead(false, net::OK), // EOF
599 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
600 MockRead("hello world"),
601 MockRead(false, net::OK),
[email protected]3d2a59b2008-09-26 19:44:25602 };
603 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]0e75a732008-10-16 20:36:09604 EXPECT_EQ(net::ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25605}
[email protected]038e9a32008-10-08 22:40:16606
607// Test the request-challenge-retry sequence for basic auth.
608// (basic auth is the easiest to mock, because it has no randomness).
609TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]af4876d2008-10-21 23:10:57610 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
611 CreateSession(), &mock_socket_factory));
[email protected]038e9a32008-10-08 22:40:16612
613 net::HttpRequestInfo request;
614 request.method = "GET";
615 request.url = GURL("http://www.google.com/");
616 request.load_flags = 0;
617
618 MockRead data_reads1[] = {
619 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
620 // Give a couple authenticate options (only the middle one is actually
621 // supported).
[email protected]aaead502008-10-15 00:20:11622 MockRead("WWW-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16623 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
624 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
625 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
626 // Large content-length -- won't matter, as connection will be reset.
627 MockRead("Content-Length: 10000\r\n\r\n"),
628 MockRead(false, net::ERR_FAILED),
629 };
630
631 // After calling trans->RestartWithAuth(), this is the request we should
632 // be issuing -- the final header line contains the credentials.
633 MockWrite data_writes2[] = {
634 MockWrite("GET / HTTP/1.1\r\n"
635 "Host: www.google.com\r\n"
636 "Connection: keep-alive\r\n"
637 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
638 };
639
640 // Lastly, the server responds with the actual content.
641 MockRead data_reads2[] = {
642 MockRead("HTTP/1.0 200 OK\r\n"),
643 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
644 MockRead("Content-Length: 100\r\n\r\n"),
645 MockRead(false, net::OK),
646 };
647
648 MockSocket data1;
649 data1.reads = data_reads1;
650 MockSocket data2;
651 data2.reads = data_reads2;
652 data2.writes = data_writes2;
653 mock_sockets[0] = &data1;
654 mock_sockets[1] = &data2;
655 mock_sockets[2] = NULL;
656
657 TestCompletionCallback callback1;
658
659 int rv = trans->Start(&request, &callback1);
660 EXPECT_EQ(net::ERR_IO_PENDING, rv);
661
662 rv = callback1.WaitForResult();
663 EXPECT_EQ(net::OK, rv);
664
665 const net::HttpResponseInfo* response = trans->GetResponseInfo();
666 EXPECT_FALSE(response == NULL);
667
668 // The password prompt info should have been set in response->auth_challenge.
669 EXPECT_FALSE(response->auth_challenge.get() == NULL);
670
671 // TODO(eroman): this should really include the effective port (80)
672 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
673 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
674 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
675
676 TestCompletionCallback callback2;
677
678 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
679 EXPECT_EQ(net::ERR_IO_PENDING, rv);
680
681 rv = callback2.WaitForResult();
682 EXPECT_EQ(net::OK, rv);
683
684 response = trans->GetResponseInfo();
685 EXPECT_FALSE(response == NULL);
686 EXPECT_TRUE(response->auth_challenge.get() == NULL);
687 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16688}
689
690// Test the flow when both the proxy server AND origin server require
691// authentication. Again, this uses basic auth for both since that is
692// the simplest to mock.
693TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
694 net::ProxyInfo proxy_info;
695 proxy_info.UseNamedProxy("myproxy:70");
696
697 // Configure against proxy server "myproxy:70".
[email protected]af4876d2008-10-21 23:10:57698 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
[email protected]038e9a32008-10-08 22:40:16699 CreateSession(new net::ProxyResolverFixed(proxy_info)),
[email protected]af4876d2008-10-21 23:10:57700 &mock_socket_factory));
[email protected]038e9a32008-10-08 22:40:16701
702 net::HttpRequestInfo request;
703 request.method = "GET";
704 request.url = GURL("http://www.google.com/");
705 request.load_flags = 0;
706
707 MockRead data_reads1[] = {
708 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
709 // Give a couple authenticate options (only the middle one is actually
710 // supported).
[email protected]aaead502008-10-15 00:20:11711 MockRead("Proxy-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16712 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
713 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
714 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
715 // Large content-length -- won't matter, as connection will be reset.
716 MockRead("Content-Length: 10000\r\n\r\n"),
717 MockRead(false, net::ERR_FAILED),
718 };
719
720 // After calling trans->RestartWithAuth() the first time, this is the
721 // request we should be issuing -- the final header line contains the
722 // proxy's credentials.
723 MockWrite data_writes2[] = {
724 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
725 "Host: www.google.com\r\n"
726 "Proxy-Connection: keep-alive\r\n"
727 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
728 };
729
730 // Now the proxy server lets the request pass through to origin server.
731 // The origin server responds with a 401.
732 MockRead data_reads2[] = {
733 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
734 // Note: We are using the same realm-name as the proxy server. This is
735 // completely valid, as realms are unique across hosts.
736 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
737 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
738 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]aaead502008-10-15 00:20:11739 MockRead(false, net::ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:16740 };
741
742 // After calling trans->RestartWithAuth() the second time, we should send
743 // the credentials for both the proxy and origin server.
744 MockWrite data_writes3[] = {
745 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
746 "Host: www.google.com\r\n"
747 "Proxy-Connection: keep-alive\r\n"
748 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
749 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
750 };
751
752 // Lastly we get the desired content.
753 MockRead data_reads3[] = {
754 MockRead("HTTP/1.0 200 OK\r\n"),
755 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
756 MockRead("Content-Length: 100\r\n\r\n"),
757 MockRead(false, net::OK),
758 };
759
760 MockSocket data1;
761 data1.reads = data_reads1;
762 MockSocket data2;
763 data2.reads = data_reads2;
764 data2.writes = data_writes2;
765 MockSocket data3;
766 data3.reads = data_reads3;
767 data3.writes = data_writes3;
768 mock_sockets[0] = &data1;
769 mock_sockets[1] = &data2;
770 mock_sockets[2] = &data3;
771 mock_sockets[3] = NULL;
772
773 TestCompletionCallback callback1;
774
775 int rv = trans->Start(&request, &callback1);
776 EXPECT_EQ(net::ERR_IO_PENDING, rv);
777
778 rv = callback1.WaitForResult();
779 EXPECT_EQ(net::OK, rv);
780
781 const net::HttpResponseInfo* response = trans->GetResponseInfo();
782 EXPECT_FALSE(response == NULL);
783
784 // The password prompt info should have been set in response->auth_challenge.
785 EXPECT_FALSE(response->auth_challenge.get() == NULL);
786
787 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host);
788 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
789 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
790
791 TestCompletionCallback callback2;
792
793 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
794 EXPECT_EQ(net::ERR_IO_PENDING, rv);
795
796 rv = callback2.WaitForResult();
797 EXPECT_EQ(net::OK, rv);
798
799 response = trans->GetResponseInfo();
800 EXPECT_FALSE(response == NULL);
801 EXPECT_FALSE(response->auth_challenge.get() == NULL);
802
803 // TODO(eroman): this should really include the effective port (80)
804 EXPECT_EQ(L"www.google.com", response->auth_challenge->host);
805 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
806 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
807
808 TestCompletionCallback callback3;
809
810 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
811 EXPECT_EQ(net::ERR_IO_PENDING, rv);
812
813 rv = callback3.WaitForResult();
814 EXPECT_EQ(net::OK, rv);
815
816 response = trans->GetResponseInfo();
817 EXPECT_TRUE(response->auth_challenge.get() == NULL);
818 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16819}
[email protected]4ddaf2502008-10-23 18:26:19820
821// Test reading a server response which has only headers, and no body.
822// After some maximum number of bytes is consumed, the transaction should
823// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
824TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
825 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
826 CreateSession(), &mock_socket_factory));
827
828 net::HttpRequestInfo request;
829 request.method = "GET";
830 request.url = GURL("http://www.google.com/");
831 request.load_flags = 0;
832
833 // Respond with 50 kb of headers (we should fail after 32 kb).
[email protected]15a5ccf82008-10-23 19:57:43834 std::string large_headers_string;
835 FillLargeHeadersString(&large_headers_string, 50 * 1024);
[email protected]4ddaf2502008-10-23 18:26:19836
837 MockRead data_reads[] = {
838 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:43839 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:19840 MockRead("\r\nBODY"),
841 MockRead(false, net::OK),
842 };
843 MockSocket data;
844 data.reads = data_reads;
845 mock_sockets[0] = &data;
846 mock_sockets[1] = NULL;
847
848 TestCompletionCallback callback;
849
850 int rv = trans->Start(&request, &callback);
851 EXPECT_EQ(net::ERR_IO_PENDING, rv);
852
853 rv = callback.WaitForResult();
854 EXPECT_EQ(net::ERR_RESPONSE_HEADERS_TOO_BIG, rv);
855
856 const net::HttpResponseInfo* response = trans->GetResponseInfo();
857 EXPECT_TRUE(response == NULL);
858}