| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ | 5 #ifndef NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ |
| 6 #define NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ | 6 #define NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ |
| 7 | 7 |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 | 9 |
| 10 #include <sstream> | 10 #include <sstream> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/file_path.h" | 14 #include "base/file_path.h" |
| 15 #include "base/file_util.h" | 15 #include "base/file_util.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
| 18 #include "base/path_service.h" | 18 #include "base/path_service.h" |
| 19 #include "base/process_util.h" | 19 #include "base/process_util.h" |
| 20 #include "base/thread.h" | 20 #include "base/thread.h" |
| 21 #include "base/time.h" | 21 #include "base/time.h" |
| 22 #include "base/utf_string_conversions.h" | 22 #include "base/utf_string_conversions.h" |
| 23 #include "base/waitable_event.h" | 23 #include "base/waitable_event.h" |
| 24 #include "net/base/cookie_monster.h" | 24 #include "net/base/cookie_monster.h" |
| 25 #include "net/base/cookie_policy.h" | 25 #include "net/base/cookie_policy.h" |
| 26 #include "net/base/host_resolver.h" | 26 #include "net/base/host_resolver.h" |
| 27 #include "net/base/io_buffer.h" | 27 #include "net/base/io_buffer.h" |
| 28 #include "net/base/net_errors.h" | 28 #include "net/base/net_errors.h" |
| 29 #include "net/base/net_test_constants.h" | |
| 30 #include "net/base/ssl_config_service_defaults.h" | 29 #include "net/base/ssl_config_service_defaults.h" |
| 31 #include "net/disk_cache/disk_cache.h" | 30 #include "net/disk_cache/disk_cache.h" |
| 32 #include "net/ftp/ftp_network_layer.h" | 31 #include "net/ftp/ftp_network_layer.h" |
| 33 #include "net/http/http_auth_handler_factory.h" | 32 #include "net/http/http_auth_handler_factory.h" |
| 34 #include "net/http/http_cache.h" | 33 #include "net/http/http_cache.h" |
| 35 #include "net/http/http_network_layer.h" | 34 #include "net/http/http_network_layer.h" |
| 36 #include "net/test/test_server.h" | 35 #include "net/test/test_server.h" |
| 37 #include "net/url_request/url_request.h" | 36 #include "net/url_request/url_request.h" |
| 38 #include "net/url_request/url_request_context.h" | 37 #include "net/url_request/url_request_context.h" |
| 39 #include "net/proxy/proxy_service.h" | 38 #include "net/proxy/proxy_service.h" |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 scoped_refptr<net::IOBuffer> buf_; | 394 scoped_refptr<net::IOBuffer> buf_; |
| 396 }; | 395 }; |
| 397 | 396 |
| 398 //----------------------------------------------------------------------------- | 397 //----------------------------------------------------------------------------- |
| 399 | 398 |
| 400 // This object bounds the lifetime of an external python-based HTTP/FTP server | 399 // This object bounds the lifetime of an external python-based HTTP/FTP server |
| 401 // that can provide various responses useful for testing. | 400 // that can provide various responses useful for testing. |
| 402 class BaseTestServer : public base::RefCounted<BaseTestServer> { | 401 class BaseTestServer : public base::RefCounted<BaseTestServer> { |
| 403 protected: | 402 protected: |
| 404 BaseTestServer() {} | 403 BaseTestServer() {} |
| 405 BaseTestServer(int connection_attempts, int connection_timeout) | |
| 406 : launcher_(connection_attempts, connection_timeout) {} | |
| 407 | 404 |
| 408 public: | 405 public: |
| 409 void set_forking(bool forking) { | |
| 410 launcher_.set_forking(forking); | |
| 411 } | |
| 412 | |
| 413 // Used with e.g. HTTPTestServer::SendQuit() | |
| 414 bool WaitToFinish(int milliseconds) { | 406 bool WaitToFinish(int milliseconds) { |
| 415 return launcher_.WaitToFinish(milliseconds); | 407 return launcher_.WaitToFinish(milliseconds); |
| 416 } | 408 } |
| 417 | 409 |
| 418 bool Stop() { | 410 bool Stop() { |
| 419 return launcher_.Stop(); | 411 return launcher_.Stop(); |
| 420 } | 412 } |
| 421 | 413 |
| 422 GURL TestServerPage(const std::string& base_address, | 414 GURL TestServerPage(const std::string& base_address, |
| 423 const std::string& path) { | 415 const std::string& path) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 435 // TODO(phajdan.jr): Check for problems with IPv6. | 427 // TODO(phajdan.jr): Check for problems with IPv6. |
| 436 | 428 |
| 437 if (password.empty()) | 429 if (password.empty()) |
| 438 return GURL(scheme_ + "://" + user + "@" + | 430 return GURL(scheme_ + "://" + user + "@" + |
| 439 host_name_ + ":" + port_str_ + "/" + path); | 431 host_name_ + ":" + port_str_ + "/" + path); |
| 440 | 432 |
| 441 return GURL(scheme_ + "://" + user + ":" + password + | 433 return GURL(scheme_ + "://" + user + ":" + password + |
| 442 "@" + host_name_ + ":" + port_str_ + "/" + path); | 434 "@" + host_name_ + ":" + port_str_ + "/" + path); |
| 443 } | 435 } |
| 444 | 436 |
| 445 virtual bool MakeGETRequest(const std::string& page_name) = 0; | |
| 446 | |
| 447 FilePath GetDataDirectory() { | 437 FilePath GetDataDirectory() { |
| 448 return launcher_.GetDocumentRootPath(); | 438 return launcher_.GetDocumentRootPath(); |
| 449 } | 439 } |
| 450 | 440 |
| 451 protected: | 441 protected: |
| 452 friend class base::RefCounted<BaseTestServer>; | 442 friend class base::RefCounted<BaseTestServer>; |
| 453 virtual ~BaseTestServer() { } | 443 virtual ~BaseTestServer() { } |
| 454 | 444 |
| 455 bool Start(net::TestServerLauncher::Protocol protocol, | 445 bool Start(net::TestServerLauncher::Protocol protocol, |
| 456 const std::string& host_name, int port, | 446 const std::string& host_name, int port, |
| 457 const FilePath& document_root, | 447 const FilePath& document_root, |
| 458 const FilePath& cert_path, | 448 const FilePath& cert_path, |
| 459 const std::wstring& file_root_url) { | 449 const std::wstring& file_root_url) { |
| 460 if (!launcher_.Start(protocol, | 450 if (!launcher_.Start(protocol, |
| 461 host_name, port, document_root, cert_path, file_root_url)) | 451 host_name, port, document_root, cert_path, file_root_url)) |
| 462 return false; | 452 return false; |
| 463 | 453 |
| 464 if (protocol == net::TestServerLauncher::ProtoFTP) | 454 if (protocol == net::TestServerLauncher::ProtoFTP) |
| 465 scheme_ = "ftp"; | 455 scheme_ = "ftp"; |
| 466 else | 456 else |
| 467 scheme_ = "http"; | 457 scheme_ = "http"; |
| 468 if (!cert_path.empty()) | 458 if (!cert_path.empty()) |
| 469 scheme_.push_back('s'); | 459 scheme_.push_back('s'); |
| 470 | 460 |
| 471 host_name_ = host_name; | 461 host_name_ = host_name; |
| 472 port_str_ = IntToString(port); | 462 port_str_ = IntToString(port); |
| 473 return true; | 463 return true; |
| 474 } | 464 } |
| 475 | 465 |
| 476 // Used by MakeGETRequest to implement sync load behavior. | |
| 477 class SyncTestDelegate : public TestDelegate { | |
| 478 public: | |
| 479 SyncTestDelegate() : event_(false, false), success_(false) { | |
| 480 } | |
| 481 virtual void OnResponseCompleted(URLRequest* request) { | |
| 482 MessageLoop::current()->DeleteSoon(FROM_HERE, request); | |
| 483 success_ = request->status().is_success(); | |
| 484 event_.Signal(); | |
| 485 } | |
| 486 bool Wait(int64 secs) { | |
| 487 TimeDelta td = TimeDelta::FromSeconds(secs); | |
| 488 if (event_.TimedWait(td)) | |
| 489 return true; | |
| 490 return false; | |
| 491 } | |
| 492 bool did_succeed() const { return success_; } | |
| 493 private: | |
| 494 base::WaitableEvent event_; | |
| 495 bool success_; | |
| 496 DISALLOW_COPY_AND_ASSIGN(SyncTestDelegate); | |
| 497 }; | |
| 498 | |
| 499 net::TestServerLauncher launcher_; | 466 net::TestServerLauncher launcher_; |
| 500 std::string scheme_; | 467 std::string scheme_; |
| 501 std::string host_name_; | 468 std::string host_name_; |
| 502 std::string port_str_; | 469 std::string port_str_; |
| 503 }; | 470 }; |
| 504 | 471 |
| 505 //----------------------------------------------------------------------------- | 472 //----------------------------------------------------------------------------- |
| 506 | 473 |
| 507 // HTTP | 474 // HTTP |
| 508 class HTTPTestServer : public BaseTestServer { | 475 class HTTPTestServer : public BaseTestServer { |
| 509 protected: | 476 protected: |
| 510 explicit HTTPTestServer() : loop_(NULL) { | 477 HTTPTestServer() {} |
| 511 } | |
| 512 | |
| 513 explicit HTTPTestServer(int connection_attempts, int connection_timeout) | |
| 514 : BaseTestServer(connection_attempts, connection_timeout), loop_(NULL) { | |
| 515 } | |
| 516 | |
| 517 virtual ~HTTPTestServer() {} | |
| 518 | 478 |
| 519 public: | 479 public: |
| 520 // Creates and returns a new HTTPTestServer. If |loop| is non-null, requests | 480 // Creates and returns a new HTTPTestServer. If |loop| is non-null, requests |
| 521 // are serviced on it, otherwise a new thread and message loop are created. | 481 // are serviced on it, otherwise a new thread and message loop are created. |
| 522 static scoped_refptr<HTTPTestServer> CreateServer( | 482 static scoped_refptr<HTTPTestServer> CreateServer( |
| 523 const std::wstring& document_root, | 483 const std::wstring& document_root) { |
| 524 MessageLoop* loop) { | 484 return CreateServerWithFileRootURL(document_root, std::wstring()); |
| 525 return CreateServerWithFileRootURL(document_root, std::wstring(), loop); | |
| 526 } | |
| 527 | |
| 528 static scoped_refptr<HTTPTestServer> CreateServer( | |
| 529 const std::wstring& document_root, | |
| 530 MessageLoop* loop, | |
| 531 int connection_attempts, | |
| 532 int connection_timeout) { | |
| 533 return CreateServerWithFileRootURL(document_root, std::wstring(), loop, | |
| 534 connection_attempts, | |
| 535 connection_timeout); | |
| 536 } | 485 } |
| 537 | 486 |
| 538 static scoped_refptr<HTTPTestServer> CreateServerWithFileRootURL( | 487 static scoped_refptr<HTTPTestServer> CreateServerWithFileRootURL( |
| 539 const std::wstring& document_root, | 488 const std::wstring& document_root, |
| 540 const std::wstring& file_root_url, | 489 const std::wstring& file_root_url) { |
| 541 MessageLoop* loop) { | 490 scoped_refptr<HTTPTestServer> test_server(new HTTPTestServer()); |
| 542 return CreateServerWithFileRootURL(document_root, file_root_url, loop, | |
| 543 net::kDefaultTestConnectionAttempts, | |
| 544 net::kDefaultTestConnectionTimeout); | |
| 545 } | |
| 546 | |
| 547 static scoped_refptr<HTTPTestServer> CreateForkingServer( | |
| 548 const std::wstring& document_root) { | |
| 549 scoped_refptr<HTTPTestServer> test_server = | |
| 550 new HTTPTestServer(net::kDefaultTestConnectionAttempts, | |
| 551 net::kDefaultTestConnectionTimeout); | |
| 552 test_server->set_forking(true); | |
| 553 FilePath no_cert; | |
| 554 FilePath docroot = FilePath::FromWStringHack(document_root); | |
| 555 if (!StartTestServer(test_server.get(), docroot, no_cert, std::wstring())) | |
| 556 return NULL; | |
| 557 return test_server; | |
| 558 } | |
| 559 | |
| 560 static scoped_refptr<HTTPTestServer> CreateServerWithFileRootURL( | |
| 561 const std::wstring& document_root, | |
| 562 const std::wstring& file_root_url, | |
| 563 MessageLoop* loop, | |
| 564 int connection_attempts, | |
| 565 int connection_timeout) { | |
| 566 scoped_refptr<HTTPTestServer> test_server = | |
| 567 new HTTPTestServer(connection_attempts, connection_timeout); | |
| 568 test_server->loop_ = loop; | |
| 569 FilePath no_cert; | 491 FilePath no_cert; |
| 570 FilePath docroot = FilePath::FromWStringHack(document_root); | 492 FilePath docroot = FilePath::FromWStringHack(document_root); |
| 571 if (!StartTestServer(test_server.get(), docroot, no_cert, file_root_url)) | 493 if (!StartTestServer(test_server.get(), docroot, no_cert, file_root_url)) |
| 572 return NULL; | 494 return NULL; |
| 573 return test_server; | 495 return test_server; |
| 574 } | 496 } |
| 575 | 497 |
| 576 static bool StartTestServer(HTTPTestServer* server, | 498 static bool StartTestServer(HTTPTestServer* server, |
| 577 const FilePath& document_root, | 499 const FilePath& document_root, |
| 578 const FilePath& cert_path, | 500 const FilePath& cert_path, |
| 579 const std::wstring& file_root_url) { | 501 const std::wstring& file_root_url) { |
| 580 return server->Start(net::TestServerLauncher::ProtoHTTP, kDefaultHostName, | 502 return server->Start(net::TestServerLauncher::ProtoHTTP, kDefaultHostName, |
| 581 kHTTPDefaultPort, document_root, cert_path, | 503 kHTTPDefaultPort, document_root, cert_path, |
| 582 file_root_url); | 504 file_root_url); |
| 583 } | 505 } |
| 584 | 506 |
| 585 // A subclass may wish to send the request in a different manner | |
| 586 virtual bool MakeGETRequest(const std::string& page_name) { | |
| 587 const GURL& url = TestServerPage(page_name); | |
| 588 | |
| 589 // Spin up a background thread for this request so that we have access to | |
| 590 // an IO message loop, and in cases where this thread already has an IO | |
| 591 // message loop, we also want to avoid spinning a nested message loop. | |
| 592 SyncTestDelegate d; | |
| 593 { | |
| 594 MessageLoop* loop = loop_; | |
| 595 scoped_ptr<base::Thread> io_thread; | |
| 596 | |
| 597 if (!loop) { | |
| 598 io_thread.reset(new base::Thread("MakeGETRequest")); | |
| 599 base::Thread::Options options; | |
| 600 options.message_loop_type = MessageLoop::TYPE_IO; | |
| 601 io_thread->StartWithOptions(options); | |
| 602 loop = io_thread->message_loop(); | |
| 603 } | |
| 604 loop->PostTask(FROM_HERE, NewRunnableFunction( | |
| 605 &HTTPTestServer::StartGETRequest, url, &d)); | |
| 606 | |
| 607 // Build bot wait for only 300 seconds we should ensure wait do not take | |
| 608 // more than 300 seconds | |
| 609 if (!d.Wait(250)) | |
| 610 return false; | |
| 611 } | |
| 612 return d.did_succeed(); | |
| 613 } | |
| 614 | |
| 615 static void StartGETRequest(const GURL& url, URLRequest::Delegate* delegate) { | |
| 616 URLRequest* request = new URLRequest(url, delegate); | |
| 617 request->set_context(new TestURLRequestContext()); | |
| 618 request->set_method("GET"); | |
| 619 request->Start(); | |
| 620 EXPECT_TRUE(request->is_pending()); | |
| 621 } | |
| 622 | |
| 623 // Some tests use browser javascript to fetch a 'kill' url that causes | |
| 624 // the server to exit by itself (rather than letting TestServerLauncher's | |
| 625 // destructor kill it). | |
| 626 // This method does the same thing so we can unit test that mechanism. | |
| 627 // You can then use WaitToFinish() to sleep until the server terminates. | |
| 628 void SendQuit() { | |
| 629 // Append the time to avoid problems where the kill page | |
| 630 // is being cached rather than being executed on the server | |
| 631 std::string page_name = StringPrintf("kill?%u", | |
| 632 static_cast<int>(base::Time::Now().ToInternalValue())); | |
| 633 int retry_count = 5; | |
| 634 while (retry_count > 0) { | |
| 635 bool r = MakeGETRequest(page_name); | |
| 636 // BUG #1048625 causes the kill GET to fail. For now we just retry. | |
| 637 // Once the bug is fixed, we should remove the while loop and put back | |
| 638 // the following DCHECK. | |
| 639 // DCHECK(r); | |
| 640 if (r) | |
| 641 break; | |
| 642 retry_count--; | |
| 643 } | |
| 644 // Make sure we were successful in stopping the testserver. | |
| 645 DCHECK_GT(retry_count, 0); | |
| 646 } | |
| 647 | |
| 648 virtual std::string scheme() { return "http"; } | 507 virtual std::string scheme() { return "http"; } |
| 649 | |
| 650 private: | |
| 651 // If non-null a background thread isn't created and instead this message loop | |
| 652 // is used. | |
| 653 MessageLoop* loop_; | |
| 654 }; | 508 }; |
| 655 | 509 |
| 656 //----------------------------------------------------------------------------- | 510 //----------------------------------------------------------------------------- |
| 657 | 511 |
| 658 class HTTPSTestServer : public HTTPTestServer { | 512 class HTTPSTestServer : public HTTPTestServer { |
| 659 protected: | 513 protected: |
| 660 explicit HTTPSTestServer() { | 514 explicit HTTPSTestServer() { |
| 661 } | 515 } |
| 662 | 516 |
| 663 public: | 517 public: |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 743 scoped_refptr<FTPTestServer> test_server = new FTPTestServer(); | 597 scoped_refptr<FTPTestServer> test_server = new FTPTestServer(); |
| 744 FilePath docroot = FilePath::FromWStringHack(document_root); | 598 FilePath docroot = FilePath::FromWStringHack(document_root); |
| 745 FilePath no_cert; | 599 FilePath no_cert; |
| 746 if (!test_server->Start(net::TestServerLauncher::ProtoFTP, | 600 if (!test_server->Start(net::TestServerLauncher::ProtoFTP, |
| 747 kDefaultHostName, kFTPDefaultPort, docroot, no_cert, std::wstring())) { | 601 kDefaultHostName, kFTPDefaultPort, docroot, no_cert, std::wstring())) { |
| 748 return NULL; | 602 return NULL; |
| 749 } | 603 } |
| 750 return test_server; | 604 return test_server; |
| 751 } | 605 } |
| 752 | 606 |
| 753 virtual bool MakeGETRequest(const std::string& page_name) { | |
| 754 const GURL& url = TestServerPage(page_name); | |
| 755 TestDelegate d; | |
| 756 URLRequest request(url, &d); | |
| 757 request.set_context(new TestURLRequestContext()); | |
| 758 request.set_method("GET"); | |
| 759 request.Start(); | |
| 760 EXPECT_TRUE(request.is_pending()); | |
| 761 | |
| 762 MessageLoop::current()->Run(); | |
| 763 if (request.is_pending()) | |
| 764 return false; | |
| 765 | |
| 766 return true; | |
| 767 } | |
| 768 | |
| 769 private: | 607 private: |
| 770 ~FTPTestServer() {} | 608 ~FTPTestServer() {} |
| 771 }; | 609 }; |
| 772 | 610 |
| 773 #endif // NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ | 611 #endif // NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ |
| OLD | NEW |