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/quic/quic_client_session.h"
9 #include "base/stl_util.h"
10 #include "net/base/capturing_net_log.h"
11 #include "net/base/net_log_unittest.h"
12 #include "net/base/test_completion_callback.h"
13 #include "net/quic/crypto/aes_128_gcm_encrypter.h"
14 #include "net/quic/crypto/crypto_protocol.h"
15 #include "net/quic/crypto/quic_decrypter.h"
16 #include "net/quic/crypto/quic_encrypter.h"
17 #include "net/quic/test_tools/crypto_test_utils.h"
18 #include "net/quic/test_tools/quic_test_utils.h"
26 const char kServerHostname
[] = "www.example.com";
28 class QuicClientSessionTest
: public ::testing::Test
{
30 QuicClientSessionTest()
32 connection_(new PacketSavingConnection(guid_
, IPEndPoint(), false)),
33 session_(connection_
, NULL
, NULL
, NULL
, kServerHostname
,
34 &crypto_config_
, &net_log_
) {
35 crypto_config_
.SetDefaults();
38 void CompleteCryptoHandshake() {
39 ASSERT_EQ(ERR_IO_PENDING
,
40 session_
.CryptoConnect(callback_
.callback()));
41 CryptoTestUtils::HandshakeWithFakeServer(
42 connection_
, session_
.GetCryptoStream());
43 ASSERT_EQ(OK
, callback_
.WaitForResult());
47 PacketSavingConnection
* connection_
;
48 CapturingNetLog net_log_
;
49 QuicClientSession session_
;
52 QuicConnectionVisitorInterface
* visitor_
;
53 TestCompletionCallback callback_
;
55 QuicCryptoClientConfig crypto_config_
;
58 TEST_F(QuicClientSessionTest
, CryptoConnect
) {
59 if (!Aes128GcmEncrypter::IsSupported()) {
60 LOG(INFO
) << "AES GCM not supported. Test skipped.";
64 CompleteCryptoHandshake();
67 TEST_F(QuicClientSessionTest
, MaxNumConnections
) {
68 if (!Aes128GcmEncrypter::IsSupported()) {
69 LOG(INFO
) << "AES GCM not supported. Test skipped.";
73 CompleteCryptoHandshake();
75 std::vector
<QuicReliableClientStream
*> streams
;
76 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
77 QuicReliableClientStream
* stream
= session_
.CreateOutgoingReliableStream();
79 streams
.push_back(stream
);
81 EXPECT_FALSE(session_
.CreateOutgoingReliableStream());
83 // Close a stream and ensure I can now open a new one.
84 session_
.CloseStream(streams
[0]->id());
85 EXPECT_TRUE(session_
.CreateOutgoingReliableStream());
88 TEST_F(QuicClientSessionTest
, GoAwayReceived
) {
89 // Initialize crypto before the client session will create a stream.
90 ASSERT_TRUE(session_
.CryptoConnect(callback_
.callback()));
91 // Simulate the server crypto handshake.
92 CryptoHandshakeMessage server_message
;
93 server_message
.set_tag(kSHLO
);
94 session_
.GetCryptoStream()->OnHandshakeMessage(server_message
);
96 // After receiving a GoAway, I should no longer be able to create outgoing
98 session_
.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY
, 1u, "Going away."));
99 EXPECT_EQ(NULL
, session_
.CreateOutgoingReliableStream());
102 TEST_F(QuicClientSessionTest
, Logging
) {
103 if (!Aes128GcmEncrypter::IsSupported()) {
104 LOG(INFO
) << "AES GCM not supported. Test skipped.";
108 CompleteCryptoHandshake();
110 // TODO(rch): Add some helper methods to simplify packet creation in tests.
111 // Receive a packet, and verify that it was logged.
112 QuicFramer
framer(kQuicVersion1
,
113 QuicDecrypter::Create(kNULL
),
114 QuicEncrypter::Create(kNULL
),
117 QuicRstStreamFrame frame
;
119 frame
.error_code
= QUIC_STREAM_CONNECTION_ERROR
;
120 frame
.error_details
= "doh!";
123 frames
.push_back(QuicFrame(&frame
));
124 QuicPacketHeader header
;
125 header
.public_header
.guid
= 1;
126 header
.public_header
.reset_flag
= false;
127 header
.public_header
.version_flag
= false;
128 header
.packet_sequence_number
= 1;
129 header
.entropy_flag
= false;
130 header
.fec_flag
= false;
131 header
.fec_entropy_flag
= false;
132 header
.fec_group
= 0;
133 scoped_ptr
<QuicPacket
> p(
134 framer
.ConstructFrameDataPacket(header
, frames
).packet
);
135 scoped_ptr
<QuicEncryptedPacket
> packet(framer
.EncryptPacket(1, *p
));
137 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip
));
138 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
139 IPEndPoint self_addr
= IPEndPoint(ip
, 8435);
141 connection_
->ProcessUdpPacketInternal(self_addr
, peer_addr
, *packet
);
143 // Check that the NetLog was filled reasonably.
144 net::CapturingNetLog::CapturedEntryList entries
;
145 net_log_
.GetEntries(&entries
);
146 EXPECT_LT(0u, entries
.size());
148 // Check that we logged a QUIC_SESSION_PACKET_RECEIVED.
149 int pos
= net::ExpectLogContainsSomewhere(
151 net::NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED
,
152 net::NetLog::PHASE_NONE
);
155 // ... and also a QUIC_SESSION_RST_STREAM_FRAME_RECEIVED.
156 pos
= net::ExpectLogContainsSomewhere(
158 net::NetLog::TYPE_QUIC_SESSION_RST_STREAM_FRAME_RECEIVED
,
159 net::NetLog::PHASE_NONE
);
163 ASSERT_TRUE(entries
[pos
].GetIntegerValue("stream_id", &stream_id
));
164 EXPECT_EQ(frame
.stream_id
, static_cast<QuicStreamId
>(stream_id
));
166 ASSERT_TRUE(entries
[pos
].GetIntegerValue("error_code", &error_code
));
167 EXPECT_EQ(frame
.error_code
, static_cast<QuicRstStreamErrorCode
>(error_code
));
169 ASSERT_TRUE(entries
[pos
].GetStringValue("details", &details
));
170 EXPECT_EQ(frame
.error_details
, details
);