| // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/quic/quic_ack_notifier_manager.h" |
| |
| #include "net/quic/quic_ack_notifier.h" |
| #include "net/quic/quic_protocol.h" |
| #include "net/quic/test_tools/quic_ack_notifier_manager_peer.h" |
| #include "net/quic/test_tools/quic_test_utils.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace net { |
| namespace test { |
| namespace { |
| |
| // Test fixture for testing AckNotifierManager. Instantiates a manager and |
| // provides shared code for adding notifiers and verifying the contents of the |
| // manager. |
| class QuicAckNotifierManagerTest : public ::testing::Test { |
| protected: |
| AckNotifierManager manager_; |
| scoped_refptr<MockAckNotifierDelegate> delegate_; |
| QuicTime::Delta zero_; |
| |
| QuicAckNotifierManagerTest() : zero_(QuicTime::Delta::Zero()) { |
| delegate_ = new MockAckNotifierDelegate; |
| } |
| |
| ~QuicAckNotifierManagerTest() override {} |
| |
| size_t CountPackets() const { |
| return AckNotifierManagerPeer::GetNumberOfRegisteredPackets(&manager_); |
| } |
| |
| // Add a mock packet with specified parameters. The packet with given |
| // sequence number must not exist in the map before. |
| void AddPacket(QuicPacketSequenceNumber sequence_number, |
| bool retransmittable) { |
| // Create a mock packet. |
| RetransmittableFrames frames(ENCRYPTION_NONE); |
| SerializedPacket packet(sequence_number, PACKET_4BYTE_SEQUENCE_NUMBER, |
| /*packet=*/nullptr, |
| /*entropy_hash=*/0, |
| retransmittable ? &frames : nullptr); |
| |
| // Create and register a notifier. Normally, this would be created by |
| // QuicPacketGenerator. |
| QuicAckNotifier* notifier = new QuicAckNotifier(delegate_.get()); |
| packet.notifiers.push_back(notifier); |
| |
| // Ensure that exactly one packet is added. |
| const size_t old_packet_count = CountPackets(); |
| |
| // Actually add the packet. |
| manager_.OnSerializedPacket(packet); |
| |
| // Ensure the change in the number of packets. |
| EXPECT_EQ(old_packet_count + 1, CountPackets()); |
| } |
| }; |
| |
| // This test verifies that QuicAckNotifierManager can handle the trivial case of |
| // received packet notification. |
| TEST_F(QuicAckNotifierManagerTest, SimpleAck) { |
| AddPacket(1, false); |
| AddPacket(2, true); |
| |
| EXPECT_CALL(*delegate_, OnAckNotification(0, 0, zero_)).Times(2); |
| manager_.OnPacketAcked(1, zero_); |
| EXPECT_EQ(1u, CountPackets()); |
| manager_.OnPacketAcked(2, zero_); |
| EXPECT_EQ(0u, CountPackets()); |
| |
| manager_.OnPacketRemoved(1); |
| manager_.OnPacketRemoved(2); |
| EXPECT_EQ(0u, CountPackets()); |
| } |
| |
| // This test verifies that QuicAckNotifierManager can correctly handle the case |
| // when some of the packets are lost, which causes retransmission and removal |
| // from the unacked packet map. |
| TEST_F(QuicAckNotifierManagerTest, AckWithLosses) { |
| const size_t retransmitted_packet_size = kDefaultMaxPacketSize; |
| |
| // Here, we simulate the following scenario: |
| // 1. We send packets 1 to 5, where only odd-numbered packets are |
| // retransmittable. |
| // 2. The peer acks 1, 2 and 5, but not 3 and 4. |
| // 3. We retransmit 3 as 6. |
| // 4. We remove 1 and 2, since we no longer care about them. |
| // 4. The peer acks 6. |
| // 5. We remove packets 3 to 6. |
| |
| // Step 1: send five packets. |
| AddPacket(1, true); |
| AddPacket(2, false); |
| AddPacket(3, true); |
| AddPacket(4, false); |
| AddPacket(5, true); |
| |
| // Step 2: handle acks from peer. |
| EXPECT_CALL(*delegate_, OnAckNotification(0, 0, zero_)).Times(3); |
| manager_.OnPacketAcked(1, zero_); |
| EXPECT_EQ(4u, CountPackets()); |
| manager_.OnPacketAcked(2, zero_); |
| EXPECT_EQ(3u, CountPackets()); |
| manager_.OnPacketAcked(5, zero_); |
| EXPECT_EQ(2u, CountPackets()); |
| |
| // Step 3: retransmit 3 as 6. |
| manager_.OnPacketRetransmitted(3, 6, retransmitted_packet_size); |
| EXPECT_EQ(2u, CountPackets()); |
| |
| // Step 4: remove 1 and 2. |
| manager_.OnPacketRemoved(1); |
| manager_.OnPacketRemoved(2); |
| EXPECT_EQ(2u, CountPackets()); |
| |
| // Step 4: ack packet 6. |
| EXPECT_CALL(*delegate_, |
| OnAckNotification(1, retransmitted_packet_size, zero_)).Times(1); |
| manager_.OnPacketAcked(6, zero_); |
| EXPECT_EQ(1u, CountPackets()); |
| |
| // Step 5: remove all packets. This causes packet 4 to be dropped from the |
| // map. |
| manager_.OnPacketRemoved(3); |
| manager_.OnPacketRemoved(4); |
| manager_.OnPacketRemoved(5); |
| manager_.OnPacketRemoved(6); |
| EXPECT_EQ(0u, CountPackets()); |
| } |
| |
| // This test verifies that the QuicAckNotifierManager behaves correctly when |
| // there are many retransmissions. |
| TEST_F(QuicAckNotifierManagerTest, RepeatedRetransmission) { |
| AddPacket(1, true); |
| |
| const size_t packet_size = kDefaultMaxPacketSize; |
| const size_t times_lost = 100; |
| const size_t total_size_lost = packet_size * times_lost; |
| const QuicPacketSequenceNumber last_packet = times_lost + 1; |
| |
| // Retransmit the packet many times. |
| for (size_t sequence_number = 1; sequence_number < last_packet; |
| sequence_number++) { |
| manager_.OnPacketRetransmitted(sequence_number, sequence_number + 1, |
| packet_size); |
| EXPECT_EQ(1u, CountPackets()); |
| } |
| |
| // Remove all lost packets. |
| for (QuicPacketSequenceNumber packet = 1; packet < last_packet; packet++) { |
| manager_.OnPacketRemoved(packet); |
| } |
| EXPECT_EQ(1u, CountPackets()); |
| |
| // Finally get the packet acknowledged. |
| EXPECT_CALL(*delegate_, OnAckNotification(times_lost, total_size_lost, zero_)) |
| .Times(1); |
| manager_.OnPacketAcked(last_packet, zero_); |
| EXPECT_EQ(0u, CountPackets()); |
| |
| // Remove the last packet. |
| manager_.OnPacketRemoved(last_packet); |
| EXPECT_EQ(0u, CountPackets()); |
| } |
| |
| } // namespace |
| } // namespace test |
| } // namespace net |