blob: a8de9623cbc3406ca6c5951092b72e03d6b12a5d [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]ff007e162009-05-23 09:13:1510#include "net/base/socket_test_util.h"
[email protected]bacff652009-03-31 17:50:3311#include "net/base/ssl_client_socket.h"
12#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5213#include "net/base/test_completion_callback.h"
14#include "net/base/upload_data.h"
[email protected]385a4672009-03-11 22:21:2915#include "net/http/http_auth_handler_ntlm.h"
initial.commit586acc5fe2008-07-26 22:42:5216#include "net/http/http_network_session.h"
17#include "net/http/http_network_transaction.h"
18#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5319#include "net/proxy/proxy_config_service_fixed.h"
initial.commit586acc5fe2008-07-26 22:42:5220#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1521#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5222
23//-----------------------------------------------------------------------------
24
[email protected]89ceba9a2009-03-21 03:46:0625namespace net {
26
[email protected]db8f44c2008-12-13 04:52:0127// Create a proxy service which fails on all requests (falls back to direct).
[email protected]1c773ea12009-04-28 19:58:4228ProxyService* CreateNullProxyService() {
29 return ProxyService::CreateNull();
initial.commit586acc5fe2008-07-26 22:42:5230}
31
[email protected]228ff742009-06-05 01:19:5932// Helper to manage the lifetimes of the dependencies for a HttpNetworkTransaction.
33class SessionDependencies {
34 public:
35 // Default set of dependencies -- "null" proxy service.
36 SessionDependencies() : proxy_service(CreateNullProxyService()) {}
37
38 // Custom proxy service dependency.
39 SessionDependencies(ProxyService* proxy_service)
40 : proxy_service(proxy_service) {}
41
42 scoped_ptr<ProxyService> proxy_service;
43 MockClientSocketFactory socket_factory;
44};
45
[email protected]1c773ea12009-04-28 19:58:4246ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5047 net::ProxyConfig proxy_config;
48 proxy_config.proxy_rules.ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3949 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5350}
51
52
[email protected]228ff742009-06-05 01:19:5953HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
54 return new HttpNetworkSession(session_deps->proxy_service.get(),
55 &session_deps->socket_factory);
[email protected]e8d536192008-10-17 22:21:1456}
57
[email protected]89836e22008-09-25 20:33:4258class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5259 public:
[email protected]0e75a732008-10-16 20:36:0960 virtual void TearDown() {
61 // Empty the current queue.
62 MessageLoop::current()->RunAllPending();
63 PlatformTest::TearDown();
64 }
65
[email protected]3d2a59b2008-09-26 19:44:2566 protected:
67 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5268
[email protected]ff007e162009-05-23 09:13:1569 struct SimpleGetHelperResult {
70 int rv;
71 std::string status_line;
72 std::string response_data;
73 };
initial.commit586acc5fe2008-07-26 22:42:5274
[email protected]ff007e162009-05-23 09:13:1575 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
76 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:5277
[email protected]228ff742009-06-05 01:19:5978 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:4079 scoped_ptr<HttpTransaction> trans(
80 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:5981 CreateSession(&session_deps),
82 &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:5283
[email protected]ff007e162009-05-23 09:13:1584 HttpRequestInfo request;
85 request.method = "GET";
86 request.url = GURL("http://www.google.com/");
87 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:5288
[email protected]ff007e162009-05-23 09:13:1589 MockSocket data;
90 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:5991 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:5292
[email protected]ff007e162009-05-23 09:13:1593 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:5294
[email protected]ff007e162009-05-23 09:13:1595 int rv = trans->Start(&request, &callback);
96 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:5297
[email protected]ff007e162009-05-23 09:13:1598 out.rv = callback.WaitForResult();
99 if (out.rv != OK)
100 return out;
101
102 const HttpResponseInfo* response = trans->GetResponseInfo();
103 EXPECT_TRUE(response != NULL);
104
105 EXPECT_TRUE(response->headers != NULL);
106 out.status_line = response->headers->GetStatusLine();
107
108 rv = ReadTransaction(trans.get(), &out.response_data);
109 EXPECT_EQ(OK, rv);
110
[email protected]aecfbf22008-10-16 02:02:47111 return out;
[email protected]ff007e162009-05-23 09:13:15112 }
initial.commit586acc5fe2008-07-26 22:42:52113
[email protected]ff007e162009-05-23 09:13:15114 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
115 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52116
[email protected]ff007e162009-05-23 09:13:15117 void ConnectStatusHelper(const MockRead& status);
initial.commit586acc5fe2008-07-26 22:42:52118
[email protected]ff007e162009-05-23 09:13:15119};
[email protected]231d5a32008-09-13 00:45:27120
[email protected]15a5ccf82008-10-23 19:57:43121// Fill |str| with a long header list that consumes >= |size| bytes.
122void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19123 const char* row =
124 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
125 const int sizeof_row = strlen(row);
126 const int num_rows = static_cast<int>(
127 ceil(static_cast<float>(size) / sizeof_row));
128 const int sizeof_data = num_rows * sizeof_row;
129 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43130 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51131
[email protected]4ddaf2502008-10-23 18:26:19132 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43133 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19134}
135
[email protected]385a4672009-03-11 22:21:29136// Alternative functions that eliminate randomness and dependency on the local
137// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20138void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29139 static const uint8 bytes[] = {
140 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
141 };
142 static size_t current_byte = 0;
143 for (size_t i = 0; i < n; ++i) {
144 output[i] = bytes[current_byte++];
145 current_byte %= arraysize(bytes);
146 }
147}
148
[email protected]fe2bc6a2009-03-23 16:52:20149void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29150 static const uint8 bytes[] = {
151 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
152 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
153 };
154 static size_t current_byte = 0;
155 for (size_t i = 0; i < n; ++i) {
156 output[i] = bytes[current_byte++];
157 current_byte %= arraysize(bytes);
158 }
159}
160
[email protected]fe2bc6a2009-03-23 16:52:20161std::string MockGetHostName() {
162 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29163}
164
[email protected]231d5a32008-09-13 00:45:27165//-----------------------------------------------------------------------------
166
167TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59168 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40169 scoped_ptr<HttpTransaction> trans(
170 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59171 CreateSession(&session_deps),
172 &session_deps.socket_factory));
[email protected]231d5a32008-09-13 00:45:27173}
174
175TEST_F(HttpNetworkTransactionTest, SimpleGET) {
176 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35177 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
178 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42179 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27180 };
[email protected]231d5a32008-09-13 00:45:27181 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42182 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27183 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
184 EXPECT_EQ("hello world", out.response_data);
185}
186
187// Response with no status line.
188TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
189 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35190 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42191 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27192 };
[email protected]231d5a32008-09-13 00:45:27193 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42194 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27195 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
196 EXPECT_EQ("hello world", out.response_data);
197}
198
199// Allow up to 4 bytes of junk to precede status line.
200TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
201 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35202 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42203 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27204 };
205 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42206 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27207 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
208 EXPECT_EQ("DATA", out.response_data);
209}
210
211// Allow up to 4 bytes of junk to precede status line.
212TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
213 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35214 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42215 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27216 };
217 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42218 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27219 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
220 EXPECT_EQ("DATA", out.response_data);
221}
222
223// Beyond 4 bytes of slop and it should fail to find a status line.
224TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
225 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35226 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42227 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27228 };
229 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42230 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25231 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
232 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27233}
234
235// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
236TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
237 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35238 MockRead("\n"),
239 MockRead("\n"),
240 MockRead("Q"),
241 MockRead("J"),
242 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42243 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27244 };
245 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42246 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27247 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
248 EXPECT_EQ("DATA", out.response_data);
249}
250
251// Close the connection before enough bytes to have a status line.
252TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
253 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35254 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42255 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27256 };
257 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42258 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27259 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
260 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52261}
262
[email protected]f9d44aa2008-09-23 23:57:17263// Simulate a 204 response, lacking a Content-Length header, sent over a
264// persistent connection. The response should still terminate since a 204
265// cannot have a response body.
266TEST_F(HttpNetworkTransactionTest, StopsReading204) {
267 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35268 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
269 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42270 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17271 };
272 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42273 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17274 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
275 EXPECT_EQ("", out.response_data);
276}
277
[email protected]ef0faf2e72009-03-05 23:27:23278// Do a request using the HEAD method. Verify that we don't try to read the
279// message body (since HEAD has none).
280TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59281 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40282 scoped_ptr<HttpTransaction> trans(
283 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59284 CreateSession(&session_deps),
285 &session_deps.socket_factory));
[email protected]ef0faf2e72009-03-05 23:27:23286
[email protected]1c773ea12009-04-28 19:58:42287 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23288 request.method = "HEAD";
289 request.url = GURL("http://www.google.com/");
290 request.load_flags = 0;
291
292 MockWrite data_writes1[] = {
293 MockWrite("HEAD / HTTP/1.1\r\n"
294 "Host: www.google.com\r\n"
295 "Connection: keep-alive\r\n"
296 "Content-Length: 0\r\n\r\n"),
297 };
298 MockRead data_reads1[] = {
299 MockRead("HTTP/1.1 404 Not Found\r\n"),
300 MockRead("Server: Blah\r\n"),
301 MockRead("Content-Length: 1234\r\n\r\n"),
302
303 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42304 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23305 };
306
307 MockSocket data1;
308 data1.reads = data_reads1;
309 data1.writes = data_writes1;
[email protected]228ff742009-06-05 01:19:59310 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23311
312 TestCompletionCallback callback1;
313
314 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42315 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23316
317 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42318 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23319
[email protected]1c773ea12009-04-28 19:58:42320 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23321 EXPECT_FALSE(response == NULL);
322
323 // Check that the headers got parsed.
324 EXPECT_TRUE(response->headers != NULL);
325 EXPECT_EQ(1234, response->headers->GetContentLength());
326 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
327
328 std::string server_header;
329 void* iter = NULL;
330 bool has_server_header = response->headers->EnumerateHeader(
331 &iter, "Server", &server_header);
332 EXPECT_TRUE(has_server_header);
333 EXPECT_EQ("Blah", server_header);
334
335 // Reading should give EOF right away, since there is no message body
336 // (despite non-zero content-length).
337 std::string response_data;
338 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42339 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23340 EXPECT_EQ("", response_data);
341}
342
initial.commit586acc5fe2008-07-26 22:42:52343TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59344 SessionDependencies session_deps;
345 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52346
347 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35348 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
349 MockRead("hello"),
350 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
351 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42352 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52353 };
354 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52355 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:59356 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52357
358 const char* kExpectedResponseData[] = {
359 "hello", "world"
360 };
361
362 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42363 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:59364 new HttpNetworkTransaction(session, &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52365
[email protected]1c773ea12009-04-28 19:58:42366 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52367 request.method = "GET";
368 request.url = GURL("http://www.google.com/");
369 request.load_flags = 0;
370
371 TestCompletionCallback callback;
372
373 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42374 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52375
376 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42377 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52378
[email protected]1c773ea12009-04-28 19:58:42379 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52380 EXPECT_TRUE(response != NULL);
381
382 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25383 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52384
385 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57386 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42387 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25388 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52389 }
390}
391
392TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59393 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40394 scoped_ptr<HttpTransaction> trans(
395 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59396 CreateSession(&session_deps),
397 &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52398
[email protected]1c773ea12009-04-28 19:58:42399 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52400 request.method = "POST";
401 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42402 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52403 request.upload_data->AppendBytes("foo", 3);
404 request.load_flags = 0;
405
406 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35407 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
408 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
409 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42410 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52411 };
412 MockSocket data;
initial.commit586acc5fe2008-07-26 22:42:52413 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:59414 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52415
416 TestCompletionCallback callback;
417
418 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42419 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52420
421 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42422 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52423
[email protected]1c773ea12009-04-28 19:58:42424 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52425 EXPECT_TRUE(response != NULL);
426
427 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25428 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52429
430 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57431 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42432 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25433 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52434}
435
[email protected]3a2d3662009-03-27 03:49:14436// This test is almost the same as Ignores100 above, but the response contains
437// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
438// HTTP/1.1.
439TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59440 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40441 scoped_ptr<HttpTransaction> trans(
442 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59443 CreateSession(&session_deps),
444 &session_deps.socket_factory));
[email protected]3a2d3662009-03-27 03:49:14445
[email protected]1c773ea12009-04-28 19:58:42446 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14447 request.method = "GET";
448 request.url = GURL("http://www.foo.com/");
449 request.load_flags = 0;
450
451 MockRead data_reads[] = {
452 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"),
453 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
454 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42455 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14456 };
457 MockSocket data;
458 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:59459 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3a2d3662009-03-27 03:49:14460
461 TestCompletionCallback callback;
462
463 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42464 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14465
466 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42467 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14468
[email protected]1c773ea12009-04-28 19:58:42469 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14470 EXPECT_TRUE(response != NULL);
471
472 EXPECT_TRUE(response->headers != NULL);
473 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
474
475 std::string response_data;
476 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42477 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14478 EXPECT_EQ("hello world", response_data);
479}
480
[email protected]3d2a59b2008-09-26 19:44:25481// read_failure specifies a read failure that should cause the network
482// transaction to resend the request.
483void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
484 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59485 SessionDependencies session_deps;
486 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52487
[email protected]1c773ea12009-04-28 19:58:42488 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52489 request.method = "GET";
490 request.url = GURL("http://www.foo.com/");
491 request.load_flags = 0;
492
493 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35494 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
495 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25496 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52497 };
498 MockSocket data1;
initial.commit586acc5fe2008-07-26 22:42:52499 data1.reads = data1_reads;
[email protected]228ff742009-06-05 01:19:59500 session_deps.socket_factory.AddMockSocket(&data1);
initial.commit586acc5fe2008-07-26 22:42:52501
502 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35503 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
504 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42505 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52506 };
507 MockSocket data2;
initial.commit586acc5fe2008-07-26 22:42:52508 data2.reads = data2_reads;
[email protected]228ff742009-06-05 01:19:59509 session_deps.socket_factory.AddMockSocket(&data2);
initial.commit586acc5fe2008-07-26 22:42:52510
511 const char* kExpectedResponseData[] = {
512 "hello", "world"
513 };
514
515 for (int i = 0; i < 2; ++i) {
516 TestCompletionCallback callback;
517
[email protected]1c773ea12009-04-28 19:58:42518 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:59519 new HttpNetworkTransaction(session, &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52520
521 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42522 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52523
524 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42525 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52526
[email protected]1c773ea12009-04-28 19:58:42527 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52528 EXPECT_TRUE(response != NULL);
529
530 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25531 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52532
533 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57534 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42535 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25536 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52537 }
538}
[email protected]3d2a59b2008-09-26 19:44:25539
540TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42541 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25542 KeepAliveConnectionResendRequestTest(read_failure);
543}
544
545TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42546 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25547 KeepAliveConnectionResendRequestTest(read_failure);
548}
549
550TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59551 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40552 scoped_ptr<HttpTransaction> trans(
553 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59554 CreateSession(&session_deps),
555 &session_deps.socket_factory));
[email protected]3d2a59b2008-09-26 19:44:25556
[email protected]1c773ea12009-04-28 19:58:42557 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25558 request.method = "GET";
559 request.url = GURL("http://www.google.com/");
560 request.load_flags = 0;
561
562 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42563 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35564 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
565 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42566 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25567 };
568 MockSocket data;
[email protected]3d2a59b2008-09-26 19:44:25569 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:59570 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3d2a59b2008-09-26 19:44:25571
572 TestCompletionCallback callback;
573
574 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42575 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25576
577 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42578 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25579
[email protected]1c773ea12009-04-28 19:58:42580 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25581 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25582}
583
584// What do various browsers do when the server closes a non-keepalive
585// connection without sending any response header or body?
586//
587// IE7: error page
588// Safari 3.1.2 (Windows): error page
589// Firefox 3.0.1: blank page
590// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42591// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
592// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25593TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
594 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42595 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35596 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
597 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42598 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25599 };
600 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42601 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25602}
[email protected]038e9a32008-10-08 22:40:16603
604// Test the request-challenge-retry sequence for basic auth.
605// (basic auth is the easiest to mock, because it has no randomness).
606TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59607 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40608 scoped_ptr<HttpTransaction> trans(
609 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59610 CreateSession(&session_deps),
611 &session_deps.socket_factory));
[email protected]038e9a32008-10-08 22:40:16612
[email protected]1c773ea12009-04-28 19:58:42613 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16614 request.method = "GET";
615 request.url = GURL("http://www.google.com/");
616 request.load_flags = 0;
617
[email protected]f9ee6b52008-11-08 06:46:23618 MockWrite data_writes1[] = {
619 MockWrite("GET / HTTP/1.1\r\n"
620 "Host: www.google.com\r\n"
621 "Connection: keep-alive\r\n\r\n"),
622 };
623
[email protected]038e9a32008-10-08 22:40:16624 MockRead data_reads1[] = {
625 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
626 // Give a couple authenticate options (only the middle one is actually
627 // supported).
[email protected]aaead502008-10-15 00:20:11628 MockRead("WWW-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16629 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
630 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
631 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
632 // Large content-length -- won't matter, as connection will be reset.
633 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42634 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16635 };
636
637 // After calling trans->RestartWithAuth(), this is the request we should
638 // be issuing -- the final header line contains the credentials.
639 MockWrite data_writes2[] = {
640 MockWrite("GET / HTTP/1.1\r\n"
641 "Host: www.google.com\r\n"
642 "Connection: keep-alive\r\n"
643 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
644 };
645
646 // Lastly, the server responds with the actual content.
647 MockRead data_reads2[] = {
648 MockRead("HTTP/1.0 200 OK\r\n"),
649 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
650 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42651 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16652 };
653
654 MockSocket data1;
655 data1.reads = data_reads1;
[email protected]f9ee6b52008-11-08 06:46:23656 data1.writes = data_writes1;
[email protected]038e9a32008-10-08 22:40:16657 MockSocket data2;
658 data2.reads = data_reads2;
659 data2.writes = data_writes2;
[email protected]228ff742009-06-05 01:19:59660 session_deps.socket_factory.AddMockSocket(&data1);
661 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]038e9a32008-10-08 22:40:16662
663 TestCompletionCallback callback1;
664
665 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42666 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16667
668 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42669 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16670
[email protected]1c773ea12009-04-28 19:58:42671 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16672 EXPECT_FALSE(response == NULL);
673
674 // The password prompt info should have been set in response->auth_challenge.
675 EXPECT_FALSE(response->auth_challenge.get() == NULL);
676
[email protected]71e4573a2009-05-21 22:03:00677 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16678 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
679 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
680
681 TestCompletionCallback callback2;
682
683 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42684 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16685
686 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42687 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16688
689 response = trans->GetResponseInfo();
690 EXPECT_FALSE(response == NULL);
691 EXPECT_TRUE(response->auth_challenge.get() == NULL);
692 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16693}
694
[email protected]2d2697f92009-02-18 21:00:32695// Test the request-challenge-retry sequence for basic auth, over a keep-alive
696// connection.
697TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59698 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40699 scoped_ptr<HttpTransaction> trans(
700 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59701 CreateSession(&session_deps),
702 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32703
[email protected]1c773ea12009-04-28 19:58:42704 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32705 request.method = "GET";
706 request.url = GURL("http://www.google.com/");
707 request.load_flags = 0;
708
709 MockWrite data_writes1[] = {
710 MockWrite("GET / HTTP/1.1\r\n"
711 "Host: www.google.com\r\n"
712 "Connection: keep-alive\r\n\r\n"),
713
714 // After calling trans->RestartWithAuth(), this is the request we should
715 // be issuing -- the final header line contains the credentials.
716 MockWrite("GET / HTTP/1.1\r\n"
717 "Host: www.google.com\r\n"
718 "Connection: keep-alive\r\n"
719 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
720 };
721
722 MockRead data_reads1[] = {
723 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
724 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
725 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
726 MockRead("Content-Length: 14\r\n\r\n"),
727 MockRead("Unauthorized\r\n"),
728
729 // Lastly, the server responds with the actual content.
730 MockRead("HTTP/1.1 200 OK\r\n"),
731 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
732 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42733 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32734 };
735
736 MockSocket data1;
737 data1.reads = data_reads1;
738 data1.writes = data_writes1;
[email protected]228ff742009-06-05 01:19:59739 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32740
741 TestCompletionCallback callback1;
742
743 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42744 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32745
746 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42747 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32748
[email protected]1c773ea12009-04-28 19:58:42749 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32750 EXPECT_FALSE(response == NULL);
751
752 // The password prompt info should have been set in response->auth_challenge.
753 EXPECT_FALSE(response->auth_challenge.get() == NULL);
754
[email protected]71e4573a2009-05-21 22:03:00755 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32756 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
757 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
758
759 TestCompletionCallback callback2;
760
761 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42762 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32763
764 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42765 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32766
767 response = trans->GetResponseInfo();
768 EXPECT_FALSE(response == NULL);
769 EXPECT_TRUE(response->auth_challenge.get() == NULL);
770 EXPECT_EQ(100, response->headers->GetContentLength());
771}
772
773// Test the request-challenge-retry sequence for basic auth, over a keep-alive
774// connection and with no response body to drain.
775TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59776 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40777 scoped_ptr<HttpTransaction> trans(
778 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59779 CreateSession(&session_deps),
780 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32781
[email protected]1c773ea12009-04-28 19:58:42782 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32783 request.method = "GET";
784 request.url = GURL("http://www.google.com/");
785 request.load_flags = 0;
786
787 MockWrite data_writes1[] = {
788 MockWrite("GET / HTTP/1.1\r\n"
789 "Host: www.google.com\r\n"
790 "Connection: keep-alive\r\n\r\n"),
791
792 // After calling trans->RestartWithAuth(), this is the request we should
793 // be issuing -- the final header line contains the credentials.
794 MockWrite("GET / HTTP/1.1\r\n"
795 "Host: www.google.com\r\n"
796 "Connection: keep-alive\r\n"
797 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
798 };
799
800 // Respond with 5 kb of response body.
801 std::string large_body_string("Unauthorized");
802 large_body_string.append(5 * 1024, ' ');
803 large_body_string.append("\r\n");
804
805 MockRead data_reads1[] = {
806 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
807 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
808 MockRead("Content-Length: 0\r\n\r\n"),
809
810 // Lastly, the server responds with the actual content.
811 MockRead("HTTP/1.1 200 OK\r\n"),
812 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
813 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42814 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32815 };
816
817 MockSocket data1;
818 data1.reads = data_reads1;
819 data1.writes = data_writes1;
[email protected]228ff742009-06-05 01:19:59820 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32821
822 TestCompletionCallback callback1;
823
824 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42825 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32826
827 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42828 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32829
[email protected]1c773ea12009-04-28 19:58:42830 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32831 EXPECT_FALSE(response == NULL);
832
833 // The password prompt info should have been set in response->auth_challenge.
834 EXPECT_FALSE(response->auth_challenge.get() == NULL);
835
[email protected]71e4573a2009-05-21 22:03:00836 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32837 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
838 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
839
840 TestCompletionCallback callback2;
841
842 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42843 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32844
845 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42846 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32847
848 response = trans->GetResponseInfo();
849 EXPECT_FALSE(response == NULL);
850 EXPECT_TRUE(response->auth_challenge.get() == NULL);
851 EXPECT_EQ(100, response->headers->GetContentLength());
852}
853
854// Test the request-challenge-retry sequence for basic auth, over a keep-alive
855// connection and with a large response body to drain.
856TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:59857 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40858 scoped_ptr<HttpTransaction> trans(
859 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59860 CreateSession(&session_deps),
861 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32862
[email protected]1c773ea12009-04-28 19:58:42863 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32864 request.method = "GET";
865 request.url = GURL("http://www.google.com/");
866 request.load_flags = 0;
867
868 MockWrite data_writes1[] = {
869 MockWrite("GET / HTTP/1.1\r\n"
870 "Host: www.google.com\r\n"
871 "Connection: keep-alive\r\n\r\n"),
872
873 // After calling trans->RestartWithAuth(), this is the request we should
874 // be issuing -- the final header line contains the credentials.
875 MockWrite("GET / HTTP/1.1\r\n"
876 "Host: www.google.com\r\n"
877 "Connection: keep-alive\r\n"
878 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
879 };
880
881 // Respond with 5 kb of response body.
882 std::string large_body_string("Unauthorized");
883 large_body_string.append(5 * 1024, ' ');
884 large_body_string.append("\r\n");
885
886 MockRead data_reads1[] = {
887 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
888 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
889 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
890 // 5134 = 12 + 5 * 1024 + 2
891 MockRead("Content-Length: 5134\r\n\r\n"),
892 MockRead(true, large_body_string.data(), large_body_string.size()),
893
894 // Lastly, the server responds with the actual content.
895 MockRead("HTTP/1.1 200 OK\r\n"),
896 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
897 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42898 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32899 };
900
901 MockSocket data1;
902 data1.reads = data_reads1;
903 data1.writes = data_writes1;
[email protected]228ff742009-06-05 01:19:59904 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32905
906 TestCompletionCallback callback1;
907
908 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42909 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32910
911 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42912 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32913
[email protected]1c773ea12009-04-28 19:58:42914 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32915 EXPECT_FALSE(response == NULL);
916
917 // The password prompt info should have been set in response->auth_challenge.
918 EXPECT_FALSE(response->auth_challenge.get() == NULL);
919
[email protected]71e4573a2009-05-21 22:03:00920 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32921 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
922 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
923
924 TestCompletionCallback callback2;
925
926 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42927 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32928
929 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42930 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32931
932 response = trans->GetResponseInfo();
933 EXPECT_FALSE(response == NULL);
934 EXPECT_TRUE(response->auth_challenge.get() == NULL);
935 EXPECT_EQ(100, response->headers->GetContentLength());
936}
937
938// Test the request-challenge-retry sequence for basic auth, over a keep-alive
939// proxy connection, when setting up an SSL tunnel.
940TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
941 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:59942 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
943 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:32944
[email protected]1c773ea12009-04-28 19:58:42945 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59946 session.get(), &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32947
[email protected]1c773ea12009-04-28 19:58:42948 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32949 request.method = "GET";
950 request.url = GURL("https://www.google.com/");
951 request.load_flags = 0;
952
953 // Since we have proxy, should try to establish tunnel.
954 MockWrite data_writes1[] = {
955 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
956 "Host: www.google.com\r\n\r\n"),
957
958 // After calling trans->RestartWithAuth(), this is the request we should
959 // be issuing -- the final header line contains the credentials.
960 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
961 "Host: www.google.com\r\n"
962 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
963 };
964
965 // The proxy responds to the connect with a 407, using a persistent
966 // connection.
967 MockRead data_reads1[] = {
968 // No credentials.
969 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
970 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
971 MockRead("Content-Length: 10\r\n\r\n"),
972 MockRead("0123456789"),
973
974 // Wrong credentials (wrong password).
975 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
976 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
977 MockRead("Content-Length: 10\r\n\r\n"),
978 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42979 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:32980 };
981
982 MockSocket data1;
983 data1.writes = data_writes1;
984 data1.reads = data_reads1;
[email protected]228ff742009-06-05 01:19:59985 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32986
987 TestCompletionCallback callback1;
988
989 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42990 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32991
992 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42993 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32994
[email protected]1c773ea12009-04-28 19:58:42995 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32996 EXPECT_FALSE(response == NULL);
997
998 EXPECT_TRUE(response->headers->IsKeepAlive());
999 EXPECT_EQ(407, response->headers->response_code());
1000 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421001 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321002
1003 // The password prompt info should have been set in response->auth_challenge.
1004 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1005
[email protected]71e4573a2009-05-21 22:03:001006 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321007 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1008 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1009
1010 TestCompletionCallback callback2;
1011
1012 // Wrong password (should be "bar").
1013 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421014 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321015
1016 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421017 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321018
1019 response = trans->GetResponseInfo();
1020 EXPECT_FALSE(response == NULL);
1021
1022 EXPECT_TRUE(response->headers->IsKeepAlive());
1023 EXPECT_EQ(407, response->headers->response_code());
1024 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421025 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321026
1027 // The password prompt info should have been set in response->auth_challenge.
1028 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1029
[email protected]71e4573a2009-05-21 22:03:001030 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321031 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1032 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1033}
1034
[email protected]a8e9b162009-03-12 00:06:441035// Test that we don't read the response body when we fail to establish a tunnel,
1036// even if the user cancels the proxy's auth attempt.
1037TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1038 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591039 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441040
[email protected]228ff742009-06-05 01:19:591041 scoped_refptr<HttpNetworkSession> session( CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441042
[email protected]1c773ea12009-04-28 19:58:421043 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591044 session.get(), &session_deps.socket_factory));
[email protected]a8e9b162009-03-12 00:06:441045
[email protected]1c773ea12009-04-28 19:58:421046 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441047 request.method = "GET";
1048 request.url = GURL("https://www.google.com/");
1049 request.load_flags = 0;
1050
1051 // Since we have proxy, should try to establish tunnel.
1052 MockWrite data_writes[] = {
1053 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1054 "Host: www.google.com\r\n\r\n"),
1055 };
1056
1057 // The proxy responds to the connect with a 407.
1058 MockRead data_reads[] = {
1059 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1060 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1061 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421062 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441063 };
1064
1065 MockSocket data;
1066 data.writes = data_writes;
1067 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:591068 session_deps.socket_factory.AddMockSocket(&data);
[email protected]a8e9b162009-03-12 00:06:441069
1070 TestCompletionCallback callback;
1071
1072 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421073 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441074
1075 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421076 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441077
[email protected]1c773ea12009-04-28 19:58:421078 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441079 EXPECT_FALSE(response == NULL);
1080
1081 EXPECT_TRUE(response->headers->IsKeepAlive());
1082 EXPECT_EQ(407, response->headers->response_code());
1083 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421084 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441085
1086 std::string response_data;
1087 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421088 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441089}
1090
[email protected]ff007e162009-05-23 09:13:151091void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081092 const MockRead& status, int expected_status) {
1093 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591094 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081095
[email protected]228ff742009-06-05 01:19:591096 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081097
[email protected]1c773ea12009-04-28 19:58:421098 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591099 session.get(), &session_deps.socket_factory));
[email protected]c744cf22009-02-27 07:28:081100
[email protected]1c773ea12009-04-28 19:58:421101 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081102 request.method = "GET";
1103 request.url = GURL("https://www.google.com/");
1104 request.load_flags = 0;
1105
1106 // Since we have proxy, should try to establish tunnel.
1107 MockWrite data_writes[] = {
1108 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1109 "Host: www.google.com\r\n\r\n"),
1110 };
1111
1112 MockRead data_reads[] = {
1113 status,
1114 MockRead("Content-Length: 10\r\n\r\n"),
1115 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421116 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081117 };
1118
1119 MockSocket data;
1120 data.writes = data_writes;
1121 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:591122 session_deps.socket_factory.AddMockSocket(&data);
[email protected]c744cf22009-02-27 07:28:081123
1124 TestCompletionCallback callback;
1125
1126 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421127 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081128
1129 rv = callback.WaitForResult();
1130 EXPECT_EQ(expected_status, rv);
1131}
1132
[email protected]ff007e162009-05-23 09:13:151133void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081134 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421135 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081136}
1137
1138TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1139 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1140}
1141
1142TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1143 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1144}
1145
1146TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1147 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1148}
1149
1150TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1151 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1152}
1153
1154TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1155 ConnectStatusHelper(
1156 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1157}
1158
1159TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1160 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1161}
1162
1163TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1164 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1165}
1166
1167TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1168 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1169}
1170
1171TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1172 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1173}
1174
1175TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1176 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1177}
1178
1179TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1180 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1181}
1182
1183TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1184 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1185}
1186
1187TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1188 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1189}
1190
1191TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1192 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1193}
1194
1195TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1196 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1197}
1198
1199TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1200 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1201}
1202
1203TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1204 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1205}
1206
1207TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1208 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1209}
1210
1211TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1212 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1213}
1214
1215TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1216 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1217}
1218
1219TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1220 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1221}
1222
1223TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1224 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1225}
1226
1227TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1228 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1229}
1230
1231TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1232 ConnectStatusHelperWithExpectedStatus(
1233 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421234 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081235}
1236
1237TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1238 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1239}
1240
1241TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1242 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1243}
1244
1245TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1246 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1247}
1248
1249TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1250 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1251}
1252
1253TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1254 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1255}
1256
1257TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1258 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1259}
1260
1261TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1262 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1263}
1264
1265TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1266 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1267}
1268
1269TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1270 ConnectStatusHelper(
1271 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1272}
1273
1274TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1275 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1276}
1277
1278TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1279 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1280}
1281
1282TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1283 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1284}
1285
1286TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1287 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1288}
1289
1290TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1291 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1292}
1293
1294TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1295 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1296}
1297
1298TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1299 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1300}
1301
[email protected]038e9a32008-10-08 22:40:161302// Test the flow when both the proxy server AND origin server require
1303// authentication. Again, this uses basic auth for both since that is
1304// the simplest to mock.
1305TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591306 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011307
[email protected]038e9a32008-10-08 22:40:161308 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421309 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591310 CreateSession(&session_deps),
1311 &session_deps.socket_factory));
[email protected]038e9a32008-10-08 22:40:161312
[email protected]1c773ea12009-04-28 19:58:421313 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161314 request.method = "GET";
1315 request.url = GURL("http://www.google.com/");
1316 request.load_flags = 0;
1317
[email protected]f9ee6b52008-11-08 06:46:231318 MockWrite data_writes1[] = {
1319 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1320 "Host: www.google.com\r\n"
1321 "Proxy-Connection: keep-alive\r\n\r\n"),
1322 };
1323
[email protected]038e9a32008-10-08 22:40:161324 MockRead data_reads1[] = {
1325 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1326 // Give a couple authenticate options (only the middle one is actually
1327 // supported).
[email protected]aaead502008-10-15 00:20:111328 MockRead("Proxy-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:161329 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1330 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1331 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1332 // Large content-length -- won't matter, as connection will be reset.
1333 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421334 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161335 };
1336
1337 // After calling trans->RestartWithAuth() the first time, this is the
1338 // request we should be issuing -- the final header line contains the
1339 // proxy's credentials.
1340 MockWrite data_writes2[] = {
1341 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1342 "Host: www.google.com\r\n"
1343 "Proxy-Connection: keep-alive\r\n"
1344 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1345 };
1346
1347 // Now the proxy server lets the request pass through to origin server.
1348 // The origin server responds with a 401.
1349 MockRead data_reads2[] = {
1350 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1351 // Note: We are using the same realm-name as the proxy server. This is
1352 // completely valid, as realms are unique across hosts.
1353 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1354 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1355 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421356 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161357 };
1358
1359 // After calling trans->RestartWithAuth() the second time, we should send
1360 // the credentials for both the proxy and origin server.
1361 MockWrite data_writes3[] = {
1362 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1363 "Host: www.google.com\r\n"
1364 "Proxy-Connection: keep-alive\r\n"
1365 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1366 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1367 };
1368
1369 // Lastly we get the desired content.
1370 MockRead data_reads3[] = {
1371 MockRead("HTTP/1.0 200 OK\r\n"),
1372 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1373 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421374 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161375 };
1376
1377 MockSocket data1;
1378 data1.reads = data_reads1;
[email protected]f9ee6b52008-11-08 06:46:231379 data1.writes = data_writes1;
[email protected]038e9a32008-10-08 22:40:161380 MockSocket data2;
1381 data2.reads = data_reads2;
1382 data2.writes = data_writes2;
1383 MockSocket data3;
1384 data3.reads = data_reads3;
1385 data3.writes = data_writes3;
[email protected]228ff742009-06-05 01:19:591386 session_deps.socket_factory.AddMockSocket(&data1);
1387 session_deps.socket_factory.AddMockSocket(&data2);
1388 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]038e9a32008-10-08 22:40:161389
1390 TestCompletionCallback callback1;
1391
1392 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421393 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161394
1395 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421396 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161397
[email protected]1c773ea12009-04-28 19:58:421398 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161399 EXPECT_FALSE(response == NULL);
1400
1401 // The password prompt info should have been set in response->auth_challenge.
1402 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1403
[email protected]71e4573a2009-05-21 22:03:001404 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161405 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1406 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1407
1408 TestCompletionCallback callback2;
1409
1410 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421411 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161412
1413 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421414 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161415
1416 response = trans->GetResponseInfo();
1417 EXPECT_FALSE(response == NULL);
1418 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1419
[email protected]71e4573a2009-05-21 22:03:001420 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161421 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1422 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1423
1424 TestCompletionCallback callback3;
1425
1426 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421427 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161428
1429 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421430 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161431
1432 response = trans->GetResponseInfo();
1433 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1434 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161435}
[email protected]4ddaf2502008-10-23 18:26:191436
[email protected]385a4672009-03-11 22:21:291437// The NTLM authentication unit tests were generated by capturing the HTTP
1438// requests and responses using Fiddler 2 and inspecting the generated random
1439// bytes in the debugger.
1440
1441// Enter the correct password and authenticate successfully.
1442TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421443 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201444 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591445 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401446 scoped_ptr<HttpTransaction> trans(
1447 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591448 CreateSession(&session_deps),
1449 &session_deps.socket_factory));
[email protected]3f918782009-02-28 01:29:241450
[email protected]1c773ea12009-04-28 19:58:421451 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241452 request.method = "GET";
1453 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1454 request.load_flags = 0;
1455
1456 MockWrite data_writes1[] = {
1457 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1458 "Host: 172.22.68.17\r\n"
1459 "Connection: keep-alive\r\n\r\n"),
1460 };
1461
1462 MockRead data_reads1[] = {
1463 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1464 // Negotiate and NTLM are often requested together. We only support NTLM.
1465 MockRead("WWW-Authenticate: Negotiate\r\n"),
1466 MockRead("WWW-Authenticate: NTLM\r\n"),
1467 MockRead("Connection: close\r\n"),
1468 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361469 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241470 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421471 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241472 };
1473
1474 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221475 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241476 // request we should be issuing -- the final header line contains a Type
1477 // 1 message.
1478 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1479 "Host: 172.22.68.17\r\n"
1480 "Connection: keep-alive\r\n"
1481 "Authorization: NTLM "
1482 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1483
1484 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1485 // (the credentials for the origin server). The second request continues
1486 // on the same connection.
1487 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1488 "Host: 172.22.68.17\r\n"
1489 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291490 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1491 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1492 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1493 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1494 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241495 };
1496
1497 MockRead data_reads2[] = {
1498 // The origin server responds with a Type 2 message.
1499 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1500 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291501 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241502 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1503 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1504 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1505 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1506 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1507 "BtAAAAAAA=\r\n"),
1508 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361509 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241510 MockRead("You are not authorized to view this page\r\n"),
1511
1512 // Lastly we get the desired content.
1513 MockRead("HTTP/1.1 200 OK\r\n"),
1514 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1515 MockRead("Content-Length: 13\r\n\r\n"),
1516 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421517 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241518 };
1519
1520 MockSocket data1;
1521 data1.reads = data_reads1;
1522 data1.writes = data_writes1;
1523 MockSocket data2;
1524 data2.reads = data_reads2;
1525 data2.writes = data_writes2;
[email protected]228ff742009-06-05 01:19:591526 session_deps.socket_factory.AddMockSocket(&data1);
1527 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]3f918782009-02-28 01:29:241528
1529 TestCompletionCallback callback1;
1530
1531 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421532 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241533
1534 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421535 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241536
[email protected]0757e7702009-03-27 04:00:221537 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1538 TestCompletionCallback callback2;
1539 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421540 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221541 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421542 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221543 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1544
[email protected]1c773ea12009-04-28 19:58:421545 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241546 EXPECT_FALSE(response == NULL);
1547
1548 // The password prompt info should have been set in response->auth_challenge.
1549 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1550
[email protected]71e4573a2009-05-21 22:03:001551 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241552 EXPECT_EQ(L"", response->auth_challenge->realm);
1553 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1554
[email protected]0757e7702009-03-27 04:00:221555 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241556
[email protected]0757e7702009-03-27 04:00:221557 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421558 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241559
[email protected]0757e7702009-03-27 04:00:221560 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421561 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241562
1563 response = trans->GetResponseInfo();
1564 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1565 EXPECT_EQ(13, response->headers->GetContentLength());
1566}
1567
[email protected]385a4672009-03-11 22:21:291568// Enter a wrong password, and then the correct one.
1569TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421570 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201571 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591572 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401573 scoped_ptr<HttpTransaction> trans(
1574 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591575 CreateSession(&session_deps),
1576 &session_deps.socket_factory));
[email protected]385a4672009-03-11 22:21:291577
[email protected]1c773ea12009-04-28 19:58:421578 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291579 request.method = "GET";
1580 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1581 request.load_flags = 0;
1582
1583 MockWrite data_writes1[] = {
1584 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1585 "Host: 172.22.68.17\r\n"
1586 "Connection: keep-alive\r\n\r\n"),
1587 };
1588
1589 MockRead data_reads1[] = {
1590 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1591 // Negotiate and NTLM are often requested together. We only support NTLM.
1592 MockRead("WWW-Authenticate: Negotiate\r\n"),
1593 MockRead("WWW-Authenticate: NTLM\r\n"),
1594 MockRead("Connection: close\r\n"),
1595 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361596 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291597 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421598 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291599 };
1600
1601 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221602 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291603 // request we should be issuing -- the final header line contains a Type
1604 // 1 message.
1605 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1606 "Host: 172.22.68.17\r\n"
1607 "Connection: keep-alive\r\n"
1608 "Authorization: NTLM "
1609 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1610
1611 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1612 // (the credentials for the origin server). The second request continues
1613 // on the same connection.
1614 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1615 "Host: 172.22.68.17\r\n"
1616 "Connection: keep-alive\r\n"
1617 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1618 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1619 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1620 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1621 "4Ww7b7E=\r\n\r\n"),
1622 };
1623
1624 MockRead data_reads2[] = {
1625 // The origin server responds with a Type 2 message.
1626 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1627 MockRead("WWW-Authenticate: NTLM "
1628 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1629 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1630 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1631 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1632 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1633 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1634 "BtAAAAAAA=\r\n"),
1635 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361636 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291637 MockRead("You are not authorized to view this page\r\n"),
1638
1639 // Wrong password.
1640 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1641 MockRead("WWW-Authenticate: Negotiate\r\n"),
1642 MockRead("WWW-Authenticate: NTLM\r\n"),
1643 MockRead("Connection: close\r\n"),
1644 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361645 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291646 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421647 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291648 };
1649
1650 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221651 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291652 // request we should be issuing -- the final header line contains a Type
1653 // 1 message.
1654 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1655 "Host: 172.22.68.17\r\n"
1656 "Connection: keep-alive\r\n"
1657 "Authorization: NTLM "
1658 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1659
1660 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1661 // (the credentials for the origin server). The second request continues
1662 // on the same connection.
1663 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1664 "Host: 172.22.68.17\r\n"
1665 "Connection: keep-alive\r\n"
1666 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1667 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1668 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1669 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1670 "+4MUm7c=\r\n\r\n"),
1671 };
1672
1673 MockRead data_reads3[] = {
1674 // The origin server responds with a Type 2 message.
1675 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1676 MockRead("WWW-Authenticate: NTLM "
1677 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1678 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1679 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1680 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1681 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1682 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1683 "BtAAAAAAA=\r\n"),
1684 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361685 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291686 MockRead("You are not authorized to view this page\r\n"),
1687
1688 // Lastly we get the desired content.
1689 MockRead("HTTP/1.1 200 OK\r\n"),
1690 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1691 MockRead("Content-Length: 13\r\n\r\n"),
1692 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421693 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291694 };
1695
1696 MockSocket data1;
1697 data1.reads = data_reads1;
1698 data1.writes = data_writes1;
1699 MockSocket data2;
1700 data2.reads = data_reads2;
1701 data2.writes = data_writes2;
1702 MockSocket data3;
1703 data3.reads = data_reads3;
1704 data3.writes = data_writes3;
[email protected]228ff742009-06-05 01:19:591705 session_deps.socket_factory.AddMockSocket(&data1);
1706 session_deps.socket_factory.AddMockSocket(&data2);
1707 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]385a4672009-03-11 22:21:291708
1709 TestCompletionCallback callback1;
1710
1711 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421712 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291713
1714 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421715 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291716
[email protected]0757e7702009-03-27 04:00:221717 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291718 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221719 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421720 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291721 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421722 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221723 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291724
[email protected]1c773ea12009-04-28 19:58:421725 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291726 EXPECT_FALSE(response == NULL);
1727
1728 // The password prompt info should have been set in response->auth_challenge.
1729 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1730
[email protected]71e4573a2009-05-21 22:03:001731 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291732 EXPECT_EQ(L"", response->auth_challenge->realm);
1733 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1734
1735 TestCompletionCallback callback3;
1736
[email protected]0757e7702009-03-27 04:00:221737 // Enter the wrong password.
1738 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421739 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291740
1741 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421742 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291743
[email protected]0757e7702009-03-27 04:00:221744 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1745 TestCompletionCallback callback4;
1746 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421747 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221748 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421749 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221750 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1751
1752 response = trans->GetResponseInfo();
1753 EXPECT_FALSE(response == NULL);
1754
1755 // The password prompt info should have been set in response->auth_challenge.
1756 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1757
[email protected]71e4573a2009-05-21 22:03:001758 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221759 EXPECT_EQ(L"", response->auth_challenge->realm);
1760 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1761
1762 TestCompletionCallback callback5;
1763
1764 // Now enter the right password.
1765 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421766 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221767
1768 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421769 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221770
[email protected]385a4672009-03-11 22:21:291771 response = trans->GetResponseInfo();
1772 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1773 EXPECT_EQ(13, response->headers->GetContentLength());
1774}
1775
[email protected]4ddaf2502008-10-23 18:26:191776// Test reading a server response which has only headers, and no body.
1777// After some maximum number of bytes is consumed, the transaction should
1778// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
1779TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:591780 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401781 scoped_ptr<HttpTransaction> trans(
1782 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591783 CreateSession(&session_deps),
1784 &session_deps.socket_factory));
[email protected]4ddaf2502008-10-23 18:26:191785
[email protected]1c773ea12009-04-28 19:58:421786 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:191787 request.method = "GET";
1788 request.url = GURL("http://www.google.com/");
1789 request.load_flags = 0;
1790
1791 // Respond with 50 kb of headers (we should fail after 32 kb).
[email protected]15a5ccf82008-10-23 19:57:431792 std::string large_headers_string;
1793 FillLargeHeadersString(&large_headers_string, 50 * 1024);
[email protected]4ddaf2502008-10-23 18:26:191794
1795 MockRead data_reads[] = {
1796 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:431797 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:191798 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:421799 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:191800 };
1801 MockSocket data;
1802 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:591803 session_deps.socket_factory.AddMockSocket(&data);
[email protected]4ddaf2502008-10-23 18:26:191804
1805 TestCompletionCallback callback;
1806
1807 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421808 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:191809
1810 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421811 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:191812
[email protected]1c773ea12009-04-28 19:58:421813 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:191814 EXPECT_TRUE(response == NULL);
1815}
[email protected]f4e426b2008-11-05 00:24:491816
1817// Make sure that we don't try to reuse a TCPClientSocket when failing to
1818// establish tunnel.
1819// http://code.google.com/p/chromium/issues/detail?id=3772
1820TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
1821 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591822 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011823
[email protected]228ff742009-06-05 01:19:591824 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:491825
[email protected]1c773ea12009-04-28 19:58:421826 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591827 session.get(), &session_deps.socket_factory));
[email protected]f4e426b2008-11-05 00:24:491828
[email protected]1c773ea12009-04-28 19:58:421829 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:491830 request.method = "GET";
1831 request.url = GURL("https://www.google.com/");
1832 request.load_flags = 0;
1833
1834 // Since we have proxy, should try to establish tunnel.
1835 MockWrite data_writes1[] = {
1836 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1837 "Host: www.google.com\r\n\r\n"),
1838 };
1839
[email protected]77848d12008-11-14 00:00:221840 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:491841 // connection. Usually a proxy would return 501 (not implemented),
1842 // or 200 (tunnel established).
1843 MockRead data_reads1[] = {
1844 MockRead("HTTP/1.1 404 Not Found\r\n"),
1845 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421846 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:491847 };
1848
1849 MockSocket data1;
1850 data1.writes = data_writes1;
1851 data1.reads = data_reads1;
[email protected]228ff742009-06-05 01:19:591852 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f4e426b2008-11-05 00:24:491853
1854 TestCompletionCallback callback1;
1855
1856 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421857 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:491858
1859 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421860 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:491861
[email protected]1c773ea12009-04-28 19:58:421862 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:081863 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:491864
[email protected]b4404c02009-04-10 16:38:521865 // Empty the current queue. This is necessary because idle sockets are
1866 // added to the connection pool asynchronously with a PostTask.
1867 MessageLoop::current()->RunAllPending();
1868
[email protected]f4e426b2008-11-05 00:24:491869 // We now check to make sure the TCPClientSocket was not added back to
1870 // the pool.
1871 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
1872 trans.reset();
[email protected]b4404c02009-04-10 16:38:521873 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:491874 // Make sure that the socket didn't get recycled after calling the destructor.
1875 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
1876}
[email protected]372d34a2008-11-05 21:30:511877
[email protected]1b157c02009-04-21 01:55:401878// Make sure that we recycle a socket after reading all of the response body.
1879TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:591880 SessionDependencies session_deps;
1881 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:401882
[email protected]1c773ea12009-04-28 19:58:421883 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591884 session.get(), &session_deps.socket_factory));
[email protected]1b157c02009-04-21 01:55:401885
[email protected]1c773ea12009-04-28 19:58:421886 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:401887 request.method = "GET";
1888 request.url = GURL("http://www.google.com/");
1889 request.load_flags = 0;
1890
1891 MockRead data_reads[] = {
1892 // A part of the response body is received with the response headers.
1893 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
1894 // The rest of the response body is received in two parts.
1895 MockRead("lo"),
1896 MockRead(" world"),
1897 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421898 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:401899 };
1900
1901 MockSocket data;
1902 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:591903 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1b157c02009-04-21 01:55:401904
1905 TestCompletionCallback callback;
1906
1907 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421908 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:401909
1910 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421911 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401912
[email protected]1c773ea12009-04-28 19:58:421913 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:401914 EXPECT_TRUE(response != NULL);
1915
1916 EXPECT_TRUE(response->headers != NULL);
1917 std::string status_line = response->headers->GetStatusLine();
1918 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
1919
1920 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
1921
1922 std::string response_data;
1923 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421924 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401925 EXPECT_EQ("hello world", response_data);
1926
1927 // Empty the current queue. This is necessary because idle sockets are
1928 // added to the connection pool asynchronously with a PostTask.
1929 MessageLoop::current()->RunAllPending();
1930
1931 // We now check to make sure the socket was added back to the pool.
1932 EXPECT_EQ(1, session->connection_pool()->idle_socket_count());
1933}
1934
[email protected]b4404c02009-04-10 16:38:521935// Make sure that we recycle a socket after a zero-length response.
1936// http://crbug.com/9880
1937TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:591938 SessionDependencies session_deps;
1939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:521940
[email protected]1c773ea12009-04-28 19:58:421941 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591942 session.get(), &session_deps.socket_factory));
[email protected]b4404c02009-04-10 16:38:521943
[email protected]1c773ea12009-04-28 19:58:421944 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:521945 request.method = "GET";
1946 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
1947 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
1948 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
1949 "rt=prt.2642,ol.2649,xjs.2951");
1950 request.load_flags = 0;
1951
1952 MockRead data_reads[] = {
1953 MockRead("HTTP/1.1 204 No Content\r\n"
1954 "Content-Length: 0\r\n"
1955 "Content-Type: text/html\r\n\r\n"),
1956 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421957 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:521958 };
1959
1960 MockSocket data;
1961 data.reads = data_reads;
[email protected]228ff742009-06-05 01:19:591962 session_deps.socket_factory.AddMockSocket(&data);
[email protected]b4404c02009-04-10 16:38:521963
1964 TestCompletionCallback callback;
1965
1966 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421967 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:521968
1969 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421970 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:521971
[email protected]1c773ea12009-04-28 19:58:421972 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:521973 EXPECT_TRUE(response != NULL);
1974
1975 EXPECT_TRUE(response->headers != NULL);
1976 std::string status_line = response->headers->GetStatusLine();
1977 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
1978
1979 EXPECT_EQ(0, session->connection_pool()->idle_socket_count());
1980
1981 std::string response_data;
1982 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421983 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:521984 EXPECT_EQ("", response_data);
1985
1986 // Empty the current queue. This is necessary because idle sockets are
1987 // added to the connection pool asynchronously with a PostTask.
1988 MessageLoop::current()->RunAllPending();
1989
1990 // We now check to make sure the socket was added back to the pool.
1991 EXPECT_EQ(1, session->connection_pool()->idle_socket_count());
1992}
1993
[email protected]372d34a2008-11-05 21:30:511994TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:421995 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:511996 // Transaction 1: a GET request that succeeds. The socket is recycled
1997 // after use.
1998 request[0].method = "GET";
1999 request[0].url = GURL("http://www.google.com/");
2000 request[0].load_flags = 0;
2001 // Transaction 2: a POST request. Reuses the socket kept alive from
2002 // transaction 1. The first attempts fails when writing the POST data.
2003 // This causes the transaction to retry with a new socket. The second
2004 // attempt succeeds.
2005 request[1].method = "POST";
2006 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422007 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512008 request[1].upload_data->AppendBytes("foo", 3);
2009 request[1].load_flags = 0;
2010
[email protected]228ff742009-06-05 01:19:592011 SessionDependencies session_deps;
2012 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512013
2014 // The first socket is used for transaction 1 and the first attempt of
2015 // transaction 2.
2016
2017 // The response of transaction 1.
2018 MockRead data_reads1[] = {
2019 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2020 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422021 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512022 };
2023 // The mock write results of transaction 1 and the first attempt of
2024 // transaction 2.
2025 MockWrite data_writes1[] = {
2026 MockWrite(false, 64), // GET
2027 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422028 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512029 };
2030 MockSocket data1;
2031 data1.reads = data_reads1;
2032 data1.writes = data_writes1;
2033
2034 // The second socket is used for the second attempt of transaction 2.
2035
2036 // The response of transaction 2.
2037 MockRead data_reads2[] = {
2038 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2039 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422040 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512041 };
2042 // The mock write results of the second attempt of transaction 2.
2043 MockWrite data_writes2[] = {
2044 MockWrite(false, 93), // POST
2045 MockWrite(false, 3), // POST data
2046 };
2047 MockSocket data2;
2048 data2.reads = data_reads2;
2049 data2.writes = data_writes2;
2050
[email protected]228ff742009-06-05 01:19:592051 session_deps.socket_factory.AddMockSocket(&data1);
2052 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]372d34a2008-11-05 21:30:512053
2054 const char* kExpectedResponseData[] = {
2055 "hello world", "welcome"
2056 };
2057
2058 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422059 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:592060 new HttpNetworkTransaction(session, &session_deps.socket_factory));
[email protected]372d34a2008-11-05 21:30:512061
2062 TestCompletionCallback callback;
2063
2064 int rv = trans->Start(&request[i], &callback);
[email protected]1c773ea12009-04-28 19:58:422065 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512066
2067 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422068 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512069
[email protected]1c773ea12009-04-28 19:58:422070 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512071 EXPECT_TRUE(response != NULL);
2072
2073 EXPECT_TRUE(response->headers != NULL);
2074 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2075
2076 std::string response_data;
2077 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422078 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512079 EXPECT_EQ(kExpectedResponseData[i], response_data);
2080 }
2081}
[email protected]f9ee6b52008-11-08 06:46:232082
2083// Test the request-challenge-retry sequence for basic auth when there is
2084// an identity in the URL. The request should be sent as normal, but when
2085// it fails the identity from the URL is used to answer the challenge.
2086TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) {
[email protected]228ff742009-06-05 01:19:592087 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402088 scoped_ptr<HttpTransaction> trans(
2089 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592090 CreateSession(&session_deps),
2091 &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232092
[email protected]1c773ea12009-04-28 19:58:422093 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232094 request.method = "GET";
2095 // Note: the URL has a username:password in it.
2096 request.url = GURL("http://foo:[email protected]/");
2097 request.load_flags = 0;
2098
2099 MockWrite data_writes1[] = {
2100 MockWrite("GET / HTTP/1.1\r\n"
2101 "Host: www.google.com\r\n"
2102 "Connection: keep-alive\r\n\r\n"),
2103 };
2104
2105 MockRead data_reads1[] = {
2106 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2107 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2108 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422109 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232110 };
2111
2112 // After the challenge above, the transaction will be restarted using the
2113 // identity from the url (foo, bar) to answer the challenge.
2114 MockWrite data_writes2[] = {
2115 MockWrite("GET / HTTP/1.1\r\n"
2116 "Host: www.google.com\r\n"
2117 "Connection: keep-alive\r\n"
2118 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2119 };
2120
2121 MockRead data_reads2[] = {
2122 MockRead("HTTP/1.0 200 OK\r\n"),
2123 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422124 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232125 };
2126
2127 MockSocket data1;
2128 data1.reads = data_reads1;
2129 data1.writes = data_writes1;
2130 MockSocket data2;
2131 data2.reads = data_reads2;
2132 data2.writes = data_writes2;
[email protected]228ff742009-06-05 01:19:592133 session_deps.socket_factory.AddMockSocket(&data1);
2134 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232135
2136 TestCompletionCallback callback1;
2137
2138 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422139 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232140
2141 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422142 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232143
[email protected]0757e7702009-03-27 04:00:222144 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2145 TestCompletionCallback callback2;
2146 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422147 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222148 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422149 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222150 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2151
[email protected]1c773ea12009-04-28 19:58:422152 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232153 EXPECT_FALSE(response == NULL);
2154
2155 // There is no challenge info, since the identity in URL worked.
2156 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2157
2158 EXPECT_EQ(100, response->headers->GetContentLength());
2159
2160 // Empty the current queue.
2161 MessageLoop::current()->RunAllPending();
2162}
2163
2164// Test that previously tried username/passwords for a realm get re-used.
2165TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592166 SessionDependencies session_deps;
2167 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232168
2169 // Transaction 1: authenticate (foo, bar) on MyRealm1
2170 {
[email protected]1c773ea12009-04-28 19:58:422171 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592172 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232173
[email protected]1c773ea12009-04-28 19:58:422174 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232175 request.method = "GET";
2176 request.url = GURL("http://www.google.com/x/y/z");
2177 request.load_flags = 0;
2178
2179 MockWrite data_writes1[] = {
2180 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2181 "Host: www.google.com\r\n"
2182 "Connection: keep-alive\r\n\r\n"),
2183 };
2184
2185 MockRead data_reads1[] = {
2186 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2187 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2188 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422189 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232190 };
2191
2192 // Resend with authorization (username=foo, password=bar)
2193 MockWrite data_writes2[] = {
2194 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2195 "Host: www.google.com\r\n"
2196 "Connection: keep-alive\r\n"
2197 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2198 };
2199
2200 // Sever accepts the authorization.
2201 MockRead data_reads2[] = {
2202 MockRead("HTTP/1.0 200 OK\r\n"),
2203 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422204 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232205 };
2206
2207 MockSocket data1;
2208 data1.reads = data_reads1;
2209 data1.writes = data_writes1;
2210 MockSocket data2;
2211 data2.reads = data_reads2;
2212 data2.writes = data_writes2;
[email protected]228ff742009-06-05 01:19:592213 session_deps.socket_factory.AddMockSocket(&data1);
2214 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232215
2216 TestCompletionCallback callback1;
2217
2218 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422219 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232220
2221 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422222 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232223
[email protected]1c773ea12009-04-28 19:58:422224 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232225 EXPECT_FALSE(response == NULL);
2226
2227 // The password prompt info should have been set in
2228 // response->auth_challenge.
2229 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2230
[email protected]71e4573a2009-05-21 22:03:002231 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232232 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2233 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2234
2235 TestCompletionCallback callback2;
2236
2237 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422238 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232239
2240 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422241 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232242
2243 response = trans->GetResponseInfo();
2244 EXPECT_FALSE(response == NULL);
2245 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2246 EXPECT_EQ(100, response->headers->GetContentLength());
2247 }
2248
2249 // ------------------------------------------------------------------------
2250
2251 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2252 {
[email protected]1c773ea12009-04-28 19:58:422253 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592254 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232255
[email protected]1c773ea12009-04-28 19:58:422256 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232257 request.method = "GET";
2258 // Note that Transaction 1 was at /x/y/z, so this is in the same
2259 // protection space as MyRealm1.
2260 request.url = GURL("http://www.google.com/x/y/a/b");
2261 request.load_flags = 0;
2262
2263 MockWrite data_writes1[] = {
2264 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2265 "Host: www.google.com\r\n"
2266 "Connection: keep-alive\r\n"
2267 // Send preemptive authorization for MyRealm1
2268 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2269 };
2270
2271 // The server didn't like the preemptive authorization, and
2272 // challenges us for a different realm (MyRealm2).
2273 MockRead data_reads1[] = {
2274 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2275 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2276 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422277 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232278 };
2279
2280 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2281 MockWrite data_writes2[] = {
2282 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2283 "Host: www.google.com\r\n"
2284 "Connection: keep-alive\r\n"
2285 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2286 };
2287
2288 // Sever accepts the authorization.
2289 MockRead data_reads2[] = {
2290 MockRead("HTTP/1.0 200 OK\r\n"),
2291 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422292 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232293 };
2294
2295 MockSocket data1;
2296 data1.reads = data_reads1;
2297 data1.writes = data_writes1;
2298 MockSocket data2;
2299 data2.reads = data_reads2;
2300 data2.writes = data_writes2;
[email protected]ff007e162009-05-23 09:13:152301
[email protected]228ff742009-06-05 01:19:592302 session_deps.socket_factory.AddMockSocket(&data1);
2303 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232304
2305 TestCompletionCallback callback1;
2306
2307 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422308 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232309
2310 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422311 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232312
[email protected]1c773ea12009-04-28 19:58:422313 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232314 EXPECT_FALSE(response == NULL);
2315
2316 // The password prompt info should have been set in
2317 // response->auth_challenge.
2318 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2319
[email protected]71e4573a2009-05-21 22:03:002320 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232321 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2322 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2323
2324 TestCompletionCallback callback2;
2325
2326 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422327 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232328
2329 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422330 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232331
2332 response = trans->GetResponseInfo();
2333 EXPECT_FALSE(response == NULL);
2334 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2335 EXPECT_EQ(100, response->headers->GetContentLength());
2336 }
2337
2338 // ------------------------------------------------------------------------
2339
2340 // Transaction 3: Resend a request in MyRealm's protection space --
2341 // succeed with preemptive authorization.
2342 {
[email protected]1c773ea12009-04-28 19:58:422343 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592344 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232345
[email protected]1c773ea12009-04-28 19:58:422346 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232347 request.method = "GET";
2348 request.url = GURL("http://www.google.com/x/y/z2");
2349 request.load_flags = 0;
2350
2351 MockWrite data_writes1[] = {
2352 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2353 "Host: www.google.com\r\n"
2354 "Connection: keep-alive\r\n"
2355 // The authorization for MyRealm1 gets sent preemptively
2356 // (since the url is in the same protection space)
2357 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2358 };
2359
2360 // Sever accepts the preemptive authorization
2361 MockRead data_reads1[] = {
2362 MockRead("HTTP/1.0 200 OK\r\n"),
2363 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422364 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232365 };
2366
2367 MockSocket data1;
2368 data1.reads = data_reads1;
2369 data1.writes = data_writes1;
[email protected]228ff742009-06-05 01:19:592370 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f9ee6b52008-11-08 06:46:232371
2372 TestCompletionCallback callback1;
2373
2374 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422375 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232376
2377 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422378 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232379
[email protected]1c773ea12009-04-28 19:58:422380 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232381 EXPECT_FALSE(response == NULL);
2382
2383 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2384 EXPECT_EQ(100, response->headers->GetContentLength());
2385 }
2386
2387 // ------------------------------------------------------------------------
2388
2389 // Transaction 4: request another URL in MyRealm (however the
2390 // url is not known to belong to the protection space, so no pre-auth).
2391 {
[email protected]1c773ea12009-04-28 19:58:422392 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592393 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232394
[email protected]1c773ea12009-04-28 19:58:422395 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232396 request.method = "GET";
2397 request.url = GURL("http://www.google.com/x/1");
2398 request.load_flags = 0;
2399
2400 MockWrite data_writes1[] = {
2401 MockWrite("GET /x/1 HTTP/1.1\r\n"
2402 "Host: www.google.com\r\n"
2403 "Connection: keep-alive\r\n\r\n"),
2404 };
2405
2406 MockRead data_reads1[] = {
2407 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2408 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2409 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422410 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232411 };
2412
2413 // Resend with authorization from MyRealm's cache.
2414 MockWrite data_writes2[] = {
2415 MockWrite("GET /x/1 HTTP/1.1\r\n"
2416 "Host: www.google.com\r\n"
2417 "Connection: keep-alive\r\n"
2418 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2419 };
2420
2421 // Sever accepts the authorization.
2422 MockRead data_reads2[] = {
2423 MockRead("HTTP/1.0 200 OK\r\n"),
2424 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422425 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232426 };
2427
2428 MockSocket data1;
2429 data1.reads = data_reads1;
2430 data1.writes = data_writes1;
2431 MockSocket data2;
2432 data2.reads = data_reads2;
2433 data2.writes = data_writes2;
[email protected]228ff742009-06-05 01:19:592434 session_deps.socket_factory.AddMockSocket(&data1);
2435 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232436
2437 TestCompletionCallback callback1;
2438
2439 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422440 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232441
2442 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422443 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232444
[email protected]0757e7702009-03-27 04:00:222445 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2446 TestCompletionCallback callback2;
2447 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422448 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222449 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422450 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222451 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2452
[email protected]1c773ea12009-04-28 19:58:422453 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232454 EXPECT_FALSE(response == NULL);
2455 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2456 EXPECT_EQ(100, response->headers->GetContentLength());
2457 }
2458
2459 // ------------------------------------------------------------------------
2460
2461 // Transaction 5: request a URL in MyRealm, but the server rejects the
2462 // cached identity. Should invalidate and re-prompt.
2463 {
[email protected]1c773ea12009-04-28 19:58:422464 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592465 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232466
[email protected]1c773ea12009-04-28 19:58:422467 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232468 request.method = "GET";
2469 request.url = GURL("http://www.google.com/p/q/t");
2470 request.load_flags = 0;
2471
2472 MockWrite data_writes1[] = {
2473 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2474 "Host: www.google.com\r\n"
2475 "Connection: keep-alive\r\n\r\n"),
2476 };
2477
2478 MockRead data_reads1[] = {
2479 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2480 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2481 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422482 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232483 };
2484
2485 // Resend with authorization from cache for MyRealm.
2486 MockWrite data_writes2[] = {
2487 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2488 "Host: www.google.com\r\n"
2489 "Connection: keep-alive\r\n"
2490 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2491 };
2492
2493 // Sever rejects the authorization.
2494 MockRead data_reads2[] = {
2495 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2496 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2497 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422498 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232499 };
2500
2501 // At this point we should prompt for new credentials for MyRealm.
2502 // Restart with username=foo3, password=foo4.
2503 MockWrite data_writes3[] = {
2504 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2505 "Host: www.google.com\r\n"
2506 "Connection: keep-alive\r\n"
2507 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2508 };
2509
2510 // Sever accepts the authorization.
2511 MockRead data_reads3[] = {
2512 MockRead("HTTP/1.0 200 OK\r\n"),
2513 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422514 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232515 };
2516
2517 MockSocket data1;
2518 data1.reads = data_reads1;
2519 data1.writes = data_writes1;
2520 MockSocket data2;
2521 data2.reads = data_reads2;
2522 data2.writes = data_writes2;
2523 MockSocket data3;
2524 data3.reads = data_reads3;
2525 data3.writes = data_writes3;
[email protected]228ff742009-06-05 01:19:592526 session_deps.socket_factory.AddMockSocket(&data1);
2527 session_deps.socket_factory.AddMockSocket(&data2);
2528 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]f9ee6b52008-11-08 06:46:232529
2530 TestCompletionCallback callback1;
2531
2532 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422533 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232534
2535 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422536 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232537
[email protected]0757e7702009-03-27 04:00:222538 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2539 TestCompletionCallback callback2;
2540 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422541 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222542 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422543 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222544 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2545
[email protected]1c773ea12009-04-28 19:58:422546 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232547 EXPECT_FALSE(response == NULL);
2548
2549 // The password prompt info should have been set in
2550 // response->auth_challenge.
2551 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2552
[email protected]71e4573a2009-05-21 22:03:002553 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232554 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2555 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2556
[email protected]0757e7702009-03-27 04:00:222557 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232558
[email protected]0757e7702009-03-27 04:00:222559 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422560 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232561
[email protected]0757e7702009-03-27 04:00:222562 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422563 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232564
2565 response = trans->GetResponseInfo();
2566 EXPECT_FALSE(response == NULL);
2567 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2568 EXPECT_EQ(100, response->headers->GetContentLength());
2569 }
2570}
[email protected]89ceba9a2009-03-21 03:46:062571
2572// Test the ResetStateForRestart() private method.
2573TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2574 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592575 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402576 scoped_ptr<HttpNetworkTransaction> trans(
2577 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592578 CreateSession(&session_deps),
2579 &session_deps.socket_factory));
[email protected]89ceba9a2009-03-21 03:46:062580
2581 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]ffeb0882009-04-30 21:51:252582 trans->header_buf_->Realloc(10);
[email protected]89ceba9a2009-03-21 03:46:062583 trans->header_buf_capacity_ = 10;
2584 trans->header_buf_len_ = 3;
2585 trans->header_buf_body_offset_ = 11;
2586 trans->header_buf_http_offset_ = 0;
2587 trans->response_body_length_ = 100;
2588 trans->response_body_read_ = 1;
2589 trans->read_buf_ = new IOBuffer(15);
2590 trans->read_buf_len_ = 15;
[email protected]ffeb0882009-04-30 21:51:252591 trans->request_headers_->headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062592 trans->request_headers_bytes_sent_ = 3;
2593
2594 // Setup state in response_
2595 trans->response_.auth_challenge = new AuthChallengeInfo();
2596 trans->response_.ssl_info.cert_status = -15;
2597 trans->response_.response_time = base::Time::Now();
[email protected]b4404c02009-04-10 16:38:522598 trans->response_.was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062599
2600 { // Setup state for response_.vary_data
2601 HttpRequestInfo request;
2602 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2603 std::replace(temp.begin(), temp.end(), '\n', '\0');
2604 scoped_refptr<HttpResponseHeaders> response = new HttpResponseHeaders(temp);
2605 request.extra_headers = "Foo: 1\nbar: 23";
2606 EXPECT_TRUE(trans->response_.vary_data.Init(request, *response));
2607 }
2608
2609 // Cause the above state to be reset.
2610 trans->ResetStateForRestart();
2611
2612 // Verify that the state that needed to be reset, has been reset.
[email protected]ffeb0882009-04-30 21:51:252613 EXPECT_EQ(NULL, trans->header_buf_->headers());
[email protected]89ceba9a2009-03-21 03:46:062614 EXPECT_EQ(0, trans->header_buf_capacity_);
2615 EXPECT_EQ(0, trans->header_buf_len_);
2616 EXPECT_EQ(-1, trans->header_buf_body_offset_);
2617 EXPECT_EQ(-1, trans->header_buf_http_offset_);
2618 EXPECT_EQ(-1, trans->response_body_length_);
2619 EXPECT_EQ(0, trans->response_body_read_);
2620 EXPECT_EQ(NULL, trans->read_buf_.get());
2621 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]ffeb0882009-04-30 21:51:252622 EXPECT_EQ("", trans->request_headers_->headers_);
[email protected]89ceba9a2009-03-21 03:46:062623 EXPECT_EQ(0U, trans->request_headers_bytes_sent_);
2624 EXPECT_EQ(NULL, trans->response_.auth_challenge.get());
2625 EXPECT_EQ(NULL, trans->response_.headers.get());
2626 EXPECT_EQ(false, trans->response_.was_cached);
[email protected]89ceba9a2009-03-21 03:46:062627 EXPECT_EQ(0, trans->response_.ssl_info.cert_status);
2628 EXPECT_FALSE(trans->response_.vary_data.is_valid());
2629}
2630
[email protected]bacff652009-03-31 17:50:332631// Test HTTPS connections to a site with a bad certificate
2632TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592633 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402634 scoped_ptr<HttpTransaction> trans(
2635 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592636 CreateSession(&session_deps),
2637 &session_deps.socket_factory));
[email protected]bacff652009-03-31 17:50:332638
2639 HttpRequestInfo request;
2640 request.method = "GET";
2641 request.url = GURL("https://www.google.com/");
2642 request.load_flags = 0;
2643
2644 MockWrite data_writes[] = {
2645 MockWrite("GET / HTTP/1.1\r\n"
2646 "Host: www.google.com\r\n"
2647 "Connection: keep-alive\r\n\r\n"),
2648 };
2649
2650 MockRead data_reads[] = {
2651 MockRead("HTTP/1.0 200 OK\r\n"),
2652 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2653 MockRead("Content-Length: 100\r\n\r\n"),
2654 MockRead(false, OK),
2655 };
2656
2657 MockSocket ssl_bad_certificate;
2658 MockSocket data(data_reads, data_writes);
2659 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2660 MockSSLSocket ssl(true, OK);
2661
[email protected]228ff742009-06-05 01:19:592662 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2663 session_deps.socket_factory.AddMockSocket(&data);
2664 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2665 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332666
2667 TestCompletionCallback callback;
2668
2669 int rv = trans->Start(&request, &callback);
2670 EXPECT_EQ(ERR_IO_PENDING, rv);
2671
2672 rv = callback.WaitForResult();
2673 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2674
2675 rv = trans->RestartIgnoringLastError(&callback);
2676 EXPECT_EQ(ERR_IO_PENDING, rv);
2677
2678 rv = callback.WaitForResult();
2679 EXPECT_EQ(OK, rv);
2680
2681 const HttpResponseInfo* response = trans->GetResponseInfo();
2682
2683 EXPECT_FALSE(response == NULL);
2684 EXPECT_EQ(100, response->headers->GetContentLength());
2685}
2686
2687// Test HTTPS connections to a site with a bad certificate, going through a
2688// proxy
2689TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592690 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332691
2692 HttpRequestInfo request;
2693 request.method = "GET";
2694 request.url = GURL("https://www.google.com/");
2695 request.load_flags = 0;
2696
2697 MockWrite proxy_writes[] = {
2698 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2699 "Host: www.google.com\r\n\r\n"),
2700 };
2701
2702 MockRead proxy_reads[] = {
2703 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422704 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:332705 };
2706
2707 MockWrite data_writes[] = {
2708 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2709 "Host: www.google.com\r\n\r\n"),
2710 MockWrite("GET / HTTP/1.1\r\n"
2711 "Host: www.google.com\r\n"
2712 "Connection: keep-alive\r\n\r\n"),
2713 };
2714
2715 MockRead data_reads[] = {
2716 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2717 MockRead("HTTP/1.0 200 OK\r\n"),
2718 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2719 MockRead("Content-Length: 100\r\n\r\n"),
2720 MockRead(false, OK),
2721 };
2722
2723 MockSocket ssl_bad_certificate(proxy_reads, proxy_writes);
2724 MockSocket data(data_reads, data_writes);
2725 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2726 MockSSLSocket ssl(true, OK);
2727
[email protected]228ff742009-06-05 01:19:592728 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2729 session_deps.socket_factory.AddMockSocket(&data);
2730 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2731 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332732
2733 TestCompletionCallback callback;
2734
2735 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:592736 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:332737
[email protected]d207a5f2009-06-04 05:28:402738 scoped_ptr<HttpTransaction> trans(
2739 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592740 CreateSession(&session_deps),
2741 &session_deps.socket_factory));
[email protected]bacff652009-03-31 17:50:332742
2743 int rv = trans->Start(&request, &callback);
2744 EXPECT_EQ(ERR_IO_PENDING, rv);
2745
2746 rv = callback.WaitForResult();
2747 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2748
2749 rv = trans->RestartIgnoringLastError(&callback);
2750 EXPECT_EQ(ERR_IO_PENDING, rv);
2751
2752 rv = callback.WaitForResult();
2753 EXPECT_EQ(OK, rv);
2754
2755 const HttpResponseInfo* response = trans->GetResponseInfo();
2756
2757 EXPECT_FALSE(response == NULL);
2758 EXPECT_EQ(100, response->headers->GetContentLength());
2759 }
2760}
2761
[email protected]1c773ea12009-04-28 19:58:422762TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:592763 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402764 scoped_ptr<HttpTransaction> trans(
2765 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592766 CreateSession(&session_deps),
2767 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422768
2769 HttpRequestInfo request;
2770 request.method = "GET";
2771 request.url = GURL("http://www.google.com/");
2772 request.user_agent = "Chromium Ultra Awesome X Edition";
2773
2774 MockWrite data_writes[] = {
2775 MockWrite("GET / HTTP/1.1\r\n"
2776 "Host: www.google.com\r\n"
2777 "Connection: keep-alive\r\n"
2778 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
2779 };
2780
2781 // Lastly, the server responds with the actual content.
2782 MockRead data_reads[] = {
2783 MockRead("HTTP/1.0 200 OK\r\n"),
2784 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2785 MockRead("Content-Length: 100\r\n\r\n"),
2786 MockRead(false, OK),
2787 };
2788
2789 MockSocket data;
2790 data.reads = data_reads;
2791 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592792 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422793
2794 TestCompletionCallback callback;
2795
2796 int rv = trans->Start(&request, &callback);
2797 EXPECT_EQ(ERR_IO_PENDING, rv);
2798
2799 rv = callback.WaitForResult();
2800 EXPECT_EQ(OK, rv);
2801}
2802
2803TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:592804 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402805 scoped_ptr<HttpTransaction> trans(
2806 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592807 CreateSession(&session_deps),
2808 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422809
2810 HttpRequestInfo request;
2811 request.method = "GET";
2812 request.url = GURL("http://www.google.com/");
2813 request.load_flags = 0;
2814 request.referrer = GURL("http://the.previous.site.com/");
2815
2816 MockWrite data_writes[] = {
2817 MockWrite("GET / HTTP/1.1\r\n"
2818 "Host: www.google.com\r\n"
2819 "Connection: keep-alive\r\n"
2820 "Referer: http://the.previous.site.com/\r\n\r\n"),
2821 };
2822
2823 // Lastly, the server responds with the actual content.
2824 MockRead data_reads[] = {
2825 MockRead("HTTP/1.0 200 OK\r\n"),
2826 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2827 MockRead("Content-Length: 100\r\n\r\n"),
2828 MockRead(false, OK),
2829 };
2830
2831 MockSocket data;
2832 data.reads = data_reads;
2833 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592834 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422835
2836 TestCompletionCallback callback;
2837
2838 int rv = trans->Start(&request, &callback);
2839 EXPECT_EQ(ERR_IO_PENDING, rv);
2840
2841 rv = callback.WaitForResult();
2842 EXPECT_EQ(OK, rv);
2843}
2844
2845TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592846 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402847 scoped_ptr<HttpTransaction> trans(
2848 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592849 CreateSession(&session_deps),
2850 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422851
2852 HttpRequestInfo request;
2853 request.method = "POST";
2854 request.url = GURL("http://www.google.com/");
2855
2856 MockWrite data_writes[] = {
2857 MockWrite("POST / HTTP/1.1\r\n"
2858 "Host: www.google.com\r\n"
2859 "Connection: keep-alive\r\n"
2860 "Content-Length: 0\r\n\r\n"),
2861 };
2862
2863 // Lastly, the server responds with the actual content.
2864 MockRead data_reads[] = {
2865 MockRead("HTTP/1.0 200 OK\r\n"),
2866 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2867 MockRead("Content-Length: 100\r\n\r\n"),
2868 MockRead(false, OK),
2869 };
2870
2871 MockSocket data;
2872 data.reads = data_reads;
2873 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592874 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422875
2876 TestCompletionCallback callback;
2877
2878 int rv = trans->Start(&request, &callback);
2879 EXPECT_EQ(ERR_IO_PENDING, rv);
2880
2881 rv = callback.WaitForResult();
2882 EXPECT_EQ(OK, rv);
2883}
2884
2885TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592886 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402887 scoped_ptr<HttpTransaction> trans(
2888 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592889 CreateSession(&session_deps),
2890 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422891
2892 HttpRequestInfo request;
2893 request.method = "PUT";
2894 request.url = GURL("http://www.google.com/");
2895
2896 MockWrite data_writes[] = {
2897 MockWrite("PUT / HTTP/1.1\r\n"
2898 "Host: www.google.com\r\n"
2899 "Connection: keep-alive\r\n"
2900 "Content-Length: 0\r\n\r\n"),
2901 };
2902
2903 // Lastly, the server responds with the actual content.
2904 MockRead data_reads[] = {
2905 MockRead("HTTP/1.0 200 OK\r\n"),
2906 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2907 MockRead("Content-Length: 100\r\n\r\n"),
2908 MockRead(false, OK),
2909 };
2910
2911 MockSocket data;
2912 data.reads = data_reads;
2913 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592914 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422915
2916 TestCompletionCallback callback;
2917
2918 int rv = trans->Start(&request, &callback);
2919 EXPECT_EQ(ERR_IO_PENDING, rv);
2920
2921 rv = callback.WaitForResult();
2922 EXPECT_EQ(OK, rv);
2923}
2924
2925TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592926 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402927 scoped_ptr<HttpTransaction> trans(
2928 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592929 CreateSession(&session_deps),
2930 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422931
2932 HttpRequestInfo request;
2933 request.method = "HEAD";
2934 request.url = GURL("http://www.google.com/");
2935
2936 MockWrite data_writes[] = {
2937 MockWrite("HEAD / HTTP/1.1\r\n"
2938 "Host: www.google.com\r\n"
2939 "Connection: keep-alive\r\n"
2940 "Content-Length: 0\r\n\r\n"),
2941 };
2942
2943 // Lastly, the server responds with the actual content.
2944 MockRead data_reads[] = {
2945 MockRead("HTTP/1.0 200 OK\r\n"),
2946 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2947 MockRead("Content-Length: 100\r\n\r\n"),
2948 MockRead(false, OK),
2949 };
2950
2951 MockSocket data;
2952 data.reads = data_reads;
2953 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592954 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422955
2956 TestCompletionCallback callback;
2957
2958 int rv = trans->Start(&request, &callback);
2959 EXPECT_EQ(ERR_IO_PENDING, rv);
2960
2961 rv = callback.WaitForResult();
2962 EXPECT_EQ(OK, rv);
2963}
2964
2965TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:592966 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402967 scoped_ptr<HttpTransaction> trans(
2968 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592969 CreateSession(&session_deps),
2970 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422971
2972 HttpRequestInfo request;
2973 request.method = "GET";
2974 request.url = GURL("http://www.google.com/");
2975 request.load_flags = LOAD_BYPASS_CACHE;
2976
2977 MockWrite data_writes[] = {
2978 MockWrite("GET / HTTP/1.1\r\n"
2979 "Host: www.google.com\r\n"
2980 "Connection: keep-alive\r\n"
2981 "Pragma: no-cache\r\n"
2982 "Cache-Control: no-cache\r\n\r\n"),
2983 };
2984
2985 // Lastly, the server responds with the actual content.
2986 MockRead data_reads[] = {
2987 MockRead("HTTP/1.0 200 OK\r\n"),
2988 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2989 MockRead("Content-Length: 100\r\n\r\n"),
2990 MockRead(false, OK),
2991 };
2992
2993 MockSocket data;
2994 data.reads = data_reads;
2995 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:592996 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422997
2998 TestCompletionCallback callback;
2999
3000 int rv = trans->Start(&request, &callback);
3001 EXPECT_EQ(ERR_IO_PENDING, rv);
3002
3003 rv = callback.WaitForResult();
3004 EXPECT_EQ(OK, rv);
3005}
3006
3007TEST_F(HttpNetworkTransactionTest,
3008 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593009 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403010 scoped_ptr<HttpTransaction> trans(
3011 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:593012 CreateSession(&session_deps),
3013 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:423014
3015 HttpRequestInfo request;
3016 request.method = "GET";
3017 request.url = GURL("http://www.google.com/");
3018 request.load_flags = LOAD_VALIDATE_CACHE;
3019
3020 MockWrite data_writes[] = {
3021 MockWrite("GET / HTTP/1.1\r\n"
3022 "Host: www.google.com\r\n"
3023 "Connection: keep-alive\r\n"
3024 "Cache-Control: max-age=0\r\n\r\n"),
3025 };
3026
3027 // Lastly, the server responds with the actual content.
3028 MockRead data_reads[] = {
3029 MockRead("HTTP/1.0 200 OK\r\n"),
3030 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3031 MockRead("Content-Length: 100\r\n\r\n"),
3032 MockRead(false, OK),
3033 };
3034
3035 MockSocket data;
3036 data.reads = data_reads;
3037 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:593038 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423039
3040 TestCompletionCallback callback;
3041
3042 int rv = trans->Start(&request, &callback);
3043 EXPECT_EQ(ERR_IO_PENDING, rv);
3044
3045 rv = callback.WaitForResult();
3046 EXPECT_EQ(OK, rv);
3047}
3048
3049TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593050 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403051 scoped_ptr<HttpTransaction> trans(
3052 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:593053 CreateSession(&session_deps),
3054 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:423055
3056 HttpRequestInfo request;
3057 request.method = "GET";
3058 request.url = GURL("http://www.google.com/");
3059 request.extra_headers = "FooHeader: Bar\r\n";
3060
3061 MockWrite data_writes[] = {
3062 MockWrite("GET / HTTP/1.1\r\n"
3063 "Host: www.google.com\r\n"
3064 "Connection: keep-alive\r\n"
3065 "FooHeader: Bar\r\n\r\n"),
3066 };
3067
3068 // Lastly, the server responds with the actual content.
3069 MockRead data_reads[] = {
3070 MockRead("HTTP/1.0 200 OK\r\n"),
3071 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3072 MockRead("Content-Length: 100\r\n\r\n"),
3073 MockRead(false, OK),
3074 };
3075
3076 MockSocket data;
3077 data.reads = data_reads;
3078 data.writes = data_writes;
[email protected]228ff742009-06-05 01:19:593079 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423080
3081 TestCompletionCallback callback;
3082
3083 int rv = trans->Start(&request, &callback);
3084 EXPECT_EQ(ERR_IO_PENDING, rv);
3085
3086 rv = callback.WaitForResult();
3087 EXPECT_EQ(OK, rv);
3088}
3089
[email protected]89ceba9a2009-03-21 03:46:063090} // namespace net