| // Copyright (c) 2012 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_packet_generator.h" |
| |
| #include <string> |
| |
| #include "net/quic/crypto/crypto_protocol.h" |
| #include "net/quic/crypto/null_encrypter.h" |
| #include "net/quic/crypto/quic_decrypter.h" |
| #include "net/quic/crypto/quic_encrypter.h" |
| #include "net/quic/quic_flags.h" |
| #include "net/quic/quic_utils.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_test_utils.h" |
| #include "net/quic/test_tools/simple_quic_framer.h" |
| #include "net/test/gtest_util.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using base::StringPiece; |
| using std::string; |
| using std::vector; |
| using testing::InSequence; |
| using testing::Return; |
| using testing::StrictMock; |
| using testing::_; |
| |
| namespace net { |
| namespace test { |
| namespace { |
| |
| const int64 kMinFecTimeoutMs = 5u; |
| |
| static const FecSendPolicy kFecSendPolicyList[] = { |
| FEC_ANY_TRIGGER, |
| FEC_ALARM_TRIGGER, |
| }; |
| |
| class MockDelegate : public QuicPacketGenerator::DelegateInterface { |
| public: |
| MockDelegate() {} |
| ~MockDelegate() override {} |
| |
| MOCK_METHOD2(ShouldGeneratePacket, |
| bool(HasRetransmittableData retransmittable, |
| IsHandshake handshake)); |
| MOCK_METHOD1(PopulateAckFrame, void(QuicAckFrame*)); |
| MOCK_METHOD1(PopulateStopWaitingFrame, void(QuicStopWaitingFrame*)); |
| MOCK_METHOD1(OnSerializedPacket, void(const SerializedPacket& packet)); |
| MOCK_METHOD2(CloseConnection, void(QuicErrorCode, bool)); |
| MOCK_METHOD0(OnResetFecGroup, void()); |
| |
| void SetCanWriteAnything() { |
| EXPECT_CALL(*this, ShouldGeneratePacket(_, _)).WillRepeatedly(Return(true)); |
| EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _)) |
| .WillRepeatedly(Return(true)); |
| } |
| |
| void SetCanNotWrite() { |
| EXPECT_CALL(*this, ShouldGeneratePacket(_, _)) |
| .WillRepeatedly(Return(false)); |
| EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _)) |
| .WillRepeatedly(Return(false)); |
| } |
| |
| // Use this when only ack frames should be allowed to be written. |
| void SetCanWriteOnlyNonRetransmittable() { |
| EXPECT_CALL(*this, ShouldGeneratePacket(_, _)) |
| .WillRepeatedly(Return(false)); |
| EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _)) |
| .WillRepeatedly(Return(true)); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MockDelegate); |
| }; |
| |
| // Simple struct for describing the contents of a packet. |
| // Useful in conjunction with a SimpleQuicFrame for validating that a packet |
| // contains the expected frames. |
| struct PacketContents { |
| PacketContents() |
| : num_ack_frames(0), |
| num_connection_close_frames(0), |
| num_goaway_frames(0), |
| num_rst_stream_frames(0), |
| num_stop_waiting_frames(0), |
| num_stream_frames(0), |
| num_ping_frames(0), |
| num_mtu_discovery_frames(0), |
| fec_group(0) {} |
| |
| size_t num_ack_frames; |
| size_t num_connection_close_frames; |
| size_t num_goaway_frames; |
| size_t num_rst_stream_frames; |
| size_t num_stop_waiting_frames; |
| size_t num_stream_frames; |
| size_t num_ping_frames; |
| size_t num_mtu_discovery_frames; |
| |
| QuicFecGroupNumber fec_group; |
| }; |
| |
| } // namespace |
| |
| class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> { |
| public: |
| QuicPacketGeneratorTest() |
| : framer_(QuicSupportedVersions(), |
| QuicTime::Zero(), |
| Perspective::IS_CLIENT), |
| generator_(42, &framer_, &random_, &delegate_), |
| creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) { |
| generator_.set_fec_send_policy(GetParam()); |
| } |
| |
| ~QuicPacketGeneratorTest() override { |
| for (SerializedPacket& packet : packets_) { |
| delete packet.packet; |
| delete packet.retransmittable_frames; |
| } |
| } |
| |
| void SavePacket(const SerializedPacket& packet) { |
| packets_.push_back(packet); |
| ASSERT_FALSE(packet.packet->owns_buffer()); |
| scoped_ptr<QuicEncryptedPacket> encrypted_deleter(packets_.back().packet); |
| packets_.back().packet = packets_.back().packet->Clone(); |
| } |
| |
| protected: |
| QuicRstStreamFrame* CreateRstStreamFrame() { |
| return new QuicRstStreamFrame(1, QUIC_STREAM_NO_ERROR, 0); |
| } |
| |
| QuicGoAwayFrame* CreateGoAwayFrame() { |
| return new QuicGoAwayFrame(QUIC_NO_ERROR, 1, string()); |
| } |
| |
| void CheckPacketContains(const PacketContents& contents, |
| size_t packet_index) { |
| ASSERT_GT(packets_.size(), packet_index); |
| const SerializedPacket& packet = packets_[packet_index]; |
| size_t num_retransmittable_frames = |
| contents.num_connection_close_frames + contents.num_goaway_frames + |
| contents.num_rst_stream_frames + contents.num_stream_frames + |
| contents.num_ping_frames; |
| size_t num_frames = |
| contents.num_ack_frames + contents.num_stop_waiting_frames + |
| contents.num_mtu_discovery_frames + num_retransmittable_frames; |
| |
| if (num_retransmittable_frames == 0) { |
| ASSERT_TRUE(packet.retransmittable_frames == nullptr); |
| } else { |
| ASSERT_TRUE(packet.retransmittable_frames != nullptr); |
| EXPECT_EQ(num_retransmittable_frames, |
| packet.retransmittable_frames->frames().size()); |
| } |
| |
| ASSERT_TRUE(packet.packet != nullptr); |
| ASSERT_TRUE(simple_framer_.ProcessPacket(*packet.packet)); |
| EXPECT_EQ(num_frames, simple_framer_.num_frames()); |
| EXPECT_EQ(contents.num_ack_frames, simple_framer_.ack_frames().size()); |
| EXPECT_EQ(contents.num_connection_close_frames, |
| simple_framer_.connection_close_frames().size()); |
| EXPECT_EQ(contents.num_goaway_frames, |
| simple_framer_.goaway_frames().size()); |
| EXPECT_EQ(contents.num_rst_stream_frames, |
| simple_framer_.rst_stream_frames().size()); |
| EXPECT_EQ(contents.num_stream_frames, |
| simple_framer_.stream_frames().size()); |
| EXPECT_EQ(contents.num_stop_waiting_frames, |
| simple_framer_.stop_waiting_frames().size()); |
| EXPECT_EQ(contents.fec_group, simple_framer_.header().fec_group); |
| |
| // From the receiver's perspective, MTU discovery frames are ping frames. |
| EXPECT_EQ(contents.num_ping_frames + contents.num_mtu_discovery_frames, |
| simple_framer_.ping_frames().size()); |
| } |
| |
| void CheckPacketHasSingleStreamFrame(size_t packet_index) { |
| ASSERT_GT(packets_.size(), packet_index); |
| const SerializedPacket& packet = packets_[packet_index]; |
| ASSERT_TRUE(packet.retransmittable_frames != nullptr); |
| EXPECT_EQ(1u, packet.retransmittable_frames->frames().size()); |
| ASSERT_TRUE(packet.packet != nullptr); |
| ASSERT_TRUE(simple_framer_.ProcessPacket(*packet.packet)); |
| EXPECT_EQ(1u, simple_framer_.num_frames()); |
| EXPECT_EQ(1u, simple_framer_.stream_frames().size()); |
| } |
| |
| void CheckAllPacketsHaveSingleStreamFrame() { |
| for (size_t i = 0; i < packets_.size(); i++) { |
| CheckPacketHasSingleStreamFrame(i); |
| } |
| } |
| |
| void CheckPacketIsFec(size_t packet_index, |
| QuicPacketSequenceNumber fec_group) { |
| ASSERT_GT(packets_.size(), packet_index); |
| const SerializedPacket& packet = packets_[packet_index]; |
| ASSERT_TRUE(packet.retransmittable_frames == nullptr); |
| ASSERT_TRUE(packet.packet != nullptr); |
| ASSERT_TRUE(simple_framer_.ProcessPacket(*packet.packet)); |
| EXPECT_TRUE(simple_framer_.header().fec_flag); |
| EXPECT_EQ(fec_group, simple_framer_.fec_data().fec_group); |
| } |
| |
| QuicIOVector CreateData(size_t len) { |
| data_array_.reset(new char[len]); |
| memset(data_array_.get(), '?', len); |
| iov_.iov_base = data_array_.get(); |
| iov_.iov_len = len; |
| return QuicIOVector(&iov_, 1, len); |
| } |
| |
| QuicIOVector MakeIOVector(StringPiece s) { |
| return ::net::MakeIOVector(s, &iov_); |
| } |
| |
| QuicFramer framer_; |
| MockRandom random_; |
| StrictMock<MockDelegate> delegate_; |
| QuicPacketGenerator generator_; |
| QuicPacketCreator* creator_; |
| SimpleQuicFramer simple_framer_; |
| vector<SerializedPacket> packets_; |
| |
| private: |
| scoped_ptr<char[]> data_array_; |
| struct iovec iov_; |
| }; |
| |
| class MockDebugDelegate : public QuicPacketGenerator::DebugDelegate { |
| public: |
| MOCK_METHOD1(OnFrameAddedToPacket, |
| void(const QuicFrame&)); |
| }; |
| |
| // Run all end to end tests with all supported FEC send polocies. |
| INSTANTIATE_TEST_CASE_P(FecSendPolicy, |
| QuicPacketGeneratorTest, |
| ::testing::ValuesIn(kFecSendPolicyList)); |
| |
| TEST_P(QuicPacketGeneratorTest, ShouldSendAck_NotWritable) { |
| delegate_.SetCanNotWrite(); |
| |
| generator_.SetShouldSendAck(false); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldNotFlush) { |
| StrictMock<MockDebugDelegate> debug_delegate; |
| |
| generator_.set_debug_delegate(&debug_delegate); |
| delegate_.SetCanWriteOnlyNonRetransmittable(); |
| generator_.StartBatchOperations(); |
| |
| EXPECT_CALL(delegate_, PopulateAckFrame(_)); |
| EXPECT_CALL(debug_delegate, OnFrameAddedToPacket(_)).Times(1); |
| |
| generator_.SetShouldSendAck(false); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) { |
| delegate_.SetCanWriteOnlyNonRetransmittable(); |
| |
| EXPECT_CALL(delegate_, PopulateAckFrame(_)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| |
| generator_.SetShouldSendAck(false); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| PacketContents contents; |
| contents.num_ack_frames = 1; |
| CheckPacketContains(contents, 0); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ShouldSendAck_MultipleCalls) { |
| // Make sure that calling SetShouldSendAck multiple times does not result in a |
| // crash. Previously this would result in multiple QuicFrames queued in the |
| // packet generator, with all but the last with internal pointers to freed |
| // memory. |
| delegate_.SetCanWriteAnything(); |
| |
| // Only one AckFrame should be created. |
| EXPECT_CALL(delegate_, PopulateAckFrame(_)).Times(1); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .Times(1) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| |
| generator_.StartBatchOperations(); |
| generator_.SetShouldSendAck(false); |
| generator_.SetShouldSendAck(false); |
| generator_.FinishBatchOperations(); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, AddControlFrame_NotWritable) { |
| delegate_.SetCanNotWrite(); |
| |
| generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) { |
| delegate_.SetCanWriteOnlyNonRetransmittable(); |
| |
| generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) { |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| |
| generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) { |
| delegate_.SetCanNotWrite(); |
| generator_.StartBatchOperations(); |
| |
| generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| generator_.FinishBatchOperations(); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.FlushAllQueuedFrames(); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| PacketContents contents; |
| contents.num_rst_stream_frames = 1; |
| CheckPacketContains(contents, 0); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) { |
| delegate_.SetCanWriteAnything(); |
| |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| |
| generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| PacketContents contents; |
| contents.num_rst_stream_frames = 1; |
| CheckPacketContains(contents, 0); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ConsumeData_NotWritable) { |
| delegate_.SetCanNotWrite(); |
| |
| QuicConsumedData consumed = generator_.ConsumeData( |
| kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(0u, consumed.bytes_consumed); |
| EXPECT_FALSE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) { |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| |
| QuicConsumedData consumed = generator_.ConsumeData( |
| kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(3u, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) { |
| delegate_.SetCanWriteAnything(); |
| |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| QuicConsumedData consumed = generator_.ConsumeData( |
| kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(3u, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| PacketContents contents; |
| contents.num_stream_frames = 1; |
| CheckPacketContains(contents, 0); |
| } |
| |
| // Test the behavior of ConsumeData when the data consumed is for the crypto |
| // handshake stream. Ensure that the packet is always sent and padded even if |
| // the generator operates in batch mode. |
| TEST_P(QuicPacketGeneratorTest, ConsumeData_Handshake) { |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| QuicConsumedData consumed = generator_.ConsumeData( |
| kCryptoStreamId, MakeIOVector("foo"), 0, false, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(3u, consumed.bytes_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| PacketContents contents; |
| contents.num_stream_frames = 1; |
| CheckPacketContains(contents, 0); |
| |
| ASSERT_EQ(1u, packets_.size()); |
| ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetMaxPacketLength()); |
| EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].packet->length()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ConsumeData_EmptyData) { |
| EXPECT_DFATAL(generator_.ConsumeData(kHeadersStreamId, MakeIOVector(""), 0, |
| false, MAY_FEC_PROTECT, nullptr), |
| "Attempt to consume empty data without FIN."); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, |
| ConsumeDataMultipleTimes_WritableAndShouldNotFlush) { |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| |
| generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 2, true, |
| MAY_FEC_PROTECT, nullptr); |
| QuicConsumedData consumed = generator_.ConsumeData( |
| 3, MakeIOVector("quux"), 7, false, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(4u, consumed.bytes_consumed); |
| EXPECT_FALSE(consumed.fin_consumed); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ConsumeData_BatchOperations) { |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| |
| generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 2, true, |
| MAY_FEC_PROTECT, nullptr); |
| QuicConsumedData consumed = generator_.ConsumeData( |
| 3, MakeIOVector("quux"), 7, false, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(4u, consumed.bytes_consumed); |
| EXPECT_FALSE(consumed.fin_consumed); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| |
| // Now both frames will be flushed out. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.FinishBatchOperations(); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| PacketContents contents; |
| contents.num_stream_frames = 2; |
| CheckPacketContains(contents, 0); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ConsumeDataFecOnMaxGroupSize) { |
| delegate_.SetCanWriteAnything(); |
| |
| // Send FEC every two packets. |
| creator_->set_max_packets_per_fec_group(2); |
| |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER, but FEC |
| // group is closed. |
| EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); |
| } else { |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| |
| // Send enough data to create 3 packets: two full and one partial. Send with |
| // MUST_FEC_PROTECT flag. |
| size_t data_len = 2 * kDefaultMaxPacketSize + 100; |
| QuicConsumedData consumed = generator_.ConsumeData( |
| 3, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| CheckPacketHasSingleStreamFrame(0); |
| CheckPacketHasSingleStreamFrame(1); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER. |
| CheckPacketHasSingleStreamFrame(2); |
| } else { |
| CheckPacketIsFec(2, 1); |
| CheckPacketHasSingleStreamFrame(3); |
| } |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // If FEC send policy is FEC_ANY_TRIGGER, then the FEC packet under |
| // construction will be sent when one more packet is sent (since FEC group |
| // size is 2), or when OnFecTimeout is called. Send more data with |
| // MAY_FEC_PROTECT. This packet should also be protected, and FEC packet is |
| // sent since FEC group size is reached. |
| // |
| // If FEC send policy is FEC_ALARM_TRIGGER, FEC group is closed when the group |
| // size is reached. FEC packet is not sent. |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); |
| } else { |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| } |
| consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT, |
| nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| CheckPacketHasSingleStreamFrame(3); |
| } else { |
| CheckPacketHasSingleStreamFrame(4); |
| CheckPacketIsFec(5, 4); |
| } |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ConsumeDataSendsFecOnTimeout) { |
| delegate_.SetCanWriteAnything(); |
| creator_->set_max_packets_per_fec_group(1000); |
| |
| // Send data with MUST_FEC_PROTECT flag. No FEC packet is emitted, but the |
| // creator FEC protects all data. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| QuicConsumedData consumed = generator_.ConsumeData(3, CreateData(1u), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| CheckPacketHasSingleStreamFrame(0); |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // Send more data with MAY_FEC_PROTECT. This packet should also be protected, |
| // and FEC packet is not yet sent. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT, |
| nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| CheckPacketHasSingleStreamFrame(1); |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // Calling OnFecTimeout should cause the FEC packet to be emitted. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.OnFecTimeout(); |
| CheckPacketIsFec(2, 1); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| |
| // Subsequent data is protected under the next FEC group. Send enough data to |
| // create 2 more packets: one full and one partial. |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| size_t data_len = kDefaultMaxPacketSize + 1; |
| consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| CheckPacketHasSingleStreamFrame(3); |
| CheckPacketHasSingleStreamFrame(4); |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // Calling OnFecTimeout should cause the FEC packet to be emitted. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.OnFecTimeout(); |
| CheckPacketIsFec(5, 4); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, GetFecTimeoutFiniteOnlyOnFirstPacketInGroup) { |
| delegate_.SetCanWriteAnything(); |
| creator_->set_max_packets_per_fec_group(6); |
| |
| // Send enough data to create 2 packets: one full and one partial. Send with |
| // MUST_FEC_PROTECT flag. No FEC packet is emitted yet, but the creator FEC |
| // protects all data. |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| size_t data_len = 1 * kDefaultMaxPacketSize + 100; |
| QuicConsumedData consumed = generator_.ConsumeData( |
| 3, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| CheckPacketHasSingleStreamFrame(0); |
| CheckPacketHasSingleStreamFrame(1); |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // GetFecTimeout returns finite timeout only for first packet in group. |
| EXPECT_EQ(QuicTime::Delta::FromMilliseconds(kMinFecTimeoutMs), |
| generator_.GetFecTimeout(/*sequence_number=*/1u)); |
| EXPECT_EQ(QuicTime::Delta::Infinite(), |
| generator_.GetFecTimeout(/*sequence_number=*/2u)); |
| |
| // Send more data with MAY_FEC_PROTECT. This packet should also be protected, |
| // and FEC packet is not yet sent. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT, |
| nullptr); |
| CheckPacketHasSingleStreamFrame(2); |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // GetFecTimeout returns finite timeout only for first packet in group. |
| EXPECT_EQ(QuicTime::Delta::Infinite(), |
| generator_.GetFecTimeout(/*sequence_number=*/3u)); |
| |
| // Calling OnFecTimeout should cause the FEC packet to be emitted. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.OnFecTimeout(); |
| CheckPacketIsFec(3, /*fec_group=*/1u); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| |
| // Subsequent data is protected under the next FEC group. Send enough data to |
| // create 2 more packets: one full and one partial. |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| data_len = kDefaultMaxPacketSize + 1u; |
| consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| CheckPacketHasSingleStreamFrame(4); |
| CheckPacketHasSingleStreamFrame(5); |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // GetFecTimeout returns finite timeout for first packet in the new group. |
| EXPECT_EQ(QuicTime::Delta::FromMilliseconds(kMinFecTimeoutMs), |
| generator_.GetFecTimeout(/*sequence_number=*/5u)); |
| EXPECT_EQ(QuicTime::Delta::Infinite(), |
| generator_.GetFecTimeout(/*sequence_number=*/6u)); |
| |
| // Calling OnFecTimeout should cause the FEC packet to be emitted. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.OnFecTimeout(); |
| CheckPacketIsFec(6, /*fec_group=*/5u); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| |
| // Send more data with MAY_FEC_PROTECT. No FEC protection, so GetFecTimeout |
| // returns infinite. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| consumed = generator_.ConsumeData(9, CreateData(1u), 0, true, MAY_FEC_PROTECT, |
| nullptr); |
| CheckPacketHasSingleStreamFrame(7); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| EXPECT_EQ(QuicTime::Delta::Infinite(), |
| generator_.GetFecTimeout(/*sequence_number=*/8u)); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) { |
| // Set the packet size be enough for two stream frames with 0 stream offset, |
| // but not enough for a stream frame of 0 offset and one with non-zero offset. |
| size_t length = |
| NullEncrypter().GetCiphertextSize(0) + |
| GetPacketHeaderSize( |
| creator_->connection_id_length(), true, |
| QuicPacketCreatorPeer::NextSequenceNumberLength(creator_), |
| NOT_IN_FEC_GROUP) + |
| // Add an extra 3 bytes for the payload and 1 byte so BytesFree is larger |
| // than the GetMinStreamFrameSize. |
| QuicFramer::GetMinStreamFrameSize(1, 0, false, NOT_IN_FEC_GROUP) + 3 + |
| QuicFramer::GetMinStreamFrameSize(1, 0, true, NOT_IN_FEC_GROUP) + 1; |
| generator_.SetMaxPacketLength(length, /*force=*/false); |
| delegate_.SetCanWriteAnything(); |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| generator_.StartBatchOperations(); |
| // Queue enough data to prevent a stream frame with a non-zero offset from |
| // fitting. |
| QuicConsumedData consumed = |
| generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 0, false, |
| MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(3u, consumed.bytes_consumed); |
| EXPECT_FALSE(consumed.fin_consumed); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| |
| // This frame will not fit with the existing frame, causing the queued frame |
| // to be serialized, and it will not fit with another frame like it, so it is |
| // serialized by itself. |
| consumed = generator_.ConsumeData(kHeadersStreamId, MakeIOVector("bar"), 3, |
| true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(3u, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| PacketContents contents; |
| contents.num_stream_frames = 1; |
| CheckPacketContains(contents, 0); |
| CheckPacketContains(contents, 1); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, NoFecPacketSentWhenBatchEnds) { |
| delegate_.SetCanWriteAnything(); |
| creator_->set_max_packets_per_fec_group(6); |
| |
| generator_.StartBatchOperations(); |
| |
| generator_.ConsumeData(3, MakeIOVector("foo"), 2, true, MUST_FEC_PROTECT, |
| nullptr); |
| QuicConsumedData consumed = generator_.ConsumeData( |
| 5, MakeIOVector("quux"), 7, false, MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(4u, consumed.bytes_consumed); |
| EXPECT_FALSE(consumed.fin_consumed); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| |
| // Now both frames will be flushed out, but FEC packet is not yet sent. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.FinishBatchOperations(); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| PacketContents contents; |
| contents.num_stream_frames = 2u; |
| contents.fec_group = 1u; |
| CheckPacketContains(contents, 0); |
| |
| // Forcing FEC timeout causes FEC packet to be emitted. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.OnFecTimeout(); |
| CheckPacketIsFec(1, /*fec_group=*/1u); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, FecTimeoutOnRttChange) { |
| EXPECT_EQ(QuicTime::Delta::Zero(), |
| QuicPacketGeneratorPeer::GetFecTimeout(&generator_)); |
| generator_.OnRttChange(QuicTime::Delta::FromMilliseconds(300)); |
| EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150), |
| QuicPacketGeneratorPeer::GetFecTimeout(&generator_)); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, FecGroupSizeOnCongestionWindowChange) { |
| delegate_.SetCanWriteAnything(); |
| creator_->set_max_packets_per_fec_group(50); |
| EXPECT_EQ(50u, creator_->max_packets_per_fec_group()); |
| EXPECT_FALSE(creator_->IsFecGroupOpen()); |
| |
| // On reduced cwnd. |
| generator_.OnCongestionWindowChange(7); |
| EXPECT_EQ(3u, creator_->max_packets_per_fec_group()); |
| |
| // On increased cwnd. |
| generator_.OnCongestionWindowChange(100); |
| EXPECT_EQ(50u, creator_->max_packets_per_fec_group()); |
| |
| // On collapsed cwnd. |
| generator_.OnCongestionWindowChange(1); |
| EXPECT_EQ(2u, creator_->max_packets_per_fec_group()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, FecGroupSizeChangeWithOpenGroup) { |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| creator_->set_max_packets_per_fec_group(50); |
| EXPECT_EQ(50u, creator_->max_packets_per_fec_group()); |
| EXPECT_FALSE(creator_->IsFecGroupOpen()); |
| |
| // Send enough data to create 4 packets with MUST_FEC_PROTECT flag. 3 packets |
| // are sent, one is queued in the creator. |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| size_t data_len = 3 * kDefaultMaxPacketSize + 1; |
| QuicConsumedData consumed = generator_.ConsumeData( |
| 7, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(creator_->IsFecGroupOpen()); |
| |
| // Change FEC groupsize. |
| generator_.OnCongestionWindowChange(2); |
| EXPECT_EQ(2u, creator_->max_packets_per_fec_group()); |
| |
| // If FEC send policy is FEC_ANY_TRIGGER, then send enough data to trigger one |
| // unprotected data packet, causing the FEC packet to also be sent. |
| // |
| // If FEC send policy is FEC_ALARM_TRIGGER, FEC group is closed and FEC packet |
| // is not sent. |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); |
| } else { |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| } |
| consumed = generator_.ConsumeData(7, CreateData(kDefaultMaxPacketSize), 0, |
| true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(kDefaultMaxPacketSize, consumed.bytes_consumed); |
| if (generator_.fec_send_policy() == FEC_ANY_TRIGGER) { |
| // Verify that one FEC packet was sent. |
| CheckPacketIsFec(4, /*fec_group=*/1u); |
| } |
| EXPECT_FALSE(creator_->IsFecGroupOpen()); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, SwitchFecOnOff) { |
| delegate_.SetCanWriteAnything(); |
| creator_->set_max_packets_per_fec_group(2); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| |
| // Send one unprotected data packet. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, |
| MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| // Verify that one data packet was sent. |
| PacketContents contents; |
| contents.num_stream_frames = 1; |
| CheckPacketContains(contents, 0); |
| |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| // If FEC send policy is FEC_ALARM_TRIGGER, FEC group is closed. |
| EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); |
| } else { |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| // Send enough data to create 3 packets with MUST_FEC_PROTECT flag. |
| size_t data_len = 2 * kDefaultMaxPacketSize + 100; |
| consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| // If FEC send policy is FEC_ANY_TRIGGER, verify that packets sent were 3 data |
| // and 1 FEC. |
| // |
| // If FEC send policy is FEC_ALARM_TRIGGER, verify that packets sent were 3 |
| // data and FEC group is closed. |
| CheckPacketHasSingleStreamFrame(1); |
| CheckPacketHasSingleStreamFrame(2); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| CheckPacketHasSingleStreamFrame(3); |
| } else { |
| CheckPacketIsFec(3, /*fec_group=*/2u); |
| CheckPacketHasSingleStreamFrame(4); |
| } |
| |
| // Calling OnFecTimeout should emit the pending FEC packet. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.OnFecTimeout(); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| CheckPacketIsFec(4, /*fec_group=*/4u); |
| } else { |
| CheckPacketIsFec(5, /*fec_group=*/5u); |
| } |
| |
| // Send one unprotected data packet. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| consumed = generator_.ConsumeData(7, CreateData(1u), 0, true, MAY_FEC_PROTECT, |
| nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| // Verify that one unprotected data packet was sent. |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| CheckPacketContains(contents, 5); |
| } else { |
| CheckPacketContains(contents, 6); |
| } |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, SwitchFecOnWithPendingFrameInCreator) { |
| delegate_.SetCanWriteAnything(); |
| // Enable FEC. |
| creator_->set_max_packets_per_fec_group(2); |
| |
| generator_.StartBatchOperations(); |
| // Queue enough data to prevent a stream frame with a non-zero offset from |
| // fitting. |
| QuicConsumedData consumed = generator_.ConsumeData(7, CreateData(1u), 0, true, |
| MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| EXPECT_TRUE(creator_->HasPendingFrames()); |
| |
| // Queue protected data for sending. Should cause queued frames to be flushed. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| consumed = generator_.ConsumeData(7, CreateData(1u), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| PacketContents contents; |
| contents.num_stream_frames = 1; |
| // Transmitted packet was not FEC protected. |
| CheckPacketContains(contents, 0); |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| EXPECT_TRUE(creator_->HasPendingFrames()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, SwitchFecOnWithPendingFramesInGenerator) { |
| // Enable FEC. |
| creator_->set_max_packets_per_fec_group(2); |
| |
| // Queue control frames in generator. |
| delegate_.SetCanNotWrite(); |
| generator_.SetShouldSendAck(true); |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| |
| // Set up frames to write into the creator when control frames are written. |
| EXPECT_CALL(delegate_, PopulateAckFrame(_)); |
| EXPECT_CALL(delegate_, PopulateStopWaitingFrame(_)); |
| |
| // Generator should have queued control frames, and creator should be empty. |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| EXPECT_FALSE(creator_->HasPendingFrames()); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| |
| // Queue protected data for sending. Should cause queued frames to be flushed. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| QuicConsumedData consumed = generator_.ConsumeData(7, CreateData(1u), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| PacketContents contents; |
| contents.num_ack_frames = 1; |
| contents.num_stop_waiting_frames = 1; |
| CheckPacketContains(contents, 0); |
| |
| // FEC protection should be on in creator. |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffWithSubsequentFramesProtected) { |
| delegate_.SetCanWriteAnything(); |
| |
| // Enable FEC. |
| creator_->set_max_packets_per_fec_group(2); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| |
| // Queue stream frame to be protected in creator. |
| generator_.StartBatchOperations(); |
| QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| // Creator has a pending protected frame. |
| EXPECT_TRUE(creator_->HasPendingFrames()); |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // Add enough unprotected data to exceed size of current packet, so that |
| // current packet is sent. Both frames will be sent out in a single packet. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| size_t data_len = kDefaultMaxPacketSize; |
| consumed = generator_.ConsumeData(5, CreateData(data_len), 0, true, |
| MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| PacketContents contents; |
| contents.num_stream_frames = 2u; |
| contents.fec_group = 1u; |
| CheckPacketContains(contents, 0); |
| // FEC protection should still be on in creator. |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffWithSubsequentPacketsProtected) { |
| delegate_.SetCanWriteAnything(); |
| |
| // Enable FEC. |
| creator_->set_max_packets_per_fec_group(2); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| |
| // Send first packet, FEC protected. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| PacketContents contents; |
| contents.num_stream_frames = 1u; |
| contents.fec_group = 1u; |
| CheckPacketContains(contents, 0); |
| |
| // FEC should still be on in creator. |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // Send unprotected data to cause second packet to be sent, which gets |
| // protected because it happens to fall within an open FEC group. Data packet |
| // will be followed by FEC packet. |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); |
| } else { |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| } |
| consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT, |
| nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| contents.num_stream_frames = 1u; |
| CheckPacketContains(contents, 1); |
| if (generator_.fec_send_policy() == FEC_ANY_TRIGGER) { |
| // FEC packet is sent when send policy is FEC_ANY_TRIGGER. |
| CheckPacketIsFec(2, /*fec_group=*/1u); |
| } |
| |
| // FEC protection should be off in creator. |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffThenOnWithCreatorProtectionOn) { |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| |
| // Enable FEC. |
| creator_->set_max_packets_per_fec_group(2); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| |
| // Queue one byte of FEC protected data. |
| QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_TRUE(creator_->HasPendingFrames()); |
| |
| // Add more unprotected data causing first packet to be sent, FEC protected. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| size_t data_len = kDefaultMaxPacketSize; |
| consumed = generator_.ConsumeData(5, CreateData(data_len), 0, true, |
| MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| PacketContents contents; |
| contents.num_stream_frames = 2u; |
| contents.fec_group = 1u; |
| CheckPacketContains(contents, 0); |
| |
| // FEC group is still open in creator. |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // Add data that should be protected, large enough to cause second packet to |
| // be sent. Data packet should be followed by FEC packet. |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); |
| } else { |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| } |
| consumed = generator_.ConsumeData(5, CreateData(data_len), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| CheckPacketContains(contents, 1); |
| if (generator_.fec_send_policy() == FEC_ANY_TRIGGER) { |
| // FEC packet is sent when send policy is FEC_ANY_TRIGGER. |
| CheckPacketIsFec(2, /*fec_group=*/1u); |
| } |
| |
| // FEC protection should remain on in creator. |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, ResetFecGroupNoTimeout) { |
| delegate_.SetCanWriteAnything(); |
| // Send FEC packet after 2 packets. |
| creator_->set_max_packets_per_fec_group(2); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| |
| // Send two packets so that when this data is consumed, two packets are sent |
| // out. In FEC_TRIGGER_ANY, this will cause an FEC packet to be sent out and |
| // with FEC_TRIGGER_ALARM, this will cause a Reset to be called. In both |
| // cases, the creator's fec protection will be turned off afterwards. |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER, but FEC |
| // group is closed. |
| EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); |
| } else { |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| // Fin Packet. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| size_t data_len = 2 * kDefaultMaxPacketSize; |
| QuicConsumedData consumed = generator_.ConsumeData( |
| 5, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| CheckPacketHasSingleStreamFrame(0); |
| CheckPacketHasSingleStreamFrame(1); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER. |
| CheckPacketHasSingleStreamFrame(2); |
| } else { |
| // FEC packet is sent after 2 packets and when send policy is |
| // FEC_ANY_TRIGGER. |
| CheckPacketIsFec(2, 1); |
| CheckPacketHasSingleStreamFrame(3); |
| } |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // Do the same send (with MUST_FEC_PROTECT) on a different stream id. |
| { |
| InSequence dummy; |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| // FEC packet is sent after 2 packets and when send policy is |
| // FEC_ANY_TRIGGER. When policy is FEC_ALARM_TRIGGER, FEC group is closed |
| // and FEC packet is not sent. |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); |
| } else { |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| // FEC packet is sent after 2 packets and when send policy is |
| // FEC_ANY_TRIGGER. When policy is FEC_ALARM_TRIGGER, FEC group is closed |
| // and FEC packet is not sent. |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); |
| } else { |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| } |
| consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true, |
| MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { |
| CheckPacketHasSingleStreamFrame(3); |
| CheckPacketHasSingleStreamFrame(4); |
| CheckPacketHasSingleStreamFrame(5); |
| } else { |
| CheckPacketHasSingleStreamFrame(4); |
| // FEC packet is sent after 2 packets and when send policy is |
| // FEC_ANY_TRIGGER. |
| CheckPacketIsFec(5, 4); |
| CheckPacketHasSingleStreamFrame(6); |
| CheckPacketHasSingleStreamFrame(7); |
| // FEC packet is sent after 2 packets and when send policy is |
| // FEC_ANY_TRIGGER. |
| CheckPacketIsFec(8, 7); |
| } |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| } |
| |
| // 1. Create and send one packet with MUST_FEC_PROTECT. |
| // 2. Call FecTimeout, expect FEC packet is sent. |
| // 3. Do the same thing over again, with a different stream id. |
| TEST_P(QuicPacketGeneratorTest, FecPacketSentOnFecTimeout) { |
| delegate_.SetCanWriteAnything(); |
| creator_->set_max_packets_per_fec_group(1000); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| |
| for (int i = 1; i < 4; i = i + 2) { |
| // Send data with MUST_FEC_PROTECT flag. No FEC packet is emitted, but the |
| // creator FEC protects all data. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| QuicConsumedData consumed = generator_.ConsumeData( |
| i + 2, CreateData(1u), 0, true, MUST_FEC_PROTECT, nullptr); |
| EXPECT_EQ(1u, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| CheckPacketHasSingleStreamFrame(0); |
| EXPECT_TRUE(creator_->IsFecProtected()); |
| |
| // Calling OnFecTimeout should cause the FEC packet to be emitted. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.OnFecTimeout(); |
| CheckPacketIsFec(i, i); |
| EXPECT_FALSE(creator_->IsFecProtected()); |
| } |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations) { |
| delegate_.SetCanNotWrite(); |
| |
| generator_.SetShouldSendAck(false); |
| generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| |
| delegate_.SetCanWriteAnything(); |
| |
| generator_.StartBatchOperations(); |
| |
| // When the first write operation is invoked, the ack frame will be returned. |
| EXPECT_CALL(delegate_, PopulateAckFrame(_)); |
| |
| // Send some data and a control frame |
| generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, MAY_FEC_PROTECT, |
| nullptr); |
| generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame())); |
| |
| // All five frames will be flushed out in a single packet. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| generator_.FinishBatchOperations(); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| PacketContents contents; |
| contents.num_ack_frames = 1; |
| contents.num_goaway_frames = 1; |
| contents.num_rst_stream_frames = 1; |
| contents.num_stream_frames = 1; |
| CheckPacketContains(contents, 0); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) { |
| delegate_.SetCanNotWrite(); |
| |
| generator_.SetShouldSendAck(false); |
| generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| |
| delegate_.SetCanWriteAnything(); |
| |
| generator_.StartBatchOperations(); |
| |
| // When the first write operation is invoked, the ack frame will be returned. |
| EXPECT_CALL(delegate_, PopulateAckFrame(_)); |
| |
| { |
| InSequence dummy; |
| // All five frames will be flushed out in a single packet |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| } |
| |
| // Send enough data to exceed one packet |
| size_t data_len = kDefaultMaxPacketSize + 100; |
| QuicConsumedData consumed = generator_.ConsumeData( |
| 3, CreateData(data_len), 0, true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame())); |
| |
| generator_.FinishBatchOperations(); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| // The first packet should have the queued data and part of the stream data. |
| PacketContents contents; |
| contents.num_ack_frames = 1; |
| contents.num_rst_stream_frames = 1; |
| contents.num_stream_frames = 1; |
| CheckPacketContains(contents, 0); |
| |
| // The second should have the remainder of the stream data. |
| PacketContents contents2; |
| contents2.num_goaway_frames = 1; |
| contents2.num_stream_frames = 1; |
| CheckPacketContains(contents2, 1); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, TestConnectionIdLength) { |
| generator_.SetConnectionIdLength(0); |
| EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID, creator_->connection_id_length()); |
| generator_.SetConnectionIdLength(1); |
| EXPECT_EQ(PACKET_1BYTE_CONNECTION_ID, creator_->connection_id_length()); |
| generator_.SetConnectionIdLength(2); |
| EXPECT_EQ(PACKET_4BYTE_CONNECTION_ID, creator_->connection_id_length()); |
| generator_.SetConnectionIdLength(3); |
| EXPECT_EQ(PACKET_4BYTE_CONNECTION_ID, creator_->connection_id_length()); |
| generator_.SetConnectionIdLength(4); |
| EXPECT_EQ(PACKET_4BYTE_CONNECTION_ID, creator_->connection_id_length()); |
| generator_.SetConnectionIdLength(5); |
| EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, creator_->connection_id_length()); |
| generator_.SetConnectionIdLength(6); |
| EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, creator_->connection_id_length()); |
| generator_.SetConnectionIdLength(7); |
| EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, creator_->connection_id_length()); |
| generator_.SetConnectionIdLength(8); |
| EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, creator_->connection_id_length()); |
| generator_.SetConnectionIdLength(9); |
| EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, creator_->connection_id_length()); |
| } |
| |
| // Test whether SetMaxPacketLength() works in the situation when the queue is |
| // empty, and we send three packets worth of data. |
| TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) { |
| delegate_.SetCanWriteAnything(); |
| |
| // Send enough data for three packets. |
| size_t data_len = 3 * kDefaultMaxPacketSize + 1; |
| size_t packet_len = kDefaultMaxPacketSize + 100; |
| ASSERT_LE(packet_len, kMaxPacketSize); |
| generator_.SetMaxPacketLength(packet_len, /*force=*/false); |
| EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength()); |
| |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .Times(3) |
| .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| QuicConsumedData consumed = |
| generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), |
| /*offset=*/2, |
| /*fin=*/true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| // We expect three packets, and first two of them have to be of packet_len |
| // size. We check multiple packets (instead of just one) because we want to |
| // ensure that |max_packet_length_| does not get changed incorrectly by the |
| // generator after first packet is serialized. |
| ASSERT_EQ(3u, packets_.size()); |
| EXPECT_EQ(packet_len, packets_[0].packet->length()); |
| EXPECT_EQ(packet_len, packets_[1].packet->length()); |
| CheckAllPacketsHaveSingleStreamFrame(); |
| } |
| |
| // Test whether SetMaxPacketLength() works in the situation when we first write |
| // data, then change packet size, then write data again. |
| TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) { |
| delegate_.SetCanWriteAnything(); |
| |
| // We send enough data to overflow default packet length, but not the altered |
| // one. |
| size_t data_len = kDefaultMaxPacketSize; |
| size_t packet_len = kDefaultMaxPacketSize + 100; |
| ASSERT_LE(packet_len, kMaxPacketSize); |
| |
| // We expect to see three packets in total. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .Times(3) |
| .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| |
| // Send two packets before packet size change. |
| QuicConsumedData consumed = |
| generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), |
| /*offset=*/2, |
| /*fin=*/false, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_FALSE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| // Make sure we already have two packets. |
| ASSERT_EQ(2u, packets_.size()); |
| |
| // Increase packet size. |
| generator_.SetMaxPacketLength(packet_len, /*force=*/false); |
| EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength()); |
| |
| // Send a packet after packet size change. |
| consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), |
| 2 + data_len, |
| /*fin=*/true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| // We expect first data chunk to get fragmented, but the second one to fit |
| // into a single packet. |
| ASSERT_EQ(3u, packets_.size()); |
| EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].packet->length()); |
| EXPECT_LE(kDefaultMaxPacketSize, packets_[2].packet->length()); |
| CheckAllPacketsHaveSingleStreamFrame(); |
| } |
| |
| // Test whether SetMaxPacketLength() works correctly when we change the packet |
| // size in the middle of the batched packet. |
| TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Midpacket) { |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| |
| size_t first_write_len = kDefaultMaxPacketSize / 2; |
| size_t second_write_len = kDefaultMaxPacketSize; |
| size_t packet_len = kDefaultMaxPacketSize + 100; |
| ASSERT_LE(packet_len, kMaxPacketSize); |
| |
| // First send half of the packet worth of data. We are in the batch mode, so |
| // should not cause packet serialization. |
| QuicConsumedData consumed = |
| generator_.ConsumeData(kHeadersStreamId, CreateData(first_write_len), |
| /*offset=*/2, |
| /*fin=*/false, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(first_write_len, consumed.bytes_consumed); |
| EXPECT_FALSE(consumed.fin_consumed); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| |
| // Make sure we have no packets so far. |
| ASSERT_EQ(0u, packets_.size()); |
| |
| // Increase packet size. Ensure it's not immediately enacted. |
| generator_.SetMaxPacketLength(packet_len, /*force=*/false); |
| EXPECT_EQ(packet_len, generator_.GetMaxPacketLength()); |
| EXPECT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength()); |
| |
| // We expect to see exactly one packet serialized after that, since we are in |
| // batch mode and we have sent approximately 3/2 of our MTU. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| |
| // Send a packet worth of data to the same stream. This should trigger |
| // serialization of other packet. |
| consumed = |
| generator_.ConsumeData(kHeadersStreamId, CreateData(second_write_len), |
| /*offset=*/2 + first_write_len, |
| /*fin=*/true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(second_write_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| |
| // We expect the first packet to contain two frames, and to not reflect the |
| // packet size change. |
| ASSERT_EQ(1u, packets_.size()); |
| EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].packet->length()); |
| |
| PacketContents contents; |
| contents.num_stream_frames = 2; |
| CheckPacketContains(contents, 0); |
| } |
| |
| // Test whether SetMaxPacketLength() works correctly when we force the change of |
| // the packet size in the middle of the batched packet. |
| TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) { |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| |
| size_t first_write_len = kDefaultMaxPacketSize / 2; |
| size_t packet_len = kDefaultMaxPacketSize + 100; |
| size_t second_write_len = packet_len + 1; |
| ASSERT_LE(packet_len, kMaxPacketSize); |
| |
| // First send half of the packet worth of data. We are in the batch mode, so |
| // should not cause packet serialization. |
| QuicConsumedData consumed = |
| generator_.ConsumeData(kHeadersStreamId, CreateData(first_write_len), |
| /*offset=*/2, |
| /*fin=*/false, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(first_write_len, consumed.bytes_consumed); |
| EXPECT_FALSE(consumed.fin_consumed); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| |
| // Make sure we have no packets so far. |
| ASSERT_EQ(0u, packets_.size()); |
| |
| // Expect a packet to be flushed. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| |
| // Increase packet size. Ensure it's immediately enacted. |
| generator_.SetMaxPacketLength(packet_len, /*force=*/true); |
| EXPECT_EQ(packet_len, generator_.GetMaxPacketLength()); |
| EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength()); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| // We expect to see exactly one packet serialized after that, because we send |
| // a value somewhat exceeding new max packet size, and the tail data does not |
| // get serialized because we are still in the batch mode. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| |
| // Send a more than a packet worth of data to the same stream. This should |
| // trigger serialization of one packet, and queue another one. |
| consumed = |
| generator_.ConsumeData(kHeadersStreamId, CreateData(second_write_len), |
| /*offset=*/2 + first_write_len, |
| /*fin=*/true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(second_write_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| |
| // We expect the first packet to be underfilled, and the second packet be up |
| // to the new max packet size. |
| ASSERT_EQ(2u, packets_.size()); |
| EXPECT_GT(kDefaultMaxPacketSize, packets_[0].packet->length()); |
| EXPECT_EQ(packet_len, packets_[1].packet->length()); |
| |
| CheckAllPacketsHaveSingleStreamFrame(); |
| } |
| |
| // Test sending an MTU probe, without any surrounding data. |
| TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) { |
| delegate_.SetCanWriteAnything(); |
| |
| const size_t target_mtu = kDefaultMaxPacketSize + 100; |
| static_assert(target_mtu < kMaxPacketSize, |
| "The MTU probe used by the test exceeds maximum packet size"); |
| |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| |
| generator_.GenerateMtuDiscoveryPacket(target_mtu, nullptr); |
| |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| ASSERT_EQ(1u, packets_.size()); |
| EXPECT_EQ(target_mtu, packets_[0].packet->length()); |
| |
| PacketContents contents; |
| contents.num_mtu_discovery_frames = 1; |
| CheckPacketContains(contents, 0); |
| } |
| |
| // Test sending an MTU probe. Surround it with data, to ensure that it resets |
| // the MTU to the value before the probe was sent. |
| TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) { |
| delegate_.SetCanWriteAnything(); |
| |
| const size_t target_mtu = kDefaultMaxPacketSize + 100; |
| static_assert(target_mtu < kMaxPacketSize, |
| "The MTU probe used by the test exceeds maximum packet size"); |
| |
| // Send enough data so it would always cause two packets to be sent. |
| const size_t data_len = target_mtu + 1; |
| |
| // Send a total of five packets: two packets before the probe, the probe |
| // itself, and two packets after the probe. |
| EXPECT_CALL(delegate_, OnSerializedPacket(_)) |
| .Times(5) |
| .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); |
| |
| // Send data before the MTU probe. |
| QuicConsumedData consumed = |
| generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), |
| /*offset=*/2, |
| /*fin=*/false, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_FALSE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| // Send the MTU probe. |
| generator_.GenerateMtuDiscoveryPacket(target_mtu, nullptr); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| // Send data after the MTU probe. |
| consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), |
| /*offset=*/2 + data_len, |
| /*fin=*/true, MAY_FEC_PROTECT, nullptr); |
| EXPECT_EQ(data_len, consumed.bytes_consumed); |
| EXPECT_TRUE(consumed.fin_consumed); |
| EXPECT_FALSE(generator_.HasQueuedFrames()); |
| |
| ASSERT_EQ(5u, packets_.size()); |
| EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].packet->length()); |
| EXPECT_EQ(target_mtu, packets_[2].packet->length()); |
| EXPECT_EQ(kDefaultMaxPacketSize, packets_[3].packet->length()); |
| |
| PacketContents probe_contents; |
| probe_contents.num_mtu_discovery_frames = 1; |
| |
| CheckPacketHasSingleStreamFrame(0); |
| CheckPacketHasSingleStreamFrame(1); |
| CheckPacketContains(probe_contents, 2); |
| CheckPacketHasSingleStreamFrame(3); |
| CheckPacketHasSingleStreamFrame(4); |
| } |
| |
| TEST_P(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) { |
| // Test added to ensure the generator does not crash when an invalid frame is |
| // added. Because this is an indication of internal programming errors, |
| // DFATALs are expected. |
| // A 1 byte sequence number length can't encode a gap of 1000. |
| QuicPacketCreatorPeer::SetSequenceNumber(creator_, 1000); |
| |
| delegate_.SetCanNotWrite(); |
| generator_.SetShouldSendAck(true); |
| delegate_.SetCanWriteAnything(); |
| generator_.StartBatchOperations(); |
| |
| // Set up frames to write into the creator when control frames are written. |
| EXPECT_CALL(delegate_, PopulateAckFrame(_)); |
| EXPECT_CALL(delegate_, PopulateStopWaitingFrame(_)); |
| // Generator should have queued control frames, and creator should be empty. |
| EXPECT_TRUE(generator_.HasQueuedFrames()); |
| EXPECT_FALSE(creator_->HasPendingFrames()); |
| |
| // This will not serialize any packets, because of the invalid frame. |
| EXPECT_CALL(delegate_, |
| CloseConnection(QUIC_FAILED_TO_SERIALIZE_PACKET, false)); |
| EXPECT_DFATAL(generator_.FinishBatchOperations(), |
| "sequence_number_length 1 is too small " |
| "for least_unacked_delta: 1001"); |
| } |
| |
| } // namespace test |
| } // namespace net |