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 |