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