| // 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_connection.h" | 
 |  | 
 | #include "net/base/net_errors.h" | 
 | #include "net/quic/congestion_control/quic_receipt_metrics_collector.h" | 
 | #include "net/quic/congestion_control/quic_send_scheduler.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/test_tools/mock_clock.h" | 
 | #include "net/quic/test_tools/quic_test_utils.h" | 
 | #include "net/quic/quic_utils.h" | 
 | #include "testing/gmock/include/gmock/gmock.h" | 
 | #include "testing/gtest/include/gtest/gtest.h" | 
 |  | 
 | using base::StringPiece; | 
 | using std::map; | 
 | using testing::_; | 
 | using testing::ContainerEq; | 
 | using testing::Return; | 
 | using testing::StrictMock; | 
 |  | 
 | namespace net { | 
 |  | 
 | // Peer to make public a number of otherwise private QuicConnection methods. | 
 | class QuicConnectionPeer { | 
 |  public: | 
 |   static void SendAck(QuicConnection* connection) { | 
 |     connection->SendAck(); | 
 |   } | 
 |  | 
 |   static void SetCollector(QuicConnection* connection, | 
 |                            QuicReceiptMetricsCollector* collector) { | 
 |     connection->collector_.reset(collector); | 
 |   } | 
 |  | 
 |   static void SetScheduler(QuicConnection* connection, | 
 |                            QuicSendScheduler* scheduler) { | 
 |     connection->scheduler_.reset(scheduler); | 
 |   } | 
 |   static QuicAckFrame* GetOutgoingAck(QuicConnection* connection) { | 
 |     return &connection->outgoing_ack_; | 
 |   } | 
 |  | 
 |  private: | 
 |   DISALLOW_COPY_AND_ASSIGN(QuicConnectionPeer); | 
 | }; | 
 |  | 
 | namespace test { | 
 | namespace { | 
 |  | 
 | const char data1[] = "foo"; | 
 | const char data2[] = "bar"; | 
 |  | 
 | class TestCollector : public QuicReceiptMetricsCollector { | 
 |  public: | 
 |   explicit TestCollector(QuicCongestionFeedbackFrame* feedback) | 
 |       : QuicReceiptMetricsCollector(&clock_, kFixRate), | 
 |         feedback_(feedback) { | 
 |   } | 
 |  | 
 |   bool GenerateCongestionFeedback( | 
 |       QuicCongestionFeedbackFrame* congestion_feedback) { | 
 |     if (feedback_ == NULL) { | 
 |       return false; | 
 |     } | 
 |     *congestion_feedback = *feedback_; | 
 |     return true; | 
 |   } | 
 |  | 
 |   MOCK_METHOD4(RecordIncomingPacket, | 
 |                void(size_t, QuicPacketSequenceNumber, QuicTime, bool)); | 
 |  | 
 |  private: | 
 |   MockClock clock_; | 
 |   QuicCongestionFeedbackFrame* feedback_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(TestCollector); | 
 | }; | 
 |  | 
 | class TestConnectionHelper : public QuicConnectionHelperInterface { | 
 |  public: | 
 |   explicit TestConnectionHelper(MockClock* clock) | 
 |       : clock_(clock), | 
 |         blocked_(false) { | 
 |   } | 
 |  | 
 |   // QuicConnectionHelperInterface | 
 |   virtual void SetConnection(QuicConnection* connection) {} | 
 |  | 
 |   virtual const QuicClock* GetClock() const { | 
 |     return clock_; | 
 |   } | 
 |  | 
 |   virtual int WritePacketToWire(const QuicEncryptedPacket& packet, | 
 |                                 int* error) { | 
 |     QuicFramer framer(QuicDecrypter::Create(kNULL), | 
 |                       QuicEncrypter::Create(kNULL)); | 
 |     FramerVisitorCapturingAcks visitor; | 
 |     framer.set_visitor(&visitor); | 
 |     EXPECT_TRUE(framer.ProcessPacket(IPEndPoint(), IPEndPoint(), packet)); | 
 |     header_ = *visitor.header(); | 
 |     if (visitor.ack()) { | 
 |       ack_.reset(new QuicAckFrame(*visitor.ack())); | 
 |     } | 
 |     if (visitor.feedback()) { | 
 |       feedback_.reset(new QuicCongestionFeedbackFrame(*visitor.feedback())); | 
 |     } | 
 |     if (blocked_) { | 
 |       *error = ERR_IO_PENDING; | 
 |       return -1; | 
 |     } | 
 |     return packet.length(); | 
 |   } | 
 |  | 
 |   virtual void SetResendAlarm(QuicPacketSequenceNumber sequence_number, | 
 |                               QuicTime::Delta delay) { | 
 |     resend_alarms_[sequence_number] = clock_->Now().Add(delay); | 
 |   } | 
 |  | 
 |   virtual void SetSendAlarm(QuicTime::Delta delay) { | 
 |     send_alarm_ = clock_->Now().Add(delay); | 
 |   } | 
 |  | 
 |   virtual void SetTimeoutAlarm(QuicTime::Delta delay) { | 
 |     timeout_alarm_ = clock_->Now().Add(delay); | 
 |   } | 
 |  | 
 |   virtual bool IsSendAlarmSet() { | 
 |     return send_alarm_ > clock_->Now(); | 
 |   } | 
 |  | 
 |   virtual void UnregisterSendAlarmIfRegistered() { | 
 |     send_alarm_ = QuicTime(); | 
 |   } | 
 |  | 
 |   const map<QuicPacketSequenceNumber, QuicTime>& resend_alarms() const { | 
 |     return resend_alarms_; | 
 |   } | 
 |  | 
 |   QuicTime timeout_alarm() const { return timeout_alarm_; } | 
 |  | 
 |   QuicPacketHeader* header() { return &header_; } | 
 |  | 
 |   QuicAckFrame* ack() { return ack_.get(); } | 
 |  | 
 |   QuicCongestionFeedbackFrame* feedback() { return feedback_.get(); } | 
 |  | 
 |   void set_blocked(bool blocked) { blocked_ = blocked; } | 
 |  | 
 |  private: | 
 |   MockClock* clock_; | 
 |   map<QuicPacketSequenceNumber, QuicTime> resend_alarms_; | 
 |   QuicTime send_alarm_; | 
 |   QuicTime timeout_alarm_; | 
 |   QuicPacketHeader header_; | 
 |   scoped_ptr<QuicAckFrame> ack_; | 
 |   scoped_ptr<QuicCongestionFeedbackFrame> feedback_; | 
 |   bool blocked_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(TestConnectionHelper); | 
 | }; | 
 |  | 
 | class TestConnection : public QuicConnection { | 
 |  public: | 
 |   TestConnection(QuicGuid guid, | 
 |                  IPEndPoint address, | 
 |                  TestConnectionHelper* helper) | 
 |       : QuicConnection(guid, address, helper) { | 
 |   } | 
 |  | 
 |   void SendAck() { | 
 |     QuicConnectionPeer::SendAck(this); | 
 |   } | 
 |  | 
 |   void SetCollector(QuicReceiptMetricsCollector* collector) { | 
 |     QuicConnectionPeer::SetCollector(this, collector); | 
 |   } | 
 |  | 
 |   void SetScheduler(QuicSendScheduler* scheduler) { | 
 |     QuicConnectionPeer::SetScheduler(this, scheduler); | 
 |   } | 
 |  | 
 |   bool SendPacket(QuicPacketSequenceNumber sequence_number, | 
 |                   QuicPacket* packet, | 
 |                   bool should_resend, | 
 |                   bool force, | 
 |                   bool is_retransmit) { | 
 |     return QuicConnection::SendPacket( | 
 |         sequence_number, packet, should_resend, force, is_retransmit); | 
 |   } | 
 |  | 
 |  private: | 
 |   DISALLOW_COPY_AND_ASSIGN(TestConnection); | 
 | }; | 
 |  | 
 | class QuicConnectionTest : public ::testing::Test { | 
 |  protected: | 
 |   QuicConnectionTest() | 
 |       : guid_(42), | 
 |         framer_(QuicDecrypter::Create(kNULL), QuicEncrypter::Create(kNULL)), | 
 |         creator_(guid_, &framer_), | 
 |         scheduler_(new StrictMock<MockScheduler>), | 
 |         helper_(new TestConnectionHelper(&clock_)), | 
 |         connection_(guid_, IPEndPoint(), helper_.get()), | 
 |         frame1_(1, false, 0, data1), | 
 |         frame2_(1, false, 3, data2), | 
 |         accept_packet_(true) { | 
 |     connection_.set_visitor(&visitor_); | 
 |     connection_.SetScheduler(scheduler_); | 
 |     // Simplify tests by not sending feedback unless specifically configured. | 
 |     SetFeedback(NULL); | 
 |     EXPECT_CALL(*scheduler_, TimeUntilSend(_)).WillRepeatedly(Return( | 
 |         QuicTime::Delta())); | 
 |   } | 
 |  | 
 |   QuicAckFrame* last_ack() { | 
 |     return helper_->ack(); | 
 |   } | 
 |  | 
 |   QuicCongestionFeedbackFrame* last_feedback() { | 
 |     return helper_->feedback(); | 
 |   } | 
 |  | 
 |   QuicPacketHeader* last_header() { | 
 |     return helper_->header(); | 
 |   } | 
 |  | 
 |   void ProcessPacket(QuicPacketSequenceNumber number) { | 
 |     EXPECT_CALL(visitor_, OnPacket(_, _, _, _)) | 
 |         .WillOnce(Return(accept_packet_)); | 
 |     EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |     ProcessDataPacket(number, 0); | 
 |   } | 
 |  | 
 |   void ProcessFecProtectedPacket(QuicPacketSequenceNumber number, | 
 |                                  bool expect_revival) { | 
 |     if (expect_revival) { | 
 |       EXPECT_CALL(visitor_, OnPacket(_, _, _, _)).Times(2).WillRepeatedly( | 
 |           Return(accept_packet_)); | 
 |       EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(2); | 
 |     } else { | 
 |       EXPECT_CALL(visitor_, OnPacket(_, _, _, _)).WillOnce( | 
 |           Return(accept_packet_)); | 
 |       EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |     } | 
 |     ProcessDataPacket(number, 1); | 
 |   } | 
 |  | 
 |   void ProcessDataPacket(QuicPacketSequenceNumber number, | 
 |                          QuicFecGroupNumber fec_group) { | 
 |     scoped_ptr<QuicPacket> packet(ConstructDataPacket(number, fec_group)); | 
 |     scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(*packet)); | 
 |     connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted); | 
 |   } | 
 |  | 
 |   // Sends an FEC packet that covers the packets that would have been sent. | 
 |   void ProcessFecPacket(QuicPacketSequenceNumber number, | 
 |                         QuicPacketSequenceNumber min_protected_packet, | 
 |                         bool expect_revival) { | 
 |     if (expect_revival) { | 
 |       EXPECT_CALL(visitor_, OnPacket(_, _, _, _)).WillOnce( | 
 |           Return(accept_packet_)); | 
 |       EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |     } | 
 |  | 
 |     // Construct the decrypted data packet so we can compute the correct | 
 |     // redundancy. | 
 |     scoped_ptr<QuicPacket> data_packet(ConstructDataPacket(number, 1)); | 
 |  | 
 |     header_.guid = guid_; | 
 |     header_.packet_sequence_number = number; | 
 |     header_.flags = PACKET_FLAGS_FEC; | 
 |     header_.fec_group = 1; | 
 |     QuicFecData fec_data; | 
 |     fec_data.min_protected_packet_sequence_number = min_protected_packet; | 
 |     fec_data.fec_group = 1; | 
 |     // Since all data packets in this test have the same payload, the | 
 |     // redundancy is either equal to that payload or the xor of that payload | 
 |     // with itself, depending on the number of packets. | 
 |     if (((number - min_protected_packet) % 2) == 0) { | 
 |       for (size_t i = kStartOfFecProtectedData; i < data_packet->length(); | 
 |            ++i) { | 
 |         data_packet->mutable_data()[i] ^= data_packet->data()[i]; | 
 |       } | 
 |     } | 
 |     fec_data.redundancy = data_packet->FecProtectedData(); | 
 |     scoped_ptr<QuicPacket> fec_packet( | 
 |         framer_.ConstructFecPacket(header_, fec_data)); | 
 |     scoped_ptr<QuicEncryptedPacket> encrypted( | 
 |         framer_.EncryptPacket(*fec_packet)); | 
 |  | 
 |     connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted); | 
 |   } | 
 |  | 
 |   void SendStreamDataToPeer(QuicStreamId id, StringPiece data, | 
 |                             QuicStreamOffset offset, bool fin, | 
 |                             QuicPacketSequenceNumber* last_packet) { | 
 |     EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |     connection_.SendStreamData(id, data, offset, fin, last_packet); | 
 |   } | 
 |  | 
 |   void SendAckPacketToPeer() { | 
 |     EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(num_packets_per_ack_); | 
 |     connection_.SendAck(); | 
 |   } | 
 |  | 
 |   void ProcessAckPacket(QuicAckFrame* frame, bool expect_success = true) { | 
 |     if (expect_success) { | 
 |       EXPECT_CALL(*scheduler_, OnIncomingAckFrame(_)); | 
 |     } | 
 |     scoped_ptr<QuicPacket> packet(creator_.AckPacket(frame).second); | 
 |     scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(*packet)); | 
 |     connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted); | 
 |   } | 
 |  | 
 |   bool IsMissing(QuicPacketSequenceNumber number) { | 
 |     return last_ack()->received_info.IsAwaitingPacket(number); | 
 |   } | 
 |  | 
 |   QuicPacket* ConstructDataPacket(QuicPacketSequenceNumber number, | 
 |                                   QuicFecGroupNumber fec_group) { | 
 |     header_.guid = guid_; | 
 |     header_.packet_sequence_number = number; | 
 |     header_.flags = PACKET_FLAGS_NONE; | 
 |     header_.fec_group = fec_group; | 
 |  | 
 |     QuicFrames frames; | 
 |     QuicFrame frame(&frame1_); | 
 |     frames.push_back(frame); | 
 |     QuicPacket* packet = framer_.ConstructFrameDataPacket(header_, frames); | 
 |     EXPECT_TRUE(packet != NULL); | 
 |     return packet; | 
 |   } | 
 |  | 
 |   void SetFeedback(QuicCongestionFeedbackFrame* feedback) { | 
 |     num_packets_per_ack_ = feedback != NULL ? 2 : 1; | 
 |     collector_ = new TestCollector(feedback); | 
 |     connection_.SetCollector(collector_); | 
 |   } | 
 |  | 
 |   QuicGuid guid_; | 
 |   QuicFramer framer_; | 
 |   QuicPacketCreator creator_; | 
 |  | 
 |   MockScheduler* scheduler_; | 
 |   TestCollector* collector_; | 
 |   MockClock clock_; | 
 |   scoped_ptr<TestConnectionHelper> helper_; | 
 |   TestConnection connection_; | 
 |   testing::StrictMock<MockConnectionVisitor> visitor_; | 
 |  | 
 |   QuicPacketHeader header_; | 
 |   QuicStreamFrame frame1_; | 
 |   QuicStreamFrame frame2_; | 
 |   bool accept_packet_; | 
 |   size_t num_packets_per_ack_; | 
 |  | 
 |  private: | 
 |   DISALLOW_COPY_AND_ASSIGN(QuicConnectionTest); | 
 | }; | 
 |  | 
 | TEST_F(QuicConnectionTest, PacketsInOrder) { | 
 |   ProcessPacket(1); | 
 |   EXPECT_EQ(1u, last_ack()->received_info.largest_received); | 
 |   EXPECT_EQ(0u, last_ack()->received_info.missing_packets.size()); | 
 |  | 
 |   ProcessPacket(2); | 
 |   EXPECT_EQ(2u, last_ack()->received_info.largest_received); | 
 |   EXPECT_EQ(0u, last_ack()->received_info.missing_packets.size()); | 
 |  | 
 |   ProcessPacket(3); | 
 |   EXPECT_EQ(3u, last_ack()->received_info.largest_received); | 
 |   EXPECT_EQ(0u, last_ack()->received_info.missing_packets.size()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, PacketsRejected) { | 
 |   ProcessPacket(1); | 
 |   EXPECT_EQ(1u, last_ack()->received_info.largest_received); | 
 |   EXPECT_EQ(0u, last_ack()->received_info.missing_packets.size()); | 
 |  | 
 |   accept_packet_ = false; | 
 |   ProcessPacket(2); | 
 |   // We should not have an ack for two. | 
 |   EXPECT_EQ(1u, last_ack()->received_info.largest_received); | 
 |   EXPECT_EQ(0u, last_ack()->received_info.missing_packets.size()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, PacketsOutOfOrder) { | 
 |   ProcessPacket(3); | 
 |   EXPECT_EQ(3u, last_ack()->received_info.largest_received); | 
 |   EXPECT_TRUE(IsMissing(2)); | 
 |   EXPECT_TRUE(IsMissing(1)); | 
 |  | 
 |   ProcessPacket(2); | 
 |   EXPECT_EQ(3u, last_ack()->received_info.largest_received); | 
 |   EXPECT_FALSE(IsMissing(2)); | 
 |   EXPECT_TRUE(IsMissing(1)); | 
 |  | 
 |   ProcessPacket(1); | 
 |   EXPECT_EQ(3u, last_ack()->received_info.largest_received); | 
 |   EXPECT_FALSE(IsMissing(2)); | 
 |   EXPECT_FALSE(IsMissing(1)); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, DuplicatePacket) { | 
 |   ProcessPacket(3); | 
 |   EXPECT_EQ(3u, last_ack()->received_info.largest_received); | 
 |   EXPECT_TRUE(IsMissing(2)); | 
 |   EXPECT_TRUE(IsMissing(1)); | 
 |  | 
 |   // Send packet 3 again, but do not set the expectation that | 
 |   // the visitor OnPacket() will be called. | 
 |   ProcessDataPacket(3, 0); | 
 |   EXPECT_EQ(3u, last_ack()->received_info.largest_received); | 
 |   EXPECT_TRUE(IsMissing(2)); | 
 |   EXPECT_TRUE(IsMissing(1)); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, PacketsOutOfOrderWithAdditionsAndLeastAwaiting) { | 
 |   ProcessPacket(3); | 
 |   EXPECT_EQ(3u, last_ack()->received_info.largest_received); | 
 |   EXPECT_TRUE(IsMissing(2)); | 
 |   EXPECT_TRUE(IsMissing(1)); | 
 |  | 
 |   ProcessPacket(2); | 
 |   EXPECT_EQ(3u, last_ack()->received_info.largest_received); | 
 |   EXPECT_TRUE(IsMissing(1)); | 
 |  | 
 |   ProcessPacket(5); | 
 |   EXPECT_EQ(5u, last_ack()->received_info.largest_received); | 
 |   EXPECT_TRUE(IsMissing(1)); | 
 |   EXPECT_TRUE(IsMissing(4)); | 
 |  | 
 |   // Pretend at this point the client has gotten acks for 2 and 3 and 1 is a | 
 |   // packet the peer will not retransmit.  It indicates this by sending 'least | 
 |   // awaiting' is 4.  The connection should then realize 1 will not be | 
 |   // retransmitted, and will remove it from the missing list. | 
 |   creator_.set_sequence_number(5); | 
 |   QuicAckFrame frame(0, 4); | 
 |   ProcessAckPacket(&frame); | 
 |  | 
 |   // Force an ack to be sent. | 
 |   SendAckPacketToPeer(); | 
 |   EXPECT_TRUE(IsMissing(4)); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, RejectPacketTooFarOut) { | 
 |   // Call ProcessDataPacket rather than ProcessPacket, as we should not get a | 
 |   // packet call to the visitor. | 
 |   ProcessDataPacket(6000, 0); | 
 |  | 
 |   SendAckPacketToPeer();  // Packet 2 | 
 |   EXPECT_EQ(0u, last_ack()->received_info.largest_received); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, LeastUnackedLower) { | 
 |   SendStreamDataToPeer(1, "foo", 0, false, NULL); | 
 |   SendStreamDataToPeer(1, "bar", 3, false, NULL); | 
 |   SendStreamDataToPeer(1, "eep", 6, false, NULL); | 
 |  | 
 |   // Start out saying the least unacked is 2 | 
 |   creator_.set_sequence_number(5); | 
 |   QuicAckFrame frame(0, 2); | 
 |   ProcessAckPacket(&frame); | 
 |  | 
 |   // Change it to 1, but lower the sequence number to fake out-of-order packets. | 
 |   // This should be fine. | 
 |   creator_.set_sequence_number(1); | 
 |   QuicAckFrame frame2(0, 1); | 
 |   // The scheduler will not process out of order acks. | 
 |   ProcessAckPacket(&frame2, false); | 
 |  | 
 |   // Now claim it's one, but set the ordering so it was sent "after" the first | 
 |   // one.  This should cause a connection error. | 
 |   EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_ACK_DATA, false)); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |   creator_.set_sequence_number(7); | 
 |   ProcessAckPacket(&frame2, false); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, LeastUnackedGreaterThanPacketSequenceNumber) { | 
 |   EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_ACK_DATA, false)); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |   // Create an ack with least_unacked is 2 in packet number 1. | 
 |   creator_.set_sequence_number(0); | 
 |   QuicAckFrame frame(0, 2); | 
 |   ProcessAckPacket(&frame, false); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, | 
 |        DISABLED_NackSequenceNumberGreaterThanLargestReceived) { | 
 |   SendStreamDataToPeer(1, "foo", 0, false, NULL); | 
 |   SendStreamDataToPeer(1, "bar", 3, false, NULL); | 
 |   SendStreamDataToPeer(1, "eep", 6, false, NULL); | 
 |  | 
 |   EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_ACK_DATA, false)); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |   QuicAckFrame frame(0, 1); | 
 |   frame.received_info.missing_packets.insert(3); | 
 |   ProcessAckPacket(&frame, false); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, AckUnsentData) { | 
 |   // Ack a packet which has not been sent. | 
 |   EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_ACK_DATA, false)); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |   QuicAckFrame frame(1, 0); | 
 |   ProcessAckPacket(&frame, false); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, AckAll) { | 
 |   ProcessPacket(1); | 
 |  | 
 |   creator_.set_sequence_number(1); | 
 |   QuicAckFrame frame1(1, 1); | 
 |   ProcessAckPacket(&frame1); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, BasicSending) { | 
 |   QuicPacketSequenceNumber last_packet; | 
 |   SendStreamDataToPeer(1, "foo", 0, false, &last_packet);  // Packet 1 | 
 |   EXPECT_EQ(1u, last_packet); | 
 |   SendAckPacketToPeer();  // Packet 2 | 
 |  | 
 |   EXPECT_EQ(1u, last_ack()->sent_info.least_unacked); | 
 |  | 
 |   SendAckPacketToPeer();  // Packet 3 | 
 |   EXPECT_EQ(1u, last_ack()->sent_info.least_unacked); | 
 |  | 
 |   SendStreamDataToPeer(1u, "bar", 3, false, &last_packet);  // Packet 4 | 
 |   EXPECT_EQ(4u, last_packet); | 
 |   SendAckPacketToPeer();  // Packet 5 | 
 |   EXPECT_EQ(1u, last_ack()->sent_info.least_unacked); | 
 |  | 
 |   QuicConnectionVisitorInterface::AckedPackets expected_acks; | 
 |   expected_acks.insert(1); | 
 |  | 
 |   // Client acks up to packet 3 | 
 |   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks))); | 
 |   QuicAckFrame frame(3, 0); | 
 |   ProcessAckPacket(&frame); | 
 |   SendAckPacketToPeer();  // Packet 6 | 
 |  | 
 |   // As soon as we've acked one, we skip ack packets 2 and 3 and note lack of | 
 |   // ack for 4. | 
 |   EXPECT_EQ(4u, last_ack()->sent_info.least_unacked); | 
 |  | 
 |   expected_acks.clear(); | 
 |   expected_acks.insert(4); | 
 |  | 
 |   // Client acks up to packet 4, the last packet | 
 |   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks))); | 
 |   QuicAckFrame frame2(6, 0); | 
 |   ProcessAckPacket(&frame2); | 
 |   SendAckPacketToPeer();  // Packet 7 | 
 |  | 
 |   // The least packet awaiting ack should now be 7 | 
 |   EXPECT_EQ(7u, last_ack()->sent_info.least_unacked); | 
 |  | 
 |   // If we force an ack, we shouldn't change our retransmit state. | 
 |   SendAckPacketToPeer();  // Packet 8 | 
 |   EXPECT_EQ(8u, last_ack()->sent_info.least_unacked); | 
 |  | 
 |   // But if we send more data it should. | 
 |   SendStreamDataToPeer(1, "eep", 6, false, &last_packet);  // Packet 9 | 
 |   EXPECT_EQ(9u, last_packet); | 
 |   SendAckPacketToPeer();  // Packet10 | 
 |   EXPECT_EQ(9u, last_ack()->sent_info.least_unacked); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, ResendOnNack) { | 
 |   QuicPacketSequenceNumber last_packet; | 
 |   SendStreamDataToPeer(1, "foo", 0, false, &last_packet);  // Packet 1 | 
 |   SendStreamDataToPeer(1, "foos", 3, false, &last_packet);  // Packet 2 | 
 |   SendStreamDataToPeer(1, "fooos", 7, false, &last_packet);  // Packet 3 | 
 |  | 
 |   QuicConnectionVisitorInterface::AckedPackets expected_acks; | 
 |   expected_acks.insert(1); | 
 |   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks))); | 
 |  | 
 |   // Client acks one but not two or three.  Right now we only resend on explicit | 
 |   // nack, so it should not trigger resend. | 
 |   QuicAckFrame ack_one(1, 0); | 
 |   ProcessAckPacket(&ack_one); | 
 |   ProcessAckPacket(&ack_one); | 
 |   ProcessAckPacket(&ack_one); | 
 |  | 
 |   expected_acks.clear(); | 
 |   expected_acks.insert(3); | 
 |   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks))); | 
 |  | 
 |   // Client acks up to 3 with two explicitly missing.  Two nacks should cause no | 
 |   // change. | 
 |   QuicAckFrame nack_two(3, 0); | 
 |   nack_two.received_info.missing_packets.insert(2); | 
 |   ProcessAckPacket(&nack_two); | 
 |   ProcessAckPacket(&nack_two); | 
 |  | 
 |   // The third nack should trigger resend. | 
 |   EXPECT_CALL(*scheduler_, SentPacket(4, 37, true)).Times(1); | 
 |   ProcessAckPacket(&nack_two); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, LimitPacketsPerNack) { | 
 |   int offset = 0; | 
 |   // Send packets 1 to 12 | 
 |   for (int i = 0; i < 12; ++i) { | 
 |     SendStreamDataToPeer(1, "foo", offset, false, NULL); | 
 |     offset += 3; | 
 |   } | 
 |  | 
 |   // Ack 12, nack 1-11 | 
 |   QuicAckFrame nack(12, 0); | 
 |   for (int i = 1; i < 12; ++i) { | 
 |     nack.received_info.missing_packets.insert(i); | 
 |   } | 
 |  | 
 |   QuicConnectionVisitorInterface::AckedPackets expected_acks; | 
 |   expected_acks.insert(12); | 
 |   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks))); | 
 |  | 
 |   // Nack three times. | 
 |   ProcessAckPacket(&nack); | 
 |   ProcessAckPacket(&nack); | 
 |   // The third call should trigger resending 10 packets and an updated ack. | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(11); | 
 |   ProcessAckPacket(&nack); | 
 |  | 
 |   // The fourth call should triggre resending the 11th packet. | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(1); | 
 |   ProcessAckPacket(&nack); | 
 | } | 
 |  | 
 | // Test sending multiple acks from the connection to the session. | 
 | TEST_F(QuicConnectionTest, MultipleAcks) { | 
 |   QuicPacketSequenceNumber last_packet; | 
 |   SendStreamDataToPeer(1u, "foo", 0, false, &last_packet);  // Packet 1 | 
 |   EXPECT_EQ(1u, last_packet); | 
 |   SendStreamDataToPeer(3u, "foo", 0, false, &last_packet);  // Packet 2 | 
 |   EXPECT_EQ(2u, last_packet); | 
 |   SendAckPacketToPeer();  // Packet 3 | 
 |   SendStreamDataToPeer(5u, "foo", 0, false, &last_packet);  // Packet 4 | 
 |   EXPECT_EQ(4u, last_packet); | 
 |   SendStreamDataToPeer(1u, "foo", 3, false, &last_packet);  // Packet 5 | 
 |   EXPECT_EQ(5u, last_packet); | 
 |   SendStreamDataToPeer(3u, "foo", 3, false, &last_packet);  // Packet 6 | 
 |   EXPECT_EQ(6u, last_packet); | 
 |  | 
 |   // Client will ack packets 1, [!2], 3, 4, 5 | 
 |   QuicAckFrame frame1(5, 0); | 
 |   frame1.received_info.missing_packets.insert(2); | 
 |  | 
 |   // The connection should pass up acks for 1, 4, 5.  2 is not acked, and 3 was | 
 |   // an ackframe so should not be passed up. | 
 |   QuicConnectionVisitorInterface::AckedPackets expected_acks; | 
 |   expected_acks.insert(1); | 
 |   expected_acks.insert(4); | 
 |   expected_acks.insert(5); | 
 |  | 
 |   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks))); | 
 |   ProcessAckPacket(&frame1); | 
 |  | 
 |   // Now the client implicitly acks 2, and explicitly acks 6 | 
 |   QuicAckFrame frame2(6, 0); | 
 |   expected_acks.clear(); | 
 |   // Both acks should be passed up. | 
 |   expected_acks.insert(2); | 
 |   expected_acks.insert(6); | 
 |  | 
 |   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks))); | 
 |   ProcessAckPacket(&frame2); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, DontLatchUnackedPacket) { | 
 |   SendStreamDataToPeer(1, "foo", 0, false, NULL);  // Packet 1; | 
 |   SendAckPacketToPeer();  // Packet 2 | 
 |  | 
 |   // This sets least unacked to 2, the ack packet. | 
 |   QuicConnectionVisitorInterface::AckedPackets expected_acks; | 
 |   expected_acks.insert(1); | 
 |   // Client acks packet 1 | 
 |   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks))); | 
 |   QuicAckFrame frame(1, 0); | 
 |   ProcessAckPacket(&frame); | 
 |  | 
 |   // Verify that our internal state has least-unacked as 2. | 
 |   QuicAckFrame* outgoing_ack = QuicConnectionPeer::GetOutgoingAck(&connection_); | 
 |   EXPECT_EQ(2u, outgoing_ack->sent_info.least_unacked); | 
 |  | 
 |   // When we send an ack, we make sure our least-unacked makes sense.  In this | 
 |   // case since we're not waiting on an ack for 2 and all packets are acked, we | 
 |   // set it to 3. | 
 |   SendAckPacketToPeer();  // Packet 3 | 
 |   EXPECT_EQ(3u, outgoing_ack->sent_info.least_unacked); | 
 |   EXPECT_EQ(3u, last_ack()->sent_info.least_unacked); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, ReviveMissingPacketAfterFecPacket) { | 
 |   // Don't send missing packet 1. | 
 |   ProcessFecPacket(2, 1, true); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, ReviveMissingPacketAfterDataPacketThenFecPacket) { | 
 |   ProcessFecProtectedPacket(1, false); | 
 |   // Don't send missing packet 2. | 
 |   ProcessFecPacket(3, 1, true); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, ReviveMissingPacketAfterDataPacketsThenFecPacket) { | 
 |   ProcessFecProtectedPacket(1, false); | 
 |   // Don't send missing packet 2. | 
 |   ProcessFecProtectedPacket(3, false); | 
 |   ProcessFecPacket(4, 1, true); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, ReviveMissingPacketAfterDataPacket) { | 
 |   // Don't send missing packet 1. | 
 |   ProcessFecPacket(3, 1, false);  // out of order | 
 |   ProcessFecProtectedPacket(2, true); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, ReviveMissingPacketAfterDataPackets) { | 
 |   ProcessFecProtectedPacket(1, false); | 
 |   // Don't send missing packet 2. | 
 |   ProcessFecPacket(6, 1, false); | 
 |   ProcessFecProtectedPacket(3, false); | 
 |   ProcessFecProtectedPacket(4, false); | 
 |   ProcessFecProtectedPacket(5, true); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, TestResend) { | 
 |   // TODO(rch): make this work | 
 |   // FLAGS_fake_packet_loss_percentage = 100; | 
 |   const QuicTime::Delta kDefaultResendTime = | 
 |       QuicTime::Delta::FromMilliseconds(500); | 
 |  | 
 |   QuicTime default_resend_time = clock_.Now().Add(kDefaultResendTime); | 
 |  | 
 |   QuicAckFrame* outgoing_ack = QuicConnectionPeer::GetOutgoingAck(&connection_); | 
 |   SendStreamDataToPeer(1, "foo", 0, false, NULL); | 
 |   EXPECT_EQ(1u, outgoing_ack->sent_info.least_unacked); | 
 |  | 
 |   EXPECT_EQ(1u, last_header()->packet_sequence_number); | 
 |   EXPECT_EQ(1u, helper_->resend_alarms().size()); | 
 |   EXPECT_EQ(default_resend_time, | 
 |             helper_->resend_alarms().find(1)->second); | 
 |   // Simulate the resend alarm firing | 
 |   clock_.AdvanceTime(kDefaultResendTime); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |   connection_.MaybeResendPacket(1); | 
 |   EXPECT_EQ(2u, last_header()->packet_sequence_number); | 
 |   EXPECT_EQ(2u, outgoing_ack->sent_info.least_unacked); | 
 | } | 
 |  | 
 | // TODO(rch): Enable after we get non-blocking sockets. | 
 | TEST_F(QuicConnectionTest, DISABLED_TestQueued) { | 
 |   EXPECT_EQ(0u, connection_.NumQueuedPackets()); | 
 |   helper_->set_blocked(true); | 
 |   SendStreamDataToPeer(1, "foo", 0, false, NULL); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 |  | 
 |   // Attempt to send all packets, but since we're actually still | 
 |   // blocked, they should all remain queued. | 
 |   EXPECT_FALSE(connection_.OnCanWrite()); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 |  | 
 |   // Unblock the writes and actually send. | 
 |   helper_->set_blocked(false); | 
 |   EXPECT_CALL(visitor_, OnCanWrite()); | 
 |   EXPECT_TRUE(connection_.OnCanWrite()); | 
 |   EXPECT_EQ(0u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, CloseFecGroup) { | 
 |   // Don't send missing packet 1 | 
 |   // Don't send missing packet 2 | 
 |   ProcessFecProtectedPacket(3, false); | 
 |   // Don't send missing FEC packet 3 | 
 |   ASSERT_EQ(1u, connection_.NumFecGroups()); | 
 |  | 
 |   // Now send non-fec protected ack packet and close the group | 
 |   QuicAckFrame frame(0, 5); | 
 |   creator_.set_sequence_number(4); | 
 |   ProcessAckPacket(&frame); | 
 |   ASSERT_EQ(0u, connection_.NumFecGroups()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, NoQuicCongestionFeedbackFrame) { | 
 |   SendAckPacketToPeer(); | 
 |   EXPECT_TRUE(last_feedback() == NULL); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, WithQuicCongestionFeedbackFrame) { | 
 |   QuicCongestionFeedbackFrame info; | 
 |   info.type = kFixRate; | 
 |   info.fix_rate.bitrate_in_bytes_per_second = 123; | 
 |   SetFeedback(&info); | 
 |  | 
 |   SendAckPacketToPeer(); | 
 |   EXPECT_EQ(kFixRate, last_feedback()->type); | 
 |   EXPECT_EQ(info.fix_rate.bitrate_in_bytes_per_second, | 
 |             last_feedback()->fix_rate.bitrate_in_bytes_per_second); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, UpdateQuicCongestionFeedbackFrame) { | 
 |   SendAckPacketToPeer(); | 
 |   EXPECT_CALL(*collector_, RecordIncomingPacket(_, _, _, _)); | 
 |   ProcessPacket(1); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, DontUpdateQuicCongestionFeedbackFrameForRevived) { | 
 |   SendAckPacketToPeer(); | 
 |   // Process an FEC packet, and revive the missing data packet | 
 |   // but only contact the collector once. | 
 |   EXPECT_CALL(*collector_, RecordIncomingPacket(_, _, _, _)); | 
 |   ProcessFecPacket(2, 1, true); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, InitialTimeout) { | 
 |   EXPECT_TRUE(connection_.connected()); | 
 |   EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, false)); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |  | 
 |   QuicTime default_timeout = clock_.Now().Add( | 
 |       QuicTime::Delta::FromMicroseconds(kDefaultTimeoutUs)); | 
 |   EXPECT_EQ(default_timeout, helper_->timeout_alarm()); | 
 |  | 
 |   // Simulate the timeout alarm firing | 
 |   clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(kDefaultTimeoutUs)); | 
 |   EXPECT_TRUE(connection_.CheckForTimeout()); | 
 |   EXPECT_FALSE(connection_.connected()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, TimeoutAfterSend) { | 
 |   EXPECT_TRUE(connection_.connected()); | 
 |  | 
 |   QuicTime default_timeout = clock_.Now().Add( | 
 |       QuicTime::Delta::FromMicroseconds(kDefaultTimeoutUs)); | 
 |  | 
 |   // When we send a packet, the timeout will change to 5000 + kDefaultTimeout. | 
 |   clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); | 
 |  | 
 |   // Send an ack so we don't set the resend alarm. | 
 |   SendAckPacketToPeer(); | 
 |   EXPECT_EQ(default_timeout, helper_->timeout_alarm()); | 
 |  | 
 |   // The original alarm will fire.  We should not time out because we had a | 
 |   // network event at t=5000.  The alarm will reregister. | 
 |   clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds( | 
 |       kDefaultTimeoutUs - 5000)); | 
 |   EXPECT_EQ(default_timeout, clock_.Now()); | 
 |   EXPECT_FALSE(connection_.CheckForTimeout()); | 
 |   EXPECT_TRUE(connection_.connected()); | 
 |   EXPECT_EQ(default_timeout.Add(QuicTime::Delta::FromMilliseconds(5)), | 
 |             helper_->timeout_alarm()); | 
 |  | 
 |   // This time, we should time out. | 
 |   EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, false)); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |   clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); | 
 |   EXPECT_EQ(default_timeout.Add(QuicTime::Delta::FromMilliseconds(5)), | 
 |             clock_.Now()); | 
 |   EXPECT_TRUE(connection_.CheckForTimeout()); | 
 |   EXPECT_FALSE(connection_.connected()); | 
 | } | 
 |  | 
 | // TODO(ianswett): Add scheduler tests when resend is false. | 
 | TEST_F(QuicConnectionTest, SendScheduler) { | 
 |   // Test that if we send a packet without delay, it is not queued. | 
 |   scoped_ptr<QuicPacket> packet(ConstructDataPacket(1, 0)); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta())); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |   connection_.SendPacket(1, packet.get(), true, false, false); | 
 |   EXPECT_EQ(0u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, SendSchedulerDelay) { | 
 |   // Test that if we send a packet with a delay, it ends up queued. | 
 |   scoped_ptr<QuicPacket> packet(ConstructDataPacket(1, 0)); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta::FromMicroseconds(1))); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(1, _, _)).Times(0); | 
 |   connection_.SendPacket(1, packet.get(), true, false, false); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, SendSchedulerForce) { | 
 |   // Test that if we force send a packet, it is not queued. | 
 |   scoped_ptr<QuicPacket> packet(ConstructDataPacket(1, 0)); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).Times(0); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |   connection_.SendPacket(1, packet.get(), true, true, false); | 
 |   EXPECT_EQ(0u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | // TODO(rch): Enable after we get non-blocking sockets. | 
 | TEST_F(QuicConnectionTest, DISABLED_SendSchedulerEAGAIN) { | 
 |   scoped_ptr<QuicPacket> packet(ConstructDataPacket(1, 0)); | 
 |   helper_->set_blocked(true); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta())); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(1, _, _)).Times(0); | 
 |   connection_.SendPacket(1, packet.get(), true, false, false); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, SendSchedulerDelayThenSend) { | 
 |   // Test that if we send a packet with a delay, it ends up queued. | 
 |   scoped_ptr<QuicPacket> packet(ConstructDataPacket(1, 0)); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta::FromMicroseconds(1))); | 
 |   connection_.SendPacket(1, packet.get(), true, false, false); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 |  | 
 |   // Advance the clock to fire the alarm, and configure the scheduler | 
 |   // to permit the packet to be sent. | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta())); | 
 |   clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(1)); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |   EXPECT_CALL(visitor_, OnCanWrite()); | 
 |   connection_.OnCanWrite(); | 
 |   EXPECT_EQ(0u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, SendSchedulerDelayThenRetransmit) { | 
 |   // Test that if we send a retransmit with a delay, it ends up queued. | 
 |   scoped_ptr<QuicPacket> packet(ConstructDataPacket(1, 0)); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta::FromMicroseconds(1))); | 
 |   connection_.SendPacket(1, packet.get(), true, false, true); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 |  | 
 |   // Advance the clock to fire the alarm, and configure the scheduler | 
 |   // to permit the packet to be sent. | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta())); | 
 |  | 
 |   // Ensure the scheduler is notified this is a retransmit. | 
 |   EXPECT_CALL(*scheduler_, SentPacket(1, _, true)); | 
 |   clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(1)); | 
 |   EXPECT_CALL(visitor_, OnCanWrite()); | 
 |   connection_.OnCanWrite(); | 
 |   EXPECT_EQ(0u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, SendSchedulerDelayAndQueue) { | 
 |   scoped_ptr<QuicPacket> packet(ConstructDataPacket(1, 0)); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta::FromMicroseconds(1))); | 
 |   connection_.SendPacket(1, packet.get(), true, false, false); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 |  | 
 |   // Attempt to send another packet and make sure that it gets queued. | 
 |   connection_.SendPacket(2, packet.get(), true, false, false); | 
 |   EXPECT_EQ(2u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, SendSchedulerDelayThenAckAndSend) { | 
 |   scoped_ptr<QuicPacket> packet(ConstructDataPacket(1, 0)); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta::FromMicroseconds(10))); | 
 |   connection_.SendPacket(1, packet.get(), true, false, false); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 |  | 
 |   // Now send non-retransmitting information, that we're not going to resend 3. | 
 |   // The far end should stop waiting for it. | 
 |   QuicAckFrame frame(0, 1); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillRepeatedly(testing::Return( | 
 |       QuicTime::Delta())); | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)); | 
 |   EXPECT_CALL(visitor_, OnCanWrite()); | 
 |   ProcessAckPacket(&frame); | 
 |  | 
 |   EXPECT_EQ(0u, connection_.NumQueuedPackets()); | 
 |   // Ensure alarm is not set | 
 |   EXPECT_FALSE(helper_->IsSendAlarmSet()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, SendSchedulerDelayThenAckAndHold) { | 
 |   scoped_ptr<QuicPacket> packet(ConstructDataPacket(1, 0)); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta::FromMicroseconds(10))); | 
 |   connection_.SendPacket(1, packet.get(), true, false, false); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 |  | 
 |   // Now send non-resending information, that we're not going to resend 3. | 
 |   // The far end should stop waiting for it. | 
 |   QuicAckFrame frame(0, 1); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta::FromMicroseconds(1))); | 
 |   EXPECT_CALL(visitor_, OnCanWrite()); | 
 |   ProcessAckPacket(&frame); | 
 |  | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, SendSchedulerDelayThenOnCanWrite) { | 
 |   scoped_ptr<QuicPacket> packet(ConstructDataPacket(1, 0)); | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta::FromMicroseconds(10))); | 
 |   connection_.SendPacket(1, packet.get(), true, false, false); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 |  | 
 |   // OnCanWrite should not send the packet (because of the delay) | 
 |   // but should still return true. | 
 |   EXPECT_CALL(visitor_, OnCanWrite()); | 
 |   EXPECT_TRUE(connection_.OnCanWrite()); | 
 |   EXPECT_EQ(1u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, TestQueueLimitsOnSendStreamData) { | 
 |   // Limit to one byte per packet. | 
 |   size_t ciphertext_size = NullEncrypter().GetCiphertextSize(1); | 
 |   connection_.options()->max_packet_length = | 
 |       ciphertext_size + QuicUtils::StreamFramePacketOverhead(1); | 
 |  | 
 |   // Queue the first packet. | 
 |   EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return( | 
 |       QuicTime::Delta::FromMicroseconds(10))); | 
 |   EXPECT_EQ(6u, | 
 |             connection_.SendStreamData(1, "EnoughDataToQueue", 0, false, NULL)); | 
 |   EXPECT_EQ(6u, connection_.NumQueuedPackets()); | 
 | } | 
 |  | 
 | TEST_F(QuicConnectionTest, LoopThroughSendingPackets) { | 
 |   // Limit to one byte per packet. | 
 |   size_t ciphertext_size = NullEncrypter().GetCiphertextSize(1); | 
 |   connection_.options()->max_packet_length = | 
 |       ciphertext_size + QuicUtils::StreamFramePacketOverhead(1); | 
 |  | 
 |   // Queue the first packet. | 
 |   EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(17); | 
 |   EXPECT_EQ(17u, | 
 |             connection_.SendStreamData(1, "EnoughDataToQueue", 0, false, NULL)); | 
 | } | 
 |  | 
 | }  // namespace | 
 | }  // namespace test | 
 | }  // namespace net |