// 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 #include "base/macros.h" #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_simple_buffer_allocator.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 { 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(SerializedPacket* packet)); MOCK_METHOD2(OnUnrecoverableError, void(QuicErrorCode, ConnectionCloseSource)); 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) {} 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; }; } // namespace class QuicPacketGeneratorTest : public ::testing::Test { public: QuicPacketGeneratorTest() : framer_(QuicSupportedVersions(), QuicTime::Zero(), Perspective::IS_CLIENT), generator_(42, &framer_, &random_, &buffer_allocator_, &delegate_), creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) { // TODO(ianswett): Fix this test so it uses a non-null encrypter. FLAGS_quic_never_write_unencrypted_data = false; } ~QuicPacketGeneratorTest() override { for (SerializedPacket& packet : packets_) { delete[] packet.encrypted_buffer; QuicUtils::ClearSerializedPacket(&packet); } } void SavePacket(SerializedPacket* packet) { packet->encrypted_buffer = QuicUtils::CopyBuffer(*packet); packets_.push_back(*packet); packet->encrypted_buffer = nullptr; packet->retransmittable_frames.clear(); } 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.empty()); } else { ASSERT_FALSE(packet.retransmittable_frames.empty()); EXPECT_EQ(num_retransmittable_frames, packet.retransmittable_frames.size()); } ASSERT_TRUE(packet.encrypted_buffer != nullptr); ASSERT_TRUE(simple_framer_.ProcessPacket( QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length))); 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()); // 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_FALSE(packet.retransmittable_frames.empty()); EXPECT_EQ(1u, packet.retransmittable_frames.size()); ASSERT_TRUE(packet.encrypted_buffer != nullptr); ASSERT_TRUE(simple_framer_.ProcessPacket( QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length))); 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); } } 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_; SimpleBufferAllocator buffer_allocator_; StrictMock delegate_; QuicPacketGenerator generator_; QuicPacketCreator* creator_; SimpleQuicFramer simple_framer_; vector packets_; private: scoped_ptr data_array_; struct iovec iov_; }; class MockDebugDelegate : public QuicPacketCreator::DebugDelegate { public: MOCK_METHOD1(OnFrameAddedToPacket, void(const QuicFrame&)); }; TEST_F(QuicPacketGeneratorTest, ShouldSendAck_NotWritable) { delegate_.SetCanNotWrite(); generator_.SetShouldSendAck(false); EXPECT_TRUE(generator_.HasQueuedFrames()); } TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldNotFlush) { StrictMock 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_F(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_F(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_F(QuicPacketGeneratorTest, AddControlFrame_NotWritable) { delegate_.SetCanNotWrite(); generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); } TEST_F(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) { delegate_.SetCanWriteOnlyNonRetransmittable(); generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); } TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); } TEST_F(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_F(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_F(QuicPacketGeneratorTest, ConsumeData_NotWritable) { delegate_.SetCanNotWrite(); QuicConsumedData consumed = generator_.ConsumeData( kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr); EXPECT_EQ(0u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); } TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); QuicConsumedData consumed = generator_.ConsumeData( kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); } TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) { delegate_.SetCanWriteAnything(); EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); QuicConsumedData consumed = generator_.ConsumeData( kHeadersStreamId, MakeIOVector("foo"), 2, true, 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_F(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, 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_.GetCurrentMaxPacketLength()); EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length); } TEST_F(QuicPacketGeneratorTest, ConsumeData_EmptyData) { EXPECT_DFATAL(generator_.ConsumeData(kHeadersStreamId, MakeIOVector(""), 0, false, nullptr), "Attempt to consume empty data without FIN."); } TEST_F(QuicPacketGeneratorTest, ConsumeDataMultipleTimes_WritableAndShouldNotFlush) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr); QuicConsumedData consumed = generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, nullptr); EXPECT_EQ(4u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); } TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr); QuicConsumedData consumed = generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, 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_F(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(), kIncludeVersion, !kIncludePathId, QuicPacketCreatorPeer::NextPacketNumberLength(creator_)) + // Add an extra 3 bytes for the payload and 1 byte so BytesFree is larger // than the GetMinStreamFrameSize. QuicFramer::GetMinStreamFrameSize(1, 0, false) + 3 + QuicFramer::GetMinStreamFrameSize(1, 0, true) + 1; generator_.SetMaxPacketLength(length); 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, 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 be added to a new open packet. consumed = generator_.ConsumeData(kHeadersStreamId, MakeIOVector("bar"), 3, true, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); creator_->Flush(); EXPECT_FALSE(generator_.HasQueuedFrames()); PacketContents contents; contents.num_stream_frames = 1; CheckPacketContains(contents, 0); CheckPacketContains(contents, 1); } TEST_F(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, 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_F(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, 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_F(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_F(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); 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, 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].encrypted_length); EXPECT_EQ(packet_len, packets_[1].encrypted_length); CheckAllPacketsHaveSingleStreamFrame(); } // Test whether SetMaxPacketLength() works in the situation when we first write // data, then change packet size, then write data again. TEST_F(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, 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); 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, 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].encrypted_length); EXPECT_LE(kDefaultMaxPacketSize, packets_[2].encrypted_length); CheckAllPacketsHaveSingleStreamFrame(); } // Test whether SetMaxPacketLength() works correctly when we force the change of // the packet size in the middle of the batched packet. TEST_F(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, 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 after flushing all frames. // Ensure it's immediately enacted. generator_.FlushAllQueuedFrames(); generator_.SetMaxPacketLength(packet_len); 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, 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].encrypted_length); EXPECT_EQ(packet_len, packets_[1].encrypted_length); CheckAllPacketsHaveSingleStreamFrame(); } // Test sending an MTU probe, without any surrounding data. TEST_F(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].encrypted_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_F(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, 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, 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].encrypted_length); EXPECT_EQ(target_mtu, packets_[2].encrypted_length); EXPECT_EQ(kDefaultMaxPacketSize, packets_[3].encrypted_length); PacketContents probe_contents; probe_contents.num_mtu_discovery_frames = 1; CheckPacketHasSingleStreamFrame(0); CheckPacketHasSingleStreamFrame(1); CheckPacketContains(probe_contents, 2); CheckPacketHasSingleStreamFrame(3); CheckPacketHasSingleStreamFrame(4); } TEST_F(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 packet number length can't encode a gap of 1000. QuicPacketCreatorPeer::SetPacketNumber(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_, OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET, ConnectionCloseSource::FROM_SELF)); EXPECT_DFATAL(generator_.FinishBatchOperations(), "packet_number_length 1 is too small " "for least_unacked_delta: 1001"); } TEST_F(QuicPacketGeneratorTest, SetCurrentPath) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); QuicConsumedData consumed = generator_.ConsumeData( kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(creator_)); // Does not change current path. generator_.SetCurrentPath(kDefaultPathId, 1, 0); EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(creator_)); // Try to switch path when a packet is under construction. QuicPathId kTestPathId1 = 1; EXPECT_DFATAL(generator_.SetCurrentPath(kTestPathId1, 1, 0), "Unable to change paths when a packet is under construction"); EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(creator_)); // Try to switch path after current open packet gets serialized. EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); generator_.FlushAllQueuedFrames(); EXPECT_FALSE(generator_.HasQueuedFrames()); generator_.SetCurrentPath(kTestPathId1, 1, 0); EXPECT_EQ(kTestPathId1, QuicPacketCreatorPeer::GetCurrentPath(creator_)); } } // namespace test } // namespace net