Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Unified Diff: net/quic/quic_packet_generator_test.cc

Issue 12334063: Land recent QUIC changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more EXPECT_FALSE Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/quic_packet_generator.cc ('k') | net/quic/quic_protocol.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/quic_packet_generator_test.cc
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..85a16e88a38d174ce0df6b45da0b6bc5e7c595c1
--- /dev/null
+++ b/net/quic/quic_packet_generator_test.cc
@@ -0,0 +1,508 @@
+// 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_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/quic/test_tools/simple_quic_framer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using testing::InSequence;
+using testing::Return;
+using testing::SaveArg;
+using testing::_;
+
+namespace net {
+namespace test {
+namespace {
+
+class MockDelegate : public QuicPacketGenerator::DelegateInterface {
+ public:
+ MockDelegate() {}
+ virtual ~MockDelegate() {}
+
+ MOCK_METHOD1(CanWrite, bool(bool is_retransmission));
+
+ MOCK_METHOD0(CreateAckFrame, QuicAckFrame*());
+ MOCK_METHOD0(CreateFeedbackFrame, QuicCongestionFeedbackFrame*());
+ MOCK_METHOD1(OnSerializedPacket, bool(const SerializedPacket& packet));
+
+ void SetCanWrite(bool can_write) {
+ EXPECT_CALL(*this, CanWrite(false)).WillRepeatedly(Return(can_write));
+ }
+
+ 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_feedback_frames(0),
+ num_goaway_frames(0),
+ num_rst_stream_frames(0),
+ num_stream_frames(0),
+ fec_group(0) {
+ }
+
+ size_t num_ack_frames;
+ size_t num_connection_close_frames;
+ size_t num_feedback_frames;
+ size_t num_goaway_frames;
+ size_t num_rst_stream_frames;
+ size_t num_stream_frames;
+
+ QuicFecGroupNumber fec_group;
+};
+
+} // namespace
+
+class QuicPacketGeneratorTest : public ::testing::Test {
+ protected:
+ QuicPacketGeneratorTest()
+ : framer_(QuicDecrypter::Create(kNULL), QuicEncrypter::Create(kNULL)),
+ creator_(42, &framer_, &random_),
+ generator_(&delegate_, &creator_),
+ packet_(0, NULL, 0, NULL),
+ packet2_(0, NULL, 0, NULL),
+ packet3_(0, NULL, 0, NULL),
+ packet4_(0, NULL, 0, NULL),
+ packet5_(0, NULL, 0, NULL) {
+ }
+
+ ~QuicPacketGeneratorTest() {
+ delete packet_.packet;
+ delete packet_.retransmittable_frames;
+ delete packet2_.packet;
+ delete packet2_.retransmittable_frames;
+ delete packet3_.packet;
+ delete packet3_.retransmittable_frames;
+ delete packet4_.packet;
+ delete packet4_.retransmittable_frames;
+ delete packet5_.packet;
+ delete packet5_.retransmittable_frames;
+ }
+
+ QuicAckFrame* CreateAckFrame() {
+ // TODO(rch): Initialize this so it can be verified later.
+ return new QuicAckFrame(0, 0);
+ }
+
+ QuicCongestionFeedbackFrame* CreateFeedbackFrame() {
+ QuicCongestionFeedbackFrame* frame = new QuicCongestionFeedbackFrame;
+ frame->type = kFixRate;
+ frame->fix_rate.bitrate = QuicBandwidth::FromBytesPerSecond(42);
+ return frame;
+ }
+
+ QuicRstStreamFrame* CreateRstStreamFrame() {
+ return new QuicRstStreamFrame(1, QUIC_NO_ERROR);
+ }
+
+ QuicGoAwayFrame* CreateGoAwayFrame() {
+ return new QuicGoAwayFrame(QUIC_NO_ERROR, 1, "");
+ }
+
+ void CheckPacketContains(const PacketContents& contents,
+ const SerializedPacket& packet) {
+ size_t num_retransmittable_frames = contents.num_connection_close_frames +
+ contents.num_goaway_frames + contents.num_rst_stream_frames +
+ contents.num_stream_frames;
+ size_t num_frames = contents.num_feedback_frames + contents.num_ack_frames +
+ num_retransmittable_frames;
+
+ if (num_retransmittable_frames == 0) {
+ ASSERT_TRUE(packet.retransmittable_frames == NULL);
+ } else {
+ ASSERT_TRUE(packet.retransmittable_frames != NULL);
+ EXPECT_EQ(num_retransmittable_frames,
+ packet.retransmittable_frames->frames().size());
+ }
+
+ ASSERT_TRUE(packet.packet != NULL);
+ 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_feedback_frames,
+ simple_framer_.feedback_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.fec_group, simple_framer_.header().fec_group);
+ }
+
+ void CheckPacketHasSingleStreamFrame(const SerializedPacket& packet) {
+ ASSERT_TRUE(packet.retransmittable_frames != NULL);
+ EXPECT_EQ(1u, packet.retransmittable_frames->frames().size());
+ ASSERT_TRUE(packet.packet != NULL);
+ ASSERT_TRUE(simple_framer_.ProcessPacket(*packet.packet));
+ EXPECT_EQ(1u, simple_framer_.num_frames());
+ EXPECT_EQ(1u, simple_framer_.stream_frames().size());
+ }
+
+ void CheckPacketIsFec(const SerializedPacket& packet,
+ QuicPacketSequenceNumber fec_group) {
+ ASSERT_TRUE(packet.retransmittable_frames == NULL);
+ ASSERT_TRUE(packet.packet != NULL);
+ ASSERT_TRUE(simple_framer_.ProcessPacket(*packet.packet));
+ EXPECT_TRUE(simple_framer_.header().fec_flag);
+ EXPECT_EQ(fec_group, simple_framer_.fec_data().fec_group);
+ }
+
+ StringPiece CreateData(size_t len) {
+ data_array_.reset(new char[len]);
+ memset(data_array_.get(), '?', len);
+ return StringPiece(data_array_.get(), len);
+ }
+
+ QuicFramer framer_;
+ MockRandom random_;
+ QuicPacketCreator creator_;
+ testing::StrictMock<MockDelegate> delegate_;
+ QuicPacketGenerator generator_;
+ SimpleQuicFramer simple_framer_;
+ SerializedPacket packet_;
+ SerializedPacket packet2_;
+ SerializedPacket packet3_;
+ SerializedPacket packet4_;
+ SerializedPacket packet5_;
+
+ private:
+ scoped_ptr<char[]> data_array_;
+};
+
+TEST_F(QuicPacketGeneratorTest, ShouldSendAck_NotWritable) {
+ delegate_.SetCanWrite(false);
+
+ generator_.SetShouldSendAck(false);
+ EXPECT_TRUE(generator_.HasQueuedData());
+}
+
+TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldNotFlush) {
+ delegate_.SetCanWrite(true);
+ generator_.StartBatchOperations();
+
+ EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
+
+ generator_.SetShouldSendAck(false);
+ EXPECT_TRUE(generator_.HasQueuedData());
+}
+
+TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) {
+ delegate_.SetCanWrite(true);
+
+ EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet_), Return(true)));
+
+ generator_.SetShouldSendAck(false);
+ EXPECT_FALSE(generator_.HasQueuedData());
+
+ PacketContents contents;
+ contents.num_ack_frames = 1;
+ CheckPacketContains(contents, packet_);
+}
+
+TEST_F(QuicPacketGeneratorTest,
+ ShouldSendAckWithFeedback_WritableAndShouldNotFlush) {
+ delegate_.SetCanWrite(true);
+ generator_.StartBatchOperations();
+
+ EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
+ EXPECT_CALL(delegate_, CreateFeedbackFrame()).WillOnce(
+ Return(CreateFeedbackFrame()));
+
+ generator_.SetShouldSendAck(true);
+ EXPECT_TRUE(generator_.HasQueuedData());
+}
+
+TEST_F(QuicPacketGeneratorTest,
+ ShouldSendAckWithFeedback_WritableAndShouldFlush) {
+ delegate_.SetCanWrite(true);
+
+ EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
+ EXPECT_CALL(delegate_, CreateFeedbackFrame()).WillOnce(
+ Return(CreateFeedbackFrame()));
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet_), Return(true)));
+
+ generator_.SetShouldSendAck(true);
+ EXPECT_FALSE(generator_.HasQueuedData());
+
+ PacketContents contents;
+ contents.num_ack_frames = 1;
+ contents.num_feedback_frames = 1;
+ CheckPacketContains(contents, packet_);
+}
+
+TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritable) {
+ delegate_.SetCanWrite(false);
+
+ generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()));
+ EXPECT_TRUE(generator_.HasQueuedData());
+}
+
+TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) {
+ delegate_.SetCanWrite(true);
+ generator_.StartBatchOperations();
+
+ generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()));
+ EXPECT_TRUE(generator_.HasQueuedData());
+}
+
+TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) {
+ delegate_.SetCanWrite(true);
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet_), Return(true)));
+
+ generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()));
+ EXPECT_FALSE(generator_.HasQueuedData());
+
+ PacketContents contents;
+ contents.num_rst_stream_frames = 1;
+ CheckPacketContains(contents, packet_);
+}
+
+TEST_F(QuicPacketGeneratorTest, ConsumeData_NotWritable) {
+ delegate_.SetCanWrite(false);
+
+ QuicConsumedData consumed = generator_.ConsumeData(1, "foo", 2, true);
+ EXPECT_EQ(0u, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_FALSE(generator_.HasQueuedData());
+}
+
+TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) {
+ delegate_.SetCanWrite(true);
+ generator_.StartBatchOperations();
+
+ QuicConsumedData consumed = generator_.ConsumeData(1, "foo", 2, true);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_TRUE(generator_.HasQueuedData());
+}
+
+TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) {
+ delegate_.SetCanWrite(true);
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet_), Return(true)));
+ QuicConsumedData consumed = generator_.ConsumeData(1, "foo", 2, true);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(generator_.HasQueuedData());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, packet_);
+}
+
+TEST_F(QuicPacketGeneratorTest,
+ ConsumeDataMultipleTimes_WritableAndShouldNotFlush) {
+ delegate_.SetCanWrite(true);
+ generator_.StartBatchOperations();
+
+ generator_.ConsumeData(1, "foo", 2, true);
+ QuicConsumedData consumed = generator_.ConsumeData(3, "quux", 7, false);
+ EXPECT_EQ(4u, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_TRUE(generator_.HasQueuedData());
+}
+
+TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) {
+ delegate_.SetCanWrite(true);
+ generator_.StartBatchOperations();
+
+ generator_.ConsumeData(1, "foo", 2, true);
+ QuicConsumedData consumed = generator_.ConsumeData(3, "quux", 7, false);
+ EXPECT_EQ(4u, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_TRUE(generator_.HasQueuedData());
+
+ // Now both frames will be flushed out.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet_), Return(true)));
+ generator_.FinishBatchOperations();
+ EXPECT_FALSE(generator_.HasQueuedData());
+
+ PacketContents contents;
+ contents.num_stream_frames = 2;
+ CheckPacketContains(contents, packet_);
+}
+
+TEST_F(QuicPacketGeneratorTest, ConsumeDataFEC) {
+ delegate_.SetCanWrite(true);
+
+ // Send FEC every two packets.
+ creator_.options()->max_packets_per_fec_group = 2;
+
+ {
+ InSequence dummy;
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet_), Return(true)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet2_), Return(true)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet3_), Return(true)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet4_), Return(true)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet5_), Return(true)));
+ }
+
+ // Send enough data to create 3 packets: two full and one partial.
+ size_t data_len = 2 * kMaxPacketSize + 100;
+ QuicConsumedData consumed =
+ generator_.ConsumeData(3, CreateData(data_len), 0, true);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(generator_.HasQueuedData());
+
+ CheckPacketHasSingleStreamFrame(packet_);
+ CheckPacketHasSingleStreamFrame(packet2_);
+ CheckPacketIsFec(packet3_, 1);
+
+ CheckPacketHasSingleStreamFrame(packet4_);
+ CheckPacketIsFec(packet5_, 4);
+}
+
+TEST_F(QuicPacketGeneratorTest, ConsumeDataSendsFecAtEnd) {
+ delegate_.SetCanWrite(true);
+
+ // Send FEC every six packets.
+ creator_.options()->max_packets_per_fec_group = 6;
+
+ {
+ InSequence dummy;
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet_), Return(true)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet2_), Return(true)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet3_), Return(true)));
+ }
+
+ // Send enough data to create 2 packets: one full and one partial.
+ size_t data_len = 1 * kMaxPacketSize + 100;
+ QuicConsumedData consumed =
+ generator_.ConsumeData(3, CreateData(data_len), 0, true);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(generator_.HasQueuedData());
+
+ CheckPacketHasSingleStreamFrame(packet_);
+ CheckPacketHasSingleStreamFrame(packet2_);
+ CheckPacketIsFec(packet3_, 1);
+}
+
+TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
+ delegate_.SetCanWrite(false);
+
+ generator_.SetShouldSendAck(true);
+ generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()));
+ EXPECT_TRUE(generator_.HasQueuedData());
+
+ delegate_.SetCanWrite(true);
+
+ generator_.StartBatchOperations();
+
+ // When the first write operation is invoked, the ack and feedback
+ // frames will be returned.
+ EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
+ EXPECT_CALL(delegate_, CreateFeedbackFrame()).WillOnce(
+ Return(CreateFeedbackFrame()));
+
+ // Send some data and a control frame
+ generator_.ConsumeData(3, "quux", 7, false);
+ generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
+
+ // All five frames will be flushed out in a single packet.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet_), Return(true)));
+ generator_.FinishBatchOperations();
+ EXPECT_FALSE(generator_.HasQueuedData());
+
+ PacketContents contents;
+ contents.num_ack_frames = 1;
+ contents.num_goaway_frames = 1;
+ contents.num_feedback_frames = 1;
+ contents.num_rst_stream_frames = 1;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, packet_);
+}
+
+TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
+ delegate_.SetCanWrite(false);
+
+ generator_.SetShouldSendAck(true);
+ generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()));
+ EXPECT_TRUE(generator_.HasQueuedData());
+
+ delegate_.SetCanWrite(true);
+
+ generator_.StartBatchOperations();
+
+ // When the first write operation is invoked, the ack and feedback
+ // frames will be returned.
+ EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
+ EXPECT_CALL(delegate_, CreateFeedbackFrame()).WillOnce(
+ Return(CreateFeedbackFrame()));
+
+ {
+ InSequence dummy;
+ // All five frames will be flushed out in a single packet
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet_), Return(true)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet2_), Return(true)));
+ }
+
+ // Send enough data to exceed one packet
+ size_t data_len = kMaxPacketSize + 100;
+ QuicConsumedData consumed =
+ generator_.ConsumeData(3, CreateData(data_len), 0, true);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
+
+ generator_.FinishBatchOperations();
+ EXPECT_FALSE(generator_.HasQueuedData());
+
+ // The first packet should have the queued data and part of the stream data.
+ PacketContents contents;
+ contents.num_ack_frames = 1;
+ contents.num_feedback_frames = 1;
+ contents.num_rst_stream_frames = 1;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, packet_);
+
+ // The second should have the remainder of the stream data.
+ PacketContents contents2;
+ contents2.num_goaway_frames = 1;
+ contents2.num_stream_frames = 1;
+ CheckPacketContains(contents2, packet2_);
+}
+
+} // namespace test
+} // namespace net
« no previous file with comments | « net/quic/quic_packet_generator.cc ('k') | net/quic/quic_protocol.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698