blob: 548ee16ef4df3cc637157fc8eded3e6eb5a4f465 [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// 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
[email protected]95d88ffe2010-02-04 21:25:336#include <vector>
[email protected]77848d12008-11-14 00:00:227
[email protected]68bf9152008-09-25 19:47:308#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:339#include "base/file_path.h"
10#include "base/file_util.h"
[email protected]bacff652009-03-31 17:50:3311#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3212#include "net/base/mock_host_resolver.h"
[email protected]ac790b42009-12-02 04:31:3113#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4214#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3315#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5216#include "net/base/test_completion_callback.h"
17#include "net/base/upload_data.h"
[email protected]dab9c7d2010-02-06 21:44:3218#include "net/spdy/spdy_session_pool.h"
[email protected]385a4672009-03-11 22:21:2919#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5720#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5221#include "net/http/http_network_session.h"
22#include "net/http/http_network_transaction.h"
[email protected]0877e3d2009-10-17 22:29:5723#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5224#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5325#include "net/proxy/proxy_config_service_fixed.h"
[email protected]f7984fc62009-06-22 23:26:4426#include "net/socket/client_socket_factory.h"
27#include "net/socket/socket_test_util.h"
28#include "net/socket/ssl_client_socket.h"
initial.commit586acc5fe2008-07-26 22:42:5229#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1530#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5231
32//-----------------------------------------------------------------------------
33
[email protected]89ceba9a2009-03-21 03:46:0634namespace net {
35
[email protected]e44de5d2009-06-05 20:12:4536// Helper to manage the lifetimes of the dependencies for a
37// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5938class SessionDependencies {
39 public:
40 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4241 SessionDependencies()
42 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3743 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1044 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]955fc2e72010-02-08 20:37:3045 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5946
47 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4548 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4249 : host_resolver(new MockHostResolver),
50 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1051 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]955fc2e72010-02-08 20:37:3052 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5953
[email protected]a2c2fb92009-07-18 07:31:0454 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0955 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4256 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5957 MockClientSocketFactory socket_factory;
[email protected]955fc2e72010-02-08 20:37:3058 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]228ff742009-06-05 01:19:5959};
60
[email protected]1c773ea12009-04-28 19:58:4261ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5062 net::ProxyConfig proxy_config;
63 proxy_config.proxy_rules.ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3964 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5365}
66
67
[email protected]228ff742009-06-05 01:19:5968HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]d13c3272010-02-04 00:24:5169 return new HttpNetworkSession(NULL,
70 session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:0971 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:4272 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:1073 session_deps->ssl_config_service,
[email protected]955fc2e72010-02-08 20:37:3074 session_deps->spdy_session_pool);
[email protected]e8d536192008-10-17 22:21:1475}
76
[email protected]89836e22008-09-25 20:33:4277class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5278 public:
[email protected]0e75a732008-10-16 20:36:0979 virtual void TearDown() {
80 // Empty the current queue.
81 MessageLoop::current()->RunAllPending();
82 PlatformTest::TearDown();
83 }
84
[email protected]3d2a59b2008-09-26 19:44:2585 protected:
86 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5287
[email protected]ff007e162009-05-23 09:13:1588 struct SimpleGetHelperResult {
89 int rv;
90 std::string status_line;
91 std::string response_data;
92 };
initial.commit586acc5fe2008-07-26 22:42:5293
[email protected]31a2bfe2010-02-09 08:03:3994 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
95 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:1596 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:5297
[email protected]228ff742009-06-05 01:19:5998 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:4099 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43100 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52101
[email protected]ff007e162009-05-23 09:13:15102 HttpRequestInfo request;
103 request.method = "GET";
104 request.url = GURL("http://www.google.com/");
105 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52106
[email protected]31a2bfe2010-02-09 08:03:39107 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59108 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52109
[email protected]ff007e162009-05-23 09:13:15110 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52111
[email protected]684970b2009-08-14 04:54:46112 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15113 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52114
[email protected]ff007e162009-05-23 09:13:15115 out.rv = callback.WaitForResult();
116 if (out.rv != OK)
117 return out;
118
119 const HttpResponseInfo* response = trans->GetResponseInfo();
120 EXPECT_TRUE(response != NULL);
121
122 EXPECT_TRUE(response->headers != NULL);
123 out.status_line = response->headers->GetStatusLine();
124
125 rv = ReadTransaction(trans.get(), &out.response_data);
126 EXPECT_EQ(OK, rv);
127
[email protected]aecfbf22008-10-16 02:02:47128 return out;
[email protected]ff007e162009-05-23 09:13:15129 }
initial.commit586acc5fe2008-07-26 22:42:52130
[email protected]ff007e162009-05-23 09:13:15131 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
132 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52133
[email protected]ff007e162009-05-23 09:13:15134 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15135};
[email protected]231d5a32008-09-13 00:45:27136
[email protected]15a5ccf82008-10-23 19:57:43137// Fill |str| with a long header list that consumes >= |size| bytes.
138void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19139 const char* row =
140 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
141 const int sizeof_row = strlen(row);
142 const int num_rows = static_cast<int>(
143 ceil(static_cast<float>(size) / sizeof_row));
144 const int sizeof_data = num_rows * sizeof_row;
145 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43146 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51147
[email protected]4ddaf2502008-10-23 18:26:19148 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43149 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19150}
151
[email protected]385a4672009-03-11 22:21:29152// Alternative functions that eliminate randomness and dependency on the local
153// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20154void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29155 static const uint8 bytes[] = {
156 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
157 };
158 static size_t current_byte = 0;
159 for (size_t i = 0; i < n; ++i) {
160 output[i] = bytes[current_byte++];
161 current_byte %= arraysize(bytes);
162 }
163}
164
[email protected]fe2bc6a2009-03-23 16:52:20165void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29166 static const uint8 bytes[] = {
167 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
168 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
169 };
170 static size_t current_byte = 0;
171 for (size_t i = 0; i < n; ++i) {
172 output[i] = bytes[current_byte++];
173 current_byte %= arraysize(bytes);
174 }
175}
176
[email protected]fe2bc6a2009-03-23 16:52:20177std::string MockGetHostName() {
178 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29179}
180
[email protected]a937a06d2009-08-19 21:19:24181class CaptureGroupNameSocketPool : public TCPClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31182 public:
[email protected]100d5fb92009-12-21 21:08:35183 CaptureGroupNameSocketPool() : TCPClientSocketPool(0, 0, NULL, NULL, NULL) {}
[email protected]d80a4322009-08-14 07:07:49184 const std::string last_group_name_received() const {
185 return last_group_name_;
186 }
187
[email protected]684970b2009-08-14 04:54:46188 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49189 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31190 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31191 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46192 CompletionCallback* callback,
193 LoadLog* load_log) {
[email protected]04e5be32009-06-26 20:00:31194 last_group_name_ = group_name;
195 return ERR_IO_PENDING;
196 }
[email protected]04e5be32009-06-26 20:00:31197 virtual void CancelRequest(const std::string& group_name,
198 const ClientSocketHandle* handle) { }
199 virtual void ReleaseSocket(const std::string& group_name,
200 ClientSocket* socket) {}
201 virtual void CloseIdleSockets() {}
202 virtual HostResolver* GetHostResolver() const {
203 return NULL;
204 }
205 virtual int IdleSocketCount() const {
206 return 0;
207 }
208 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
209 return 0;
210 }
211 virtual LoadState GetLoadState(const std::string& group_name,
212 const ClientSocketHandle* handle) const {
213 return LOAD_STATE_IDLE;
214 }
[email protected]d80a4322009-08-14 07:07:49215
216 private:
[email protected]04e5be32009-06-26 20:00:31217 std::string last_group_name_;
218};
219
[email protected]231d5a32008-09-13 00:45:27220//-----------------------------------------------------------------------------
221
222TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59223 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40224 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43225 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27226}
227
228TEST_F(HttpNetworkTransactionTest, SimpleGET) {
229 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35230 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
231 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42232 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27233 };
[email protected]31a2bfe2010-02-09 08:03:39234 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
235 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42236 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27237 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
238 EXPECT_EQ("hello world", out.response_data);
239}
240
241// Response with no status line.
242TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
243 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35244 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42245 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27246 };
[email protected]31a2bfe2010-02-09 08:03:39247 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
248 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42249 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27250 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
251 EXPECT_EQ("hello world", out.response_data);
252}
253
254// Allow up to 4 bytes of junk to precede status line.
255TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
256 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35257 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42258 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27259 };
[email protected]31a2bfe2010-02-09 08:03:39260 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
261 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42262 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27263 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
264 EXPECT_EQ("DATA", out.response_data);
265}
266
267// Allow up to 4 bytes of junk to precede status line.
268TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
269 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35270 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42271 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27272 };
[email protected]31a2bfe2010-02-09 08:03:39273 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
274 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42275 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27276 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
277 EXPECT_EQ("DATA", out.response_data);
278}
279
280// Beyond 4 bytes of slop and it should fail to find a status line.
281TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
282 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35283 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42284 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27285 };
[email protected]31a2bfe2010-02-09 08:03:39286 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
287 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42288 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25289 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
290 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27291}
292
293// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
294TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
295 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35296 MockRead("\n"),
297 MockRead("\n"),
298 MockRead("Q"),
299 MockRead("J"),
300 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42301 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27302 };
[email protected]31a2bfe2010-02-09 08:03:39303 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
304 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42305 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27306 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
307 EXPECT_EQ("DATA", out.response_data);
308}
309
310// Close the connection before enough bytes to have a status line.
311TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
312 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35313 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42314 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27315 };
[email protected]31a2bfe2010-02-09 08:03:39316 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
317 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42318 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27319 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
320 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52321}
322
[email protected]f9d44aa2008-09-23 23:57:17323// Simulate a 204 response, lacking a Content-Length header, sent over a
324// persistent connection. The response should still terminate since a 204
325// cannot have a response body.
326TEST_F(HttpNetworkTransactionTest, StopsReading204) {
327 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35328 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
329 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42330 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17331 };
[email protected]31a2bfe2010-02-09 08:03:39332 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
333 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42334 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17335 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
336 EXPECT_EQ("", out.response_data);
337}
338
[email protected]0877e3d2009-10-17 22:29:57339// A simple request using chunked encoding with some extra data after.
340// (Like might be seen in a pipelined response.)
341TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
342 MockRead data_reads[] = {
343 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
344 MockRead("5\r\nHello\r\n"),
345 MockRead("1\r\n"),
346 MockRead(" \r\n"),
347 MockRead("5\r\nworld\r\n"),
348 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
349 MockRead(false, OK),
350 };
[email protected]31a2bfe2010-02-09 08:03:39351 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
352 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57353 EXPECT_EQ(OK, out.rv);
354 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
355 EXPECT_EQ("Hello world", out.response_data);
356}
357
[email protected]ef0faf2e72009-03-05 23:27:23358// Do a request using the HEAD method. Verify that we don't try to read the
359// message body (since HEAD has none).
360TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59361 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40362 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43363 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23364
[email protected]1c773ea12009-04-28 19:58:42365 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23366 request.method = "HEAD";
367 request.url = GURL("http://www.google.com/");
368 request.load_flags = 0;
369
370 MockWrite data_writes1[] = {
371 MockWrite("HEAD / HTTP/1.1\r\n"
372 "Host: www.google.com\r\n"
373 "Connection: keep-alive\r\n"
374 "Content-Length: 0\r\n\r\n"),
375 };
376 MockRead data_reads1[] = {
377 MockRead("HTTP/1.1 404 Not Found\r\n"),
378 MockRead("Server: Blah\r\n"),
379 MockRead("Content-Length: 1234\r\n\r\n"),
380
381 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42382 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23383 };
384
[email protected]31a2bfe2010-02-09 08:03:39385 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
386 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59387 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23388
389 TestCompletionCallback callback1;
390
[email protected]684970b2009-08-14 04:54:46391 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42392 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23393
394 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42395 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23396
[email protected]1c773ea12009-04-28 19:58:42397 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23398 EXPECT_FALSE(response == NULL);
399
400 // Check that the headers got parsed.
401 EXPECT_TRUE(response->headers != NULL);
402 EXPECT_EQ(1234, response->headers->GetContentLength());
403 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
404
405 std::string server_header;
406 void* iter = NULL;
407 bool has_server_header = response->headers->EnumerateHeader(
408 &iter, "Server", &server_header);
409 EXPECT_TRUE(has_server_header);
410 EXPECT_EQ("Blah", server_header);
411
412 // Reading should give EOF right away, since there is no message body
413 // (despite non-zero content-length).
414 std::string response_data;
415 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42416 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23417 EXPECT_EQ("", response_data);
418}
419
initial.commit586acc5fe2008-07-26 22:42:52420TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59421 SessionDependencies session_deps;
422 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52423
424 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35425 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
426 MockRead("hello"),
427 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
428 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42429 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52430 };
[email protected]31a2bfe2010-02-09 08:03:39431 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59432 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52433
434 const char* kExpectedResponseData[] = {
435 "hello", "world"
436 };
437
438 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43439 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52440
[email protected]1c773ea12009-04-28 19:58:42441 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52442 request.method = "GET";
443 request.url = GURL("http://www.google.com/");
444 request.load_flags = 0;
445
446 TestCompletionCallback callback;
447
[email protected]684970b2009-08-14 04:54:46448 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42449 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52450
451 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42452 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52453
[email protected]1c773ea12009-04-28 19:58:42454 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52455 EXPECT_TRUE(response != NULL);
456
457 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25458 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52459
460 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57461 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42462 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25463 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52464 }
465}
466
467TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59468 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40469 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43470 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52471
[email protected]1c773ea12009-04-28 19:58:42472 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52473 request.method = "POST";
474 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42475 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52476 request.upload_data->AppendBytes("foo", 3);
477 request.load_flags = 0;
478
479 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35480 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
481 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
482 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42483 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52484 };
[email protected]31a2bfe2010-02-09 08:03:39485 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59486 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52487
488 TestCompletionCallback callback;
489
[email protected]684970b2009-08-14 04:54:46490 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42491 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52492
493 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42494 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52495
[email protected]1c773ea12009-04-28 19:58:42496 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52497 EXPECT_TRUE(response != NULL);
498
499 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25500 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52501
502 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57503 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42504 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25505 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52506}
507
[email protected]3a2d3662009-03-27 03:49:14508// This test is almost the same as Ignores100 above, but the response contains
509// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57510// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14511TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59512 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40513 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43514 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14515
[email protected]1c773ea12009-04-28 19:58:42516 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14517 request.method = "GET";
518 request.url = GURL("http://www.foo.com/");
519 request.load_flags = 0;
520
521 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57522 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
523 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14524 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42525 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14526 };
[email protected]31a2bfe2010-02-09 08:03:39527 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59528 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14529
530 TestCompletionCallback callback;
531
[email protected]684970b2009-08-14 04:54:46532 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42533 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14534
535 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42536 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14537
[email protected]1c773ea12009-04-28 19:58:42538 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14539 EXPECT_TRUE(response != NULL);
540
541 EXPECT_TRUE(response->headers != NULL);
542 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
543
544 std::string response_data;
545 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42546 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14547 EXPECT_EQ("hello world", response_data);
548}
549
[email protected]ee9410e72010-01-07 01:42:38550TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
551 SessionDependencies session_deps;
552 scoped_ptr<HttpTransaction> trans(
553 new HttpNetworkTransaction(CreateSession(&session_deps)));
554
555 HttpRequestInfo request;
556 request.method = "POST";
557 request.url = GURL("http://www.foo.com/");
558 request.load_flags = 0;
559
560 MockRead data_reads[] = {
561 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
562 MockRead(true, 0),
563 };
[email protected]31a2bfe2010-02-09 08:03:39564 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38565 session_deps.socket_factory.AddSocketDataProvider(&data);
566
567 TestCompletionCallback callback;
568
569 int rv = trans->Start(&request, &callback, NULL);
570 EXPECT_EQ(ERR_IO_PENDING, rv);
571
572 rv = callback.WaitForResult();
573 EXPECT_EQ(OK, rv);
574
575 std::string response_data;
576 rv = ReadTransaction(trans.get(), &response_data);
577 EXPECT_EQ(OK, rv);
578 EXPECT_EQ("", response_data);
579}
580
581TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
582 SessionDependencies session_deps;
583 scoped_ptr<HttpTransaction> trans(
584 new HttpNetworkTransaction(CreateSession(&session_deps)));
585
586 HttpRequestInfo request;
587 request.method = "POST";
588 request.url = GURL("http://www.foo.com/");
589 request.load_flags = 0;
590
591 MockRead data_reads[] = {
592 MockRead(true, 0),
593 };
[email protected]31a2bfe2010-02-09 08:03:39594 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38595 session_deps.socket_factory.AddSocketDataProvider(&data);
596
597 TestCompletionCallback callback;
598
599 int rv = trans->Start(&request, &callback, NULL);
600 EXPECT_EQ(ERR_IO_PENDING, rv);
601
602 rv = callback.WaitForResult();
603 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
604}
605
[email protected]3d2a59b2008-09-26 19:44:25606// read_failure specifies a read failure that should cause the network
607// transaction to resend the request.
608void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
609 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59610 SessionDependencies session_deps;
611 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52612
[email protected]1c773ea12009-04-28 19:58:42613 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52614 request.method = "GET";
615 request.url = GURL("http://www.foo.com/");
616 request.load_flags = 0;
617
618 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35619 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
620 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25621 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52622 };
[email protected]31a2bfe2010-02-09 08:03:39623 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59624 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52625
626 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35627 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
628 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42629 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52630 };
[email protected]31a2bfe2010-02-09 08:03:39631 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59632 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52633
634 const char* kExpectedResponseData[] = {
635 "hello", "world"
636 };
637
638 for (int i = 0; i < 2; ++i) {
639 TestCompletionCallback callback;
640
[email protected]5695b8c2009-09-30 21:36:43641 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52642
[email protected]684970b2009-08-14 04:54:46643 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42644 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52645
646 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42647 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52648
[email protected]1c773ea12009-04-28 19:58:42649 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52650 EXPECT_TRUE(response != NULL);
651
652 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25653 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52654
655 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57656 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42657 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25658 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52659 }
660}
[email protected]3d2a59b2008-09-26 19:44:25661
662TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42663 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25664 KeepAliveConnectionResendRequestTest(read_failure);
665}
666
667TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42668 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25669 KeepAliveConnectionResendRequestTest(read_failure);
670}
671
672TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59673 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40674 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43675 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25676
[email protected]1c773ea12009-04-28 19:58:42677 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25678 request.method = "GET";
679 request.url = GURL("http://www.google.com/");
680 request.load_flags = 0;
681
682 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42683 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35684 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
685 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42686 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25687 };
[email protected]31a2bfe2010-02-09 08:03:39688 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59689 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25690
691 TestCompletionCallback callback;
692
[email protected]684970b2009-08-14 04:54:46693 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42694 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25695
696 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42697 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25698
[email protected]1c773ea12009-04-28 19:58:42699 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25700 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25701}
702
703// What do various browsers do when the server closes a non-keepalive
704// connection without sending any response header or body?
705//
706// IE7: error page
707// Safari 3.1.2 (Windows): error page
708// Firefox 3.0.1: blank page
709// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42710// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
711// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25712TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
713 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42714 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35715 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
716 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42717 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25718 };
[email protected]31a2bfe2010-02-09 08:03:39719 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
720 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42721 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25722}
[email protected]038e9a32008-10-08 22:40:16723
724// Test the request-challenge-retry sequence for basic auth.
725// (basic auth is the easiest to mock, because it has no randomness).
726TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59727 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40728 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43729 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16730
[email protected]1c773ea12009-04-28 19:58:42731 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16732 request.method = "GET";
733 request.url = GURL("http://www.google.com/");
734 request.load_flags = 0;
735
[email protected]f9ee6b52008-11-08 06:46:23736 MockWrite data_writes1[] = {
737 MockWrite("GET / HTTP/1.1\r\n"
738 "Host: www.google.com\r\n"
739 "Connection: keep-alive\r\n\r\n"),
740 };
741
[email protected]038e9a32008-10-08 22:40:16742 MockRead data_reads1[] = {
743 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
744 // Give a couple authenticate options (only the middle one is actually
745 // supported).
[email protected]22927ad2009-09-21 19:56:19746 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16747 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
748 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
749 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
750 // Large content-length -- won't matter, as connection will be reset.
751 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42752 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16753 };
754
755 // After calling trans->RestartWithAuth(), this is the request we should
756 // be issuing -- the final header line contains the credentials.
757 MockWrite data_writes2[] = {
758 MockWrite("GET / HTTP/1.1\r\n"
759 "Host: www.google.com\r\n"
760 "Connection: keep-alive\r\n"
761 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
762 };
763
764 // Lastly, the server responds with the actual content.
765 MockRead data_reads2[] = {
766 MockRead("HTTP/1.0 200 OK\r\n"),
767 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
768 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42769 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16770 };
771
[email protected]31a2bfe2010-02-09 08:03:39772 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
773 data_writes1, arraysize(data_writes1));
774 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
775 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59776 session_deps.socket_factory.AddSocketDataProvider(&data1);
777 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16778
779 TestCompletionCallback callback1;
780
[email protected]684970b2009-08-14 04:54:46781 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42782 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16783
784 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42785 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16786
[email protected]1c773ea12009-04-28 19:58:42787 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16788 EXPECT_FALSE(response == NULL);
789
790 // The password prompt info should have been set in response->auth_challenge.
791 EXPECT_FALSE(response->auth_challenge.get() == NULL);
792
[email protected]71e4573a2009-05-21 22:03:00793 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16794 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
795 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
796
797 TestCompletionCallback callback2;
798
799 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42800 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16801
802 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42803 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16804
805 response = trans->GetResponseInfo();
806 EXPECT_FALSE(response == NULL);
807 EXPECT_TRUE(response->auth_challenge.get() == NULL);
808 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16809}
810
[email protected]861fcd52009-08-26 02:33:46811TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
812 SessionDependencies session_deps;
813 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43814 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46815
816 HttpRequestInfo request;
817 request.method = "GET";
818 request.url = GURL("http://www.google.com/");
819 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
820
821 MockWrite data_writes[] = {
822 MockWrite("GET / HTTP/1.1\r\n"
823 "Host: www.google.com\r\n"
824 "Connection: keep-alive\r\n\r\n"),
825 };
826
827 MockRead data_reads[] = {
828 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
829 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
830 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
831 // Large content-length -- won't matter, as connection will be reset.
832 MockRead("Content-Length: 10000\r\n\r\n"),
833 MockRead(false, ERR_FAILED),
834 };
835
[email protected]31a2bfe2010-02-09 08:03:39836 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
837 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59838 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46839 TestCompletionCallback callback;
840
841 int rv = trans->Start(&request, &callback, NULL);
842 EXPECT_EQ(ERR_IO_PENDING, rv);
843
844 rv = callback.WaitForResult();
845 EXPECT_EQ(0, rv);
846
847 const HttpResponseInfo* response = trans->GetResponseInfo();
848 ASSERT_FALSE(response == NULL);
849 EXPECT_TRUE(response->auth_challenge.get() == NULL);
850}
851
[email protected]2d2697f92009-02-18 21:00:32852// Test the request-challenge-retry sequence for basic auth, over a keep-alive
853// connection.
854TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59855 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40856 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43857 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32858
[email protected]1c773ea12009-04-28 19:58:42859 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32860 request.method = "GET";
861 request.url = GURL("http://www.google.com/");
862 request.load_flags = 0;
863
864 MockWrite data_writes1[] = {
865 MockWrite("GET / HTTP/1.1\r\n"
866 "Host: www.google.com\r\n"
867 "Connection: keep-alive\r\n\r\n"),
868
869 // After calling trans->RestartWithAuth(), this is the request we should
870 // be issuing -- the final header line contains the credentials.
871 MockWrite("GET / HTTP/1.1\r\n"
872 "Host: www.google.com\r\n"
873 "Connection: keep-alive\r\n"
874 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
875 };
876
877 MockRead data_reads1[] = {
878 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
879 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
880 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
881 MockRead("Content-Length: 14\r\n\r\n"),
882 MockRead("Unauthorized\r\n"),
883
884 // Lastly, the server responds with the actual content.
885 MockRead("HTTP/1.1 200 OK\r\n"),
886 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
887 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42888 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32889 };
890
[email protected]31a2bfe2010-02-09 08:03:39891 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
892 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59893 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32894
895 TestCompletionCallback callback1;
896
[email protected]684970b2009-08-14 04:54:46897 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42898 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32899
900 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42901 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32902
[email protected]1c773ea12009-04-28 19:58:42903 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32904 EXPECT_FALSE(response == NULL);
905
906 // The password prompt info should have been set in response->auth_challenge.
907 EXPECT_FALSE(response->auth_challenge.get() == NULL);
908
[email protected]71e4573a2009-05-21 22:03:00909 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32910 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
911 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
912
913 TestCompletionCallback callback2;
914
915 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42916 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32917
918 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42919 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32920
921 response = trans->GetResponseInfo();
922 EXPECT_FALSE(response == NULL);
923 EXPECT_TRUE(response->auth_challenge.get() == NULL);
924 EXPECT_EQ(100, response->headers->GetContentLength());
925}
926
927// Test the request-challenge-retry sequence for basic auth, over a keep-alive
928// connection and with no response body to drain.
929TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59930 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40931 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43932 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32933
[email protected]1c773ea12009-04-28 19:58:42934 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32935 request.method = "GET";
936 request.url = GURL("http://www.google.com/");
937 request.load_flags = 0;
938
939 MockWrite data_writes1[] = {
940 MockWrite("GET / HTTP/1.1\r\n"
941 "Host: www.google.com\r\n"
942 "Connection: keep-alive\r\n\r\n"),
943
944 // After calling trans->RestartWithAuth(), this is the request we should
945 // be issuing -- the final header line contains the credentials.
946 MockWrite("GET / HTTP/1.1\r\n"
947 "Host: www.google.com\r\n"
948 "Connection: keep-alive\r\n"
949 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
950 };
951
[email protected]2d2697f92009-02-18 21:00:32952 MockRead data_reads1[] = {
953 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
954 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:31955 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:32956
957 // Lastly, the server responds with the actual content.
958 MockRead("HTTP/1.1 200 OK\r\n"),
959 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
960 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42961 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32962 };
963
[email protected]31a2bfe2010-02-09 08:03:39964 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
965 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59966 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32967
968 TestCompletionCallback callback1;
969
[email protected]684970b2009-08-14 04:54:46970 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42971 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32972
973 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42974 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32975
[email protected]1c773ea12009-04-28 19:58:42976 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32977 EXPECT_FALSE(response == NULL);
978
979 // The password prompt info should have been set in response->auth_challenge.
980 EXPECT_FALSE(response->auth_challenge.get() == NULL);
981
[email protected]71e4573a2009-05-21 22:03:00982 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32983 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
984 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
985
986 TestCompletionCallback callback2;
987
988 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42989 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32990
991 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42992 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32993
994 response = trans->GetResponseInfo();
995 EXPECT_FALSE(response == NULL);
996 EXPECT_TRUE(response->auth_challenge.get() == NULL);
997 EXPECT_EQ(100, response->headers->GetContentLength());
998}
999
1000// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1001// connection and with a large response body to drain.
1002TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591003 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401004 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431005 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321006
[email protected]1c773ea12009-04-28 19:58:421007 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321008 request.method = "GET";
1009 request.url = GURL("http://www.google.com/");
1010 request.load_flags = 0;
1011
1012 MockWrite data_writes1[] = {
1013 MockWrite("GET / HTTP/1.1\r\n"
1014 "Host: www.google.com\r\n"
1015 "Connection: keep-alive\r\n\r\n"),
1016
1017 // After calling trans->RestartWithAuth(), this is the request we should
1018 // be issuing -- the final header line contains the credentials.
1019 MockWrite("GET / HTTP/1.1\r\n"
1020 "Host: www.google.com\r\n"
1021 "Connection: keep-alive\r\n"
1022 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1023 };
1024
1025 // Respond with 5 kb of response body.
1026 std::string large_body_string("Unauthorized");
1027 large_body_string.append(5 * 1024, ' ');
1028 large_body_string.append("\r\n");
1029
1030 MockRead data_reads1[] = {
1031 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1032 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1033 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1034 // 5134 = 12 + 5 * 1024 + 2
1035 MockRead("Content-Length: 5134\r\n\r\n"),
1036 MockRead(true, large_body_string.data(), large_body_string.size()),
1037
1038 // Lastly, the server responds with the actual content.
1039 MockRead("HTTP/1.1 200 OK\r\n"),
1040 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1041 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421042 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321043 };
1044
[email protected]31a2bfe2010-02-09 08:03:391045 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1046 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591047 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321048
1049 TestCompletionCallback callback1;
1050
[email protected]684970b2009-08-14 04:54:461051 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421052 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321053
1054 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421055 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321056
[email protected]1c773ea12009-04-28 19:58:421057 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321058 EXPECT_FALSE(response == NULL);
1059
1060 // The password prompt info should have been set in response->auth_challenge.
1061 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1062
[email protected]71e4573a2009-05-21 22:03:001063 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321064 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1065 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1066
1067 TestCompletionCallback callback2;
1068
1069 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421070 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321071
1072 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421073 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321074
1075 response = trans->GetResponseInfo();
1076 EXPECT_FALSE(response == NULL);
1077 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1078 EXPECT_EQ(100, response->headers->GetContentLength());
1079}
1080
1081// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311082// connection, but the server gets impatient and closes the connection.
1083TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1084 SessionDependencies session_deps;
1085 scoped_ptr<HttpTransaction> trans(
1086 new HttpNetworkTransaction(CreateSession(&session_deps)));
1087
1088 HttpRequestInfo request;
1089 request.method = "GET";
1090 request.url = GURL("http://www.google.com/");
1091 request.load_flags = 0;
1092
1093 MockWrite data_writes1[] = {
1094 MockWrite("GET / HTTP/1.1\r\n"
1095 "Host: www.google.com\r\n"
1096 "Connection: keep-alive\r\n\r\n"),
1097 // This simulates the seemingly successful write to a closed connection
1098 // if the bug is not fixed.
1099 MockWrite("GET / HTTP/1.1\r\n"
1100 "Host: www.google.com\r\n"
1101 "Connection: keep-alive\r\n"
1102 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1103 };
1104
1105 MockRead data_reads1[] = {
1106 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1107 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1108 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1109 MockRead("Content-Length: 14\r\n\r\n"),
1110 // Tell MockTCPClientSocket to simulate the server closing the connection.
1111 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1112 MockRead("Unauthorized\r\n"),
1113 MockRead(false, OK), // The server closes the connection.
1114 };
1115
1116 // After calling trans->RestartWithAuth(), this is the request we should
1117 // be issuing -- the final header line contains the credentials.
1118 MockWrite data_writes2[] = {
1119 MockWrite("GET / HTTP/1.1\r\n"
1120 "Host: www.google.com\r\n"
1121 "Connection: keep-alive\r\n"
1122 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1123 };
1124
1125 // Lastly, the server responds with the actual content.
1126 MockRead data_reads2[] = {
1127 MockRead("HTTP/1.1 200 OK\r\n"),
1128 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1129 MockRead("Content-Length: 100\r\n\r\n"),
1130 MockRead(false, OK),
1131 };
1132
[email protected]31a2bfe2010-02-09 08:03:391133 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1134 data_writes1, arraysize(data_writes1));
1135 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1136 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311137 session_deps.socket_factory.AddSocketDataProvider(&data1);
1138 session_deps.socket_factory.AddSocketDataProvider(&data2);
1139
1140 TestCompletionCallback callback1;
1141
1142 int rv = trans->Start(&request, &callback1, NULL);
1143 EXPECT_EQ(ERR_IO_PENDING, rv);
1144
1145 rv = callback1.WaitForResult();
1146 EXPECT_EQ(OK, rv);
1147
1148 const HttpResponseInfo* response = trans->GetResponseInfo();
1149 EXPECT_FALSE(response == NULL);
1150
1151 // The password prompt info should have been set in response->auth_challenge.
1152 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1153
1154 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1155 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1156 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1157
1158 TestCompletionCallback callback2;
1159
1160 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1161 EXPECT_EQ(ERR_IO_PENDING, rv);
1162
1163 rv = callback2.WaitForResult();
1164 EXPECT_EQ(OK, rv);
1165
1166 response = trans->GetResponseInfo();
1167 ASSERT_FALSE(response == NULL);
1168 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1169 EXPECT_EQ(100, response->headers->GetContentLength());
1170}
1171
1172// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321173// proxy connection, when setting up an SSL tunnel.
1174TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1175 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591176 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1177 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321178
[email protected]5695b8c2009-09-30 21:36:431179 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321180
[email protected]1c773ea12009-04-28 19:58:421181 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321182 request.method = "GET";
1183 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461184 // Ensure that proxy authentication is attempted even
1185 // when the no authentication data flag is set.
1186 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321187
1188 // Since we have proxy, should try to establish tunnel.
1189 MockWrite data_writes1[] = {
1190 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451191 "Host: www.google.com\r\n"
1192 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321193
1194 // After calling trans->RestartWithAuth(), this is the request we should
1195 // be issuing -- the final header line contains the credentials.
1196 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1197 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451198 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321199 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1200 };
1201
1202 // The proxy responds to the connect with a 407, using a persistent
1203 // connection.
1204 MockRead data_reads1[] = {
1205 // No credentials.
1206 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1207 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1208 MockRead("Content-Length: 10\r\n\r\n"),
1209 MockRead("0123456789"),
1210
1211 // Wrong credentials (wrong password).
1212 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1213 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1214 MockRead("Content-Length: 10\r\n\r\n"),
1215 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421216 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321217 };
1218
[email protected]31a2bfe2010-02-09 08:03:391219 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1220 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591221 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321222
1223 TestCompletionCallback callback1;
1224
[email protected]684970b2009-08-14 04:54:461225 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421226 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321227
1228 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421229 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321230
[email protected]1c773ea12009-04-28 19:58:421231 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321232 EXPECT_FALSE(response == NULL);
1233
1234 EXPECT_TRUE(response->headers->IsKeepAlive());
1235 EXPECT_EQ(407, response->headers->response_code());
1236 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421237 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321238
1239 // The password prompt info should have been set in response->auth_challenge.
1240 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1241
[email protected]71e4573a2009-05-21 22:03:001242 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321243 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1244 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1245
1246 TestCompletionCallback callback2;
1247
1248 // Wrong password (should be "bar").
1249 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421250 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321251
1252 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421253 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321254
1255 response = trans->GetResponseInfo();
1256 EXPECT_FALSE(response == NULL);
1257
1258 EXPECT_TRUE(response->headers->IsKeepAlive());
1259 EXPECT_EQ(407, response->headers->response_code());
1260 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421261 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321262
1263 // The password prompt info should have been set in response->auth_challenge.
1264 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1265
[email protected]71e4573a2009-05-21 22:03:001266 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321267 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1268 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1269}
1270
[email protected]a8e9b162009-03-12 00:06:441271// Test that we don't read the response body when we fail to establish a tunnel,
1272// even if the user cancels the proxy's auth attempt.
1273TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1274 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591275 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441276
[email protected]e44de5d2009-06-05 20:12:451277 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441278
[email protected]5695b8c2009-09-30 21:36:431279 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441280
[email protected]1c773ea12009-04-28 19:58:421281 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441282 request.method = "GET";
1283 request.url = GURL("https://www.google.com/");
1284 request.load_flags = 0;
1285
1286 // Since we have proxy, should try to establish tunnel.
1287 MockWrite data_writes[] = {
1288 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451289 "Host: www.google.com\r\n"
1290 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441291 };
1292
1293 // The proxy responds to the connect with a 407.
1294 MockRead data_reads[] = {
1295 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1296 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1297 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421298 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441299 };
1300
[email protected]31a2bfe2010-02-09 08:03:391301 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1302 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591303 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441304
1305 TestCompletionCallback callback;
1306
[email protected]684970b2009-08-14 04:54:461307 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421308 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441309
1310 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421311 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441312
[email protected]1c773ea12009-04-28 19:58:421313 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441314 EXPECT_FALSE(response == NULL);
1315
1316 EXPECT_TRUE(response->headers->IsKeepAlive());
1317 EXPECT_EQ(407, response->headers->response_code());
1318 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421319 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441320
1321 std::string response_data;
1322 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421323 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441324}
1325
[email protected]ff007e162009-05-23 09:13:151326void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081327 const MockRead& status, int expected_status) {
1328 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591329 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081330
[email protected]228ff742009-06-05 01:19:591331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081332
[email protected]5695b8c2009-09-30 21:36:431333 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081334
[email protected]1c773ea12009-04-28 19:58:421335 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081336 request.method = "GET";
1337 request.url = GURL("https://www.google.com/");
1338 request.load_flags = 0;
1339
1340 // Since we have proxy, should try to establish tunnel.
1341 MockWrite data_writes[] = {
1342 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451343 "Host: www.google.com\r\n"
1344 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081345 };
1346
1347 MockRead data_reads[] = {
1348 status,
1349 MockRead("Content-Length: 10\r\n\r\n"),
1350 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421351 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081352 };
1353
[email protected]31a2bfe2010-02-09 08:03:391354 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1355 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591356 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081357
1358 TestCompletionCallback callback;
1359
[email protected]684970b2009-08-14 04:54:461360 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421361 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081362
1363 rv = callback.WaitForResult();
1364 EXPECT_EQ(expected_status, rv);
1365}
1366
[email protected]ff007e162009-05-23 09:13:151367void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081368 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421369 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081370}
1371
1372TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1373 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1374}
1375
1376TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1377 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1378}
1379
1380TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1381 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1382}
1383
1384TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1385 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1386}
1387
1388TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1389 ConnectStatusHelper(
1390 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1391}
1392
1393TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1394 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1395}
1396
1397TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1398 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1399}
1400
1401TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1402 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1403}
1404
1405TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1406 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1407}
1408
1409TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1410 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1411}
1412
1413TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1414 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1415}
1416
1417TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1418 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1419}
1420
1421TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1422 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1423}
1424
1425TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1426 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1427}
1428
1429TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1430 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1431}
1432
1433TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1434 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1435}
1436
1437TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1438 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1439}
1440
1441TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1442 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1443}
1444
1445TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1446 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1447}
1448
1449TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1450 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1451}
1452
1453TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1454 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1455}
1456
1457TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1458 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1459}
1460
1461TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1462 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1463}
1464
1465TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1466 ConnectStatusHelperWithExpectedStatus(
1467 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421468 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081469}
1470
1471TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1472 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1473}
1474
1475TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1476 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1477}
1478
1479TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1480 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1481}
1482
1483TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1484 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1485}
1486
1487TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1488 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1489}
1490
1491TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1492 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1493}
1494
1495TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1496 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1497}
1498
1499TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1500 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1501}
1502
1503TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1504 ConnectStatusHelper(
1505 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1506}
1507
1508TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1509 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1510}
1511
1512TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1513 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1514}
1515
1516TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1517 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1518}
1519
1520TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1521 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1522}
1523
1524TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1525 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1526}
1527
1528TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1529 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1530}
1531
1532TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1533 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1534}
1535
[email protected]038e9a32008-10-08 22:40:161536// Test the flow when both the proxy server AND origin server require
1537// authentication. Again, this uses basic auth for both since that is
1538// the simplest to mock.
1539TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591540 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011541
[email protected]038e9a32008-10-08 22:40:161542 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421543 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431544 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161545
[email protected]1c773ea12009-04-28 19:58:421546 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161547 request.method = "GET";
1548 request.url = GURL("http://www.google.com/");
1549 request.load_flags = 0;
1550
[email protected]f9ee6b52008-11-08 06:46:231551 MockWrite data_writes1[] = {
1552 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1553 "Host: www.google.com\r\n"
1554 "Proxy-Connection: keep-alive\r\n\r\n"),
1555 };
1556
[email protected]038e9a32008-10-08 22:40:161557 MockRead data_reads1[] = {
1558 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1559 // Give a couple authenticate options (only the middle one is actually
1560 // supported).
[email protected]22927ad2009-09-21 19:56:191561 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161562 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1563 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1564 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1565 // Large content-length -- won't matter, as connection will be reset.
1566 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421567 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161568 };
1569
1570 // After calling trans->RestartWithAuth() the first time, this is the
1571 // request we should be issuing -- the final header line contains the
1572 // proxy's credentials.
1573 MockWrite data_writes2[] = {
1574 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1575 "Host: www.google.com\r\n"
1576 "Proxy-Connection: keep-alive\r\n"
1577 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1578 };
1579
1580 // Now the proxy server lets the request pass through to origin server.
1581 // The origin server responds with a 401.
1582 MockRead data_reads2[] = {
1583 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1584 // Note: We are using the same realm-name as the proxy server. This is
1585 // completely valid, as realms are unique across hosts.
1586 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1587 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1588 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421589 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161590 };
1591
1592 // After calling trans->RestartWithAuth() the second time, we should send
1593 // the credentials for both the proxy and origin server.
1594 MockWrite data_writes3[] = {
1595 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1596 "Host: www.google.com\r\n"
1597 "Proxy-Connection: keep-alive\r\n"
1598 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1599 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1600 };
1601
1602 // Lastly we get the desired content.
1603 MockRead data_reads3[] = {
1604 MockRead("HTTP/1.0 200 OK\r\n"),
1605 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1606 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421607 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161608 };
1609
[email protected]31a2bfe2010-02-09 08:03:391610 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1611 data_writes1, arraysize(data_writes1));
1612 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1613 data_writes2, arraysize(data_writes2));
1614 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1615 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591616 session_deps.socket_factory.AddSocketDataProvider(&data1);
1617 session_deps.socket_factory.AddSocketDataProvider(&data2);
1618 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161619
1620 TestCompletionCallback callback1;
1621
[email protected]684970b2009-08-14 04:54:461622 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421623 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161624
1625 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421626 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161627
[email protected]1c773ea12009-04-28 19:58:421628 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161629 EXPECT_FALSE(response == NULL);
1630
1631 // The password prompt info should have been set in response->auth_challenge.
1632 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1633
[email protected]71e4573a2009-05-21 22:03:001634 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161635 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1636 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1637
1638 TestCompletionCallback callback2;
1639
1640 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421641 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161642
1643 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421644 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161645
1646 response = trans->GetResponseInfo();
1647 EXPECT_FALSE(response == NULL);
1648 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1649
[email protected]71e4573a2009-05-21 22:03:001650 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161651 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1652 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1653
1654 TestCompletionCallback callback3;
1655
1656 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421657 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161658
1659 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421660 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161661
1662 response = trans->GetResponseInfo();
1663 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1664 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161665}
[email protected]4ddaf2502008-10-23 18:26:191666
[email protected]ea9dc9a2009-09-05 00:43:321667// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1668// can't hook into its internals to cause it to generate predictable NTLM
1669// authorization headers.
1670#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291671// The NTLM authentication unit tests were generated by capturing the HTTP
1672// requests and responses using Fiddler 2 and inspecting the generated random
1673// bytes in the debugger.
1674
1675// Enter the correct password and authenticate successfully.
1676TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421677 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201678 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591679 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401680 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431681 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241682
[email protected]1c773ea12009-04-28 19:58:421683 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241684 request.method = "GET";
1685 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1686 request.load_flags = 0;
1687
1688 MockWrite data_writes1[] = {
1689 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1690 "Host: 172.22.68.17\r\n"
1691 "Connection: keep-alive\r\n\r\n"),
1692 };
1693
1694 MockRead data_reads1[] = {
1695 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1696 // Negotiate and NTLM are often requested together. We only support NTLM.
1697 MockRead("WWW-Authenticate: Negotiate\r\n"),
1698 MockRead("WWW-Authenticate: NTLM\r\n"),
1699 MockRead("Connection: close\r\n"),
1700 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361701 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241702 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421703 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241704 };
1705
1706 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221707 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241708 // request we should be issuing -- the final header line contains a Type
1709 // 1 message.
1710 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1711 "Host: 172.22.68.17\r\n"
1712 "Connection: keep-alive\r\n"
1713 "Authorization: NTLM "
1714 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1715
1716 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1717 // (the credentials for the origin server). The second request continues
1718 // on the same connection.
1719 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1720 "Host: 172.22.68.17\r\n"
1721 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291722 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1723 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1724 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1725 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1726 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241727 };
1728
1729 MockRead data_reads2[] = {
1730 // The origin server responds with a Type 2 message.
1731 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1732 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291733 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241734 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1735 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1736 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1737 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1738 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1739 "BtAAAAAAA=\r\n"),
1740 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361741 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241742 MockRead("You are not authorized to view this page\r\n"),
1743
1744 // Lastly we get the desired content.
1745 MockRead("HTTP/1.1 200 OK\r\n"),
1746 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1747 MockRead("Content-Length: 13\r\n\r\n"),
1748 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421749 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241750 };
1751
[email protected]31a2bfe2010-02-09 08:03:391752 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1753 data_writes1, arraysize(data_writes1));
1754 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1755 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591756 session_deps.socket_factory.AddSocketDataProvider(&data1);
1757 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241758
1759 TestCompletionCallback callback1;
1760
[email protected]684970b2009-08-14 04:54:461761 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421762 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241763
1764 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421765 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241766
[email protected]0757e7702009-03-27 04:00:221767 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1768 TestCompletionCallback callback2;
1769 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421770 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221771 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421772 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221773 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1774
[email protected]1c773ea12009-04-28 19:58:421775 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241776 EXPECT_FALSE(response == NULL);
1777
1778 // The password prompt info should have been set in response->auth_challenge.
1779 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1780
[email protected]71e4573a2009-05-21 22:03:001781 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241782 EXPECT_EQ(L"", response->auth_challenge->realm);
1783 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1784
[email protected]0757e7702009-03-27 04:00:221785 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241786
[email protected]0757e7702009-03-27 04:00:221787 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421788 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241789
[email protected]0757e7702009-03-27 04:00:221790 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421791 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241792
1793 response = trans->GetResponseInfo();
1794 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1795 EXPECT_EQ(13, response->headers->GetContentLength());
1796}
1797
[email protected]385a4672009-03-11 22:21:291798// Enter a wrong password, and then the correct one.
1799TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421800 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201801 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591802 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401803 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431804 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291805
[email protected]1c773ea12009-04-28 19:58:421806 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291807 request.method = "GET";
1808 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1809 request.load_flags = 0;
1810
1811 MockWrite data_writes1[] = {
1812 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1813 "Host: 172.22.68.17\r\n"
1814 "Connection: keep-alive\r\n\r\n"),
1815 };
1816
1817 MockRead data_reads1[] = {
1818 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1819 // Negotiate and NTLM are often requested together. We only support NTLM.
1820 MockRead("WWW-Authenticate: Negotiate\r\n"),
1821 MockRead("WWW-Authenticate: NTLM\r\n"),
1822 MockRead("Connection: close\r\n"),
1823 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361824 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291825 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421826 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291827 };
1828
1829 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221830 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291831 // request we should be issuing -- the final header line contains a Type
1832 // 1 message.
1833 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1834 "Host: 172.22.68.17\r\n"
1835 "Connection: keep-alive\r\n"
1836 "Authorization: NTLM "
1837 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1838
1839 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1840 // (the credentials for the origin server). The second request continues
1841 // on the same connection.
1842 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1843 "Host: 172.22.68.17\r\n"
1844 "Connection: keep-alive\r\n"
1845 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1846 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1847 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1848 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1849 "4Ww7b7E=\r\n\r\n"),
1850 };
1851
1852 MockRead data_reads2[] = {
1853 // The origin server responds with a Type 2 message.
1854 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1855 MockRead("WWW-Authenticate: NTLM "
1856 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1857 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1858 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1859 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1860 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1861 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1862 "BtAAAAAAA=\r\n"),
1863 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361864 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291865 MockRead("You are not authorized to view this page\r\n"),
1866
1867 // Wrong password.
1868 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1869 MockRead("WWW-Authenticate: Negotiate\r\n"),
1870 MockRead("WWW-Authenticate: NTLM\r\n"),
1871 MockRead("Connection: close\r\n"),
1872 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361873 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291874 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421875 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291876 };
1877
1878 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221879 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291880 // request we should be issuing -- the final header line contains a Type
1881 // 1 message.
1882 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1883 "Host: 172.22.68.17\r\n"
1884 "Connection: keep-alive\r\n"
1885 "Authorization: NTLM "
1886 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1887
1888 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1889 // (the credentials for the origin server). The second request continues
1890 // on the same connection.
1891 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1892 "Host: 172.22.68.17\r\n"
1893 "Connection: keep-alive\r\n"
1894 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1895 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1896 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1897 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1898 "+4MUm7c=\r\n\r\n"),
1899 };
1900
1901 MockRead data_reads3[] = {
1902 // The origin server responds with a Type 2 message.
1903 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1904 MockRead("WWW-Authenticate: NTLM "
1905 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1906 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1907 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1908 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1909 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1910 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1911 "BtAAAAAAA=\r\n"),
1912 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361913 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291914 MockRead("You are not authorized to view this page\r\n"),
1915
1916 // Lastly we get the desired content.
1917 MockRead("HTTP/1.1 200 OK\r\n"),
1918 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1919 MockRead("Content-Length: 13\r\n\r\n"),
1920 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421921 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291922 };
1923
[email protected]31a2bfe2010-02-09 08:03:391924 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1925 data_writes1, arraysize(data_writes1));
1926 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1927 data_writes2, arraysize(data_writes2));
1928 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1929 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591930 session_deps.socket_factory.AddSocketDataProvider(&data1);
1931 session_deps.socket_factory.AddSocketDataProvider(&data2);
1932 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291933
1934 TestCompletionCallback callback1;
1935
[email protected]684970b2009-08-14 04:54:461936 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421937 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291938
1939 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421940 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291941
[email protected]0757e7702009-03-27 04:00:221942 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291943 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221944 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421945 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291946 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421947 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221948 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291949
[email protected]1c773ea12009-04-28 19:58:421950 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291951 EXPECT_FALSE(response == NULL);
1952
1953 // The password prompt info should have been set in response->auth_challenge.
1954 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1955
[email protected]71e4573a2009-05-21 22:03:001956 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291957 EXPECT_EQ(L"", response->auth_challenge->realm);
1958 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1959
1960 TestCompletionCallback callback3;
1961
[email protected]0757e7702009-03-27 04:00:221962 // Enter the wrong password.
1963 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421964 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291965
1966 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421967 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291968
[email protected]0757e7702009-03-27 04:00:221969 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1970 TestCompletionCallback callback4;
1971 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421972 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221973 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421974 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221975 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1976
1977 response = trans->GetResponseInfo();
1978 EXPECT_FALSE(response == NULL);
1979
1980 // The password prompt info should have been set in response->auth_challenge.
1981 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1982
[email protected]71e4573a2009-05-21 22:03:001983 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221984 EXPECT_EQ(L"", response->auth_challenge->realm);
1985 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1986
1987 TestCompletionCallback callback5;
1988
1989 // Now enter the right password.
1990 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421991 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221992
1993 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421994 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221995
[email protected]385a4672009-03-11 22:21:291996 response = trans->GetResponseInfo();
1997 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1998 EXPECT_EQ(13, response->headers->GetContentLength());
1999}
[email protected]ea9dc9a2009-09-05 00:43:322000#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292001
[email protected]4ddaf2502008-10-23 18:26:192002// Test reading a server response which has only headers, and no body.
2003// After some maximum number of bytes is consumed, the transaction should
2004// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2005TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592006 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402007 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432008 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192009
[email protected]1c773ea12009-04-28 19:58:422010 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192011 request.method = "GET";
2012 request.url = GURL("http://www.google.com/");
2013 request.load_flags = 0;
2014
[email protected]b75b7b2f2009-10-06 00:54:532015 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432016 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532017 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192018
2019 MockRead data_reads[] = {
2020 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432021 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192022 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422023 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192024 };
[email protected]31a2bfe2010-02-09 08:03:392025 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592026 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192027
2028 TestCompletionCallback callback;
2029
[email protected]684970b2009-08-14 04:54:462030 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422031 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192032
2033 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422034 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192035
[email protected]1c773ea12009-04-28 19:58:422036 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192037 EXPECT_TRUE(response == NULL);
2038}
[email protected]f4e426b2008-11-05 00:24:492039
2040// Make sure that we don't try to reuse a TCPClientSocket when failing to
2041// establish tunnel.
2042// http://code.google.com/p/chromium/issues/detail?id=3772
2043TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2044 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592045 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012046
[email protected]228ff742009-06-05 01:19:592047 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492048
[email protected]5695b8c2009-09-30 21:36:432049 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492050
[email protected]1c773ea12009-04-28 19:58:422051 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492052 request.method = "GET";
2053 request.url = GURL("https://www.google.com/");
2054 request.load_flags = 0;
2055
2056 // Since we have proxy, should try to establish tunnel.
2057 MockWrite data_writes1[] = {
2058 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452059 "Host: www.google.com\r\n"
2060 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492061 };
2062
[email protected]77848d12008-11-14 00:00:222063 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492064 // connection. Usually a proxy would return 501 (not implemented),
2065 // or 200 (tunnel established).
2066 MockRead data_reads1[] = {
2067 MockRead("HTTP/1.1 404 Not Found\r\n"),
2068 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422069 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492070 };
2071
[email protected]31a2bfe2010-02-09 08:03:392072 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2073 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592074 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492075
2076 TestCompletionCallback callback1;
2077
[email protected]684970b2009-08-14 04:54:462078 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422079 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492080
2081 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422082 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492083
[email protected]1c773ea12009-04-28 19:58:422084 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082085 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492086
[email protected]b4404c02009-04-10 16:38:522087 // Empty the current queue. This is necessary because idle sockets are
2088 // added to the connection pool asynchronously with a PostTask.
2089 MessageLoop::current()->RunAllPending();
2090
[email protected]f4e426b2008-11-05 00:24:492091 // We now check to make sure the TCPClientSocket was not added back to
2092 // the pool.
[email protected]a937a06d2009-08-19 21:19:242093 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492094 trans.reset();
[email protected]b4404c02009-04-10 16:38:522095 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492096 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242097 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492098}
[email protected]372d34a2008-11-05 21:30:512099
[email protected]1b157c02009-04-21 01:55:402100// Make sure that we recycle a socket after reading all of the response body.
2101TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592102 SessionDependencies session_deps;
2103 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402104
[email protected]5695b8c2009-09-30 21:36:432105 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402106
[email protected]1c773ea12009-04-28 19:58:422107 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402108 request.method = "GET";
2109 request.url = GURL("http://www.google.com/");
2110 request.load_flags = 0;
2111
2112 MockRead data_reads[] = {
2113 // A part of the response body is received with the response headers.
2114 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2115 // The rest of the response body is received in two parts.
2116 MockRead("lo"),
2117 MockRead(" world"),
2118 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422119 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402120 };
2121
[email protected]31a2bfe2010-02-09 08:03:392122 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592123 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402124
2125 TestCompletionCallback callback;
2126
[email protected]684970b2009-08-14 04:54:462127 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422128 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402129
2130 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422131 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402132
[email protected]1c773ea12009-04-28 19:58:422133 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402134 EXPECT_TRUE(response != NULL);
2135
2136 EXPECT_TRUE(response->headers != NULL);
2137 std::string status_line = response->headers->GetStatusLine();
2138 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2139
[email protected]a937a06d2009-08-19 21:19:242140 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402141
2142 std::string response_data;
2143 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422144 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402145 EXPECT_EQ("hello world", response_data);
2146
2147 // Empty the current queue. This is necessary because idle sockets are
2148 // added to the connection pool asynchronously with a PostTask.
2149 MessageLoop::current()->RunAllPending();
2150
2151 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242152 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402153}
2154
[email protected]b4404c02009-04-10 16:38:522155// Make sure that we recycle a socket after a zero-length response.
2156// http://crbug.com/9880
2157TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592158 SessionDependencies session_deps;
2159 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522160
[email protected]5695b8c2009-09-30 21:36:432161 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522162
[email protected]1c773ea12009-04-28 19:58:422163 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522164 request.method = "GET";
2165 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2166 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2167 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2168 "rt=prt.2642,ol.2649,xjs.2951");
2169 request.load_flags = 0;
2170
2171 MockRead data_reads[] = {
2172 MockRead("HTTP/1.1 204 No Content\r\n"
2173 "Content-Length: 0\r\n"
2174 "Content-Type: text/html\r\n\r\n"),
2175 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422176 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522177 };
2178
[email protected]31a2bfe2010-02-09 08:03:392179 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592180 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522181
2182 TestCompletionCallback callback;
2183
[email protected]684970b2009-08-14 04:54:462184 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422185 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522186
2187 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422188 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522189
[email protected]1c773ea12009-04-28 19:58:422190 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522191 EXPECT_TRUE(response != NULL);
2192
2193 EXPECT_TRUE(response->headers != NULL);
2194 std::string status_line = response->headers->GetStatusLine();
2195 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2196
[email protected]a937a06d2009-08-19 21:19:242197 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522198
2199 std::string response_data;
2200 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422201 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522202 EXPECT_EQ("", response_data);
2203
2204 // Empty the current queue. This is necessary because idle sockets are
2205 // added to the connection pool asynchronously with a PostTask.
2206 MessageLoop::current()->RunAllPending();
2207
2208 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242209 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522210}
2211
[email protected]372d34a2008-11-05 21:30:512212TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422213 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512214 // Transaction 1: a GET request that succeeds. The socket is recycled
2215 // after use.
2216 request[0].method = "GET";
2217 request[0].url = GURL("http://www.google.com/");
2218 request[0].load_flags = 0;
2219 // Transaction 2: a POST request. Reuses the socket kept alive from
2220 // transaction 1. The first attempts fails when writing the POST data.
2221 // This causes the transaction to retry with a new socket. The second
2222 // attempt succeeds.
2223 request[1].method = "POST";
2224 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422225 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512226 request[1].upload_data->AppendBytes("foo", 3);
2227 request[1].load_flags = 0;
2228
[email protected]228ff742009-06-05 01:19:592229 SessionDependencies session_deps;
2230 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512231
2232 // The first socket is used for transaction 1 and the first attempt of
2233 // transaction 2.
2234
2235 // The response of transaction 1.
2236 MockRead data_reads1[] = {
2237 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2238 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422239 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512240 };
2241 // The mock write results of transaction 1 and the first attempt of
2242 // transaction 2.
2243 MockWrite data_writes1[] = {
2244 MockWrite(false, 64), // GET
2245 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422246 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512247 };
[email protected]31a2bfe2010-02-09 08:03:392248 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2249 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512250
2251 // The second socket is used for the second attempt of transaction 2.
2252
2253 // The response of transaction 2.
2254 MockRead data_reads2[] = {
2255 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2256 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422257 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512258 };
2259 // The mock write results of the second attempt of transaction 2.
2260 MockWrite data_writes2[] = {
2261 MockWrite(false, 93), // POST
2262 MockWrite(false, 3), // POST data
2263 };
[email protected]31a2bfe2010-02-09 08:03:392264 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2265 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512266
[email protected]5ecc992a42009-11-11 01:41:592267 session_deps.socket_factory.AddSocketDataProvider(&data1);
2268 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512269
2270 const char* kExpectedResponseData[] = {
2271 "hello world", "welcome"
2272 };
2273
2274 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422275 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432276 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512277
2278 TestCompletionCallback callback;
2279
[email protected]684970b2009-08-14 04:54:462280 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422281 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512282
2283 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422284 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512285
[email protected]1c773ea12009-04-28 19:58:422286 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512287 EXPECT_TRUE(response != NULL);
2288
2289 EXPECT_TRUE(response->headers != NULL);
2290 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2291
2292 std::string response_data;
2293 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422294 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512295 EXPECT_EQ(kExpectedResponseData[i], response_data);
2296 }
2297}
[email protected]f9ee6b52008-11-08 06:46:232298
2299// Test the request-challenge-retry sequence for basic auth when there is
2300// an identity in the URL. The request should be sent as normal, but when
2301// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322302TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592303 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402304 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432305 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232306
[email protected]1c773ea12009-04-28 19:58:422307 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232308 request.method = "GET";
2309 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292310 request.url = GURL("http://foo:b@[email protected]/");
2311
2312 // The password contains an escaped character -- for this test to pass it
2313 // will need to be unescaped by HttpNetworkTransaction.
2314 EXPECT_EQ("b%40r", request.url.password());
2315
[email protected]ea9dc9a2009-09-05 00:43:322316 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232317
2318 MockWrite data_writes1[] = {
2319 MockWrite("GET / HTTP/1.1\r\n"
2320 "Host: www.google.com\r\n"
2321 "Connection: keep-alive\r\n\r\n"),
2322 };
2323
2324 MockRead data_reads1[] = {
2325 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2326 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2327 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422328 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232329 };
2330
2331 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322332 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232333 MockWrite data_writes2[] = {
2334 MockWrite("GET / HTTP/1.1\r\n"
2335 "Host: www.google.com\r\n"
2336 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292337 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232338 };
2339
2340 MockRead data_reads2[] = {
2341 MockRead("HTTP/1.0 200 OK\r\n"),
2342 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422343 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232344 };
2345
[email protected]31a2bfe2010-02-09 08:03:392346 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2347 data_writes1, arraysize(data_writes1));
2348 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2349 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592350 session_deps.socket_factory.AddSocketDataProvider(&data1);
2351 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232352
2353 TestCompletionCallback callback1;
2354
[email protected]684970b2009-08-14 04:54:462355 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422356 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232357
2358 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422359 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232360
[email protected]0757e7702009-03-27 04:00:222361 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2362 TestCompletionCallback callback2;
2363 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422364 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222365 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422366 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222367 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2368
[email protected]1c773ea12009-04-28 19:58:422369 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232370 EXPECT_FALSE(response == NULL);
2371
2372 // There is no challenge info, since the identity in URL worked.
2373 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2374
2375 EXPECT_EQ(100, response->headers->GetContentLength());
2376
2377 // Empty the current queue.
2378 MessageLoop::current()->RunAllPending();
2379}
2380
[email protected]ea9dc9a2009-09-05 00:43:322381// Test the request-challenge-retry sequence for basic auth when there is
2382// an incorrect identity in the URL. The identity from the URL should be used
2383// only once.
2384TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2385 SessionDependencies session_deps;
2386 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432387 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322388
2389 HttpRequestInfo request;
2390 request.method = "GET";
2391 // Note: the URL has a username:password in it. The password "baz" is
2392 // wrong (should be "bar").
2393 request.url = GURL("http://foo:[email protected]/");
2394
2395 request.load_flags = LOAD_NORMAL;
2396
2397 MockWrite data_writes1[] = {
2398 MockWrite("GET / HTTP/1.1\r\n"
2399 "Host: www.google.com\r\n"
2400 "Connection: keep-alive\r\n\r\n"),
2401 };
2402
2403 MockRead data_reads1[] = {
2404 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2405 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2406 MockRead("Content-Length: 10\r\n\r\n"),
2407 MockRead(false, ERR_FAILED),
2408 };
2409
2410 // After the challenge above, the transaction will be restarted using the
2411 // identity from the url (foo, baz) to answer the challenge.
2412 MockWrite data_writes2[] = {
2413 MockWrite("GET / HTTP/1.1\r\n"
2414 "Host: www.google.com\r\n"
2415 "Connection: keep-alive\r\n"
2416 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2417 };
2418
2419 MockRead data_reads2[] = {
2420 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2421 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2422 MockRead("Content-Length: 10\r\n\r\n"),
2423 MockRead(false, ERR_FAILED),
2424 };
2425
2426 // After the challenge above, the transaction will be restarted using the
2427 // identity supplied by the user (foo, bar) to answer the challenge.
2428 MockWrite data_writes3[] = {
2429 MockWrite("GET / HTTP/1.1\r\n"
2430 "Host: www.google.com\r\n"
2431 "Connection: keep-alive\r\n"
2432 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2433 };
2434
2435 MockRead data_reads3[] = {
2436 MockRead("HTTP/1.0 200 OK\r\n"),
2437 MockRead("Content-Length: 100\r\n\r\n"),
2438 MockRead(false, OK),
2439 };
2440
[email protected]31a2bfe2010-02-09 08:03:392441 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2442 data_writes1, arraysize(data_writes1));
2443 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2444 data_writes2, arraysize(data_writes2));
2445 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2446 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592447 session_deps.socket_factory.AddSocketDataProvider(&data1);
2448 session_deps.socket_factory.AddSocketDataProvider(&data2);
2449 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322450
2451 TestCompletionCallback callback1;
2452
2453 int rv = trans->Start(&request, &callback1, NULL);
2454 EXPECT_EQ(ERR_IO_PENDING, rv);
2455
2456 rv = callback1.WaitForResult();
2457 EXPECT_EQ(OK, rv);
2458
2459 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2460 TestCompletionCallback callback2;
2461 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2462 EXPECT_EQ(ERR_IO_PENDING, rv);
2463 rv = callback2.WaitForResult();
2464 EXPECT_EQ(OK, rv);
2465 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2466
2467 const HttpResponseInfo* response = trans->GetResponseInfo();
2468 EXPECT_FALSE(response == NULL);
2469 // The password prompt info should have been set in response->auth_challenge.
2470 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2471
2472 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2473 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2474 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2475
2476 TestCompletionCallback callback3;
2477 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2478 EXPECT_EQ(ERR_IO_PENDING, rv);
2479 rv = callback3.WaitForResult();
2480 EXPECT_EQ(OK, rv);
2481 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2482
2483 response = trans->GetResponseInfo();
2484 EXPECT_FALSE(response == NULL);
2485
2486 // There is no challenge info, since the identity worked.
2487 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2488
2489 EXPECT_EQ(100, response->headers->GetContentLength());
2490
2491 // Empty the current queue.
2492 MessageLoop::current()->RunAllPending();
2493}
2494
[email protected]f9ee6b52008-11-08 06:46:232495// Test that previously tried username/passwords for a realm get re-used.
2496TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592497 SessionDependencies session_deps;
2498 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232499
2500 // Transaction 1: authenticate (foo, bar) on MyRealm1
2501 {
[email protected]5695b8c2009-09-30 21:36:432502 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232503
[email protected]1c773ea12009-04-28 19:58:422504 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232505 request.method = "GET";
2506 request.url = GURL("http://www.google.com/x/y/z");
2507 request.load_flags = 0;
2508
2509 MockWrite data_writes1[] = {
2510 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2511 "Host: www.google.com\r\n"
2512 "Connection: keep-alive\r\n\r\n"),
2513 };
2514
2515 MockRead data_reads1[] = {
2516 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2517 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2518 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422519 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232520 };
2521
2522 // Resend with authorization (username=foo, password=bar)
2523 MockWrite data_writes2[] = {
2524 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2525 "Host: www.google.com\r\n"
2526 "Connection: keep-alive\r\n"
2527 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2528 };
2529
2530 // Sever accepts the authorization.
2531 MockRead data_reads2[] = {
2532 MockRead("HTTP/1.0 200 OK\r\n"),
2533 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422534 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232535 };
2536
[email protected]31a2bfe2010-02-09 08:03:392537 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2538 data_writes1, arraysize(data_writes1));
2539 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2540 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592541 session_deps.socket_factory.AddSocketDataProvider(&data1);
2542 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232543
2544 TestCompletionCallback callback1;
2545
[email protected]684970b2009-08-14 04:54:462546 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422547 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232548
2549 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422550 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232551
[email protected]1c773ea12009-04-28 19:58:422552 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232553 EXPECT_FALSE(response == NULL);
2554
2555 // The password prompt info should have been set in
2556 // response->auth_challenge.
2557 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2558
[email protected]71e4573a2009-05-21 22:03:002559 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232560 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2561 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2562
2563 TestCompletionCallback callback2;
2564
2565 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422566 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232567
2568 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422569 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232570
2571 response = trans->GetResponseInfo();
2572 EXPECT_FALSE(response == NULL);
2573 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2574 EXPECT_EQ(100, response->headers->GetContentLength());
2575 }
2576
2577 // ------------------------------------------------------------------------
2578
2579 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2580 {
[email protected]5695b8c2009-09-30 21:36:432581 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232582
[email protected]1c773ea12009-04-28 19:58:422583 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232584 request.method = "GET";
2585 // Note that Transaction 1 was at /x/y/z, so this is in the same
2586 // protection space as MyRealm1.
2587 request.url = GURL("http://www.google.com/x/y/a/b");
2588 request.load_flags = 0;
2589
2590 MockWrite data_writes1[] = {
2591 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2592 "Host: www.google.com\r\n"
2593 "Connection: keep-alive\r\n"
2594 // Send preemptive authorization for MyRealm1
2595 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2596 };
2597
2598 // The server didn't like the preemptive authorization, and
2599 // challenges us for a different realm (MyRealm2).
2600 MockRead data_reads1[] = {
2601 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2602 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2603 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422604 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232605 };
2606
2607 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2608 MockWrite data_writes2[] = {
2609 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2610 "Host: www.google.com\r\n"
2611 "Connection: keep-alive\r\n"
2612 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2613 };
2614
2615 // Sever accepts the authorization.
2616 MockRead data_reads2[] = {
2617 MockRead("HTTP/1.0 200 OK\r\n"),
2618 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422619 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232620 };
2621
[email protected]31a2bfe2010-02-09 08:03:392622 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2623 data_writes1, arraysize(data_writes1));
2624 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2625 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592626 session_deps.socket_factory.AddSocketDataProvider(&data1);
2627 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232628
2629 TestCompletionCallback callback1;
2630
[email protected]684970b2009-08-14 04:54:462631 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422632 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232633
2634 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422635 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232636
[email protected]1c773ea12009-04-28 19:58:422637 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232638 EXPECT_FALSE(response == NULL);
2639
2640 // The password prompt info should have been set in
2641 // response->auth_challenge.
2642 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2643
[email protected]71e4573a2009-05-21 22:03:002644 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232645 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2646 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2647
2648 TestCompletionCallback callback2;
2649
2650 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422651 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232652
2653 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422654 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232655
2656 response = trans->GetResponseInfo();
2657 EXPECT_FALSE(response == NULL);
2658 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2659 EXPECT_EQ(100, response->headers->GetContentLength());
2660 }
2661
2662 // ------------------------------------------------------------------------
2663
2664 // Transaction 3: Resend a request in MyRealm's protection space --
2665 // succeed with preemptive authorization.
2666 {
[email protected]5695b8c2009-09-30 21:36:432667 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232668
[email protected]1c773ea12009-04-28 19:58:422669 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232670 request.method = "GET";
2671 request.url = GURL("http://www.google.com/x/y/z2");
2672 request.load_flags = 0;
2673
2674 MockWrite data_writes1[] = {
2675 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2676 "Host: www.google.com\r\n"
2677 "Connection: keep-alive\r\n"
2678 // The authorization for MyRealm1 gets sent preemptively
2679 // (since the url is in the same protection space)
2680 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2681 };
2682
2683 // Sever accepts the preemptive authorization
2684 MockRead data_reads1[] = {
2685 MockRead("HTTP/1.0 200 OK\r\n"),
2686 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422687 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232688 };
2689
[email protected]31a2bfe2010-02-09 08:03:392690 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2691 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592692 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232693
2694 TestCompletionCallback callback1;
2695
[email protected]684970b2009-08-14 04:54:462696 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422697 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232698
2699 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422700 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232701
[email protected]1c773ea12009-04-28 19:58:422702 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232703 EXPECT_FALSE(response == NULL);
2704
2705 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2706 EXPECT_EQ(100, response->headers->GetContentLength());
2707 }
2708
2709 // ------------------------------------------------------------------------
2710
2711 // Transaction 4: request another URL in MyRealm (however the
2712 // url is not known to belong to the protection space, so no pre-auth).
2713 {
[email protected]5695b8c2009-09-30 21:36:432714 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232715
[email protected]1c773ea12009-04-28 19:58:422716 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232717 request.method = "GET";
2718 request.url = GURL("http://www.google.com/x/1");
2719 request.load_flags = 0;
2720
2721 MockWrite data_writes1[] = {
2722 MockWrite("GET /x/1 HTTP/1.1\r\n"
2723 "Host: www.google.com\r\n"
2724 "Connection: keep-alive\r\n\r\n"),
2725 };
2726
2727 MockRead data_reads1[] = {
2728 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2729 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2730 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422731 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232732 };
2733
2734 // Resend with authorization from MyRealm's cache.
2735 MockWrite data_writes2[] = {
2736 MockWrite("GET /x/1 HTTP/1.1\r\n"
2737 "Host: www.google.com\r\n"
2738 "Connection: keep-alive\r\n"
2739 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2740 };
2741
2742 // Sever accepts the authorization.
2743 MockRead data_reads2[] = {
2744 MockRead("HTTP/1.0 200 OK\r\n"),
2745 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422746 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232747 };
2748
[email protected]31a2bfe2010-02-09 08:03:392749 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2750 data_writes1, arraysize(data_writes1));
2751 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2752 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592753 session_deps.socket_factory.AddSocketDataProvider(&data1);
2754 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232755
2756 TestCompletionCallback callback1;
2757
[email protected]684970b2009-08-14 04:54:462758 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422759 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232760
2761 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422762 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232763
[email protected]0757e7702009-03-27 04:00:222764 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2765 TestCompletionCallback callback2;
2766 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422767 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222768 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422769 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222770 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2771
[email protected]1c773ea12009-04-28 19:58:422772 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232773 EXPECT_FALSE(response == NULL);
2774 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2775 EXPECT_EQ(100, response->headers->GetContentLength());
2776 }
2777
2778 // ------------------------------------------------------------------------
2779
2780 // Transaction 5: request a URL in MyRealm, but the server rejects the
2781 // cached identity. Should invalidate and re-prompt.
2782 {
[email protected]5695b8c2009-09-30 21:36:432783 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232784
[email protected]1c773ea12009-04-28 19:58:422785 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232786 request.method = "GET";
2787 request.url = GURL("http://www.google.com/p/q/t");
2788 request.load_flags = 0;
2789
2790 MockWrite data_writes1[] = {
2791 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2792 "Host: www.google.com\r\n"
2793 "Connection: keep-alive\r\n\r\n"),
2794 };
2795
2796 MockRead data_reads1[] = {
2797 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2798 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2799 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422800 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232801 };
2802
2803 // Resend with authorization from cache for MyRealm.
2804 MockWrite data_writes2[] = {
2805 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2806 "Host: www.google.com\r\n"
2807 "Connection: keep-alive\r\n"
2808 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2809 };
2810
2811 // Sever rejects the authorization.
2812 MockRead data_reads2[] = {
2813 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2814 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2815 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422816 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232817 };
2818
2819 // At this point we should prompt for new credentials for MyRealm.
2820 // Restart with username=foo3, password=foo4.
2821 MockWrite data_writes3[] = {
2822 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2823 "Host: www.google.com\r\n"
2824 "Connection: keep-alive\r\n"
2825 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2826 };
2827
2828 // Sever accepts the authorization.
2829 MockRead data_reads3[] = {
2830 MockRead("HTTP/1.0 200 OK\r\n"),
2831 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422832 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232833 };
2834
[email protected]31a2bfe2010-02-09 08:03:392835 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2836 data_writes1, arraysize(data_writes1));
2837 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2838 data_writes2, arraysize(data_writes2));
2839 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2840 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592841 session_deps.socket_factory.AddSocketDataProvider(&data1);
2842 session_deps.socket_factory.AddSocketDataProvider(&data2);
2843 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232844
2845 TestCompletionCallback callback1;
2846
[email protected]684970b2009-08-14 04:54:462847 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422848 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232849
2850 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422851 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232852
[email protected]0757e7702009-03-27 04:00:222853 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2854 TestCompletionCallback callback2;
2855 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422856 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222857 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422858 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222859 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2860
[email protected]1c773ea12009-04-28 19:58:422861 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232862 EXPECT_FALSE(response == NULL);
2863
2864 // The password prompt info should have been set in
2865 // response->auth_challenge.
2866 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2867
[email protected]71e4573a2009-05-21 22:03:002868 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232869 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2870 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2871
[email protected]0757e7702009-03-27 04:00:222872 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232873
[email protected]0757e7702009-03-27 04:00:222874 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422875 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232876
[email protected]0757e7702009-03-27 04:00:222877 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422878 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232879
2880 response = trans->GetResponseInfo();
2881 EXPECT_FALSE(response == NULL);
2882 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2883 EXPECT_EQ(100, response->headers->GetContentLength());
2884 }
2885}
[email protected]89ceba9a2009-03-21 03:46:062886
2887// Test the ResetStateForRestart() private method.
2888TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2889 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592890 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402891 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432892 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062893
2894 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062895 trans->read_buf_ = new IOBuffer(15);
2896 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572897 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062898
2899 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142900 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572901 response->auth_challenge = new AuthChallengeInfo();
2902 response->ssl_info.cert_status = -15;
2903 response->response_time = base::Time::Now();
2904 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062905
2906 { // Setup state for response_.vary_data
2907 HttpRequestInfo request;
2908 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2909 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572910 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]89ceba9a2009-03-21 03:46:062911 request.extra_headers = "Foo: 1\nbar: 23";
[email protected]0877e3d2009-10-17 22:29:572912 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062913 }
2914
2915 // Cause the above state to be reset.
2916 trans->ResetStateForRestart();
2917
2918 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:072919 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062920 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572921 EXPECT_EQ(0U, trans->request_headers_.size());
2922 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2923 EXPECT_TRUE(response->headers.get() == NULL);
2924 EXPECT_EQ(false, response->was_cached);
2925 EXPECT_EQ(0, response->ssl_info.cert_status);
2926 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062927}
2928
[email protected]bacff652009-03-31 17:50:332929// Test HTTPS connections to a site with a bad certificate
2930TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592931 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402932 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432933 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332934
2935 HttpRequestInfo request;
2936 request.method = "GET";
2937 request.url = GURL("https://www.google.com/");
2938 request.load_flags = 0;
2939
2940 MockWrite data_writes[] = {
2941 MockWrite("GET / HTTP/1.1\r\n"
2942 "Host: www.google.com\r\n"
2943 "Connection: keep-alive\r\n\r\n"),
2944 };
2945
2946 MockRead data_reads[] = {
2947 MockRead("HTTP/1.0 200 OK\r\n"),
2948 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2949 MockRead("Content-Length: 100\r\n\r\n"),
2950 MockRead(false, OK),
2951 };
2952
[email protected]5ecc992a42009-11-11 01:41:592953 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:392954 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2955 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592956 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2957 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332958
[email protected]5ecc992a42009-11-11 01:41:592959 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2960 session_deps.socket_factory.AddSocketDataProvider(&data);
2961 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2962 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332963
2964 TestCompletionCallback callback;
2965
[email protected]684970b2009-08-14 04:54:462966 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332967 EXPECT_EQ(ERR_IO_PENDING, rv);
2968
2969 rv = callback.WaitForResult();
2970 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2971
2972 rv = trans->RestartIgnoringLastError(&callback);
2973 EXPECT_EQ(ERR_IO_PENDING, rv);
2974
2975 rv = callback.WaitForResult();
2976 EXPECT_EQ(OK, rv);
2977
2978 const HttpResponseInfo* response = trans->GetResponseInfo();
2979
2980 EXPECT_FALSE(response == NULL);
2981 EXPECT_EQ(100, response->headers->GetContentLength());
2982}
2983
2984// Test HTTPS connections to a site with a bad certificate, going through a
2985// proxy
2986TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592987 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332988
2989 HttpRequestInfo request;
2990 request.method = "GET";
2991 request.url = GURL("https://www.google.com/");
2992 request.load_flags = 0;
2993
2994 MockWrite proxy_writes[] = {
2995 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452996 "Host: www.google.com\r\n"
2997 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332998 };
2999
3000 MockRead proxy_reads[] = {
3001 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423002 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333003 };
3004
3005 MockWrite data_writes[] = {
3006 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453007 "Host: www.google.com\r\n"
3008 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333009 MockWrite("GET / HTTP/1.1\r\n"
3010 "Host: www.google.com\r\n"
3011 "Connection: keep-alive\r\n\r\n"),
3012 };
3013
3014 MockRead data_reads[] = {
3015 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3016 MockRead("HTTP/1.0 200 OK\r\n"),
3017 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3018 MockRead("Content-Length: 100\r\n\r\n"),
3019 MockRead(false, OK),
3020 };
3021
[email protected]31a2bfe2010-02-09 08:03:393022 StaticSocketDataProvider ssl_bad_certificate(
3023 proxy_reads, arraysize(proxy_reads),
3024 proxy_writes, arraysize(proxy_writes));
3025 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3026 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593027 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3028 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333029
[email protected]5ecc992a42009-11-11 01:41:593030 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3031 session_deps.socket_factory.AddSocketDataProvider(&data);
3032 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3033 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333034
3035 TestCompletionCallback callback;
3036
3037 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593038 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333039
[email protected]d207a5f2009-06-04 05:28:403040 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433041 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333042
[email protected]684970b2009-08-14 04:54:463043 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:333044 EXPECT_EQ(ERR_IO_PENDING, rv);
3045
3046 rv = callback.WaitForResult();
3047 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3048
3049 rv = trans->RestartIgnoringLastError(&callback);
3050 EXPECT_EQ(ERR_IO_PENDING, rv);
3051
3052 rv = callback.WaitForResult();
3053 EXPECT_EQ(OK, rv);
3054
3055 const HttpResponseInfo* response = trans->GetResponseInfo();
3056
3057 EXPECT_FALSE(response == NULL);
3058 EXPECT_EQ(100, response->headers->GetContentLength());
3059 }
3060}
3061
[email protected]1c773ea12009-04-28 19:58:423062TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593063 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403064 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433065 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423066
3067 HttpRequestInfo request;
3068 request.method = "GET";
3069 request.url = GURL("http://www.google.com/");
3070 request.user_agent = "Chromium Ultra Awesome X Edition";
3071
3072 MockWrite data_writes[] = {
3073 MockWrite("GET / HTTP/1.1\r\n"
3074 "Host: www.google.com\r\n"
3075 "Connection: keep-alive\r\n"
3076 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3077 };
3078
3079 // Lastly, the server responds with the actual content.
3080 MockRead data_reads[] = {
3081 MockRead("HTTP/1.0 200 OK\r\n"),
3082 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3083 MockRead("Content-Length: 100\r\n\r\n"),
3084 MockRead(false, OK),
3085 };
3086
[email protected]31a2bfe2010-02-09 08:03:393087 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3088 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593089 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423090
3091 TestCompletionCallback callback;
3092
[email protected]684970b2009-08-14 04:54:463093 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423094 EXPECT_EQ(ERR_IO_PENDING, rv);
3095
3096 rv = callback.WaitForResult();
3097 EXPECT_EQ(OK, rv);
3098}
3099
3100TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593101 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403102 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433103 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423104
3105 HttpRequestInfo request;
3106 request.method = "GET";
3107 request.url = GURL("http://www.google.com/");
3108 request.load_flags = 0;
3109 request.referrer = GURL("http://the.previous.site.com/");
3110
3111 MockWrite data_writes[] = {
3112 MockWrite("GET / HTTP/1.1\r\n"
3113 "Host: www.google.com\r\n"
3114 "Connection: keep-alive\r\n"
3115 "Referer: http://the.previous.site.com/\r\n\r\n"),
3116 };
3117
3118 // Lastly, the server responds with the actual content.
3119 MockRead data_reads[] = {
3120 MockRead("HTTP/1.0 200 OK\r\n"),
3121 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3122 MockRead("Content-Length: 100\r\n\r\n"),
3123 MockRead(false, OK),
3124 };
3125
[email protected]31a2bfe2010-02-09 08:03:393126 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3127 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593128 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423129
3130 TestCompletionCallback callback;
3131
[email protected]684970b2009-08-14 04:54:463132 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423133 EXPECT_EQ(ERR_IO_PENDING, rv);
3134
3135 rv = callback.WaitForResult();
3136 EXPECT_EQ(OK, rv);
3137}
3138
3139TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593140 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403141 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433142 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423143
3144 HttpRequestInfo request;
3145 request.method = "POST";
3146 request.url = GURL("http://www.google.com/");
3147
3148 MockWrite data_writes[] = {
3149 MockWrite("POST / HTTP/1.1\r\n"
3150 "Host: www.google.com\r\n"
3151 "Connection: keep-alive\r\n"
3152 "Content-Length: 0\r\n\r\n"),
3153 };
3154
3155 // Lastly, the server responds with the actual content.
3156 MockRead data_reads[] = {
3157 MockRead("HTTP/1.0 200 OK\r\n"),
3158 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3159 MockRead("Content-Length: 100\r\n\r\n"),
3160 MockRead(false, OK),
3161 };
3162
[email protected]31a2bfe2010-02-09 08:03:393163 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3164 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593165 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423166
3167 TestCompletionCallback callback;
3168
[email protected]684970b2009-08-14 04:54:463169 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423170 EXPECT_EQ(ERR_IO_PENDING, rv);
3171
3172 rv = callback.WaitForResult();
3173 EXPECT_EQ(OK, rv);
3174}
3175
3176TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593177 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403178 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433179 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423180
3181 HttpRequestInfo request;
3182 request.method = "PUT";
3183 request.url = GURL("http://www.google.com/");
3184
3185 MockWrite data_writes[] = {
3186 MockWrite("PUT / HTTP/1.1\r\n"
3187 "Host: www.google.com\r\n"
3188 "Connection: keep-alive\r\n"
3189 "Content-Length: 0\r\n\r\n"),
3190 };
3191
3192 // Lastly, the server responds with the actual content.
3193 MockRead data_reads[] = {
3194 MockRead("HTTP/1.0 200 OK\r\n"),
3195 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3196 MockRead("Content-Length: 100\r\n\r\n"),
3197 MockRead(false, OK),
3198 };
3199
[email protected]31a2bfe2010-02-09 08:03:393200 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3201 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593202 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423203
3204 TestCompletionCallback callback;
3205
[email protected]684970b2009-08-14 04:54:463206 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423207 EXPECT_EQ(ERR_IO_PENDING, rv);
3208
3209 rv = callback.WaitForResult();
3210 EXPECT_EQ(OK, rv);
3211}
3212
3213TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593214 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403215 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433216 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423217
3218 HttpRequestInfo request;
3219 request.method = "HEAD";
3220 request.url = GURL("http://www.google.com/");
3221
3222 MockWrite data_writes[] = {
3223 MockWrite("HEAD / HTTP/1.1\r\n"
3224 "Host: www.google.com\r\n"
3225 "Connection: keep-alive\r\n"
3226 "Content-Length: 0\r\n\r\n"),
3227 };
3228
3229 // Lastly, the server responds with the actual content.
3230 MockRead data_reads[] = {
3231 MockRead("HTTP/1.0 200 OK\r\n"),
3232 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3233 MockRead("Content-Length: 100\r\n\r\n"),
3234 MockRead(false, OK),
3235 };
3236
[email protected]31a2bfe2010-02-09 08:03:393237 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3238 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593239 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423240
3241 TestCompletionCallback callback;
3242
[email protected]684970b2009-08-14 04:54:463243 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423244 EXPECT_EQ(ERR_IO_PENDING, rv);
3245
3246 rv = callback.WaitForResult();
3247 EXPECT_EQ(OK, rv);
3248}
3249
3250TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593251 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403252 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433253 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423254
3255 HttpRequestInfo request;
3256 request.method = "GET";
3257 request.url = GURL("http://www.google.com/");
3258 request.load_flags = LOAD_BYPASS_CACHE;
3259
3260 MockWrite data_writes[] = {
3261 MockWrite("GET / HTTP/1.1\r\n"
3262 "Host: www.google.com\r\n"
3263 "Connection: keep-alive\r\n"
3264 "Pragma: no-cache\r\n"
3265 "Cache-Control: no-cache\r\n\r\n"),
3266 };
3267
3268 // Lastly, the server responds with the actual content.
3269 MockRead data_reads[] = {
3270 MockRead("HTTP/1.0 200 OK\r\n"),
3271 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3272 MockRead("Content-Length: 100\r\n\r\n"),
3273 MockRead(false, OK),
3274 };
3275
[email protected]31a2bfe2010-02-09 08:03:393276 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3277 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593278 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423279
3280 TestCompletionCallback callback;
3281
[email protected]684970b2009-08-14 04:54:463282 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423283 EXPECT_EQ(ERR_IO_PENDING, rv);
3284
3285 rv = callback.WaitForResult();
3286 EXPECT_EQ(OK, rv);
3287}
3288
3289TEST_F(HttpNetworkTransactionTest,
3290 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593291 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403292 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433293 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423294
3295 HttpRequestInfo request;
3296 request.method = "GET";
3297 request.url = GURL("http://www.google.com/");
3298 request.load_flags = LOAD_VALIDATE_CACHE;
3299
3300 MockWrite data_writes[] = {
3301 MockWrite("GET / HTTP/1.1\r\n"
3302 "Host: www.google.com\r\n"
3303 "Connection: keep-alive\r\n"
3304 "Cache-Control: max-age=0\r\n\r\n"),
3305 };
3306
3307 // Lastly, the server responds with the actual content.
3308 MockRead data_reads[] = {
3309 MockRead("HTTP/1.0 200 OK\r\n"),
3310 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3311 MockRead("Content-Length: 100\r\n\r\n"),
3312 MockRead(false, OK),
3313 };
3314
[email protected]31a2bfe2010-02-09 08:03:393315 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3316 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593317 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423318
3319 TestCompletionCallback callback;
3320
[email protected]684970b2009-08-14 04:54:463321 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423322 EXPECT_EQ(ERR_IO_PENDING, rv);
3323
3324 rv = callback.WaitForResult();
3325 EXPECT_EQ(OK, rv);
3326}
3327
3328TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593329 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403330 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433331 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423332
3333 HttpRequestInfo request;
3334 request.method = "GET";
3335 request.url = GURL("http://www.google.com/");
3336 request.extra_headers = "FooHeader: Bar\r\n";
3337
3338 MockWrite data_writes[] = {
3339 MockWrite("GET / HTTP/1.1\r\n"
3340 "Host: www.google.com\r\n"
3341 "Connection: keep-alive\r\n"
3342 "FooHeader: Bar\r\n\r\n"),
3343 };
3344
3345 // Lastly, the server responds with the actual content.
3346 MockRead data_reads[] = {
3347 MockRead("HTTP/1.0 200 OK\r\n"),
3348 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3349 MockRead("Content-Length: 100\r\n\r\n"),
3350 MockRead(false, OK),
3351 };
3352
[email protected]31a2bfe2010-02-09 08:03:393353 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3354 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593355 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423356
3357 TestCompletionCallback callback;
3358
[email protected]684970b2009-08-14 04:54:463359 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423360 EXPECT_EQ(ERR_IO_PENDING, rv);
3361
3362 rv = callback.WaitForResult();
3363 EXPECT_EQ(OK, rv);
3364}
3365
[email protected]3cd17242009-06-23 02:59:023366TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093367 SessionDependencies session_deps(
3368 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023369
3370 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433371 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023372
3373 HttpRequestInfo request;
3374 request.method = "GET";
3375 request.url = GURL("http://www.google.com/");
3376 request.load_flags = 0;
3377
3378 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3379 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3380
3381 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353382 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023383 MockWrite("GET / HTTP/1.1\r\n"
3384 "Host: www.google.com\r\n"
3385 "Connection: keep-alive\r\n\r\n")
3386 };
3387
3388 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593389 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023390 MockRead("HTTP/1.0 200 OK\r\n"),
3391 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3392 MockRead("Payload"),
3393 MockRead(false, OK)
3394 };
3395
[email protected]31a2bfe2010-02-09 08:03:393396 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3397 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593398 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023399
3400 TestCompletionCallback callback;
3401
[email protected]684970b2009-08-14 04:54:463402 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023403 EXPECT_EQ(ERR_IO_PENDING, rv);
3404
3405 rv = callback.WaitForResult();
3406 EXPECT_EQ(OK, rv);
3407
3408 const HttpResponseInfo* response = trans->GetResponseInfo();
3409 EXPECT_FALSE(response == NULL);
3410
3411 std::string response_text;
3412 rv = ReadTransaction(trans.get(), &response_text);
3413 EXPECT_EQ(OK, rv);
3414 EXPECT_EQ("Payload", response_text);
3415}
3416
3417TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093418 SessionDependencies session_deps(
3419 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023420
3421 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433422 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023423
3424 HttpRequestInfo request;
3425 request.method = "GET";
3426 request.url = GURL("https://www.google.com/");
3427 request.load_flags = 0;
3428
3429 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3430 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3431
3432 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353433 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3434 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023435 MockWrite("GET / HTTP/1.1\r\n"
3436 "Host: www.google.com\r\n"
3437 "Connection: keep-alive\r\n\r\n")
3438 };
3439
3440 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353441 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3442 arraysize(read_buffer)),
3443 MockRead("HTTP/1.0 200 OK\r\n"),
3444 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3445 MockRead("Payload"),
3446 MockRead(false, OK)
3447 };
3448
[email protected]31a2bfe2010-02-09 08:03:393449 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3450 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593451 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353452
[email protected]5ecc992a42009-11-11 01:41:593453 SSLSocketDataProvider ssl(true, OK);
3454 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353455
3456 TestCompletionCallback callback;
3457
[email protected]684970b2009-08-14 04:54:463458 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353459 EXPECT_EQ(ERR_IO_PENDING, rv);
3460
3461 rv = callback.WaitForResult();
3462 EXPECT_EQ(OK, rv);
3463
3464 const HttpResponseInfo* response = trans->GetResponseInfo();
3465 EXPECT_FALSE(response == NULL);
3466
3467 std::string response_text;
3468 rv = ReadTransaction(trans.get(), &response_text);
3469 EXPECT_EQ(OK, rv);
3470 EXPECT_EQ("Payload", response_text);
3471}
3472
3473TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093474 SessionDependencies session_deps(
3475 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353476
3477 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433478 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353479
3480 HttpRequestInfo request;
3481 request.method = "GET";
3482 request.url = GURL("http://www.google.com/");
3483 request.load_flags = 0;
3484
3485 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3486 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373487 const char kSOCKS5OkRequest[] = {
3488 0x05, // Version
3489 0x01, // Command (CONNECT)
3490 0x00, // Reserved.
3491 0x03, // Address type (DOMAINNAME).
3492 0x0E, // Length of domain (14)
3493 // Domain string:
3494 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3495 0x00, 0x50, // 16-bit port (80)
3496 };
[email protected]e0c27be2009-07-15 13:09:353497 const char kSOCKS5OkResponse[] =
3498 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3499
3500 MockWrite data_writes[] = {
3501 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3502 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3503 MockWrite("GET / HTTP/1.1\r\n"
3504 "Host: www.google.com\r\n"
3505 "Connection: keep-alive\r\n\r\n")
3506 };
3507
3508 MockRead data_reads[] = {
3509 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3510 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3511 MockRead("HTTP/1.0 200 OK\r\n"),
3512 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3513 MockRead("Payload"),
3514 MockRead(false, OK)
3515 };
3516
[email protected]31a2bfe2010-02-09 08:03:393517 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3518 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593519 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353520
3521 TestCompletionCallback callback;
3522
[email protected]684970b2009-08-14 04:54:463523 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353524 EXPECT_EQ(ERR_IO_PENDING, rv);
3525
3526 rv = callback.WaitForResult();
3527 EXPECT_EQ(OK, rv);
3528
3529 const HttpResponseInfo* response = trans->GetResponseInfo();
3530 EXPECT_FALSE(response == NULL);
3531
3532 std::string response_text;
3533 rv = ReadTransaction(trans.get(), &response_text);
3534 EXPECT_EQ(OK, rv);
3535 EXPECT_EQ("Payload", response_text);
3536}
3537
3538TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093539 SessionDependencies session_deps(
3540 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353541
3542 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433543 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353544
3545 HttpRequestInfo request;
3546 request.method = "GET";
3547 request.url = GURL("https://www.google.com/");
3548 request.load_flags = 0;
3549
3550 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3551 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373552 const unsigned char kSOCKS5OkRequest[] = {
3553 0x05, // Version
3554 0x01, // Command (CONNECT)
3555 0x00, // Reserved.
3556 0x03, // Address type (DOMAINNAME).
3557 0x0E, // Length of domain (14)
3558 // Domain string:
3559 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3560 0x01, 0xBB, // 16-bit port (443)
3561 };
3562
[email protected]e0c27be2009-07-15 13:09:353563 const char kSOCKS5OkResponse[] =
3564 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3565
3566 MockWrite data_writes[] = {
3567 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3568 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3569 arraysize(kSOCKS5OkRequest)),
3570 MockWrite("GET / HTTP/1.1\r\n"
3571 "Host: www.google.com\r\n"
3572 "Connection: keep-alive\r\n\r\n")
3573 };
3574
3575 MockRead data_reads[] = {
3576 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3577 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023578 MockRead("HTTP/1.0 200 OK\r\n"),
3579 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3580 MockRead("Payload"),
3581 MockRead(false, OK)
3582 };
3583
[email protected]31a2bfe2010-02-09 08:03:393584 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3585 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593586 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023587
[email protected]5ecc992a42009-11-11 01:41:593588 SSLSocketDataProvider ssl(true, OK);
3589 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023590
3591 TestCompletionCallback callback;
3592
[email protected]684970b2009-08-14 04:54:463593 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023594 EXPECT_EQ(ERR_IO_PENDING, rv);
3595
3596 rv = callback.WaitForResult();
3597 EXPECT_EQ(OK, rv);
3598
3599 const HttpResponseInfo* response = trans->GetResponseInfo();
3600 EXPECT_FALSE(response == NULL);
3601
3602 std::string response_text;
3603 rv = ReadTransaction(trans.get(), &response_text);
3604 EXPECT_EQ(OK, rv);
3605 EXPECT_EQ("Payload", response_text);
3606}
3607
[email protected]04e5be32009-06-26 20:00:313608// Tests that for connection endpoints the group names are correctly set.
3609TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3610 const struct {
3611 const std::string proxy_server;
3612 const std::string url;
3613 const std::string expected_group_name;
3614 } tests[] = {
3615 {
3616 "", // no proxy (direct)
3617 "http://www.google.com/direct",
3618 "http://www.google.com/",
3619 },
3620 {
3621 "http_proxy",
3622 "http://www.google.com/http_proxy_normal",
3623 "proxy/http_proxy:80/",
3624 },
3625 {
3626 "socks4://socks_proxy:1080",
3627 "http://www.google.com/socks4_direct",
3628 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3629 },
3630
3631 // SSL Tests
3632 {
3633 "",
3634 "https://www.google.com/direct_ssl",
3635 "https://www.google.com/",
3636 },
3637 {
3638 "http_proxy",
3639 "https://www.google.com/http_connect_ssl",
3640 "proxy/http_proxy:80/https://www.google.com/",
3641 },
3642 {
3643 "socks4://socks_proxy:1080",
3644 "https://www.google.com/socks4_ssl",
3645 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3646 },
3647 };
3648
3649 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093650 SessionDependencies session_deps(
3651 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313652
3653 scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3654 new CaptureGroupNameSocketPool());
3655
3656 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a937a06d2009-08-19 21:19:243657 session->tcp_socket_pool_ = conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313658
[email protected]5695b8c2009-09-30 21:36:433659 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313660
3661 HttpRequestInfo request;
3662 request.method = "GET";
3663 request.url = GURL(tests[i].url);
3664 request.load_flags = 0;
3665
3666 TestCompletionCallback callback;
3667
3668 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463669 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]04e5be32009-06-26 20:00:313670 EXPECT_EQ(tests[i].expected_group_name,
3671 conn_pool->last_group_name_received());
3672 }
3673}
3674
[email protected]9172a982009-06-06 00:30:253675TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543676 SessionDependencies session_deps(
3677 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323678
[email protected]69719062010-01-05 20:09:213679 // This simulates failure resolving all hostnames; that means we will fail
3680 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:323681 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3682
[email protected]9172a982009-06-06 00:30:253683 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433684 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253685
3686 HttpRequestInfo request;
3687 request.method = "GET";
3688 request.url = GURL("http://www.google.com/");
3689
3690 TestCompletionCallback callback;
3691
[email protected]684970b2009-08-14 04:54:463692 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253693 EXPECT_EQ(ERR_IO_PENDING, rv);
3694
[email protected]9172a982009-06-06 00:30:253695 rv = callback.WaitForResult();
3696 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3697}
3698
[email protected]f3e6c1e2009-06-15 20:52:123699// Host resolution observer used by
3700// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3701// resovle requests are issued with a referrer of |expected_referrer|.
3702class ResolutionReferrerObserver : public HostResolver::Observer {
3703 public:
3704 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3705 : expected_referrer_(expected_referrer),
3706 called_start_with_referrer_(false),
3707 called_finish_with_referrer_(false) {
3708 }
3709
3710 virtual void OnStartResolution(int id,
3711 const HostResolver::RequestInfo& info) {
3712 if (info.referrer() == expected_referrer_)
3713 called_start_with_referrer_ = true;
3714 }
3715
3716 virtual void OnFinishResolutionWithStatus(
3717 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3718 if (info.referrer() == expected_referrer_)
3719 called_finish_with_referrer_ = true;
3720 }
3721
[email protected]eb255d32009-06-17 02:11:033722 virtual void OnCancelResolution(int id,
3723 const HostResolver::RequestInfo& info ) {
3724 FAIL() << "Should not be cancelling any requests!";
3725 }
3726
[email protected]f3e6c1e2009-06-15 20:52:123727 bool did_complete_with_expected_referrer() const {
3728 return called_start_with_referrer_ && called_finish_with_referrer_;
3729 }
3730
3731 private:
3732 GURL expected_referrer_;
3733 bool called_start_with_referrer_;
3734 bool called_finish_with_referrer_;
3735
3736 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3737};
3738
3739// Make sure that when HostResolver::Resolve() is invoked, it passes through
3740// the "referrer". This is depended on by the DNS prefetch observer.
3741TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3742 GURL referrer = GURL("http://expected-referrer/");
3743 EXPECT_TRUE(referrer.is_valid());
3744 ResolutionReferrerObserver resolution_observer(referrer);
3745
3746 SessionDependencies session_deps;
3747 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433748 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123749
3750 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143751 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123752
3753 // Connect up a mock socket which will fail when reading.
3754 MockRead data_reads[] = {
3755 MockRead(false, ERR_FAILED),
3756 };
[email protected]31a2bfe2010-02-09 08:03:393757 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593758 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123759
3760 // Issue a request, containing an HTTP referrer.
3761 HttpRequestInfo request;
3762 request.method = "GET";
3763 request.referrer = referrer;
3764 request.url = GURL("http://www.google.com/");
3765
3766 // Run the request until it fails reading from the socket.
3767 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463768 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123769 EXPECT_EQ(ERR_IO_PENDING, rv);
3770 rv = callback.WaitForResult();
3771 EXPECT_EQ(ERR_FAILED, rv);
3772
3773 // Check that the host resolution observer saw |referrer|.
3774 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3775}
3776
[email protected]3b9cca42009-06-16 01:08:283777// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3778// host cache is bypassed.
3779TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3780 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323781
[email protected]a2c2fb92009-07-18 07:31:043782 // Select a host resolver that does caching.
3783 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323784
[email protected]3b9cca42009-06-16 01:08:283785 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433786 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283787
3788 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3789 // a synchronous lookup.)
3790 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143791 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463792 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3793 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283794 EXPECT_EQ(OK, rv);
3795
3796 // Verify that it was added to host cache, by doing a subsequent async lookup
3797 // and confirming it completes synchronously.
3798 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463799 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283800 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463801 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323802 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283803
3804 // Inject a failure the next time that "www.google.com" is resolved. This way
3805 // we can tell if the next lookup hit the cache, or the "network".
3806 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323807 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283808
3809 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3810 // first read -- this won't be reached as the host resolution will fail first.
3811 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:393812 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593813 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:283814
3815 // Issue a request, asking to bypass the cache(s).
3816 HttpRequestInfo request;
3817 request.method = "GET";
3818 request.load_flags = LOAD_BYPASS_CACHE;
3819 request.url = GURL("http://www.google.com/");
3820
3821 // Run the request.
3822 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463823 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283824 ASSERT_EQ(ERR_IO_PENDING, rv);
3825 rv = callback.WaitForResult();
3826
3827 // If we bypassed the cache, we would have gotten a failure while resolving
3828 // "www.google.com".
3829 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3830}
3831
[email protected]0877e3d2009-10-17 22:29:573832// Make sure we can handle an error when writing the request.
3833TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3834 SessionDependencies session_deps;
3835 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3836
3837 HttpRequestInfo request;
3838 request.method = "GET";
3839 request.url = GURL("http://www.foo.com/");
3840 request.load_flags = 0;
3841
3842 MockWrite write_failure[] = {
3843 MockWrite(true, ERR_CONNECTION_RESET),
3844 };
[email protected]31a2bfe2010-02-09 08:03:393845 StaticSocketDataProvider data(NULL, 0,
3846 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:593847 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573848
3849 TestCompletionCallback callback;
3850
3851 scoped_ptr<HttpTransaction> trans(
3852 new HttpNetworkTransaction(CreateSession(&session_deps)));
3853
3854 int rv = trans->Start(&request, &callback, NULL);
3855 EXPECT_EQ(ERR_IO_PENDING, rv);
3856
3857 rv = callback.WaitForResult();
3858 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3859}
3860
3861// Check that a connection closed after the start of the headers finishes ok.
3862TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3863 SessionDependencies session_deps;
3864 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3865
3866 HttpRequestInfo request;
3867 request.method = "GET";
3868 request.url = GURL("http://www.foo.com/");
3869 request.load_flags = 0;
3870
3871 MockRead data_reads[] = {
3872 MockRead("HTTP/1."),
3873 MockRead(false, OK),
3874 };
3875
[email protected]31a2bfe2010-02-09 08:03:393876 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593877 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573878
3879 TestCompletionCallback callback;
3880
3881 scoped_ptr<HttpTransaction> trans(
3882 new HttpNetworkTransaction(CreateSession(&session_deps)));
3883
3884 int rv = trans->Start(&request, &callback, NULL);
3885 EXPECT_EQ(ERR_IO_PENDING, rv);
3886
3887 rv = callback.WaitForResult();
3888 EXPECT_EQ(OK, rv);
3889
3890 const HttpResponseInfo* response = trans->GetResponseInfo();
3891 EXPECT_TRUE(response != NULL);
3892
3893 EXPECT_TRUE(response->headers != NULL);
3894 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3895
3896 std::string response_data;
3897 rv = ReadTransaction(trans.get(), &response_data);
3898 EXPECT_EQ(OK, rv);
3899 EXPECT_EQ("", response_data);
3900}
3901
3902// Make sure that a dropped connection while draining the body for auth
3903// restart does the right thing.
3904TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3905 SessionDependencies session_deps;
3906 scoped_ptr<HttpTransaction> trans(
3907 new HttpNetworkTransaction(CreateSession(&session_deps)));
3908
3909 HttpRequestInfo request;
3910 request.method = "GET";
3911 request.url = GURL("http://www.google.com/");
3912 request.load_flags = 0;
3913
3914 MockWrite data_writes1[] = {
3915 MockWrite("GET / HTTP/1.1\r\n"
3916 "Host: www.google.com\r\n"
3917 "Connection: keep-alive\r\n\r\n"),
3918 };
3919
3920 MockRead data_reads1[] = {
3921 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3922 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3923 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3924 MockRead("Content-Length: 14\r\n\r\n"),
3925 MockRead("Unauth"),
3926 MockRead(true, ERR_CONNECTION_RESET),
3927 };
3928
[email protected]31a2bfe2010-02-09 08:03:393929 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3930 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593931 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:573932
3933 // After calling trans->RestartWithAuth(), this is the request we should
3934 // be issuing -- the final header line contains the credentials.
3935 MockWrite data_writes2[] = {
3936 MockWrite("GET / HTTP/1.1\r\n"
3937 "Host: www.google.com\r\n"
3938 "Connection: keep-alive\r\n"
3939 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3940 };
3941
3942 // Lastly, the server responds with the actual content.
3943 MockRead data_reads2[] = {
3944 MockRead("HTTP/1.1 200 OK\r\n"),
3945 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3946 MockRead("Content-Length: 100\r\n\r\n"),
3947 MockRead(false, OK),
3948 };
3949
[email protected]31a2bfe2010-02-09 08:03:393950 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3951 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593952 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:573953
3954 TestCompletionCallback callback1;
3955
3956 int rv = trans->Start(&request, &callback1, NULL);
3957 EXPECT_EQ(ERR_IO_PENDING, rv);
3958
3959 rv = callback1.WaitForResult();
3960 EXPECT_EQ(OK, rv);
3961
3962 const HttpResponseInfo* response = trans->GetResponseInfo();
3963 EXPECT_FALSE(response == NULL);
3964
3965 // The password prompt info should have been set in response->auth_challenge.
3966 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3967
3968 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3969 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3970 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3971
3972 TestCompletionCallback callback2;
3973
3974 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3975 EXPECT_EQ(ERR_IO_PENDING, rv);
3976
3977 rv = callback2.WaitForResult();
3978 EXPECT_EQ(OK, rv);
3979
3980 response = trans->GetResponseInfo();
3981 EXPECT_FALSE(response == NULL);
3982 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3983 EXPECT_EQ(100, response->headers->GetContentLength());
3984}
3985
3986// Test HTTPS connections going through a proxy that sends extra data.
3987TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
3988 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
3989
3990 HttpRequestInfo request;
3991 request.method = "GET";
3992 request.url = GURL("https://www.google.com/");
3993 request.load_flags = 0;
3994
3995 MockRead proxy_reads[] = {
3996 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
3997 MockRead(false, OK)
3998 };
3999
[email protected]31a2bfe2010-02-09 08:03:394000 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594001 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574002
[email protected]5ecc992a42009-11-11 01:41:594003 session_deps.socket_factory.AddSocketDataProvider(&data);
4004 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574005
4006 TestCompletionCallback callback;
4007
4008 session_deps.socket_factory.ResetNextMockIndexes();
4009
4010 scoped_ptr<HttpTransaction> trans(
4011 new HttpNetworkTransaction(CreateSession(&session_deps)));
4012
4013 int rv = trans->Start(&request, &callback, NULL);
4014 EXPECT_EQ(ERR_IO_PENDING, rv);
4015
4016 rv = callback.WaitForResult();
4017 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4018}
4019
[email protected]e22e1362009-11-23 21:31:124020TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
4021 MockRead data_reads[] = {
4022 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4023 MockRead(false, OK),
4024 };
[email protected]31a2bfe2010-02-09 08:03:394025 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
4026 arraysize(data_reads));
[email protected]e22e1362009-11-23 21:31:124027 EXPECT_EQ(OK, out.rv);
4028 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
4029 EXPECT_EQ("", out.response_data);
4030}
4031
[email protected]95d88ffe2010-02-04 21:25:334032TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4033 SessionDependencies session_deps;
4034 scoped_ptr<HttpTransaction> trans(
4035 new HttpNetworkTransaction(CreateSession(&session_deps)));
4036
4037 HttpRequestInfo request;
4038 request.method = "POST";
4039 request.url = GURL("http://www.google.com/upload");
4040 request.upload_data = new UploadData;
4041 request.load_flags = 0;
4042
4043 FilePath temp_file_path;
4044 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4045 const uint64 kFakeSize = 100000; // file is actually blank
4046
4047 std::vector<UploadData::Element> elements;
4048 UploadData::Element element;
4049 element.SetToFilePath(temp_file_path);
4050 element.SetContentLength(kFakeSize);
4051 elements.push_back(element);
4052 request.upload_data->set_elements(elements);
4053 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4054
4055 MockRead data_reads[] = {
4056 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4057 MockRead("hello world"),
4058 MockRead(false, OK),
4059 };
[email protected]31a2bfe2010-02-09 08:03:394060 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334061 session_deps.socket_factory.AddSocketDataProvider(&data);
4062
4063 TestCompletionCallback callback;
4064
4065 int rv = trans->Start(&request, &callback, NULL);
4066 EXPECT_EQ(ERR_IO_PENDING, rv);
4067
4068 rv = callback.WaitForResult();
4069 EXPECT_EQ(OK, rv);
4070
4071 const HttpResponseInfo* response = trans->GetResponseInfo();
4072 EXPECT_TRUE(response != NULL);
4073
4074 EXPECT_TRUE(response->headers != NULL);
4075 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4076
4077 std::string response_data;
4078 rv = ReadTransaction(trans.get(), &response_data);
4079 EXPECT_EQ(OK, rv);
4080 EXPECT_EQ("hello world", response_data);
4081
4082 file_util::Delete(temp_file_path, false);
4083}
4084
[email protected]89ceba9a2009-03-21 03:46:064085} // namespace net