Home | History | Annotate | Download | only in quic
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/quic/quic_connection_helper.h"
      6 
      7 #include <vector>
      8 
      9 #include "net/base/net_errors.h"
     10 #include "net/quic/crypto/quic_decrypter.h"
     11 #include "net/quic/crypto/quic_encrypter.h"
     12 #include "net/quic/test_tools/mock_clock.h"
     13 #include "net/quic/test_tools/quic_connection_peer.h"
     14 #include "net/quic/test_tools/quic_test_utils.h"
     15 #include "net/quic/test_tools/test_task_runner.h"
     16 #include "net/socket/socket_test_util.h"
     17 #include "testing/gmock/include/gmock/gmock.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 using testing::_;
     21 
     22 namespace net {
     23 namespace test {
     24 
     25 const char kData[] = "foo";
     26 const bool kFromPeer = true;
     27 
     28 class TestDelegate : public QuicAlarm::Delegate {
     29  public:
     30   TestDelegate() : fired_(false) {}
     31 
     32   virtual QuicTime OnAlarm() OVERRIDE {
     33     fired_ = true;
     34     return QuicTime::Zero();
     35   }
     36 
     37   bool fired() const { return fired_; }
     38 
     39  private:
     40   bool fired_;
     41 };
     42 
     43 class TestConnection : public QuicConnection {
     44  public:
     45   TestConnection(QuicGuid guid,
     46                  IPEndPoint address,
     47                  QuicConnectionHelper* helper)
     48       : QuicConnection(guid, address, helper, false, QuicVersionMax()) {
     49   }
     50 
     51   void SendAck() {
     52     QuicConnectionPeer::SendAck(this);
     53   }
     54 
     55   void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
     56     QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
     57   }
     58 
     59   using QuicConnection::SendOrQueuePacket;
     60 };
     61 
     62 class QuicConnectionHelperTest : public ::testing::Test {
     63  protected:
     64   // Holds a packet to be written to the wire, and the IO mode that should
     65   // be used by the mock socket when performing the write.
     66   struct PacketToWrite {
     67     PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
     68         : mode(mode),
     69           packet(packet) {
     70     }
     71     IoMode mode;
     72     QuicEncryptedPacket* packet;
     73   };
     74 
     75   QuicConnectionHelperTest()
     76       : guid_(2),
     77         framer_(QuicVersionMax(), QuicTime::Zero(), false),
     78         net_log_(BoundNetLog()),
     79         frame_(1, false, 0, kData) {
     80     Initialize();
     81   }
     82 
     83   ~QuicConnectionHelperTest() {
     84     for (size_t i = 0; i < writes_.size(); i++) {
     85       delete writes_[i].packet;
     86     }
     87   }
     88 
     89   // Adds a packet to the list of expected writes.
     90   void AddWrite(IoMode mode, QuicEncryptedPacket* packet) {
     91     writes_.push_back(PacketToWrite(mode, packet));
     92   }
     93 
     94   // Returns the packet to be written at position |pos|.
     95   QuicEncryptedPacket* GetWrite(size_t pos) {
     96     return writes_[pos].packet;
     97   }
     98 
     99   bool AtEof() {
    100     return socket_data_->at_read_eof() && socket_data_->at_write_eof();
    101   }
    102 
    103   // Configures the test fixture to use the list of expected writes.
    104   void Initialize() {
    105     mock_writes_.reset(new MockWrite[writes_.size()]);
    106     for (size_t i = 0; i < writes_.size(); i++) {
    107       mock_writes_[i] = MockWrite(writes_[i].mode,
    108                                   writes_[i].packet->data(),
    109                                   writes_[i].packet->length());
    110     };
    111 
    112     socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
    113                                                     writes_.size()));
    114 
    115     socket_.reset(new MockUDPClientSocket(socket_data_.get(),
    116                                           net_log_.net_log()));
    117     socket_->Connect(IPEndPoint());
    118     runner_ = new TestTaskRunner(&clock_);
    119     helper_ = new QuicConnectionHelper(runner_.get(), &clock_,
    120                                        &random_generator_, socket_.get());
    121     send_algorithm_ = new testing::StrictMock<MockSendAlgorithm>();
    122     EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
    123         WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
    124     connection_.reset(new TestConnection(guid_, IPEndPoint(), helper_));
    125     connection_->set_visitor(&visitor_);
    126     connection_->SetSendAlgorithm(send_algorithm_);
    127   }
    128 
    129   // Returns a newly created packet to send kData on stream 1.
    130   QuicEncryptedPacket* ConstructDataPacket(
    131       QuicPacketSequenceNumber sequence_number) {
    132     InitializeHeader(sequence_number);
    133 
    134     return ConstructPacket(header_, QuicFrame(&frame_));
    135   }
    136 
    137   // Returns a newly created packet to send kData on stream 1.
    138   QuicPacket* ConstructRawDataPacket(
    139       QuicPacketSequenceNumber sequence_number) {
    140     InitializeHeader(sequence_number);
    141 
    142     QuicFrames frames;
    143     frames.push_back(QuicFrame(&frame_));
    144     return framer_.BuildUnsizedDataPacket(header_, frames).packet;
    145   }
    146 
    147   // Returns a newly created packet to send ack data.
    148   QuicEncryptedPacket* ConstructAckPacket(
    149       QuicPacketSequenceNumber sequence_number) {
    150     InitializeHeader(sequence_number);
    151 
    152     QuicAckFrame ack(0, QuicTime::Zero(), sequence_number);
    153     ack.sent_info.entropy_hash = 0;
    154     ack.received_info.entropy_hash = 0;
    155 
    156     QuicCongestionFeedbackFrame feedback;
    157     feedback.type = kTCP;
    158     feedback.tcp.accumulated_number_of_lost_packets = 0;
    159     feedback.tcp.receive_window = 16000 << 4;
    160 
    161     QuicFrames frames;
    162     frames.push_back(QuicFrame(&ack));
    163     frames.push_back(QuicFrame(&feedback));
    164     scoped_ptr<QuicPacket> packet(
    165         framer_.BuildUnsizedDataPacket(header_, frames).packet);
    166     return framer_.EncryptPacket(
    167         ENCRYPTION_NONE, header_.packet_sequence_number, *packet);
    168   }
    169 
    170   // Returns a newly created packet to send a connection close frame.
    171   QuicEncryptedPacket* ConstructClosePacket(
    172       QuicPacketSequenceNumber sequence_number,
    173       QuicPacketSequenceNumber least_waiting) {
    174     InitializeHeader(sequence_number);
    175 
    176     QuicFrames frames;
    177     QuicAckFrame ack(0, QuicTime::Zero(), least_waiting + 1);
    178     ack.sent_info.entropy_hash = 0;
    179     ack.received_info.entropy_hash = 0;
    180     QuicConnectionCloseFrame close;
    181     close.error_code = QUIC_CONNECTION_TIMED_OUT;
    182     close.ack_frame = ack;
    183 
    184     return ConstructPacket(header_, QuicFrame(&close));
    185   }
    186 
    187   testing::StrictMock<MockSendAlgorithm>* send_algorithm_;
    188   scoped_refptr<TestTaskRunner> runner_;
    189   QuicConnectionHelper* helper_;
    190   scoped_ptr<MockUDPClientSocket> socket_;
    191   scoped_ptr<MockWrite[]> mock_writes_;
    192   MockClock clock_;
    193   MockRandom random_generator_;
    194   scoped_ptr<TestConnection> connection_;
    195   testing::StrictMock<MockConnectionVisitor> visitor_;
    196 
    197  private:
    198   void InitializeHeader(QuicPacketSequenceNumber sequence_number) {
    199     header_.public_header.guid = guid_;
    200     header_.public_header.reset_flag = false;
    201     header_.public_header.version_flag = true;
    202     header_.packet_sequence_number = sequence_number;
    203     header_.entropy_flag = false;
    204     header_.fec_flag = false;
    205     header_.is_in_fec_group = NOT_IN_FEC_GROUP;
    206     header_.fec_group = 0;
    207   }
    208 
    209   QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header,
    210                                        const QuicFrame& frame) {
    211     QuicFrames frames;
    212     frames.push_back(frame);
    213     scoped_ptr<QuicPacket> packet(
    214         framer_.BuildUnsizedDataPacket(header_, frames).packet);
    215     return framer_.EncryptPacket(
    216         ENCRYPTION_NONE, header_.packet_sequence_number, *packet);
    217   }
    218 
    219   QuicGuid guid_;
    220   QuicFramer framer_;
    221   QuicPacketHeader header_;
    222   BoundNetLog net_log_;
    223   QuicStreamFrame frame_;
    224   scoped_ptr<StaticSocketDataProvider> socket_data_;
    225   std::vector<PacketToWrite> writes_;
    226 };
    227 
    228 TEST_F(QuicConnectionHelperTest, GetClock) {
    229   EXPECT_EQ(&clock_, helper_->GetClock());
    230 }
    231 
    232 TEST_F(QuicConnectionHelperTest, GetRandomGenerator) {
    233   EXPECT_EQ(&random_generator_, helper_->GetRandomGenerator());
    234 }
    235 
    236 TEST_F(QuicConnectionHelperTest, CreateAlarm) {
    237   TestDelegate* delegate = new TestDelegate();
    238   scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
    239 
    240   // The timeout alarm task is always posted.
    241   ASSERT_EQ(1u, runner_->GetPostedTasks().size());
    242 
    243   QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
    244   alarm->Set(clock_.Now().Add(delta));
    245 
    246   // Verify that the alarm task has been posted.
    247   ASSERT_EQ(2u, runner_->GetPostedTasks().size());
    248   EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
    249             runner_->GetPostedTasks()[1].delay);
    250 
    251   runner_->RunNextTask();
    252   EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
    253   EXPECT_TRUE(delegate->fired());
    254 }
    255 
    256 TEST_F(QuicConnectionHelperTest, CreateAlarmAndCancel) {
    257   TestDelegate* delegate = new TestDelegate();
    258   scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
    259 
    260   QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
    261   alarm->Set(clock_.Now().Add(delta));
    262   alarm->Cancel();
    263 
    264   // The alarm task should still be posted.
    265   ASSERT_EQ(2u, runner_->GetPostedTasks().size());
    266   EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
    267             runner_->GetPostedTasks()[1].delay);
    268 
    269   runner_->RunNextTask();
    270   EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
    271   EXPECT_FALSE(delegate->fired());
    272 }
    273 
    274 TEST_F(QuicConnectionHelperTest, CreateAlarmAndReset) {
    275   TestDelegate* delegate = new TestDelegate();
    276   scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
    277 
    278   QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
    279   alarm->Set(clock_.Now().Add(delta));
    280   alarm->Cancel();
    281   QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3);
    282   alarm->Set(clock_.Now().Add(new_delta));
    283 
    284   // The alarm task should still be posted.
    285   ASSERT_EQ(2u, runner_->GetPostedTasks().size());
    286   EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
    287             runner_->GetPostedTasks()[1].delay);
    288 
    289   runner_->RunNextTask();
    290   EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
    291   EXPECT_FALSE(delegate->fired());
    292 
    293   // The alarm task should be posted again.
    294   ASSERT_EQ(2u, runner_->GetPostedTasks().size());
    295 
    296   runner_->RunNextTask();
    297   EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now());
    298   EXPECT_TRUE(delegate->fired());
    299 }
    300 
    301 TEST_F(QuicConnectionHelperTest, TestRetransmission) {
    302   AddWrite(SYNCHRONOUS, ConstructDataPacket(1));
    303   AddWrite(SYNCHRONOUS, ConstructDataPacket(2));
    304   Initialize();
    305 
    306   EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
    307       testing::Return(QuicTime::Delta::Zero()));
    308 
    309   QuicTime::Delta kDefaultRetransmissionTime =
    310       QuicTime::Delta::FromMilliseconds(500);
    311   QuicTime start = clock_.ApproximateNow();
    312 
    313   EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION));
    314   EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, _));
    315   // Send a packet.
    316   connection_->SendStreamData(1, kData, 0, false);
    317   EXPECT_CALL(*send_algorithm_, SentPacket(_, 2, _, IS_RETRANSMISSION));
    318   // Since no ack was received, the retransmission alarm will fire and
    319   // retransmit it.
    320   runner_->RunNextTask();
    321 
    322   EXPECT_EQ(kDefaultRetransmissionTime,
    323             clock_.ApproximateNow().Subtract(start));
    324   EXPECT_TRUE(AtEof());
    325 }
    326 
    327 TEST_F(QuicConnectionHelperTest, TestMultipleRetransmission) {
    328   AddWrite(SYNCHRONOUS, ConstructDataPacket(1));
    329   AddWrite(SYNCHRONOUS, ConstructDataPacket(2));
    330   AddWrite(SYNCHRONOUS, ConstructDataPacket(3));
    331   Initialize();
    332 
    333   EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
    334       testing::Return(QuicTime::Delta::Zero()));
    335 
    336   QuicTime::Delta kDefaultRetransmissionTime =
    337       QuicTime::Delta::FromMilliseconds(500);
    338   QuicTime start = clock_.ApproximateNow();
    339 
    340   EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION));
    341   EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, _));
    342   // Send a packet.
    343   connection_->SendStreamData(1, kData, 0, false);
    344   EXPECT_CALL(*send_algorithm_, SentPacket(_, 2, _, IS_RETRANSMISSION));
    345   // Since no ack was received, the retransmission alarm will fire and
    346   // retransmit it.
    347   runner_->RunNextTask();
    348 
    349   EXPECT_EQ(kDefaultRetransmissionTime,
    350             clock_.ApproximateNow().Subtract(start));
    351 
    352   // Since no ack was received, the retransmission alarm will fire and
    353   // retransmit it.
    354   EXPECT_CALL(*send_algorithm_, SentPacket(_, 3, _, IS_RETRANSMISSION));
    355   EXPECT_CALL(*send_algorithm_, AbandoningPacket(2, _));
    356   runner_->RunNextTask();
    357 
    358   EXPECT_EQ(kDefaultRetransmissionTime.Add(kDefaultRetransmissionTime),
    359             clock_.ApproximateNow().Subtract(start));
    360 
    361   EXPECT_TRUE(AtEof());
    362 }
    363 
    364 TEST_F(QuicConnectionHelperTest, InitialTimeout) {
    365   AddWrite(SYNCHRONOUS, ConstructClosePacket(1, 0));
    366   Initialize();
    367 
    368   // Verify that a single task was posted.
    369   ASSERT_EQ(1u, runner_->GetPostedTasks().size());
    370   EXPECT_EQ(base::TimeDelta::FromSeconds(kDefaultInitialTimeoutSecs),
    371             runner_->GetPostedTasks().front().delay);
    372 
    373   EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION));
    374   // After we run the next task, we should close the connection.
    375   EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, false));
    376 
    377   runner_->RunNextTask();
    378   EXPECT_EQ(QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(
    379                 kDefaultInitialTimeoutSecs)),
    380             clock_.ApproximateNow());
    381   EXPECT_FALSE(connection_->connected());
    382   EXPECT_TRUE(AtEof());
    383 }
    384 
    385 TEST_F(QuicConnectionHelperTest, WritePacketToWire) {
    386   AddWrite(SYNCHRONOUS, ConstructDataPacket(1));
    387   Initialize();
    388 
    389   int len = GetWrite(0)->length();
    390   int error = 0;
    391   EXPECT_EQ(len, helper_->WritePacketToWire(*GetWrite(0), &error));
    392   EXPECT_EQ(0, error);
    393   EXPECT_TRUE(AtEof());
    394 }
    395 
    396 TEST_F(QuicConnectionHelperTest, WritePacketToWireAsync) {
    397   AddWrite(ASYNC, ConstructClosePacket(1, 0));
    398   Initialize();
    399 
    400   EXPECT_CALL(visitor_, OnCanWrite()).WillOnce(testing::Return(true));
    401   int error = 0;
    402   EXPECT_EQ(-1, helper_->WritePacketToWire(*GetWrite(0), &error));
    403   EXPECT_EQ(ERR_IO_PENDING, error);
    404   base::MessageLoop::current()->RunUntilIdle();
    405   EXPECT_TRUE(AtEof());
    406 }
    407 
    408 TEST_F(QuicConnectionHelperTest, TimeoutAfterSend) {
    409   AddWrite(SYNCHRONOUS, ConstructAckPacket(1));
    410   AddWrite(SYNCHRONOUS, ConstructClosePacket(2, 1));
    411   Initialize();
    412 
    413   EXPECT_TRUE(connection_->connected());
    414   QuicTime start = clock_.ApproximateNow();
    415 
    416   // When we send a packet, the timeout will change to 5000 +
    417   // kDefaultInitialTimeoutSecs.
    418   clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(5000));
    419   EXPECT_EQ(5000u, clock_.ApproximateNow().Subtract(start).ToMicroseconds());
    420   EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION));
    421 
    422   // Send an ack so we don't set the retransmission alarm.
    423   connection_->SendAck();
    424 
    425   // The original alarm will fire.  We should not time out because we had a
    426   // network event at t=5000.  The alarm will reregister.
    427   runner_->RunNextTask();
    428 
    429   EXPECT_EQ(QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(
    430                 kDefaultInitialTimeoutSecs)),
    431             clock_.ApproximateNow());
    432   EXPECT_TRUE(connection_->connected());
    433 
    434   // This time, we should time out.
    435   EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, !kFromPeer));
    436   EXPECT_CALL(*send_algorithm_, SentPacket(_, 2, _, NOT_RETRANSMISSION));
    437   runner_->RunNextTask();
    438   EXPECT_EQ(kDefaultInitialTimeoutSecs * 1000000 + 5000,
    439             clock_.ApproximateNow().Subtract(
    440                 QuicTime::Zero()).ToMicroseconds());
    441   EXPECT_FALSE(connection_->connected());
    442   EXPECT_TRUE(AtEof());
    443 }
    444 
    445 TEST_F(QuicConnectionHelperTest, SendSchedulerDelayThenSend) {
    446   AddWrite(SYNCHRONOUS, ConstructDataPacket(1));
    447   Initialize();
    448 
    449   // Test that if we send a packet with a delay, it ends up queued.
    450   EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
    451       testing::Return(QuicTime::Delta::Zero()));
    452   EXPECT_CALL(
    453       *send_algorithm_, TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
    454           testing::Return(QuicTime::Delta::FromMicroseconds(1)));
    455 
    456   QuicPacket* packet = ConstructRawDataPacket(1);
    457   connection_->SendOrQueuePacket(
    458       ENCRYPTION_NONE, 1, packet, 0, HAS_RETRANSMITTABLE_DATA);
    459   EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION));
    460   EXPECT_EQ(1u, connection_->NumQueuedPackets());
    461 
    462   // Advance the clock to fire the alarm, and configure the scheduler
    463   // to permit the packet to be sent.
    464   EXPECT_CALL(*send_algorithm_,
    465               TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillRepeatedly(
    466       testing::Return(QuicTime::Delta::Zero()));
    467   EXPECT_CALL(visitor_, OnCanWrite()).WillOnce(testing::Return(true));
    468   runner_->RunNextTask();
    469   EXPECT_EQ(0u, connection_->NumQueuedPackets());
    470   EXPECT_TRUE(AtEof());
    471 }
    472 
    473 }  // namespace test
    474 }  // namespace net
    475