Add a new test in QuicChromiumClientSessionTest to verify path degrading during crypto handshake will be detected.

Bug: 790547
Change-Id: If39cf0fcf342372669f951fef758334e9520ccea
Reviewed-on: https://chromium-review.googlesource.com/1161491
Reviewed-by: Ryan Hamilton <[email protected]>
Commit-Queue: Zhongyi Shi <[email protected]>
Cr-Commit-Position: refs/heads/master@{#580419}
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index da7c531b..eaeacf28 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -82,6 +82,8 @@
 
   void OverrideChannelIDSent() { force_channel_id_sent_ = true; }
 
+  MOCK_METHOD0(OnPathDegrading, void());
+
  private:
   bool force_channel_id_sent_ = false;
 };
@@ -1430,6 +1432,65 @@
   EXPECT_TRUE(new_socket_data.AllWriteDataConsumed());
 }
 
+TEST_P(QuicChromiumClientSessionTest, DetectPathDegradingDuringHandshake) {
+  migrate_session_early_v2_ = true;
+
+  MockQuicData quic_data;
+  quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeDummyCHLOPacket(1));
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeDummyCHLOPacket(2));
+  quic_data.AddSocketDataToFactory(&socket_factory_);
+
+  // Set the crypto handshake mode to cold start and send CHLO packets.
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::COLD_START_WITH_CHLO_SENT);
+  Initialize();
+
+  session_->CryptoConnect(callback_.callback());
+
+  // Check retransmission alarm is set after sending the initial CHLO packet.
+  quic::QuicAlarm* retransmission_alarm =
+      quic::test::QuicConnectionPeer::GetRetransmissionAlarm(
+          session_->connection());
+  EXPECT_TRUE(retransmission_alarm->IsSet());
+  quic::QuicTime retransmission_time = retransmission_alarm->deadline();
+
+  // Check path degrading alarm is set after sending the initial CHLO packet.
+  quic::QuicAlarm* path_degrading_alarm =
+      quic::test::QuicConnectionPeer::GetPathDegradingAlarm(
+          session_->connection());
+  EXPECT_TRUE(path_degrading_alarm->IsSet());
+  quic::QuicTime path_degrading_time = path_degrading_alarm->deadline();
+  EXPECT_LE(retransmission_time, path_degrading_time);
+
+  // Do not create outgoing stream since encryption is not established.
+  std::unique_ptr<QuicChromiumClientSession::Handle> handle =
+      session_->CreateHandle(destination_);
+  TestCompletionCallback callback;
+  EXPECT_TRUE(handle->IsConnected());
+  EXPECT_FALSE(handle->IsCryptoHandshakeConfirmed());
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle->RequestStream(/*require_handshake_confirmation=*/true,
+                            callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
+
+  // Fire the retransmission alarm to retransmit the crypto packet.
+  quic::QuicTime::Delta delay = retransmission_time - clock_.ApproximateNow();
+  clock_.AdvanceTime(delay);
+  alarm_factory_.FireAlarm(retransmission_alarm);
+
+  // Fire the path degrading alarm to notify session that path is degrading
+  // during crypto handshake.
+  delay = path_degrading_time - clock_.ApproximateNow();
+  clock_.AdvanceTime(delay);
+  EXPECT_CALL(*session_.get(), OnPathDegrading());
+  alarm_factory_.FireAlarm(path_degrading_alarm);
+
+  EXPECT_TRUE(session_->connection()->IsPathDegrading());
+  EXPECT_TRUE(quic_data.AllReadDataConsumed());
+  EXPECT_TRUE(quic_data.AllWriteDataConsumed());
+}
+
 TEST_P(QuicChromiumClientSessionTest, RetransmittableOnWireTimeout) {
   migrate_session_early_v2_ = true;