- add sources.
[platform/framework/web/crosswalk.git] / src / net / url_request / url_request_ftp_job_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/url_request/url_request_ftp_job.h"
6
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/run_loop.h"
10 #include "net/base/request_priority.h"
11 #include "net/ftp/ftp_auth_cache.h"
12 #include "net/http/http_transaction_unittest.h"
13 #include "net/proxy/mock_proxy_resolver.h"
14 #include "net/proxy/proxy_config_service.h"
15 #include "net/proxy/proxy_config_service_fixed.h"
16 #include "net/socket/socket_test_util.h"
17 #include "net/url_request/ftp_protocol_handler.h"
18 #include "net/url_request/url_request.h"
19 #include "net/url_request/url_request_context.h"
20 #include "net/url_request/url_request_job_factory_impl.h"
21 #include "net/url_request/url_request_status.h"
22 #include "net/url_request/url_request_test_util.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "url/gurl.h"
25
26 namespace net {
27
28 class FtpTestURLRequestContext : public TestURLRequestContext {
29  public:
30   FtpTestURLRequestContext(ClientSocketFactory* socket_factory,
31                            ProxyService* proxy_service,
32                            NetworkDelegate* network_delegate,
33                            FtpTransactionFactory* ftp_transaction_factory)
34       : TestURLRequestContext(true),
35         ftp_protocol_handler_(new FtpProtocolHandler(ftp_transaction_factory)) {
36     set_client_socket_factory(socket_factory);
37     context_storage_.set_proxy_service(proxy_service);
38     set_network_delegate(network_delegate);
39     URLRequestJobFactoryImpl* job_factory = new URLRequestJobFactoryImpl;
40     job_factory->SetProtocolHandler("ftp", ftp_protocol_handler_);
41     context_storage_.set_job_factory(job_factory);
42     Init();
43   }
44
45   FtpAuthCache* GetFtpAuthCache() {
46     return ftp_protocol_handler_->ftp_auth_cache_.get();
47   }
48
49   void set_proxy_service(ProxyService* proxy_service) {
50     context_storage_.set_proxy_service(proxy_service);
51   }
52
53  private:
54   FtpProtocolHandler* ftp_protocol_handler_;
55 };
56
57 namespace {
58
59 class SimpleProxyConfigService : public ProxyConfigService {
60  public:
61   SimpleProxyConfigService() {
62     // Any FTP requests that ever go through HTTP paths are proxied requests.
63     config_.proxy_rules().ParseFromString("ftp=localhost");
64   }
65
66   virtual void AddObserver(Observer* observer) OVERRIDE {
67     observer_ = observer;
68   }
69
70   virtual void RemoveObserver(Observer* observer) OVERRIDE {
71     if (observer_ == observer) {
72       observer_ = NULL;
73     }
74   }
75
76   virtual ConfigAvailability GetLatestProxyConfig(
77       ProxyConfig* config) OVERRIDE {
78     *config = config_;
79     return CONFIG_VALID;
80   }
81
82   void IncrementConfigId() {
83     config_.set_id(config_.id() + 1);
84     observer_->OnProxyConfigChanged(config_, ProxyConfigService::CONFIG_VALID);
85   }
86
87  private:
88   ProxyConfig config_;
89   Observer* observer_;
90 };
91
92 // Inherit from URLRequestFtpJob to expose the priority and some
93 // other hidden functions.
94 class TestURLRequestFtpJob : public URLRequestFtpJob {
95  public:
96   TestURLRequestFtpJob(URLRequest* request,
97                        FtpTransactionFactory* ftp_factory,
98                        FtpAuthCache* ftp_auth_cache)
99       : URLRequestFtpJob(request, NULL, ftp_factory, ftp_auth_cache) {}
100
101   using URLRequestFtpJob::SetPriority;
102   using URLRequestFtpJob::Start;
103   using URLRequestFtpJob::Kill;
104   using URLRequestFtpJob::priority;
105
106  protected:
107   virtual ~TestURLRequestFtpJob() {}
108 };
109
110 class MockFtpTransactionFactory : public FtpTransactionFactory {
111  public:
112   virtual FtpTransaction* CreateTransaction() OVERRIDE {
113     return NULL;
114   }
115
116   virtual void Suspend(bool suspend) OVERRIDE {}
117 };
118
119 // Fixture for priority-related tests. Priority matters when there is
120 // an HTTP proxy.
121 class URLRequestFtpJobPriorityTest : public testing::Test {
122  protected:
123   URLRequestFtpJobPriorityTest()
124       : proxy_service_(new SimpleProxyConfigService, NULL, NULL),
125         req_(GURL("ftp://ftp.example.com"),
126              DEFAULT_PRIORITY,
127              &delegate_,
128              &context_) {
129     context_.set_proxy_service(&proxy_service_);
130     context_.set_http_transaction_factory(&network_layer_);
131   }
132
133   ProxyService proxy_service_;
134   MockNetworkLayer network_layer_;
135   MockFtpTransactionFactory ftp_factory_;
136   FtpAuthCache ftp_auth_cache_;
137   TestURLRequestContext context_;
138   TestDelegate delegate_;
139   TestURLRequest req_;
140 };
141
142 // Make sure that SetPriority actually sets the URLRequestFtpJob's
143 // priority, both before and after start.
144 TEST_F(URLRequestFtpJobPriorityTest, SetPriorityBasic) {
145   scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
146       &req_, &ftp_factory_, &ftp_auth_cache_));
147   EXPECT_EQ(DEFAULT_PRIORITY, job->priority());
148
149   job->SetPriority(LOWEST);
150   EXPECT_EQ(LOWEST, job->priority());
151
152   job->SetPriority(LOW);
153   EXPECT_EQ(LOW, job->priority());
154
155   job->Start();
156   EXPECT_EQ(LOW, job->priority());
157
158   job->SetPriority(MEDIUM);
159   EXPECT_EQ(MEDIUM, job->priority());
160 }
161
162 // Make sure that URLRequestFtpJob passes on its priority to its
163 // transaction on start.
164 TEST_F(URLRequestFtpJobPriorityTest, SetTransactionPriorityOnStart) {
165   scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
166       &req_, &ftp_factory_, &ftp_auth_cache_));
167   job->SetPriority(LOW);
168
169   EXPECT_FALSE(network_layer_.last_transaction());
170
171   job->Start();
172
173   ASSERT_TRUE(network_layer_.last_transaction());
174   EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
175 }
176
177 // Make sure that URLRequestFtpJob passes on its priority updates to
178 // its transaction.
179 TEST_F(URLRequestFtpJobPriorityTest, SetTransactionPriority) {
180   scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
181       &req_, &ftp_factory_, &ftp_auth_cache_));
182   job->SetPriority(LOW);
183   job->Start();
184   ASSERT_TRUE(network_layer_.last_transaction());
185   EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
186
187   job->SetPriority(HIGHEST);
188   EXPECT_EQ(HIGHEST, network_layer_.last_transaction()->priority());
189 }
190
191 // Make sure that URLRequestFtpJob passes on its priority updates to
192 // newly-created transactions after the first one.
193 TEST_F(URLRequestFtpJobPriorityTest, SetSubsequentTransactionPriority) {
194   scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
195       &req_, &ftp_factory_, &ftp_auth_cache_));
196   job->Start();
197
198   job->SetPriority(LOW);
199   ASSERT_TRUE(network_layer_.last_transaction());
200   EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
201
202   job->Kill();
203   network_layer_.ClearLastTransaction();
204
205   // Creates a second transaction.
206   job->Start();
207   ASSERT_TRUE(network_layer_.last_transaction());
208   EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
209 }
210
211 class URLRequestFtpJobTest : public testing::Test {
212  public:
213   URLRequestFtpJobTest()
214       : request_context_(&socket_factory_,
215                          new ProxyService(
216                              new SimpleProxyConfigService, NULL, NULL),
217                          &network_delegate_,
218                          &ftp_transaction_factory_) {
219   }
220
221   virtual ~URLRequestFtpJobTest() {
222     // Clean up any remaining tasks that mess up unrelated tests.
223     base::RunLoop run_loop;
224     run_loop.RunUntilIdle();
225   }
226
227   void AddSocket(MockRead* reads, size_t reads_size,
228                  MockWrite* writes, size_t writes_size) {
229     DeterministicSocketData* socket_data = new DeterministicSocketData(
230         reads, reads_size, writes, writes_size);
231     socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
232     socket_data->StopAfter(reads_size + writes_size - 1);
233     socket_factory_.AddSocketDataProvider(socket_data);
234
235     socket_data_.push_back(socket_data);
236   }
237
238   FtpTestURLRequestContext* request_context() { return &request_context_; }
239   TestNetworkDelegate* network_delegate() { return &network_delegate_; }
240   DeterministicSocketData* socket_data(size_t index) {
241     return socket_data_[index];
242   }
243
244  private:
245   ScopedVector<DeterministicSocketData> socket_data_;
246   DeterministicMockClientSocketFactory socket_factory_;
247   TestNetworkDelegate network_delegate_;
248   MockFtpTransactionFactory ftp_transaction_factory_;
249
250   FtpTestURLRequestContext request_context_;
251 };
252
253 TEST_F(URLRequestFtpJobTest, FtpProxyRequest) {
254   MockWrite writes[] = {
255     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
256               "Host: ftp.example.com\r\n"
257               "Proxy-Connection: keep-alive\r\n\r\n"),
258   };
259   MockRead reads[] = {
260     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
261     MockRead(ASYNC, 2, "Content-Length: 9\r\n\r\n"),
262     MockRead(ASYNC, 3, "test.html"),
263   };
264
265   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
266
267   TestDelegate request_delegate;
268   URLRequest url_request(GURL("ftp://ftp.example.com/"),
269                          DEFAULT_PRIORITY,
270                          &request_delegate,
271                          request_context());
272   url_request.Start();
273   ASSERT_TRUE(url_request.is_pending());
274   socket_data(0)->RunFor(4);
275
276   EXPECT_TRUE(url_request.status().is_success());
277   EXPECT_EQ(1, network_delegate()->completed_requests());
278   EXPECT_EQ(0, network_delegate()->error_count());
279   EXPECT_FALSE(request_delegate.auth_required_called());
280   EXPECT_EQ("test.html", request_delegate.data_received());
281 }
282
283 // Regression test for http://crbug.com/237526 .
284 TEST_F(URLRequestFtpJobTest, FtpProxyRequestOrphanJob) {
285   // Use a PAC URL so that URLRequestFtpJob's |pac_request_| field is non-NULL.
286   request_context()->set_proxy_service(
287       new ProxyService(
288           new ProxyConfigServiceFixed(
289               ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
290           new MockAsyncProxyResolver, NULL));
291
292   TestDelegate request_delegate;
293   URLRequest url_request(GURL("ftp://ftp.example.com/"),
294                          DEFAULT_PRIORITY,
295                          &request_delegate,
296                          request_context());
297   url_request.Start();
298
299   // Now |url_request| will be deleted before its completion,
300   // resulting in it being orphaned. It should not crash.
301 }
302
303 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAuthNoCredentials) {
304   MockWrite writes[] = {
305     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
306               "Host: ftp.example.com\r\n"
307               "Proxy-Connection: keep-alive\r\n\r\n"),
308   };
309   MockRead reads[] = {
310     // No credentials.
311     MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
312     MockRead(ASYNC, 2, "Proxy-Authenticate: Basic "
313              "realm=\"MyRealm1\"\r\n"),
314     MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
315     MockRead(ASYNC, 4, "test.html"),
316   };
317
318   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
319
320   TestDelegate request_delegate;
321   URLRequest url_request(GURL("ftp://ftp.example.com/"),
322                          DEFAULT_PRIORITY,
323                          &request_delegate,
324                          request_context());
325   url_request.Start();
326   ASSERT_TRUE(url_request.is_pending());
327   socket_data(0)->RunFor(5);
328
329   EXPECT_TRUE(url_request.status().is_success());
330   EXPECT_EQ(1, network_delegate()->completed_requests());
331   EXPECT_EQ(0, network_delegate()->error_count());
332   EXPECT_TRUE(request_delegate.auth_required_called());
333   EXPECT_EQ("test.html", request_delegate.data_received());
334 }
335
336 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAuthWithCredentials) {
337   MockWrite writes[] = {
338     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
339               "Host: ftp.example.com\r\n"
340               "Proxy-Connection: keep-alive\r\n\r\n"),
341     MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
342               "Host: ftp.example.com\r\n"
343               "Proxy-Connection: keep-alive\r\n"
344               "Proxy-Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
345   };
346   MockRead reads[] = {
347     // No credentials.
348     MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
349     MockRead(ASYNC, 2, "Proxy-Authenticate: Basic "
350              "realm=\"MyRealm1\"\r\n"),
351     MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
352     MockRead(ASYNC, 4, "test.html"),
353
354     // Second response.
355     MockRead(ASYNC, 6, "HTTP/1.1 200 OK\r\n"),
356     MockRead(ASYNC, 7, "Content-Length: 10\r\n\r\n"),
357     MockRead(ASYNC, 8, "test2.html"),
358   };
359
360   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
361
362   TestDelegate request_delegate;
363   request_delegate.set_credentials(
364       AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
365   URLRequest url_request(GURL("ftp://ftp.example.com/"),
366                          DEFAULT_PRIORITY,
367                          &request_delegate,
368                          request_context());
369   url_request.Start();
370   ASSERT_TRUE(url_request.is_pending());
371   socket_data(0)->RunFor(9);
372
373   EXPECT_TRUE(url_request.status().is_success());
374   EXPECT_EQ(1, network_delegate()->completed_requests());
375   EXPECT_EQ(0, network_delegate()->error_count());
376   EXPECT_TRUE(request_delegate.auth_required_called());
377   EXPECT_EQ("test2.html", request_delegate.data_received());
378 }
379
380 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedServerAuthNoCredentials) {
381   MockWrite writes[] = {
382     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
383               "Host: ftp.example.com\r\n"
384               "Proxy-Connection: keep-alive\r\n\r\n"),
385   };
386   MockRead reads[] = {
387     // No credentials.
388     MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
389     MockRead(ASYNC, 2, "WWW-Authenticate: Basic "
390              "realm=\"MyRealm1\"\r\n"),
391     MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
392     MockRead(ASYNC, 4, "test.html"),
393   };
394
395   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
396
397   TestDelegate request_delegate;
398   URLRequest url_request(GURL("ftp://ftp.example.com/"),
399                          DEFAULT_PRIORITY,
400                          &request_delegate,
401                          request_context());
402   url_request.Start();
403   ASSERT_TRUE(url_request.is_pending());
404   socket_data(0)->RunFor(5);
405
406   EXPECT_TRUE(url_request.status().is_success());
407   EXPECT_EQ(1, network_delegate()->completed_requests());
408   EXPECT_EQ(0, network_delegate()->error_count());
409   EXPECT_TRUE(request_delegate.auth_required_called());
410   EXPECT_EQ("test.html", request_delegate.data_received());
411 }
412
413 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedServerAuthWithCredentials) {
414   MockWrite writes[] = {
415     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
416               "Host: ftp.example.com\r\n"
417               "Proxy-Connection: keep-alive\r\n\r\n"),
418     MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
419               "Host: ftp.example.com\r\n"
420               "Proxy-Connection: keep-alive\r\n"
421               "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
422   };
423   MockRead reads[] = {
424     // No credentials.
425     MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
426     MockRead(ASYNC, 2, "WWW-Authenticate: Basic "
427              "realm=\"MyRealm1\"\r\n"),
428     MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
429     MockRead(ASYNC, 4, "test.html"),
430
431     // Second response.
432     MockRead(ASYNC, 6, "HTTP/1.1 200 OK\r\n"),
433     MockRead(ASYNC, 7, "Content-Length: 10\r\n\r\n"),
434     MockRead(ASYNC, 8, "test2.html"),
435   };
436
437   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
438
439   TestDelegate request_delegate;
440   request_delegate.set_credentials(
441       AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
442   URLRequest url_request(GURL("ftp://ftp.example.com/"),
443                          DEFAULT_PRIORITY,
444                          &request_delegate,
445                          request_context());
446   url_request.Start();
447   ASSERT_TRUE(url_request.is_pending());
448   socket_data(0)->RunFor(9);
449
450   EXPECT_TRUE(url_request.status().is_success());
451   EXPECT_EQ(1, network_delegate()->completed_requests());
452   EXPECT_EQ(0, network_delegate()->error_count());
453   EXPECT_TRUE(request_delegate.auth_required_called());
454   EXPECT_EQ("test2.html", request_delegate.data_received());
455 }
456
457 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAndServerAuth) {
458   MockWrite writes[] = {
459     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
460               "Host: ftp.example.com\r\n"
461               "Proxy-Connection: keep-alive\r\n\r\n"),
462     MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
463               "Host: ftp.example.com\r\n"
464               "Proxy-Connection: keep-alive\r\n"
465               "Proxy-Authorization: Basic "
466               "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n"),
467     MockWrite(ASYNC, 10, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
468               "Host: ftp.example.com\r\n"
469               "Proxy-Connection: keep-alive\r\n"
470               "Proxy-Authorization: Basic "
471               "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n"
472               "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
473   };
474   MockRead reads[] = {
475     // No credentials.
476     MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
477     MockRead(ASYNC, 2, "Proxy-Authenticate: Basic "
478              "realm=\"MyRealm1\"\r\n"),
479     MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
480     MockRead(ASYNC, 4, "test.html"),
481
482     // Second response.
483     MockRead(ASYNC, 6, "HTTP/1.1 401 Unauthorized\r\n"),
484     MockRead(ASYNC, 7, "WWW-Authenticate: Basic "
485              "realm=\"MyRealm1\"\r\n"),
486     MockRead(ASYNC, 8, "Content-Length: 9\r\n\r\n"),
487     MockRead(ASYNC, 9, "test.html"),
488
489     // Third response.
490     MockRead(ASYNC, 11, "HTTP/1.1 200 OK\r\n"),
491     MockRead(ASYNC, 12, "Content-Length: 10\r\n\r\n"),
492     MockRead(ASYNC, 13, "test2.html"),
493   };
494
495   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
496
497   GURL url("ftp://ftp.example.com");
498
499   // Make sure cached FTP credentials are not used for proxy authentication.
500   request_context()->GetFtpAuthCache()->Add(
501       url.GetOrigin(),
502       AuthCredentials(ASCIIToUTF16("userdonotuse"),
503                       ASCIIToUTF16("passworddonotuse")));
504
505   TestDelegate request_delegate;
506   request_delegate.set_credentials(
507       AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")));
508   URLRequest url_request(
509       url, DEFAULT_PRIORITY, &request_delegate, request_context());
510   url_request.Start();
511   ASSERT_TRUE(url_request.is_pending());
512   socket_data(0)->RunFor(5);
513
514   request_delegate.set_credentials(
515       AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
516   socket_data(0)->RunFor(9);
517
518   EXPECT_TRUE(url_request.status().is_success());
519   EXPECT_EQ(1, network_delegate()->completed_requests());
520   EXPECT_EQ(0, network_delegate()->error_count());
521   EXPECT_TRUE(request_delegate.auth_required_called());
522   EXPECT_EQ("test2.html", request_delegate.data_received());
523 }
524
525 TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotSaveCookies) {
526   MockWrite writes[] = {
527     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
528               "Host: ftp.example.com\r\n"
529               "Proxy-Connection: keep-alive\r\n\r\n"),
530   };
531   MockRead reads[] = {
532     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
533     MockRead(ASYNC, 2, "Content-Length: 9\r\n"),
534     MockRead(ASYNC, 3, "Set-Cookie: name=value\r\n\r\n"),
535     MockRead(ASYNC, 4, "test.html"),
536   };
537
538   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
539
540   TestDelegate request_delegate;
541   URLRequest url_request(GURL("ftp://ftp.example.com/"),
542                          DEFAULT_PRIORITY,
543                          &request_delegate,
544                          request_context());
545   url_request.Start();
546   ASSERT_TRUE(url_request.is_pending());
547
548   socket_data(0)->RunFor(5);
549
550   EXPECT_TRUE(url_request.status().is_success());
551   EXPECT_EQ(1, network_delegate()->completed_requests());
552   EXPECT_EQ(0, network_delegate()->error_count());
553
554   // Make sure we do not accept cookies.
555   EXPECT_EQ(0, network_delegate()->set_cookie_count());
556
557   EXPECT_FALSE(request_delegate.auth_required_called());
558   EXPECT_EQ("test.html", request_delegate.data_received());
559 }
560
561 TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotFollowRedirects) {
562   MockWrite writes[] = {
563     MockWrite(SYNCHRONOUS, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
564               "Host: ftp.example.com\r\n"
565               "Proxy-Connection: keep-alive\r\n\r\n"),
566   };
567   MockRead reads[] = {
568     MockRead(SYNCHRONOUS, 1, "HTTP/1.1 302 Found\r\n"),
569     MockRead(ASYNC, 2, "Location: http://other.example.com/\r\n\r\n"),
570   };
571
572   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
573
574   TestDelegate request_delegate;
575   URLRequest url_request(GURL("ftp://ftp.example.com/"),
576                          DEFAULT_PRIORITY,
577                          &request_delegate,
578                          request_context());
579   url_request.Start();
580   EXPECT_TRUE(url_request.is_pending());
581
582   base::MessageLoop::current()->RunUntilIdle();
583
584   EXPECT_TRUE(url_request.is_pending());
585   EXPECT_EQ(0, request_delegate.response_started_count());
586   EXPECT_EQ(0, network_delegate()->error_count());
587   ASSERT_TRUE(url_request.status().is_success());
588
589   socket_data(0)->RunFor(1);
590
591   EXPECT_EQ(1, network_delegate()->completed_requests());
592   EXPECT_EQ(1, network_delegate()->error_count());
593   EXPECT_FALSE(url_request.status().is_success());
594   EXPECT_EQ(ERR_UNSAFE_REDIRECT, url_request.status().error());
595 }
596
597 // We should re-use socket for requests using the same scheme, host, and port.
598 TEST_F(URLRequestFtpJobTest, FtpProxyRequestReuseSocket) {
599   MockWrite writes[] = {
600     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
601               "Host: ftp.example.com\r\n"
602               "Proxy-Connection: keep-alive\r\n\r\n"),
603     MockWrite(ASYNC, 4, "GET ftp://ftp.example.com/second HTTP/1.1\r\n"
604               "Host: ftp.example.com\r\n"
605               "Proxy-Connection: keep-alive\r\n\r\n"),
606   };
607   MockRead reads[] = {
608     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
609     MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"),
610     MockRead(ASYNC, 3, "test1.html"),
611     MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"),
612     MockRead(ASYNC, 6, "Content-Length: 10\r\n\r\n"),
613     MockRead(ASYNC, 7, "test2.html"),
614   };
615
616   AddSocket(reads, arraysize(reads), writes, arraysize(writes));
617
618   TestDelegate request_delegate1;
619   URLRequest url_request1(GURL("ftp://ftp.example.com/first"),
620                           DEFAULT_PRIORITY,
621                           &request_delegate1,
622                           request_context());
623   url_request1.Start();
624   ASSERT_TRUE(url_request1.is_pending());
625   socket_data(0)->RunFor(4);
626
627   EXPECT_TRUE(url_request1.status().is_success());
628   EXPECT_EQ(1, network_delegate()->completed_requests());
629   EXPECT_EQ(0, network_delegate()->error_count());
630   EXPECT_FALSE(request_delegate1.auth_required_called());
631   EXPECT_EQ("test1.html", request_delegate1.data_received());
632
633   TestDelegate request_delegate2;
634   URLRequest url_request2(GURL("ftp://ftp.example.com/second"),
635                           DEFAULT_PRIORITY,
636                           &request_delegate2,
637                           request_context());
638   url_request2.Start();
639   ASSERT_TRUE(url_request2.is_pending());
640   socket_data(0)->RunFor(4);
641
642   EXPECT_TRUE(url_request2.status().is_success());
643   EXPECT_EQ(2, network_delegate()->completed_requests());
644   EXPECT_EQ(0, network_delegate()->error_count());
645   EXPECT_FALSE(request_delegate2.auth_required_called());
646   EXPECT_EQ("test2.html", request_delegate2.data_received());
647 }
648
649 // We should not re-use socket when there are two requests to the same host,
650 // but one is FTP and the other is HTTP.
651 TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotReuseSocket) {
652   MockWrite writes1[] = {
653     MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
654               "Host: ftp.example.com\r\n"
655               "Proxy-Connection: keep-alive\r\n\r\n"),
656   };
657   MockWrite writes2[] = {
658     MockWrite(ASYNC, 0, "GET /second HTTP/1.1\r\n"
659               "Host: ftp.example.com\r\n"
660               "Connection: keep-alive\r\n"
661               "User-Agent:\r\n"
662               "Accept-Encoding: gzip,deflate\r\n"
663               "Accept-Language: en-us,fr\r\n\r\n"),
664   };
665   MockRead reads1[] = {
666     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
667     MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"),
668     MockRead(ASYNC, 3, "test1.html"),
669   };
670   MockRead reads2[] = {
671     MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
672     MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"),
673     MockRead(ASYNC, 3, "test2.html"),
674   };
675
676   AddSocket(reads1, arraysize(reads1), writes1, arraysize(writes1));
677   AddSocket(reads2, arraysize(reads2), writes2, arraysize(writes2));
678
679   TestDelegate request_delegate1;
680   URLRequest url_request1(GURL("ftp://ftp.example.com/first"),
681                           DEFAULT_PRIORITY,
682                           &request_delegate1,
683                           request_context());
684   url_request1.Start();
685   ASSERT_TRUE(url_request1.is_pending());
686   socket_data(0)->RunFor(4);
687
688   EXPECT_TRUE(url_request1.status().is_success());
689   EXPECT_EQ(1, network_delegate()->completed_requests());
690   EXPECT_EQ(0, network_delegate()->error_count());
691   EXPECT_FALSE(request_delegate1.auth_required_called());
692   EXPECT_EQ("test1.html", request_delegate1.data_received());
693
694   TestDelegate request_delegate2;
695   URLRequest url_request2(GURL("http://ftp.example.com/second"),
696                           DEFAULT_PRIORITY,
697                           &request_delegate2,
698                           request_context());
699   url_request2.Start();
700   ASSERT_TRUE(url_request2.is_pending());
701   socket_data(1)->RunFor(4);
702
703   EXPECT_TRUE(url_request2.status().is_success());
704   EXPECT_EQ(2, network_delegate()->completed_requests());
705   EXPECT_EQ(0, network_delegate()->error_count());
706   EXPECT_FALSE(request_delegate2.auth_required_called());
707   EXPECT_EQ("test2.html", request_delegate2.data_received());
708 }
709
710 }  // namespace
711
712 }  // namespace net