namespace test {
namespace {
-class MockHelper : public QuicSentPacketManager::HelperInterface {
- public:
- MOCK_METHOD0(GetNextPacketSequenceNumber, QuicPacketSequenceNumber());
-};
-
class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
protected:
QuicSentPacketManagerTest()
- : manager_(true, &helper_, &clock_, kFixRate),
+ : manager_(true, &clock_, &stats_, kFixRate),
send_algorithm_(new StrictMock<MockSendAlgorithm>) {
QuicSentPacketManagerPeer::SetSendAlgorithm(&manager_, send_algorithm_);
// Disable tail loss probes for most tests.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000));
}
- ~QuicSentPacketManagerTest() {
+ virtual ~QuicSentPacketManagerTest() {
STLDeleteElements(&packets_);
}
HAS_RETRANSMITTABLE_DATA);
}
+ void SendFecPacket(QuicPacketSequenceNumber sequence_number) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, sequence_number, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ SerializedPacket packet(CreateFecPacket(sequence_number));
+ manager_.OnSerializedPacket(packet);
+ manager_.OnPacketSent(sequence_number, clock_.ApproximateNow(),
+ packet.packet->length(), NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA);
+ }
+
// Based on QuicConnection's WritePendingRetransmissions.
void RetransmitNextPacket(
QuicPacketSequenceNumber retransmission_sequence_number) {
pending.transmission_type, HAS_RETRANSMITTABLE_DATA);
}
- testing::StrictMock<MockHelper> helper_;
QuicSentPacketManager manager_;
vector<QuicPacket*> packets_;
MockClock clock_;
+ QuicConnectionStats stats_;
MockSendAlgorithm* send_algorithm_;
};
}
TEST_F(QuicSentPacketManagerTest, IsUnAckedRetransmit) {
- SerializedPacket serialized_packet(CreateDataPacket(1));
-
- manager_.OnSerializedPacket(serialized_packet);
+ SendDataPacket(1);
RetransmitPacket(1, 2);
EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_, 2));
}
TEST_F(QuicSentPacketManagerTest, RetransmitThenAck) {
- SerializedPacket serialized_packet(CreateDataPacket(1));
-
- manager_.OnSerializedPacket(serialized_packet);
- RetransmitPacket(1, 2);
+ SendDataPacket(1);
+ RetransmitAndSendPacket(1, 2);
// Ack 2 but not 1.
ReceivedPacketInfo received_info;
received_info.largest_observed = 2;
received_info.missing_packets.insert(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(2, _)).Times(1);
manager_.OnIncomingAck(received_info, QuicTime::Zero());
- // No unacked packets remain.
- VerifyUnackedPackets(NULL, 0);
+ // Packet 1 is unacked, pending, but not retransmittable.
+ QuicPacketSequenceNumber unacked[] = { 1 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
VerifyRetransmittablePackets(NULL, 0);
}
TEST_F(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
- SerializedPacket serialized_packet(CreateDataPacket(1));
-
- manager_.OnSerializedPacket(serialized_packet);
+ SendDataPacket(1);
QuicSentPacketManagerPeer::MarkForRetransmission(
&manager_, 1, NACK_RETRANSMISSION);
EXPECT_TRUE(manager_.HasPendingRetransmissions());
// Ack 1.
ReceivedPacketInfo received_info;
received_info.largest_observed = 1;
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _)).Times(1);
manager_.OnIncomingAck(received_info, QuicTime::Zero());
// There should no longer be a pending retransmission.
// No unacked packets remain.
VerifyUnackedPackets(NULL, 0);
VerifyRetransmittablePackets(NULL, 0);
+ EXPECT_EQ(0u, stats_.packets_spuriously_retransmitted);
}
TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
received_info.largest_observed = 1;
EXPECT_TRUE(manager_.OnIncomingAck(received_info, clock_.ApproximateNow()));
- // 2 remains unacked, but no packets have retransmittable data.
- QuicPacketSequenceNumber unacked[] = { 2 };
- VerifyUnackedPackets(unacked, arraysize(unacked));
+ // No packets should be unacked.
+ VerifyUnackedPackets(NULL, 0);
EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
VerifyRetransmittablePackets(NULL, 0);
// Verify that the retransmission alarm would not fire,
// since there is no retransmittable data outstanding.
EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
+ EXPECT_EQ(1u, stats_.packets_spuriously_retransmitted);
+}
+
+TEST_F(QuicSentPacketManagerTest, RetransmitAndSendThenAckPrevious) {
+ SendDataPacket(1);
+ RetransmitAndSendPacket(1, 2);
+ QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(15);
+ clock_.AdvanceTime(rtt);
+
+ // Ack 1 but not 2.
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(rtt));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _));
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 1;
+ EXPECT_TRUE(manager_.OnIncomingAck(received_info, clock_.ApproximateNow()));
+
+ // 2 remains unacked, but no packets have retransmittable data.
+ QuicPacketSequenceNumber unacked[] = { 2 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ VerifyRetransmittablePackets(NULL, 0);
+
+ EXPECT_EQ(1u, stats_.packets_spuriously_retransmitted);
}
TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
VerifyUnackedPackets(NULL, 0);
EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_EQ(1u, stats_.packets_spuriously_retransmitted);
}
-TEST_F(QuicSentPacketManagerTest, TruncatedAck) {
- SerializedPacket serialized_packet(CreateDataPacket(1));
+TEST_F(QuicSentPacketManagerTest, LoseButDontRetransmitRevivedPacket) {
+ SendDataPacket(1);
+ SendDataPacket(2);
+ SendFecPacket(3);
+ SendDataPacket(4);
- manager_.OnSerializedPacket(serialized_packet);
- RetransmitPacket(1, 2);
- RetransmitPacket(2, 3);
- RetransmitPacket(3, 4);
+ // Ack 2 and 3, and mark 1 as revived.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 3;
+ received_info.missing_packets.insert(1);
+ received_info.revived_packets.insert(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(2);
+ manager_.OnIncomingAck(received_info, clock_.ApproximateNow());
- // Truncated ack with 2 NACKs
+ EXPECT_FALSE(manager_.HasPendingRetransmissions());
+ QuicPacketSequenceNumber unacked[] = { 1, 4 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ QuicPacketSequenceNumber retransmittable[] = { 4 };
+ VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
+
+ // Ack the 4th packet and expect the 1st to be considered lost.
+ received_info.largest_observed = 4;
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(4, _));
+ manager_.OnIncomingAck(received_info, clock_.ApproximateNow());
+
+ EXPECT_FALSE(manager_.HasPendingRetransmissions());
+ VerifyRetransmittablePackets(NULL, 0);
+}
+
+TEST_F(QuicSentPacketManagerTest, TruncatedAck) {
+ SendDataPacket(1);
+ RetransmitAndSendPacket(1, 2);
+ RetransmitAndSendPacket(2, 3);
+ RetransmitAndSendPacket(3, 4);
+ RetransmitAndSendPacket(4, 5);
+
+ // Truncated ack with 4 NACKs, so the first packet is lost.
ReceivedPacketInfo received_info;
- received_info.largest_observed = 2;
+ received_info.largest_observed = 4;
received_info.missing_packets.insert(1);
received_info.missing_packets.insert(2);
+ received_info.missing_packets.insert(3);
+ received_info.missing_packets.insert(4);
received_info.is_truncated = true;
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _));
manager_.OnIncomingAck(received_info, QuicTime::Zero());
// High water mark will be raised.
}
TEST_F(QuicSentPacketManagerTest, AckPreviousTransmissionThenTruncatedAck) {
- SerializedPacket serialized_packet(CreateDataPacket(1));
-
- manager_.OnSerializedPacket(serialized_packet);
- RetransmitPacket(1, 2);
- RetransmitPacket(2, 3);
- RetransmitPacket(3, 4);
+ SendDataPacket(1);
+ RetransmitAndSendPacket(1, 2);
+ RetransmitAndSendPacket(2, 3);
+ RetransmitAndSendPacket(3, 4);
manager_.OnSerializedPacket(CreateDataPacket(5));
manager_.OnSerializedPacket(CreateDataPacket(6));
manager_.OnSerializedPacket(CreateDataPacket(7));
ReceivedPacketInfo received_info;
received_info.largest_observed = 2;
received_info.missing_packets.insert(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(2, _));
manager_.OnIncomingAck(received_info, QuicTime::Zero());
EXPECT_TRUE(manager_.IsUnacked(4));
}
received_info.missing_packets.insert(5);
received_info.missing_packets.insert(6);
received_info.is_truncated = true;
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(3, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(3, _));
manager_.OnIncomingAck(received_info, QuicTime::Zero());
}
// High water mark will be raised.
- QuicPacketSequenceNumber unacked[] = { 5, 6, 7, 8, 9 };
+ QuicPacketSequenceNumber unacked[] = { 4, 5, 6, 7, 8, 9 };
VerifyUnackedPackets(unacked, arraysize(unacked));
QuicPacketSequenceNumber retransmittable[] = { 5, 6, 7, 8, 9 };
VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
}
-TEST_F(QuicSentPacketManagerTest, SendDropAckRetransmitManyPackets) {
- manager_.OnSerializedPacket(CreateDataPacket(1));
- manager_.OnSerializedPacket(CreateDataPacket(2));
- manager_.OnSerializedPacket(CreateDataPacket(3));
-
- {
- // Ack packets 1 and 3.
- ReceivedPacketInfo received_info;
- received_info.largest_observed = 3;
- received_info.missing_packets.insert(2);
- manager_.OnIncomingAck(received_info, QuicTime::Zero());
-
- QuicPacketSequenceNumber unacked[] = { 2 };
- VerifyUnackedPackets(unacked, arraysize(unacked));
- QuicPacketSequenceNumber retransmittable[] = { 2 };
- VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
- }
-
- manager_.OnSerializedPacket(CreateDataPacket(4));
- manager_.OnSerializedPacket(CreateDataPacket(5));
-
- {
- // Ack packets 5.
- ReceivedPacketInfo received_info;
- received_info.largest_observed = 5;
- received_info.missing_packets.insert(2);
- received_info.missing_packets.insert(4);
- manager_.OnIncomingAck(received_info, QuicTime::Zero());
-
- QuicPacketSequenceNumber unacked[] = { 2, 4 };
- VerifyUnackedPackets(unacked, arraysize(unacked));
- QuicPacketSequenceNumber retransmittable[] = { 2, 4 };
- VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
- }
-
- manager_.OnSerializedPacket(CreateDataPacket(6));
- manager_.OnSerializedPacket(CreateDataPacket(7));
-
- {
- // Ack packets 7.
- ReceivedPacketInfo received_info;
- received_info.largest_observed = 7;
- received_info.missing_packets.insert(2);
- received_info.missing_packets.insert(4);
- received_info.missing_packets.insert(6);
- manager_.OnIncomingAck(received_info, QuicTime::Zero());
-
- QuicPacketSequenceNumber unacked[] = { 2, 4, 6 };
- VerifyUnackedPackets(unacked, arraysize(unacked));
- QuicPacketSequenceNumber retransmittable[] = { 2, 4, 6 };
- VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
- }
-
- RetransmitPacket(2, 8);
- manager_.OnSerializedPacket(CreateDataPacket(9));
- manager_.OnSerializedPacket(CreateDataPacket(10));
-
- {
- // Ack packet 10.
- ReceivedPacketInfo received_info;
- received_info.largest_observed = 10;
- received_info.missing_packets.insert(2);
- received_info.missing_packets.insert(4);
- received_info.missing_packets.insert(6);
- received_info.missing_packets.insert(8);
- received_info.missing_packets.insert(9);
- manager_.OnIncomingAck(received_info, QuicTime::Zero());
-
- QuicPacketSequenceNumber unacked[] = { 2, 4, 6, 8, 9 };
- VerifyUnackedPackets(unacked, arraysize(unacked));
- QuicPacketSequenceNumber retransmittable[] = { 4, 6, 8, 9 };
- VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
- }
-
-
- RetransmitPacket(4, 11);
- manager_.OnSerializedPacket(CreateDataPacket(12));
- manager_.OnSerializedPacket(CreateDataPacket(13));
-
- {
- // Ack packet 13.
- ReceivedPacketInfo received_info;
- received_info.largest_observed = 13;
- received_info.missing_packets.insert(2);
- received_info.missing_packets.insert(4);
- received_info.missing_packets.insert(6);
- received_info.missing_packets.insert(8);
- received_info.missing_packets.insert(9);
- received_info.missing_packets.insert(11);
- received_info.missing_packets.insert(12);
- manager_.OnIncomingAck(received_info, QuicTime::Zero());
-
- QuicPacketSequenceNumber unacked[] = { 2, 4, 6, 8, 9, 11, 12 };
- VerifyUnackedPackets(unacked, arraysize(unacked));
- QuicPacketSequenceNumber retransmittable[] = { 6, 8, 9, 11, 12 };
- VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
- }
-
- RetransmitPacket(6, 14);
- manager_.OnSerializedPacket(CreateDataPacket(15));
- manager_.OnSerializedPacket(CreateDataPacket(16));
-
- {
- // Ack packet 16.
- ReceivedPacketInfo received_info;
- received_info.largest_observed = 13;
- received_info.missing_packets.insert(2);
- received_info.missing_packets.insert(4);
- received_info.missing_packets.insert(6);
- received_info.missing_packets.insert(8);
- received_info.missing_packets.insert(9);
- received_info.missing_packets.insert(11);
- received_info.missing_packets.insert(12);
- received_info.is_truncated = true;
- manager_.OnIncomingAck(received_info, QuicTime::Zero());
-
- // Truncated ack raises the high water mark by clearing out 2, 4, and 6.
- QuicPacketSequenceNumber unacked[] = { 8, 9, 11, 12, 14, 15, 16 };
- VerifyUnackedPackets(unacked, arraysize(unacked));
- QuicPacketSequenceNumber retransmittable[] = { 8, 9, 11, 12, 14, 15, 16 };
- VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
- }
-}
-
TEST_F(QuicSentPacketManagerTest, GetLeastUnackedSentPacket) {
- EXPECT_CALL(helper_, GetNextPacketSequenceNumber()).WillOnce(Return(1u));
- EXPECT_EQ(1u, manager_.GetLeastUnackedSentPacket());
+ EXPECT_EQ(0u, manager_.GetLeastUnackedSentPacket());
}
TEST_F(QuicSentPacketManagerTest, GetLeastUnackedSentPacketUnacked) {
manager_.OnSerializedPacket(serialized_packet);
manager_.DiscardUnackedPacket(1u);
- EXPECT_CALL(helper_, GetNextPacketSequenceNumber()).WillOnce(Return(2u));
- EXPECT_EQ(2u, manager_.GetLeastUnackedSentPacket());
+ EXPECT_EQ(0u, manager_.GetLeastUnackedSentPacket());
}
TEST_F(QuicSentPacketManagerTest, GetLeastUnackedPacketAndDiscard) {
QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
EXPECT_EQ(i, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
}
+ EXPECT_EQ(1u, stats_.packets_lost);
}
// A stretch ack is an ack that covers more than 1 packet of previously
EXPECT_EQ(
1u, QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
EXPECT_EQ(3u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+ EXPECT_EQ(1u, stats_.packets_lost);
}
// Ack a packet 3 packets ahead, causing a retransmit.
EXPECT_EQ(
1u, QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
EXPECT_EQ(3u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+ EXPECT_EQ(1u, stats_.packets_lost);
}
TEST_F(QuicSentPacketManagerTest, EarlyRetransmit1Packet) {
EXPECT_EQ(
1u, QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
EXPECT_EQ(1u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+ EXPECT_EQ(1u, stats_.packets_lost);
}
TEST_F(QuicSentPacketManagerTest, EarlyRetransmitAllPackets) {
EXPECT_EQ(
4u, QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
EXPECT_EQ(4u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+ EXPECT_EQ(4u, stats_.packets_lost);
}
TEST_F(QuicSentPacketManagerTest, NackRetransmit2Packets) {
EXPECT_FALSE(manager_.HasPendingRetransmissions());
EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_EQ(2u, stats_.tlp_count);
+ EXPECT_EQ(0u, stats_.rto_count);
}
TEST_F(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
manager_.OnRetransmissionTimeout();
EXPECT_TRUE(manager_.HasPendingRetransmissions());
+ EXPECT_EQ(2u, stats_.tlp_count);
+ EXPECT_EQ(1u, stats_.rto_count);
}
TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
}
+TEST_F(QuicSentPacketManagerTest,
+ CryptoHandshakeRetransmissionThenRetransmitAll) {
+ // Send 1 crypto packet.
+ SendCryptoPacket(1);
+ EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+
+ // Retransmit the crypto packet as 2.
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(1);
+ manager_.OnRetransmissionTimeout();
+ RetransmitNextPacket(2);
+
+ // Now retransmit all the unacked packets, which occurs when there is a
+ // version negotiation.
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(1);
+ manager_.RetransmitUnackedPackets(ALL_PACKETS);
+ QuicPacketSequenceNumber unacked[] = { 1, 2 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ EXPECT_TRUE(manager_.HasPendingRetransmissions());
+ EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+}
+
TEST_F(QuicSentPacketManagerTest, TailLossProbeTimeoutUnsentDataPacket) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
// Serialize two data packets and send the latter.
}
TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
+ SendDataPacket(1);
EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
- .WillOnce(Return(QuicTime::Delta::FromMilliseconds(1)));
+ .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(1)));
+ QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(200);
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
- QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
+ // If the delay is smaller than the min, ensure it exponentially backs off
+ // from the min.
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_EQ(delay,
+ QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
+ delay = delay.Add(delay);
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
+ manager_.OnRetransmissionTimeout();
+ RetransmitNextPacket(i + 2);
+ }
}
TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMax) {