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