Re-land cl/443493674 by fixing build error.
Original description: When retransmittable-on-wire timeout, re-send 1st 1-RTT packet or random bytes (which are behind client connection options ROWF and ROWR, respectively).

PiperOrigin-RevId: 443532932
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc
index 97f69f3..b77cc15 100644
--- a/quiche/quic/core/quic_connection_test.cc
+++ b/quiche/quic/core/quic_connection_test.cc
@@ -1285,6 +1285,10 @@
 
   void SimulateNextPacketTooLarge() { writer_->SimulateNextPacketTooLarge(); }
 
+  void ExpectNextPacketUnprocessable() {
+    writer_->ExpectNextPacketUnprocessable();
+  }
+
   void AlwaysGetPacketTooLarge() { writer_->AlwaysGetPacketTooLarge(); }
 
   void SetWritePauseTimeDelta(QuicTime::Delta delta) {
@@ -7646,6 +7650,150 @@
             connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
 }
 
+TEST_P(QuicConnectionTest, RetransmittableOnWireSendFirstPacket) {
+  if (!GetQuicReloadableFlag(quic_use_ping_manager) ||
+      !VersionHasIetfQuicFrames(connection_.version().transport_version)) {
+    return;
+  }
+  EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+
+  const QuicTime::Delta kRetransmittableOnWireTimeout =
+      QuicTime::Delta::FromMilliseconds(200);
+  const QuicTime::Delta kTestRtt = QuicTime::Delta::FromMilliseconds(100);
+
+  connection_.set_initial_retransmittable_on_wire_timeout(
+      kRetransmittableOnWireTimeout);
+
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  QuicConfig config;
+  QuicTagVector connection_options;
+  connection_options.push_back(kROWF);
+  config.SetClientConnectionOptions(connection_options);
+  connection_.SetFromConfig(config);
+
+  // Send a request.
+  connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN);
+  // Receive an ACK after 1-RTT.
+  clock_.AdvanceTime(kTestRtt);
+  EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+  QuicAckFrame frame =
+      InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}});
+  ProcessAckPacket(&frame);
+  ASSERT_TRUE(connection_.GetPingAlarm()->IsSet());
+  EXPECT_EQ(kRetransmittableOnWireTimeout,
+            connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+  EXPECT_EQ(1u, writer_->packets_write_attempts());
+
+  // Fire retransmittable-on-wire alarm.
+  clock_.AdvanceTime(kRetransmittableOnWireTimeout);
+  connection_.GetPingAlarm()->Fire();
+  EXPECT_EQ(2u, writer_->packets_write_attempts());
+  // Verify alarm is set in keep-alive mode.
+  ASSERT_TRUE(connection_.GetPingAlarm()->IsSet());
+  EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs),
+            connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+}
+
+TEST_P(QuicConnectionTest, RetransmittableOnWireSendRandomBytes) {
+  if (!GetQuicReloadableFlag(quic_use_ping_manager) ||
+      !VersionHasIetfQuicFrames(connection_.version().transport_version)) {
+    return;
+  }
+  EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+
+  const QuicTime::Delta kRetransmittableOnWireTimeout =
+      QuicTime::Delta::FromMilliseconds(200);
+  const QuicTime::Delta kTestRtt = QuicTime::Delta::FromMilliseconds(100);
+
+  connection_.set_initial_retransmittable_on_wire_timeout(
+      kRetransmittableOnWireTimeout);
+
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  QuicConfig config;
+  QuicTagVector connection_options;
+  connection_options.push_back(kROWR);
+  config.SetClientConnectionOptions(connection_options);
+  connection_.SetFromConfig(config);
+
+  // Send a request.
+  connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN);
+  // Receive an ACK after 1-RTT.
+  clock_.AdvanceTime(kTestRtt);
+  EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+  QuicAckFrame frame =
+      InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}});
+  ProcessAckPacket(&frame);
+  ASSERT_TRUE(connection_.GetPingAlarm()->IsSet());
+  EXPECT_EQ(kRetransmittableOnWireTimeout,
+            connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+  EXPECT_EQ(1u, writer_->packets_write_attempts());
+
+  // Fire retransmittable-on-wire alarm.
+  clock_.AdvanceTime(kRetransmittableOnWireTimeout);
+  // Next packet is not processable by the framer in the test writer.
+  ExpectNextPacketUnprocessable();
+  connection_.GetPingAlarm()->Fire();
+  EXPECT_EQ(2u, writer_->packets_write_attempts());
+  // Verify alarm is set in keep-alive mode.
+  ASSERT_TRUE(connection_.GetPingAlarm()->IsSet());
+  EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs),
+            connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+}
+
+TEST_P(QuicConnectionTest,
+       RetransmittableOnWireSendRandomBytesWithWriterBlocked) {
+  if (!GetQuicReloadableFlag(quic_use_ping_manager) ||
+      !VersionHasIetfQuicFrames(connection_.version().transport_version)) {
+    return;
+  }
+  EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+  EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+
+  const QuicTime::Delta kRetransmittableOnWireTimeout =
+      QuicTime::Delta::FromMilliseconds(200);
+  const QuicTime::Delta kTestRtt = QuicTime::Delta::FromMilliseconds(100);
+
+  connection_.set_initial_retransmittable_on_wire_timeout(
+      kRetransmittableOnWireTimeout);
+
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  QuicConfig config;
+  QuicTagVector connection_options;
+  connection_options.push_back(kROWR);
+  config.SetClientConnectionOptions(connection_options);
+  connection_.SetFromConfig(config);
+
+  // Send a request.
+  connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN);
+  // Receive an ACK after 1-RTT.
+  clock_.AdvanceTime(kTestRtt);
+  EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+  QuicAckFrame frame =
+      InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}});
+  ProcessAckPacket(&frame);
+  ASSERT_TRUE(connection_.GetPingAlarm()->IsSet());
+  EXPECT_EQ(kRetransmittableOnWireTimeout,
+            connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+  EXPECT_EQ(1u, writer_->packets_write_attempts());
+  // Receive an out of order data packet and block the ACK packet.
+  BlockOnNextWrite();
+  ProcessDataPacket(3);
+  EXPECT_EQ(2u, writer_->packets_write_attempts());
+  EXPECT_EQ(1u, connection_.NumQueuedPackets());
+
+  // Fire retransmittable-on-wire alarm.
+  clock_.AdvanceTime(kRetransmittableOnWireTimeout);
+  connection_.GetPingAlarm()->Fire();
+  // Verify the random bytes packet gets queued.
+  EXPECT_EQ(2u, connection_.NumQueuedPackets());
+}
+
 // This test verifies that the connection marks path as degrading and does not
 // spin timer to detect path degrading when a new packet is sent on the
 // degraded path.