| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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_headers_stream.h" | 5 #include "net/quic/quic_headers_stream.h" |
| 6 | 6 |
| 7 #include "base/test/histogram_tester.h" | |
| 8 #include "net/quic/quic_utils.h" | 7 #include "net/quic/quic_utils.h" |
| 9 #include "net/quic/spdy_utils.h" | 8 #include "net/quic/spdy_utils.h" |
| 10 #include "net/quic/test_tools/quic_connection_peer.h" | 9 #include "net/quic/test_tools/quic_connection_peer.h" |
| 11 #include "net/quic/test_tools/quic_spdy_session_peer.h" | 10 #include "net/quic/test_tools/quic_spdy_session_peer.h" |
| 12 #include "net/quic/test_tools/quic_test_utils.h" | 11 #include "net/quic/test_tools/quic_test_utils.h" |
| 13 #include "net/quic/test_tools/reliable_quic_stream_peer.h" | 12 #include "net/quic/test_tools/reliable_quic_stream_peer.h" |
| 14 #include "net/spdy/spdy_protocol.h" | 13 #include "net/spdy/spdy_protocol.h" |
| 15 #include "net/spdy/spdy_test_utils.h" | 14 #include "net/spdy/spdy_test_utils.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 16 |
| 18 using base::Bucket; | |
| 19 using base::HistogramTester; | |
| 20 using base::StringPiece; | 17 using base::StringPiece; |
| 21 using std::ostream; | 18 using std::ostream; |
| 22 using std::string; | 19 using std::string; |
| 23 using std::vector; | 20 using std::vector; |
| 24 using testing::ElementsAre; | 21 using testing::ElementsAre; |
| 25 using testing::InSequence; | 22 using testing::InSequence; |
| 26 using testing::Invoke; | 23 using testing::Invoke; |
| 27 using testing::StrictMock; | 24 using testing::StrictMock; |
| 28 using testing::WithArgs; | 25 using testing::WithArgs; |
| 29 using testing::_; | 26 using testing::_; |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 return versions; | 216 return versions; |
| 220 } | 217 } |
| 221 | 218 |
| 222 void CloseConnection() { | 219 void CloseConnection() { |
| 223 QuicConnectionPeer::CloseConnection(connection_); | 220 QuicConnectionPeer::CloseConnection(connection_); |
| 224 } | 221 } |
| 225 | 222 |
| 226 static const bool kFrameComplete = true; | 223 static const bool kFrameComplete = true; |
| 227 static const bool kHasPriority = true; | 224 static const bool kHasPriority = true; |
| 228 | 225 |
| 229 MockHelper helper_; | 226 MockConnectionHelper helper_; |
| 230 StrictMock<MockConnection>* connection_; | 227 StrictMock<MockConnection>* connection_; |
| 231 StrictMock<MockQuicSpdySession> session_; | 228 StrictMock<MockQuicSpdySession> session_; |
| 232 QuicHeadersStream* headers_stream_; | 229 QuicHeadersStream* headers_stream_; |
| 233 SpdyHeaderBlock headers_; | 230 SpdyHeaderBlock headers_; |
| 234 string body_; | 231 string body_; |
| 235 string saved_data_; | 232 string saved_data_; |
| 236 string saved_header_data_; | 233 string saved_header_data_; |
| 237 SpdyFramer framer_; | 234 SpdyFramer framer_; |
| 238 StrictMock<MockVisitor> visitor_; | 235 StrictMock<MockVisitor> visitor_; |
| 239 QuicStreamFrame stream_frame_; | 236 QuicStreamFrame stream_frame_; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 stream_frame_.data = StringPiece(frame->data(), frame->size()); | 293 stream_frame_.data = StringPiece(frame->data(), frame->size()); |
| 297 headers_stream_->OnStreamFrame(stream_frame_); | 294 headers_stream_->OnStreamFrame(stream_frame_); |
| 298 stream_frame_.offset += frame->size(); | 295 stream_frame_.offset += frame->size(); |
| 299 CheckHeaders(); | 296 CheckHeaders(); |
| 300 } | 297 } |
| 301 } | 298 } |
| 302 } | 299 } |
| 303 } | 300 } |
| 304 | 301 |
| 305 TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) { | 302 TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) { |
| 306 // In the absence of surfacing HOL measurements externally, via UMA | 303 EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(0); |
| 307 // or tcp connection stats, log messages are the only indication. | 304 testing::InSequence seq; |
| 308 // This test verifies that false positives are not generated when | |
| 309 // headers arrive in order. | |
| 310 #if 0 | |
| 311 ScopedMockLog log(kDoNotCaptureLogsYet); | |
| 312 EXPECT_CALL(log, Log(_, _, _)).Times(0); | |
| 313 log.StartCapturingLogs(); | |
| 314 #endif | |
| 315 InSequence seq; | |
| 316 HistogramTester histogram_tester; | |
| 317 bool fin = true; | 305 bool fin = true; |
| 318 for (int stream_num = 0; stream_num < 10; stream_num++) { | 306 for (int stream_num = 0; stream_num < 10; stream_num++) { |
| 319 QuicStreamId stream_id = QuicClientDataStreamId(stream_num); | 307 QuicStreamId stream_id = QuicClientDataStreamId(stream_num); |
| 320 // Replace with "WriteHeadersAndSaveData" | 308 // Replace with "WriteHeadersAndSaveData" |
| 321 scoped_ptr<SpdySerializedFrame> frame; | 309 scoped_ptr<SpdySerializedFrame> frame; |
| 322 if (perspective() == Perspective::IS_SERVER) { | 310 if (perspective() == Perspective::IS_SERVER) { |
| 323 SpdyHeadersIR headers_frame(stream_id); | 311 SpdyHeadersIR headers_frame(stream_id); |
| 324 headers_frame.set_header_block(headers_); | 312 headers_frame.set_header_block(headers_); |
| 325 headers_frame.set_fin(fin); | 313 headers_frame.set_fin(fin); |
| 326 headers_frame.set_has_priority(true); | 314 headers_frame.set_has_priority(true); |
| 327 frame.reset(framer_.SerializeFrame(headers_frame)); | 315 frame.reset(framer_.SerializeFrame(headers_frame)); |
| 328 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)); | 316 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)); |
| 329 } else { | 317 } else { |
| 330 SpdyHeadersIR headers_frame(stream_id); | 318 SpdyHeadersIR headers_frame(stream_id); |
| 331 headers_frame.set_header_block(headers_); | 319 headers_frame.set_header_block(headers_); |
| 332 headers_frame.set_fin(fin); | 320 headers_frame.set_fin(fin); |
| 333 frame.reset(framer_.SerializeFrame(headers_frame)); | 321 frame.reset(framer_.SerializeFrame(headers_frame)); |
| 334 } | 322 } |
| 335 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)); | 323 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)); |
| 336 EXPECT_CALL(session_, | 324 EXPECT_CALL(session_, |
| 337 OnStreamHeadersComplete(stream_id, fin, frame->size())); | 325 OnStreamHeadersComplete(stream_id, fin, frame->size())); |
| 338 stream_frame_.data = StringPiece(frame->data(), frame->size()); | 326 stream_frame_.data = StringPiece(frame->data(), frame->size()); |
| 339 headers_stream_->OnStreamFrame(stream_frame_); | 327 headers_stream_->OnStreamFrame(stream_frame_); |
| 340 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); | 328 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); |
| 341 stream_frame_.offset += frame->size(); | 329 stream_frame_.offset += frame->size(); |
| 342 } | 330 } |
| 343 histogram_tester.ExpectTotalCount("Net.QuicSession.HeadersHOLBlockedTime", 0); | |
| 344 } | 331 } |
| 345 | 332 |
| 346 TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) { | 333 TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) { |
| 347 // In the absence of surfacing HOL measurements externally, via UMA | |
| 348 // or tcp connection stats, log messages are the only indication. | |
| 349 // This test verifies that HOL blocking log messages are correct | |
| 350 // when there are out of order arrivals. | |
| 351 #if 0 | |
| 352 ScopedMockLog log(kDoNotCaptureLogsYet); | |
| 353 #endif | |
| 354 HistogramTester histogram_tester; | |
| 355 QuicStreamId stream_id; | 334 QuicStreamId stream_id; |
| 356 bool fin = true; | 335 bool fin = true; |
| 357 QuicStreamFrame stream_frames[10]; | 336 QuicStreamFrame stream_frames[10]; |
| 358 scoped_ptr<SpdySerializedFrame> frames[10]; | 337 scoped_ptr<SpdySerializedFrame> frames[10]; |
| 359 // First create all the frames in order | 338 // First create all the frames in order |
| 360 { | 339 { |
| 361 InSequence seq; | 340 InSequence seq; |
| 362 for (int stream_num = 0; stream_num < 10; ++stream_num) { | 341 for (int stream_num = 0; stream_num < 10; ++stream_num) { |
| 363 stream_id = QuicClientDataStreamId(stream_num); | 342 stream_id = QuicClientDataStreamId(stream_num); |
| 364 if (perspective() == Perspective::IS_SERVER) { | 343 if (perspective() == Perspective::IS_SERVER) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 378 stream_frames[stream_num].data = | 357 stream_frames[stream_num].data = |
| 379 StringPiece(frames[stream_num]->data(), frames[stream_num]->size()); | 358 StringPiece(frames[stream_num]->data(), frames[stream_num]->size()); |
| 380 DVLOG(1) << "make frame for stream " << stream_num << " offset " | 359 DVLOG(1) << "make frame for stream " << stream_num << " offset " |
| 381 << stream_frames[stream_num].offset; | 360 << stream_frames[stream_num].offset; |
| 382 stream_frame_.offset += frames[stream_num]->size(); | 361 stream_frame_.offset += frames[stream_num]->size(); |
| 383 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)).Times(1); | 362 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)).Times(1); |
| 384 EXPECT_CALL(session_, OnStreamHeadersComplete(stream_id, fin, _)) | 363 EXPECT_CALL(session_, OnStreamHeadersComplete(stream_id, fin, _)) |
| 385 .Times(1); | 364 .Times(1); |
| 386 } | 365 } |
| 387 } | 366 } |
| 388 #if 0 | 367 |
| 389 // Actually writing the frames in reverse order will trigger log messages. | 368 // Actually writing the frames in reverse order will cause HOL blocking. |
| 390 { | 369 EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(9); |
| 391 InSequence seq; | 370 |
| 392 for (int stream_num = 0; stream_num < 10; ++stream_num) { | |
| 393 stream_id = QuicClientDataStreamId(stream_num); | |
| 394 if (stream_num > 0) { | |
| 395 string expected_msg = StringPrintf( | |
| 396 "stream %d: Net.QuicSession.HeadersHOLBlockedTime %d", | |
| 397 stream_id, stream_num); | |
| 398 #ifndef NDEBUG | |
| 399 EXPECT_CALL(log, Log(INFO, _, expected_msg)); | |
| 400 #endif | |
| 401 } | |
| 402 } | |
| 403 } | |
| 404 log.StartCapturingLogs(); | |
| 405 #endif | |
| 406 for (int stream_num = 9; stream_num >= 0; --stream_num) { | 371 for (int stream_num = 9; stream_num >= 0; --stream_num) { |
| 407 DVLOG(1) << "OnStreamFrame for stream " << stream_num << " offset " | 372 DVLOG(1) << "OnStreamFrame for stream " << stream_num << " offset " |
| 408 << stream_frames[stream_num].offset; | 373 << stream_frames[stream_num].offset; |
| 409 headers_stream_->OnStreamFrame(stream_frames[stream_num]); | 374 headers_stream_->OnStreamFrame(stream_frames[stream_num]); |
| 410 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); | 375 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); |
| 411 } | 376 } |
| 412 // We expect 1 sample each for delays from 1 to 9 ms (8 and 9 go | |
| 413 // into the same bucket). | |
| 414 EXPECT_THAT( | |
| 415 histogram_tester.GetAllSamples("Net.QuicSession.HeadersHOLBlockedTime"), | |
| 416 ElementsAre(Bucket(1, 1), Bucket(2, 1), Bucket(3, 1), Bucket(4, 1), | |
| 417 Bucket(5, 1), Bucket(6, 1), Bucket(7, 1), Bucket(8, 2))); | |
| 418 } | 377 } |
| 419 | 378 |
| 420 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) { | 379 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) { |
| 421 // We want to create a frame that is more than the SPDY Framer's max control | 380 // We want to create a frame that is more than the SPDY Framer's max control |
| 422 // frame size, which is 16K, but less than the HPACK decoders max decode | 381 // frame size, which is 16K, but less than the HPACK decoders max decode |
| 423 // buffer size, which is 32K. | 382 // buffer size, which is 32K. |
| 424 headers_["key0"] = string(1 << 13, '.'); | 383 headers_["key0"] = string(1 << 13, '.'); |
| 425 headers_["key1"] = string(1 << 13, '.'); | 384 headers_["key1"] = string(1 << 13, '.'); |
| 426 headers_["key2"] = string(1 << 13, '.'); | 385 headers_["key2"] = string(1 << 13, '.'); |
| 427 for (QuicStreamId stream_id = kClientDataStreamId1; | 386 for (QuicStreamId stream_id = kClientDataStreamId1; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 } | 502 } |
| 544 | 503 |
| 545 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) { | 504 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) { |
| 546 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl( | 505 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl( |
| 547 headers_stream_)); | 506 headers_stream_)); |
| 548 } | 507 } |
| 549 | 508 |
| 550 } // namespace | 509 } // namespace |
| 551 } // namespace test | 510 } // namespace test |
| 552 } // namespace net | 511 } // namespace net |
| OLD | NEW |