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.
5 #include "net/tools/quic/quic_client_session.h"
9 #include "net/base/ip_endpoint.h"
10 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
11 #include "net/quic/quic_flags.h"
12 #include "net/quic/test_tools/crypto_test_utils.h"
13 #include "net/quic/test_tools/quic_session_peer.h"
14 #include "net/quic/test_tools/quic_test_utils.h"
15 #include "net/tools/quic/quic_spdy_client_stream.h"
16 #include "net/tools/quic/test_tools/quic_test_utils.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using net::test::CryptoTestUtils
;
20 using net::test::DefaultQuicConfig
;
21 using net::test::PacketSavingConnection
;
22 using net::test::QuicSessionPeer
;
23 using net::test::SupportedVersions
;
24 using net::test::TestPeerIPAddress
;
25 using net::test::ValueRestore
;
26 using net::test::kTestPort
;
27 using net::tools::test::MockConnection
;
28 using testing::Invoke
;
36 const char kServerHostname
[] = "www.example.org";
37 const uint16 kPort
= 80;
39 class ToolsQuicClientSessionTest
40 : public ::testing::TestWithParam
<QuicVersion
> {
42 ToolsQuicClientSessionTest()
44 new PacketSavingConnection(false, SupportedVersions(GetParam()))) {
45 session_
.reset(new QuicClientSession(DefaultQuicConfig(), connection_
));
46 session_
->InitializeSession(
47 QuicServerId(kServerHostname
, kPort
, false, PRIVACY_MODE_DISABLED
),
49 // Advance the time, because timers do not like uninitialized times.
50 connection_
->AdvanceTime(QuicTime::Delta::FromSeconds(1));
53 void CompleteCryptoHandshake() {
54 session_
->CryptoConnect();
55 CryptoTestUtils::HandshakeWithFakeServer(
56 connection_
, session_
->GetCryptoStream());
59 PacketSavingConnection
* connection_
;
60 scoped_ptr
<QuicClientSession
> session_
;
61 QuicCryptoClientConfig crypto_config_
;
64 INSTANTIATE_TEST_CASE_P(Tests
, ToolsQuicClientSessionTest
,
65 ::testing::ValuesIn(QuicSupportedVersions()));
67 TEST_P(ToolsQuicClientSessionTest
, CryptoConnect
) {
68 CompleteCryptoHandshake();
71 TEST_P(ToolsQuicClientSessionTest
, MaxNumStreams
) {
72 session_
->config()->SetMaxStreamsPerConnection(1, 1);
73 // FLAGS_max_streams_per_connection = 1;
74 // Initialize crypto before the client session will create a stream.
75 CompleteCryptoHandshake();
77 QuicSpdyClientStream
* stream
= session_
->CreateOutgoingDataStream();
79 EXPECT_FALSE(session_
->CreateOutgoingDataStream());
81 // Close a stream and ensure I can now open a new one.
82 session_
->CloseStream(stream
->id());
83 stream
= session_
->CreateOutgoingDataStream();
87 TEST_P(ToolsQuicClientSessionTest
, GoAwayReceived
) {
88 CompleteCryptoHandshake();
90 // After receiving a GoAway, I should no longer be able to create outgoing
92 session_
->OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY
, 1u, "Going away."));
93 EXPECT_EQ(nullptr, session_
->CreateOutgoingDataStream());
96 TEST_P(ToolsQuicClientSessionTest
, SetFecProtectionFromConfig
) {
97 ValueRestore
<bool> old_flag(&FLAGS_enable_quic_fec
, true);
99 // Set FEC config in client's connection options.
101 copt
.push_back(kFHDR
);
102 session_
->config()->SetConnectionOptionsToSend(copt
);
104 // Doing the handshake should set up FEC config correctly.
105 CompleteCryptoHandshake();
107 // Verify that headers stream is always protected and data streams are
108 // optionally protected.
109 EXPECT_EQ(FEC_PROTECT_ALWAYS
,
110 QuicSessionPeer::GetHeadersStream(session_
.get())->fec_policy());
111 QuicSpdyClientStream
* stream
= session_
->CreateOutgoingDataStream();
113 EXPECT_EQ(FEC_PROTECT_OPTIONAL
, stream
->fec_policy());
116 // Regression test for b/17206611.
117 TEST_P(ToolsQuicClientSessionTest
, InvalidPacketReceived
) {
118 // Create Packet with 0 length.
119 QuicEncryptedPacket
invalid_packet(nullptr, 0, false);
120 IPEndPoint
server_address(TestPeerIPAddress(), kTestPort
);
121 IPEndPoint
client_address(TestPeerIPAddress(), kTestPort
);
123 EXPECT_CALL(*reinterpret_cast<MockConnection
*>(session_
->connection()),
124 ProcessUdpPacket(server_address
, client_address
, _
))
126 Invoke(reinterpret_cast<MockConnection
*>(session_
->connection()),
127 &MockConnection::ReallyProcessUdpPacket
));
129 // Validate that empty packets don't close the connection.
130 EXPECT_CALL(*connection_
, SendConnectionCloseWithDetails(_
, _
)).Times(0);
131 session_
->connection()->ProcessUdpPacket(client_address
, server_address
,
134 // Verifiy that small, invalid packets don't close the connection.
135 char buf
[2] = {0x00, 0x01};
136 QuicEncryptedPacket
valid_packet(buf
, 2, false);
137 // Close connection shouldn't be called.
138 EXPECT_CALL(*connection_
, SendConnectionCloseWithDetails(_
, _
)).Times(0);
139 session_
->connection()->ProcessUdpPacket(client_address
, server_address
,