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_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