1 // Copyright 2013 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 "base/basictypes.h" 6 #include "base/compiler_specific.h" 7 #include "base/memory/scoped_ptr.h" 8 #include "base/stl_util.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "net/base/test_completion_callback.h" 11 #include "net/base/upload_bytes_element_reader.h" 12 #include "net/base/upload_data_stream.h" 13 #include "net/cert/mock_cert_verifier.h" 14 #include "net/dns/mapped_host_resolver.h" 15 #include "net/dns/mock_host_resolver.h" 16 #include "net/http/http_auth_handler_factory.h" 17 #include "net/http/http_network_session.h" 18 #include "net/http/http_network_transaction.h" 19 #include "net/http/http_server_properties_impl.h" 20 #include "net/http/http_transaction_test_util.h" 21 #include "net/http/transport_security_state.h" 22 #include "net/proxy/proxy_service.h" 23 #include "net/quic/test_tools/quic_test_utils.h" 24 #include "net/ssl/ssl_config_service_defaults.h" 25 #include "net/tools/quic/quic_in_memory_cache.h" 26 #include "net/tools/quic/quic_server.h" 27 #include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h" 28 #include "net/tools/quic/test_tools/server_thread.h" 29 #include "testing/gtest/include/gtest/gtest.h" 30 #include "testing/platform_test.h" 31 32 using base::StringPiece; 33 using net::tools::QuicInMemoryCache; 34 using net::tools::QuicServer; 35 using net::tools::test::QuicInMemoryCachePeer; 36 using net::tools::test::ServerThread; 37 38 namespace net { 39 namespace test { 40 41 namespace { 42 43 const char kResponseBody[] = "some arbitrary response body"; 44 45 // Factory for creating HttpTransactions, used by TestTransactionConsumer. 46 class TestTransactionFactory : public HttpTransactionFactory { 47 public: 48 TestTransactionFactory(const HttpNetworkSession::Params& params) 49 : session_(new HttpNetworkSession(params)) {} 50 51 virtual ~TestTransactionFactory() { 52 } 53 54 // HttpTransactionFactory methods 55 virtual int CreateTransaction(RequestPriority priority, 56 scoped_ptr<HttpTransaction>* trans) OVERRIDE { 57 trans->reset(new HttpNetworkTransaction(priority, session_)); 58 return OK; 59 } 60 61 virtual HttpCache* GetCache() OVERRIDE { 62 return NULL; 63 } 64 65 virtual HttpNetworkSession* GetSession() OVERRIDE { 66 return session_; 67 }; 68 69 private: 70 scoped_refptr<HttpNetworkSession> session_; 71 }; 72 73 } // namespace 74 75 class QuicEndToEndTest : public PlatformTest { 76 protected: 77 QuicEndToEndTest() 78 : host_resolver_impl_(CreateResolverImpl()), 79 host_resolver_(host_resolver_impl_.PassAs<HostResolver>()), 80 ssl_config_service_(new SSLConfigServiceDefaults), 81 proxy_service_(ProxyService::CreateDirect()), 82 auth_handler_factory_( 83 HttpAuthHandlerFactory::CreateDefault(&host_resolver_)), 84 strike_register_no_startup_period_(false) { 85 request_.method = "GET"; 86 request_.url = GURL("http://www.google.com/"); 87 request_.load_flags = 0; 88 89 params_.enable_quic = true; 90 params_.quic_clock = NULL; 91 params_.quic_random = NULL; 92 params_.host_resolver = &host_resolver_; 93 params_.cert_verifier = &cert_verifier_; 94 params_.transport_security_state = &transport_security_state_; 95 params_.proxy_service = proxy_service_.get(); 96 params_.ssl_config_service = ssl_config_service_.get(); 97 params_.http_auth_handler_factory = auth_handler_factory_.get(); 98 params_.http_server_properties = http_server_properties.GetWeakPtr(); 99 } 100 101 // Creates a mock host resolver in which www.google.com 102 // resolves to localhost. 103 static MockHostResolver* CreateResolverImpl() { 104 MockHostResolver* resolver = new MockHostResolver(); 105 resolver->rules()->AddRule("www.google.com", "127.0.0.1"); 106 return resolver; 107 } 108 109 virtual void SetUp() { 110 QuicInMemoryCachePeer::ResetForTests(); 111 StartServer(); 112 113 // Use a mapped host resolver so that request for www.google.com (port 80) 114 // reach the server running on localhost. 115 std::string map_rule = "MAP www.google.com www.google.com:" + 116 base::IntToString(server_thread_->GetPort()); 117 EXPECT_TRUE(host_resolver_.AddRuleFromString(map_rule)); 118 119 // To simplify the test, and avoid the race with the HTTP request, we force 120 // QUIC for these requests. 121 params_.origin_to_force_quic_on = 122 HostPortPair::FromString("www.google.com:80"); 123 124 transaction_factory_.reset(new TestTransactionFactory(params_)); 125 } 126 127 virtual void TearDown() { 128 StopServer(); 129 QuicInMemoryCachePeer::ResetForTests(); 130 } 131 132 // Starts the QUIC server listening on a random port. 133 void StartServer() { 134 net::IPAddressNumber ip; 135 CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip)); 136 server_address_ = IPEndPoint(ip, 0); 137 server_config_.SetDefaults(); 138 server_config_.SetInitialFlowControlWindowToSend( 139 kInitialSessionFlowControlWindowForTest); 140 server_config_.SetInitialStreamFlowControlWindowToSend( 141 kInitialStreamFlowControlWindowForTest); 142 server_config_.SetInitialSessionFlowControlWindowToSend( 143 kInitialSessionFlowControlWindowForTest); 144 server_thread_.reset(new ServerThread( 145 new QuicServer(server_config_, QuicSupportedVersions()), 146 server_address_, 147 strike_register_no_startup_period_)); 148 server_thread_->Initialize(); 149 server_address_ = IPEndPoint(server_address_.address(), 150 server_thread_->GetPort()); 151 server_thread_->Start(); 152 server_started_ = true; 153 } 154 155 // Stops the QUIC server. 156 void StopServer() { 157 if (!server_started_) { 158 return; 159 } 160 if (server_thread_.get()) { 161 server_thread_->Quit(); 162 server_thread_->Join(); 163 } 164 } 165 166 // Adds an entry to the cache used by the QUIC server to serve 167 // responses. 168 void AddToCache(const StringPiece& method, 169 const StringPiece& path, 170 const StringPiece& version, 171 const StringPiece& response_code, 172 const StringPiece& response_detail, 173 const StringPiece& body) { 174 QuicInMemoryCache::GetInstance()->AddSimpleResponse( 175 method, path, version, response_code, response_detail, body); 176 } 177 178 // Populates |request_body_| with |length_| ASCII bytes. 179 void GenerateBody(size_t length) { 180 request_body_.clear(); 181 request_body_.reserve(length); 182 for (size_t i = 0; i < length; ++i) { 183 request_body_.append(1, static_cast<char>(32 + i % (126 - 32))); 184 } 185 } 186 187 // Initializes |request_| for a post of |length| bytes. 188 void InitializePostRequest(size_t length) { 189 GenerateBody(length); 190 ScopedVector<UploadElementReader> element_readers; 191 element_readers.push_back( 192 new UploadBytesElementReader(request_body_.data(), 193 request_body_.length())); 194 upload_data_stream_.reset(new UploadDataStream(element_readers.Pass(), 0)); 195 request_.method = "POST"; 196 request_.url = GURL("http://www.google.com/"); 197 request_.upload_data_stream = upload_data_stream_.get(); 198 ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback())); 199 } 200 201 // Checks that |consumer| completed and received |status_line| and |body|. 202 void CheckResponse(const TestTransactionConsumer& consumer, 203 const std::string& status_line, 204 const std::string& body) { 205 ASSERT_TRUE(consumer.is_done()); 206 EXPECT_EQ(OK, consumer.error()); 207 EXPECT_EQ(status_line, 208 consumer.response_info()->headers->GetStatusLine()); 209 EXPECT_EQ(body, consumer.content()); 210 } 211 212 scoped_ptr<MockHostResolver> host_resolver_impl_; 213 MappedHostResolver host_resolver_; 214 MockCertVerifier cert_verifier_; 215 TransportSecurityState transport_security_state_; 216 scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_; 217 scoped_ptr<ProxyService> proxy_service_; 218 scoped_ptr<HttpAuthHandlerFactory> auth_handler_factory_; 219 HttpServerPropertiesImpl http_server_properties; 220 HttpNetworkSession::Params params_; 221 scoped_ptr<TestTransactionFactory> transaction_factory_; 222 HttpRequestInfo request_; 223 std::string request_body_; 224 scoped_ptr<UploadDataStream> upload_data_stream_; 225 scoped_ptr<ServerThread> server_thread_; 226 IPEndPoint server_address_; 227 std::string server_hostname_; 228 QuicConfig server_config_; 229 bool server_started_; 230 bool strike_register_no_startup_period_; 231 }; 232 233 TEST_F(QuicEndToEndTest, LargeGetWithNoPacketLoss) { 234 std::string response(10 * 1024, 'x'); 235 236 AddToCache("GET", request_.url.spec(), 237 "HTTP/1.1", "200", "OK", 238 response); 239 240 TestTransactionConsumer consumer(DEFAULT_PRIORITY, 241 transaction_factory_.get()); 242 consumer.Start(&request_, BoundNetLog()); 243 244 // Will terminate when the last consumer completes. 245 base::MessageLoop::current()->Run(); 246 247 CheckResponse(consumer, "HTTP/1.1 200 OK", response); 248 } 249 250 // http://crbug.com/307284 251 TEST_F(QuicEndToEndTest, DISABLED_LargePostWithNoPacketLoss) { 252 InitializePostRequest(10 * 1024 * 1024); 253 254 AddToCache("POST", request_.url.spec(), 255 "HTTP/1.1", "200", "OK", 256 kResponseBody); 257 258 TestTransactionConsumer consumer(DEFAULT_PRIORITY, 259 transaction_factory_.get()); 260 consumer.Start(&request_, BoundNetLog()); 261 262 // Will terminate when the last consumer completes. 263 base::MessageLoop::current()->Run(); 264 265 CheckResponse(consumer, "HTTP/1.1 200 OK", kResponseBody); 266 } 267 268 TEST_F(QuicEndToEndTest, LargePostWithPacketLoss) { 269 // FLAGS_fake_packet_loss_percentage = 30; 270 InitializePostRequest(1024 * 1024); 271 272 const char kResponseBody[] = "some really big response body"; 273 AddToCache("POST", request_.url.spec(), 274 "HTTP/1.1", "200", "OK", 275 kResponseBody); 276 277 TestTransactionConsumer consumer(DEFAULT_PRIORITY, 278 transaction_factory_.get()); 279 consumer.Start(&request_, BoundNetLog()); 280 281 // Will terminate when the last consumer completes. 282 base::MessageLoop::current()->Run(); 283 284 CheckResponse(consumer, "HTTP/1.1 200 OK", kResponseBody); 285 } 286 287 TEST_F(QuicEndToEndTest, UberTest) { 288 // FLAGS_fake_packet_loss_percentage = 30; 289 290 const char kResponseBody[] = "some really big response body"; 291 AddToCache("GET", request_.url.spec(), 292 "HTTP/1.1", "200", "OK", 293 kResponseBody); 294 295 std::vector<TestTransactionConsumer*> consumers; 296 size_t num_requests = 100; 297 for (size_t i = 0; i < num_requests; ++i) { 298 TestTransactionConsumer* consumer = 299 new TestTransactionConsumer(DEFAULT_PRIORITY, 300 transaction_factory_.get()); 301 consumers.push_back(consumer); 302 consumer->Start(&request_, BoundNetLog()); 303 } 304 305 // Will terminate when the last consumer completes. 306 base::MessageLoop::current()->Run(); 307 308 for (size_t i = 0; i < num_requests; ++i) { 309 CheckResponse(*consumers[i], "HTTP/1.1 200 OK", kResponseBody); 310 } 311 STLDeleteElements(&consumers); 312 } 313 314 } // namespace test 315 } // namespace net 316