summaryrefslogtreecommitdiffstats
path: root/chromium/net/quic/quic_network_transaction_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/quic/quic_network_transaction_unittest.cc')
-rw-r--r--chromium/net/quic/quic_network_transaction_unittest.cc691
1 files changed, 396 insertions, 295 deletions
diff --git a/chromium/net/quic/quic_network_transaction_unittest.cc b/chromium/net/quic/quic_network_transaction_unittest.cc
index 2e4610ce5e7..bd3e3cd94b2 100644
--- a/chromium/net/quic/quic_network_transaction_unittest.cc
+++ b/chromium/net/quic/quic_network_transaction_unittest.cc
@@ -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"
@@ -17,7 +19,7 @@
#include "net/http/http_server_properties_impl.h"
#include "net/http/http_stream.h"
#include "net/http/http_stream_factory.h"
-#include "net/http/http_transaction_unittest.h"
+#include "net/http/http_transaction_test_util.h"
#include "net/http/transport_security_state.h"
#include "net/proxy/proxy_config_service_fixed.h"
#include "net/proxy/proxy_resolver.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,18 +53,62 @@ 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),
@@ -69,6 +116,7 @@ class QuicNetworkTransactionTest : public PlatformTest {
request_.method = "GET";
request_.url = GURL("http://www.google.com/");
request_.load_flags = 0;
+ clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
}
virtual void SetUp() {
@@ -83,146 +131,71 @@ class QuicNetworkTransactionTest : public PlatformTest {
PlatformTest::TearDown();
NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
base::MessageLoop::current()->RunUntilIdle();
- HttpStreamFactory::set_use_alternate_protocols(false);
- HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
- }
-
- scoped_ptr<QuicEncryptedPacket> ConstructRstPacket(
- QuicPacketSequenceNumber num,
- QuicStreamId stream_id) {
- QuicPacketHeader header;
- header.public_header.guid = random_generator_.RandUint64();
- 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)));
}
scoped_ptr<QuicEncryptedPacket> ConstructConnectionClosePacket(
QuicPacketSequenceNumber num) {
- QuicPacketHeader header;
- header.public_header.guid = random_generator_.RandUint64();
- 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;
-
- QuicConnectionCloseFrame close;
- close.error_code = QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
- close.error_details = "Time to panic!";
- 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 = random_generator_.RandUint64();
- 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);
}
- 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);
+ SpdyHeaderBlock GetRequestHeaders(const std::string& method,
+ const std::string& scheme,
+ const std::string& path) {
+ return maker_.GetRequestHeaders(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);
- }
-
- // 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, MakeIOVector(data));
- return ConstructPacket(header_, QuicFrame(&frame)).release();
+ return maker_.MakeDataPacket(
+ sequence_number, stream_id, should_include_version, fin, offset, data);
}
- 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));
+ 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);
}
- 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;
+ 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() {
- CreateSessionWithFactory(&socket_factory_);
+ CreateSessionWithFactory(&socket_factory_, false);
+ }
+
+ void CreateSessionWithNextProtos() {
+ CreateSessionWithFactory(&socket_factory_, true);
}
- void CreateSessionWithFactory(ClientSocketFactory* socket_factory) {
+ // If |use_next_protos| is true, enables SPDY and QUIC.
+ void CreateSessionWithFactory(ClientSocketFactory* socket_factory,
+ bool use_next_protos) {
params_.enable_quic = true;
params_.quic_clock = clock_;
params_.quic_random = &random_generator_;
@@ -235,6 +208,12 @@ 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());
+
+ if (use_next_protos) {
+ params_.use_alternate_protocols = true;
+ params_.next_protos = NextProtosSpdy3();
+ }
session_ = new HttpNetworkSession(params_);
session_->quic_stream_factory()->set_require_confirmation(false);
@@ -308,13 +287,22 @@ class QuicNetworkTransactionTest : public PlatformTest {
EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
}
+ void ExpectQuicAlternateProtocolMapping() {
+ ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol(
+ HostPortPair::FromURL(request_.url)));
+ const PortAlternateProtocolPair alternate =
+ session_->http_server_properties()->GetAlternateProtocol(
+ HostPortPair::FromURL(request_.url));
+ EXPECT_EQ(QUIC, alternate.protocol);
+ }
+
void AddHangingNonAlternateProtocolSocketData() {
MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
hanging_data_.set_connect_data(hanging_connect);
socket_factory_.AddSocketDataProvider(&hanging_data_);
}
- QuicPacketHeader header_;
+ QuicTestPacketMaker maker_;
scoped_refptr<HttpNetworkSession> session_;
MockClientSocketFactory socket_factory_;
MockCryptoClientStreamFactory crypto_client_stream_factory_;
@@ -324,7 +312,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;
@@ -334,35 +321,26 @@ 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));
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ 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".
@@ -405,19 +383,43 @@ 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"));
+
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ 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();
@@ -429,7 +431,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");
@@ -451,9 +453,7 @@ TEST_F(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
SendRequestAndExpectHttpResponse("hello world");
}
-TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
- HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
-
+TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead(kQuicAlternateProtocolHttpHeader),
@@ -466,46 +466,34 @@ 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));
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ 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".
AddHangingNonAlternateProtocolSocketData();
- CreateSession();
+ CreateSessionWithNextProtos();
SendRequestAndExpectHttpResponse("hello world");
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;
- HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
@@ -519,43 +507,31 @@ 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));
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF
- 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);
+ 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".
AddHangingNonAlternateProtocolSocketData();
- CreateSession();
+ CreateSessionWithNextProtos();
// TODO(rtenneti): Test QUIC over HTTPS, GetSSLInfo().
SendRequestAndExpectHttpResponse("hello world");
}
-TEST_F(QuicNetworkTransactionTest, HungAlternateProtocol) {
- HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
+TEST_P(QuicNetworkTransactionTest, HungAlternateProtocol) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::COLD_START);
@@ -594,7 +570,7 @@ TEST_F(QuicNetworkTransactionTest, HungAlternateProtocol) {
http_writes, arraysize(http_writes));
socket_factory.AddSocketDataProvider(&http_data2);
- CreateSessionWithFactory(&socket_factory);
+ CreateSessionWithFactory(&socket_factory, true);
// Run the first request.
http_data.StopAfter(arraysize(http_reads) + arraysize(http_writes));
@@ -613,70 +589,43 @@ TEST_F(QuicNetworkTransactionTest, HungAlternateProtocol) {
ASSERT_TRUE(!quic_data.at_write_eof());
}
-TEST_F(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
- };
-
- 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);
+TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ 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".
AddHangingNonAlternateProtocolSocketData();
- CreateSession();
+ CreateSessionWithNextProtos();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
SendRequestAndExpectQuicResponse("hello!");
}
-TEST_F(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);
+TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ 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
@@ -692,38 +641,65 @@ TEST_F(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
NULL,
net_log_.bound());
- CreateSession();
+ CreateSessionWithNextProtos();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
SendRequestAndExpectQuicResponse("hello!");
}
-TEST_F(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));
+TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {
+ proxy_service_.reset(
+ ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
- MockWrite quic_writes[] = {
- MockWrite(SYNCHRONOUS, req->data(), req->length()),
- MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
+ // Since we are using a proxy, the QUIC job will not succeed.
+ MockWrite http_writes[] = {
+ MockWrite(SYNCHRONOUS, 0, "GET http://www.google.com/ HTTP/1.1\r\n"),
+ MockWrite(SYNCHRONOUS, 1, "Host: www.google.com\r\n"),
+ MockWrite(SYNCHRONOUS, 2, "Proxy-Connection: keep-alive\r\n\r\n")
};
- 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
+ MockRead http_reads[] = {
+ MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"),
+ MockRead(SYNCHRONOUS, 4, kQuicAlternateProtocolHttpHeader),
+ MockRead(SYNCHRONOUS, 5, "hello world"),
+ MockRead(SYNCHRONOUS, OK, 6)
};
- DelayedSocketData quic_data(
- 1, // wait for one write to finish before reading.
- quic_reads, arraysize(quic_reads),
- quic_writes, arraysize(quic_writes));
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
+ http_writes, arraysize(http_writes));
+ socket_factory_.AddSocketDataProvider(&http_data);
- socket_factory_.AddSocketDataProvider(&quic_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());
+
+ CreateSessionWithNextProtos();
+ AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
+ SendRequestAndExpectHttpResponse("hello world");
+}
+
+TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ 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".
@@ -741,7 +717,7 @@ TEST_F(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address,
CompletionCallback(), NULL, net_log_.bound());
- CreateSession();
+ CreateSessionWithNextProtos();
session_->quic_stream_factory()->set_require_confirmation(true);
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
@@ -756,9 +732,7 @@ TEST_F(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
EXPECT_EQ(OK, callback.WaitForResult());
}
-TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
- HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
-
+TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
// Alternate-protocol job
scoped_ptr<QuicEncryptedPacket> close(ConstructConnectionClosePacket(1));
MockRead quic_reads[] = {
@@ -781,15 +755,13 @@ TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
NULL, 0);
socket_factory_.AddSocketDataProvider(&http_data);
- CreateSession();
+ CreateSessionWithNextProtos();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
SendRequestAndExpectHttpResponse("hello from http");
ExpectBrokenAlternateProtocolMapping();
}
-TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
- HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
-
+TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
// Alternate-protocol job
MockRead quic_reads[] = {
MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
@@ -810,16 +782,45 @@ TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
NULL, 0);
socket_factory_.AddSocketDataProvider(&http_data);
- CreateSession();
+ CreateSessionWithNextProtos();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
SendRequestAndExpectHttpResponse("hello from http");
ExpectBrokenAlternateProtocolMapping();
}
-TEST_F(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
- HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
+TEST_P(QuicNetworkTransactionTest, NoBrokenAlternateProtocolIfTcpFails) {
+ // Alternate-protocol job will fail when the session attempts to read.
+ MockRead quic_reads[] = {
+ MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
+ };
+ StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
+ NULL, 0);
+ socket_factory_.AddSocketDataProvider(&quic_data);
+ // Main job will also fail.
+ MockRead http_reads[] = {
+ MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
+ };
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
+ NULL, 0);
+ http_data.set_connect_data(MockConnect(ASYNC, ERR_SOCKET_NOT_CONNECTED));
+ socket_factory_.AddSocketDataProvider(&http_data);
+
+ CreateSessionWithNextProtos();
+
+ AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
+ scoped_ptr<HttpNetworkTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
+ TestCompletionCallback callback;
+ int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, callback.WaitForResult());
+ ExpectQuicAlternateProtocolMapping();
+}
+
+TEST_P(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
// Alternate-protocol job
MockRead quic_reads[] = {
MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
@@ -830,6 +831,11 @@ TEST_F(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
AddHangingNonAlternateProtocolSocketData();
+ // Second Alternate-protocol job which will race with the TCP job.
+ StaticSocketDataProvider quic_data2(quic_reads, arraysize(quic_reads),
+ NULL, 0);
+ socket_factory_.AddSocketDataProvider(&quic_data2);
+
// Final job that will proceed when the QUIC job fails.
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n\r\n"),
@@ -842,7 +848,7 @@ TEST_F(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
NULL, 0);
socket_factory_.AddSocketDataProvider(&http_data);
- CreateSession();
+ CreateSessionWithNextProtos();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
@@ -854,5 +860,100 @@ TEST_F(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
EXPECT_TRUE(quic_data.at_write_eof());
}
+TEST_P(QuicNetworkTransactionTest, DISABLED_HangingZeroRttFallback) {
+ // Alternate-protocol job
+ MockRead quic_reads[] = {
+ MockRead(ASYNC, ERR_IO_PENDING),
+ };
+ StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
+ NULL, 0);
+ socket_factory_.AddSocketDataProvider(&quic_data);
+
+ // Main job that will proceed when the QUIC job fails.
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n\r\n"),
+ MockRead("hello from http"),
+ 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);
+
+ CreateSessionWithNextProtos();
+
+ AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
+
+ SendRequestAndExpectHttpResponse("hello from http");
+}
+
+TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolOnConnectFailure) {
+ // Alternate-protocol job will fail before creating a QUIC session.
+ StaticSocketDataProvider quic_data(NULL, 0, NULL, 0);
+ quic_data.set_connect_data(MockConnect(SYNCHRONOUS,
+ ERR_INTERNET_DISCONNECTED));
+ socket_factory_.AddSocketDataProvider(&quic_data);
+
+ // Main job which will succeed even though the alternate job fails.
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n\r\n"),
+ MockRead("hello from http"),
+ 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);
+
+ CreateSessionWithNextProtos();
+ AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
+ SendRequestAndExpectHttpResponse("hello from http");
+
+ ExpectBrokenAlternateProtocolMapping();
+}
+
+TEST_P(QuicNetworkTransactionTest, ConnectionCloseDuringConnect) {
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddRead(ConstructConnectionClosePacket(1));
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ 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());
+
+ CreateSessionWithNextProtos();
+ AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
+ SendRequestAndExpectHttpResponse("hello world");
+}
+
} // namespace test
} // namespace net