OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/quic_session.h" | 5 #include "net/quic/quic_session.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
| 10 #include "base/basictypes.h" |
10 #include "base/containers/hash_tables.h" | 11 #include "base/containers/hash_tables.h" |
| 12 #include "net/quic/crypto/crypto_protocol.h" |
11 #include "net/quic/quic_crypto_stream.h" | 13 #include "net/quic/quic_crypto_stream.h" |
12 #include "net/quic/quic_protocol.h" | 14 #include "net/quic/quic_protocol.h" |
13 #include "net/quic/reliable_quic_stream.h" | 15 #include "net/quic/reliable_quic_stream.h" |
14 #include "net/quic/test_tools/quic_connection_peer.h" | 16 #include "net/quic/test_tools/quic_connection_peer.h" |
15 #include "net/quic/test_tools/quic_data_stream_peer.h" | 17 #include "net/quic/test_tools/quic_data_stream_peer.h" |
16 #include "net/quic/test_tools/quic_session_peer.h" | 18 #include "net/quic/test_tools/quic_session_peer.h" |
17 #include "net/quic/test_tools/quic_test_utils.h" | 19 #include "net/quic/test_tools/quic_test_utils.h" |
18 #include "net/quic/test_tools/reliable_quic_stream_peer.h" | 20 #include "net/quic/test_tools/reliable_quic_stream_peer.h" |
19 #include "net/spdy/spdy_framer.h" | 21 #include "net/spdy/spdy_framer.h" |
20 #include "testing/gmock/include/gmock/gmock.h" | 22 #include "testing/gmock/include/gmock/gmock.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
22 | 24 |
23 using base::hash_map; | 25 using base::hash_map; |
24 using std::set; | 26 using std::set; |
25 using std::vector; | 27 using std::vector; |
26 using testing::_; | 28 using testing::_; |
27 using testing::InSequence; | 29 using testing::InSequence; |
28 using testing::InvokeWithoutArgs; | 30 using testing::InvokeWithoutArgs; |
| 31 using testing::Return; |
29 using testing::StrictMock; | 32 using testing::StrictMock; |
30 | 33 |
31 namespace net { | 34 namespace net { |
32 namespace test { | 35 namespace test { |
33 namespace { | 36 namespace { |
34 | 37 |
35 const QuicPriority kSomeMiddlePriority = 2; | 38 const QuicPriority kHighestPriority = 0; |
| 39 const QuicPriority kSomeMiddlePriority = 3; |
36 | 40 |
37 class TestCryptoStream : public QuicCryptoStream { | 41 class TestCryptoStream : public QuicCryptoStream { |
38 public: | 42 public: |
39 explicit TestCryptoStream(QuicSession* session) | 43 explicit TestCryptoStream(QuicSession* session) |
40 : QuicCryptoStream(session) { | 44 : QuicCryptoStream(session) { |
41 } | 45 } |
42 | 46 |
43 virtual void OnHandshakeMessage( | 47 virtual void OnHandshakeMessage( |
44 const CryptoHandshakeMessage& message) OVERRIDE { | 48 const CryptoHandshakeMessage& message) OVERRIDE { |
45 encryption_established_ = true; | 49 encryption_established_ = true; |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 const char data[] = | 276 const char data[] = |
273 "\0\0\0\0" // priority | 277 "\0\0\0\0" // priority |
274 "\1\0\0\0" // headers id | 278 "\1\0\0\0" // headers id |
275 "\0\0\0\4" // length | 279 "\0\0\0\4" // length |
276 "abcd"; // invalid compressed data | 280 "abcd"; // invalid compressed data |
277 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE)); | 281 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE)); |
278 stream->ProcessRawData(data, arraysize(data)); | 282 stream->ProcessRawData(data, arraysize(data)); |
279 } | 283 } |
280 } | 284 } |
281 | 285 |
| 286 TEST_P(QuicSessionTest, DebugDFatalIfMarkingClosedStreamWriteBlocked) { |
| 287 TestStream* stream2 = session_.CreateOutgoingDataStream(); |
| 288 // Close the stream. |
| 289 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD); |
| 290 // TODO(rtenneti): enable when chromium supports EXPECT_DEBUG_DFATAL. |
| 291 /* |
| 292 QuicStreamId kClosedStreamId = stream2->id(); |
| 293 EXPECT_DEBUG_DFATAL( |
| 294 session_.MarkWriteBlocked(kClosedStreamId, kSomeMiddlePriority), |
| 295 "Marking unknown stream 2 blocked."); |
| 296 */ |
| 297 } |
| 298 |
| 299 TEST_P(QuicSessionTest, DebugDFatalIfMarkWriteBlockedCalledWithWrongPriority) { |
| 300 const QuicPriority kDifferentPriority = 0; |
| 301 |
| 302 TestStream* stream2 = session_.CreateOutgoingDataStream(); |
| 303 EXPECT_NE(kDifferentPriority, stream2->EffectivePriority()); |
| 304 // TODO(rtenneti): enable when chromium supports EXPECT_DEBUG_DFATAL. |
| 305 /* |
| 306 EXPECT_DEBUG_DFATAL( |
| 307 session_.MarkWriteBlocked(stream2->id(), kDifferentPriority), |
| 308 "Priorities do not match. Got: 0 Expected: 3"); |
| 309 */ |
| 310 } |
| 311 |
282 TEST_P(QuicSessionTest, OnCanWrite) { | 312 TEST_P(QuicSessionTest, OnCanWrite) { |
283 TestStream* stream2 = session_.CreateOutgoingDataStream(); | 313 TestStream* stream2 = session_.CreateOutgoingDataStream(); |
284 TestStream* stream4 = session_.CreateOutgoingDataStream(); | 314 TestStream* stream4 = session_.CreateOutgoingDataStream(); |
285 TestStream* stream6 = session_.CreateOutgoingDataStream(); | 315 TestStream* stream6 = session_.CreateOutgoingDataStream(); |
286 | 316 |
287 session_.MarkWriteBlocked(stream2->id(), kSomeMiddlePriority); | 317 session_.MarkWriteBlocked(stream2->id(), kSomeMiddlePriority); |
288 session_.MarkWriteBlocked(stream6->id(), kSomeMiddlePriority); | 318 session_.MarkWriteBlocked(stream6->id(), kSomeMiddlePriority); |
289 session_.MarkWriteBlocked(stream4->id(), kSomeMiddlePriority); | 319 session_.MarkWriteBlocked(stream4->id(), kSomeMiddlePriority); |
290 | 320 |
291 InSequence s; | 321 InSequence s; |
292 StreamBlocker stream2_blocker(&session_, stream2->id()); | 322 StreamBlocker stream2_blocker(&session_, stream2->id()); |
293 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce( | 323 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce( |
294 // Reregister, to test the loop limit. | 324 // Reregister, to test the loop limit. |
295 InvokeWithoutArgs(&stream2_blocker, &StreamBlocker::MarkWriteBlocked)); | 325 InvokeWithoutArgs(&stream2_blocker, &StreamBlocker::MarkWriteBlocked)); |
296 EXPECT_CALL(*stream6, OnCanWrite()); | 326 EXPECT_CALL(*stream6, OnCanWrite()); |
297 EXPECT_CALL(*stream4, OnCanWrite()); | 327 EXPECT_CALL(*stream4, OnCanWrite()); |
298 | 328 |
299 EXPECT_FALSE(session_.OnCanWrite()); | 329 EXPECT_FALSE(session_.OnCanWrite()); |
300 } | 330 } |
301 | 331 |
| 332 TEST_P(QuicSessionTest, OnCanWriteCongestionControlBlocks) { |
| 333 InSequence s; |
| 334 |
| 335 // Drive congestion control manually. |
| 336 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>; |
| 337 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm); |
| 338 |
| 339 TestStream* stream2 = session_.CreateOutgoingDataStream(); |
| 340 TestStream* stream4 = session_.CreateOutgoingDataStream(); |
| 341 TestStream* stream6 = session_.CreateOutgoingDataStream(); |
| 342 |
| 343 session_.MarkWriteBlocked(stream2->id(), kSomeMiddlePriority); |
| 344 session_.MarkWriteBlocked(stream6->id(), kSomeMiddlePriority); |
| 345 session_.MarkWriteBlocked(stream4->id(), kSomeMiddlePriority); |
| 346 |
| 347 StreamBlocker stream2_blocker(&session_, stream2->id()); |
| 348 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _, _)).WillOnce(Return( |
| 349 QuicTime::Delta::Zero())); |
| 350 EXPECT_CALL(*stream2, OnCanWrite()); |
| 351 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _, _)).WillOnce(Return( |
| 352 QuicTime::Delta::Zero())); |
| 353 EXPECT_CALL(*stream6, OnCanWrite()); |
| 354 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _, _)).WillOnce(Return( |
| 355 QuicTime::Delta::Infinite())); |
| 356 // stream4->OnCanWrite is not called. |
| 357 |
| 358 // TODO(avd) change return value to 'true', since the connection |
| 359 // can't write because it is congestion control blocked. |
| 360 EXPECT_FALSE(session_.OnCanWrite()); |
| 361 |
| 362 // Still congestion-control blocked. |
| 363 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _, _)).WillOnce(Return( |
| 364 QuicTime::Delta::Infinite())); |
| 365 EXPECT_FALSE(session_.OnCanWrite()); |
| 366 |
| 367 // stream4->OnCanWrite is called once the connection stops being |
| 368 // congestion-control blocked. |
| 369 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _, _)).WillOnce(Return( |
| 370 QuicTime::Delta::Zero())); |
| 371 EXPECT_CALL(*stream4, OnCanWrite()); |
| 372 EXPECT_TRUE(session_.OnCanWrite()); |
| 373 } |
| 374 |
302 TEST_P(QuicSessionTest, BufferedHandshake) { | 375 TEST_P(QuicSessionTest, BufferedHandshake) { |
303 EXPECT_FALSE(session_.HasPendingHandshake()); // Default value. | 376 EXPECT_FALSE(session_.HasPendingHandshake()); // Default value. |
304 | 377 |
305 // Test that blocking other streams does not change our status. | 378 // Test that blocking other streams does not change our status. |
306 TestStream* stream2 = session_.CreateOutgoingDataStream(); | 379 TestStream* stream2 = session_.CreateOutgoingDataStream(); |
307 StreamBlocker stream2_blocker(&session_, stream2->id()); | 380 StreamBlocker stream2_blocker(&session_, stream2->id()); |
308 stream2_blocker.MarkWriteBlocked(); | 381 stream2_blocker.MarkWriteBlocked(); |
309 EXPECT_FALSE(session_.HasPendingHandshake()); | 382 EXPECT_FALSE(session_.HasPendingHandshake()); |
310 | 383 |
311 TestStream* stream3 = session_.CreateOutgoingDataStream(); | 384 TestStream* stream3 = session_.CreateOutgoingDataStream(); |
312 StreamBlocker stream3_blocker(&session_, stream3->id()); | 385 StreamBlocker stream3_blocker(&session_, stream3->id()); |
313 stream3_blocker.MarkWriteBlocked(); | 386 stream3_blocker.MarkWriteBlocked(); |
314 EXPECT_FALSE(session_.HasPendingHandshake()); | 387 EXPECT_FALSE(session_.HasPendingHandshake()); |
315 | 388 |
316 // Blocking (due to buffering of) the Crypto stream is detected. | 389 // Blocking (due to buffering of) the Crypto stream is detected. |
317 session_.MarkWriteBlocked(kCryptoStreamId, kSomeMiddlePriority); | 390 session_.MarkWriteBlocked(kCryptoStreamId, kHighestPriority); |
318 EXPECT_TRUE(session_.HasPendingHandshake()); | 391 EXPECT_TRUE(session_.HasPendingHandshake()); |
319 | 392 |
320 TestStream* stream4 = session_.CreateOutgoingDataStream(); | 393 TestStream* stream4 = session_.CreateOutgoingDataStream(); |
321 StreamBlocker stream4_blocker(&session_, stream4->id()); | 394 StreamBlocker stream4_blocker(&session_, stream4->id()); |
322 stream4_blocker.MarkWriteBlocked(); | 395 stream4_blocker.MarkWriteBlocked(); |
323 EXPECT_TRUE(session_.HasPendingHandshake()); | 396 EXPECT_TRUE(session_.HasPendingHandshake()); |
324 | 397 |
325 InSequence s; | 398 InSequence s; |
326 // Force most streams to re-register, which is common scenario when we block | 399 // Force most streams to re-register, which is common scenario when we block |
327 // the Crypto stream, and only the crypto stream can "really" write. | 400 // the Crypto stream, and only the crypto stream can "really" write. |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 } | 577 } |
505 | 578 |
506 QuicRstStreamFrame rst1(stream_id1, QUIC_STREAM_NO_ERROR); | 579 QuicRstStreamFrame rst1(stream_id1, QUIC_STREAM_NO_ERROR); |
507 session_.OnRstStream(rst1); | 580 session_.OnRstStream(rst1); |
508 EXPECT_EQ(0u, session_.GetNumOpenStreams()); | 581 EXPECT_EQ(0u, session_.GetNumOpenStreams()); |
509 } | 582 } |
510 | 583 |
511 } // namespace | 584 } // namespace |
512 } // namespace test | 585 } // namespace test |
513 } // namespace net | 586 } // namespace net |
OLD | NEW |