Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_network_transaction_unittest.cc
index 137ceda..851371d 100644 (file)
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <vector>
+
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
@@ -30,6 +32,7 @@
 #include "net/quic/test_tools/mock_clock.h"
 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
 #include "net/quic/test_tools/mock_random.h"
+#include "net/quic/test_tools/quic_test_packet_maker.h"
 #include "net/quic/test_tools/quic_test_utils.h"
 #include "net/socket/client_socket_factory.h"
 #include "net/socket/mock_client_socket_pool_manager.h"
@@ -50,20 +53,65 @@ static const char kQuicAlternateProtocolHttpHeader[] =
     "Alternate-Protocol: 80:quic\r\n\r\n";
 static const char kQuicAlternateProtocolHttpsHeader[] =
     "Alternate-Protocol: 443:quic\r\n\r\n";
+
 }  // namespace
 
 namespace net {
 namespace test {
 
-class QuicNetworkTransactionTest : public PlatformTest {
+// Helper class to encapsulate MockReads and MockWrites for QUIC.
+// Simplify ownership issues and the interaction with the MockSocketFactory.
+class MockQuicData {
+ public:
+  ~MockQuicData() {
+    STLDeleteElements(&packets_);
+  }
+
+  void AddRead(scoped_ptr<QuicEncryptedPacket> packet) {
+    reads_.push_back(MockRead(SYNCHRONOUS, packet->data(), packet->length(),
+                              sequence_number_++));
+    packets_.push_back(packet.release());
+  }
+
+  void AddRead(IoMode mode, int rv) {
+    reads_.push_back(MockRead(mode, rv));
+  }
+
+  void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
+    writes_.push_back(MockWrite(SYNCHRONOUS, packet->data(), packet->length(),
+                                sequence_number_++));
+    packets_.push_back(packet.release());
+  }
+
+  void AddDelayedSocketDataToFactory(MockClientSocketFactory* factory,
+                                     size_t delay) {
+    MockRead* reads = reads_.empty() ? NULL  : &reads_[0];
+    MockWrite* writes = writes_.empty() ? NULL  : &writes_[0];
+    socket_data_.reset(new DelayedSocketData(
+        delay, reads, reads_.size(), writes, writes_.size()));
+    factory->AddSocketDataProvider(socket_data_.get());
+  }
+
+ private:
+  std::vector<QuicEncryptedPacket*> packets_;
+  std::vector<MockWrite> writes_;
+  std::vector<MockRead> reads_;
+  size_t sequence_number_;
+  scoped_ptr<SocketDataProvider> socket_data_;
+};
+
+class QuicNetworkTransactionTest
+    : public PlatformTest,
+      public testing::WithParamInterface<QuicVersion> {
  protected:
   QuicNetworkTransactionTest()
-      : clock_(new MockClock),
+      : maker_(GetParam(), 0),
+        clock_(new MockClock),
         ssl_config_service_(new SSLConfigServiceDefaults),
         proxy_service_(ProxyService::CreateDirect()),
-        compressor_(new QuicSpdyCompressor()),
         auth_handler_factory_(
             HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
+        random_generator_(0),
         hanging_data_(NULL, 0, NULL, 0) {
     request_.method = "GET";
     request_.url = GURL("http://www.google.com/");
@@ -89,134 +137,71 @@ class QuicNetworkTransactionTest : public PlatformTest {
   scoped_ptr<QuicEncryptedPacket> ConstructRstPacket(
       QuicPacketSequenceNumber num,
       QuicStreamId stream_id) {
-    QuicPacketHeader header;
-    header.public_header.guid = 0xDEADBEEF;
-    header.public_header.reset_flag = false;
-    header.public_header.version_flag = false;
-    header.public_header.sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
-    header.packet_sequence_number = num;
-    header.entropy_flag = false;
-    header.fec_flag = false;
-    header.fec_group = 0;
-
-    QuicRstStreamFrame rst(stream_id, QUIC_STREAM_NO_ERROR);
-    return scoped_ptr<QuicEncryptedPacket>(
-        ConstructPacket(header, QuicFrame(&rst)));
+    return maker_.MakeRstPacket(
+        num, false, stream_id, QUIC_STREAM_NO_ERROR);
   }
 
   scoped_ptr<QuicEncryptedPacket> ConstructConnectionClosePacket(
       QuicPacketSequenceNumber num) {
-    QuicPacketHeader header;
-    header.public_header.guid = 0xDEADBEEF;
-    header.public_header.reset_flag = false;
-    header.public_header.version_flag = false;
-    header.public_header.sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
-    header.packet_sequence_number = num;
-    header.entropy_flag = false;
-    header.fec_flag = false;
-    header.fec_group = 0;
-
-    QuicAckFrame ack_frame(0, QuicTime::Zero(), 0);
-    QuicConnectionCloseFrame close;
-    close.error_code = QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
-    close.error_details = "Time to panic!";
-    close.ack_frame = ack_frame;
-    return scoped_ptr<QuicEncryptedPacket>(
-        ConstructPacket(header, QuicFrame(&close)));
+    return maker_.MakeConnectionClosePacket(num);
   }
 
   scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
       QuicPacketSequenceNumber largest_received,
       QuicPacketSequenceNumber least_unacked) {
-    QuicPacketHeader header;
-    header.public_header.guid = 0xDEADBEEF;
-    header.public_header.reset_flag = false;
-    header.public_header.version_flag = false;
-    header.public_header.sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
-    header.packet_sequence_number = 2;
-    header.entropy_flag = false;
-    header.fec_flag = false;
-    header.fec_group = 0;
-
-    QuicAckFrame ack(largest_received, QuicTime::Zero(), least_unacked);
-
-    QuicCongestionFeedbackFrame feedback;
-    feedback.type = kTCP;
-    feedback.tcp.accumulated_number_of_lost_packets = 0;
-    feedback.tcp.receive_window = 256000;
-
-    QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
-    QuicFrames frames;
-    frames.push_back(QuicFrame(&ack));
-    frames.push_back(QuicFrame(&feedback));
-    scoped_ptr<QuicPacket> packet(
-        framer.BuildUnsizedDataPacket(header, frames).packet);
-    return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
-        ENCRYPTION_NONE, header.packet_sequence_number, *packet));
+    return maker_.MakeAckPacket(2, largest_received, least_unacked, true);
+  }
+
+  SpdyHeaderBlock GetRequestHeaders(const std::string& method,
+                                    const std::string& scheme,
+                                    const std::string& path) {
+    return maker_.GetRequestHeaders(method, scheme, path);
   }
 
   std::string GetRequestString(const std::string& method,
                                const std::string& scheme,
                                const std::string& path) {
-    SpdyHeaderBlock headers;
-    headers[":method"] = method;
-    headers[":host"] = "www.google.com";
-    headers[":path"] = path;
-    headers[":scheme"] = scheme;
-    headers[":version"] = "HTTP/1.1";
-    return SerializeHeaderBlock(headers);
+    return maker_.GetRequestString(method, scheme, path);
   }
 
-  std::string GetResponseString(const std::string& status,
-                                const std::string& body) {
-    SpdyHeaderBlock headers;
-    headers[":status"] = status;
-    headers[":version"] = "HTTP/1.1";
-    headers["content-type"] = "text/plain";
-    return compressor_->CompressHeaders(headers) + body;
+  SpdyHeaderBlock GetResponseHeaders(const std::string& status) {
+    return maker_.GetResponseHeaders(status);
   }
 
-  std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers) {
-    QuicSpdyCompressor compressor;
-    return compressor.CompressHeadersWithPriority(
-        ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY), headers);
+  std::string GetResponseString(const std::string& status,
+                                const std::string& body) {
+    return maker_.GetResponseString(status, body);
   }
 
-  // Returns a newly created packet to send kData on stream 1.
-  QuicEncryptedPacket* ConstructDataPacket(
+  scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
       QuicPacketSequenceNumber sequence_number,
       QuicStreamId stream_id,
       bool should_include_version,
       bool fin,
       QuicStreamOffset offset,
       base::StringPiece data) {
-    InitializeHeader(sequence_number, should_include_version);
-    QuicStreamFrame frame(stream_id, fin, offset, data);
-    return ConstructPacket(header_, QuicFrame(&frame)).release();
-  }
-
-  scoped_ptr<QuicEncryptedPacket> ConstructPacket(
-      const QuicPacketHeader& header,
-      const QuicFrame& frame) {
-    QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
-    QuicFrames frames;
-    frames.push_back(frame);
-    scoped_ptr<QuicPacket> packet(
-        framer.BuildUnsizedDataPacket(header, frames).packet);
-    return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
-        ENCRYPTION_NONE, header.packet_sequence_number, *packet));
-  }
-
-  void InitializeHeader(QuicPacketSequenceNumber sequence_number,
-                        bool should_include_version) {
-    header_.public_header.guid = random_generator_.RandUint64();
-    header_.public_header.reset_flag = false;
-    header_.public_header.version_flag = should_include_version;
-    header_.public_header.sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
-    header_.packet_sequence_number = sequence_number;
-    header_.fec_group = 0;
-    header_.entropy_flag = false;
-    header_.fec_flag = false;
+    return maker_.MakeDataPacket(
+        sequence_number, stream_id, should_include_version, fin, offset, data);
+  }
+
+  scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
+      QuicPacketSequenceNumber sequence_number,
+      QuicStreamId stream_id,
+      bool should_include_version,
+      bool fin,
+      const SpdyHeaderBlock& headers) {
+    return maker_.MakeRequestHeadersPacket(
+        sequence_number, stream_id, should_include_version, fin, headers);
+  }
+
+  scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
+      QuicPacketSequenceNumber sequence_number,
+      QuicStreamId stream_id,
+      bool should_include_version,
+      bool fin,
+      const SpdyHeaderBlock& headers) {
+    return maker_.MakeResponseHeadersPacket(
+        sequence_number, stream_id, should_include_version, fin, headers);
   }
 
   void CreateSession() {
@@ -236,6 +221,7 @@ class QuicNetworkTransactionTest : public PlatformTest {
     params_.ssl_config_service = ssl_config_service_.get();
     params_.http_auth_handler_factory = auth_handler_factory_.get();
     params_.http_server_properties = http_server_properties.GetWeakPtr();
+    params_.quic_supported_versions = SupportedVersions(GetParam());
 
     session_ = new HttpNetworkSession(params_);
     session_->quic_stream_factory()->set_require_confirmation(false);
@@ -315,7 +301,7 @@ class QuicNetworkTransactionTest : public PlatformTest {
     socket_factory_.AddSocketDataProvider(&hanging_data_);
   }
 
-  QuicPacketHeader header_;
+  QuicTestPacketMaker maker_;
   scoped_refptr<HttpNetworkSession> session_;
   MockClientSocketFactory socket_factory_;
   MockCryptoClientStreamFactory crypto_client_stream_factory_;
@@ -325,7 +311,6 @@ class QuicNetworkTransactionTest : public PlatformTest {
   TransportSecurityState transport_security_state_;
   scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
   scoped_ptr<ProxyService> proxy_service_;
-  scoped_ptr<QuicSpdyCompressor> compressor_;
   scoped_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
   MockRandom random_generator_;
   HttpServerPropertiesImpl http_server_properties;
@@ -335,35 +320,37 @@ class QuicNetworkTransactionTest : public PlatformTest {
   StaticSocketDataProvider hanging_data_;
 };
 
-TEST_F(QuicNetworkTransactionTest, ForceQuic) {
+INSTANTIATE_TEST_CASE_P(Version, QuicNetworkTransactionTest,
+                        ::testing::ValuesIn(QuicSupportedVersions()));
+
+TEST_P(QuicNetworkTransactionTest, ForceQuic) {
   params_.origin_to_force_quic_on =
       HostPortPair::FromString("www.google.com:80");
 
-  QuicStreamId stream_id = 3;
-  scoped_ptr<QuicEncryptedPacket> req(
-      ConstructDataPacket(1, stream_id, true, true, 0,
-                          GetRequestString("GET", "http", "/")));
-  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
-
-  MockWrite quic_writes[] = {
-    MockWrite(SYNCHRONOUS, req->data(), req->length()),
-    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
-  };
-
-  scoped_ptr<QuicEncryptedPacket> resp(
-      ConstructDataPacket(
-          1, stream_id, false, true, 0, GetResponseString("200 OK", "hello!")));
-  MockRead quic_reads[] = {
-    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
-    MockRead(ASYNC, OK),  // EOF
-  };
-
-  DelayedSocketData quic_data(
-      1,  // wait for one write to finish before reading.
-      quic_reads, arraysize(quic_reads),
-      quic_writes, arraysize(quic_writes));
+  QuicStreamId stream_id = GetParam() > QUIC_VERSION_12 ? 5 : 3;
+  MockQuicData mock_quic_data;
+  if (GetParam() > QUIC_VERSION_12) {
+    mock_quic_data.AddWrite(
+        ConstructRequestHeadersPacket(1, stream_id, true, true,
+                                      GetRequestHeaders("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructResponseHeadersPacket(1, stream_id, false, false,
+                                       GetResponseHeaders("200 OK")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(2, stream_id, false, true, 0, "hello!"));
+    mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+  } else {
+    mock_quic_data.AddWrite(
+        ConstructDataPacket(1, stream_id, true, true, 0,
+                            GetRequestString("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(1, stream_id, false, true, 0,
+                            GetResponseString("200 OK", "hello!")));
+    mock_quic_data.AddWrite(ConstructAckPacket(1, 0));
+  }
+  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
 
-  socket_factory_.AddSocketDataProvider(&quic_data);
+  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
 
   // The non-alternate protocol job needs to hang in order to guarantee that
   // the alternate-protocol job will "win".
@@ -406,19 +393,54 @@ TEST_F(QuicNetworkTransactionTest, ForceQuic) {
 
   int log_stream_id;
   ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &log_stream_id));
-  EXPECT_EQ(stream_id, static_cast<QuicStreamId>(log_stream_id));
+  EXPECT_EQ(3, log_stream_id);
 }
 
-TEST_F(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
+TEST_P(QuicNetworkTransactionTest, QuicProxy) {
+  proxy_service_.reset(
+      ProxyService::CreateFixedFromPacResult("QUIC myproxy:70"));
+
+  QuicStreamId stream_id = GetParam() > QUIC_VERSION_12 ? 5 : 3;
+  MockQuicData mock_quic_data;
+  if (GetParam() > QUIC_VERSION_12) {
+    mock_quic_data.AddWrite(
+        ConstructRequestHeadersPacket(1, stream_id, true, true,
+                                      GetRequestHeaders("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructResponseHeadersPacket(1, stream_id, false, false,
+                                       GetResponseHeaders("200 OK")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(2, stream_id, false, true, 0, "hello!"));
+    mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+  } else {
+    mock_quic_data.AddWrite(
+        ConstructDataPacket(1, stream_id, true, true, 0,
+                            GetRequestString("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(1, stream_id, false, true, 0,
+                            GetResponseString("200 OK", "hello!")));
+    mock_quic_data.AddWrite(ConstructAckPacket(1, 0));
+  }
+  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
+
+  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
+
+  // There is no need to set up an alternate protocol job, because
+  // no attempt will be made to speak to the proxy over TCP.
+
+  CreateSession();
+
+  SendRequestAndExpectQuicResponse("hello!");
+}
+
+TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
   params_.origin_to_force_quic_on =
       HostPortPair::FromString("www.google.com:80");
 
-  MockRead quic_reads[] = {
-    MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
-  };
-  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
-                                     NULL, 0);
-  socket_factory_.AddSocketDataProvider(&quic_data);
+  MockQuicData mock_quic_data;
+  mock_quic_data.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED);
+
+  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 0);
 
   CreateSession();
 
@@ -430,7 +452,7 @@ TEST_F(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
   EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
 }
 
-TEST_F(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
+TEST_P(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
   // Attempt to "force" quic on 443, which will not be honored.
   params_.origin_to_force_quic_on =
       HostPortPair::FromString("www.google.com:443");
@@ -452,7 +474,7 @@ TEST_F(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
   SendRequestAndExpectHttpResponse("hello world");
 }
 
-TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
+TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
   HttpStreamFactory::EnableNpnSpdy3();  // Enables QUIC too.
 
   MockRead http_reads[] = {
@@ -467,30 +489,30 @@ TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
                                      NULL, 0);
   socket_factory_.AddSocketDataProvider(&http_data);
 
-  scoped_ptr<QuicEncryptedPacket> req(
-      ConstructDataPacket(1, 3, true, true, 0,
-                          GetRequestString("GET", "http", "/")));
-  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
-
-  MockWrite quic_writes[] = {
-    MockWrite(SYNCHRONOUS, req->data(), req->length()),
-    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
-  };
-
-  scoped_ptr<QuicEncryptedPacket> resp(
-      ConstructDataPacket(
-          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
-  MockRead quic_reads[] = {
-    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
-    MockRead(ASYNC, OK),  // EOF
-  };
-
-  DelayedSocketData quic_data(
-      1,  // wait for one write to finish before reading.
-      quic_reads, arraysize(quic_reads),
-      quic_writes, arraysize(quic_writes));
+  QuicStreamId stream_id = GetParam() > QUIC_VERSION_12 ? 5 : 3;
+  MockQuicData mock_quic_data;
+  if (GetParam() > QUIC_VERSION_12) {
+    mock_quic_data.AddWrite(
+        ConstructRequestHeadersPacket(1, stream_id, true, true,
+                                      GetRequestHeaders("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructResponseHeadersPacket(1, stream_id, false, false,
+                                       GetResponseHeaders("200 OK")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(2, stream_id, false, true, 0, "hello!"));
+    mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+  } else {
+    mock_quic_data.AddWrite(
+        ConstructDataPacket(1, stream_id, true, true, 0,
+                            GetRequestString("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(1, stream_id, false, true, 0,
+                            GetResponseString("200 OK", "hello!")));
+    mock_quic_data.AddWrite(ConstructAckPacket(1, 0));
+  }
+  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
 
-  socket_factory_.AddSocketDataProvider(&quic_data);
+  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
 
   // The non-alternate protocol job needs to hang in order to guarantee that
   // the alternate-protocol job will "win".
@@ -502,7 +524,7 @@ TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
   SendRequestAndExpectQuicResponse("hello!");
 }
 
-TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
+TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
   params_.origin_to_force_quic_on =
       HostPortPair::FromString("www.google.com:443");
   params_.enable_quic_https = true;
@@ -520,30 +542,30 @@ TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
                                      NULL, 0);
   socket_factory_.AddSocketDataProvider(&http_data);
 
-  scoped_ptr<QuicEncryptedPacket> req(
-      ConstructDataPacket(1, 3, true, true, 0,
-                          GetRequestString("GET", "https", "/")));
-  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
-
-  MockWrite quic_writes[] = {
-    MockWrite(SYNCHRONOUS, req->data(), req->length()),
-    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
-  };
-
-  scoped_ptr<QuicEncryptedPacket> resp(
-      ConstructDataPacket(
-          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
-  MockRead quic_reads[] = {
-    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
-    MockRead(ASYNC, OK),  // EOF
-  };
-
-  DelayedSocketData quic_data(
-      1,  // wait for one write to finish before reading.
-      quic_reads, arraysize(quic_reads),
-      quic_writes, arraysize(quic_writes));
+  QuicStreamId stream_id = GetParam() > QUIC_VERSION_12 ? 5 : 3;
+  MockQuicData mock_quic_data;
+  if (GetParam() > QUIC_VERSION_12) {
+    mock_quic_data.AddWrite(
+        ConstructRequestHeadersPacket(1, stream_id, true, true,
+                                      GetRequestHeaders("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructResponseHeadersPacket(1, stream_id, false, false,
+                                       GetResponseHeaders("200 OK")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(2, stream_id, false, true, 0, "hello!"));
+    mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+  } else {
+    mock_quic_data.AddWrite(
+        ConstructDataPacket(1, stream_id, true, true, 0,
+                            GetRequestString("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(1, stream_id, false, true, 0,
+                            GetResponseString("200 OK", "hello!")));
+    mock_quic_data.AddWrite(ConstructAckPacket(1, 0));
+  }
+  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
 
-  socket_factory_.AddSocketDataProvider(&quic_data);
+  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
 
   // The non-alternate protocol job needs to hang in order to guarantee that
   // the alternate-protocol job will "win".
@@ -555,7 +577,7 @@ TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
   SendRequestAndExpectHttpResponse("hello world");
 }
 
-TEST_F(QuicNetworkTransactionTest, HungAlternateProtocol) {
+TEST_P(QuicNetworkTransactionTest, HungAlternateProtocol) {
   HttpStreamFactory::EnableNpnSpdy3();  // Enables QUIC too.
   crypto_client_stream_factory_.set_handshake_mode(
       MockCryptoClientStream::COLD_START);
@@ -614,33 +636,33 @@ TEST_F(QuicNetworkTransactionTest, HungAlternateProtocol) {
   ASSERT_TRUE(!quic_data.at_write_eof());
 }
 
-TEST_F(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
+TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
   HttpStreamFactory::EnableNpnSpdy3();  // Enables QUIC too.
 
-  scoped_ptr<QuicEncryptedPacket> req(
-      ConstructDataPacket(1, 3, true, true, 0,
-                          GetRequestString("GET", "http", "/")));
-  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
-
-  MockWrite quic_writes[] = {
-    MockWrite(SYNCHRONOUS, req->data(), req->length()),
-    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
-  };
-
-  scoped_ptr<QuicEncryptedPacket> resp(
-      ConstructDataPacket(
-          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
-  MockRead quic_reads[] = {
-    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
-    MockRead(ASYNC, OK),  // EOF
-  };
+  QuicStreamId stream_id = GetParam() > QUIC_VERSION_12 ? 5 : 3;
+  MockQuicData mock_quic_data;
+  if (GetParam() > QUIC_VERSION_12) {
+    mock_quic_data.AddWrite(
+        ConstructRequestHeadersPacket(1, stream_id, true, true,
+                                      GetRequestHeaders("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructResponseHeadersPacket(1, stream_id, false, false,
+                                       GetResponseHeaders("200 OK")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(2, stream_id, false, true, 0, "hello!"));
+    mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+  } else {
+    mock_quic_data.AddWrite(
+        ConstructDataPacket(1, stream_id, true, true, 0,
+                            GetRequestString("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(1, stream_id, false, true, 0,
+                            GetResponseString("200 OK", "hello!")));
+    mock_quic_data.AddWrite(ConstructAckPacket(1, 0));
+  }
+  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
 
-  DelayedSocketData quic_data(
-      1,  // wait for one write to finish before reading.
-      quic_reads, arraysize(quic_reads),
-      quic_writes, arraysize(quic_writes));
-
-  socket_factory_.AddSocketDataProvider(&quic_data);
+  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
 
   // The non-alternate protocol job needs to hang in order to guarantee that
   // the alternate-protocol job will "win".
@@ -651,33 +673,32 @@ TEST_F(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
   SendRequestAndExpectQuicResponse("hello!");
 }
 
-TEST_F(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
+TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
   HttpStreamFactory::EnableNpnSpdy3();  // Enables QUIC too.
 
-  scoped_ptr<QuicEncryptedPacket> req(
-      ConstructDataPacket(1, 3, true, true, 0,
-                          GetRequestString("GET", "http", "/")));
-  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
-
-  MockWrite quic_writes[] = {
-    MockWrite(SYNCHRONOUS, req->data(), req->length()),
-    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
-  };
-
-  scoped_ptr<QuicEncryptedPacket> resp(
-      ConstructDataPacket(
-          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
-  MockRead quic_reads[] = {
-    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
-    MockRead(ASYNC, OK),  // EOF
-  };
-
-  DelayedSocketData quic_data(
-      1,  // wait for one write to finish before reading.
-      quic_reads, arraysize(quic_reads),
-      quic_writes, arraysize(quic_writes));
-
-  socket_factory_.AddSocketDataProvider(&quic_data);
+  QuicStreamId stream_id = GetParam() > QUIC_VERSION_12 ? 5 : 3;
+  MockQuicData mock_quic_data;
+  if (GetParam() > QUIC_VERSION_12) {
+    mock_quic_data.AddWrite(
+        ConstructRequestHeadersPacket(1, stream_id, true, true,
+                                      GetRequestHeaders("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructResponseHeadersPacket(1, stream_id, false, false,
+                                       GetResponseHeaders("200 OK")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(2, stream_id, false, true, 0, "hello!"));
+    mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+  } else {
+    mock_quic_data.AddWrite(
+        ConstructDataPacket(1, stream_id, true, true, 0,
+                            GetRequestString("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(1, stream_id, false, true, 0,
+                            GetResponseString("200 OK", "hello!")));
+    mock_quic_data.AddWrite(ConstructAckPacket(1, 0));
+  }
+  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
+  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
 
   // In order for a new QUIC session to be established via alternate-protocol
   // without racing an HTTP connection, we need the host resolution to happen
@@ -698,33 +719,32 @@ TEST_F(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
   SendRequestAndExpectQuicResponse("hello!");
 }
 
-TEST_F(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
+TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
   HttpStreamFactory::EnableNpnSpdy3();  // Enables QUIC too.
 
-  scoped_ptr<QuicEncryptedPacket> req(
-      ConstructDataPacket(1, 3, true, true, 0,
-                          GetRequestString("GET", "http", "/")));
-  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
-
-  MockWrite quic_writes[] = {
-    MockWrite(SYNCHRONOUS, req->data(), req->length()),
-    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
-  };
-
-  scoped_ptr<QuicEncryptedPacket> resp(
-      ConstructDataPacket(
-          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
-  MockRead quic_reads[] = {
-    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
-    MockRead(ASYNC, OK),  // EOF
-  };
-
-  DelayedSocketData quic_data(
-      1,  // wait for one write to finish before reading.
-      quic_reads, arraysize(quic_reads),
-      quic_writes, arraysize(quic_writes));
-
-  socket_factory_.AddSocketDataProvider(&quic_data);
+  QuicStreamId stream_id = GetParam() > QUIC_VERSION_12 ? 5 : 3;
+  MockQuicData mock_quic_data;
+  if (GetParam() > QUIC_VERSION_12) {
+    mock_quic_data.AddWrite(
+        ConstructRequestHeadersPacket(1, stream_id, true, true,
+                                      GetRequestHeaders("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructResponseHeadersPacket(1, stream_id, false, false,
+                                       GetResponseHeaders("200 OK")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(2, stream_id, false, true, 0, "hello!"));
+    mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+  } else {
+    mock_quic_data.AddWrite(
+        ConstructDataPacket(1, stream_id, true, true, 0,
+                            GetRequestString("GET", "http", "/")));
+    mock_quic_data.AddRead(
+        ConstructDataPacket(1, stream_id, false, true, 0,
+                            GetResponseString("200 OK", "hello!")));
+    mock_quic_data.AddWrite(ConstructAckPacket(1, 0));
+  }
+  mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
+  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1);
 
   // The non-alternate protocol job needs to hang in order to guarantee that
   // the alternate-protocol job will "win".
@@ -757,7 +777,7 @@ TEST_F(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
   EXPECT_EQ(OK, callback.WaitForResult());
 }
 
-TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
+TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
   HttpStreamFactory::EnableNpnSpdy3();  // Enables QUIC too.
 
   // Alternate-protocol job
@@ -788,7 +808,7 @@ TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
   ExpectBrokenAlternateProtocolMapping();
 }
 
-TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
+TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
   HttpStreamFactory::EnableNpnSpdy3();  // Enables QUIC too.
 
   // Alternate-protocol job
@@ -818,7 +838,7 @@ TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
   ExpectBrokenAlternateProtocolMapping();
 }
 
-TEST_F(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
+TEST_P(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
   HttpStreamFactory::EnableNpnSpdy3();  // Enables QUIC too.
 
   // Alternate-protocol job
@@ -855,5 +875,56 @@ TEST_F(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
   EXPECT_TRUE(quic_data.at_write_eof());
 }
 
+TEST_P(QuicNetworkTransactionTest, ConnectionCloseDuringConnect) {
+  HttpStreamFactory::EnableNpnSpdy3();  // Enables QUIC too.
+
+  QuicStreamId stream_id = GetParam() > QUIC_VERSION_12 ? 5 : 3;
+  MockQuicData mock_quic_data;
+  mock_quic_data.AddRead(ConstructConnectionClosePacket(1));
+  if (GetParam() > QUIC_VERSION_12) {
+    mock_quic_data.AddWrite(
+        ConstructRequestHeadersPacket(1, stream_id, true, true,
+                                      GetRequestHeaders("GET", "http", "/")));
+    mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+  } else {
+    mock_quic_data.AddWrite(
+        ConstructDataPacket(1, stream_id, true, true, 0,
+                            GetRequestString("GET", "http", "/")));
+    mock_quic_data.AddWrite(ConstructAckPacket(1, 0));
+  }
+  mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 0);
+
+  // When the QUIC connection fails, we will try the request again over HTTP.
+  MockRead http_reads[] = {
+    MockRead("HTTP/1.1 200 OK\r\n"),
+    MockRead(kQuicAlternateProtocolHttpHeader),
+    MockRead("hello world"),
+    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+    MockRead(ASYNC, OK)
+  };
+
+  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
+                                     NULL, 0);
+  socket_factory_.AddSocketDataProvider(&http_data);
+
+  // In order for a new QUIC session to be established via alternate-protocol
+  // without racing an HTTP connection, we need the host resolution to happen
+  // synchronously.
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", "");
+  HostResolver::RequestInfo info(HostPortPair("www.google.com", 80));
+  AddressList address;
+  host_resolver_.Resolve(info,
+                         DEFAULT_PRIORITY,
+                         &address,
+                         CompletionCallback(),
+                         NULL,
+                         net_log_.bound());
+
+  CreateSession();
+  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
+  SendRequestAndExpectHttpResponse("hello world");
+}
+
 }  // namespace test
 }  // namespace net