1 // Copyright (c) 2011 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 "chrome/browser/net/connection_tester.h" 6 7 #include "chrome/test/testing_pref_service.h" 8 #include "content/browser/browser_thread.h" 9 #include "net/base/cert_verifier.h" 10 #include "net/base/cookie_monster.h" 11 #include "net/base/dnsrr_resolver.h" 12 #include "net/base/mock_host_resolver.h" 13 #include "net/base/ssl_config_service_defaults.h" 14 #include "net/ftp/ftp_network_layer.h" 15 #include "net/http/http_auth_handler_factory.h" 16 #include "net/http/http_network_layer.h" 17 #include "net/http/http_network_session.h" 18 #include "net/proxy/proxy_config_service_fixed.h" 19 #include "net/test/test_server.h" 20 #include "net/url_request/url_request_context.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/platform_test.h" 23 24 namespace { 25 26 // This is a testing delegate which simply counts how many times each of 27 // the delegate's methods were invoked. 28 class ConnectionTesterDelegate : public ConnectionTester::Delegate { 29 public: 30 ConnectionTesterDelegate() 31 : start_connection_test_suite_count_(0), 32 start_connection_test_experiment_count_(0), 33 completed_connection_test_experiment_count_(0), 34 completed_connection_test_suite_count_(0) { 35 } 36 37 virtual void OnStartConnectionTestSuite() { 38 start_connection_test_suite_count_++; 39 } 40 41 virtual void OnStartConnectionTestExperiment( 42 const ConnectionTester::Experiment& experiment) { 43 start_connection_test_experiment_count_++; 44 } 45 46 virtual void OnCompletedConnectionTestExperiment( 47 const ConnectionTester::Experiment& experiment, 48 int result) { 49 completed_connection_test_experiment_count_++; 50 } 51 52 virtual void OnCompletedConnectionTestSuite() { 53 completed_connection_test_suite_count_++; 54 MessageLoop::current()->Quit(); 55 } 56 57 int start_connection_test_suite_count() const { 58 return start_connection_test_suite_count_; 59 } 60 61 int start_connection_test_experiment_count() const { 62 return start_connection_test_experiment_count_; 63 } 64 65 int completed_connection_test_experiment_count() const { 66 return completed_connection_test_experiment_count_; 67 } 68 69 int completed_connection_test_suite_count() const { 70 return completed_connection_test_suite_count_; 71 } 72 73 private: 74 int start_connection_test_suite_count_; 75 int start_connection_test_experiment_count_; 76 int completed_connection_test_experiment_count_; 77 int completed_connection_test_suite_count_; 78 }; 79 80 // The test fixture is responsible for: 81 // - Making sure each test has an IO loop running 82 // - Catching any host resolve requests and mapping them to localhost 83 // (so the test doesn't use any external network dependencies). 84 class ConnectionTesterTest : public PlatformTest { 85 public: 86 ConnectionTesterTest() 87 : message_loop_(MessageLoop::TYPE_IO), 88 io_thread_(BrowserThread::IO, &message_loop_), 89 test_server_(net::TestServer::TYPE_HTTP, 90 FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))), 91 proxy_script_fetcher_context_(new net::URLRequestContext) { 92 InitializeRequestContext(); 93 } 94 95 protected: 96 // Destroy last the MessageLoop last to give a chance for objects like 97 // ObserverListThreadSave to shut down properly. For example, 98 // SSLClientAuthCache calls RemoveObserver when destroyed, but if the 99 // MessageLoop is already destroyed, then the RemoveObserver will be a 100 // no-op, and the ObserverList will contain invalid entries. 101 MessageLoop message_loop_; 102 BrowserThread io_thread_; 103 net::TestServer test_server_; 104 ConnectionTesterDelegate test_delegate_; 105 net::MockHostResolver host_resolver_; 106 net::CertVerifier cert_verifier_; 107 net::DnsRRResolver dnsrr_resolver_; 108 scoped_refptr<net::ProxyService> proxy_service_; 109 scoped_refptr<net::SSLConfigService> ssl_config_service_; 110 scoped_ptr<net::HttpTransactionFactory> http_transaction_factory_; 111 net::HttpAuthHandlerRegistryFactory http_auth_handler_factory_; 112 scoped_refptr<net::URLRequestContext> proxy_script_fetcher_context_; 113 114 private: 115 void InitializeRequestContext() { 116 proxy_script_fetcher_context_->set_host_resolver(&host_resolver_); 117 proxy_script_fetcher_context_->set_cert_verifier(&cert_verifier_); 118 proxy_script_fetcher_context_->set_dnsrr_resolver(&dnsrr_resolver_); 119 proxy_script_fetcher_context_->set_http_auth_handler_factory( 120 &http_auth_handler_factory_); 121 proxy_service_ = net::ProxyService::CreateDirect(); 122 proxy_script_fetcher_context_->set_proxy_service(proxy_service_); 123 ssl_config_service_ = net::SSLConfigService::CreateSystemSSLConfigService(); 124 net::HttpNetworkSession::Params session_params; 125 session_params.host_resolver = &host_resolver_; 126 session_params.cert_verifier = &cert_verifier_; 127 session_params.dnsrr_resolver = &dnsrr_resolver_; 128 session_params.http_auth_handler_factory = &http_auth_handler_factory_; 129 session_params.ssl_config_service = ssl_config_service_; 130 session_params.proxy_service = proxy_service_; 131 scoped_refptr<net::HttpNetworkSession> network_session( 132 new net::HttpNetworkSession(session_params)); 133 http_transaction_factory_.reset( 134 new net::HttpNetworkLayer(network_session)); 135 proxy_script_fetcher_context_->set_http_transaction_factory( 136 http_transaction_factory_.get()); 137 // In-memory cookie store. 138 proxy_script_fetcher_context_->set_cookie_store( 139 new net::CookieMonster(NULL, NULL)); 140 } 141 }; 142 143 TEST_F(ConnectionTesterTest, RunAllTests) { 144 ASSERT_TRUE(test_server_.Start()); 145 146 ConnectionTester tester(&test_delegate_, proxy_script_fetcher_context_); 147 148 // Start the test suite on URL "echoall". 149 // TODO(eroman): Is this URL right? 150 tester.RunAllTests(test_server_.GetURL("echoall")); 151 152 // Wait for all the tests to complete. 153 MessageLoop::current()->Run(); 154 155 const int kNumExperiments = 156 ConnectionTester::PROXY_EXPERIMENT_COUNT * 157 ConnectionTester::HOST_RESOLVER_EXPERIMENT_COUNT; 158 159 EXPECT_EQ(1, test_delegate_.start_connection_test_suite_count()); 160 EXPECT_EQ(kNumExperiments, 161 test_delegate_.start_connection_test_experiment_count()); 162 EXPECT_EQ(kNumExperiments, 163 test_delegate_.completed_connection_test_experiment_count()); 164 EXPECT_EQ(1, test_delegate_.completed_connection_test_suite_count()); 165 } 166 167 TEST_F(ConnectionTesterTest, DeleteWhileInProgress) { 168 ASSERT_TRUE(test_server_.Start()); 169 170 scoped_ptr<ConnectionTester> tester( 171 new ConnectionTester(&test_delegate_, proxy_script_fetcher_context_)); 172 173 // Start the test suite on URL "echoall". 174 // TODO(eroman): Is this URL right? 175 tester->RunAllTests(test_server_.GetURL("echoall")); 176 177 MessageLoop::current()->RunAllPending(); 178 179 EXPECT_EQ(1, test_delegate_.start_connection_test_suite_count()); 180 EXPECT_EQ(1, test_delegate_.start_connection_test_experiment_count()); 181 EXPECT_EQ(0, test_delegate_.completed_connection_test_experiment_count()); 182 EXPECT_EQ(0, test_delegate_.completed_connection_test_suite_count()); 183 184 // Delete the ConnectionTester while it is in progress. 185 tester.reset(); 186 187 // Drain the tasks on the message loop. 188 // 189 // Note that we cannot simply stop the message loop, since that will delete 190 // any pending tasks instead of running them. This causes a problem with 191 // net::ClientSocketPoolBaseHelper, since the "Group" holds a pointer 192 // |backup_task| that it will try to deref during the destructor, but 193 // depending on the order that pending tasks were deleted in, it might 194 // already be invalid! See http://crbug.com/43291. 195 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); 196 MessageLoop::current()->Run(); 197 } 198 199 } // namespace 200