| Index: net/quic/quic_connection_test.cc | 
| diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc | 
| index 4ac928482a98d16c6f7480948a9ca380db658c7b..fc27219535612ddea857471d6cd0a11db3a97bb4 100644 | 
| --- a/net/quic/quic_connection_test.cc | 
| +++ b/net/quic/quic_connection_test.cc | 
| @@ -1682,92 +1682,134 @@ TEST_P(QuicConnectionTest, FECQueueing) { | 
| EXPECT_EQ(2u, connection_.NumQueuedPackets()); | 
| } | 
|  | 
| -TEST_P(QuicConnectionTest, AbandonFECFromCongestionWindow) { | 
| +TEST_P(QuicConnectionTest, RemoveFECFromInflightOnRetransmissionTimeout) { | 
| +  EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); | 
| EXPECT_TRUE(QuicConnectionPeer::GetPacketCreator( | 
| &connection_)->IsFecEnabled()); | 
| +  QuicSentPacketManager* manager = | 
| +      QuicConnectionPeer::GetSentPacketManager(&connection_); | 
| +  EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager)); | 
|  | 
| // 1 Data and 1 FEC packet. | 
| EXPECT_CALL(*send_algorithm_, | 
| OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(2); | 
| connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr); | 
| +  size_t data_and_fec = QuicSentPacketManagerPeer::GetBytesInFlight(manager); | 
| +  EXPECT_LT(0u, data_and_fec); | 
|  | 
| -  const QuicTime::Delta retransmission_time = | 
| -      QuicTime::Delta::FromMilliseconds(5000); | 
| -  clock_.AdvanceTime(retransmission_time); | 
| +  clock_.AdvanceTime(DefaultRetransmissionTime()); | 
|  | 
| -  // Abandon FEC packet and data packet. | 
| +  // On RTO, both data and FEC packets are removed from inflight, | 
| +  // and retransmission of the data (but not FEC) gets added into the inflight. | 
| EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); | 
| EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); | 
| -  EXPECT_CALL(visitor_, OnCanWrite()); | 
| -  connection_.OnRetransmissionTimeout(); | 
| +  connection_.GetRetransmissionAlarm()->Fire(); | 
| +  ; | 
| + | 
| +  size_t data_only = QuicSentPacketManagerPeer::GetBytesInFlight(manager); | 
| +  EXPECT_LT(0u, data_only); | 
| +  EXPECT_GE(data_and_fec, 2 * data_only); | 
| + | 
| +  // Receive ack for the retransmission. No data should be outstanding. | 
| +  QuicAckFrame ack = InitAckFrame(3); | 
| +  NackPacket(1, &ack); | 
| +  NackPacket(2, &ack); | 
| +  SequenceNumberSet lost_packets; | 
| +  EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) | 
| +      .WillOnce(Return(lost_packets)); | 
| +  EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); | 
| +  ProcessAckPacket(&ack); | 
| +  EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager)); | 
| + | 
| +  // Ensure the alarm is not set since all packets have been acked or abandoned. | 
| +  EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); | 
| +  EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager)); | 
| } | 
|  | 
| -TEST_P(QuicConnectionTest, DontAbandonAckedFEC) { | 
| +TEST_P(QuicConnectionTest, RemoveFECFromInflightOnLossRetransmission) { | 
| EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); | 
| EXPECT_TRUE(QuicConnectionPeer::GetPacketCreator( | 
| &connection_)->IsFecEnabled()); | 
| +  QuicSentPacketManager* manager = | 
| +      QuicConnectionPeer::GetSentPacketManager(&connection_); | 
|  | 
| -  // 3 Data and 3 FEC packets. | 
| +  // 1 Data packet and 1 FEC packet, followed by more data to trigger NACKs. | 
| EXPECT_CALL(*send_algorithm_, | 
| OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(6); | 
| connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr); | 
| -  // Send some more data afterwards to ensure early retransmit doesn't trigger. | 
| -  connection_.SendStreamDataWithStringWithFec(3, "foo", 3, !kFin, nullptr); | 
| -  connection_.SendStreamDataWithStringWithFec(3, "foo", 6, !kFin, nullptr); | 
| - | 
| -  QuicAckFrame ack_fec = InitAckFrame(2); | 
| -  // Data packet missing. | 
| -  // TODO(ianswett): Note that this is not a sensible ack, since if the FEC was | 
| -  // received, it would cause the covered packet to be acked as well. | 
| -  NackPacket(1, &ack_fec); | 
| +  connection_.SendStreamDataWithString(3, "foo", 3, !kFin, nullptr); | 
| +  connection_.SendStreamDataWithString(3, "foo", 6, !kFin, nullptr); | 
| +  connection_.SendStreamDataWithString(3, "foo", 9, !kFin, nullptr); | 
| +  connection_.SendStreamDataWithString(3, "foo", 12, !kFin, nullptr); | 
| +  size_t multiple_data_and_fec = | 
| +      QuicSentPacketManagerPeer::GetBytesInFlight(manager); | 
| +  EXPECT_LT(0u, multiple_data_and_fec); | 
| + | 
| +  // Ack data packets, and NACK 1 data packet and FEC packet. Triggers | 
| +  // NACK-based loss detection of data and FEC packet, but only data is | 
| +  // retransmitted and considered oustanding. | 
| +  QuicAckFrame ack = InitAckFrame(6); | 
| +  NackPacket(2, &ack); | 
| +  NackPacket(3, &ack); | 
| +  SequenceNumberSet lost_packets; | 
| +  lost_packets.insert(2); | 
| +  lost_packets.insert(3); | 
| +  EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) | 
| +      .WillOnce(Return(lost_packets)); | 
| EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); | 
| -  ProcessAckPacket(&ack_fec); | 
| -  clock_.AdvanceTime(DefaultRetransmissionTime()); | 
| - | 
| -  // Don't abandon the acked FEC packet, but it will abandon 2 the subsequent | 
| -  // FEC packets. | 
| -  EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); | 
| -  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3); | 
| -  connection_.GetRetransmissionAlarm()->Fire(); | 
| +  EXPECT_CALL(*send_algorithm_, | 
| +              OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(1); | 
| +  ProcessAckPacket(&ack); | 
| +  size_t data_only = QuicSentPacketManagerPeer::GetBytesInFlight(manager); | 
| +  EXPECT_GT(multiple_data_and_fec, data_only); | 
| +  EXPECT_LT(0u, data_only); | 
| + | 
| +  // Receive ack for the retransmission. No data should be outstanding. | 
| +  QuicAckFrame ack2 = InitAckFrame(7); | 
| +  NackPacket(2, &ack2); | 
| +  NackPacket(3, &ack2); | 
| +  SequenceNumberSet lost_packets2; | 
| +  EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) | 
| +      .WillOnce(Return(lost_packets2)); | 
| +  EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); | 
| +  ProcessAckPacket(&ack2); | 
| +  EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager)); | 
| } | 
|  | 
| -TEST_P(QuicConnectionTest, AbandonAllFEC) { | 
| +TEST_P(QuicConnectionTest, NoTLPForFECPacket) { | 
| +  // Turn on TLP for this test. | 
| +  QuicSentPacketManagerPeer::SetMaxTailLossProbes( | 
| +      QuicConnectionPeer::GetSentPacketManager(&connection_), 1); | 
| + | 
| EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); | 
| EXPECT_TRUE(QuicConnectionPeer::GetPacketCreator( | 
| &connection_)->IsFecEnabled()); | 
| +  QuicSentPacketManager* manager = | 
| +      QuicConnectionPeer::GetSentPacketManager(&connection_); | 
|  | 
| -  // 3 Data and 3 FEC packet. | 
| +  // 1 Data packet and 1 FEC packet. | 
| EXPECT_CALL(*send_algorithm_, | 
| -              OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(6); | 
| +              OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(2); | 
| connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr); | 
| -  // Send some more data afterwards to ensure early retransmit doesn't trigger. | 
| -  connection_.SendStreamDataWithStringWithFec(3, "foo", 3, !kFin, nullptr); | 
| -  // Advance the time so not all the FEC packets are abandoned. | 
| -  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); | 
| -  connection_.SendStreamDataWithStringWithFec(3, "foo", 6, !kFin, nullptr); | 
| - | 
| -  QuicAckFrame ack_fec = InitAckFrame(5); | 
| -  // Ack all data packets, but no fec packets. | 
| -  NackPacket(2, &ack_fec); | 
| -  NackPacket(4, &ack_fec); | 
| - | 
| -  // Lose the first FEC packet and ack the three data packets. | 
| -  SequenceNumberSet lost_packets; | 
| -  lost_packets.insert(2); | 
| -  EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) | 
| -      .WillOnce(Return(lost_packets)); | 
| + | 
| +  // Ack data packet, but not FEC packet. | 
| +  QuicAckFrame ack = InitAckFrame(1); | 
| EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); | 
| -  ProcessAckPacket(&ack_fec); | 
| +  ProcessAckPacket(&ack); | 
|  | 
| -  clock_.AdvanceTime(DefaultRetransmissionTime().Subtract( | 
| -      QuicTime::Delta::FromMilliseconds(1))); | 
| +  // No TLP alarm for FEC, so when retransmission alarm fires, it is an RTO. | 
| +  EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); | 
| +  EXPECT_LT(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager)); | 
| +  QuicTime rto_time = connection_.GetRetransmissionAlarm()->deadline(); | 
| +  EXPECT_NE(QuicTime::Zero(), rto_time); | 
|  | 
| -  // Abandon all packets | 
| +  // Simulate the retransmission alarm firing. FEC packet is no longer | 
| +  // outstanding. | 
| EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(false)); | 
| +  clock_.AdvanceTime(rto_time.Subtract(clock_.Now())); | 
| connection_.GetRetransmissionAlarm()->Fire(); | 
| - | 
| -  // Ensure the alarm is not set since all packets have been abandoned. | 
| EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); | 
| +  EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager)); | 
| } | 
|  | 
| TEST_P(QuicConnectionTest, FramePacking) { | 
| @@ -3026,8 +3068,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentClose) { | 
| CryptoHandshakeMessage msg; | 
| string error_details; | 
| QuicConfig client_config; | 
| -  client_config.SetInitialFlowControlWindowToSend( | 
| -      kInitialSessionFlowControlWindowForTest); | 
| client_config.SetInitialStreamFlowControlWindowToSend( | 
| kInitialStreamFlowControlWindowForTest); | 
| client_config.SetInitialSessionFlowControlWindowToSend( | 
|  |