// 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_session.h" #include "net/quic/quic_connection.h" #include #include "base/hash_tables.h" #include "net/quic/test_tools/quic_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using base::hash_map; using std::set; using testing::_; namespace net { namespace test { namespace { class TestCryptoStream : public QuicCryptoStream { public: explicit TestCryptoStream(QuicSession* session) : QuicCryptoStream(session) { } void OnHandshakeMessage(const CryptoHandshakeMessage& message) { set_handshake_complete(true); } }; class TestStream : public ReliableQuicStream { public: TestStream(QuicStreamId id, QuicSession* session) : ReliableQuicStream(id, session) { } virtual uint32 ProcessData(const char* data, uint32 data_len) { return data_len; } }; class TestSession : public QuicSession { public: TestSession(QuicConnection* connection, bool is_server) : QuicSession(connection, is_server), crypto_stream_(this) { } virtual QuicCryptoStream* GetCryptoStream() { return &crypto_stream_; } virtual TestStream* CreateOutgoingReliableStream() { TestStream* stream = new TestStream(GetNextStreamId(), this); ActivateStream(stream); return stream; } virtual TestStream* CreateIncomingReliableStream(QuicStreamId id) { return new TestStream(id, this); } bool IsClosedStream(QuicStreamId id) { return QuicSession::IsClosedStream(id); } ReliableQuicStream* GetIncomingReliableStream(QuicStreamId stream_id) { return QuicSession::GetIncomingReliableStream(stream_id); } TestCryptoStream crypto_stream_; }; class QuicSessionTest : public ::testing::Test { protected: QuicSessionTest() : guid_(1), connection_(new MockConnection(guid_, IPEndPoint())), session_(connection_, true) { } void CheckClosedStreams() { for (int i = kCryptoStreamId; i < 100; i++) { if (closed_streams_.count(i) == 0) { EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i; } else { EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i; } } } void CloseStream(QuicStreamId id) { session_.CloseStream(id); closed_streams_.insert(id); } QuicGuid guid_; MockConnection* connection_; TestSession session_; QuicConnectionVisitorInterface* visitor_; hash_map* streams_; set closed_streams_; }; TEST_F(QuicSessionTest, IsHandshakeComplete) { EXPECT_FALSE(session_.IsHandshakeComplete()); CryptoHandshakeMessage message; session_.crypto_stream_.OnHandshakeMessage(message); EXPECT_TRUE(session_.IsHandshakeComplete()); } TEST_F(QuicSessionTest, IsClosedStreamDefault) { // Ensure that no streams are initially closed. for (int i = kCryptoStreamId; i < 100; i++) { EXPECT_FALSE(session_.IsClosedStream(i)); } } TEST_F(QuicSessionTest, IsClosedStreamLocallyCreated) { scoped_ptr stream2(session_.CreateOutgoingReliableStream()); scoped_ptr stream4(session_.CreateOutgoingReliableStream()); CheckClosedStreams(); CloseStream(4); CheckClosedStreams(); CloseStream(2); CheckClosedStreams(); } TEST_F(QuicSessionTest, IsClosedStreamPeerCreated) { scoped_ptr stream3(session_.GetIncomingReliableStream(3)); scoped_ptr stream5(session_.GetIncomingReliableStream(5)); CheckClosedStreams(); CloseStream(3); CheckClosedStreams(); CloseStream(5); // Create stream id 9, and implicitly 7 scoped_ptr stream9(session_.GetIncomingReliableStream(9)); CheckClosedStreams(); // Close 9, but make sure 7 is still not closed CloseStream(9); CheckClosedStreams(); } TEST_F(QuicSessionTest, StreamIdTooLarge) { scoped_ptr stream3(session_.GetIncomingReliableStream(3)); EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_STREAM_ID)); scoped_ptr stream5( session_.GetIncomingReliableStream(105)); } } // namespace } // namespace test } // namespace net