Home | History | Annotate | Download | only in quic
      1 // Copyright 2014 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_flow_controller.h"
      6 
      7 #include "base/strings/stringprintf.h"
      8 #include "net/quic/quic_flags.h"
      9 #include "net/quic/quic_utils.h"
     10 #include "net/quic/test_tools/quic_connection_peer.h"
     11 #include "net/quic/test_tools/quic_flow_controller_peer.h"
     12 #include "net/quic/test_tools/quic_test_utils.h"
     13 #include "net/test/gtest_util.h"
     14 #include "testing/gmock/include/gmock/gmock.h"
     15 
     16 using base::StringPrintf;
     17 
     18 namespace net {
     19 namespace test {
     20 
     21 using ::testing::_;
     22 
     23 class QuicFlowControllerTest : public ::testing::Test {
     24  public:
     25   QuicFlowControllerTest()
     26       : stream_id_(1234),
     27         send_window_(kInitialSessionFlowControlWindowForTest),
     28         receive_window_(kInitialSessionFlowControlWindowForTest),
     29         max_receive_window_(kInitialSessionFlowControlWindowForTest),
     30         connection_(false),
     31         old_flag_(&FLAGS_enable_quic_stream_flow_control_2, true) {
     32   }
     33 
     34   void Initialize() {
     35     flow_controller_.reset(new QuicFlowController(
     36         &connection_, stream_id_, false, send_window_,
     37         receive_window_, max_receive_window_));
     38   }
     39 
     40  protected:
     41   QuicStreamId stream_id_;
     42   uint64 send_window_;
     43   uint64 receive_window_;
     44   uint64 max_receive_window_;
     45   scoped_ptr<QuicFlowController> flow_controller_;
     46   MockConnection connection_;
     47   ValueRestore<bool> old_flag_;
     48 };
     49 
     50 TEST_F(QuicFlowControllerTest, SendingBytes) {
     51   Initialize();
     52 
     53   EXPECT_TRUE(flow_controller_->IsEnabled());
     54   EXPECT_FALSE(flow_controller_->IsBlocked());
     55   EXPECT_FALSE(flow_controller_->FlowControlViolation());
     56   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
     57 
     58   // Send some bytes, but not enough to block.
     59   flow_controller_->AddBytesSent(send_window_ / 2);
     60   EXPECT_FALSE(flow_controller_->IsBlocked());
     61   EXPECT_EQ(send_window_ / 2, flow_controller_->SendWindowSize());
     62 
     63   // Send enough bytes to block.
     64   flow_controller_->AddBytesSent(send_window_ / 2);
     65   EXPECT_TRUE(flow_controller_->IsBlocked());
     66   EXPECT_EQ(0u, flow_controller_->SendWindowSize());
     67 
     68   // BLOCKED frame should get sent.
     69   EXPECT_CALL(connection_, SendBlocked(stream_id_)).Times(1);
     70   flow_controller_->MaybeSendBlocked();
     71 
     72   // Update the send window, and verify this has unblocked.
     73   EXPECT_TRUE(flow_controller_->UpdateSendWindowOffset(2 * send_window_));
     74   EXPECT_FALSE(flow_controller_->IsBlocked());
     75   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
     76 
     77   // Updating with a smaller offset doesn't change anything.
     78   EXPECT_FALSE(flow_controller_->UpdateSendWindowOffset(send_window_ / 10));
     79   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
     80 
     81   // Try to send more bytes, violating flow control.
     82   EXPECT_CALL(connection_,
     83               SendConnectionClose(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA));
     84   EXPECT_DFATAL(
     85       flow_controller_->AddBytesSent(send_window_ * 10),
     86       StringPrintf("Trying to send an extra %d bytes",
     87                    static_cast<int>(send_window_ * 10)));
     88   EXPECT_TRUE(flow_controller_->IsBlocked());
     89   EXPECT_EQ(0u, flow_controller_->SendWindowSize());
     90 }
     91 
     92 TEST_F(QuicFlowControllerTest, ReceivingBytes) {
     93   Initialize();
     94 
     95   EXPECT_TRUE(flow_controller_->IsEnabled());
     96   EXPECT_FALSE(flow_controller_->IsBlocked());
     97   EXPECT_FALSE(flow_controller_->FlowControlViolation());
     98   EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
     99             QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
    100 
    101   // Receive some bytes, updating highest received offset, but not enough to
    102   // fill flow control receive window.
    103   EXPECT_TRUE(
    104       flow_controller_->UpdateHighestReceivedOffset(1 + receive_window_ / 2));
    105   EXPECT_FALSE(flow_controller_->FlowControlViolation());
    106   EXPECT_EQ((receive_window_ / 2) - 1,
    107             QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
    108 
    109   // Consume enough bytes to send a WINDOW_UPDATE frame.
    110   EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, _)).Times(1);
    111 
    112   flow_controller_->AddBytesConsumed(1 + receive_window_ / 2);
    113 
    114   // Result is that once again we have a fully open receive window.
    115   EXPECT_FALSE(flow_controller_->FlowControlViolation());
    116   EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
    117             QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
    118 }
    119 
    120 TEST_F(QuicFlowControllerTest,
    121        DisabledWhenQuicVersionDoesNotSupportFlowControl) {
    122   // Only support version 16: no flow control.
    123   QuicConnectionPeer::SetSupportedVersions(&connection_,
    124                                            SupportedVersions(QUIC_VERSION_16));
    125 
    126   Initialize();
    127 
    128   MockConnection connection(false);
    129 
    130   // Should not be enabled, and should not report as blocked.
    131   EXPECT_FALSE(flow_controller_->IsEnabled());
    132   EXPECT_FALSE(flow_controller_->IsBlocked());
    133   EXPECT_FALSE(flow_controller_->FlowControlViolation());
    134 
    135   // Any attempts to add/remove bytes should have no effect.
    136   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
    137   EXPECT_EQ(send_window_,
    138             QuicFlowControllerPeer::SendWindowOffset(flow_controller_.get()));
    139   EXPECT_EQ(receive_window_, QuicFlowControllerPeer::ReceiveWindowOffset(
    140                                  flow_controller_.get()));
    141   flow_controller_->AddBytesSent(123);
    142   flow_controller_->AddBytesConsumed(456);
    143   flow_controller_->UpdateHighestReceivedOffset(789);
    144   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
    145   EXPECT_EQ(send_window_,
    146             QuicFlowControllerPeer::SendWindowOffset(flow_controller_.get()));
    147   EXPECT_EQ(receive_window_, QuicFlowControllerPeer::ReceiveWindowOffset(
    148                                  flow_controller_.get()));
    149 
    150   // Any attempt to change offset should have no effect.
    151   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
    152   EXPECT_EQ(send_window_,
    153             QuicFlowControllerPeer::SendWindowOffset(flow_controller_.get()));
    154   flow_controller_->UpdateSendWindowOffset(send_window_ + 12345);
    155   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
    156   EXPECT_EQ(send_window_,
    157             QuicFlowControllerPeer::SendWindowOffset(flow_controller_.get()));
    158 
    159   // The connection should never send WINDOW_UPDATE or BLOCKED frames, even if
    160   // the internal state implies that it should.
    161 
    162   // If the flow controller was enabled, then a send window size of 0 would
    163   // trigger a BLOCKED frame to be sent.
    164   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
    165   EXPECT_CALL(connection_, SendBlocked(_)).Times(0);
    166   flow_controller_->MaybeSendBlocked();
    167 
    168   // If the flow controller was enabled, then a WINDOW_UPDATE would be sent if
    169   // (receive window) < (max receive window / 2)
    170   QuicFlowControllerPeer::SetReceiveWindowOffset(flow_controller_.get(),
    171                                                  max_receive_window_ / 10);
    172   EXPECT_TRUE(QuicFlowControllerPeer::ReceiveWindowSize(
    173                   flow_controller_.get()) < (max_receive_window_ / 2));
    174   EXPECT_CALL(connection_, SendWindowUpdate(_, _)).Times(0);
    175   flow_controller_->AddBytesConsumed(0);
    176 
    177   // Should not be enabled, and should not report as blocked.
    178   EXPECT_FALSE(flow_controller_->IsEnabled());
    179   EXPECT_FALSE(flow_controller_->IsBlocked());
    180   EXPECT_FALSE(flow_controller_->FlowControlViolation());
    181 }
    182 
    183 TEST_F(QuicFlowControllerTest, OnlySendBlockedFrameOncePerOffset) {
    184   Initialize();
    185 
    186   // Test that we don't send duplicate BLOCKED frames. We should only send one
    187   // BLOCKED frame at a given send window offset.
    188   EXPECT_TRUE(flow_controller_->IsEnabled());
    189   EXPECT_FALSE(flow_controller_->IsBlocked());
    190   EXPECT_FALSE(flow_controller_->FlowControlViolation());
    191   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
    192 
    193   // Send enough bytes to block.
    194   flow_controller_->AddBytesSent(send_window_);
    195   EXPECT_TRUE(flow_controller_->IsBlocked());
    196   EXPECT_EQ(0u, flow_controller_->SendWindowSize());
    197 
    198   // Expect that 2 BLOCKED frames should get sent in total.
    199   EXPECT_CALL(connection_, SendBlocked(stream_id_)).Times(2);
    200 
    201   // BLOCKED frame should get sent.
    202   flow_controller_->MaybeSendBlocked();
    203 
    204   // BLOCKED frame should not get sent again until our send offset changes.
    205   flow_controller_->MaybeSendBlocked();
    206   flow_controller_->MaybeSendBlocked();
    207   flow_controller_->MaybeSendBlocked();
    208   flow_controller_->MaybeSendBlocked();
    209   flow_controller_->MaybeSendBlocked();
    210 
    211   // Update the send window, then send enough bytes to block again.
    212   EXPECT_TRUE(flow_controller_->UpdateSendWindowOffset(2 * send_window_));
    213   EXPECT_FALSE(flow_controller_->IsBlocked());
    214   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
    215   flow_controller_->AddBytesSent(send_window_);
    216   EXPECT_TRUE(flow_controller_->IsBlocked());
    217   EXPECT_EQ(0u, flow_controller_->SendWindowSize());
    218 
    219   // BLOCKED frame should get sent as send offset has changed.
    220   flow_controller_->MaybeSendBlocked();
    221 }
    222 
    223 }  // namespace test
    224 }  // namespace net
    225