quic_end_to_end_unittest.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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
30extern int FLAGS_fake_packet_loss_percentage;
31
32using base::StringPiece;
33using net::tools::QuicInMemoryCache;
34using net::tools::test::QuicInMemoryCachePeer;
35using net::tools::test::ServerThread;
36
37namespace net {
38namespace test {
39
40namespace {
41
42const char kResponseBody[] = "some arbitrary response body";
43
44// Factory for creating HttpTransactions, used by TestTransactionConsumer.
45class 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
77class 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_->listening()->Wait();
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()->Signal();
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
228TEST_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
246TEST_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
263TEST_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
282TEST_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