Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / tools / quic / quic_server_session_test.cc
blob3696d18e40d67072af9179167699c679e4bc58e6
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.
5 #include "net/tools/quic/quic_server_session.h"
7 #include "net/quic/crypto/quic_crypto_server_config.h"
8 #include "net/quic/crypto/quic_random.h"
9 #include "net/quic/proto/cached_network_parameters.pb.h"
10 #include "net/quic/quic_connection.h"
11 #include "net/quic/quic_crypto_server_stream.h"
12 #include "net/quic/quic_flags.h"
13 #include "net/quic/quic_utils.h"
14 #include "net/quic/test_tools/quic_config_peer.h"
15 #include "net/quic/test_tools/quic_connection_peer.h"
16 #include "net/quic/test_tools/quic_data_stream_peer.h"
17 #include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
18 #include "net/quic/test_tools/quic_session_peer.h"
19 #include "net/quic/test_tools/quic_spdy_session_peer.h"
20 #include "net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h"
21 #include "net/quic/test_tools/quic_test_utils.h"
22 #include "net/test/gtest_util.h"
23 #include "net/tools/quic/quic_spdy_server_stream.h"
24 #include "net/tools/quic/test_tools/mock_quic_server_session_visitor.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 using __gnu_cxx::vector;
29 using net::test::MockConnection;
30 using net::test::QuicConfigPeer;
31 using net::test::QuicConnectionPeer;
32 using net::test::QuicDataStreamPeer;
33 using net::test::QuicSentPacketManagerPeer;
34 using net::test::QuicSessionPeer;
35 using net::test::QuicSpdySessionPeer;
36 using net::test::QuicSustainedBandwidthRecorderPeer;
37 using net::test::SupportedVersions;
38 using net::test::ValueRestore;
39 using net::test::kClientDataStreamId1;
40 using net::test::kClientDataStreamId2;
41 using net::test::kClientDataStreamId3;
42 using net::test::kInitialSessionFlowControlWindowForTest;
43 using net::test::kInitialStreamFlowControlWindowForTest;
44 using std::string;
45 using testing::StrictMock;
46 using testing::_;
48 namespace net {
49 namespace tools {
50 namespace test {
52 class QuicServerSessionPeer {
53 public:
54 static ReliableQuicStream* GetIncomingDynamicStream(QuicServerSession* s,
55 QuicStreamId id) {
56 return s->GetIncomingDynamicStream(id);
58 static void SetCryptoStream(QuicServerSession* s,
59 QuicCryptoServerStream* crypto_stream) {
60 s->crypto_stream_.reset(crypto_stream);
61 s->static_streams()[kCryptoStreamId] = crypto_stream;
63 static bool IsBandwidthResumptionEnabled(QuicServerSession* s) {
64 return s->bandwidth_resumption_enabled_;
68 namespace {
70 const size_t kMaxStreamsForTest = 10;
72 class QuicServerSessionTest : public ::testing::TestWithParam<QuicVersion> {
73 protected:
74 QuicServerSessionTest()
75 : crypto_config_(QuicCryptoServerConfig::TESTING,
76 QuicRandom::GetInstance()) {
77 config_.SetMaxStreamsPerConnection(kMaxStreamsForTest,
78 kMaxStreamsForTest);
79 config_.SetInitialStreamFlowControlWindowToSend(
80 kInitialStreamFlowControlWindowForTest);
81 config_.SetInitialSessionFlowControlWindowToSend(
82 kInitialSessionFlowControlWindowForTest);
84 connection_ = new StrictMock<MockConnection>(Perspective::IS_SERVER,
85 SupportedVersions(GetParam()));
86 session_.reset(
87 new QuicServerSession(config_, connection_, &owner_, &crypto_config_));
88 MockClock clock;
89 handshake_message_.reset(crypto_config_.AddDefaultConfig(
90 QuicRandom::GetInstance(), &clock,
91 QuicCryptoServerConfig::ConfigOptions()));
92 session_->Initialize();
93 visitor_ = QuicConnectionPeer::GetVisitor(connection_);
96 StrictMock<MockQuicServerSessionVisitor> owner_;
97 StrictMock<MockConnection>* connection_;
98 QuicConfig config_;
99 QuicCryptoServerConfig crypto_config_;
100 scoped_ptr<QuicServerSession> session_;
101 scoped_ptr<CryptoHandshakeMessage> handshake_message_;
102 QuicConnectionVisitorInterface* visitor_;
105 // Compares CachedNetworkParameters.
106 MATCHER_P(EqualsProto, network_params, "") {
107 CachedNetworkParameters reference(network_params);
108 return (arg->bandwidth_estimate_bytes_per_second() ==
109 reference.bandwidth_estimate_bytes_per_second() &&
110 arg->bandwidth_estimate_bytes_per_second() ==
111 reference.bandwidth_estimate_bytes_per_second() &&
112 arg->max_bandwidth_estimate_bytes_per_second() ==
113 reference.max_bandwidth_estimate_bytes_per_second() &&
114 arg->max_bandwidth_timestamp_seconds() ==
115 reference.max_bandwidth_timestamp_seconds() &&
116 arg->min_rtt_ms() == reference.min_rtt_ms() &&
117 arg->previous_connection_state() ==
118 reference.previous_connection_state());
121 INSTANTIATE_TEST_CASE_P(Tests, QuicServerSessionTest,
122 ::testing::ValuesIn(QuicSupportedVersions()));
124 TEST_P(QuicServerSessionTest, CloseStreamDueToReset) {
125 // Open a stream, then reset it.
126 // Send two bytes of payload to open it.
127 QuicStreamFrame data1(kClientDataStreamId1, false, 0, StringPiece("HT"));
128 session_->OnStreamFrame(data1);
129 EXPECT_EQ(1u, session_->GetNumOpenStreams());
131 // Send a reset (and expect the peer to send a RST in response).
132 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0);
133 EXPECT_CALL(*connection_,
134 SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0));
135 visitor_->OnRstStream(rst1);
136 EXPECT_EQ(0u, session_->GetNumOpenStreams());
138 // Send the same two bytes of payload in a new packet.
139 visitor_->OnStreamFrame(data1);
141 // The stream should not be re-opened.
142 EXPECT_EQ(0u, session_->GetNumOpenStreams());
143 EXPECT_TRUE(connection_->connected());
146 TEST_P(QuicServerSessionTest, NeverOpenStreamDueToReset) {
147 // Send a reset (and expect the peer to send a RST in response).
148 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0);
149 EXPECT_CALL(*connection_,
150 SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0));
151 visitor_->OnRstStream(rst1);
152 EXPECT_EQ(0u, session_->GetNumOpenStreams());
154 // Send two bytes of payload.
155 QuicStreamFrame data1(kClientDataStreamId1, false, 0, StringPiece("HT"));
156 visitor_->OnStreamFrame(data1);
158 // The stream should never be opened, now that the reset is received.
159 EXPECT_EQ(0u, session_->GetNumOpenStreams());
160 EXPECT_TRUE(connection_->connected());
163 TEST_P(QuicServerSessionTest, AcceptClosedStream) {
164 // Send (empty) compressed headers followed by two bytes of data.
165 QuicStreamFrame frame1(kClientDataStreamId1, false, 0,
166 StringPiece("\1\0\0\0\0\0\0\0HT"));
167 QuicStreamFrame frame2(kClientDataStreamId2, false, 0,
168 StringPiece("\2\0\0\0\0\0\0\0HT"));
169 visitor_->OnStreamFrame(frame1);
170 visitor_->OnStreamFrame(frame2);
171 EXPECT_EQ(2u, session_->GetNumOpenStreams());
173 // Send a reset (and expect the peer to send a RST in response).
174 QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0);
175 EXPECT_CALL(*connection_,
176 SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0));
177 visitor_->OnRstStream(rst);
179 // If we were tracking, we'd probably want to reject this because it's data
180 // past the reset point of stream 3. As it's a closed stream we just drop the
181 // data on the floor, but accept the packet because it has data for stream 5.
182 QuicStreamFrame frame3(kClientDataStreamId1, false, 2, StringPiece("TP"));
183 QuicStreamFrame frame4(kClientDataStreamId2, false, 2, StringPiece("TP"));
184 visitor_->OnStreamFrame(frame3);
185 visitor_->OnStreamFrame(frame4);
186 // The stream should never be opened, now that the reset is received.
187 EXPECT_EQ(1u, session_->GetNumOpenStreams());
188 EXPECT_TRUE(connection_->connected());
191 TEST_P(QuicServerSessionTest, MaxOpenStreams) {
192 // Test that the server closes the connection if a client attempts to open too
193 // many data streams. The server accepts slightly more than the negotiated
194 // stream limit to deal with rare cases where a client FIN/RST is lost.
196 // The slightly increased stream limit is set during config negotiation. It
197 // should be either an increase of 10 over negotiated limit, or a fixed
198 // percentage scaling, whichever is larger. Test both before continuing.
199 EXPECT_EQ(kMaxStreamsForTest, session_->get_max_open_streams());
200 session_->OnConfigNegotiated();
201 EXPECT_LT(kMaxStreamsMultiplier * kMaxStreamsForTest,
202 kMaxStreamsForTest + kMaxStreamsMinimumIncrement);
203 EXPECT_EQ(kMaxStreamsForTest + kMaxStreamsMinimumIncrement,
204 session_->get_max_open_streams());
205 EXPECT_EQ(0u, session_->GetNumOpenStreams());
206 QuicStreamId stream_id = kClientDataStreamId1;
207 // Open the max configured number of streams, should be no problem.
208 for (size_t i = 0; i < kMaxStreamsForTest; ++i) {
209 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(),
210 stream_id));
211 stream_id += 2;
214 // Open more streams: server should accept slightly more than the limit.
215 for (size_t i = 0; i < kMaxStreamsMinimumIncrement; ++i) {
216 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(),
217 stream_id));
218 stream_id += 2;
221 // Now violate the server's internal stream limit.
222 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS));
223 stream_id += 2;
224 EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(),
225 stream_id));
228 TEST_P(QuicServerSessionTest, MaxOpenStreamsImplicit) {
229 // Test that the server closes the connection if a client attempts to open too
230 // many data streams implicitly. The server accepts slightly more than the
231 // negotiated stream limit to deal with rare cases where a client FIN/RST is
232 // lost.
234 // The slightly increased stream limit is set during config negotiation.
235 EXPECT_EQ(kMaxStreamsForTest, session_->get_max_open_streams());
236 session_->OnConfigNegotiated();
237 EXPECT_LT(kMaxStreamsMultiplier * kMaxStreamsForTest,
238 kMaxStreamsForTest + kMaxStreamsMinimumIncrement);
239 EXPECT_EQ(kMaxStreamsForTest + kMaxStreamsMinimumIncrement,
240 session_->get_max_open_streams());
242 EXPECT_EQ(0u, session_->GetNumOpenStreams());
243 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream(
244 session_.get(), kClientDataStreamId1));
245 // Implicitly open streams up to the server's limit.
246 const int kActualMaxStreams =
247 kMaxStreamsForTest + kMaxStreamsMinimumIncrement;
248 const int kMaxValidStreamId =
249 kClientDataStreamId1 + (kActualMaxStreams - 1) * 2;
250 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream(
251 session_.get(), kMaxValidStreamId));
253 // Opening a further stream will result in connection close.
254 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS));
255 EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDynamicStream(
256 session_.get(), kMaxValidStreamId + 2));
259 TEST_P(QuicServerSessionTest, GetEvenIncomingError) {
260 // Incoming streams on the server session must be odd.
261 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_STREAM_ID));
262 EXPECT_EQ(nullptr,
263 QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(), 4));
266 TEST_P(QuicServerSessionTest, GetStreamDisconnected) {
267 // Don't create new streams if the connection is disconnected.
268 QuicConnectionPeer::CloseConnection(connection_);
269 EXPECT_DFATAL(
270 QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(), 5),
271 "ShouldCreateIncomingDynamicStream called when disconnected");
274 TEST_P(QuicServerSessionTest, SetFecProtectionFromConfig) {
275 ValueRestore<bool> old_flag(&FLAGS_enable_quic_fec, true);
277 // Set received config to have FEC connection option.
278 QuicTagVector copt;
279 copt.push_back(kFHDR);
280 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
281 session_->OnConfigNegotiated();
283 // Verify that headers stream is always protected and data streams are
284 // optionally protected.
285 EXPECT_EQ(FEC_PROTECT_ALWAYS, QuicSpdySessionPeer::GetHeadersStream(
286 session_.get())->fec_policy());
287 ReliableQuicStream* stream = QuicServerSessionPeer::GetIncomingDynamicStream(
288 session_.get(), kClientDataStreamId1);
289 ASSERT_TRUE(stream);
290 EXPECT_EQ(FEC_PROTECT_OPTIONAL, stream->fec_policy());
293 class MockQuicCryptoServerStream : public QuicCryptoServerStream {
294 public:
295 explicit MockQuicCryptoServerStream(
296 const QuicCryptoServerConfig* crypto_config, QuicSession* session)
297 : QuicCryptoServerStream(crypto_config, session) {}
298 ~MockQuicCryptoServerStream() override {}
300 MOCK_METHOD1(SendServerConfigUpdate,
301 void(const CachedNetworkParameters* cached_network_parameters));
303 private:
304 DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream);
307 TEST_P(QuicServerSessionTest, BandwidthEstimates) {
308 // Test that bandwidth estimate updates are sent to the client, only when
309 // bandwidth resumption is enabled, the bandwidth estimate has changed
310 // sufficiently, enough time has passed,
311 // and we don't have any other data to write.
313 // Client has sent kBWRE connection option to trigger bandwidth resumption.
314 QuicTagVector copt;
315 copt.push_back(kBWRE);
316 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
317 session_->OnConfigNegotiated();
318 EXPECT_TRUE(
319 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_.get()));
321 int32 bandwidth_estimate_kbytes_per_second = 123;
322 int32 max_bandwidth_estimate_kbytes_per_second = 134;
323 int32 max_bandwidth_estimate_timestamp = 1122334455;
324 const string serving_region = "not a real region";
325 session_->set_serving_region(serving_region);
327 MockQuicCryptoServerStream* crypto_stream =
328 new MockQuicCryptoServerStream(&crypto_config_, session_.get());
329 QuicServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
331 // Set some initial bandwidth values.
332 QuicSentPacketManager* sent_packet_manager =
333 QuicConnectionPeer::GetSentPacketManager(session_->connection());
334 QuicSustainedBandwidthRecorder& bandwidth_recorder =
335 QuicSentPacketManagerPeer::GetBandwidthRecorder(sent_packet_manager);
336 // Seed an rtt measurement equal to the initial default rtt.
337 RttStats* rtt_stats =
338 QuicSentPacketManagerPeer::GetRttStats(sent_packet_manager);
339 rtt_stats->UpdateRtt(QuicTime::Delta::FromMicroseconds(
340 rtt_stats->initial_rtt_us()), QuicTime::Delta::Zero(), QuicTime::Zero());
341 QuicSustainedBandwidthRecorderPeer::SetBandwidthEstimate(
342 &bandwidth_recorder, bandwidth_estimate_kbytes_per_second);
343 QuicSustainedBandwidthRecorderPeer::SetMaxBandwidthEstimate(
344 &bandwidth_recorder, max_bandwidth_estimate_kbytes_per_second,
345 max_bandwidth_estimate_timestamp);
346 // Queue up some pending data.
347 session_->MarkConnectionLevelWriteBlocked(
348 kCryptoStreamId, QuicWriteBlockedList::kHighestPriority);
349 EXPECT_TRUE(session_->HasDataToWrite());
351 // There will be no update sent yet - not enough time has passed.
352 QuicTime now = QuicTime::Zero();
353 session_->OnCongestionWindowChange(now);
355 // Bandwidth estimate has now changed sufficiently but not enough time has
356 // passed to send a Server Config Update.
357 bandwidth_estimate_kbytes_per_second =
358 bandwidth_estimate_kbytes_per_second * 1.6;
359 session_->OnCongestionWindowChange(now);
361 // Bandwidth estimate has now changed sufficiently and enough time has passed,
362 // but not enough packets have been sent.
363 int64 srtt_ms =
364 sent_packet_manager->GetRttStats()->smoothed_rtt().ToMilliseconds();
365 now = now.Add(QuicTime::Delta::FromMilliseconds(
366 kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms));
367 session_->OnCongestionWindowChange(now);
369 // The connection no longer has pending data to be written.
370 session_->OnCanWrite();
371 EXPECT_FALSE(session_->HasDataToWrite());
372 session_->OnCongestionWindowChange(now);
374 // Bandwidth estimate has now changed sufficiently, enough time has passed,
375 // and enough packets have been sent.
376 QuicConnectionPeer::SetSequenceNumberOfLastSentPacket(
377 session_->connection(), kMinPacketsBetweenServerConfigUpdates);
379 // Verify that the proto has exactly the values we expect.
380 CachedNetworkParameters expected_network_params;
381 expected_network_params.set_bandwidth_estimate_bytes_per_second(
382 bandwidth_recorder.BandwidthEstimate().ToBytesPerSecond());
383 expected_network_params.set_max_bandwidth_estimate_bytes_per_second(
384 bandwidth_recorder.MaxBandwidthEstimate().ToBytesPerSecond());
385 expected_network_params.set_max_bandwidth_timestamp_seconds(
386 bandwidth_recorder.MaxBandwidthTimestamp());
387 expected_network_params.set_min_rtt_ms(session_->connection()
388 ->sent_packet_manager()
389 .GetRttStats()
390 ->min_rtt()
391 .ToMilliseconds());
392 expected_network_params.set_previous_connection_state(
393 CachedNetworkParameters::CONGESTION_AVOIDANCE);
394 expected_network_params.set_timestamp(
395 session_->connection()->clock()->WallNow().ToUNIXSeconds());
396 expected_network_params.set_serving_region(serving_region);
398 EXPECT_CALL(*crypto_stream,
399 SendServerConfigUpdate(EqualsProto(expected_network_params)))
400 .Times(1);
401 EXPECT_CALL(*connection_, OnSendConnectionState(_)).Times(1);
402 session_->OnCongestionWindowChange(now);
405 TEST_P(QuicServerSessionTest, BandwidthResumptionExperiment) {
406 // Test that if a client provides a CachedNetworkParameters with the same
407 // serving region as the current server, and which was made within an hour of
408 // now, that this data is passed down to the send algorithm.
410 // Client has sent kBWRE connection option to trigger bandwidth resumption.
411 QuicTagVector copt;
412 copt.push_back(kBWRE);
413 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
415 const string kTestServingRegion = "a serving region";
416 session_->set_serving_region(kTestServingRegion);
418 // Set the time to be one hour + one second from the 0 baseline.
419 connection_->AdvanceTime(
420 QuicTime::Delta::FromSeconds(kNumSecondsPerHour + 1));
422 QuicCryptoServerStream* crypto_stream =
423 static_cast<QuicCryptoServerStream*>(
424 QuicSessionPeer::GetCryptoStream(session_.get()));
426 // No effect if no CachedNetworkParameters provided.
427 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0);
428 session_->OnConfigNegotiated();
430 // No effect if CachedNetworkParameters provided, but different serving
431 // regions.
432 CachedNetworkParameters cached_network_params;
433 cached_network_params.set_bandwidth_estimate_bytes_per_second(1);
434 cached_network_params.set_serving_region("different serving region");
435 crypto_stream->set_previous_cached_network_params(cached_network_params);
436 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0);
437 session_->OnConfigNegotiated();
439 // Same serving region, but timestamp is too old, should have no effect.
440 cached_network_params.set_serving_region(kTestServingRegion);
441 cached_network_params.set_timestamp(0);
442 crypto_stream->set_previous_cached_network_params(cached_network_params);
443 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0);
444 session_->OnConfigNegotiated();
446 // Same serving region, and timestamp is recent: estimate is stored.
447 cached_network_params.set_timestamp(
448 connection_->clock()->WallNow().ToUNIXSeconds());
449 crypto_stream->set_previous_cached_network_params(cached_network_params);
450 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(1);
451 session_->OnConfigNegotiated();
454 TEST_P(QuicServerSessionTest, BandwidthMaxEnablesResumption) {
455 EXPECT_FALSE(
456 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_.get()));
458 // Client has sent kBWMX connection option to trigger bandwidth resumption.
459 QuicTagVector copt;
460 copt.push_back(kBWMX);
461 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
462 session_->OnConfigNegotiated();
463 EXPECT_TRUE(
464 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_.get()));
467 TEST_P(QuicServerSessionTest, NoBandwidthResumptionByDefault) {
468 EXPECT_FALSE(
469 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_.get()));
470 session_->OnConfigNegotiated();
471 EXPECT_FALSE(
472 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_.get()));
475 } // namespace
476 } // namespace test
477 } // namespace tools
478 } // namespace net