Index: net/quic/quic_connection_test.cc |
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc |
index dbb29212cf52d78d833b804387b1d27edc7fd21d..63cf071578ead3cadf7629bc6f8b999ba7bb6d8e 100644 |
--- a/net/quic/quic_connection_test.cc |
+++ b/net/quic/quic_connection_test.cc |
@@ -24,6 +24,7 @@ |
#include "net/quic/test_tools/quic_connection_peer.h" |
#include "net/quic/test_tools/quic_framer_peer.h" |
#include "net/quic/test_tools/quic_packet_creator_peer.h" |
+#include "net/quic/test_tools/quic_packet_generator_peer.h" |
#include "net/quic/test_tools/quic_sent_packet_manager_peer.h" |
#include "net/quic/test_tools/quic_test_utils.h" |
#include "net/quic/test_tools/simple_quic_framer.h" |
@@ -564,6 +565,11 @@ class TestConnection : public QuicConnection { |
QuicConnectionPeer::GetPingAlarm(this)); |
} |
+ TestConnectionHelper::TestAlarm* GetFecAlarm() { |
+ return reinterpret_cast<TestConnectionHelper::TestAlarm*>( |
+ QuicConnectionPeer::GetFecAlarm(this)); |
+ } |
+ |
TestConnectionHelper::TestAlarm* GetResumeWritesAlarm() { |
return reinterpret_cast<TestConnectionHelper::TestAlarm*>( |
QuicConnectionPeer::GetResumeWritesAlarm(this)); |
@@ -633,8 +639,15 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> { |
helper_(new TestConnectionHelper(&clock_, &random_generator_)), |
writer_(new TestPacketWriter(version(), &clock_)), |
factory_(writer_.get()), |
- connection_(connection_id_, IPEndPoint(), helper_.get(), |
- factory_, false, version()), |
+ connection_(connection_id_, |
+ IPEndPoint(), |
+ helper_.get(), |
+ factory_, |
+ false, |
+ version()), |
+ creator_(QuicConnectionPeer::GetPacketCreator(&connection_)), |
+ generator_(QuicConnectionPeer::GetPacketGenerator(&connection_)), |
+ manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)), |
frame1_(1, false, 0, MakeIOVector(data1)), |
frame2_(1, false, 3, MakeIOVector(data2)), |
sequence_number_length_(PACKET_6BYTE_SEQUENCE_NUMBER), |
@@ -834,8 +847,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> { |
.WillOnce(DoAll(SaveArg<3>(&packet_size), Return(true))); |
connection_.SendStreamDataWithString(id, data, offset, fin, nullptr); |
if (last_packet != nullptr) { |
- *last_packet = |
- QuicConnectionPeer::GetPacketCreator(&connection_)->sequence_number(); |
+ *last_packet = creator_->sequence_number(); |
} |
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) |
.Times(AnyNumber()); |
@@ -1024,6 +1036,9 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> { |
scoped_ptr<TestPacketWriter> writer_; |
NiceMock<MockPacketWriterFactory> factory_; |
TestConnection connection_; |
+ QuicPacketCreator* creator_; |
+ QuicPacketGenerator* generator_; |
+ QuicSentPacketManager* manager_; |
StrictMock<MockConnectionVisitor> visitor_; |
QuicPacketHeader header_; |
@@ -1174,10 +1189,8 @@ TEST_P(QuicConnectionTest, TruncatedAck) { |
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); |
ProcessAckPacket(&frame); |
- const QuicSentPacketManager& sent_packet_manager = |
- connection_.sent_packet_manager(); |
// A truncated ack will not have the true largest observed. |
- EXPECT_GT(num_packets, sent_packet_manager.largest_observed()); |
+ EXPECT_GT(num_packets, manager_->largest_observed()); |
AckPacket(192, &frame); |
@@ -1187,7 +1200,7 @@ TEST_P(QuicConnectionTest, TruncatedAck) { |
.WillOnce(Return(SequenceNumberSet())); |
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); |
ProcessAckPacket(&frame); |
- EXPECT_EQ(num_packets, sent_packet_manager.largest_observed()); |
+ EXPECT_EQ(num_packets, manager_->largest_observed()); |
} |
TEST_P(QuicConnectionTest, AckReceiptCausesAckSendBadEntropy) { |
@@ -1415,12 +1428,10 @@ TEST_P(QuicConnectionTest, AckAll) { |
TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) { |
QuicPacketSequenceNumber last_packet; |
- QuicPacketCreator* creator = |
- QuicConnectionPeer::GetPacketCreator(&connection_); |
SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); |
EXPECT_EQ(1u, last_packet); |
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, |
- creator->next_sequence_number_length()); |
+ creator_->next_sequence_number_length()); |
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, |
writer_->header().public_header.sequence_number_length); |
@@ -1430,7 +1441,7 @@ TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) { |
SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet); |
EXPECT_EQ(2u, last_packet); |
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER, |
- creator->next_sequence_number_length()); |
+ creator_->next_sequence_number_length()); |
// The 1 packet lag is due to the sequence number length being recalculated in |
// QuicConnection after a packet is sent. |
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, |
@@ -1442,7 +1453,7 @@ TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) { |
SendStreamDataToPeer(1, "foo", 6, !kFin, &last_packet); |
EXPECT_EQ(3u, last_packet); |
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER, |
- creator->next_sequence_number_length()); |
+ creator_->next_sequence_number_length()); |
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER, |
writer_->header().public_header.sequence_number_length); |
@@ -1452,7 +1463,7 @@ TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) { |
SendStreamDataToPeer(1, "bar", 9, !kFin, &last_packet); |
EXPECT_EQ(4u, last_packet); |
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER, |
- creator->next_sequence_number_length()); |
+ creator_->next_sequence_number_length()); |
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER, |
writer_->header().public_header.sequence_number_length); |
@@ -1462,7 +1473,7 @@ TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) { |
SendStreamDataToPeer(1, "foo", 12, !kFin, &last_packet); |
EXPECT_EQ(5u, last_packet); |
EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER, |
- creator->next_sequence_number_length()); |
+ creator_->next_sequence_number_length()); |
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER, |
writer_->header().public_header.sequence_number_length); |
} |
@@ -1472,44 +1483,42 @@ TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) { |
TEST_P(QuicConnectionTest, |
DISABLED_SendingDifferentSequenceNumberLengthsUnackedDelta) { |
QuicPacketSequenceNumber last_packet; |
- QuicPacketCreator* creator = |
- QuicConnectionPeer::GetPacketCreator(&connection_); |
SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); |
EXPECT_EQ(1u, last_packet); |
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, |
- creator->next_sequence_number_length()); |
+ creator_->next_sequence_number_length()); |
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, |
writer_->header().public_header.sequence_number_length); |
- creator->set_sequence_number(100); |
+ creator_->set_sequence_number(100); |
SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet); |
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER, |
- creator->next_sequence_number_length()); |
+ creator_->next_sequence_number_length()); |
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, |
writer_->header().public_header.sequence_number_length); |
- creator->set_sequence_number(100 * 256); |
+ creator_->set_sequence_number(100 * 256); |
SendStreamDataToPeer(1, "foo", 6, !kFin, &last_packet); |
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER, |
- creator->next_sequence_number_length()); |
+ creator_->next_sequence_number_length()); |
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER, |
writer_->header().public_header.sequence_number_length); |
- creator->set_sequence_number(100 * 256 * 256); |
+ creator_->set_sequence_number(100 * 256 * 256); |
SendStreamDataToPeer(1, "bar", 9, !kFin, &last_packet); |
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER, |
- creator->next_sequence_number_length()); |
+ creator_->next_sequence_number_length()); |
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER, |
writer_->header().public_header.sequence_number_length); |
- creator->set_sequence_number(100 * 256 * 256 * 256); |
+ creator_->set_sequence_number(100 * 256 * 256 * 256); |
SendStreamDataToPeer(1, "foo", 12, !kFin, &last_packet); |
EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER, |
- creator->next_sequence_number_length()); |
+ creator_->next_sequence_number_length()); |
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER, |
writer_->header().public_header.sequence_number_length); |
} |
@@ -1635,8 +1644,6 @@ TEST_P(QuicConnectionTest, RecordSentTimeBeforePacketSent) { |
TEST_P(QuicConnectionTest, FECSending) { |
// All packets carry version info till version is negotiated. |
- QuicPacketCreator* creator = |
- QuicConnectionPeer::GetPacketCreator(&connection_); |
size_t payload_length; |
// GetPacketLengthForOneStream() assumes a stream offset of 0 in determining |
// packet length. The size of the offset field in a stream frame is 0 for |
@@ -1647,7 +1654,7 @@ TEST_P(QuicConnectionTest, FECSending) { |
connection_.version(), kIncludeVersion, |
PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_SEQUENCE_NUMBER, |
IN_FEC_GROUP, &payload_length); |
- creator->set_max_packet_length(length); |
+ creator_->set_max_packet_length(length); |
// Send 4 protected data packets, which should also trigger 1 FEC packet. |
EXPECT_CALL(*send_algorithm_, |
@@ -1656,58 +1663,107 @@ TEST_P(QuicConnectionTest, FECSending) { |
const string payload(payload_length * 4 + 2, 'a'); |
connection_.SendStreamDataWithStringWithFec(1, payload, 0, !kFin, nullptr); |
// Expect the FEC group to be closed after SendStreamDataWithString. |
- EXPECT_FALSE(creator->IsFecGroupOpen()); |
- EXPECT_FALSE(creator->IsFecProtected()); |
+ EXPECT_FALSE(creator_->IsFecGroupOpen()); |
+ EXPECT_FALSE(creator_->IsFecProtected()); |
} |
TEST_P(QuicConnectionTest, FECQueueing) { |
// All packets carry version info till version is negotiated. |
size_t payload_length; |
- QuicPacketCreator* creator = |
- QuicConnectionPeer::GetPacketCreator(&connection_); |
size_t length = GetPacketLengthForOneStream( |
connection_.version(), kIncludeVersion, |
PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_SEQUENCE_NUMBER, |
IN_FEC_GROUP, &payload_length); |
- creator->set_max_packet_length(length); |
- EXPECT_TRUE(creator->IsFecEnabled()); |
+ creator_->set_max_packet_length(length); |
+ EXPECT_TRUE(creator_->IsFecEnabled()); |
EXPECT_EQ(0u, connection_.NumQueuedPackets()); |
BlockOnNextWrite(); |
const string payload(payload_length, 'a'); |
connection_.SendStreamDataWithStringWithFec(1, payload, 0, !kFin, nullptr); |
- EXPECT_FALSE(creator->IsFecGroupOpen()); |
- EXPECT_FALSE(creator->IsFecProtected()); |
+ EXPECT_FALSE(creator_->IsFecGroupOpen()); |
+ EXPECT_FALSE(creator_->IsFecProtected()); |
// Expect the first data packet and the fec packet to be queued. |
EXPECT_EQ(2u, connection_.NumQueuedPackets()); |
} |
+TEST_P(QuicConnectionTest, FECAlarmStoppedWhenFECPacketSent) { |
+ EXPECT_TRUE(creator_->IsFecEnabled()); |
+ EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
+ |
+ creator_->set_max_packets_per_fec_group(2); |
+ |
+ // 1 Data packet. FEC alarm should be set. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.SendStreamDataWithStringWithFec(3, "foo", 0, true, nullptr); |
+ EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); |
+ |
+ // Second data packet triggers FEC packet out. FEC alarm should not be set. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(2); |
+ connection_.SendStreamDataWithStringWithFec(5, "foo", 0, true, nullptr); |
+ EXPECT_TRUE(writer_->header().fec_flag); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
+} |
+ |
+TEST_P(QuicConnectionTest, FECAlarmStoppedOnConnectionClose) { |
+ EXPECT_TRUE(creator_->IsFecEnabled()); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
+ creator_->set_max_packets_per_fec_group(100); |
+ |
+ // 1 Data packet. FEC alarm should be set. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr); |
+ EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); |
+ |
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NO_ERROR, false)); |
+ // Closing connection should stop the FEC alarm. |
+ connection_.CloseConnection(QUIC_NO_ERROR, /*from_peer=*/false); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
+} |
+ |
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)); |
+ EXPECT_TRUE(creator_->IsFecEnabled()); |
+ EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
- // 1 Data and 1 FEC packet. |
+ // 1 Data packet. FEC alarm should be set. |
EXPECT_CALL(*send_algorithm_, |
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(2); |
+ OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr); |
- size_t data_and_fec = QuicSentPacketManagerPeer::GetBytesInFlight(manager); |
- EXPECT_LT(0u, data_and_fec); |
+ EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); |
+ size_t protected_packet = |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_); |
+ // Force FEC timeout to send FEC packet out. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, 2u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.GetFecAlarm()->Fire(); |
+ EXPECT_TRUE(writer_->header().fec_flag); |
+ |
+ size_t fec_packet = protected_packet; |
+ EXPECT_EQ(protected_packet + fec_packet, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
clock_.AdvanceTime(DefaultRetransmissionTime()); |
- // On RTO, both data and FEC packets are removed from inflight, |
- // and retransmission of the data (but not FEC) gets added into the inflight. |
+ // On RTO, both data and FEC packets are removed from inflight, only the data |
+ // packet is retransmitted, and this retransmission (but not FEC) gets added |
+ // back into the inflight. |
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); |
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); |
connection_.GetRetransmissionAlarm()->Fire(); |
- size_t data_only = QuicSentPacketManagerPeer::GetBytesInFlight(manager); |
- EXPECT_LT(0u, data_only); |
- EXPECT_GE(data_and_fec, 2 * data_only); |
+ // The retransmission of packet 1 will be 3 bytes smaller than packet 1, since |
+ // the first transmission will have 1 byte for FEC group number and 2 bytes of |
+ // stream frame size, which are absent in the retransmission. |
+ size_t retransmitted_packet = protected_packet - 3; |
+ EXPECT_EQ(retransmitted_packet, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
// Receive ack for the retransmission. No data should be outstanding. |
QuicAckFrame ack = InitAckFrame(3); |
@@ -1718,34 +1774,53 @@ TEST_P(QuicConnectionTest, RemoveFECFromInflightOnRetransmissionTimeout) { |
.WillOnce(Return(lost_packets)); |
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); |
ProcessAckPacket(&ack); |
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager)); |
+ 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)); |
+ EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
} |
TEST_P(QuicConnectionTest, RemoveFECFromInflightOnLossRetransmission) { |
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
- EXPECT_TRUE(QuicConnectionPeer::GetPacketCreator( |
- &connection_)->IsFecEnabled()); |
- QuicSentPacketManager* manager = |
- QuicConnectionPeer::GetSentPacketManager(&connection_); |
+ EXPECT_TRUE(creator_->IsFecEnabled()); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
- // 1 Data packet and 1 FEC packet, followed by more data to trigger NACKs. |
+ // 1 FEC-protected data packet. FEC alarm should be set. |
EXPECT_CALL(*send_algorithm_, |
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(6); |
- connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr); |
- 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 |
+ OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr); |
+ EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); |
+ size_t protected_packet = |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_); |
+ |
+ // Force FEC timeout to send FEC packet out. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.GetFecAlarm()->Fire(); |
+ EXPECT_TRUE(writer_->header().fec_flag); |
+ size_t fec_packet = protected_packet; |
+ EXPECT_EQ(protected_packet + fec_packet, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ |
+ // Send more data to trigger NACKs. Note that all data starts at stream offset |
+ // 0 to ensure the same packet size, for ease of testing. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(4); |
+ connection_.SendStreamDataWithString(5, "foo", 0, kFin, nullptr); |
+ connection_.SendStreamDataWithString(7, "foo", 0, kFin, nullptr); |
+ connection_.SendStreamDataWithString(9, "foo", 0, kFin, nullptr); |
+ connection_.SendStreamDataWithString(11, "foo", 0, kFin, nullptr); |
+ |
+ // An unprotected packet will be 3 bytes smaller than an FEC-protected packet, |
+ // since the protected packet will have 1 byte for FEC group number and |
+ // 2 bytes of stream frame size, which are absent in the unprotected packet. |
+ size_t unprotected_packet = protected_packet - 3; |
+ EXPECT_EQ(protected_packet + fec_packet + 4 * unprotected_packet, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
+ |
+ // Ack data packets, and NACK FEC packet and one data packet. Triggers |
+ // NACK-based loss detection of both packets, but only data packet is |
// retransmitted and considered oustanding. |
QuicAckFrame ack = InitAckFrame(6); |
NackPacket(2, &ack); |
@@ -1758,10 +1833,13 @@ TEST_P(QuicConnectionTest, RemoveFECFromInflightOnLossRetransmission) { |
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); |
EXPECT_CALL(*send_algorithm_, |
OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
ProcessAckPacket(&ack); |
- size_t data_only = QuicSentPacketManagerPeer::GetBytesInFlight(manager); |
- EXPECT_GT(multiple_data_and_fec, data_only); |
- EXPECT_LT(0u, data_only); |
+ // On receiving this ack from the server, the client will no longer send |
+ // version number in subsequent packets, including in this retransmission. |
+ size_t unprotected_packet_no_version = unprotected_packet - 4; |
+ EXPECT_EQ(unprotected_packet_no_version, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
// Receive ack for the retransmission. No data should be outstanding. |
QuicAckFrame ack2 = InitAckFrame(7); |
@@ -1772,33 +1850,150 @@ TEST_P(QuicConnectionTest, RemoveFECFromInflightOnLossRetransmission) { |
.WillOnce(Return(lost_packets2)); |
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); |
ProcessAckPacket(&ack2); |
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager)); |
+ EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
} |
-TEST_P(QuicConnectionTest, NoTLPForFECPacket) { |
+TEST_P(QuicConnectionTest, FECRemainsInflightOnTLPOfEarlierData) { |
+ // This test checks if TLP is sent correctly when a data and an FEC packet |
+ // are outstanding. TLP should be sent for the data packet when the |
+ // retransmission alarm fires. |
// Turn on TLP for this test. |
- QuicSentPacketManagerPeer::SetMaxTailLossProbes( |
- QuicConnectionPeer::GetSentPacketManager(&connection_), 1); |
+ QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1); |
+ EXPECT_TRUE(creator_->IsFecEnabled()); |
+ EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
+ |
+ // 1 Data packet. FEC alarm should be set. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr); |
+ EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); |
+ size_t protected_packet = |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_); |
+ EXPECT_LT(0u, protected_packet); |
+ |
+ // Force FEC timeout to send FEC packet out. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, 2u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.GetFecAlarm()->Fire(); |
+ EXPECT_TRUE(writer_->header().fec_flag); |
+ size_t fec_packet = protected_packet; |
+ EXPECT_EQ(protected_packet + fec_packet, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ |
+ // TLP alarm should be set. |
+ QuicTime retransmission_time = |
+ connection_.GetRetransmissionAlarm()->deadline(); |
+ EXPECT_NE(QuicTime::Zero(), retransmission_time); |
+ // Simulate the retransmission alarm firing and sending a TLP, so send |
+ // algorithm's OnRetransmissionTimeout is not called. |
+ clock_.AdvanceTime(retransmission_time.Subtract(clock_.Now())); |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, 3u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.GetRetransmissionAlarm()->Fire(); |
+ // The TLP retransmission of packet 1 will be 3 bytes smaller than packet 1, |
+ // since packet 1 will have 1 byte for FEC group number and 2 bytes of stream |
+ // frame size, which are absent in the the TLP retransmission. |
+ size_t tlp_packet = protected_packet - 3; |
+ EXPECT_EQ(protected_packet + fec_packet + tlp_packet, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+} |
+ |
+TEST_P(QuicConnectionTest, FECRemainsInflightOnTLPOfLaterData) { |
+ // Tests if TLP is sent correctly when data packet 1 and an FEC packet are |
+ // sent followed by data packet 2, and data packet 1 is acked. TLP should be |
+ // sent for data packet 2 when the retransmission alarm fires. Turn on TLP for |
+ // this test. |
+ QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1); |
+ EXPECT_TRUE(creator_->IsFecEnabled()); |
+ EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
+ |
+ // 1 Data packet. FEC alarm should be set. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr); |
+ EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); |
+ size_t protected_packet = |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_); |
+ EXPECT_LT(0u, protected_packet); |
+ |
+ // Force FEC timeout to send FEC packet out. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, 2u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.GetFecAlarm()->Fire(); |
+ EXPECT_TRUE(writer_->header().fec_flag); |
+ // Protected data packet and FEC packet oustanding. |
+ size_t fec_packet = protected_packet; |
+ EXPECT_EQ(protected_packet + fec_packet, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ |
+ // Send 1 unprotected data packet. No FEC alarm should be set. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, 3u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.SendStreamDataWithString(5, "foo", 0, kFin, nullptr); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
+ // Protected data packet, FEC packet, and unprotected data packet oustanding. |
+ // An unprotected packet will be 3 bytes smaller than an FEC-protected packet, |
+ // since the protected packet will have 1 byte for FEC group number and |
+ // 2 bytes of stream frame size, which are absent in the unprotected packet. |
+ size_t unprotected_packet = protected_packet - 3; |
+ EXPECT_EQ(protected_packet + fec_packet + unprotected_packet, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ |
+ // Receive ack for first data packet. FEC and second data packet are still |
+ // outstanding. |
+ QuicAckFrame ack = InitAckFrame(1); |
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); |
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
+ ProcessAckPacket(&ack); |
+ // FEC packet and unprotected data packet oustanding. |
+ EXPECT_EQ(fec_packet + unprotected_packet, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+ |
+ // TLP alarm should be set. |
+ QuicTime retransmission_time = |
+ connection_.GetRetransmissionAlarm()->deadline(); |
+ EXPECT_NE(QuicTime::Zero(), retransmission_time); |
+ // Simulate the retransmission alarm firing and sending a TLP, so send |
+ // algorithm's OnRetransmissionTimeout is not called. |
+ clock_.AdvanceTime(retransmission_time.Subtract(clock_.Now())); |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, 4u, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.GetRetransmissionAlarm()->Fire(); |
+ // Having received an ack from the server, the client will no longer send |
+ // version number in subsequent packets, including in this retransmission. |
+ size_t tlp_packet_no_version = unprotected_packet - 4; |
+ EXPECT_EQ(fec_packet + unprotected_packet + tlp_packet_no_version, |
+ QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
+} |
+ |
+TEST_P(QuicConnectionTest, NoTLPForFECPacket) { |
+ // Turn on TLP for this test. |
+ QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1); |
+ EXPECT_TRUE(creator_->IsFecEnabled()); |
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
- EXPECT_TRUE(QuicConnectionPeer::GetPacketCreator( |
- &connection_)->IsFecEnabled()); |
- QuicSentPacketManager* manager = |
- QuicConnectionPeer::GetSentPacketManager(&connection_); |
- // 1 Data packet and 1 FEC packet. |
+ // Send 1 FEC-protected data packet. FEC alarm should be set. |
EXPECT_CALL(*send_algorithm_, |
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(2); |
+ OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr); |
+ EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); |
+ // Force FEC timeout to send FEC packet out. |
+ EXPECT_CALL(*send_algorithm_, |
+ OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(1); |
+ connection_.GetFecAlarm()->Fire(); |
+ EXPECT_TRUE(writer_->header().fec_flag); |
// Ack data packet, but not FEC packet. |
QuicAckFrame ack = InitAckFrame(1); |
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); |
ProcessAckPacket(&ack); |
- // No TLP alarm for FEC, so when retransmission alarm fires, it is an RTO. |
+ // No TLP alarm for FEC, but retransmission alarm should be set for an RTO. |
+ EXPECT_LT(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); |
- EXPECT_LT(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager)); |
QuicTime rto_time = connection_.GetRetransmissionAlarm()->deadline(); |
EXPECT_NE(QuicTime::Zero(), rto_time); |
@@ -1808,7 +2003,7 @@ TEST_P(QuicConnectionTest, NoTLPForFECPacket) { |
clock_.AdvanceTime(rto_time.Subtract(clock_.Now())); |
connection_.GetRetransmissionAlarm()->Fire(); |
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); |
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager)); |
+ EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); |
} |
TEST_P(QuicConnectionTest, FramePacking) { |
@@ -1887,13 +2082,12 @@ TEST_P(QuicConnectionTest, FramePackingCryptoThenNonCrypto) { |
} |
TEST_P(QuicConnectionTest, FramePackingFEC) { |
- EXPECT_TRUE(QuicConnectionPeer::GetPacketCreator( |
- &connection_)->IsFecEnabled()); |
+ EXPECT_TRUE(creator_->IsFecEnabled()); |
CongestionBlockWrites(); |
// Queue an ack and two stream frames. Ack gets flushed when FEC is turned on |
- // for sending protected data; two stream frames are packing in 1 packet. |
+ // for sending protected data; two stream frames are packed in 1 packet. |
EXPECT_CALL(visitor_, OnCanWrite()).WillOnce(DoAll( |
IgnoreResult(InvokeWithoutArgs( |
&connection_, &TestConnection::SendStreamData3WithFec)), |
@@ -1901,7 +2095,7 @@ TEST_P(QuicConnectionTest, FramePackingFEC) { |
&connection_, &TestConnection::SendStreamData5WithFec)))); |
connection_.SendAck(); |
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3); |
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); |
CongestionUnblockWrites(); |
connection_.GetSendAlarm()->Fire(); |
EXPECT_EQ(0u, connection_.NumQueuedPackets()); |
@@ -1909,7 +2103,10 @@ TEST_P(QuicConnectionTest, FramePackingFEC) { |
// Parse the last packet and ensure it's in an fec group. |
EXPECT_EQ(2u, writer_->header().fec_group); |
- EXPECT_EQ(0u, writer_->frame_count()); |
+ EXPECT_EQ(2u, writer_->frame_count()); |
+ |
+ // FEC alarm should be set. |
+ EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); |
} |
TEST_P(QuicConnectionTest, FramePackingAckResponse) { |
@@ -2431,8 +2628,7 @@ TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPackets) { |
} |
TEST_P(QuicConnectionTest, TLP) { |
- QuicSentPacketManagerPeer::SetMaxTailLossProbes( |
- QuicConnectionPeer::GetSentPacketManager(&connection_), 1); |
+ QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1); |
SendStreamDataToPeer(3, "foo", 0, !kFin, nullptr); |
EXPECT_EQ(1u, stop_waiting()->least_unacked); |
@@ -2926,6 +3122,7 @@ TEST_P(QuicConnectionTest, InitialTimeout) { |
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); |
EXPECT_FALSE(connection_.GetPingAlarm()->IsSet()); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
EXPECT_FALSE(connection_.GetResumeWritesAlarm()->IsSet()); |
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); |
EXPECT_FALSE(connection_.GetSendAlarm()->IsSet()); |
@@ -2968,6 +3165,7 @@ TEST_P(QuicConnectionTest, OverallTimeout) { |
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); |
EXPECT_FALSE(connection_.GetPingAlarm()->IsSet()); |
+ EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); |
EXPECT_FALSE(connection_.GetResumeWritesAlarm()->IsSet()); |
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); |
EXPECT_FALSE(connection_.GetSendAlarm()->IsSet()); |
@@ -3139,8 +3337,7 @@ TEST_P(QuicConnectionTest, TestQueueLimitsOnSendStreamData) { |
connection_.version(), kIncludeVersion, |
PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_SEQUENCE_NUMBER, |
NOT_IN_FEC_GROUP, &payload_length); |
- QuicConnectionPeer::GetPacketCreator(&connection_)->set_max_packet_length( |
- length); |
+ creator_->set_max_packet_length(length); |
// Queue the first packet. |
EXPECT_CALL(*send_algorithm_, |
@@ -3164,8 +3361,7 @@ TEST_P(QuicConnectionTest, LoopThroughSendingPackets) { |
connection_.version(), kIncludeVersion, |
PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_SEQUENCE_NUMBER, |
NOT_IN_FEC_GROUP, &payload_length); |
- QuicConnectionPeer::GetPacketCreator(&connection_)->set_max_packet_length( |
- length); |
+ creator_->set_max_packet_length(length); |
// Queue the first packet. |
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(7); |
@@ -3738,8 +3934,7 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) { |
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted); |
- ASSERT_FALSE(QuicPacketCreatorPeer::SendVersionInPacket( |
- QuicConnectionPeer::GetPacketCreator(&connection_))); |
+ ASSERT_FALSE(QuicPacketCreatorPeer::SendVersionInPacket(creator_)); |
} |
TEST_P(QuicConnectionTest, BadVersionNegotiation) { |
@@ -4175,32 +4370,25 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterFECRecovery) { |
} |
TEST_P(QuicConnectionTest, NetworkChangeVisitorCwndCallbackChangesFecState) { |
- QuicPacketCreator* creator = |
- QuicConnectionPeer::GetPacketCreator(&connection_); |
- size_t max_packets_per_fec_group = creator->max_packets_per_fec_group(); |
+ size_t max_packets_per_fec_group = creator_->max_packets_per_fec_group(); |
QuicSentPacketManager::NetworkChangeVisitor* visitor = |
- QuicSentPacketManagerPeer::GetNetworkChangeVisitor( |
- QuicConnectionPeer::GetSentPacketManager(&connection_)); |
+ QuicSentPacketManagerPeer::GetNetworkChangeVisitor(manager_); |
EXPECT_TRUE(visitor); |
// Increase FEC group size by increasing congestion window to a large number. |
EXPECT_CALL(*send_algorithm_, GetCongestionWindow()).WillRepeatedly( |
Return(1000 * kDefaultTCPMSS)); |
visitor->OnCongestionWindowChange(); |
- EXPECT_LT(max_packets_per_fec_group, creator->max_packets_per_fec_group()); |
+ EXPECT_LT(max_packets_per_fec_group, creator_->max_packets_per_fec_group()); |
} |
TEST_P(QuicConnectionTest, NetworkChangeVisitorConfigCallbackChangesFecState) { |
- QuicSentPacketManager* sent_packet_manager = |
- QuicConnectionPeer::GetSentPacketManager(&connection_); |
QuicSentPacketManager::NetworkChangeVisitor* visitor = |
- QuicSentPacketManagerPeer::GetNetworkChangeVisitor(sent_packet_manager); |
+ QuicSentPacketManagerPeer::GetNetworkChangeVisitor(manager_); |
EXPECT_TRUE(visitor); |
- |
- QuicPacketGenerator* generator = |
- QuicConnectionPeer::GetPacketGenerator(&connection_); |
- EXPECT_EQ(QuicTime::Delta::Zero(), generator->fec_timeout()); |
+ EXPECT_EQ(QuicTime::Delta::Zero(), |
+ QuicPacketGeneratorPeer::GetFecTimeout(generator_)); |
// Verify that sending a config with a new initial rtt changes fec timeout. |
// Create and process a config with a non-zero initial RTT. |
@@ -4208,28 +4396,25 @@ TEST_P(QuicConnectionTest, NetworkChangeVisitorConfigCallbackChangesFecState) { |
QuicConfig config; |
config.SetInitialRoundTripTimeUsToSend(300000); |
connection_.SetFromConfig(config); |
- EXPECT_LT(QuicTime::Delta::Zero(), generator->fec_timeout()); |
+ EXPECT_LT(QuicTime::Delta::Zero(), |
+ QuicPacketGeneratorPeer::GetFecTimeout(generator_)); |
} |
TEST_P(QuicConnectionTest, NetworkChangeVisitorRttCallbackChangesFecState) { |
// Verify that sending a config with a new initial rtt changes fec timeout. |
- QuicSentPacketManager* sent_packet_manager = |
- QuicConnectionPeer::GetSentPacketManager(&connection_); |
QuicSentPacketManager::NetworkChangeVisitor* visitor = |
- QuicSentPacketManagerPeer::GetNetworkChangeVisitor(sent_packet_manager); |
+ QuicSentPacketManagerPeer::GetNetworkChangeVisitor(manager_); |
EXPECT_TRUE(visitor); |
- |
- QuicPacketGenerator* generator = |
- QuicConnectionPeer::GetPacketGenerator(&connection_); |
- EXPECT_EQ(QuicTime::Delta::Zero(), generator->fec_timeout()); |
+ EXPECT_EQ(QuicTime::Delta::Zero(), |
+ QuicPacketGeneratorPeer::GetFecTimeout(generator_)); |
// Increase FEC timeout by increasing RTT. |
- RttStats* rtt_stats = |
- QuicSentPacketManagerPeer::GetRttStats(sent_packet_manager); |
+ RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager_); |
rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(300), |
QuicTime::Delta::Zero(), QuicTime::Zero()); |
visitor->OnRttChange(); |
- EXPECT_LT(QuicTime::Delta::Zero(), generator->fec_timeout()); |
+ EXPECT_LT(QuicTime::Delta::Zero(), |
+ QuicPacketGeneratorPeer::GetFecTimeout(generator_)); |
} |
class MockQuicConnectionDebugVisitor |