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 |