Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: net/quic/quic_headers_stream_test.cc

Issue 1408803002: relnote: Measure HOL blocking in QUIC headers stream. Flag protected by quic_measure_headers_hol_bl… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@uma_for_hol_merge
Patch Set: get rid of git certs leakage Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_headers_stream.cc ('k') | net/quic/quic_stream_sequencer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
7 #include "net/quic/quic_utils.h" 8 #include "net/quic/quic_utils.h"
8 #include "net/quic/spdy_utils.h" 9 #include "net/quic/spdy_utils.h"
9 #include "net/quic/test_tools/quic_connection_peer.h" 10 #include "net/quic/test_tools/quic_connection_peer.h"
10 #include "net/quic/test_tools/quic_spdy_session_peer.h" 11 #include "net/quic/test_tools/quic_spdy_session_peer.h"
11 #include "net/quic/test_tools/quic_test_utils.h" 12 #include "net/quic/test_tools/quic_test_utils.h"
12 #include "net/quic/test_tools/reliable_quic_stream_peer.h" 13 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
13 #include "net/spdy/spdy_protocol.h" 14 #include "net/spdy/spdy_protocol.h"
14 #include "net/spdy/spdy_test_utils.h" 15 #include "net/spdy/spdy_test_utils.h"
15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
16 17
18 using base::Bucket;
19 using base::HistogramTester;
17 using base::StringPiece; 20 using base::StringPiece;
18 using std::ostream; 21 using std::ostream;
19 using std::string; 22 using std::string;
20 using std::vector; 23 using std::vector;
24 using testing::ElementsAre;
25 using testing::InSequence;
21 using testing::Invoke; 26 using testing::Invoke;
22 using testing::StrictMock; 27 using testing::StrictMock;
23 using testing::WithArgs; 28 using testing::WithArgs;
24 using testing::_; 29 using testing::_;
25 30
26 namespace net { 31 namespace net {
27 namespace test { 32 namespace test {
28 namespace { 33 namespace {
29 34
35 // TODO(ckrasic): this workaround is due to absence of std::initializer_list
36 const bool kFins[] = {false, true};
37
30 class MockVisitor : public SpdyFramerVisitorInterface { 38 class MockVisitor : public SpdyFramerVisitorInterface {
31 public: 39 public:
32 MOCK_METHOD1(OnError, void(SpdyFramer* framer)); 40 MOCK_METHOD1(OnError, void(SpdyFramer* framer));
33 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id, 41 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id,
34 size_t length, 42 size_t length,
35 bool fin)); 43 bool fin));
36 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id, 44 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id,
37 const char* data, 45 const char* data,
38 size_t len, 46 size_t len,
39 bool fin)); 47 bool fin));
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 body_("hello world"), 125 body_("hello world"),
118 framer_(HTTP2), 126 framer_(HTTP2),
119 stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, "") { 127 stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, "") {
120 headers_[":version"] = "HTTP/1.1"; 128 headers_[":version"] = "HTTP/1.1";
121 headers_[":status"] = "200 Ok"; 129 headers_[":status"] = "200 Ok";
122 headers_["content-length"] = "11"; 130 headers_["content-length"] = "11";
123 framer_.set_visitor(&visitor_); 131 framer_.set_visitor(&visitor_);
124 EXPECT_EQ(version(), session_.connection()->version()); 132 EXPECT_EQ(version(), session_.connection()->version());
125 EXPECT_TRUE(headers_stream_ != nullptr); 133 EXPECT_TRUE(headers_stream_ != nullptr);
126 VLOG(1) << GetParam(); 134 VLOG(1) << GetParam();
135 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
127 } 136 }
128 137
129 QuicConsumedData SaveIov(const QuicIOVector& data) { 138 QuicConsumedData SaveIov(const QuicIOVector& data) {
130 const iovec* iov = data.iov; 139 const iovec* iov = data.iov;
131 int count = data.iov_count; 140 int count = data.iov_count;
132 for (int i = 0 ; i < count; ++i) { 141 for (int i = 0 ; i < count; ++i) {
133 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len); 142 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
134 } 143 }
135 return QuicConsumedData(saved_data_.length(), false); 144 return QuicConsumedData(saved_data_.length(), false);
136 } 145 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 EXPECT_EQ(3u, headers_stream_->id()); 248 EXPECT_EQ(3u, headers_stream_->id());
240 } 249 }
241 250
242 TEST_P(QuicHeadersStreamTest, EffectivePriority) { 251 TEST_P(QuicHeadersStreamTest, EffectivePriority) {
243 EXPECT_EQ(0u, headers_stream_->EffectivePriority()); 252 EXPECT_EQ(0u, headers_stream_->EffectivePriority());
244 } 253 }
245 254
246 TEST_P(QuicHeadersStreamTest, WriteHeaders) { 255 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
247 for (QuicStreamId stream_id = kClientDataStreamId1; 256 for (QuicStreamId stream_id = kClientDataStreamId1;
248 stream_id < kClientDataStreamId3; stream_id += 2) { 257 stream_id < kClientDataStreamId3; stream_id += 2) {
249 for (int count = 0; count < 2; ++count) { 258 for (bool fin : kFins) {
250 bool fin = (count == 0);
251 if (perspective() == Perspective::IS_SERVER) { 259 if (perspective() == Perspective::IS_SERVER) {
252 WriteHeadersAndExpectSynReply(stream_id, fin); 260 WriteHeadersAndExpectSynReply(stream_id, fin);
253 } else { 261 } else {
254 for (QuicPriority priority = 0; priority < 7; ++priority) { 262 for (QuicPriority priority = 0; priority < 7; ++priority) {
255 // TODO(rch): implement priorities correctly. 263 // TODO(rch): implement priorities correctly.
256 WriteHeadersAndExpectSynStream(stream_id, fin, 0); 264 WriteHeadersAndExpectSynStream(stream_id, fin, 0);
257 } 265 }
258 } 266 }
259 } 267 }
260 } 268 }
261 } 269 }
262 270
263 TEST_P(QuicHeadersStreamTest, ProcessRawData) { 271 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
264 for (QuicStreamId stream_id = kClientDataStreamId1; 272 for (QuicStreamId stream_id = kClientDataStreamId1;
265 stream_id < kClientDataStreamId3; stream_id += 2) { 273 stream_id < kClientDataStreamId3; stream_id += 2) {
266 for (int count = 0; count < 2; ++count) { 274 for (bool fin : kFins) {
267 bool fin = (count == 0);
268 for (QuicPriority priority = 0; priority < 7; ++priority) { 275 for (QuicPriority priority = 0; priority < 7; ++priority) {
269 // Replace with "WriteHeadersAndSaveData" 276 // Replace with "WriteHeadersAndSaveData"
270 scoped_ptr<SpdySerializedFrame> frame; 277 scoped_ptr<SpdySerializedFrame> frame;
271 if (perspective() == Perspective::IS_SERVER) { 278 if (perspective() == Perspective::IS_SERVER) {
272 SpdyHeadersIR headers_frame(stream_id); 279 SpdyHeadersIR headers_frame(stream_id);
273 headers_frame.set_header_block(headers_); 280 headers_frame.set_header_block(headers_);
274 headers_frame.set_fin(fin); 281 headers_frame.set_fin(fin);
275 headers_frame.set_has_priority(true); 282 headers_frame.set_has_priority(true);
276 frame.reset(framer_.SerializeFrame(headers_frame)); 283 frame.reset(framer_.SerializeFrame(headers_frame));
277 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)); 284 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
(...skipping 11 matching lines...) Expand all
289 OnStreamHeadersComplete(stream_id, fin, frame->size())); 296 OnStreamHeadersComplete(stream_id, fin, frame->size()));
290 stream_frame_.data = StringPiece(frame->data(), frame->size()); 297 stream_frame_.data = StringPiece(frame->data(), frame->size());
291 headers_stream_->OnStreamFrame(stream_frame_); 298 headers_stream_->OnStreamFrame(stream_frame_);
292 stream_frame_.offset += frame->size(); 299 stream_frame_.offset += frame->size();
293 CheckHeaders(); 300 CheckHeaders();
294 } 301 }
295 } 302 }
296 } 303 }
297 } 304 }
298 305
306 TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) {
307 // In the absence of surfacing HOL measurements externally, via UMA
308 // or tcp connection stats, log messages are the only indication.
309 // This test verifies that false positives are not generated when
310 // headers arrive in order.
311 #if 0
312 ScopedMockLog log(kDoNotCaptureLogsYet);
313 EXPECT_CALL(log, Log(_, _, _)).Times(0);
314 log.StartCapturingLogs();
315 #endif
316 InSequence seq;
317 HistogramTester histogram_tester;
318 bool fin = true;
319 for (int stream_num = 0; stream_num < 10; stream_num++) {
320 QuicStreamId stream_id = QuicClientDataStreamId(stream_num);
321 // Replace with "WriteHeadersAndSaveData"
322 scoped_ptr<SpdySerializedFrame> frame;
323 if (perspective() == Perspective::IS_SERVER) {
324 SpdyHeadersIR headers_frame(stream_id);
325 headers_frame.set_header_block(headers_);
326 headers_frame.set_fin(fin);
327 headers_frame.set_has_priority(true);
328 frame.reset(framer_.SerializeFrame(headers_frame));
329 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
330 } else {
331 SpdyHeadersIR headers_frame(stream_id);
332 headers_frame.set_header_block(headers_);
333 headers_frame.set_fin(fin);
334 frame.reset(framer_.SerializeFrame(headers_frame));
335 }
336 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _));
337 EXPECT_CALL(session_,
338 OnStreamHeadersComplete(stream_id, fin, frame->size()));
339 stream_frame_.data = StringPiece(frame->data(), frame->size());
340 headers_stream_->OnStreamFrame(stream_frame_);
341 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
342 stream_frame_.offset += frame->size();
343 }
344 histogram_tester.ExpectTotalCount("Net.QuicSession.HeadersHOLBlockedTime", 0);
345 }
346
347 TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) {
348 // In the absence of surfacing HOL measurements externally, via UMA
349 // or tcp connection stats, log messages are the only indication.
350 // This test verifies that HOL blocking log messages are correct
351 // when there are out of order arrivals.
352 #if 0
353 ScopedMockLog log(kDoNotCaptureLogsYet);
354 #endif
355 HistogramTester histogram_tester;
356 QuicStreamId stream_id;
357 bool fin = true;
358 QuicStreamFrame stream_frames[10];
359 scoped_ptr<SpdySerializedFrame> frames[10];
360 // First create all the frames in order
361 {
362 InSequence seq;
363 for (int stream_num = 0; stream_num < 10; ++stream_num) {
364 stream_id = QuicClientDataStreamId(stream_num);
365 if (perspective() == Perspective::IS_SERVER) {
366 SpdyHeadersIR headers_frame(stream_id);
367 headers_frame.set_header_block(headers_);
368 headers_frame.set_fin(fin);
369 headers_frame.set_has_priority(true);
370 frames[stream_num].reset(framer_.SerializeFrame(headers_frame));
371 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)).Times(1);
372 } else {
373 SpdyHeadersIR headers_frame(stream_id);
374 headers_frame.set_header_block(headers_);
375 headers_frame.set_fin(fin);
376 frames[stream_num].reset(framer_.SerializeFrame(headers_frame));
377 }
378 stream_frames[stream_num] = stream_frame_;
379 stream_frames[stream_num].data =
380 StringPiece(frames[stream_num]->data(), frames[stream_num]->size());
381 DVLOG(1) << "make frame for stream " << stream_num << " offset "
382 << stream_frames[stream_num].offset;
383 stream_frame_.offset += frames[stream_num]->size();
384 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)).Times(1);
385 EXPECT_CALL(session_, OnStreamHeadersComplete(stream_id, fin, _))
386 .Times(1);
387 }
388 }
389 #if 0
390 // Actually writing the frames in reverse order will trigger log messages.
391 {
392 InSequence seq;
393 for (int stream_num = 0; stream_num < 10; ++stream_num) {
394 stream_id = QuicClientDataStreamId(stream_num);
395 if (stream_num > 0) {
396 string expected_msg = StringPrintf(
397 "stream %d: Net.QuicSession.HeadersHOLBlockedTime %d",
398 stream_id, stream_num);
399 #ifndef NDEBUG
400 EXPECT_CALL(log, Log(INFO, _, expected_msg));
401 #endif
402 }
403 }
404 }
405 log.StartCapturingLogs();
406 #endif
407 for (int stream_num = 9; stream_num >= 0; --stream_num) {
408 DVLOG(1) << "OnStreamFrame for stream " << stream_num << " offset "
409 << stream_frames[stream_num].offset;
410 headers_stream_->OnStreamFrame(stream_frames[stream_num]);
411 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
412 }
413 // We expect 1 sample each for delays from 1 to 9 ms (8 and 9 go
414 // into the same bucket).
415 EXPECT_THAT(
416 histogram_tester.GetAllSamples("Net.QuicSession.HeadersHOLBlockedTime"),
417 ElementsAre(Bucket(1, 1), Bucket(2, 1), Bucket(3, 1), Bucket(4, 1),
418 Bucket(5, 1), Bucket(6, 1), Bucket(7, 1), Bucket(8, 2)));
419 }
420
299 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) { 421 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
300 // We want to create a frame that is more than the SPDY Framer's max control 422 // We want to create a frame that is more than the SPDY Framer's max control
301 // frame size, which is 16K, but less than the HPACK decoders max decode 423 // frame size, which is 16K, but less than the HPACK decoders max decode
302 // buffer size, which is 32K. 424 // buffer size, which is 32K.
303 headers_["key0"] = string(1 << 13, '.'); 425 headers_["key0"] = string(1 << 13, '.');
304 headers_["key1"] = string(1 << 13, '.'); 426 headers_["key1"] = string(1 << 13, '.');
305 headers_["key2"] = string(1 << 13, '.'); 427 headers_["key2"] = string(1 << 13, '.');
306 for (QuicStreamId stream_id = kClientDataStreamId1; 428 for (QuicStreamId stream_id = kClientDataStreamId1;
307 stream_id < kClientDataStreamId3; stream_id += 2) { 429 stream_id < kClientDataStreamId3; stream_id += 2) {
308 for (int count = 0; count < 2; ++count) { 430 for (bool fin : kFins) {
309 bool fin = (count == 0);
310 for (QuicPriority priority = 0; priority < 7; ++priority) { 431 for (QuicPriority priority = 0; priority < 7; ++priority) {
311 // Replace with "WriteHeadersAndSaveData" 432 // Replace with "WriteHeadersAndSaveData"
312 scoped_ptr<SpdySerializedFrame> frame; 433 scoped_ptr<SpdySerializedFrame> frame;
313 if (perspective() == Perspective::IS_SERVER) { 434 if (perspective() == Perspective::IS_SERVER) {
314 SpdyHeadersIR headers_frame(stream_id); 435 SpdyHeadersIR headers_frame(stream_id);
315 headers_frame.set_header_block(headers_); 436 headers_frame.set_header_block(headers_);
316 headers_frame.set_fin(fin); 437 headers_frame.set_fin(fin);
317 headers_frame.set_has_priority(true); 438 headers_frame.set_has_priority(true);
318 frame.reset(framer_.SerializeFrame(headers_frame)); 439 frame.reset(framer_.SerializeFrame(headers_frame));
319 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)); 440 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 } 544 }
424 545
425 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) { 546 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
426 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl( 547 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
427 headers_stream_)); 548 headers_stream_));
428 } 549 }
429 550
430 } // namespace 551 } // namespace
431 } // namespace test 552 } // namespace test
432 } // namespace net 553 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_headers_stream.cc ('k') | net/quic/quic_stream_sequencer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698