Home | History | Annotate | Download | only in quic
      1 // Copyright 2013 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/tools/quic/quic_server_session.h"
      6 
      7 #include "net/quic/crypto/quic_crypto_server_config.h"
      8 #include "net/quic/crypto/quic_random.h"
      9 #include "net/quic/quic_connection.h"
     10 #include "net/quic/quic_utils.h"
     11 #include "net/quic/test_tools/quic_connection_peer.h"
     12 #include "net/quic/test_tools/quic_data_stream_peer.h"
     13 #include "net/quic/test_tools/quic_test_utils.h"
     14 #include "net/tools/quic/quic_spdy_server_stream.h"
     15 #include "net/tools/quic/test_tools/quic_test_utils.h"
     16 #include "testing/gmock/include/gmock/gmock.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 using __gnu_cxx::vector;
     20 using net::test::MockConnection;
     21 using net::test::QuicConnectionPeer;
     22 using net::test::QuicDataStreamPeer;
     23 using net::test::SupportedVersions;
     24 using net::test::kClientDataStreamId1;
     25 using net::test::kClientDataStreamId2;
     26 using net::test::kClientDataStreamId3;
     27 using net::test::kClientDataStreamId4;
     28 using testing::StrictMock;
     29 using testing::_;
     30 
     31 namespace net {
     32 namespace tools {
     33 namespace test {
     34 
     35 class QuicServerSessionPeer {
     36  public:
     37   static QuicDataStream* GetIncomingDataStream(
     38       QuicServerSession* s, QuicStreamId id) {
     39     return s->GetIncomingDataStream(id);
     40   }
     41   static QuicDataStream* GetDataStream(QuicServerSession* s, QuicStreamId id) {
     42     return s->GetDataStream(id);
     43   }
     44 };
     45 
     46 namespace {
     47 
     48 class QuicServerSessionTest : public ::testing::TestWithParam<QuicVersion> {
     49  protected:
     50   QuicServerSessionTest()
     51       : crypto_config_(QuicCryptoServerConfig::TESTING,
     52                        QuicRandom::GetInstance()) {
     53     config_.SetDefaults();
     54     config_.set_max_streams_per_connection(3, 3);
     55     config_.SetInitialFlowControlWindowToSend(
     56         kInitialSessionFlowControlWindowForTest);
     57     config_.SetInitialStreamFlowControlWindowToSend(
     58         kInitialStreamFlowControlWindowForTest);
     59     config_.SetInitialSessionFlowControlWindowToSend(
     60         kInitialSessionFlowControlWindowForTest);
     61 
     62     connection_ =
     63         new StrictMock<MockConnection>(true, SupportedVersions(GetParam()));
     64     session_.reset(new QuicServerSession(config_, connection_, &owner_));
     65     session_->InitializeSession(crypto_config_);
     66     visitor_ = QuicConnectionPeer::GetVisitor(connection_);
     67   }
     68 
     69   QuicVersion version() const { return connection_->version(); }
     70 
     71   StrictMock<MockQuicServerSessionVisitor> owner_;
     72   StrictMock<MockConnection>* connection_;
     73   QuicConfig config_;
     74   QuicCryptoServerConfig crypto_config_;
     75   scoped_ptr<QuicServerSession> session_;
     76   QuicConnectionVisitorInterface* visitor_;
     77 };
     78 
     79 INSTANTIATE_TEST_CASE_P(Tests, QuicServerSessionTest,
     80                         ::testing::ValuesIn(QuicSupportedVersions()));
     81 
     82 TEST_P(QuicServerSessionTest, CloseStreamDueToReset) {
     83   // Open a stream, then reset it.
     84   // Send two bytes of payload to open it.
     85   QuicStreamFrame data1(kClientDataStreamId1, false, 0, MakeIOVector("HT"));
     86   vector<QuicStreamFrame> frames;
     87   frames.push_back(data1);
     88   session_->OnStreamFrames(frames);
     89   EXPECT_EQ(1u, session_->GetNumOpenStreams());
     90 
     91   // Send a reset (and expect the peer to send a RST in response).
     92   QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0);
     93   EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1,
     94                                           QUIC_RST_FLOW_CONTROL_ACCOUNTING, 0));
     95   visitor_->OnRstStream(rst1);
     96   EXPECT_EQ(0u, session_->GetNumOpenStreams());
     97 
     98   // Send the same two bytes of payload in a new packet.
     99   visitor_->OnStreamFrames(frames);
    100 
    101   // The stream should not be re-opened.
    102   EXPECT_EQ(0u, session_->GetNumOpenStreams());
    103   EXPECT_TRUE(connection_->connected());
    104 }
    105 
    106 TEST_P(QuicServerSessionTest, NeverOpenStreamDueToReset) {
    107   // Send a reset (and expect the peer to send a RST in response).
    108   QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0);
    109   EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1,
    110                                           QUIC_RST_FLOW_CONTROL_ACCOUNTING, 0));
    111   visitor_->OnRstStream(rst1);
    112   EXPECT_EQ(0u, session_->GetNumOpenStreams());
    113 
    114   // Send two bytes of payload.
    115   QuicStreamFrame data1(kClientDataStreamId1, false, 0, MakeIOVector("HT"));
    116   vector<QuicStreamFrame> frames;
    117   frames.push_back(data1);
    118   visitor_->OnStreamFrames(frames);
    119 
    120   // The stream should never be opened, now that the reset is received.
    121   EXPECT_EQ(0u, session_->GetNumOpenStreams());
    122   EXPECT_TRUE(connection_->connected());
    123 }
    124 
    125 TEST_P(QuicServerSessionTest, AcceptClosedStream) {
    126   vector<QuicStreamFrame> frames;
    127   // Send (empty) compressed headers followed by two bytes of data.
    128   frames.push_back(QuicStreamFrame(kClientDataStreamId1, false, 0,
    129                                    MakeIOVector("\1\0\0\0\0\0\0\0HT")));
    130   frames.push_back(QuicStreamFrame(kClientDataStreamId2, false, 0,
    131                                    MakeIOVector("\2\0\0\0\0\0\0\0HT")));
    132   visitor_->OnStreamFrames(frames);
    133   EXPECT_EQ(2u, session_->GetNumOpenStreams());
    134 
    135   // Send a reset (and expect the peer to send a RST in response).
    136   QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0);
    137   EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1,
    138                                           QUIC_RST_FLOW_CONTROL_ACCOUNTING, 0));
    139   visitor_->OnRstStream(rst);
    140 
    141   // If we were tracking, we'd probably want to reject this because it's data
    142   // past the reset point of stream 3.  As it's a closed stream we just drop the
    143   // data on the floor, but accept the packet because it has data for stream 5.
    144   frames.clear();
    145   frames.push_back(
    146       QuicStreamFrame(kClientDataStreamId1, false, 2, MakeIOVector("TP")));
    147   frames.push_back(
    148       QuicStreamFrame(kClientDataStreamId2, false, 2, MakeIOVector("TP")));
    149   visitor_->OnStreamFrames(frames);
    150   // The stream should never be opened, now that the reset is received.
    151   EXPECT_EQ(1u, session_->GetNumOpenStreams());
    152   EXPECT_TRUE(connection_->connected());
    153 }
    154 
    155 TEST_P(QuicServerSessionTest, MaxNumConnections) {
    156   EXPECT_EQ(0u, session_->GetNumOpenStreams());
    157   EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
    158       session_.get(), kClientDataStreamId1));
    159   EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
    160       session_.get(), kClientDataStreamId2));
    161   EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
    162       session_.get(), kClientDataStreamId3));
    163   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS));
    164   EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDataStream(
    165       session_.get(), kClientDataStreamId4));
    166 }
    167 
    168 TEST_P(QuicServerSessionTest, MaxNumConnectionsImplicit) {
    169   EXPECT_EQ(0u, session_->GetNumOpenStreams());
    170   EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
    171       session_.get(), kClientDataStreamId1));
    172   // Implicitly opens two more streams.
    173   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS));
    174   EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDataStream(
    175       session_.get(), kClientDataStreamId4));
    176 }
    177 
    178 TEST_P(QuicServerSessionTest, GetEvenIncomingError) {
    179   // Incoming streams on the server session must be odd.
    180   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_STREAM_ID));
    181   EXPECT_EQ(NULL,
    182             QuicServerSessionPeer::GetIncomingDataStream(session_.get(), 4));
    183 }
    184 
    185 }  // namespace
    186 }  // namespace test
    187 }  // namespace tools
    188 }  // namespace net
    189