Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / url_request / url_request_ftp_job_unittest.cc
blob3e388c50fd38c9b21cf3c075ae429f5288ae8b6e
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.
5 #include "net/url_request/url_request_ftp_job.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/scoped_vector.h"
10 #include "base/run_loop.h"
11 #include "net/base/host_port_pair.h"
12 #include "net/base/request_priority.h"
13 #include "net/ftp/ftp_auth_cache.h"
14 #include "net/http/http_transaction_test_util.h"
15 #include "net/proxy/mock_proxy_resolver.h"
16 #include "net/proxy/proxy_config_service.h"
17 #include "net/proxy/proxy_config_service_fixed.h"
18 #include "net/socket/socket_test_util.h"
19 #include "net/url_request/ftp_protocol_handler.h"
20 #include "net/url_request/url_request.h"
21 #include "net/url_request/url_request_context.h"
22 #include "net/url_request/url_request_job_factory_impl.h"
23 #include "net/url_request/url_request_status.h"
24 #include "net/url_request/url_request_test_util.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "url/gurl.h"
28 using base::ASCIIToUTF16;
30 namespace net {
31 namespace {
33 class MockProxyResolverFactory : public ProxyResolverFactory {
34 public:
35 MockProxyResolverFactory() : ProxyResolverFactory(false) {}
36 int CreateProxyResolver(
37 const scoped_refptr<ProxyResolverScriptData>& pac_script,
38 scoped_ptr<ProxyResolver>* resolver,
39 const CompletionCallback& callback,
40 scoped_ptr<Request>* request) override {
41 resolver->reset(new MockAsyncProxyResolver());
42 return OK;
46 } // namespace
48 class FtpTestURLRequestContext : public TestURLRequestContext {
49 public:
50 FtpTestURLRequestContext(ClientSocketFactory* socket_factory,
51 scoped_ptr<ProxyService> proxy_service,
52 NetworkDelegate* network_delegate,
53 FtpTransactionFactory* ftp_transaction_factory)
54 : TestURLRequestContext(true),
55 ftp_protocol_handler_(new FtpProtocolHandler(ftp_transaction_factory)) {
56 set_client_socket_factory(socket_factory);
57 context_storage_.set_proxy_service(proxy_service.Pass());
58 set_network_delegate(network_delegate);
59 scoped_ptr<URLRequestJobFactoryImpl> job_factory =
60 make_scoped_ptr(new URLRequestJobFactoryImpl);
61 job_factory->SetProtocolHandler("ftp",
62 make_scoped_ptr(ftp_protocol_handler_));
63 context_storage_.set_job_factory(job_factory.Pass());
64 Init();
67 FtpAuthCache* GetFtpAuthCache() {
68 return ftp_protocol_handler_->ftp_auth_cache_.get();
71 void set_proxy_service(scoped_ptr<ProxyService> proxy_service) {
72 context_storage_.set_proxy_service(proxy_service.Pass());
75 private:
76 FtpProtocolHandler* ftp_protocol_handler_;
79 namespace {
81 class SimpleProxyConfigService : public ProxyConfigService {
82 public:
83 SimpleProxyConfigService() {
84 // Any FTP requests that ever go through HTTP paths are proxied requests.
85 config_.proxy_rules().ParseFromString("ftp=localhost");
88 void AddObserver(Observer* observer) override { observer_ = observer; }
90 void RemoveObserver(Observer* observer) override {
91 if (observer_ == observer) {
92 observer_ = NULL;
96 ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) override {
97 *config = config_;
98 return CONFIG_VALID;
101 void IncrementConfigId() {
102 config_.set_id(config_.id() + 1);
103 observer_->OnProxyConfigChanged(config_, ProxyConfigService::CONFIG_VALID);
106 private:
107 ProxyConfig config_;
108 Observer* observer_;
111 // Inherit from URLRequestFtpJob to expose the priority and some
112 // other hidden functions.
113 class TestURLRequestFtpJob : public URLRequestFtpJob {
114 public:
115 TestURLRequestFtpJob(URLRequest* request,
116 FtpTransactionFactory* ftp_factory,
117 FtpAuthCache* ftp_auth_cache)
118 : URLRequestFtpJob(request, NULL, ftp_factory, ftp_auth_cache) {}
120 using URLRequestFtpJob::SetPriority;
121 using URLRequestFtpJob::Start;
122 using URLRequestFtpJob::Kill;
123 using URLRequestFtpJob::priority;
125 protected:
126 ~TestURLRequestFtpJob() override {}
129 class MockFtpTransactionFactory : public FtpTransactionFactory {
130 public:
131 FtpTransaction* CreateTransaction() override { return NULL; }
133 void Suspend(bool suspend) override {}
136 // Fixture for priority-related tests. Priority matters when there is
137 // an HTTP proxy.
138 class URLRequestFtpJobPriorityTest : public testing::Test {
139 protected:
140 URLRequestFtpJobPriorityTest()
141 : proxy_service_(new SimpleProxyConfigService, NULL, NULL),
142 req_(context_.CreateRequest(GURL("ftp://ftp.example.com"),
143 DEFAULT_PRIORITY,
144 &delegate_)) {
145 context_.set_proxy_service(&proxy_service_);
146 context_.set_http_transaction_factory(&network_layer_);
149 ProxyService proxy_service_;
150 MockNetworkLayer network_layer_;
151 MockFtpTransactionFactory ftp_factory_;
152 FtpAuthCache ftp_auth_cache_;
153 TestURLRequestContext context_;
154 TestDelegate delegate_;
155 scoped_ptr<URLRequest> req_;
158 // Make sure that SetPriority actually sets the URLRequestFtpJob's
159 // priority, both before and after start.
160 TEST_F(URLRequestFtpJobPriorityTest, SetPriorityBasic) {
161 scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
162 req_.get(), &ftp_factory_, &ftp_auth_cache_));
163 EXPECT_EQ(DEFAULT_PRIORITY, job->priority());
165 job->SetPriority(LOWEST);
166 EXPECT_EQ(LOWEST, job->priority());
168 job->SetPriority(LOW);
169 EXPECT_EQ(LOW, job->priority());
171 job->Start();
172 EXPECT_EQ(LOW, job->priority());
174 job->SetPriority(MEDIUM);
175 EXPECT_EQ(MEDIUM, job->priority());
178 // Make sure that URLRequestFtpJob passes on its priority to its
179 // transaction on start.
180 TEST_F(URLRequestFtpJobPriorityTest, SetTransactionPriorityOnStart) {
181 scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
182 req_.get(), &ftp_factory_, &ftp_auth_cache_));
183 job->SetPriority(LOW);
185 EXPECT_FALSE(network_layer_.last_transaction());
187 job->Start();
189 ASSERT_TRUE(network_layer_.last_transaction());
190 EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
193 // Make sure that URLRequestFtpJob passes on its priority updates to
194 // its transaction.
195 TEST_F(URLRequestFtpJobPriorityTest, SetTransactionPriority) {
196 scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
197 req_.get(), &ftp_factory_, &ftp_auth_cache_));
198 job->SetPriority(LOW);
199 job->Start();
200 ASSERT_TRUE(network_layer_.last_transaction());
201 EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
203 job->SetPriority(HIGHEST);
204 EXPECT_EQ(HIGHEST, network_layer_.last_transaction()->priority());
207 // Make sure that URLRequestFtpJob passes on its priority updates to
208 // newly-created transactions after the first one.
209 TEST_F(URLRequestFtpJobPriorityTest, SetSubsequentTransactionPriority) {
210 scoped_refptr<TestURLRequestFtpJob> job(new TestURLRequestFtpJob(
211 req_.get(), &ftp_factory_, &ftp_auth_cache_));
212 job->Start();
214 job->SetPriority(LOW);
215 ASSERT_TRUE(network_layer_.last_transaction());
216 EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
218 job->Kill();
219 network_layer_.ClearLastTransaction();
221 // Creates a second transaction.
222 job->Start();
223 ASSERT_TRUE(network_layer_.last_transaction());
224 EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
227 class URLRequestFtpJobTest : public testing::Test {
228 public:
229 URLRequestFtpJobTest()
230 : request_context_(
231 &socket_factory_,
232 make_scoped_ptr(
233 new ProxyService(new SimpleProxyConfigService, NULL, NULL)),
234 &network_delegate_,
235 &ftp_transaction_factory_) {}
237 ~URLRequestFtpJobTest() override {
238 // Clean up any remaining tasks that mess up unrelated tests.
239 base::RunLoop().RunUntilIdle();
242 void AddSocket(MockRead* reads, size_t reads_size,
243 MockWrite* writes, size_t writes_size) {
244 SequencedSocketData* socket_data =
245 new SequencedSocketData(reads, reads_size, writes, writes_size);
246 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
247 socket_factory_.AddSocketDataProvider(socket_data);
249 socket_data_.push_back(socket_data);
252 FtpTestURLRequestContext* request_context() { return &request_context_; }
253 TestNetworkDelegate* network_delegate() { return &network_delegate_; }
255 private:
256 ScopedVector<SequencedSocketData> socket_data_;
257 MockClientSocketFactory socket_factory_;
258 TestNetworkDelegate network_delegate_;
259 MockFtpTransactionFactory ftp_transaction_factory_;
261 FtpTestURLRequestContext request_context_;
264 TEST_F(URLRequestFtpJobTest, FtpProxyRequest) {
265 MockWrite writes[] = {
266 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
267 "Host: ftp.example.com\r\n"
268 "Proxy-Connection: keep-alive\r\n\r\n"),
270 MockRead reads[] = {
271 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
272 MockRead(ASYNC, 2, "Content-Length: 9\r\n\r\n"),
273 MockRead(ASYNC, 3, "test.html"),
276 AddSocket(reads, arraysize(reads), writes, arraysize(writes));
278 TestDelegate request_delegate;
279 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest(
280 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate));
281 url_request->Start();
282 ASSERT_TRUE(url_request->is_pending());
284 // The TestDelegate will by default quit the message loop on completion.
285 base::RunLoop().Run();
287 EXPECT_TRUE(url_request->status().is_success());
288 EXPECT_TRUE(url_request->proxy_server().Equals(
289 HostPortPair::FromString("localhost:80")));
290 EXPECT_EQ(1, network_delegate()->completed_requests());
291 EXPECT_EQ(0, network_delegate()->error_count());
292 EXPECT_FALSE(request_delegate.auth_required_called());
293 EXPECT_EQ("test.html", request_delegate.data_received());
296 // Regression test for http://crbug.com/237526 .
297 TEST_F(URLRequestFtpJobTest, FtpProxyRequestOrphanJob) {
298 // Use a PAC URL so that URLRequestFtpJob's |pac_request_| field is non-NULL.
299 request_context()->set_proxy_service(make_scoped_ptr(new ProxyService(
300 new ProxyConfigServiceFixed(
301 ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
302 make_scoped_ptr(new MockProxyResolverFactory), NULL)));
304 TestDelegate request_delegate;
305 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest(
306 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate));
307 url_request->Start();
309 // Now |url_request| will be deleted before its completion,
310 // resulting in it being orphaned. It should not crash.
313 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAuthNoCredentials) {
314 MockWrite writes[] = {
315 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
316 "Host: ftp.example.com\r\n"
317 "Proxy-Connection: keep-alive\r\n\r\n"),
319 MockRead reads[] = {
320 // No credentials.
321 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
322 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic "
323 "realm=\"MyRealm1\"\r\n"),
324 MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
325 MockRead(ASYNC, 4, "test.html"),
328 AddSocket(reads, arraysize(reads), writes, arraysize(writes));
330 TestDelegate request_delegate;
331 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest(
332 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate));
333 url_request->Start();
334 ASSERT_TRUE(url_request->is_pending());
336 // The TestDelegate will by default quit the message loop on completion.
337 base::RunLoop().Run();
339 EXPECT_TRUE(url_request->status().is_success());
340 EXPECT_TRUE(url_request->proxy_server().Equals(
341 HostPortPair::FromString("localhost:80")));
342 EXPECT_EQ(1, network_delegate()->completed_requests());
343 EXPECT_EQ(0, network_delegate()->error_count());
344 EXPECT_TRUE(request_delegate.auth_required_called());
345 EXPECT_EQ("test.html", request_delegate.data_received());
348 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAuthWithCredentials) {
349 MockWrite writes[] = {
350 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
351 "Host: ftp.example.com\r\n"
352 "Proxy-Connection: keep-alive\r\n\r\n"),
353 MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
354 "Host: ftp.example.com\r\n"
355 "Proxy-Connection: keep-alive\r\n"
356 "Proxy-Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
358 MockRead reads[] = {
359 // No credentials.
360 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
361 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic "
362 "realm=\"MyRealm1\"\r\n"),
363 MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
364 MockRead(ASYNC, 4, "test.html"),
366 // Second response.
367 MockRead(ASYNC, 6, "HTTP/1.1 200 OK\r\n"),
368 MockRead(ASYNC, 7, "Content-Length: 10\r\n\r\n"),
369 MockRead(ASYNC, 8, "test2.html"),
372 AddSocket(reads, arraysize(reads), writes, arraysize(writes));
374 TestDelegate request_delegate;
375 request_delegate.set_credentials(
376 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
377 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest(
378 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate));
379 url_request->Start();
380 ASSERT_TRUE(url_request->is_pending());
382 // The TestDelegate will by default quit the message loop on completion.
383 base::RunLoop().Run();
385 EXPECT_TRUE(url_request->status().is_success());
386 EXPECT_EQ(1, network_delegate()->completed_requests());
387 EXPECT_EQ(0, network_delegate()->error_count());
388 EXPECT_TRUE(request_delegate.auth_required_called());
389 EXPECT_EQ("test2.html", request_delegate.data_received());
392 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedServerAuthNoCredentials) {
393 MockWrite writes[] = {
394 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
395 "Host: ftp.example.com\r\n"
396 "Proxy-Connection: keep-alive\r\n\r\n"),
398 MockRead reads[] = {
399 // No credentials.
400 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
401 MockRead(ASYNC, 2, "WWW-Authenticate: Basic "
402 "realm=\"MyRealm1\"\r\n"),
403 MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
404 MockRead(ASYNC, 4, "test.html"),
407 AddSocket(reads, arraysize(reads), writes, arraysize(writes));
409 TestDelegate request_delegate;
410 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest(
411 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate));
412 url_request->Start();
413 ASSERT_TRUE(url_request->is_pending());
415 // The TestDelegate will by default quit the message loop on completion.
416 base::RunLoop().Run();
418 EXPECT_TRUE(url_request->status().is_success());
419 EXPECT_EQ(1, network_delegate()->completed_requests());
420 EXPECT_EQ(0, network_delegate()->error_count());
421 EXPECT_TRUE(request_delegate.auth_required_called());
422 EXPECT_EQ("test.html", request_delegate.data_received());
425 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedServerAuthWithCredentials) {
426 MockWrite writes[] = {
427 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
428 "Host: ftp.example.com\r\n"
429 "Proxy-Connection: keep-alive\r\n\r\n"),
430 MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
431 "Host: ftp.example.com\r\n"
432 "Proxy-Connection: keep-alive\r\n"
433 "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
435 MockRead reads[] = {
436 // No credentials.
437 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
438 MockRead(ASYNC, 2, "WWW-Authenticate: Basic "
439 "realm=\"MyRealm1\"\r\n"),
440 MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
441 MockRead(ASYNC, 4, "test.html"),
443 // Second response.
444 MockRead(ASYNC, 6, "HTTP/1.1 200 OK\r\n"),
445 MockRead(ASYNC, 7, "Content-Length: 10\r\n\r\n"),
446 MockRead(ASYNC, 8, "test2.html"),
449 AddSocket(reads, arraysize(reads), writes, arraysize(writes));
451 TestDelegate request_delegate;
452 request_delegate.set_credentials(
453 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
454 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest(
455 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate));
456 url_request->Start();
457 ASSERT_TRUE(url_request->is_pending());
459 // The TestDelegate will by default quit the message loop on completion.
460 base::RunLoop().Run();
462 EXPECT_TRUE(url_request->status().is_success());
463 EXPECT_EQ(1, network_delegate()->completed_requests());
464 EXPECT_EQ(0, network_delegate()->error_count());
465 EXPECT_TRUE(request_delegate.auth_required_called());
466 EXPECT_EQ("test2.html", request_delegate.data_received());
469 TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAndServerAuth) {
470 MockWrite writes[] = {
471 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
472 "Host: ftp.example.com\r\n"
473 "Proxy-Connection: keep-alive\r\n\r\n"),
474 MockWrite(ASYNC, 5, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
475 "Host: ftp.example.com\r\n"
476 "Proxy-Connection: keep-alive\r\n"
477 "Proxy-Authorization: Basic "
478 "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n"),
479 MockWrite(ASYNC, 10, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
480 "Host: ftp.example.com\r\n"
481 "Proxy-Connection: keep-alive\r\n"
482 "Proxy-Authorization: Basic "
483 "cHJveHl1c2VyOnByb3h5cGFzcw==\r\n"
484 "Authorization: Basic bXl1c2VyOm15cGFzcw==\r\n\r\n"),
486 MockRead reads[] = {
487 // No credentials.
488 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
489 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic "
490 "realm=\"MyRealm1\"\r\n"),
491 MockRead(ASYNC, 3, "Content-Length: 9\r\n\r\n"),
492 MockRead(ASYNC, 4, "test.html"),
494 // Second response.
495 MockRead(ASYNC, 6, "HTTP/1.1 401 Unauthorized\r\n"),
496 MockRead(ASYNC, 7, "WWW-Authenticate: Basic "
497 "realm=\"MyRealm1\"\r\n"),
498 MockRead(ASYNC, 8, "Content-Length: 9\r\n\r\n"),
499 MockRead(ASYNC, 9, "test.html"),
501 // Third response.
502 MockRead(ASYNC, 11, "HTTP/1.1 200 OK\r\n"),
503 MockRead(ASYNC, 12, "Content-Length: 10\r\n\r\n"),
504 MockRead(ASYNC, 13, "test2.html"),
507 AddSocket(reads, arraysize(reads), writes, arraysize(writes));
509 GURL url("ftp://ftp.example.com");
511 // Make sure cached FTP credentials are not used for proxy authentication.
512 request_context()->GetFtpAuthCache()->Add(
513 url.GetOrigin(),
514 AuthCredentials(ASCIIToUTF16("userdonotuse"),
515 ASCIIToUTF16("passworddonotuse")));
517 TestDelegate request_delegate;
518 request_delegate.set_quit_on_auth_required(true);
519 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest(
520 url, DEFAULT_PRIORITY, &request_delegate));
521 url_request->Start();
522 ASSERT_TRUE(url_request->is_pending());
524 // Run until proxy auth is requested.
525 base::RunLoop().Run();
527 ASSERT_TRUE(request_delegate.auth_required_called());
528 EXPECT_EQ(0, network_delegate()->completed_requests());
529 EXPECT_EQ(0, network_delegate()->error_count());
530 url_request->SetAuth(
531 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")));
533 // Run until server auth is requested.
534 base::RunLoop().Run();
536 EXPECT_TRUE(url_request->status().is_success());
537 EXPECT_EQ(0, network_delegate()->completed_requests());
538 EXPECT_EQ(0, network_delegate()->error_count());
539 url_request->SetAuth(
540 AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
542 // The TestDelegate will by default quit the message loop on completion.
543 base::RunLoop().Run();
545 EXPECT_TRUE(url_request->status().is_success());
546 EXPECT_EQ(1, network_delegate()->completed_requests());
547 EXPECT_EQ(0, network_delegate()->error_count());
548 EXPECT_TRUE(request_delegate.auth_required_called());
549 EXPECT_EQ("test2.html", request_delegate.data_received());
552 TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotSaveCookies) {
553 MockWrite writes[] = {
554 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
555 "Host: ftp.example.com\r\n"
556 "Proxy-Connection: keep-alive\r\n\r\n"),
558 MockRead reads[] = {
559 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
560 MockRead(ASYNC, 2, "Content-Length: 9\r\n"),
561 MockRead(ASYNC, 3, "Set-Cookie: name=value\r\n\r\n"),
562 MockRead(ASYNC, 4, "test.html"),
565 AddSocket(reads, arraysize(reads), writes, arraysize(writes));
567 TestDelegate request_delegate;
568 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest(
569 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate));
570 url_request->Start();
571 ASSERT_TRUE(url_request->is_pending());
573 // The TestDelegate will by default quit the message loop on completion.
574 base::RunLoop().Run();
576 EXPECT_TRUE(url_request->status().is_success());
577 EXPECT_EQ(1, network_delegate()->completed_requests());
578 EXPECT_EQ(0, network_delegate()->error_count());
580 // Make sure we do not accept cookies.
581 EXPECT_EQ(0, network_delegate()->set_cookie_count());
583 EXPECT_FALSE(request_delegate.auth_required_called());
584 EXPECT_EQ("test.html", request_delegate.data_received());
587 TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotFollowRedirects) {
588 MockWrite writes[] = {
589 MockWrite(SYNCHRONOUS, 0, "GET ftp://ftp.example.com/ HTTP/1.1\r\n"
590 "Host: ftp.example.com\r\n"
591 "Proxy-Connection: keep-alive\r\n\r\n"),
593 MockRead reads[] = {
594 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 302 Found\r\n"),
595 MockRead(ASYNC, 2, "Location: http://other.example.com/\r\n\r\n"),
598 AddSocket(reads, arraysize(reads), writes, arraysize(writes));
600 TestDelegate request_delegate;
601 scoped_ptr<URLRequest> url_request(request_context()->CreateRequest(
602 GURL("ftp://ftp.example.com/"), DEFAULT_PRIORITY, &request_delegate));
603 url_request->Start();
604 EXPECT_TRUE(url_request->is_pending());
606 // The TestDelegate will by default quit the message loop on completion.
607 base::RunLoop().Run();
609 EXPECT_EQ(1, network_delegate()->completed_requests());
610 EXPECT_EQ(1, network_delegate()->error_count());
611 EXPECT_FALSE(url_request->status().is_success());
612 EXPECT_EQ(ERR_UNSAFE_REDIRECT, url_request->status().error());
615 // We should re-use socket for requests using the same scheme, host, and port.
616 TEST_F(URLRequestFtpJobTest, FtpProxyRequestReuseSocket) {
617 MockWrite writes[] = {
618 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
619 "Host: ftp.example.com\r\n"
620 "Proxy-Connection: keep-alive\r\n\r\n"),
621 MockWrite(ASYNC, 4, "GET ftp://ftp.example.com/second HTTP/1.1\r\n"
622 "Host: ftp.example.com\r\n"
623 "Proxy-Connection: keep-alive\r\n\r\n"),
625 MockRead reads[] = {
626 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
627 MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"),
628 MockRead(ASYNC, 3, "test1.html"),
629 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"),
630 MockRead(ASYNC, 6, "Content-Length: 10\r\n\r\n"),
631 MockRead(ASYNC, 7, "test2.html"),
634 AddSocket(reads, arraysize(reads), writes, arraysize(writes));
636 TestDelegate request_delegate1;
638 scoped_ptr<URLRequest> url_request1(
639 request_context()->CreateRequest(GURL("ftp://ftp.example.com/first"),
640 DEFAULT_PRIORITY, &request_delegate1));
641 url_request1->Start();
642 ASSERT_TRUE(url_request1->is_pending());
644 // The TestDelegate will by default quit the message loop on completion.
645 base::RunLoop().Run();
647 EXPECT_TRUE(url_request1->status().is_success());
648 EXPECT_TRUE(url_request1->proxy_server().Equals(
649 HostPortPair::FromString("localhost:80")));
650 EXPECT_EQ(1, network_delegate()->completed_requests());
651 EXPECT_EQ(0, network_delegate()->error_count());
652 EXPECT_FALSE(request_delegate1.auth_required_called());
653 EXPECT_EQ("test1.html", request_delegate1.data_received());
655 TestDelegate request_delegate2;
656 scoped_ptr<URLRequest> url_request2(
657 request_context()->CreateRequest(GURL("ftp://ftp.example.com/second"),
658 DEFAULT_PRIORITY, &request_delegate2));
659 url_request2->Start();
660 ASSERT_TRUE(url_request2->is_pending());
662 // The TestDelegate will by default quit the message loop on completion.
663 base::RunLoop().Run();
665 EXPECT_TRUE(url_request2->status().is_success());
666 EXPECT_EQ(2, network_delegate()->completed_requests());
667 EXPECT_EQ(0, network_delegate()->error_count());
668 EXPECT_FALSE(request_delegate2.auth_required_called());
669 EXPECT_EQ("test2.html", request_delegate2.data_received());
672 // We should not re-use socket when there are two requests to the same host,
673 // but one is FTP and the other is HTTP.
674 TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotReuseSocket) {
675 MockWrite writes1[] = {
676 MockWrite(ASYNC, 0, "GET ftp://ftp.example.com/first HTTP/1.1\r\n"
677 "Host: ftp.example.com\r\n"
678 "Proxy-Connection: keep-alive\r\n\r\n"),
680 MockWrite writes2[] = {
681 MockWrite(ASYNC, 0, "GET /second HTTP/1.1\r\n"
682 "Host: ftp.example.com\r\n"
683 "Connection: keep-alive\r\n"
684 "User-Agent:\r\n"
685 "Accept-Encoding: gzip, deflate\r\n"
686 "Accept-Language: en-us,fr\r\n\r\n"),
688 MockRead reads1[] = {
689 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
690 MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"),
691 MockRead(ASYNC, 3, "test1.html"),
693 MockRead reads2[] = {
694 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n"),
695 MockRead(ASYNC, 2, "Content-Length: 10\r\n\r\n"),
696 MockRead(ASYNC, 3, "test2.html"),
699 AddSocket(reads1, arraysize(reads1), writes1, arraysize(writes1));
700 AddSocket(reads2, arraysize(reads2), writes2, arraysize(writes2));
702 TestDelegate request_delegate1;
703 scoped_ptr<URLRequest> url_request1(
704 request_context()->CreateRequest(GURL("ftp://ftp.example.com/first"),
705 DEFAULT_PRIORITY, &request_delegate1));
706 url_request1->Start();
707 ASSERT_TRUE(url_request1->is_pending());
709 // The TestDelegate will by default quit the message loop on completion.
710 base::RunLoop().Run();
712 EXPECT_TRUE(url_request1->status().is_success());
713 EXPECT_EQ(1, network_delegate()->completed_requests());
714 EXPECT_EQ(0, network_delegate()->error_count());
715 EXPECT_FALSE(request_delegate1.auth_required_called());
716 EXPECT_EQ("test1.html", request_delegate1.data_received());
718 TestDelegate request_delegate2;
719 scoped_ptr<URLRequest> url_request2(
720 request_context()->CreateRequest(GURL("http://ftp.example.com/second"),
721 DEFAULT_PRIORITY, &request_delegate2));
722 url_request2->Start();
723 ASSERT_TRUE(url_request2->is_pending());
725 // The TestDelegate will by default quit the message loop on completion.
726 base::RunLoop().Run();
728 EXPECT_TRUE(url_request2->status().is_success());
729 EXPECT_EQ(2, network_delegate()->completed_requests());
730 EXPECT_EQ(0, network_delegate()->error_count());
731 EXPECT_FALSE(request_delegate2.auth_required_called());
732 EXPECT_EQ("test2.html", request_delegate2.data_received());
735 } // namespace
737 } // namespace net