Home | History | Annotate | Download | only in quic
      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