| 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);
|
| }
|
|
|