blob: 852612f77e9d6bebae676e9629cb2ca9a10f63fb [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"
[email protected]bacff652009-03-31 17:50:339#include "net/base/completion_callback.h"
[email protected]9172a982009-06-06 00:30:2510#include "net/base/host_resolver_unittest.h"
[email protected]ff007e162009-05-23 09:13:1511#include "net/base/socket_test_util.h"
[email protected]bacff652009-03-31 17:50:3312#include "net/base/ssl_client_socket.h"
13#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5214#include "net/base/test_completion_callback.h"
15#include "net/base/upload_data.h"
[email protected]385a4672009-03-11 22:21:2916#include "net/http/http_auth_handler_ntlm.h"
initial.commit586acc5fe2008-07-26 22:42:5217#include "net/http/http_network_session.h"
18#include "net/http/http_network_transaction.h"
19#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5320#include "net/proxy/proxy_config_service_fixed.h"
initial.commit586acc5fe2008-07-26 22:42:5221#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1522#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5223
24//-----------------------------------------------------------------------------
25
[email protected]89ceba9a2009-03-21 03:46:0626namespace net {
27
[email protected]db8f44c2008-12-13 04:52:0128// Create a proxy service which fails on all requests (falls back to direct).
[email protected]1c773ea12009-04-28 19:58:4229ProxyService* CreateNullProxyService() {
30 return ProxyService::CreateNull();
initial.commit586acc5fe2008-07-26 22:42:5231}
32
[email protected]e44de5d2009-06-05 20:12:4533// Helper to manage the lifetimes of the dependencies for a
34// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5935class SessionDependencies {
36 public:
37 // Default set of dependencies -- "null" proxy service.
38 SessionDependencies() : proxy_service(CreateNullProxyService()) {}
39
40 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4541 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]228ff742009-06-05 01:19:5942 : proxy_service(proxy_service) {}
43
44 scoped_ptr<ProxyService> proxy_service;
45 MockClientSocketFactory socket_factory;
46};
47
[email protected]1c773ea12009-04-28 19:58:4248ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5049 net::ProxyConfig proxy_config;
50 proxy_config.proxy_rules.ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3951 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5352}
53
54
[email protected]228ff742009-06-05 01:19:5955HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
56 return new HttpNetworkSession(session_deps->proxy_service.get(),
57 &session_deps->socket_factory);
[email protected]e8d536192008-10-17 22:21:1458}
59
[email protected]89836e22008-09-25 20:33:4260class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5261 public:
[email protected]0e75a732008-10-16 20:36:0962 virtual void TearDown() {
63 // Empty the current queue.
64 MessageLoop::current()->RunAllPending();
65 PlatformTest::TearDown();
66 }
67
[email protected]3d2a59b2008-09-26 19:44:2568 protected:
69 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5270
[email protected]ff007e162009-05-23 09:13:1571 struct SimpleGetHelperResult {
72 int rv;
73 std::string status_line;
74 std::string response_data;
75 };
initial.commit586acc5fe2008-07-26 22:42:5276
[email protected]ff007e162009-05-23 09:13:1577 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
78 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:5279
[email protected]228ff742009-06-05 01:19:5980 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:4081 scoped_ptr<HttpTransaction> trans(
82 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:5983 CreateSession(&session_deps),
84 &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:5285
[email protected]ff007e162009-05-23 09:13:1586 HttpRequestInfo request;
87 request.method = "GET";
88 request.url = GURL("http://www.google.com/");
89 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:5290
[email protected]ff007e162009-05-23 09:13:1591 MockSocket data;
92 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:5993 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:5294
[email protected]ff007e162009-05-23 09:13:1595 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:5296
[email protected]ff007e162009-05-23 09:13:1597 int rv = trans->Start(&request, &callback);
98 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:5299
[email protected]ff007e162009-05-23 09:13:15100 out.rv = callback.WaitForResult();
101 if (out.rv != OK)
102 return out;
103
104 const HttpResponseInfo* response = trans->GetResponseInfo();
105 EXPECT_TRUE(response != NULL);
106
107 EXPECT_TRUE(response->headers != NULL);
108 out.status_line = response->headers->GetStatusLine();
109
110 rv = ReadTransaction(trans.get(), &out.response_data);
111 EXPECT_EQ(OK, rv);
112
[email protected]aecfbf22008-10-16 02:02:47113 return out;
[email protected]ff007e162009-05-23 09:13:15114 }
initial.commit586acc5fe2008-07-26 22:42:52115
[email protected]ff007e162009-05-23 09:13:15116 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
117 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52118
[email protected]ff007e162009-05-23 09:13:15119 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15120};
[email protected]231d5a32008-09-13 00:45:27121
[email protected]15a5ccf82008-10-23 19:57:43122// Fill |str| with a long header list that consumes >= |size| bytes.
123void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19124 const char* row =
125 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
126 const int sizeof_row = strlen(row);
127 const int num_rows = static_cast<int>(
128 ceil(static_cast<float>(size) / sizeof_row));
129 const int sizeof_data = num_rows * sizeof_row;
130 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43131 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51132
[email protected]4ddaf2502008-10-23 18:26:19133 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43134 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19135}
136
[email protected]385a4672009-03-11 22:21:29137// Alternative functions that eliminate randomness and dependency on the local
138// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20139void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29140 static const uint8 bytes[] = {
141 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
142 };
143 static size_t current_byte = 0;
144 for (size_t i = 0; i < n; ++i) {
145 output[i] = bytes[current_byte++];
146 current_byte %= arraysize(bytes);
147 }
148}
149
[email protected]fe2bc6a2009-03-23 16:52:20150void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29151 static const uint8 bytes[] = {
152 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
153 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
154 };
155 static size_t current_byte = 0;
156 for (size_t i = 0; i < n; ++i) {
157 output[i] = bytes[current_byte++];
158 current_byte %= arraysize(bytes);
159 }
160}
161
[email protected]fe2bc6a2009-03-23 16:52:20162std::string MockGetHostName() {
163 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29164}
165
[email protected]231d5a32008-09-13 00:45:27166//-----------------------------------------------------------------------------
167
168TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59169 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40170 scoped_ptr<HttpTransaction> trans(
171 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59172 CreateSession(&session_deps),
173 &session_deps.socket_factory));
[email protected]231d5a32008-09-13 00:45:27174}
175
176TEST_F(HttpNetworkTransactionTest, SimpleGET) {
177 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35178 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
179 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42180 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27181 };
[email protected]231d5a32008-09-13 00:45:27182 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42183 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27184 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
185 EXPECT_EQ("hello world", out.response_data);
186}
187
188// Response with no status line.
189TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
190 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35191 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42192 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27193 };
[email protected]231d5a32008-09-13 00:45:27194 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42195 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27196 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
197 EXPECT_EQ("hello world", out.response_data);
198}
199
200// Allow up to 4 bytes of junk to precede status line.
201TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
202 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35203 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42204 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27205 };
206 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42207 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27208 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
209 EXPECT_EQ("DATA", out.response_data);
210}
211
212// Allow up to 4 bytes of junk to precede status line.
213TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
214 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35215 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42216 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27217 };
218 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42219 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27220 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
221 EXPECT_EQ("DATA", out.response_data);
222}
223
224// Beyond 4 bytes of slop and it should fail to find a status line.
225TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
226 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35227 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42228 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27229 };
230 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42231 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25232 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
233 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27234}
235
236// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
237TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
238 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35239 MockRead("\n"),
240 MockRead("\n"),
241 MockRead("Q"),
242 MockRead("J"),
243 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42244 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27245 };
246 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42247 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27248 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
249 EXPECT_EQ("DATA", out.response_data);
250}
251
252// Close the connection before enough bytes to have a status line.
253TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
254 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35255 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42256 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27257 };
258 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42259 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27260 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
261 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52262}
263
[email protected]f9d44aa2008-09-23 23:57:17264// Simulate a 204 response, lacking a Content-Length header, sent over a
265// persistent connection. The response should still terminate since a 204
266// cannot have a response body.
267TEST_F(HttpNetworkTransactionTest, StopsReading204) {
268 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35269 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
270 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42271 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17272 };
273 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42274 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17275 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
276 EXPECT_EQ("", out.response_data);
277}
278
[email protected]ef0faf2e72009-03-05 23:27:23279// Do a request using the HEAD method. Verify that we don't try to read the
280// message body (since HEAD has none).
281TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59282 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40283 scoped_ptr<HttpTransaction> trans(
284 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59285 CreateSession(&session_deps),
286 &session_deps.socket_factory));
[email protected]ef0faf2e72009-03-05 23:27:23287
[email protected]1c773ea12009-04-28 19:58:42288 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23289 request.method = "HEAD";
290 request.url = GURL("http://www.google.com/");
291 request.load_flags = 0;
292
293 MockWrite data_writes1[] = {
294 MockWrite("HEAD / HTTP/1.1\r\n"
295 "Host: www.google.com\r\n"
296 "Connection: keep-alive\r\n"
297 "Content-Length: 0\r\n\r\n"),
298 };
299 MockRead data_reads1[] = {
300 MockRead("HTTP/1.1 404 Not Found\r\n"),
301 MockRead("Server: Blah\r\n"),
302 MockRead("Content-Length: 1234\r\n\r\n"),
303
304 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42305 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23306 };
307
308 MockSocket data1;
309 data1.reads = data_reads1;
310 data1.writes = data_writes1;
[email protected]228ff742009-06-05 01:19:59311 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23312
313 TestCompletionCallback callback1;
314
315 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42316 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23317
318 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42319 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23320
[email protected]1c773ea12009-04-28 19:58:42321 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23322 EXPECT_FALSE(response == NULL);
323
324 // Check that the headers got parsed.
325 EXPECT_TRUE(response->headers != NULL);
326 EXPECT_EQ(1234, response->headers->GetContentLength());
327 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
328
329 std::string server_header;
330 void* iter = NULL;
331 bool has_server_header = response->headers->EnumerateHeader(
332 &iter, "Server", &server_header);
333 EXPECT_TRUE(has_server_header);
334 EXPECT_EQ("Blah", server_header);
335
336 // Reading should give EOF right away, since there is no message body
337 // (despite non-zero content-length).
338 std::string response_data;
339 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42340 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23341 EXPECT_EQ("", response_data);
342}
343
initial.commit586acc5fe2008-07-26 22:42:52344TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59345 SessionDependencies session_deps;
346 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52347
348 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35349 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
350 MockRead("hello"),
351 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
352 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42353 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52354 };
355 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52356 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:59357 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52358
359 const char* kExpectedResponseData[] = {
360 "hello", "world"
361 };
362
363 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42364 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:59365 new HttpNetworkTransaction(session, &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52366
[email protected]1c773ea12009-04-28 19:58:42367 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52368 request.method = "GET";
369 request.url = GURL("http://www.google.com/");
370 request.load_flags = 0;
371
372 TestCompletionCallback callback;
373
374 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42375 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52376
377 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42378 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52379
[email protected]1c773ea12009-04-28 19:58:42380 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52381 EXPECT_TRUE(response != NULL);
382
383 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25384 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52385
386 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57387 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42388 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25389 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52390 }
391}
392
393TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59394 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40395 scoped_ptr<HttpTransaction> trans(
396 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59397 CreateSession(&session_deps),
398 &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52399
[email protected]1c773ea12009-04-28 19:58:42400 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52401 request.method = "POST";
402 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42403 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52404 request.upload_data->AppendBytes("foo", 3);
405 request.load_flags = 0;
406
407 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35408 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
409 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
410 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42411 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52412 };
413 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52414 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:59415 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52416
417 TestCompletionCallback callback;
418
419 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42420 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52421
422 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42423 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52424
[email protected]1c773ea12009-04-28 19:58:42425 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52426 EXPECT_TRUE(response != NULL);
427
428 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25429 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52430
431 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57432 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42433 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25434 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52435}
436
[email protected]3a2d3662009-03-27 03:49:14437// This test is almost the same as Ignores100 above, but the response contains
438// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
439// HTTP/1.1.
440TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59441 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40442 scoped_ptr<HttpTransaction> trans(
443 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59444 CreateSession(&session_deps),
445 &session_deps.socket_factory));
[email protected]3a2d3662009-03-27 03:49:14446
[email protected]1c773ea12009-04-28 19:58:42447 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14448 request.method = "GET";
449 request.url = GURL("http://www.foo.com/");
450 request.load_flags = 0;
451
452 MockRead data_reads[] = {
453 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"),
454 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
455 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42456 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14457 };
458 MockSocket data;
459 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:59460 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3a2d3662009-03-27 03:49:14461
462 TestCompletionCallback callback;
463
464 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42465 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14466
467 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42468 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14469
[email protected]1c773ea12009-04-28 19:58:42470 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14471 EXPECT_TRUE(response != NULL);
472
473 EXPECT_TRUE(response->headers != NULL);
474 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
475
476 std::string response_data;
477 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42478 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14479 EXPECT_EQ("hello world", response_data);
480}
481
[email protected]3d2a59b2008-09-26 19:44:25482// read_failure specifies a read failure that should cause the network
483// transaction to resend the request.
484void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
485 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59486 SessionDependencies session_deps;
487 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52488
[email protected]1c773ea12009-04-28 19:58:42489 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52490 request.method = "GET";
491 request.url = GURL("http://www.foo.com/");
492 request.load_flags = 0;
493
494 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35495 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
496 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25497 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52498 };
499 MockSocket data1;
initial.commit586acc5fe2008-07-26 22:42:52500 data1.reads = data1_reads;
[email protected]228ff742009-06-05 01:19:59501 session_deps.socket_factory.AddMockSocket(&data1);
initial.commit586acc5fe2008-07-26 22:42:52502
503 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35504 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
505 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42506 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52507 };
508 MockSocket data2;
initial.commit586acc5fe2008-07-26 22:42:52509 data2.reads = data2_reads;
[email protected]228ff742009-06-05 01:19:59510 session_deps.socket_factory.AddMockSocket(&data2);
initial.commit586acc5fe2008-07-26 22:42:52511
512 const char* kExpectedResponseData[] = {
513 "hello", "world"
514 };
515
516 for (int i = 0; i < 2; ++i) {
517 TestCompletionCallback callback;
518
[email protected]1c773ea12009-04-28 19:58:42519 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:59520 new HttpNetworkTransaction(session, &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52521
522 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42523 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52524
525 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42526 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52527
[email protected]1c773ea12009-04-28 19:58:42528 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52529 EXPECT_TRUE(response != NULL);
530
531 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25532 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52533
534 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57535 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42536 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25537 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52538 }
539}
[email protected]3d2a59b2008-09-26 19:44:25540
541TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42542 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25543 KeepAliveConnectionResendRequestTest(read_failure);
544}
545
546TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42547 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25548 KeepAliveConnectionResendRequestTest(read_failure);
549}
550
551TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59552 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40553 scoped_ptr<HttpTransaction> trans(
554 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59555 CreateSession(&session_deps),
556 &session_deps.socket_factory));
[email protected]3d2a59b2008-09-26 19:44:25557
[email protected]1c773ea12009-04-28 19:58:42558 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25559 request.method = "GET";
560 request.url = GURL("http://www.google.com/");
561 request.load_flags = 0;
562
563 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42564 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35565 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
566 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42567 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25568 };
569 MockSocket data;
[email protected]3d2a59b2008-09-26 19:44:25570 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:59571 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3d2a59b2008-09-26 19:44:25572
573 TestCompletionCallback callback;
574
575 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42576 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25577
578 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42579 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25580
[email protected]1c773ea12009-04-28 19:58:42581 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25582 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25583}
584
585// What do various browsers do when the server closes a non-keepalive
586// connection without sending any response header or body?
587//
588// IE7: error page
589// Safari 3.1.2 (Windows): error page
590// Firefox 3.0.1: blank page
591// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42592// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
593// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25594TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
595 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42596 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35597 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
598 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42599 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25600 };
601 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42602 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25603}
[email protected]038e9a32008-10-08 22:40:16604
605// Test the request-challenge-retry sequence for basic auth.
606// (basic auth is the easiest to mock, because it has no randomness).
607TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59608 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40609 scoped_ptr<HttpTransaction> trans(
610 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59611 CreateSession(&session_deps),
612 &session_deps.socket_factory));
[email protected]038e9a32008-10-08 22:40:16613
[email protected]1c773ea12009-04-28 19:58:42614 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16615 request.method = "GET";
616 request.url = GURL("http://www.google.com/");
617 request.load_flags = 0;
618
[email protected]f9ee6b52008-11-08 06:46:23619 MockWrite data_writes1[] = {
620 MockWrite("GET / HTTP/1.1\r\n"
621 "Host: www.google.com\r\n"
622 "Connection: keep-alive\r\n\r\n"),
623 };
624
[email protected]038e9a32008-10-08 22:40:16625 MockRead data_reads1[] = {
626 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
627 // Give a couple authenticate options (only the middle one is actually
628 // supported).
[email protected]aaead502008-10-15 00:20:11629 MockRead("WWW-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16630 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
631 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
632 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
633 // Large content-length -- won't matter, as connection will be reset.
634 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42635 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16636 };
637
638 // After calling trans->RestartWithAuth(), this is the request we should
639 // be issuing -- the final header line contains the credentials.
640 MockWrite data_writes2[] = {
641 MockWrite("GET / HTTP/1.1\r\n"
642 "Host: www.google.com\r\n"
643 "Connection: keep-alive\r\n"
644 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
645 };
646
647 // Lastly, the server responds with the actual content.
648 MockRead data_reads2[] = {
649 MockRead("HTTP/1.0 200 OK\r\n"),
650 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
651 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42652 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16653 };
654
655 MockSocket data1;
656 data1.reads = data_reads1;
[email protected]f9ee6b52008-11-08 06:46:23657 data1.writes = data_writes1;
[email protected]038e9a32008-10-08 22:40:16658 MockSocket data2;
659 data2.reads = data_reads2;
660 data2.writes = data_writes2;
[email protected]228ff742009-06-05 01:19:59661 session_deps.socket_factory.AddMockSocket(&data1);
662 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]038e9a32008-10-08 22:40:16663
664 TestCompletionCallback callback1;
665
666 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42667 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16668
669 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42670 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16671
[email protected]1c773ea12009-04-28 19:58:42672 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16673 EXPECT_FALSE(response == NULL);
674
675 // The password prompt info should have been set in response->auth_challenge.
676 EXPECT_FALSE(response->auth_challenge.get() == NULL);
677
[email protected]71e4573a2009-05-21 22:03:00678 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16679 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
680 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
681
682 TestCompletionCallback callback2;
683
684 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42685 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16686
687 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42688 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16689
690 response = trans->GetResponseInfo();
691 EXPECT_FALSE(response == NULL);
692 EXPECT_TRUE(response->auth_challenge.get() == NULL);
693 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16694}
695
[email protected]2d2697f92009-02-18 21:00:32696// Test the request-challenge-retry sequence for basic auth, over a keep-alive
697// connection.
698TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59699 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40700 scoped_ptr<HttpTransaction> trans(
701 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59702 CreateSession(&session_deps),
703 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32704
[email protected]1c773ea12009-04-28 19:58:42705 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32706 request.method = "GET";
707 request.url = GURL("http://www.google.com/");
708 request.load_flags = 0;
709
710 MockWrite data_writes1[] = {
711 MockWrite("GET / HTTP/1.1\r\n"
712 "Host: www.google.com\r\n"
713 "Connection: keep-alive\r\n\r\n"),
714
715 // After calling trans->RestartWithAuth(), this is the request we should
716 // be issuing -- the final header line contains the credentials.
717 MockWrite("GET / HTTP/1.1\r\n"
718 "Host: www.google.com\r\n"
719 "Connection: keep-alive\r\n"
720 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
721 };
722
723 MockRead data_reads1[] = {
724 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
725 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
726 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
727 MockRead("Content-Length: 14\r\n\r\n"),
728 MockRead("Unauthorized\r\n"),
729
730 // Lastly, the server responds with the actual content.
731 MockRead("HTTP/1.1 200 OK\r\n"),
732 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
733 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42734 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32735 };
736
737 MockSocket data1;
738 data1.reads = data_reads1;
739 data1.writes = data_writes1;
[email protected]228ff742009-06-05 01:19:59740 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32741
742 TestCompletionCallback callback1;
743
744 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42745 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32746
747 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42748 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32749
[email protected]1c773ea12009-04-28 19:58:42750 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32751 EXPECT_FALSE(response == NULL);
752
753 // The password prompt info should have been set in response->auth_challenge.
754 EXPECT_FALSE(response->auth_challenge.get() == NULL);
755
[email protected]71e4573a2009-05-21 22:03:00756 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32757 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
758 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
759
760 TestCompletionCallback callback2;
761
762 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42763 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32764
765 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42766 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32767
768 response = trans->GetResponseInfo();
769 EXPECT_FALSE(response == NULL);
770 EXPECT_TRUE(response->auth_challenge.get() == NULL);
771 EXPECT_EQ(100, response->headers->GetContentLength());
772}
773
774// Test the request-challenge-retry sequence for basic auth, over a keep-alive
775// connection and with no response body to drain.
776TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59777 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40778 scoped_ptr<HttpTransaction> trans(
779 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59780 CreateSession(&session_deps),
781 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32782
[email protected]1c773ea12009-04-28 19:58:42783 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32784 request.method = "GET";
785 request.url = GURL("http://www.google.com/");
786 request.load_flags = 0;
787
788 MockWrite data_writes1[] = {
789 MockWrite("GET / HTTP/1.1\r\n"
790 "Host: www.google.com\r\n"
791 "Connection: keep-alive\r\n\r\n"),
792
793 // After calling trans->RestartWithAuth(), this is the request we should
794 // be issuing -- the final header line contains the credentials.
795 MockWrite("GET / HTTP/1.1\r\n"
796 "Host: www.google.com\r\n"
797 "Connection: keep-alive\r\n"
798 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
799 };
800
801 // Respond with 5 kb of response body.
802 std::string large_body_string("Unauthorized");
803 large_body_string.append(5 * 1024, ' ');
804 large_body_string.append("\r\n");
805
806 MockRead data_reads1[] = {
807 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
808 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
809 MockRead("Content-Length: 0\r\n\r\n"),
810
811 // Lastly, the server responds with the actual content.
812 MockRead("HTTP/1.1 200 OK\r\n"),
813 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
814 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42815 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32816 };
817
818 MockSocket data1;
819 data1.reads = data_reads1;
820 data1.writes = data_writes1;
[email protected]228ff742009-06-05 01:19:59821 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32822
823 TestCompletionCallback callback1;
824
825 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42826 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32827
828 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42829 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32830
[email protected]1c773ea12009-04-28 19:58:42831 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32832 EXPECT_FALSE(response == NULL);
833
834 // The password prompt info should have been set in response->auth_challenge.
835 EXPECT_FALSE(response->auth_challenge.get() == NULL);
836
[email protected]71e4573a2009-05-21 22:03:00837 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32838 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
839 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
840
841 TestCompletionCallback callback2;
842
843 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42844 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32845
846 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42847 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32848
849 response = trans->GetResponseInfo();
850 EXPECT_FALSE(response == NULL);
851 EXPECT_TRUE(response->auth_challenge.get() == NULL);
852 EXPECT_EQ(100, response->headers->GetContentLength());
853}
854
855// Test the request-challenge-retry sequence for basic auth, over a keep-alive
856// connection and with a large response body to drain.
857TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:59858 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40859 scoped_ptr<HttpTransaction> trans(
860 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59861 CreateSession(&session_deps),
862 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32863
[email protected]1c773ea12009-04-28 19:58:42864 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32865 request.method = "GET";
866 request.url = GURL("http://www.google.com/");
867 request.load_flags = 0;
868
869 MockWrite data_writes1[] = {
870 MockWrite("GET / HTTP/1.1\r\n"
871 "Host: www.google.com\r\n"
872 "Connection: keep-alive\r\n\r\n"),
873
874 // After calling trans->RestartWithAuth(), this is the request we should
875 // be issuing -- the final header line contains the credentials.
876 MockWrite("GET / HTTP/1.1\r\n"
877 "Host: www.google.com\r\n"
878 "Connection: keep-alive\r\n"
879 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
880 };
881
882 // Respond with 5 kb of response body.
883 std::string large_body_string("Unauthorized");
884 large_body_string.append(5 * 1024, ' ');
885 large_body_string.append("\r\n");
886
887 MockRead data_reads1[] = {
888 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
889 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
890 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
891 // 5134 = 12 + 5 * 1024 + 2
892 MockRead("Content-Length: 5134\r\n\r\n"),
893 MockRead(true, large_body_string.data(), large_body_string.size()),
894
895 // Lastly, the server responds with the actual content.
896 MockRead("HTTP/1.1 200 OK\r\n"),
897 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
898 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42899 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32900 };
901
902 MockSocket data1;
903 data1.reads = data_reads1;
904 data1.writes = data_writes1;
[email protected]228ff742009-06-05 01:19:59905 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32906
907 TestCompletionCallback callback1;
908
909 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42910 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32911
912 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42913 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32914
[email protected]1c773ea12009-04-28 19:58:42915 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32916 EXPECT_FALSE(response == NULL);
917
918 // The password prompt info should have been set in response->auth_challenge.
919 EXPECT_FALSE(response->auth_challenge.get() == NULL);
920
[email protected]71e4573a2009-05-21 22:03:00921 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32922 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
923 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
924
925 TestCompletionCallback callback2;
926
927 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42928 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32929
930 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42931 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32932
933 response = trans->GetResponseInfo();
934 EXPECT_FALSE(response == NULL);
935 EXPECT_TRUE(response->auth_challenge.get() == NULL);
936 EXPECT_EQ(100, response->headers->GetContentLength());
937}
938
939// Test the request-challenge-retry sequence for basic auth, over a keep-alive
940// proxy connection, when setting up an SSL tunnel.
941TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
942 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:59943 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
944 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:32945
[email protected]1c773ea12009-04-28 19:58:42946 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59947 session.get(), &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32948
[email protected]1c773ea12009-04-28 19:58:42949 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32950 request.method = "GET";
951 request.url = GURL("https://www.google.com/");
952 request.load_flags = 0;
953
954 // Since we have proxy, should try to establish tunnel.
955 MockWrite data_writes1[] = {
956 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:45957 "Host: www.google.com\r\n"
958 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:32959
960 // After calling trans->RestartWithAuth(), this is the request we should
961 // be issuing -- the final header line contains the credentials.
962 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
963 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:45964 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:32965 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
966 };
967
968 // The proxy responds to the connect with a 407, using a persistent
969 // connection.
970 MockRead data_reads1[] = {
971 // No credentials.
972 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
973 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
974 MockRead("Content-Length: 10\r\n\r\n"),
975 MockRead("0123456789"),
976
977 // Wrong credentials (wrong password).
978 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
979 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
980 MockRead("Content-Length: 10\r\n\r\n"),
981 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42982 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:32983 };
984
985 MockSocket data1;
986 data1.writes = data_writes1;
987 data1.reads = data_reads1;
[email protected]228ff742009-06-05 01:19:59988 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32989
990 TestCompletionCallback callback1;
991
992 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42993 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32994
995 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42996 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32997
[email protected]1c773ea12009-04-28 19:58:42998 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32999 EXPECT_FALSE(response == NULL);
1000
1001 EXPECT_TRUE(response->headers->IsKeepAlive());
1002 EXPECT_EQ(407, response->headers->response_code());
1003 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421004 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321005
1006 // The password prompt info should have been set in response->auth_challenge.
1007 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1008
[email protected]71e4573a2009-05-21 22:03:001009 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321010 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1011 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1012
1013 TestCompletionCallback callback2;
1014
1015 // Wrong password (should be "bar").
1016 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421017 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321018
1019 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421020 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321021
1022 response = trans->GetResponseInfo();
1023 EXPECT_FALSE(response == NULL);
1024
1025 EXPECT_TRUE(response->headers->IsKeepAlive());
1026 EXPECT_EQ(407, response->headers->response_code());
1027 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421028 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321029
1030 // The password prompt info should have been set in response->auth_challenge.
1031 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1032
[email protected]71e4573a2009-05-21 22:03:001033 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321034 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1035 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1036}
1037
[email protected]a8e9b162009-03-12 00:06:441038// Test that we don't read the response body when we fail to establish a tunnel,
1039// even if the user cancels the proxy's auth attempt.
1040TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1041 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591042 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441043
[email protected]e44de5d2009-06-05 20:12:451044 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441045
[email protected]1c773ea12009-04-28 19:58:421046 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591047 session.get(), &session_deps.socket_factory));
[email protected]a8e9b162009-03-12 00:06:441048
[email protected]1c773ea12009-04-28 19:58:421049 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441050 request.method = "GET";
1051 request.url = GURL("https://www.google.com/");
1052 request.load_flags = 0;
1053
1054 // Since we have proxy, should try to establish tunnel.
1055 MockWrite data_writes[] = {
1056 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451057 "Host: www.google.com\r\n"
1058 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441059 };
1060
1061 // The proxy responds to the connect with a 407.
1062 MockRead data_reads[] = {
1063 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1064 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1065 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421066 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441067 };
1068
1069 MockSocket data;
1070 data.writes = data_writes;
1071 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:591072 session_deps.socket_factory.AddMockSocket(&data);
[email protected]a8e9b162009-03-12 00:06:441073
1074 TestCompletionCallback callback;
1075
1076 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421077 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441078
1079 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421080 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441081
[email protected]1c773ea12009-04-28 19:58:421082 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441083 EXPECT_FALSE(response == NULL);
1084
1085 EXPECT_TRUE(response->headers->IsKeepAlive());
1086 EXPECT_EQ(407, response->headers->response_code());
1087 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421088 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441089
1090 std::string response_data;
1091 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421092 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441093}
1094
[email protected]ff007e162009-05-23 09:13:151095void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081096 const MockRead& status, int expected_status) {
1097 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591098 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081099
[email protected]228ff742009-06-05 01:19:591100 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081101
[email protected]1c773ea12009-04-28 19:58:421102 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591103 session.get(), &session_deps.socket_factory));
[email protected]c744cf22009-02-27 07:28:081104
[email protected]1c773ea12009-04-28 19:58:421105 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081106 request.method = "GET";
1107 request.url = GURL("https://www.google.com/");
1108 request.load_flags = 0;
1109
1110 // Since we have proxy, should try to establish tunnel.
1111 MockWrite data_writes[] = {
1112 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451113 "Host: www.google.com\r\n"
1114 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081115 };
1116
1117 MockRead data_reads[] = {
1118 status,
1119 MockRead("Content-Length: 10\r\n\r\n"),
1120 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421121 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081122 };
1123
1124 MockSocket data;
1125 data.writes = data_writes;
1126 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:591127 session_deps.socket_factory.AddMockSocket(&data);
[email protected]c744cf22009-02-27 07:28:081128
1129 TestCompletionCallback callback;
1130
1131 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421132 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081133
1134 rv = callback.WaitForResult();
1135 EXPECT_EQ(expected_status, rv);
1136}
1137
[email protected]ff007e162009-05-23 09:13:151138void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081139 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421140 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081141}
1142
1143TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1144 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1145}
1146
1147TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1148 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1149}
1150
1151TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1152 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1153}
1154
1155TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1156 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1157}
1158
1159TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1160 ConnectStatusHelper(
1161 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1162}
1163
1164TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1165 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1166}
1167
1168TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1169 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1170}
1171
1172TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1173 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1174}
1175
1176TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1177 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1178}
1179
1180TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1181 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1182}
1183
1184TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1185 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1186}
1187
1188TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1189 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1190}
1191
1192TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1193 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1194}
1195
1196TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1197 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1198}
1199
1200TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1201 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1202}
1203
1204TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1205 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1206}
1207
1208TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1209 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1210}
1211
1212TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1213 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1214}
1215
1216TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1217 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1218}
1219
1220TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1221 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1222}
1223
1224TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1225 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1226}
1227
1228TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1229 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1230}
1231
1232TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1233 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1234}
1235
1236TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1237 ConnectStatusHelperWithExpectedStatus(
1238 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421239 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081240}
1241
1242TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1243 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1244}
1245
1246TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1247 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1248}
1249
1250TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1251 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1252}
1253
1254TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1255 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1256}
1257
1258TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1259 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1260}
1261
1262TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1263 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1264}
1265
1266TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1267 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1268}
1269
1270TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1271 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1272}
1273
1274TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1275 ConnectStatusHelper(
1276 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1277}
1278
1279TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1280 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1281}
1282
1283TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1284 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1285}
1286
1287TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1288 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1289}
1290
1291TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1292 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1293}
1294
1295TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1296 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1297}
1298
1299TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1300 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1301}
1302
1303TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1304 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1305}
1306
[email protected]038e9a32008-10-08 22:40:161307// Test the flow when both the proxy server AND origin server require
1308// authentication. Again, this uses basic auth for both since that is
1309// the simplest to mock.
1310TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591311 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011312
[email protected]038e9a32008-10-08 22:40:161313 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421314 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591315 CreateSession(&session_deps),
1316 &session_deps.socket_factory));
[email protected]038e9a32008-10-08 22:40:161317
[email protected]1c773ea12009-04-28 19:58:421318 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161319 request.method = "GET";
1320 request.url = GURL("http://www.google.com/");
1321 request.load_flags = 0;
1322
[email protected]f9ee6b52008-11-08 06:46:231323 MockWrite data_writes1[] = {
1324 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1325 "Host: www.google.com\r\n"
1326 "Proxy-Connection: keep-alive\r\n\r\n"),
1327 };
1328
[email protected]038e9a32008-10-08 22:40:161329 MockRead data_reads1[] = {
1330 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1331 // Give a couple authenticate options (only the middle one is actually
1332 // supported).
[email protected]aaead502008-10-15 00:20:111333 MockRead("Proxy-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:161334 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1335 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1336 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1337 // Large content-length -- won't matter, as connection will be reset.
1338 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421339 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161340 };
1341
1342 // After calling trans->RestartWithAuth() the first time, this is the
1343 // request we should be issuing -- the final header line contains the
1344 // proxy's credentials.
1345 MockWrite data_writes2[] = {
1346 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1347 "Host: www.google.com\r\n"
1348 "Proxy-Connection: keep-alive\r\n"
1349 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1350 };
1351
1352 // Now the proxy server lets the request pass through to origin server.
1353 // The origin server responds with a 401.
1354 MockRead data_reads2[] = {
1355 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1356 // Note: We are using the same realm-name as the proxy server. This is
1357 // completely valid, as realms are unique across hosts.
1358 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1359 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1360 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421361 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161362 };
1363
1364 // After calling trans->RestartWithAuth() the second time, we should send
1365 // the credentials for both the proxy and origin server.
1366 MockWrite data_writes3[] = {
1367 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1368 "Host: www.google.com\r\n"
1369 "Proxy-Connection: keep-alive\r\n"
1370 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1371 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1372 };
1373
1374 // Lastly we get the desired content.
1375 MockRead data_reads3[] = {
1376 MockRead("HTTP/1.0 200 OK\r\n"),
1377 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1378 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421379 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161380 };
1381
1382 MockSocket data1;
1383 data1.reads = data_reads1;
[email protected]f9ee6b52008-11-08 06:46:231384 data1.writes = data_writes1;
[email protected]038e9a32008-10-08 22:40:161385 MockSocket data2;
1386 data2.reads = data_reads2;
1387 data2.writes = data_writes2;
1388 MockSocket data3;
1389 data3.reads = data_reads3;
1390 data3.writes = data_writes3;
[email protected]228ff742009-06-05 01:19:591391 session_deps.socket_factory.AddMockSocket(&data1);
1392 session_deps.socket_factory.AddMockSocket(&data2);
1393 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]038e9a32008-10-08 22:40:161394
1395 TestCompletionCallback callback1;
1396
1397 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421398 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161399
1400 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421401 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161402
[email protected]1c773ea12009-04-28 19:58:421403 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161404 EXPECT_FALSE(response == NULL);
1405
1406 // The password prompt info should have been set in response->auth_challenge.
1407 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1408
[email protected]71e4573a2009-05-21 22:03:001409 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161410 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1411 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1412
1413 TestCompletionCallback callback2;
1414
1415 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421416 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161417
1418 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421419 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161420
1421 response = trans->GetResponseInfo();
1422 EXPECT_FALSE(response == NULL);
1423 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1424
[email protected]71e4573a2009-05-21 22:03:001425 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161426 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1427 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1428
1429 TestCompletionCallback callback3;
1430
1431 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421432 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161433
1434 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421435 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161436
1437 response = trans->GetResponseInfo();
1438 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1439 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161440}
[email protected]4ddaf2502008-10-23 18:26:191441
[email protected]385a4672009-03-11 22:21:291442// The NTLM authentication unit tests were generated by capturing the HTTP
1443// requests and responses using Fiddler 2 and inspecting the generated random
1444// bytes in the debugger.
1445
1446// Enter the correct password and authenticate successfully.
1447TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421448 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201449 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591450 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401451 scoped_ptr<HttpTransaction> trans(
1452 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591453 CreateSession(&session_deps),
1454 &session_deps.socket_factory));
[email protected]3f918782009-02-28 01:29:241455
[email protected]1c773ea12009-04-28 19:58:421456 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241457 request.method = "GET";
1458 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1459 request.load_flags = 0;
1460
1461 MockWrite data_writes1[] = {
1462 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1463 "Host: 172.22.68.17\r\n"
1464 "Connection: keep-alive\r\n\r\n"),
1465 };
1466
1467 MockRead data_reads1[] = {
1468 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1469 // Negotiate and NTLM are often requested together. We only support NTLM.
1470 MockRead("WWW-Authenticate: Negotiate\r\n"),
1471 MockRead("WWW-Authenticate: NTLM\r\n"),
1472 MockRead("Connection: close\r\n"),
1473 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361474 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241475 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421476 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241477 };
1478
1479 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221480 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241481 // request we should be issuing -- the final header line contains a Type
1482 // 1 message.
1483 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1484 "Host: 172.22.68.17\r\n"
1485 "Connection: keep-alive\r\n"
1486 "Authorization: NTLM "
1487 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1488
1489 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1490 // (the credentials for the origin server). The second request continues
1491 // on the same connection.
1492 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1493 "Host: 172.22.68.17\r\n"
1494 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291495 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1496 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1497 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1498 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1499 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241500 };
1501
1502 MockRead data_reads2[] = {
1503 // The origin server responds with a Type 2 message.
1504 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1505 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291506 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241507 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1508 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1509 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1510 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1511 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1512 "BtAAAAAAA=\r\n"),
1513 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361514 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241515 MockRead("You are not authorized to view this page\r\n"),
1516
1517 // Lastly we get the desired content.
1518 MockRead("HTTP/1.1 200 OK\r\n"),
1519 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1520 MockRead("Content-Length: 13\r\n\r\n"),
1521 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421522 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241523 };
1524
1525 MockSocket data1;
1526 data1.reads = data_reads1;
1527 data1.writes = data_writes1;
1528 MockSocket data2;
1529 data2.reads = data_reads2;
1530 data2.writes = data_writes2;
[email protected]228ff742009-06-05 01:19:591531 session_deps.socket_factory.AddMockSocket(&data1);
1532 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]3f918782009-02-28 01:29:241533
1534 TestCompletionCallback callback1;
1535
1536 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421537 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241538
1539 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421540 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241541
[email protected]0757e7702009-03-27 04:00:221542 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1543 TestCompletionCallback callback2;
1544 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421545 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221546 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421547 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221548 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1549
[email protected]1c773ea12009-04-28 19:58:421550 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241551 EXPECT_FALSE(response == NULL);
1552
1553 // The password prompt info should have been set in response->auth_challenge.
1554 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1555
[email protected]71e4573a2009-05-21 22:03:001556 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241557 EXPECT_EQ(L"", response->auth_challenge->realm);
1558 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1559
[email protected]0757e7702009-03-27 04:00:221560 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241561
[email protected]0757e7702009-03-27 04:00:221562 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421563 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241564
[email protected]0757e7702009-03-27 04:00:221565 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421566 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241567
1568 response = trans->GetResponseInfo();
1569 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1570 EXPECT_EQ(13, response->headers->GetContentLength());
1571}
1572
[email protected]385a4672009-03-11 22:21:291573// Enter a wrong password, and then the correct one.
1574TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421575 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201576 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591577 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401578 scoped_ptr<HttpTransaction> trans(
1579 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591580 CreateSession(&session_deps),
1581 &session_deps.socket_factory));
[email protected]385a4672009-03-11 22:21:291582
[email protected]1c773ea12009-04-28 19:58:421583 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291584 request.method = "GET";
1585 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1586 request.load_flags = 0;
1587
1588 MockWrite data_writes1[] = {
1589 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1590 "Host: 172.22.68.17\r\n"
1591 "Connection: keep-alive\r\n\r\n"),
1592 };
1593
1594 MockRead data_reads1[] = {
1595 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1596 // Negotiate and NTLM are often requested together. We only support NTLM.
1597 MockRead("WWW-Authenticate: Negotiate\r\n"),
1598 MockRead("WWW-Authenticate: NTLM\r\n"),
1599 MockRead("Connection: close\r\n"),
1600 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361601 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291602 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421603 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291604 };
1605
1606 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221607 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291608 // request we should be issuing -- the final header line contains a Type
1609 // 1 message.
1610 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1611 "Host: 172.22.68.17\r\n"
1612 "Connection: keep-alive\r\n"
1613 "Authorization: NTLM "
1614 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1615
1616 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1617 // (the credentials for the origin server). The second request continues
1618 // on the same connection.
1619 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1620 "Host: 172.22.68.17\r\n"
1621 "Connection: keep-alive\r\n"
1622 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1623 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1624 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1625 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1626 "4Ww7b7E=\r\n\r\n"),
1627 };
1628
1629 MockRead data_reads2[] = {
1630 // The origin server responds with a Type 2 message.
1631 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1632 MockRead("WWW-Authenticate: NTLM "
1633 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1634 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1635 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1636 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1637 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1638 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1639 "BtAAAAAAA=\r\n"),
1640 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361641 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291642 MockRead("You are not authorized to view this page\r\n"),
1643
1644 // Wrong password.
1645 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1646 MockRead("WWW-Authenticate: Negotiate\r\n"),
1647 MockRead("WWW-Authenticate: NTLM\r\n"),
1648 MockRead("Connection: close\r\n"),
1649 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361650 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291651 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421652 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291653 };
1654
1655 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221656 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291657 // request we should be issuing -- the final header line contains a Type
1658 // 1 message.
1659 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1660 "Host: 172.22.68.17\r\n"
1661 "Connection: keep-alive\r\n"
1662 "Authorization: NTLM "
1663 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1664
1665 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1666 // (the credentials for the origin server). The second request continues
1667 // on the same connection.
1668 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1669 "Host: 172.22.68.17\r\n"
1670 "Connection: keep-alive\r\n"
1671 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1672 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1673 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1674 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1675 "+4MUm7c=\r\n\r\n"),
1676 };
1677
1678 MockRead data_reads3[] = {
1679 // The origin server responds with a Type 2 message.
1680 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1681 MockRead("WWW-Authenticate: NTLM "
1682 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1683 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1684 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1685 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1686 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1687 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1688 "BtAAAAAAA=\r\n"),
1689 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361690 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291691 MockRead("You are not authorized to view this page\r\n"),
1692
1693 // Lastly we get the desired content.
1694 MockRead("HTTP/1.1 200 OK\r\n"),
1695 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1696 MockRead("Content-Length: 13\r\n\r\n"),
1697 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421698 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291699 };
1700
1701 MockSocket data1;
1702 data1.reads = data_reads1;
1703 data1.writes = data_writes1;
1704 MockSocket data2;
1705 data2.reads = data_reads2;
1706 data2.writes = data_writes2;
1707 MockSocket data3;
1708 data3.reads = data_reads3;
1709 data3.writes = data_writes3;
[email protected]228ff742009-06-05 01:19:591710 session_deps.socket_factory.AddMockSocket(&data1);
1711 session_deps.socket_factory.AddMockSocket(&data2);
1712 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]385a4672009-03-11 22:21:291713
1714 TestCompletionCallback callback1;
1715
1716 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421717 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291718
1719 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421720 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291721
[email protected]0757e7702009-03-27 04:00:221722 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291723 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221724 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421725 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291726 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421727 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221728 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291729
[email protected]1c773ea12009-04-28 19:58:421730 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291731 EXPECT_FALSE(response == NULL);
1732
1733 // The password prompt info should have been set in response->auth_challenge.
1734 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1735
[email protected]71e4573a2009-05-21 22:03:001736 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291737 EXPECT_EQ(L"", response->auth_challenge->realm);
1738 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1739
1740 TestCompletionCallback callback3;
1741
[email protected]0757e7702009-03-27 04:00:221742 // Enter the wrong password.
1743 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421744 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291745
1746 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421747 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291748
[email protected]0757e7702009-03-27 04:00:221749 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1750 TestCompletionCallback callback4;
1751 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421752 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221753 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421754 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221755 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1756
1757 response = trans->GetResponseInfo();
1758 EXPECT_FALSE(response == NULL);
1759
1760 // The password prompt info should have been set in response->auth_challenge.
1761 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1762
[email protected]71e4573a2009-05-21 22:03:001763 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221764 EXPECT_EQ(L"", response->auth_challenge->realm);
1765 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1766
1767 TestCompletionCallback callback5;
1768
1769 // Now enter the right password.
1770 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421771 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221772
1773 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421774 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221775
[email protected]385a4672009-03-11 22:21:291776 response = trans->GetResponseInfo();
1777 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1778 EXPECT_EQ(13, response->headers->GetContentLength());
1779}
1780
[email protected]4ddaf2502008-10-23 18:26:191781// Test reading a server response which has only headers, and no body.
1782// After some maximum number of bytes is consumed, the transaction should
1783// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
1784TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:591785 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401786 scoped_ptr<HttpTransaction> trans(
1787 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591788 CreateSession(&session_deps),
1789 &session_deps.socket_factory));
[email protected]4ddaf2502008-10-23 18:26:191790
[email protected]1c773ea12009-04-28 19:58:421791 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:191792 request.method = "GET";
1793 request.url = GURL("http://www.google.com/");
1794 request.load_flags = 0;
1795
1796 // Respond with 50 kb of headers (we should fail after 32 kb).
[email protected]15a5ccf82008-10-23 19:57:431797 std::string large_headers_string;
1798 FillLargeHeadersString(&large_headers_string, 50 * 1024);
[email protected]4ddaf2502008-10-23 18:26:191799
1800 MockRead data_reads[] = {
1801 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:431802 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:191803 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:421804 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:191805 };
1806 MockSocket data;
1807 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:591808 session_deps.socket_factory.AddMockSocket(&data);
[email protected]4ddaf2502008-10-23 18:26:191809
1810 TestCompletionCallback callback;
1811
1812 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421813 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:191814
1815 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421816 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:191817
[email protected]1c773ea12009-04-28 19:58:421818 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:191819 EXPECT_TRUE(response == NULL);
1820}
[email protected]f4e426b2008-11-05 00:24:491821
1822// Make sure that we don't try to reuse a TCPClientSocket when failing to
1823// establish tunnel.
1824// http://code.google.com/p/chromium/issues/detail?id=3772
1825TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
1826 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591827 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011828
[email protected]228ff742009-06-05 01:19:591829 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:491830
[email protected]1c773ea12009-04-28 19:58:421831 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591832 session.get(), &session_deps.socket_factory));
[email protected]f4e426b2008-11-05 00:24:491833
[email protected]1c773ea12009-04-28 19:58:421834 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:491835 request.method = "GET";
1836 request.url = GURL("https://www.google.com/");
1837 request.load_flags = 0;
1838
1839 // Since we have proxy, should try to establish tunnel.
1840 MockWrite data_writes1[] = {
1841 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451842 "Host: www.google.com\r\n"
1843 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:491844 };
1845
[email protected]77848d12008-11-14 00:00:221846 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:491847 // connection. Usually a proxy would return 501 (not implemented),
1848 // or 200 (tunnel established).
1849 MockRead data_reads1[] = {
1850 MockRead("HTTP/1.1 404 Not Found\r\n"),
1851 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421852 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:491853 };
1854
1855 MockSocket data1;
1856 data1.writes = data_writes1;
1857 data1.reads = data_reads1;
[email protected]228ff742009-06-05 01:19:591858 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f4e426b2008-11-05 00:24:491859
1860 TestCompletionCallback callback1;
1861
1862 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421863 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:491864
1865 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421866 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:491867
[email protected]1c773ea12009-04-28 19:58:421868 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:081869 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:491870
[email protected]b4404c02009-04-10 16:38:521871 // Empty the current queue. This is necessary because idle sockets are
1872 // added to the connection pool asynchronously with a PostTask.
1873 MessageLoop::current()->RunAllPending();
1874
[email protected]f4e426b2008-11-05 00:24:491875 // We now check to make sure the TCPClientSocket was not added back to
1876 // the pool.
1877 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
1878 trans.reset();
[email protected]b4404c02009-04-10 16:38:521879 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:491880 // Make sure that the socket didn't get recycled after calling the destructor.
1881 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
1882}
[email protected]372d34a2008-11-05 21:30:511883
[email protected]1b157c02009-04-21 01:55:401884// Make sure that we recycle a socket after reading all of the response body.
1885TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:591886 SessionDependencies session_deps;
1887 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:401888
[email protected]1c773ea12009-04-28 19:58:421889 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591890 session.get(), &session_deps.socket_factory));
[email protected]1b157c02009-04-21 01:55:401891
[email protected]1c773ea12009-04-28 19:58:421892 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:401893 request.method = "GET";
1894 request.url = GURL("http://www.google.com/");
1895 request.load_flags = 0;
1896
1897 MockRead data_reads[] = {
1898 // A part of the response body is received with the response headers.
1899 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
1900 // The rest of the response body is received in two parts.
1901 MockRead("lo"),
1902 MockRead(" world"),
1903 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421904 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:401905 };
1906
1907 MockSocket data;
1908 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:591909 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1b157c02009-04-21 01:55:401910
1911 TestCompletionCallback callback;
1912
1913 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421914 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:401915
1916 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421917 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401918
[email protected]1c773ea12009-04-28 19:58:421919 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:401920 EXPECT_TRUE(response != NULL);
1921
1922 EXPECT_TRUE(response->headers != NULL);
1923 std::string status_line = response->headers->GetStatusLine();
1924 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
1925
1926 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
1927
1928 std::string response_data;
1929 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421930 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401931 EXPECT_EQ("hello world", response_data);
1932
1933 // Empty the current queue. This is necessary because idle sockets are
1934 // added to the connection pool asynchronously with a PostTask.
1935 MessageLoop::current()->RunAllPending();
1936
1937 // We now check to make sure the socket was added back to the pool.
1938 EXPECT_EQ(1, session->connection_pool()->idle_socket_count());
1939}
1940
[email protected]b4404c02009-04-10 16:38:521941// Make sure that we recycle a socket after a zero-length response.
1942// http://crbug.com/9880
1943TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:591944 SessionDependencies session_deps;
1945 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:521946
[email protected]1c773ea12009-04-28 19:58:421947 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591948 session.get(), &session_deps.socket_factory));
[email protected]b4404c02009-04-10 16:38:521949
[email protected]1c773ea12009-04-28 19:58:421950 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:521951 request.method = "GET";
1952 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
1953 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
1954 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
1955 "rt=prt.2642,ol.2649,xjs.2951");
1956 request.load_flags = 0;
1957
1958 MockRead data_reads[] = {
1959 MockRead("HTTP/1.1 204 No Content\r\n"
1960 "Content-Length: 0\r\n"
1961 "Content-Type: text/html\r\n\r\n"),
1962 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421963 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:521964 };
1965
1966 MockSocket data;
1967 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:591968 session_deps.socket_factory.AddMockSocket(&data);
[email protected]b4404c02009-04-10 16:38:521969
1970 TestCompletionCallback callback;
1971
1972 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421973 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:521974
1975 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421976 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:521977
[email protected]1c773ea12009-04-28 19:58:421978 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:521979 EXPECT_TRUE(response != NULL);
1980
1981 EXPECT_TRUE(response->headers != NULL);
1982 std::string status_line = response->headers->GetStatusLine();
1983 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
1984
1985 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
1986
1987 std::string response_data;
1988 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421989 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:521990 EXPECT_EQ("", response_data);
1991
1992 // Empty the current queue. This is necessary because idle sockets are
1993 // added to the connection pool asynchronously with a PostTask.
1994 MessageLoop::current()->RunAllPending();
1995
1996 // We now check to make sure the socket was added back to the pool.
1997 EXPECT_EQ(1, session->connection_pool()->idle_socket_count());
1998}
1999
[email protected]372d34a2008-11-05 21:30:512000TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422001 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512002 // Transaction 1: a GET request that succeeds. The socket is recycled
2003 // after use.
2004 request[0].method = "GET";
2005 request[0].url = GURL("http://www.google.com/");
2006 request[0].load_flags = 0;
2007 // Transaction 2: a POST request. Reuses the socket kept alive from
2008 // transaction 1. The first attempts fails when writing the POST data.
2009 // This causes the transaction to retry with a new socket. The second
2010 // attempt succeeds.
2011 request[1].method = "POST";
2012 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422013 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512014 request[1].upload_data->AppendBytes("foo", 3);
2015 request[1].load_flags = 0;
2016
[email protected]228ff742009-06-05 01:19:592017 SessionDependencies session_deps;
2018 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512019
2020 // The first socket is used for transaction 1 and the first attempt of
2021 // transaction 2.
2022
2023 // The response of transaction 1.
2024 MockRead data_reads1[] = {
2025 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2026 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422027 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512028 };
2029 // The mock write results of transaction 1 and the first attempt of
2030 // transaction 2.
2031 MockWrite data_writes1[] = {
2032 MockWrite(false, 64), // GET
2033 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422034 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512035 };
2036 MockSocket data1;
2037 data1.reads = data_reads1;
2038 data1.writes = data_writes1;
2039
2040 // The second socket is used for the second attempt of transaction 2.
2041
2042 // The response of transaction 2.
2043 MockRead data_reads2[] = {
2044 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2045 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422046 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512047 };
2048 // The mock write results of the second attempt of transaction 2.
2049 MockWrite data_writes2[] = {
2050 MockWrite(false, 93), // POST
2051 MockWrite(false, 3), // POST data
2052 };
2053 MockSocket data2;
2054 data2.reads = data_reads2;
2055 data2.writes = data_writes2;
2056
[email protected]228ff742009-06-05 01:19:592057 session_deps.socket_factory.AddMockSocket(&data1);
2058 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]372d34a2008-11-05 21:30:512059
2060 const char* kExpectedResponseData[] = {
2061 "hello world", "welcome"
2062 };
2063
2064 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422065 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:592066 new HttpNetworkTransaction(session, &session_deps.socket_factory));
[email protected]372d34a2008-11-05 21:30:512067
2068 TestCompletionCallback callback;
2069
2070 int rv = trans->Start(&request[i], &callback);
[email protected]1c773ea12009-04-28 19:58:422071 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512072
2073 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422074 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512075
[email protected]1c773ea12009-04-28 19:58:422076 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512077 EXPECT_TRUE(response != NULL);
2078
2079 EXPECT_TRUE(response->headers != NULL);
2080 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2081
2082 std::string response_data;
2083 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422084 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512085 EXPECT_EQ(kExpectedResponseData[i], response_data);
2086 }
2087}
[email protected]f9ee6b52008-11-08 06:46:232088
2089// Test the request-challenge-retry sequence for basic auth when there is
2090// an identity in the URL. The request should be sent as normal, but when
2091// it fails the identity from the URL is used to answer the challenge.
2092TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) {
[email protected]228ff742009-06-05 01:19:592093 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402094 scoped_ptr<HttpTransaction> trans(
2095 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592096 CreateSession(&session_deps),
2097 &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232098
[email protected]1c773ea12009-04-28 19:58:422099 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232100 request.method = "GET";
2101 // Note: the URL has a username:password in it.
2102 request.url = GURL("http://foo:[email protected]/");
2103 request.load_flags = 0;
2104
2105 MockWrite data_writes1[] = {
2106 MockWrite("GET / HTTP/1.1\r\n"
2107 "Host: www.google.com\r\n"
2108 "Connection: keep-alive\r\n\r\n"),
2109 };
2110
2111 MockRead data_reads1[] = {
2112 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2113 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2114 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422115 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232116 };
2117
2118 // After the challenge above, the transaction will be restarted using the
2119 // identity from the url (foo, bar) to answer the challenge.
2120 MockWrite data_writes2[] = {
2121 MockWrite("GET / HTTP/1.1\r\n"
2122 "Host: www.google.com\r\n"
2123 "Connection: keep-alive\r\n"
2124 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2125 };
2126
2127 MockRead data_reads2[] = {
2128 MockRead("HTTP/1.0 200 OK\r\n"),
2129 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422130 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232131 };
2132
2133 MockSocket data1;
2134 data1.reads = data_reads1;
2135 data1.writes = data_writes1;
2136 MockSocket data2;
2137 data2.reads = data_reads2;
2138 data2.writes = data_writes2;
[email protected]228ff742009-06-05 01:19:592139 session_deps.socket_factory.AddMockSocket(&data1);
2140 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232141
2142 TestCompletionCallback callback1;
2143
2144 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422145 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232146
2147 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422148 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232149
[email protected]0757e7702009-03-27 04:00:222150 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2151 TestCompletionCallback callback2;
2152 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422153 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222154 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422155 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222156 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2157
[email protected]1c773ea12009-04-28 19:58:422158 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232159 EXPECT_FALSE(response == NULL);
2160
2161 // There is no challenge info, since the identity in URL worked.
2162 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2163
2164 EXPECT_EQ(100, response->headers->GetContentLength());
2165
2166 // Empty the current queue.
2167 MessageLoop::current()->RunAllPending();
2168}
2169
2170// Test that previously tried username/passwords for a realm get re-used.
2171TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592172 SessionDependencies session_deps;
2173 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232174
2175 // Transaction 1: authenticate (foo, bar) on MyRealm1
2176 {
[email protected]1c773ea12009-04-28 19:58:422177 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592178 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232179
[email protected]1c773ea12009-04-28 19:58:422180 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232181 request.method = "GET";
2182 request.url = GURL("http://www.google.com/x/y/z");
2183 request.load_flags = 0;
2184
2185 MockWrite data_writes1[] = {
2186 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2187 "Host: www.google.com\r\n"
2188 "Connection: keep-alive\r\n\r\n"),
2189 };
2190
2191 MockRead data_reads1[] = {
2192 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2193 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2194 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422195 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232196 };
2197
2198 // Resend with authorization (username=foo, password=bar)
2199 MockWrite data_writes2[] = {
2200 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2201 "Host: www.google.com\r\n"
2202 "Connection: keep-alive\r\n"
2203 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2204 };
2205
2206 // Sever accepts the authorization.
2207 MockRead data_reads2[] = {
2208 MockRead("HTTP/1.0 200 OK\r\n"),
2209 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422210 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232211 };
2212
2213 MockSocket data1;
2214 data1.reads = data_reads1;
2215 data1.writes = data_writes1;
2216 MockSocket data2;
2217 data2.reads = data_reads2;
2218 data2.writes = data_writes2;
[email protected]228ff742009-06-05 01:19:592219 session_deps.socket_factory.AddMockSocket(&data1);
2220 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232221
2222 TestCompletionCallback callback1;
2223
2224 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422225 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232226
2227 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422228 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232229
[email protected]1c773ea12009-04-28 19:58:422230 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232231 EXPECT_FALSE(response == NULL);
2232
2233 // The password prompt info should have been set in
2234 // response->auth_challenge.
2235 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2236
[email protected]71e4573a2009-05-21 22:03:002237 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232238 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2239 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2240
2241 TestCompletionCallback callback2;
2242
2243 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422244 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232245
2246 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422247 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232248
2249 response = trans->GetResponseInfo();
2250 EXPECT_FALSE(response == NULL);
2251 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2252 EXPECT_EQ(100, response->headers->GetContentLength());
2253 }
2254
2255 // ------------------------------------------------------------------------
2256
2257 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2258 {
[email protected]1c773ea12009-04-28 19:58:422259 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592260 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232261
[email protected]1c773ea12009-04-28 19:58:422262 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232263 request.method = "GET";
2264 // Note that Transaction 1 was at /x/y/z, so this is in the same
2265 // protection space as MyRealm1.
2266 request.url = GURL("http://www.google.com/x/y/a/b");
2267 request.load_flags = 0;
2268
2269 MockWrite data_writes1[] = {
2270 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2271 "Host: www.google.com\r\n"
2272 "Connection: keep-alive\r\n"
2273 // Send preemptive authorization for MyRealm1
2274 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2275 };
2276
2277 // The server didn't like the preemptive authorization, and
2278 // challenges us for a different realm (MyRealm2).
2279 MockRead data_reads1[] = {
2280 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2281 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2282 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422283 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232284 };
2285
2286 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2287 MockWrite data_writes2[] = {
2288 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2289 "Host: www.google.com\r\n"
2290 "Connection: keep-alive\r\n"
2291 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2292 };
2293
2294 // Sever accepts the authorization.
2295 MockRead data_reads2[] = {
2296 MockRead("HTTP/1.0 200 OK\r\n"),
2297 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422298 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232299 };
2300
2301 MockSocket data1;
2302 data1.reads = data_reads1;
2303 data1.writes = data_writes1;
2304 MockSocket data2;
2305 data2.reads = data_reads2;
2306 data2.writes = data_writes2;
[email protected]ff007e162009-05-23 09:13:152307
[email protected]228ff742009-06-05 01:19:592308 session_deps.socket_factory.AddMockSocket(&data1);
2309 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232310
2311 TestCompletionCallback callback1;
2312
2313 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422314 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232315
2316 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422317 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232318
[email protected]1c773ea12009-04-28 19:58:422319 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232320 EXPECT_FALSE(response == NULL);
2321
2322 // The password prompt info should have been set in
2323 // response->auth_challenge.
2324 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2325
[email protected]71e4573a2009-05-21 22:03:002326 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232327 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2328 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2329
2330 TestCompletionCallback callback2;
2331
2332 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422333 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232334
2335 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422336 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232337
2338 response = trans->GetResponseInfo();
2339 EXPECT_FALSE(response == NULL);
2340 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2341 EXPECT_EQ(100, response->headers->GetContentLength());
2342 }
2343
2344 // ------------------------------------------------------------------------
2345
2346 // Transaction 3: Resend a request in MyRealm's protection space --
2347 // succeed with preemptive authorization.
2348 {
[email protected]1c773ea12009-04-28 19:58:422349 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592350 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232351
[email protected]1c773ea12009-04-28 19:58:422352 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232353 request.method = "GET";
2354 request.url = GURL("http://www.google.com/x/y/z2");
2355 request.load_flags = 0;
2356
2357 MockWrite data_writes1[] = {
2358 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2359 "Host: www.google.com\r\n"
2360 "Connection: keep-alive\r\n"
2361 // The authorization for MyRealm1 gets sent preemptively
2362 // (since the url is in the same protection space)
2363 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2364 };
2365
2366 // Sever accepts the preemptive authorization
2367 MockRead data_reads1[] = {
2368 MockRead("HTTP/1.0 200 OK\r\n"),
2369 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422370 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232371 };
2372
2373 MockSocket data1;
2374 data1.reads = data_reads1;
2375 data1.writes = data_writes1;
[email protected]228ff742009-06-05 01:19:592376 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f9ee6b52008-11-08 06:46:232377
2378 TestCompletionCallback callback1;
2379
2380 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422381 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232382
2383 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422384 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232385
[email protected]1c773ea12009-04-28 19:58:422386 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232387 EXPECT_FALSE(response == NULL);
2388
2389 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2390 EXPECT_EQ(100, response->headers->GetContentLength());
2391 }
2392
2393 // ------------------------------------------------------------------------
2394
2395 // Transaction 4: request another URL in MyRealm (however the
2396 // url is not known to belong to the protection space, so no pre-auth).
2397 {
[email protected]1c773ea12009-04-28 19:58:422398 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592399 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232400
[email protected]1c773ea12009-04-28 19:58:422401 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232402 request.method = "GET";
2403 request.url = GURL("http://www.google.com/x/1");
2404 request.load_flags = 0;
2405
2406 MockWrite data_writes1[] = {
2407 MockWrite("GET /x/1 HTTP/1.1\r\n"
2408 "Host: www.google.com\r\n"
2409 "Connection: keep-alive\r\n\r\n"),
2410 };
2411
2412 MockRead data_reads1[] = {
2413 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2414 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2415 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422416 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232417 };
2418
2419 // Resend with authorization from MyRealm's cache.
2420 MockWrite data_writes2[] = {
2421 MockWrite("GET /x/1 HTTP/1.1\r\n"
2422 "Host: www.google.com\r\n"
2423 "Connection: keep-alive\r\n"
2424 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2425 };
2426
2427 // Sever accepts the authorization.
2428 MockRead data_reads2[] = {
2429 MockRead("HTTP/1.0 200 OK\r\n"),
2430 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422431 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232432 };
2433
2434 MockSocket data1;
2435 data1.reads = data_reads1;
2436 data1.writes = data_writes1;
2437 MockSocket data2;
2438 data2.reads = data_reads2;
2439 data2.writes = data_writes2;
[email protected]228ff742009-06-05 01:19:592440 session_deps.socket_factory.AddMockSocket(&data1);
2441 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232442
2443 TestCompletionCallback callback1;
2444
2445 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422446 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232447
2448 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422449 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232450
[email protected]0757e7702009-03-27 04:00:222451 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2452 TestCompletionCallback callback2;
2453 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422454 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222455 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422456 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222457 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2458
[email protected]1c773ea12009-04-28 19:58:422459 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232460 EXPECT_FALSE(response == NULL);
2461 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2462 EXPECT_EQ(100, response->headers->GetContentLength());
2463 }
2464
2465 // ------------------------------------------------------------------------
2466
2467 // Transaction 5: request a URL in MyRealm, but the server rejects the
2468 // cached identity. Should invalidate and re-prompt.
2469 {
[email protected]1c773ea12009-04-28 19:58:422470 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592471 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232472
[email protected]1c773ea12009-04-28 19:58:422473 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232474 request.method = "GET";
2475 request.url = GURL("http://www.google.com/p/q/t");
2476 request.load_flags = 0;
2477
2478 MockWrite data_writes1[] = {
2479 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2480 "Host: www.google.com\r\n"
2481 "Connection: keep-alive\r\n\r\n"),
2482 };
2483
2484 MockRead data_reads1[] = {
2485 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2486 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2487 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422488 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232489 };
2490
2491 // Resend with authorization from cache for MyRealm.
2492 MockWrite data_writes2[] = {
2493 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2494 "Host: www.google.com\r\n"
2495 "Connection: keep-alive\r\n"
2496 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2497 };
2498
2499 // Sever rejects the authorization.
2500 MockRead data_reads2[] = {
2501 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2502 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2503 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422504 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232505 };
2506
2507 // At this point we should prompt for new credentials for MyRealm.
2508 // Restart with username=foo3, password=foo4.
2509 MockWrite data_writes3[] = {
2510 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2511 "Host: www.google.com\r\n"
2512 "Connection: keep-alive\r\n"
2513 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2514 };
2515
2516 // Sever accepts the authorization.
2517 MockRead data_reads3[] = {
2518 MockRead("HTTP/1.0 200 OK\r\n"),
2519 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422520 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232521 };
2522
2523 MockSocket data1;
2524 data1.reads = data_reads1;
2525 data1.writes = data_writes1;
2526 MockSocket data2;
2527 data2.reads = data_reads2;
2528 data2.writes = data_writes2;
2529 MockSocket data3;
2530 data3.reads = data_reads3;
2531 data3.writes = data_writes3;
[email protected]228ff742009-06-05 01:19:592532 session_deps.socket_factory.AddMockSocket(&data1);
2533 session_deps.socket_factory.AddMockSocket(&data2);
2534 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]f9ee6b52008-11-08 06:46:232535
2536 TestCompletionCallback callback1;
2537
2538 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422539 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232540
2541 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422542 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232543
[email protected]0757e7702009-03-27 04:00:222544 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2545 TestCompletionCallback callback2;
2546 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422547 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222548 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422549 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222550 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2551
[email protected]1c773ea12009-04-28 19:58:422552 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232553 EXPECT_FALSE(response == NULL);
2554
2555 // The password prompt info should have been set in
2556 // response->auth_challenge.
2557 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2558
[email protected]71e4573a2009-05-21 22:03:002559 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232560 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2561 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2562
[email protected]0757e7702009-03-27 04:00:222563 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232564
[email protected]0757e7702009-03-27 04:00:222565 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422566 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232567
[email protected]0757e7702009-03-27 04:00:222568 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422569 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232570
2571 response = trans->GetResponseInfo();
2572 EXPECT_FALSE(response == NULL);
2573 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2574 EXPECT_EQ(100, response->headers->GetContentLength());
2575 }
2576}
[email protected]89ceba9a2009-03-21 03:46:062577
2578// Test the ResetStateForRestart() private method.
2579TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2580 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592581 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402582 scoped_ptr<HttpNetworkTransaction> trans(
2583 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592584 CreateSession(&session_deps),
2585 &session_deps.socket_factory));
[email protected]89ceba9a2009-03-21 03:46:062586
2587 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]ffeb0882009-04-30 21:51:252588 trans->header_buf_->Realloc(10);
[email protected]89ceba9a2009-03-21 03:46:062589 trans->header_buf_capacity_ = 10;
2590 trans->header_buf_len_ = 3;
2591 trans->header_buf_body_offset_ = 11;
2592 trans->header_buf_http_offset_ = 0;
2593 trans->response_body_length_ = 100;
2594 trans->response_body_read_ = 1;
2595 trans->read_buf_ = new IOBuffer(15);
2596 trans->read_buf_len_ = 15;
[email protected]ffeb0882009-04-30 21:51:252597 trans->request_headers_->headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062598 trans->request_headers_bytes_sent_ = 3;
2599
2600 // Setup state in response_
2601 trans->response_.auth_challenge = new AuthChallengeInfo();
2602 trans->response_.ssl_info.cert_status = -15;
2603 trans->response_.response_time = base::Time::Now();
[email protected]b4404c02009-04-10 16:38:522604 trans->response_.was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062605
2606 { // Setup state for response_.vary_data
2607 HttpRequestInfo request;
2608 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2609 std::replace(temp.begin(), temp.end(), '\n', '\0');
2610 scoped_refptr<HttpResponseHeaders> response = new HttpResponseHeaders(temp);
2611 request.extra_headers = "Foo: 1\nbar: 23";
2612 EXPECT_TRUE(trans->response_.vary_data.Init(request, *response));
2613 }
2614
2615 // Cause the above state to be reset.
2616 trans->ResetStateForRestart();
2617
2618 // Verify that the state that needed to be reset, has been reset.
[email protected]ffeb0882009-04-30 21:51:252619 EXPECT_EQ(NULL, trans->header_buf_->headers());
[email protected]89ceba9a2009-03-21 03:46:062620 EXPECT_EQ(0, trans->header_buf_capacity_);
2621 EXPECT_EQ(0, trans->header_buf_len_);
2622 EXPECT_EQ(-1, trans->header_buf_body_offset_);
2623 EXPECT_EQ(-1, trans->header_buf_http_offset_);
2624 EXPECT_EQ(-1, trans->response_body_length_);
2625 EXPECT_EQ(0, trans->response_body_read_);
2626 EXPECT_EQ(NULL, trans->read_buf_.get());
2627 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]ffeb0882009-04-30 21:51:252628 EXPECT_EQ("", trans->request_headers_->headers_);
[email protected]89ceba9a2009-03-21 03:46:062629 EXPECT_EQ(0U, trans->request_headers_bytes_sent_);
2630 EXPECT_EQ(NULL, trans->response_.auth_challenge.get());
2631 EXPECT_EQ(NULL, trans->response_.headers.get());
2632 EXPECT_EQ(false, trans->response_.was_cached);
[email protected]89ceba9a2009-03-21 03:46:062633 EXPECT_EQ(0, trans->response_.ssl_info.cert_status);
2634 EXPECT_FALSE(trans->response_.vary_data.is_valid());
2635}
2636
[email protected]bacff652009-03-31 17:50:332637// Test HTTPS connections to a site with a bad certificate
2638TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592639 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402640 scoped_ptr<HttpTransaction> trans(
2641 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592642 CreateSession(&session_deps),
2643 &session_deps.socket_factory));
[email protected]bacff652009-03-31 17:50:332644
2645 HttpRequestInfo request;
2646 request.method = "GET";
2647 request.url = GURL("https://www.google.com/");
2648 request.load_flags = 0;
2649
2650 MockWrite data_writes[] = {
2651 MockWrite("GET / HTTP/1.1\r\n"
2652 "Host: www.google.com\r\n"
2653 "Connection: keep-alive\r\n\r\n"),
2654 };
2655
2656 MockRead data_reads[] = {
2657 MockRead("HTTP/1.0 200 OK\r\n"),
2658 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2659 MockRead("Content-Length: 100\r\n\r\n"),
2660 MockRead(false, OK),
2661 };
2662
2663 MockSocket ssl_bad_certificate;
2664 MockSocket data(data_reads, data_writes);
2665 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2666 MockSSLSocket ssl(true, OK);
2667
[email protected]228ff742009-06-05 01:19:592668 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2669 session_deps.socket_factory.AddMockSocket(&data);
2670 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2671 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332672
2673 TestCompletionCallback callback;
2674
2675 int rv = trans->Start(&request, &callback);
2676 EXPECT_EQ(ERR_IO_PENDING, rv);
2677
2678 rv = callback.WaitForResult();
2679 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2680
2681 rv = trans->RestartIgnoringLastError(&callback);
2682 EXPECT_EQ(ERR_IO_PENDING, rv);
2683
2684 rv = callback.WaitForResult();
2685 EXPECT_EQ(OK, rv);
2686
2687 const HttpResponseInfo* response = trans->GetResponseInfo();
2688
2689 EXPECT_FALSE(response == NULL);
2690 EXPECT_EQ(100, response->headers->GetContentLength());
2691}
2692
2693// Test HTTPS connections to a site with a bad certificate, going through a
2694// proxy
2695TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592696 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332697
2698 HttpRequestInfo request;
2699 request.method = "GET";
2700 request.url = GURL("https://www.google.com/");
2701 request.load_flags = 0;
2702
2703 MockWrite proxy_writes[] = {
2704 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452705 "Host: www.google.com\r\n"
2706 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332707 };
2708
2709 MockRead proxy_reads[] = {
2710 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422711 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:332712 };
2713
2714 MockWrite data_writes[] = {
2715 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452716 "Host: www.google.com\r\n"
2717 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332718 MockWrite("GET / HTTP/1.1\r\n"
2719 "Host: www.google.com\r\n"
2720 "Connection: keep-alive\r\n\r\n"),
2721 };
2722
2723 MockRead data_reads[] = {
2724 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2725 MockRead("HTTP/1.0 200 OK\r\n"),
2726 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2727 MockRead("Content-Length: 100\r\n\r\n"),
2728 MockRead(false, OK),
2729 };
2730
2731 MockSocket ssl_bad_certificate(proxy_reads, proxy_writes);
2732 MockSocket data(data_reads, data_writes);
2733 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2734 MockSSLSocket ssl(true, OK);
2735
[email protected]228ff742009-06-05 01:19:592736 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2737 session_deps.socket_factory.AddMockSocket(&data);
2738 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2739 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332740
2741 TestCompletionCallback callback;
2742
2743 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:592744 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:332745
[email protected]d207a5f2009-06-04 05:28:402746 scoped_ptr<HttpTransaction> trans(
2747 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592748 CreateSession(&session_deps),
2749 &session_deps.socket_factory));
[email protected]bacff652009-03-31 17:50:332750
2751 int rv = trans->Start(&request, &callback);
2752 EXPECT_EQ(ERR_IO_PENDING, rv);
2753
2754 rv = callback.WaitForResult();
2755 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2756
2757 rv = trans->RestartIgnoringLastError(&callback);
2758 EXPECT_EQ(ERR_IO_PENDING, rv);
2759
2760 rv = callback.WaitForResult();
2761 EXPECT_EQ(OK, rv);
2762
2763 const HttpResponseInfo* response = trans->GetResponseInfo();
2764
2765 EXPECT_FALSE(response == NULL);
2766 EXPECT_EQ(100, response->headers->GetContentLength());
2767 }
2768}
2769
[email protected]1c773ea12009-04-28 19:58:422770TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:592771 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402772 scoped_ptr<HttpTransaction> trans(
2773 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592774 CreateSession(&session_deps),
2775 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422776
2777 HttpRequestInfo request;
2778 request.method = "GET";
2779 request.url = GURL("http://www.google.com/");
2780 request.user_agent = "Chromium Ultra Awesome X Edition";
2781
2782 MockWrite data_writes[] = {
2783 MockWrite("GET / HTTP/1.1\r\n"
2784 "Host: www.google.com\r\n"
2785 "Connection: keep-alive\r\n"
2786 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
2787 };
2788
2789 // Lastly, the server responds with the actual content.
2790 MockRead data_reads[] = {
2791 MockRead("HTTP/1.0 200 OK\r\n"),
2792 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2793 MockRead("Content-Length: 100\r\n\r\n"),
2794 MockRead(false, OK),
2795 };
2796
2797 MockSocket data;
2798 data.reads = data_reads;
2799 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592800 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422801
2802 TestCompletionCallback callback;
2803
2804 int rv = trans->Start(&request, &callback);
2805 EXPECT_EQ(ERR_IO_PENDING, rv);
2806
2807 rv = callback.WaitForResult();
2808 EXPECT_EQ(OK, rv);
2809}
2810
2811TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:592812 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402813 scoped_ptr<HttpTransaction> trans(
2814 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592815 CreateSession(&session_deps),
2816 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422817
2818 HttpRequestInfo request;
2819 request.method = "GET";
2820 request.url = GURL("http://www.google.com/");
2821 request.load_flags = 0;
2822 request.referrer = GURL("http://the.previous.site.com/");
2823
2824 MockWrite data_writes[] = {
2825 MockWrite("GET / HTTP/1.1\r\n"
2826 "Host: www.google.com\r\n"
2827 "Connection: keep-alive\r\n"
2828 "Referer: http://the.previous.site.com/\r\n\r\n"),
2829 };
2830
2831 // Lastly, the server responds with the actual content.
2832 MockRead data_reads[] = {
2833 MockRead("HTTP/1.0 200 OK\r\n"),
2834 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2835 MockRead("Content-Length: 100\r\n\r\n"),
2836 MockRead(false, OK),
2837 };
2838
2839 MockSocket data;
2840 data.reads = data_reads;
2841 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592842 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422843
2844 TestCompletionCallback callback;
2845
2846 int rv = trans->Start(&request, &callback);
2847 EXPECT_EQ(ERR_IO_PENDING, rv);
2848
2849 rv = callback.WaitForResult();
2850 EXPECT_EQ(OK, rv);
2851}
2852
2853TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592854 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402855 scoped_ptr<HttpTransaction> trans(
2856 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592857 CreateSession(&session_deps),
2858 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422859
2860 HttpRequestInfo request;
2861 request.method = "POST";
2862 request.url = GURL("http://www.google.com/");
2863
2864 MockWrite data_writes[] = {
2865 MockWrite("POST / HTTP/1.1\r\n"
2866 "Host: www.google.com\r\n"
2867 "Connection: keep-alive\r\n"
2868 "Content-Length: 0\r\n\r\n"),
2869 };
2870
2871 // Lastly, the server responds with the actual content.
2872 MockRead data_reads[] = {
2873 MockRead("HTTP/1.0 200 OK\r\n"),
2874 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2875 MockRead("Content-Length: 100\r\n\r\n"),
2876 MockRead(false, OK),
2877 };
2878
2879 MockSocket data;
2880 data.reads = data_reads;
2881 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592882 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422883
2884 TestCompletionCallback callback;
2885
2886 int rv = trans->Start(&request, &callback);
2887 EXPECT_EQ(ERR_IO_PENDING, rv);
2888
2889 rv = callback.WaitForResult();
2890 EXPECT_EQ(OK, rv);
2891}
2892
2893TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592894 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402895 scoped_ptr<HttpTransaction> trans(
2896 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592897 CreateSession(&session_deps),
2898 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422899
2900 HttpRequestInfo request;
2901 request.method = "PUT";
2902 request.url = GURL("http://www.google.com/");
2903
2904 MockWrite data_writes[] = {
2905 MockWrite("PUT / HTTP/1.1\r\n"
2906 "Host: www.google.com\r\n"
2907 "Connection: keep-alive\r\n"
2908 "Content-Length: 0\r\n\r\n"),
2909 };
2910
2911 // Lastly, the server responds with the actual content.
2912 MockRead data_reads[] = {
2913 MockRead("HTTP/1.0 200 OK\r\n"),
2914 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2915 MockRead("Content-Length: 100\r\n\r\n"),
2916 MockRead(false, OK),
2917 };
2918
2919 MockSocket data;
2920 data.reads = data_reads;
2921 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592922 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422923
2924 TestCompletionCallback callback;
2925
2926 int rv = trans->Start(&request, &callback);
2927 EXPECT_EQ(ERR_IO_PENDING, rv);
2928
2929 rv = callback.WaitForResult();
2930 EXPECT_EQ(OK, rv);
2931}
2932
2933TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592934 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402935 scoped_ptr<HttpTransaction> trans(
2936 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592937 CreateSession(&session_deps),
2938 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422939
2940 HttpRequestInfo request;
2941 request.method = "HEAD";
2942 request.url = GURL("http://www.google.com/");
2943
2944 MockWrite data_writes[] = {
2945 MockWrite("HEAD / HTTP/1.1\r\n"
2946 "Host: www.google.com\r\n"
2947 "Connection: keep-alive\r\n"
2948 "Content-Length: 0\r\n\r\n"),
2949 };
2950
2951 // Lastly, the server responds with the actual content.
2952 MockRead data_reads[] = {
2953 MockRead("HTTP/1.0 200 OK\r\n"),
2954 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2955 MockRead("Content-Length: 100\r\n\r\n"),
2956 MockRead(false, OK),
2957 };
2958
2959 MockSocket data;
2960 data.reads = data_reads;
2961 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592962 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422963
2964 TestCompletionCallback callback;
2965
2966 int rv = trans->Start(&request, &callback);
2967 EXPECT_EQ(ERR_IO_PENDING, rv);
2968
2969 rv = callback.WaitForResult();
2970 EXPECT_EQ(OK, rv);
2971}
2972
2973TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:592974 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402975 scoped_ptr<HttpTransaction> trans(
2976 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592977 CreateSession(&session_deps),
2978 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422979
2980 HttpRequestInfo request;
2981 request.method = "GET";
2982 request.url = GURL("http://www.google.com/");
2983 request.load_flags = LOAD_BYPASS_CACHE;
2984
2985 MockWrite data_writes[] = {
2986 MockWrite("GET / HTTP/1.1\r\n"
2987 "Host: www.google.com\r\n"
2988 "Connection: keep-alive\r\n"
2989 "Pragma: no-cache\r\n"
2990 "Cache-Control: no-cache\r\n\r\n"),
2991 };
2992
2993 // Lastly, the server responds with the actual content.
2994 MockRead data_reads[] = {
2995 MockRead("HTTP/1.0 200 OK\r\n"),
2996 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2997 MockRead("Content-Length: 100\r\n\r\n"),
2998 MockRead(false, OK),
2999 };
3000
3001 MockSocket data;
3002 data.reads = data_reads;
3003 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:593004 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423005
3006 TestCompletionCallback callback;
3007
3008 int rv = trans->Start(&request, &callback);
3009 EXPECT_EQ(ERR_IO_PENDING, rv);
3010
3011 rv = callback.WaitForResult();
3012 EXPECT_EQ(OK, rv);
3013}
3014
3015TEST_F(HttpNetworkTransactionTest,
3016 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593017 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403018 scoped_ptr<HttpTransaction> trans(
3019 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:593020 CreateSession(&session_deps),
3021 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:423022
3023 HttpRequestInfo request;
3024 request.method = "GET";
3025 request.url = GURL("http://www.google.com/");
3026 request.load_flags = LOAD_VALIDATE_CACHE;
3027
3028 MockWrite data_writes[] = {
3029 MockWrite("GET / HTTP/1.1\r\n"
3030 "Host: www.google.com\r\n"
3031 "Connection: keep-alive\r\n"
3032 "Cache-Control: max-age=0\r\n\r\n"),
3033 };
3034
3035 // Lastly, the server responds with the actual content.
3036 MockRead data_reads[] = {
3037 MockRead("HTTP/1.0 200 OK\r\n"),
3038 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3039 MockRead("Content-Length: 100\r\n\r\n"),
3040 MockRead(false, OK),
3041 };
3042
3043 MockSocket data;
3044 data.reads = data_reads;
3045 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:593046 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423047
3048 TestCompletionCallback callback;
3049
3050 int rv = trans->Start(&request, &callback);
3051 EXPECT_EQ(ERR_IO_PENDING, rv);
3052
3053 rv = callback.WaitForResult();
3054 EXPECT_EQ(OK, rv);
3055}
3056
3057TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593058 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403059 scoped_ptr<HttpTransaction> trans(
3060 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:593061 CreateSession(&session_deps),
3062 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:423063
3064 HttpRequestInfo request;
3065 request.method = "GET";
3066 request.url = GURL("http://www.google.com/");
3067 request.extra_headers = "FooHeader: Bar\r\n";
3068
3069 MockWrite data_writes[] = {
3070 MockWrite("GET / HTTP/1.1\r\n"
3071 "Host: www.google.com\r\n"
3072 "Connection: keep-alive\r\n"
3073 "FooHeader: Bar\r\n\r\n"),
3074 };
3075
3076 // Lastly, the server responds with the actual content.
3077 MockRead data_reads[] = {
3078 MockRead("HTTP/1.0 200 OK\r\n"),
3079 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3080 MockRead("Content-Length: 100\r\n\r\n"),
3081 MockRead(false, OK),
3082 };
3083
3084 MockSocket data;
3085 data.reads = data_reads;
3086 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:593087 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423088
3089 TestCompletionCallback callback;
3090
3091 int rv = trans->Start(&request, &callback);
3092 EXPECT_EQ(ERR_IO_PENDING, rv);
3093
3094 rv = callback.WaitForResult();
3095 EXPECT_EQ(OK, rv);
3096}
3097
[email protected]9172a982009-06-06 00:30:253098TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
3099 scoped_refptr<RuleBasedHostMapper> host_mapper(new RuleBasedHostMapper());
3100 ScopedHostMapper scoped_host_mapper(host_mapper.get());
3101 host_mapper->AddSimulatedFailure("*");
3102
[email protected]5c6a17e2009-06-10 00:54:543103 SessionDependencies session_deps(
3104 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]9172a982009-06-06 00:30:253105 scoped_ptr<HttpTransaction> trans(
3106 new HttpNetworkTransaction(
3107 CreateSession(&session_deps),
3108 &session_deps.socket_factory));
3109
3110 HttpRequestInfo request;
3111 request.method = "GET";
3112 request.url = GURL("http://www.google.com/");
3113
3114 TestCompletionCallback callback;
3115
3116 int rv = trans->Start(&request, &callback);
3117 EXPECT_EQ(ERR_IO_PENDING, rv);
3118
[email protected]9172a982009-06-06 00:30:253119 rv = callback.WaitForResult();
3120 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3121}
3122
[email protected]89ceba9a2009-03-21 03:46:063123} // namespace net