1// Copyright (c) 2012 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 <vector>
6
7#include "base/basictypes.h"
8#include "base/compiler_specific.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/stl_util.h"
11#include "net/base/capturing_net_log.h"
12#include "net/base/net_log_unittest.h"
13#include "net/base/test_completion_callback.h"
14#include "net/cert/mock_cert_verifier.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_stream.h"
21#include "net/http/http_stream_factory.h"
22#include "net/http/http_transaction_test_util.h"
23#include "net/http/transport_security_state.h"
24#include "net/proxy/proxy_config_service_fixed.h"
25#include "net/proxy/proxy_resolver.h"
26#include "net/proxy/proxy_service.h"
27#include "net/quic/crypto/quic_decrypter.h"
28#include "net/quic/crypto/quic_encrypter.h"
29#include "net/quic/quic_framer.h"
30#include "net/quic/quic_http_utils.h"
31#include "net/quic/test_tools/crypto_test_utils.h"
32#include "net/quic/test_tools/mock_clock.h"
33#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
34#include "net/quic/test_tools/mock_random.h"
35#include "net/quic/test_tools/quic_test_packet_maker.h"
36#include "net/quic/test_tools/quic_test_utils.h"
37#include "net/socket/client_socket_factory.h"
38#include "net/socket/mock_client_socket_pool_manager.h"
39#include "net/socket/socket_test_util.h"
40#include "net/socket/ssl_client_socket.h"
41#include "net/spdy/spdy_frame_builder.h"
42#include "net/spdy/spdy_framer.h"
43#include "net/ssl/ssl_config_service_defaults.h"
44#include "testing/gtest/include/gtest/gtest.h"
45#include "testing/platform_test.h"
46
47//-----------------------------------------------------------------------------
48
49namespace {
50
51// This is the expected return from a current server advertising QUIC.
52static const char kQuicAlternateProtocolHttpHeader[] =
53    "Alternate-Protocol: 80:quic\r\n\r\n";
54static const char kQuicAlternateProtocol50pctHttpHeader[] =
55    "Alternate-Protocol: 80:quic,p=.5\r\n\r\n";
56static const char kQuicAlternateProtocolHttpsHeader[] =
57    "Alternate-Protocol: 443:quic\r\n\r\n";
58
59}  // namespace
60
61namespace net {
62namespace test {
63
64// Helper class to encapsulate MockReads and MockWrites for QUIC.
65// Simplify ownership issues and the interaction with the MockSocketFactory.
66class MockQuicData {
67 public:
68  ~MockQuicData() {
69    STLDeleteElements(&packets_);
70  }
71
72  void AddRead(scoped_ptr<QuicEncryptedPacket> packet) {
73    reads_.push_back(MockRead(SYNCHRONOUS, packet->data(), packet->length(),
74                              sequence_number_++));
75    packets_.push_back(packet.release());
76  }
77
78  void AddRead(IoMode mode, int rv) {
79    reads_.push_back(MockRead(mode, rv));
80  }
81
82  void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
83    writes_.push_back(MockWrite(SYNCHRONOUS, packet->data(), packet->length(),
84                                sequence_number_++));
85    packets_.push_back(packet.release());
86  }
87
88  void AddDelayedSocketDataToFactory(MockClientSocketFactory* factory,
89                                     size_t delay) {
90    MockRead* reads = reads_.empty() ? NULL  : &reads_[0];
91    MockWrite* writes = writes_.empty() ? NULL  : &writes_[0];
92    socket_data_.reset(new DelayedSocketData(
93        delay, reads, reads_.size(), writes, writes_.size()));
94    factory->AddSocketDataProvider(socket_data_.get());
95  }
96
97 private:
98  std::vector<QuicEncryptedPacket*> packets_;
99  std::vector<MockWrite> writes_;
100  std::vector<MockRead> reads_;
101  size_t sequence_number_;
102  scoped_ptr<SocketDataProvider> socket_data_;
103};
104
105class QuicNetworkTransactionTest
106    : public PlatformTest,
107      public ::testing::WithParamInterface<QuicVersion> {
108 protected:
109  QuicNetworkTransactionTest()
110      : clock_(new MockClock),
111        maker_(GetParam(), 0, clock_),
112        ssl_config_service_(new SSLConfigServiceDefaults),
113        proxy_service_(ProxyService::CreateDirect()),
114        auth_handler_factory_(
115            HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
116        random_generator_(0),
117        hanging_data_(NULL, 0, NULL, 0) {
118    request_.method = "GET";
119    request_.url = GURL("http://www.google.com/");
120    request_.load_flags = 0;
121    clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
122  }
123
124  virtual void SetUp() {
125    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
126    base::MessageLoop::current()->RunUntilIdle();
127  }
128
129  virtual void TearDown() {
130    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
131    // Empty the current queue.
132    base::MessageLoop::current()->RunUntilIdle();
133    PlatformTest::TearDown();
134    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
135    base::MessageLoop::current()->RunUntilIdle();
136  }
137
138  scoped_ptr<QuicEncryptedPacket> ConstructConnectionClosePacket(
139      QuicPacketSequenceNumber num) {
140    return maker_.MakeConnectionClosePacket(num);
141  }
142
143  scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
144      QuicPacketSequenceNumber largest_received,
145      QuicPacketSequenceNumber least_unacked) {
146    return maker_.MakeAckPacket(2, largest_received, least_unacked, true);
147  }
148
149  SpdyHeaderBlock GetRequestHeaders(const std::string& method,
150                                    const std::string& scheme,
151                                    const std::string& path) {
152    return maker_.GetRequestHeaders(method, scheme, path);
153  }
154
155  SpdyHeaderBlock GetResponseHeaders(const std::string& status) {
156    return maker_.GetResponseHeaders(status);
157  }
158
159  scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
160      QuicPacketSequenceNumber sequence_number,
161      QuicStreamId stream_id,
162      bool should_include_version,
163      bool fin,
164      QuicStreamOffset offset,
165      base::StringPiece data) {
166    return maker_.MakeDataPacket(
167        sequence_number, stream_id, should_include_version, fin, offset, data);
168  }
169
170  scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
171      QuicPacketSequenceNumber sequence_number,
172      QuicStreamId stream_id,
173      bool should_include_version,
174      bool fin,
175      const SpdyHeaderBlock& headers) {
176    return maker_.MakeRequestHeadersPacket(
177        sequence_number, stream_id, should_include_version, fin, headers);
178  }
179
180  scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
181      QuicPacketSequenceNumber sequence_number,
182      QuicStreamId stream_id,
183      bool should_include_version,
184      bool fin,
185      const SpdyHeaderBlock& headers) {
186    return maker_.MakeResponseHeadersPacket(
187        sequence_number, stream_id, should_include_version, fin, headers);
188  }
189
190  void CreateSession() {
191    CreateSessionWithFactory(&socket_factory_, false);
192  }
193
194  void CreateSessionWithNextProtos() {
195    CreateSessionWithFactory(&socket_factory_, true);
196  }
197
198  // If |use_next_protos| is true, enables SPDY and QUIC.
199  void CreateSessionWithFactory(ClientSocketFactory* socket_factory,
200                                bool use_next_protos) {
201    params_.enable_quic = true;
202    params_.quic_clock = clock_;
203    params_.quic_random = &random_generator_;
204    params_.client_socket_factory = socket_factory;
205    params_.quic_crypto_client_stream_factory = &crypto_client_stream_factory_;
206    params_.host_resolver = &host_resolver_;
207    params_.cert_verifier = &cert_verifier_;
208    params_.transport_security_state = &transport_security_state_;
209    params_.proxy_service = proxy_service_.get();
210    params_.ssl_config_service = ssl_config_service_.get();
211    params_.http_auth_handler_factory = auth_handler_factory_.get();
212    params_.http_server_properties = http_server_properties.GetWeakPtr();
213    params_.quic_supported_versions = SupportedVersions(GetParam());
214
215    if (use_next_protos) {
216      params_.use_alternate_protocols = true;
217      params_.next_protos = NextProtosSpdy3();
218    }
219
220    session_ = new HttpNetworkSession(params_);
221    session_->quic_stream_factory()->set_require_confirmation(false);
222  }
223
224  void CheckWasQuicResponse(const scoped_ptr<HttpNetworkTransaction>& trans) {
225    const HttpResponseInfo* response = trans->GetResponseInfo();
226    ASSERT_TRUE(response != NULL);
227    ASSERT_TRUE(response->headers.get() != NULL);
228    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
229    EXPECT_TRUE(response->was_fetched_via_spdy);
230    EXPECT_TRUE(response->was_npn_negotiated);
231    EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3,
232              response->connection_info);
233  }
234
235  void CheckWasHttpResponse(const scoped_ptr<HttpNetworkTransaction>& trans) {
236    const HttpResponseInfo* response = trans->GetResponseInfo();
237    ASSERT_TRUE(response != NULL);
238    ASSERT_TRUE(response->headers.get() != NULL);
239    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
240    EXPECT_FALSE(response->was_fetched_via_spdy);
241    EXPECT_FALSE(response->was_npn_negotiated);
242    EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
243              response->connection_info);
244  }
245
246  void CheckResponseData(HttpNetworkTransaction* trans,
247                         const std::string& expected) {
248    std::string response_data;
249    ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
250    EXPECT_EQ(expected, response_data);
251  }
252
253  void RunTransaction(HttpNetworkTransaction* trans) {
254    TestCompletionCallback callback;
255    int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
256    EXPECT_EQ(ERR_IO_PENDING, rv);
257    EXPECT_EQ(OK, callback.WaitForResult());
258  }
259
260  void SendRequestAndExpectHttpResponse(const std::string& expected) {
261    scoped_ptr<HttpNetworkTransaction> trans(
262        new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
263    RunTransaction(trans.get());
264    CheckWasHttpResponse(trans);
265    CheckResponseData(trans.get(), expected);
266  }
267
268  void SendRequestAndExpectQuicResponse(const std::string& expected) {
269    scoped_ptr<HttpNetworkTransaction> trans(
270        new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
271    RunTransaction(trans.get());
272    CheckWasQuicResponse(trans);
273    CheckResponseData(trans.get(), expected);
274  }
275
276  void AddQuicAlternateProtocolMapping(
277      MockCryptoClientStream::HandshakeMode handshake_mode) {
278    crypto_client_stream_factory_.set_handshake_mode(handshake_mode);
279    session_->http_server_properties()->SetAlternateProtocol(
280        HostPortPair::FromURL(request_.url), 80, QUIC, 1);
281  }
282
283  void ExpectBrokenAlternateProtocolMapping() {
284    ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol(
285        HostPortPair::FromURL(request_.url)));
286    const AlternateProtocolInfo alternate =
287        session_->http_server_properties()->GetAlternateProtocol(
288            HostPortPair::FromURL(request_.url));
289    EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
290  }
291
292  void ExpectQuicAlternateProtocolMapping() {
293    ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol(
294        HostPortPair::FromURL(request_.url)));
295    const AlternateProtocolInfo alternate =
296        session_->http_server_properties()->GetAlternateProtocol(
297            HostPortPair::FromURL(request_.url));
298    EXPECT_EQ(QUIC, alternate.protocol);
299  }
300
301  void AddHangingNonAlternateProtocolSocketData() {
302    MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
303    hanging_data_.set_connect_data(hanging_connect);
304    socket_factory_.AddSocketDataProvider(&hanging_data_);
305  }
306
307  MockClock* clock_;  // Owned by QuicStreamFactory after CreateSession.
308  QuicTestPacketMaker maker_;
309  scoped_refptr<HttpNetworkSession> session_;
310  MockClientSocketFactory socket_factory_;
311  MockCryptoClientStreamFactory crypto_client_stream_factory_;
312  MockHostResolver host_resolver_;
313  MockCertVerifier cert_verifier_;
314  TransportSecurityState transport_security_state_;
315  scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
316  scoped_ptr<ProxyService> proxy_service_;
317  scoped_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
318  MockRandom random_generator_;
319  HttpServerPropertiesImpl http_server_properties;
320  HttpNetworkSession::Params params_;
321  HttpRequestInfo request_;
322  CapturingBoundNetLog net_log_;
323  StaticSocketDataProvider hanging_data_;
324};
325
326INSTANTIATE_TEST_CASE_P(Version, QuicNetworkTransactionTest,
327                        ::testing::ValuesIn(QuicSupportedVersions()));
328
329TEST_P(QuicNetworkTransactionTest, ForceQuic) {
330  params_.origin_to_force_quic_on =
331      HostPortPair::FromString("www.google.com:80");
332
333  MockQuicData mock_quic_data;
334  mock_quic_data.AddWrite(
335      ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
336                                    GetRequestHeaders("GET", "http", "/")));
337  mock_quic_data.AddRead(
338      ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
339                                     GetResponseHeaders("200 OK")));
340  mock_quic_data.AddRead(
341      ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
342  mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
343  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
344
345  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
346
347  // The non-alternate protocol job needs to hang in order to guarantee that
348  // the alternate-protocol job will "win".
349  AddHangingNonAlternateProtocolSocketData();
350
351  CreateSession();
352
353  SendRequestAndExpectQuicResponse("hello!");
354
355  // Check that the NetLog was filled reasonably.
356  net::CapturingNetLog::CapturedEntryList entries;
357  net_log_.GetEntries(&entries);
358  EXPECT_LT(0u, entries.size());
359
360  // Check that we logged a QUIC_SESSION_PACKET_RECEIVED.
361  int pos = net::ExpectLogContainsSomewhere(
362      entries, 0,
363      net::NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED,
364      net::NetLog::PHASE_NONE);
365  EXPECT_LT(0, pos);
366
367  // ... and also a TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED.
368  pos = net::ExpectLogContainsSomewhere(
369      entries, 0,
370      net::NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED,
371      net::NetLog::PHASE_NONE);
372  EXPECT_LT(0, pos);
373
374  std::string packet_sequence_number;
375  ASSERT_TRUE(entries[pos].GetStringValue(
376      "packet_sequence_number", &packet_sequence_number));
377  EXPECT_EQ("1", packet_sequence_number);
378
379  // ... and also a QUIC_SESSION_STREAM_FRAME_RECEIVED.
380  pos = net::ExpectLogContainsSomewhere(
381      entries, 0,
382      net::NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_RECEIVED,
383      net::NetLog::PHASE_NONE);
384  EXPECT_LT(0, pos);
385
386  int log_stream_id;
387  ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &log_stream_id));
388  EXPECT_EQ(3, log_stream_id);
389}
390
391TEST_P(QuicNetworkTransactionTest, QuicProxy) {
392  proxy_service_.reset(
393      ProxyService::CreateFixedFromPacResult("QUIC myproxy:70"));
394
395  MockQuicData mock_quic_data;
396  mock_quic_data.AddWrite(
397      ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
398                                    GetRequestHeaders("GET", "http", "/")));
399  mock_quic_data.AddRead(
400      ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
401                                     GetResponseHeaders("200 OK")));
402  mock_quic_data.AddRead(
403      ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
404  mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
405  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
406
407  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
408
409  // There is no need to set up an alternate protocol job, because
410  // no attempt will be made to speak to the proxy over TCP.
411
412  CreateSession();
413
414  SendRequestAndExpectQuicResponse("hello!");
415}
416
417TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
418  params_.origin_to_force_quic_on =
419      HostPortPair::FromString("www.google.com:80");
420
421  MockQuicData mock_quic_data;
422  mock_quic_data.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED);
423
424  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 0);
425
426  CreateSession();
427
428  scoped_ptr<HttpNetworkTransaction> trans(
429      new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
430  TestCompletionCallback callback;
431  int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
432  EXPECT_EQ(ERR_IO_PENDING, rv);
433  EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
434}
435
436TEST_P(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
437  // Attempt to "force" quic on 443, which will not be honored.
438  params_.origin_to_force_quic_on =
439      HostPortPair::FromString("www.google.com:443");
440
441  MockRead http_reads[] = {
442    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
443    MockRead("hello world"),
444    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
445    MockRead(ASYNC, OK)
446  };
447
448  StaticSocketDataProvider data(http_reads, arraysize(http_reads), NULL, 0);
449  socket_factory_.AddSocketDataProvider(&data);
450  SSLSocketDataProvider ssl(ASYNC, OK);
451  socket_factory_.AddSSLSocketDataProvider(&ssl);
452
453  CreateSession();
454
455  SendRequestAndExpectHttpResponse("hello world");
456}
457
458TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
459  MockRead http_reads[] = {
460    MockRead("HTTP/1.1 200 OK\r\n"),
461    MockRead(kQuicAlternateProtocolHttpHeader),
462    MockRead("hello world"),
463    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
464    MockRead(ASYNC, OK)
465  };
466
467  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
468                                     NULL, 0);
469  socket_factory_.AddSocketDataProvider(&http_data);
470
471  MockQuicData mock_quic_data;
472  mock_quic_data.AddWrite(
473      ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
474                                    GetRequestHeaders("GET", "http", "/")));
475  mock_quic_data.AddRead(
476      ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
477                                     GetResponseHeaders("200 OK")));
478  mock_quic_data.AddRead(
479      ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
480  mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
481  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
482
483  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
484
485  // The non-alternate protocol job needs to hang in order to guarantee that
486  // the alternate-protocol job will "win".
487  AddHangingNonAlternateProtocolSocketData();
488
489  CreateSessionWithNextProtos();
490
491  SendRequestAndExpectHttpResponse("hello world");
492  SendRequestAndExpectQuicResponse("hello!");
493}
494
495TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolProbabilityForQuic) {
496  MockRead http_reads[] = {
497    MockRead("HTTP/1.1 200 OK\r\n"),
498    MockRead(kQuicAlternateProtocol50pctHttpHeader),
499    MockRead("hello world"),
500    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
501    MockRead(ASYNC, OK)
502  };
503
504  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
505                                     NULL, 0);
506  socket_factory_.AddSocketDataProvider(&http_data);
507
508  MockQuicData mock_quic_data;
509  mock_quic_data.AddWrite(
510      ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
511                                    GetRequestHeaders("GET", "http", "/")));
512  mock_quic_data.AddRead(
513      ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
514                                     GetResponseHeaders("200 OK")));
515  mock_quic_data.AddRead(
516      ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
517  mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
518  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
519
520  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
521
522  // The non-alternate protocol job needs to hang in order to guarantee that
523  // the alternate-protocol job will "win".
524  AddHangingNonAlternateProtocolSocketData();
525
526  params_.alternate_protocol_probability_threshold = .25;
527  CreateSessionWithNextProtos();
528
529  SendRequestAndExpectHttpResponse("hello world");
530  SendRequestAndExpectQuicResponse("hello!");
531}
532
533TEST_P(QuicNetworkTransactionTest, DontUseAlternateProtocolProbabilityForQuic) {
534  MockRead http_reads[] = {
535    MockRead("HTTP/1.1 200 OK\r\n"),
536    MockRead(kQuicAlternateProtocol50pctHttpHeader),
537    MockRead("hello world"),
538    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
539    MockRead(ASYNC, OK)
540  };
541
542  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
543                                     NULL, 0);
544  socket_factory_.AddSocketDataProvider(&http_data);
545  socket_factory_.AddSocketDataProvider(&http_data);
546
547  params_.alternate_protocol_probability_threshold = .75;
548  CreateSessionWithNextProtos();
549
550  SendRequestAndExpectHttpResponse("hello world");
551  SendRequestAndExpectHttpResponse("hello world");
552}
553
554TEST_P(QuicNetworkTransactionTest,
555       DontUseAlternateProtocolWithBadProbabilityForQuic) {
556  MockRead http_reads[] = {
557    MockRead("HTTP/1.1 200 OK\r\n"),
558    MockRead("Alternate-Protocol: 443:quic,p=2\r\n\r\n"),
559    MockRead("hello world"),
560    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
561    MockRead(ASYNC, OK)
562  };
563
564  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
565                                     NULL, 0);
566  socket_factory_.AddSocketDataProvider(&http_data);
567  socket_factory_.AddSocketDataProvider(&http_data);
568
569  params_.alternate_protocol_probability_threshold = .75;
570  CreateSessionWithNextProtos();
571
572  SendRequestAndExpectHttpResponse("hello world");
573  SendRequestAndExpectHttpResponse("hello world");
574}
575
576TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
577  params_.origin_to_force_quic_on =
578      HostPortPair::FromString("www.google.com:443");
579
580  MockRead http_reads[] = {
581    MockRead("HTTP/1.1 200 OK\r\n"),
582    MockRead(kQuicAlternateProtocolHttpsHeader),
583    MockRead("hello world"),
584    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
585    MockRead(ASYNC, OK)
586  };
587
588  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
589                                     NULL, 0);
590  socket_factory_.AddSocketDataProvider(&http_data);
591
592  MockQuicData mock_quic_data;
593  mock_quic_data.AddWrite(
594      ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
595                                    GetRequestHeaders("GET", "http", "/")));
596  mock_quic_data.AddRead(
597      ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
598                                     GetResponseHeaders("200 OK")));
599  mock_quic_data.AddRead(
600      ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
601  mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
602  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
603
604  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
605
606  // The non-alternate protocol job needs to hang in order to guarantee that
607  // the alternate-protocol job will "win".
608  AddHangingNonAlternateProtocolSocketData();
609
610  CreateSessionWithNextProtos();
611
612  // TODO(rtenneti): Test QUIC over HTTPS, GetSSLInfo().
613  SendRequestAndExpectHttpResponse("hello world");
614}
615
616TEST_P(QuicNetworkTransactionTest, HungAlternateProtocol) {
617  crypto_client_stream_factory_.set_handshake_mode(
618      MockCryptoClientStream::COLD_START);
619
620  MockWrite http_writes[] = {
621    MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"),
622    MockWrite(SYNCHRONOUS, 1, "Host: www.google.com\r\n"),
623    MockWrite(SYNCHRONOUS, 2, "Connection: keep-alive\r\n\r\n")
624  };
625
626  MockRead http_reads[] = {
627    MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"),
628    MockRead(SYNCHRONOUS, 4, kQuicAlternateProtocolHttpHeader),
629    MockRead(SYNCHRONOUS, 5, "hello world"),
630    MockRead(SYNCHRONOUS, OK, 6)
631  };
632
633  DeterministicMockClientSocketFactory socket_factory;
634
635  DeterministicSocketData http_data(http_reads, arraysize(http_reads),
636                                    http_writes, arraysize(http_writes));
637  socket_factory.AddSocketDataProvider(&http_data);
638
639  // The QUIC transaction will not be allowed to complete.
640  MockWrite quic_writes[] = {
641    MockWrite(ASYNC, ERR_IO_PENDING, 0)
642  };
643  MockRead quic_reads[] = {
644    MockRead(ASYNC, ERR_IO_PENDING, 1),
645  };
646  DeterministicSocketData quic_data(quic_reads, arraysize(quic_reads),
647                                    quic_writes, arraysize(quic_writes));
648  socket_factory.AddSocketDataProvider(&quic_data);
649
650  // The HTTP transaction will complete.
651  DeterministicSocketData http_data2(http_reads, arraysize(http_reads),
652                                     http_writes, arraysize(http_writes));
653  socket_factory.AddSocketDataProvider(&http_data2);
654
655  CreateSessionWithFactory(&socket_factory, true);
656
657  // Run the first request.
658  http_data.StopAfter(arraysize(http_reads) + arraysize(http_writes));
659  SendRequestAndExpectHttpResponse("hello world");
660  ASSERT_TRUE(http_data.at_read_eof());
661  ASSERT_TRUE(http_data.at_write_eof());
662
663  // Now run the second request in which the QUIC socket hangs,
664  // and verify the the transaction continues over HTTP.
665  http_data2.StopAfter(arraysize(http_reads) + arraysize(http_writes));
666  SendRequestAndExpectHttpResponse("hello world");
667
668  ASSERT_TRUE(http_data2.at_read_eof());
669  ASSERT_TRUE(http_data2.at_write_eof());
670  ASSERT_TRUE(!quic_data.at_read_eof());
671  ASSERT_TRUE(!quic_data.at_write_eof());
672}
673
674TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
675  MockQuicData mock_quic_data;
676  mock_quic_data.AddWrite(
677      ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
678                                    GetRequestHeaders("GET", "http", "/")));
679  mock_quic_data.AddRead(
680      ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
681                                     GetResponseHeaders("200 OK")));
682  mock_quic_data.AddRead(
683      ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
684  mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
685  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
686
687  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
688
689  // The non-alternate protocol job needs to hang in order to guarantee that
690  // the alternate-protocol job will "win".
691  AddHangingNonAlternateProtocolSocketData();
692
693  CreateSessionWithNextProtos();
694  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
695  SendRequestAndExpectQuicResponse("hello!");
696}
697
698TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
699  MockQuicData mock_quic_data;
700  mock_quic_data.AddWrite(
701      ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
702                                    GetRequestHeaders("GET", "http", "/")));
703  mock_quic_data.AddRead(
704      ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
705                                     GetResponseHeaders("200 OK")));
706  mock_quic_data.AddRead(
707      ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
708  mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
709  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
710  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
711
712  // In order for a new QUIC session to be established via alternate-protocol
713  // without racing an HTTP connection, we need the host resolution to happen
714  // synchronously.
715  host_resolver_.set_synchronous_mode(true);
716  host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", "");
717  HostResolver::RequestInfo info(HostPortPair("www.google.com", 80));
718  AddressList address;
719  host_resolver_.Resolve(info,
720                         DEFAULT_PRIORITY,
721                         &address,
722                         CompletionCallback(),
723                         NULL,
724                         net_log_.bound());
725
726  CreateSessionWithNextProtos();
727  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
728  SendRequestAndExpectQuicResponse("hello!");
729}
730
731TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {
732  proxy_service_.reset(
733      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
734
735  // Since we are using a proxy, the QUIC job will not succeed.
736  MockWrite http_writes[] = {
737    MockWrite(SYNCHRONOUS, 0, "GET http://www.google.com/ HTTP/1.1\r\n"),
738    MockWrite(SYNCHRONOUS, 1, "Host: www.google.com\r\n"),
739    MockWrite(SYNCHRONOUS, 2, "Proxy-Connection: keep-alive\r\n\r\n")
740  };
741
742  MockRead http_reads[] = {
743    MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"),
744    MockRead(SYNCHRONOUS, 4, kQuicAlternateProtocolHttpHeader),
745    MockRead(SYNCHRONOUS, 5, "hello world"),
746    MockRead(SYNCHRONOUS, OK, 6)
747  };
748
749  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
750                                     http_writes, arraysize(http_writes));
751  socket_factory_.AddSocketDataProvider(&http_data);
752
753  // In order for a new QUIC session to be established via alternate-protocol
754  // without racing an HTTP connection, we need the host resolution to happen
755  // synchronously.
756  host_resolver_.set_synchronous_mode(true);
757  host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", "");
758  HostResolver::RequestInfo info(HostPortPair("www.google.com", 80));
759  AddressList address;
760  host_resolver_.Resolve(info,
761                         DEFAULT_PRIORITY,
762                         &address,
763                         CompletionCallback(),
764                         NULL,
765                         net_log_.bound());
766
767  CreateSessionWithNextProtos();
768  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
769  SendRequestAndExpectHttpResponse("hello world");
770}
771
772TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
773  MockQuicData mock_quic_data;
774  mock_quic_data.AddWrite(
775      ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
776                                    GetRequestHeaders("GET", "http", "/")));
777  mock_quic_data.AddRead(
778      ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
779                                     GetResponseHeaders("200 OK")));
780  mock_quic_data.AddRead(
781      ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
782  mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
783  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
784  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
785
786  // The non-alternate protocol job needs to hang in order to guarantee that
787  // the alternate-protocol job will "win".
788  AddHangingNonAlternateProtocolSocketData();
789
790  // In order for a new QUIC session to be established via alternate-protocol
791  // without racing an HTTP connection, we need the host resolution to happen
792  // synchronously.  Of course, even though QUIC *could* perform a 0-RTT
793  // connection to the the server, in this test we require confirmation
794  // before encrypting so the HTTP job will still start.
795  host_resolver_.set_synchronous_mode(true);
796  host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", "");
797  HostResolver::RequestInfo info(HostPortPair("www.google.com", 80));
798  AddressList address;
799  host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address,
800                         CompletionCallback(), NULL, net_log_.bound());
801
802  CreateSessionWithNextProtos();
803  session_->quic_stream_factory()->set_require_confirmation(true);
804  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
805
806  scoped_ptr<HttpNetworkTransaction> trans(
807      new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
808  TestCompletionCallback callback;
809  int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
810  EXPECT_EQ(ERR_IO_PENDING, rv);
811
812  crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
813      QuicSession::HANDSHAKE_CONFIRMED);
814  EXPECT_EQ(OK, callback.WaitForResult());
815}
816
817TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
818  // Alternate-protocol job
819  scoped_ptr<QuicEncryptedPacket> close(ConstructConnectionClosePacket(1));
820  MockRead quic_reads[] = {
821    MockRead(ASYNC, close->data(), close->length()),
822    MockRead(ASYNC, OK),  // EOF
823  };
824  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
825                                     NULL, 0);
826  socket_factory_.AddSocketDataProvider(&quic_data);
827
828  // Main job which will succeed even though the alternate job fails.
829  MockRead http_reads[] = {
830    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
831    MockRead("hello from http"),
832    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
833    MockRead(ASYNC, OK)
834  };
835
836  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
837                                     NULL, 0);
838  socket_factory_.AddSocketDataProvider(&http_data);
839
840  CreateSessionWithNextProtos();
841  AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
842  SendRequestAndExpectHttpResponse("hello from http");
843  ExpectBrokenAlternateProtocolMapping();
844}
845
846TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
847  // Alternate-protocol job
848  MockRead quic_reads[] = {
849    MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
850  };
851  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
852                                     NULL, 0);
853  socket_factory_.AddSocketDataProvider(&quic_data);
854
855  // Main job which will succeed even though the alternate job fails.
856  MockRead http_reads[] = {
857    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
858    MockRead("hello from http"),
859    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
860    MockRead(ASYNC, OK)
861  };
862
863  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
864                                     NULL, 0);
865  socket_factory_.AddSocketDataProvider(&http_data);
866
867  CreateSessionWithNextProtos();
868
869  AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
870  SendRequestAndExpectHttpResponse("hello from http");
871  ExpectBrokenAlternateProtocolMapping();
872}
873
874TEST_P(QuicNetworkTransactionTest, NoBrokenAlternateProtocolIfTcpFails) {
875  // Alternate-protocol job will fail when the session attempts to read.
876  MockRead quic_reads[] = {
877    MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
878  };
879  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
880                                     NULL, 0);
881  socket_factory_.AddSocketDataProvider(&quic_data);
882
883  // Main job will also fail.
884  MockRead http_reads[] = {
885    MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
886  };
887
888  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
889                                     NULL, 0);
890  http_data.set_connect_data(MockConnect(ASYNC, ERR_SOCKET_NOT_CONNECTED));
891  socket_factory_.AddSocketDataProvider(&http_data);
892
893  CreateSessionWithNextProtos();
894
895  AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
896  scoped_ptr<HttpNetworkTransaction> trans(
897      new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
898  TestCompletionCallback callback;
899  int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
900  EXPECT_EQ(ERR_IO_PENDING, rv);
901  EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, callback.WaitForResult());
902  ExpectQuicAlternateProtocolMapping();
903}
904
905TEST_P(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
906  // Alternate-protocol job
907  MockRead quic_reads[] = {
908    MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
909  };
910  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
911                                     NULL, 0);
912  socket_factory_.AddSocketDataProvider(&quic_data);
913
914  AddHangingNonAlternateProtocolSocketData();
915
916  // Second Alternate-protocol job which will race with the TCP job.
917  StaticSocketDataProvider quic_data2(quic_reads, arraysize(quic_reads),
918                                      NULL, 0);
919  socket_factory_.AddSocketDataProvider(&quic_data2);
920
921  // Final job that will proceed when the QUIC job fails.
922  MockRead http_reads[] = {
923    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
924    MockRead("hello from http"),
925    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
926    MockRead(ASYNC, OK)
927  };
928
929  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
930                                     NULL, 0);
931  socket_factory_.AddSocketDataProvider(&http_data);
932
933  CreateSessionWithNextProtos();
934
935  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
936
937  SendRequestAndExpectHttpResponse("hello from http");
938
939  ExpectBrokenAlternateProtocolMapping();
940
941  EXPECT_TRUE(quic_data.at_read_eof());
942  EXPECT_TRUE(quic_data.at_write_eof());
943}
944
945TEST_P(QuicNetworkTransactionTest, DISABLED_HangingZeroRttFallback) {
946  // Alternate-protocol job
947  MockRead quic_reads[] = {
948    MockRead(ASYNC, ERR_IO_PENDING),
949  };
950  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
951                                     NULL, 0);
952  socket_factory_.AddSocketDataProvider(&quic_data);
953
954  // Main job that will proceed when the QUIC job fails.
955  MockRead http_reads[] = {
956    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
957    MockRead("hello from http"),
958    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
959    MockRead(ASYNC, OK)
960  };
961
962  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
963                                     NULL, 0);
964  socket_factory_.AddSocketDataProvider(&http_data);
965
966  CreateSessionWithNextProtos();
967
968  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
969
970  SendRequestAndExpectHttpResponse("hello from http");
971}
972
973TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolOnConnectFailure) {
974  // Alternate-protocol job will fail before creating a QUIC session.
975  StaticSocketDataProvider quic_data(NULL, 0, NULL, 0);
976  quic_data.set_connect_data(MockConnect(SYNCHRONOUS,
977                                         ERR_INTERNET_DISCONNECTED));
978  socket_factory_.AddSocketDataProvider(&quic_data);
979
980  // Main job which will succeed even though the alternate job fails.
981  MockRead http_reads[] = {
982    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
983    MockRead("hello from http"),
984    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
985    MockRead(ASYNC, OK)
986  };
987
988  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
989                                     NULL, 0);
990  socket_factory_.AddSocketDataProvider(&http_data);
991
992  CreateSessionWithNextProtos();
993  AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
994  SendRequestAndExpectHttpResponse("hello from http");
995
996  ExpectBrokenAlternateProtocolMapping();
997}
998
999TEST_P(QuicNetworkTransactionTest, ConnectionCloseDuringConnect) {
1000  MockQuicData mock_quic_data;
1001  mock_quic_data.AddRead(ConstructConnectionClosePacket(1));
1002  mock_quic_data.AddWrite(
1003      ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
1004                                    GetRequestHeaders("GET", "http", "/")));
1005  mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
1006  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 0);
1007
1008  // When the QUIC connection fails, we will try the request again over HTTP.
1009  MockRead http_reads[] = {
1010    MockRead("HTTP/1.1 200 OK\r\n"),
1011    MockRead(kQuicAlternateProtocolHttpHeader),
1012    MockRead("hello world"),
1013    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1014    MockRead(ASYNC, OK)
1015  };
1016
1017  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
1018                                     NULL, 0);
1019  socket_factory_.AddSocketDataProvider(&http_data);
1020
1021  // In order for a new QUIC session to be established via alternate-protocol
1022  // without racing an HTTP connection, we need the host resolution to happen
1023  // synchronously.
1024  host_resolver_.set_synchronous_mode(true);
1025  host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", "");
1026  HostResolver::RequestInfo info(HostPortPair("www.google.com", 80));
1027  AddressList address;
1028  host_resolver_.Resolve(info,
1029                         DEFAULT_PRIORITY,
1030                         &address,
1031                         CompletionCallback(),
1032                         NULL,
1033                         net_log_.bound());
1034
1035  CreateSessionWithNextProtos();
1036  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
1037  SendRequestAndExpectHttpResponse("hello world");
1038}
1039
1040}  // namespace test
1041}  // namespace net
1042