static const char kQuicAlternateProtocolHttpsHeader[] =
"Alternate-Protocol: 443:quic\r\n\r\n";
+// Used by the QuicNetworkTransactionTest unit tests.
+const net::QuicStreamId kStreamId5 = 5;
+
} // namespace
namespace net {
class QuicNetworkTransactionTest
: public PlatformTest,
- public testing::WithParamInterface<QuicVersion> {
+ public ::testing::WithParamInterface<QuicVersion> {
protected:
QuicNetworkTransactionTest()
: maker_(GetParam(), 0),
request_.method = "GET";
request_.url = GURL("http://www.google.com/");
request_.load_flags = 0;
+ clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
}
virtual void SetUp() {
HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
}
- scoped_ptr<QuicEncryptedPacket> ConstructRstPacket(
- QuicPacketSequenceNumber num,
- QuicStreamId stream_id) {
- return maker_.MakeRstPacket(
- num, false, stream_id, QUIC_STREAM_NO_ERROR);
- }
-
scoped_ptr<QuicEncryptedPacket> ConstructConnectionClosePacket(
QuicPacketSequenceNumber num) {
return maker_.MakeConnectionClosePacket(num);
return maker_.GetRequestHeaders(method, scheme, path);
}
- std::string GetRequestString(const std::string& method,
- const std::string& scheme,
- const std::string& path) {
- return maker_.GetRequestString(method, scheme, path);
- }
-
SpdyHeaderBlock GetResponseHeaders(const std::string& status) {
return maker_.GetResponseHeaders(status);
}
- std::string GetResponseString(const std::string& status,
- const std::string& body) {
- return maker_.GetResponseString(status, body);
- }
-
scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
QuicPacketSequenceNumber sequence_number,
QuicStreamId stream_id,
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);
params_.origin_to_force_quic_on =
HostPortPair::FromString("www.google.com:80");
- 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.AddWrite(
+ ConstructRequestHeadersPacket(1, kStreamId5, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kStreamId5, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kStreamId5, 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);
EXPECT_EQ(3, log_stream_id);
}
+TEST_P(QuicNetworkTransactionTest, QuicProxy) {
+ proxy_service_.reset(
+ ProxyService::CreateFixedFromPacResult("QUIC myproxy:70"));
+
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kStreamId5, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kStreamId5, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kStreamId5, 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");
NULL, 0);
socket_factory_.AddSocketDataProvider(&http_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.AddWrite(
+ ConstructRequestHeadersPacket(1, kStreamId5, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kStreamId5, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kStreamId5, 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);
NULL, 0);
socket_factory_.AddSocketDataProvider(&http_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.AddWrite(
+ ConstructRequestHeadersPacket(1, kStreamId5, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kStreamId5, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kStreamId5, 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);
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
- 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.AddWrite(
+ ConstructRequestHeadersPacket(1, kStreamId5, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kStreamId5, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kStreamId5, 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);
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
- 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.AddWrite(
+ ConstructRequestHeadersPacket(1, kStreamId5, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kStreamId5, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kStreamId5, 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);
SendRequestAndExpectQuicResponse("hello!");
}
+TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {
+ proxy_service_.reset(
+ ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
+
+ // 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")
+ };
+
+ 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)
+ };
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
+ http_writes, arraysize(http_writes));
+ 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");
+}
+
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
- 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.AddWrite(
+ ConstructRequestHeadersPacket(1, kStreamId5, true, true,
+ GetRequestHeaders("GET", "http", "/")));
+ mock_quic_data.AddRead(
+ ConstructResponseHeadersPacket(1, kStreamId5, false, false,
+ GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kStreamId5, 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);
EXPECT_TRUE(quic_data.at_write_eof());
}
+TEST_P(QuicNetworkTransactionTest, NoBrokenAlternateProtocolOnConnectFailure) {
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
+
+ // 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);
+
+ CreateSession();
+ AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
+ SendRequestAndExpectHttpResponse("hello from http");
+ ExpectQuicAlternateProtocolMapping();
+}
+
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.AddWrite(
+ ConstructRequestHeadersPacket(1, kStreamId5, 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.