gfe-relnote: In QUIC, add exponential backoff for PTO timeout when there is not RTT measurement. Protected by gfe2_reloadable_flag_quic_enable_version_draft_25_v3 and gfe2_reloadable_flag_quic_enable_version_draft_27.

Also change PTO timeout from 2 * initial_rtt to 3 * initial_rtt.

PiperOrigin-RevId: 308102591
Change-Id: If44e9e7f6107b7a95650e5f4744ea847d2b998d2
diff --git a/quic/core/quic_sent_packet_manager_test.cc b/quic/core/quic_sent_packet_manager_test.cc
index e846058..e63a9b8 100644
--- a/quic/core/quic_sent_packet_manager_test.cc
+++ b/quic/core/quic_sent_packet_manager_test.cc
@@ -3772,6 +3772,59 @@
   EXPECT_EQ(expected_delay, manager_.GetPathDegradingDelay());
 }
 
+// Regression test for b/154050235.
+TEST_F(QuicSentPacketManagerTest, ExponentialBackoffWithNoRttMeasurement) {
+  QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
+  manager_.EnableIetfPtoAndLossDetection();
+  RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+  EXPECT_EQ(QuicTime::Delta::FromMilliseconds(kInitialRttMs),
+            rtt_stats->initial_rtt());
+  EXPECT_TRUE(rtt_stats->smoothed_rtt().IsZero());
+
+  SendCryptoPacket(1);
+  QuicTime::Delta expected_pto_delay =
+      QuicTime::Delta::FromMilliseconds(3 * kInitialRttMs);
+  EXPECT_EQ(clock_.Now() + expected_pto_delay,
+            manager_.GetRetransmissionTime());
+
+  // Invoke PTO.
+  clock_.AdvanceTime(expected_pto_delay);
+  manager_.OnRetransmissionTimeout();
+
+  EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+      .WillOnce(WithArgs<1>(Invoke([this]() { RetransmitCryptoPacket(3); })));
+  manager_.MaybeSendProbePackets();
+  // Verify exponential backoff of the PTO timeout.
+  EXPECT_EQ(clock_.Now() + 2 * expected_pto_delay,
+            manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, PtoDelayWithTinyInitialRtt) {
+  manager_.EnableIetfPtoAndLossDetection();
+  RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+  // Assume client provided a tiny initial RTT.
+  rtt_stats->set_initial_rtt(QuicTime::Delta::FromMicroseconds(1));
+  EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1), rtt_stats->initial_rtt());
+  EXPECT_TRUE(rtt_stats->smoothed_rtt().IsZero());
+
+  SendCryptoPacket(1);
+  QuicTime::Delta expected_pto_delay = QuicTime::Delta::FromMilliseconds(10);
+  // Verify kMinHandshakeTimeoutMs is respected.
+  EXPECT_EQ(clock_.Now() + expected_pto_delay,
+            manager_.GetRetransmissionTime());
+
+  // Invoke PTO.
+  clock_.AdvanceTime(expected_pto_delay);
+  manager_.OnRetransmissionTimeout();
+
+  EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+      .WillOnce(WithArgs<1>(Invoke([this]() { RetransmitCryptoPacket(3); })));
+  manager_.MaybeSendProbePackets();
+  // Verify exponential backoff of the PTO timeout.
+  EXPECT_EQ(clock_.Now() + 2 * expected_pto_delay,
+            manager_.GetRetransmissionTime());
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic