| Index: net/quic/chromium/quic_stream_factory_test.cc
|
| diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
|
| index d6fd5aeb42ec0c74be6e856b963bf382beebf52f..92f93ee28d23e98e90cdfeeea424fe8f5510e607 100644
|
| --- a/net/quic/chromium/quic_stream_factory_test.cc
|
| +++ b/net/quic/chromium/quic_stream_factory_test.cc
|
| @@ -316,6 +316,12 @@ class QuicStreamFactoryTestBase {
|
| return QuicStreamFactoryPeer::HasActiveSession(factory_.get(), server_id);
|
| }
|
|
|
| + bool HasActiveJob(const HostPortPair& host_port_pair,
|
| + const PrivacyMode privacy_mode) {
|
| + QuicServerId server_id(host_port_pair, privacy_mode);
|
| + return QuicStreamFactoryPeer::HasActiveJob(factory_.get(), server_id);
|
| + }
|
| +
|
| bool HasActiveCertVerifierJob(const QuicServerId& server_id) {
|
| return QuicStreamFactoryPeer::HasActiveCertVerifierJob(factory_.get(),
|
| server_id);
|
| @@ -1803,6 +1809,134 @@ TEST_P(QuicStreamFactoryTest, CloseAllSessions) {
|
| EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
|
| }
|
|
|
| +// Regression test for crbug.com/700617. Test a write error during the
|
| +// crypto handshake will not hang QuicStreamFactory::Job and should
|
| +// report QUIC_HANDSHAKE_FAILED to upper layers. Subsequent
|
| +// QuicStreamRequest should succeed without hanging.
|
| +TEST_P(QuicStreamFactoryTest,
|
| + WriteErrorInCryptoConnectWithAsyncHostResolution) {
|
| + Initialize();
|
| + // Use unmocked crypto stream to do crypto connect.
|
| + crypto_client_stream_factory_.set_handshake_mode(
|
| + MockCryptoClientStream::USE_DEFAULT_CRYPTO_STREAM);
|
| +
|
| + MockQuicData socket_data;
|
| + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
|
| + // Trigger PACKET_WRITE_ERROR when sending packets in crypto connect.
|
| + socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
|
| + socket_data.AddSocketDataToFactory(&socket_factory_);
|
| +
|
| + // Create request, should fail after the write of the CHLO fails.
|
| + QuicStreamRequest request(factory_.get());
|
| + EXPECT_EQ(ERR_IO_PENDING,
|
| + request.Request(host_port_pair_, privacy_mode_,
|
| + /*cert_verify_flags=*/0, url_, "GET", net_log_,
|
| + callback_.callback()));
|
| + EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, callback_.WaitForResult());
|
| + EXPECT_FALSE(HasActiveSession(host_port_pair_));
|
| + EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
|
| +
|
| + // Verify new requests can be sent normally without hanging.
|
| + crypto_client_stream_factory_.set_handshake_mode(
|
| + MockCryptoClientStream::COLD_START);
|
| + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
|
| + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
|
| + MockQuicData socket_data2;
|
| + socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
|
| + socket_data2.AddWrite(
|
| + ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
|
| + kDefaultMaxUncompressedHeaderSize, nullptr));
|
| + socket_data2.AddSocketDataToFactory(&socket_factory_);
|
| +
|
| + QuicStreamRequest request2(factory_.get());
|
| + EXPECT_EQ(ERR_IO_PENDING,
|
| + request2.Request(host_port_pair_, privacy_mode_,
|
| + /*cert_verify_flags=*/0, url_, "GET", net_log_,
|
| + callback_.callback()));
|
| + EXPECT_FALSE(HasActiveSession(host_port_pair_));
|
| + EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
|
| + // Run the message loop to complete host resolution.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Complete handshake. QuicStreamFactory::Job should complete and succeed.
|
| + crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
|
| + QuicSession::HANDSHAKE_CONFIRMED);
|
| + EXPECT_THAT(callback_.WaitForResult(), IsOk());
|
| + EXPECT_TRUE(HasActiveSession(host_port_pair_));
|
| + EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
|
| +
|
| + // Create QuicHttpStream.
|
| + std::unique_ptr<QuicHttpStream> stream = request2.CreateStream();
|
| + EXPECT_TRUE(stream.get());
|
| + stream.reset();
|
| + EXPECT_TRUE(socket_data.AllReadDataConsumed());
|
| + EXPECT_TRUE(socket_data.AllWriteDataConsumed());
|
| + EXPECT_TRUE(socket_data2.AllReadDataConsumed());
|
| + EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
|
| +}
|
| +
|
| +TEST_P(QuicStreamFactoryTest, WriteErrorInCryptoConnectWithSyncHostResolution) {
|
| + Initialize();
|
| + // Use unmocked crypto stream to do crypto connect.
|
| + crypto_client_stream_factory_.set_handshake_mode(
|
| + MockCryptoClientStream::USE_DEFAULT_CRYPTO_STREAM);
|
| + host_resolver_.set_synchronous_mode(true);
|
| + host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
|
| + "192.168.0.1", "");
|
| +
|
| + MockQuicData socket_data;
|
| + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
|
| + // Trigger PACKET_WRITE_ERROR when sending packets in crypto connect.
|
| + socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
|
| + socket_data.AddSocketDataToFactory(&socket_factory_);
|
| +
|
| + // Create request, should fail immediately.
|
| + QuicStreamRequest request(factory_.get());
|
| + EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED,
|
| + request.Request(host_port_pair_, privacy_mode_,
|
| + /*cert_verify_flags=*/0, url_, "GET", net_log_,
|
| + callback_.callback()));
|
| + // Check no active session, or active jobs left for this server.
|
| + EXPECT_FALSE(HasActiveSession(host_port_pair_));
|
| + EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
|
| +
|
| + // Verify new requests can be sent normally without hanging.
|
| + crypto_client_stream_factory_.set_handshake_mode(
|
| + MockCryptoClientStream::COLD_START);
|
| + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
|
| + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
|
| + MockQuicData socket_data2;
|
| + socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
|
| + socket_data2.AddWrite(
|
| + ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
|
| + kDefaultMaxUncompressedHeaderSize, nullptr));
|
| + socket_data2.AddSocketDataToFactory(&socket_factory_);
|
| +
|
| + QuicStreamRequest request2(factory_.get());
|
| + EXPECT_EQ(ERR_IO_PENDING,
|
| + request2.Request(host_port_pair_, privacy_mode_,
|
| + /*cert_verify_flags=*/0, url_, "GET", net_log_,
|
| + callback_.callback()));
|
| + EXPECT_FALSE(HasActiveSession(host_port_pair_));
|
| + EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
|
| +
|
| + // Complete handshake.
|
| + crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
|
| + QuicSession::HANDSHAKE_CONFIRMED);
|
| + EXPECT_THAT(callback_.WaitForResult(), IsOk());
|
| + EXPECT_TRUE(HasActiveSession(host_port_pair_));
|
| + EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
|
| +
|
| + // Create QuicHttpStream.
|
| + std::unique_ptr<QuicHttpStream> stream = request2.CreateStream();
|
| + EXPECT_TRUE(stream.get());
|
| + stream.reset();
|
| + EXPECT_TRUE(socket_data.AllReadDataConsumed());
|
| + EXPECT_TRUE(socket_data.AllWriteDataConsumed());
|
| + EXPECT_TRUE(socket_data2.AllReadDataConsumed());
|
| + EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
|
| +}
|
| +
|
| TEST_P(QuicStreamFactoryTest, OnIPAddressChanged) {
|
| close_sessions_on_ip_change_ = true;
|
| Initialize();
|
|
|