Index: net/quic/quic_connection_test.cc |
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc |
index 7feb87a0b28c648c6555ab39d00a889c4a662658..e4418c34ae8e147608737d70a647499816603cd0 100644 |
--- a/net/quic/quic_connection_test.cc |
+++ b/net/quic/quic_connection_test.cc |
@@ -8,6 +8,7 @@ |
#include "base/bind.h" |
#include "base/stl_util.h" |
#include "net/base/net_errors.h" |
+#include "net/quic/congestion_control/loss_detection_interface.h" |
#include "net/quic/congestion_control/receive_algorithm_interface.h" |
#include "net/quic/congestion_control/send_algorithm_interface.h" |
#include "net/quic/crypto/null_encrypter.h" |
@@ -426,6 +427,11 @@ class TestConnection : public QuicConnection { |
QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm); |
} |
+ void SetLossAlgorithm(LossDetectionInterface* loss_algorithm) { |
+ QuicSentPacketManagerPeer::SetLossAlgorithm( |
+ QuicConnectionPeer::GetSentPacketManager(this), loss_algorithm); |
+ } |
+ |
void SendPacket(EncryptionLevel level, |
QuicPacketSequenceNumber sequence_number, |
QuicPacket* packet, |
@@ -539,6 +545,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> { |
framer_(SupportedVersions(version()), QuicTime::Zero(), false), |
creator_(guid_, &framer_, &random_generator_, false), |
send_algorithm_(new StrictMock<MockSendAlgorithm>), |
+ loss_algorithm_(NULL), |
helper_(new TestConnectionHelper(&clock_, &random_generator_)), |
writer_(new TestPacketWriter(version())), |
connection_(guid_, IPEndPoint(), helper_.get(), writer_.get(), |
@@ -571,6 +578,15 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> { |
EXPECT_CALL(visitor_, OnCanWrite()).Times(AnyNumber()); |
} |
+ void SetUpMockLossAlgorithm() { |
+ loss_algorithm_ = new MockLossAlgorithm(); |
+ connection_.SetLossAlgorithm(loss_algorithm_); |
+ EXPECT_CALL(*loss_algorithm_, GetLossTimeout()) |
+ .WillRepeatedly(Return(QuicTime::Zero())); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillRepeatedly(Return(SequenceNumberSet())); |
+ } |
+ |
QuicVersion version() { |
return GetParam(); |
} |
@@ -902,6 +918,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> { |
MockEntropyCalculator entropy_calculator_; |
MockSendAlgorithm* send_algorithm_; |
+ MockLossAlgorithm* loss_algorithm_; |
TestReceiveAlgorithm* receive_algorithm_; |
MockClock clock_; |
MockRandom random_generator_; |
@@ -1109,19 +1126,25 @@ TEST_P(QuicConnectionTest, OutOfOrderReceiptCausesAckSend) { |
} |
TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) { |
+ SetUpMockLossAlgorithm(); |
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
- EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1); |
+ |
QuicPacketSequenceNumber original; |
QuicByteCount packet_size; |
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _)) |
.WillOnce(DoAll(SaveArg<1>(&original), SaveArg<2>(&packet_size), |
Return(true))); |
- EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1); |
connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL); |
QuicAckFrame frame = InitAckFrame(original, 1); |
NackPacket(original, &frame); |
// First nack triggers early retransmit. |
+ SequenceNumberSet lost_packets; |
+ lost_packets.insert(1); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(lost_packets)); |
EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1); |
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1); |
QuicPacketSequenceNumber retransmission; |
EXPECT_CALL(*send_algorithm_, |
OnPacketSent(_, _, packet_size - kQuicVersionSize, |
@@ -1134,6 +1157,8 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) { |
NackPacket(original, &frame2); |
EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(SequenceNumberSet())); |
ProcessAckPacket(&frame2); |
// Now if the peer sends an ack which still reports the retransmitted packet |
@@ -1147,6 +1172,9 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) { |
EXPECT_EQ(1u, writer_->stream_frames()->size()); |
writer_->Reset(); |
+ // No more packet loss for the rest of the test. |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillRepeatedly(Return(SequenceNumberSet())); |
ProcessAckPacket(&frame2); |
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, |
HAS_RETRANSMITTABLE_DATA)); |
@@ -1788,10 +1816,7 @@ TEST_P(QuicConnectionTest, OnCanWrite) { |
} |
TEST_P(QuicConnectionTest, RetransmitOnNack) { |
- EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)); |
- EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1); |
- EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _)).Times(1); |
+ SetUpMockLossAlgorithm(); |
QuicPacketSequenceNumber last_packet; |
QuicByteCount second_packet_size; |
SendStreamDataToPeer(3, "foo", 0, !kFin, &last_packet); // Packet 1 |
@@ -1801,20 +1826,23 @@ TEST_P(QuicConnectionTest, RetransmitOnNack) { |
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
- // Peer acks one but not two or three. Right now we only retransmit on |
- // explicit nack, so it should not trigger a retransmission. |
+ // Don't lose a packet on an ack, and nothing is retransmitted. |
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _)); |
QuicAckFrame ack_one = InitAckFrame(1, 0); |
ProcessAckPacket(&ack_one); |
- ProcessAckPacket(&ack_one); |
- ProcessAckPacket(&ack_one); |
- // Peer acks up to 3 with two explicitly missing. |
- // Early retransmit causes 2 to be retransmitted on the first ack. |
+ // Lose a packet and ensure it triggers retransmission. |
QuicAckFrame nack_two = InitAckFrame(3, 0); |
NackPacket(2, &nack_two); |
- // The third nack should trigger a retransmission. |
+ SequenceNumberSet lost_packets; |
+ lost_packets.insert(2); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(lost_packets)); |
EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(3, _)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(2, _)).Times(1); |
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _)).Times(1); |
EXPECT_CALL(*send_algorithm_, |
OnPacketSent(_, _, second_packet_size - kQuicVersionSize, |
NACK_RETRANSMISSION, _)).Times(1); |
@@ -1822,10 +1850,7 @@ TEST_P(QuicConnectionTest, RetransmitOnNack) { |
} |
TEST_P(QuicConnectionTest, DiscardRetransmit) { |
- EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)); |
- EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1); |
- EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _)).Times(1); |
+ SetUpMockLossAlgorithm(); |
QuicPacketSequenceNumber last_packet; |
SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1 |
SendStreamDataToPeer(1, "foos", 3, !kFin, &last_packet); // Packet 2 |
@@ -1833,26 +1858,26 @@ TEST_P(QuicConnectionTest, DiscardRetransmit) { |
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
- // Peer acks one but not two or three. Right now we only retransmit on |
- // explicit nack, so it should not trigger a retransmission. |
- QuicAckFrame ack_one = InitAckFrame(1, 0); |
- ProcessAckPacket(&ack_one); |
- ProcessAckPacket(&ack_one); |
- ProcessAckPacket(&ack_one); |
- |
- // Peer acks up to 3 with two explicitly missing. Two nacks should cause no |
- // change. |
+ // Instigate a loss with an ack. |
QuicAckFrame nack_two = InitAckFrame(3, 0); |
NackPacket(2, &nack_two); |
// The first nack should trigger a fast retransmission, but we'll be |
// write blocked, so the packet will be queued. |
BlockOnNextWrite(); |
+ SequenceNumberSet lost_packets; |
+ lost_packets.insert(2); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(lost_packets)); |
EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(2); |
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(2, _)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _)); |
ProcessAckPacket(&nack_two); |
EXPECT_EQ(1u, connection_.NumQueuedPackets()); |
// Now, ack the previous transmission. |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(SequenceNumberSet())); |
QuicAckFrame ack_all = InitAckFrame(3, 0); |
ProcessAckPacket(&ack_all); |
@@ -1869,19 +1894,25 @@ TEST_P(QuicConnectionTest, DiscardRetransmit) { |
} |
TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) { |
+ SetUpMockLossAlgorithm(); |
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
- EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1); |
QuicPacketSequenceNumber largest_observed; |
QuicByteCount packet_size; |
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _)) |
.WillOnce(DoAll(SaveArg<1>(&largest_observed), SaveArg<2>(&packet_size), |
Return(true))); |
- EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1); |
connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL); |
+ |
QuicAckFrame frame = InitAckFrame(1, largest_observed); |
NackPacket(largest_observed, &frame); |
// The first nack should retransmit the largest observed packet. |
+ SequenceNumberSet lost_packets; |
+ lost_packets.insert(1); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(lost_packets)); |
EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1); |
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1); |
EXPECT_CALL(*send_algorithm_, |
OnPacketSent(_, _, packet_size - kQuicVersionSize, |
NACK_RETRANSMISSION, _)); |
@@ -1983,6 +2014,7 @@ TEST_P(QuicConnectionTest, AlarmsWhenWriteBlocked) { |
} |
TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) { |
+ SetUpMockLossAlgorithm(); |
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
int offset = 0; |
// Send packets 1 to 15. |
@@ -1992,13 +2024,17 @@ TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) { |
} |
// Ack 15, nack 1-14. |
+ SequenceNumberSet lost_packets; |
QuicAckFrame nack = InitAckFrame(15, 0); |
for (int i = 1; i < 15; ++i) { |
NackPacket(i, &nack); |
+ lost_packets.insert(i); |
} |
// 14 packets have been NACK'd and lost. In TCP cubic, PRR limits |
// the retransmission rate in the case of burst losses. |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(lost_packets)); |
EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
EXPECT_CALL(*send_algorithm_, OnPacketAcked(15, _)).Times(1); |
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(14); |
@@ -2867,12 +2903,17 @@ TEST_P(QuicConnectionTest, DontSendDelayedAckOnOutgoingCryptoPacket) { |
} |
TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) { |
+ SetUpMockLossAlgorithm(); |
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
connection_.SendStreamDataWithString(kStreamId3, "foo", 0, !kFin, NULL); |
connection_.SendStreamDataWithString(kStreamId3, "foo", 3, !kFin, NULL); |
// Ack the second packet, which will retransmit the first packet. |
QuicAckFrame ack = InitAckFrame(2, 0); |
NackPacket(1, &ack); |
+ SequenceNumberSet lost_packets; |
+ lost_packets.insert(1); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(lost_packets)); |
EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
EXPECT_CALL(*send_algorithm_, OnPacketAcked(2, _)).Times(1); |
EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1); |
@@ -2886,6 +2927,8 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) { |
// and see if there is more data to send. |
ack = InitAckFrame(3, 0); |
NackPacket(1, &ack); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(SequenceNumberSet())); |
EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
EXPECT_CALL(*send_algorithm_, OnPacketAcked(3, _)).Times(1); |
ProcessAckPacket(&ack); |
@@ -2898,6 +2941,8 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) { |
// Send the same ack, but send both data and an ack together. |
ack = InitAckFrame(3, 0); |
NackPacket(1, &ack); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(SequenceNumberSet())); |
EXPECT_CALL(visitor_, OnCanWrite()).WillOnce( |
IgnoreResult(InvokeWithoutArgs( |
&connection_, |
@@ -3565,6 +3610,7 @@ TEST_P(QuicConnectionTest, AckNotifierTriggerCallback) { |
} |
TEST_P(QuicConnectionTest, AckNotifierFailToTriggerCallback) { |
+ SetUpMockLossAlgorithm(); |
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
// Create a delegate which we don't expect to be called. |
@@ -3586,31 +3632,38 @@ TEST_P(QuicConnectionTest, AckNotifierFailToTriggerCallback) { |
// which we registered to be notified about. |
QuicAckFrame frame = InitAckFrame(3, 0); |
NackPacket(1, &frame); |
- EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)); |
- EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)); |
+ SequenceNumberSet lost_packets; |
+ lost_packets.insert(1); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(lost_packets)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)); |
ProcessAckPacket(&frame); |
} |
TEST_P(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) { |
+ SetUpMockLossAlgorithm(); |
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); |
// Create a delegate which we expect to be called. |
scoped_refptr<MockAckNotifierDelegate> delegate(new MockAckNotifierDelegate); |
EXPECT_CALL(*delegate, OnAckNotification()).Times(1); |
- // In total expect ACKs for all 4 packets. |
- EXPECT_CALL(*send_algorithm_, UpdateRtt(_)).Times(2); |
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(4); |
- |
// Send four packets, and register to be notified on ACK of packet 2. |
connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL); |
connection_.SendStreamDataWithString(3, "bar", 0, !kFin, delegate.get()); |
connection_.SendStreamDataWithString(3, "baz", 0, !kFin, NULL); |
connection_.SendStreamDataWithString(3, "qux", 0, !kFin, NULL); |
- // Now we receive ACK for packets 1, 3, and 4, which invokes fast retransmit. |
+ // Now we receive ACK for packets 1, 3, and 4 and lose 2. |
QuicAckFrame frame = InitAckFrame(4, 0); |
NackPacket(2, &frame); |
+ SequenceNumberSet lost_packets; |
+ lost_packets.insert(2); |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillOnce(Return(lost_packets)); |
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(3); |
EXPECT_CALL(*send_algorithm_, OnPacketLost(2, _)); |
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _)); |
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); |
@@ -3618,6 +3671,10 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) { |
// Now we get an ACK for packet 5 (retransmitted packet 2), which should |
// trigger the callback. |
+ EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) |
+ .WillRepeatedly(Return(SequenceNumberSet())); |
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); |
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(5, _)); |
QuicAckFrame second_ack_frame = InitAckFrame(5, 0); |
ProcessAckPacket(&second_ack_frame); |
} |