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

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

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 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_http_utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "net/quic/quic_headers_stream.h"
6
7 #include <string>
8
9 #include "base/strings/string_number_conversions.h"
10 #include "net/quic/quic_bug_tracker.h"
11 #include "net/quic/quic_utils.h"
12 #include "net/quic/spdy_utils.h"
13 #include "net/quic/test_tools/quic_connection_peer.h"
14 #include "net/quic/test_tools/quic_headers_stream_peer.h"
15 #include "net/quic/test_tools/quic_spdy_session_peer.h"
16 #include "net/quic/test_tools/quic_test_utils.h"
17 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
18 #include "net/spdy/spdy_alt_svc_wire_format.h"
19 #include "net/spdy/spdy_flags.h"
20 #include "net/spdy/spdy_protocol.h"
21 #include "net/spdy/spdy_test_utils.h"
22 #include "net/test/gtest_util.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 using base::StringPiece;
26 using std::ostream;
27 using std::string;
28 using std::vector;
29 using testing::ElementsAre;
30 using testing::_;
31 using testing::AtLeast;
32 using testing::HasSubstr;
33 using testing::InSequence;
34 using testing::Invoke;
35 using testing::Return;
36 using testing::StrictMock;
37 using testing::WithArgs;
38 using testing::_;
39
40 // TODO(bnc): Merge these correctly.
41 bool FLAGS_use_http2_frame_decoder_adapter;
42 bool FLAGS_spdy_use_hpack_decoder2;
43 bool FLAGS_spdy_framer_use_new_methods2;
44
45 namespace net {
46 namespace test {
47
48 class MockHpackDebugVisitor : public QuicHeadersStream::HpackDebugVisitor {
49 public:
50 explicit MockHpackDebugVisitor() : HpackDebugVisitor() {}
51
52 MOCK_METHOD1(OnUseEntry, void(QuicTime::Delta elapsed));
53
54 private:
55 DISALLOW_COPY_AND_ASSIGN(MockHpackDebugVisitor);
56 };
57
58 namespace {
59
60 // TODO(ckrasic): this workaround is due to absence of std::initializer_list
61 const bool kFins[] = {false, true};
62
63 class MockVisitor : public SpdyFramerVisitorInterface {
64 public:
65 MOCK_METHOD1(OnError, void(SpdyFramer* framer));
66 MOCK_METHOD3(OnDataFrameHeader,
67 void(SpdyStreamId stream_id, size_t length, bool fin));
68 MOCK_METHOD3(OnStreamFrameData,
69 void(SpdyStreamId stream_id, const char* data, size_t len));
70 MOCK_METHOD1(OnStreamEnd, void(SpdyStreamId stream_id));
71 MOCK_METHOD2(OnStreamPadding, void(SpdyStreamId stream_id, size_t len));
72 MOCK_METHOD1(OnHeaderFrameStart,
73 SpdyHeadersHandlerInterface*(SpdyStreamId stream_id));
74 MOCK_METHOD2(OnHeaderFrameEnd, void(SpdyStreamId stream_id, bool end));
75 MOCK_METHOD3(OnControlFrameHeaderData,
76 bool(SpdyStreamId stream_id,
77 const char* header_data,
78 size_t len));
79 MOCK_METHOD5(OnSynStream,
80 void(SpdyStreamId stream_id,
81 SpdyStreamId associated_stream_id,
82 SpdyPriority priority,
83 bool fin,
84 bool unidirectional));
85 MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
86 MOCK_METHOD2(OnRstStream,
87 void(SpdyStreamId stream_id, SpdyRstStreamStatus status));
88 MOCK_METHOD1(OnSettings, void(bool clear_persisted));
89 MOCK_METHOD3(OnSetting,
90 void(SpdySettingsIds id, uint8_t flags, uint32_t value));
91 MOCK_METHOD0(OnSettingsAck, void());
92 MOCK_METHOD0(OnSettingsEnd, void());
93 MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
94 MOCK_METHOD2(OnGoAway,
95 void(SpdyStreamId last_accepted_stream_id,
96 SpdyGoAwayStatus status));
97 MOCK_METHOD7(OnHeaders,
98 void(SpdyStreamId stream_id,
99 bool has_priority,
100 int weight,
101 SpdyStreamId parent_stream_id,
102 bool exclusive,
103 bool fin,
104 bool end));
105 MOCK_METHOD2(OnWindowUpdate,
106 void(SpdyStreamId stream_id, int delta_window_size));
107 MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
108 MOCK_METHOD3(OnPushPromise,
109 void(SpdyStreamId stream_id,
110 SpdyStreamId promised_stream_id,
111 bool end));
112 MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end));
113 MOCK_METHOD4(OnPriority,
114 void(SpdyStreamId stream_id,
115 SpdyStreamId parent_id,
116 int weight,
117 bool exclusive));
118 MOCK_METHOD3(OnAltSvc,
119 void(SpdyStreamId stream_id,
120 StringPiece origin,
121 const SpdyAltSvcWireFormat::AlternativeServiceVector&
122 altsvc_vector));
123 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type));
124 };
125
126 class ForceHolAckListener : public QuicAckListenerInterface {
127 public:
128 ForceHolAckListener() : total_acked_bytes_(0) {}
129
130 void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override {
131 total_acked_bytes_ += acked_bytes;
132 }
133
134 void OnPacketRetransmitted(int retransmitted_bytes) override {}
135
136 size_t total_acked_bytes() { return total_acked_bytes_; }
137
138 private:
139 ~ForceHolAckListener() override {}
140
141 size_t total_acked_bytes_;
142
143 DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener);
144 };
145
146 enum Http2DecoderChoice {
147 HTTP2_DECODER_SPDY,
148 HTTP2_DECODER_NESTED_SPDY,
149 HTTP2_DECODER_NEW
150 };
151 ostream& operator<<(ostream& os, Http2DecoderChoice v) {
152 switch (v) {
153 case HTTP2_DECODER_SPDY:
154 return os << "SPDY";
155 case HTTP2_DECODER_NESTED_SPDY:
156 return os << "NESTED_SPDY";
157 case HTTP2_DECODER_NEW:
158 return os << "NEW";
159 }
160 return os;
161 }
162
163 enum HpackDecoderChoice { HPACK_DECODER_SPDY, HPACK_DECODER_NEW };
164 ostream& operator<<(ostream& os, HpackDecoderChoice v) {
165 switch (v) {
166 case HPACK_DECODER_SPDY:
167 return os << "SPDY";
168 case HPACK_DECODER_NEW:
169 return os << "NEW";
170 }
171 return os;
172 }
173
174 typedef std::
175 tuple<QuicVersion, Perspective, Http2DecoderChoice, HpackDecoderChoice>
176 TestParamsTuple;
177
178 struct TestParams {
179 explicit TestParams(TestParamsTuple params)
180 : version(std::get<0>(params)),
181 perspective(std::get<1>(params)),
182 http2_decoder(std::get<2>(params)),
183 hpack_decoder(std::get<3>(params)) {
184 switch (http2_decoder) {
185 case HTTP2_DECODER_SPDY:
186 FLAGS_use_nested_spdy_framer_decoder = false;
187 FLAGS_use_http2_frame_decoder_adapter = false;
188 break;
189 case HTTP2_DECODER_NESTED_SPDY:
190 FLAGS_use_nested_spdy_framer_decoder = true;
191 FLAGS_use_http2_frame_decoder_adapter = false;
192 break;
193 case HTTP2_DECODER_NEW:
194 FLAGS_use_nested_spdy_framer_decoder = false;
195 FLAGS_use_http2_frame_decoder_adapter = true;
196 // Http2FrameDecoderAdapter needs the new header methods, else
197 // --use_http2_frame_decoder_adapter=true will be ignored.
198 FLAGS_spdy_framer_use_new_methods2 = true;
199 break;
200 }
201 switch (hpack_decoder) {
202 case HPACK_DECODER_SPDY:
203 FLAGS_spdy_use_hpack_decoder2 = false;
204 break;
205 case HPACK_DECODER_NEW:
206 FLAGS_spdy_use_hpack_decoder2 = true;
207 // Needs new header methods to be used.
208 FLAGS_spdy_framer_use_new_methods2 = true;
209 break;
210 }
211 FLAGS_quic_supports_push_promise = true;
212 FLAGS_quic_always_log_bugs_for_tests = true;
213 VLOG(1) << "TestParams: version: " << QuicVersionToString(version)
214 << ", perspective: " << perspective
215 << ", http2_decoder: " << http2_decoder
216 << ", hpack_decoder: " << hpack_decoder;
217 }
218
219 QuicVersion version;
220 Perspective perspective;
221 Http2DecoderChoice http2_decoder;
222 HpackDecoderChoice hpack_decoder;
223 };
224
225 class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> {
226 public:
227 // Constructing the test_params_ object will set the necessary flags before
228 // the MockQuicConnection is constructed, which we need because the latter
229 // will construct a SpdyFramer that will use those flags to decide whether
230 // to construct a decoder adapter.
231 QuicHeadersStreamTest()
232 : test_params_(GetParam()),
233 connection_(new StrictMock<MockQuicConnection>(&helper_,
234 &alarm_factory_,
235 perspective(),
236 GetVersion())),
237 session_(connection_),
238 headers_stream_(QuicSpdySessionPeer::GetHeadersStream(&session_)),
239 body_("hello world"),
240 hpack_encoder_visitor_(new StrictMock<MockHpackDebugVisitor>),
241 hpack_decoder_visitor_(new StrictMock<MockHpackDebugVisitor>),
242 stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, ""),
243 next_promised_stream_id_(2) {
244 headers_[":version"] = "HTTP/1.1";
245 headers_[":status"] = "200 Ok";
246 headers_["content-length"] = "11";
247 framer_ = std::unique_ptr<SpdyFramer>(new SpdyFramer(HTTP2));
248 framer_->set_visitor(&visitor_);
249 EXPECT_EQ(version(), session_.connection()->version());
250 EXPECT_TRUE(headers_stream_ != nullptr);
251 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
252 }
253
254 QuicConsumedData SaveIov(const QuicIOVector& data) {
255 const iovec* iov = data.iov;
256 int count = data.iov_count;
257 int consumed = 0;
258 for (int i = 0; i < count; ++i) {
259 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
260 consumed += iov[i].iov_len;
261 }
262 return QuicConsumedData(consumed, false);
263 }
264
265 QuicConsumedData SaveIovAndNotifyAckListener(
266 const QuicIOVector& data,
267 QuicAckListenerInterface* ack_listener) {
268 QuicConsumedData result = SaveIov(data);
269 if (ack_listener) {
270 ack_listener->OnPacketAcked(result.bytes_consumed,
271 QuicTime::Delta::Zero());
272 }
273 return result;
274 }
275
276 void SavePayload(const char* data, size_t len) {
277 saved_payloads_.append(data, len);
278 }
279
280 bool SaveHeaderData(const char* data, int len) {
281 saved_header_data_.append(data, len);
282 return true;
283 }
284
285 void SaveHeaderDataStringPiece(StringPiece data) {
286 saved_header_data_.append(data.data(), data.length());
287 }
288
289 void SavePromiseHeaderList(QuicStreamId /* stream_id */,
290 QuicStreamId /* promised_stream_id */,
291 size_t size,
292 const QuicHeaderList& header_list) {
293 SaveToHandler(size, header_list);
294 }
295
296 void SaveHeaderList(QuicStreamId /* stream_id */,
297 bool /* fin */,
298 size_t size,
299 const QuicHeaderList& header_list) {
300 SaveToHandler(size, header_list);
301 }
302
303 void SaveToHandler(size_t size, const QuicHeaderList& header_list) {
304 headers_handler_.reset(new TestHeadersHandler);
305 headers_handler_->OnHeaderBlockStart();
306 for (const auto& p : header_list) {
307 headers_handler_->OnHeader(p.first, p.second);
308 }
309 headers_handler_->OnHeaderBlockEnd(size);
310 }
311
312 void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
313 bool fin,
314 SpdyPriority priority) {
315 WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
316 }
317
318 void WriteHeadersAndExpectSynReply(QuicStreamId stream_id, bool fin) {
319 WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
320 }
321
322 void WriteHeadersAndCheckData(QuicStreamId stream_id,
323 bool fin,
324 SpdyPriority priority,
325 SpdyFrameType type) {
326 // Write the headers and capture the outgoing data
327 EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _,
328 false, nullptr))
329 .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
330 headers_stream_->WriteHeaders(stream_id, headers_.Clone(), fin, priority,
331 nullptr);
332
333 // Parse the outgoing data and check that it matches was was written.
334 if (type == SYN_STREAM) {
335 EXPECT_CALL(visitor_,
336 OnHeaders(stream_id, kHasPriority,
337 Spdy3PriorityToHttp2Weight(priority),
338 /*parent_stream_id=*/0,
339 /*exclusive=*/false, fin, kFrameComplete));
340 } else {
341 EXPECT_CALL(visitor_,
342 OnHeaders(stream_id, !kHasPriority,
343 /*priority=*/0,
344 /*parent_stream_id=*/0,
345 /*exclusive=*/false, fin, kFrameComplete));
346 }
347 headers_handler_.reset(new TestHeadersHandler);
348 EXPECT_CALL(visitor_, OnHeaderFrameStart(stream_id))
349 .WillOnce(Return(headers_handler_.get()));
350 EXPECT_CALL(visitor_, OnHeaderFrameEnd(stream_id, true)).Times(1);
351 if (fin) {
352 EXPECT_CALL(visitor_, OnStreamEnd(stream_id));
353 }
354 framer_->ProcessInput(saved_data_.data(), saved_data_.length());
355 EXPECT_FALSE(framer_->HasError())
356 << SpdyFramer::ErrorCodeToString(framer_->error_code());
357
358 CheckHeaders();
359 saved_data_.clear();
360 }
361
362 void CheckHeaders() {
363 EXPECT_EQ(headers_, headers_handler_->decoded_block());
364 headers_handler_.reset();
365 }
366
367 Perspective perspective() const { return test_params_.perspective; }
368
369 QuicVersion version() const { return test_params_.version; }
370
371 QuicVersionVector GetVersion() {
372 QuicVersionVector versions;
373 versions.push_back(version());
374 return versions;
375 }
376
377 void TearDownLocalConnectionState() {
378 QuicConnectionPeer::TearDownLocalConnectionState(connection_);
379 }
380
381 QuicStreamId NextPromisedStreamId() { return next_promised_stream_id_ += 2; }
382
383 static const bool kFrameComplete = true;
384 static const bool kHasPriority = true;
385
386 const TestParams test_params_;
387 MockQuicConnectionHelper helper_;
388 MockAlarmFactory alarm_factory_;
389 StrictMock<MockQuicConnection>* connection_;
390 StrictMock<MockQuicSpdySession> session_;
391 QuicHeadersStream* headers_stream_;
392 SpdyHeaderBlock headers_;
393 std::unique_ptr<TestHeadersHandler> headers_handler_;
394 string body_;
395 string saved_data_;
396 string saved_header_data_;
397 string saved_payloads_;
398 std::unique_ptr<SpdyFramer> framer_;
399 StrictMock<MockVisitor> visitor_;
400 std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_encoder_visitor_;
401 std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_decoder_visitor_;
402 QuicStreamFrame stream_frame_;
403 QuicStreamId next_promised_stream_id_;
404 };
405
406 // Run all tests with each version, perspective (client or server),
407 // HTTP/2 and HPACK decoder.
408 INSTANTIATE_TEST_CASE_P(
409 Tests,
410 QuicHeadersStreamTest,
411 ::testing::Combine(
412 ::testing::ValuesIn(QuicSupportedVersions()),
413 ::testing::Values(Perspective::IS_CLIENT, Perspective::IS_SERVER),
414 ::testing::Values(HTTP2_DECODER_SPDY,
415 HTTP2_DECODER_NESTED_SPDY,
416 HTTP2_DECODER_NEW),
417 ::testing::Values(HPACK_DECODER_SPDY, HPACK_DECODER_NEW)));
418
419 TEST_P(QuicHeadersStreamTest, StreamId) {
420 EXPECT_EQ(3u, headers_stream_->id());
421 }
422
423 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
424 for (QuicStreamId stream_id = kClientDataStreamId1;
425 stream_id < kClientDataStreamId3; stream_id += 2) {
426 for (bool fin : kFins) {
427 if (perspective() == Perspective::IS_SERVER) {
428 WriteHeadersAndExpectSynReply(stream_id, fin);
429 } else {
430 for (SpdyPriority priority = 0; priority < 7; ++priority) {
431 // TODO(rch): implement priorities correctly.
432 WriteHeadersAndExpectSynStream(stream_id, fin, 0);
433 }
434 }
435 }
436 }
437 }
438
439 TEST_P(QuicHeadersStreamTest, WritePushPromises) {
440 for (QuicStreamId stream_id = kClientDataStreamId1;
441 stream_id < kClientDataStreamId3; stream_id += 2) {
442 QuicStreamId promised_stream_id = NextPromisedStreamId();
443 if (perspective() == Perspective::IS_SERVER) {
444 // Write the headers and capture the outgoing data
445 EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _,
446 false, nullptr))
447 .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
448 headers_stream_->WritePushPromise(stream_id, promised_stream_id,
449 headers_.Clone(), nullptr);
450
451 // Parse the outgoing data and check that it matches was was written.
452 EXPECT_CALL(visitor_,
453 OnPushPromise(stream_id, promised_stream_id, kFrameComplete));
454 headers_handler_.reset(new TestHeadersHandler);
455 EXPECT_CALL(visitor_, OnHeaderFrameStart(stream_id))
456 .WillOnce(Return(headers_handler_.get()));
457 EXPECT_CALL(visitor_, OnHeaderFrameEnd(stream_id, true)).Times(1);
458 framer_->ProcessInput(saved_data_.data(), saved_data_.length());
459 EXPECT_FALSE(framer_->HasError())
460 << SpdyFramer::ErrorCodeToString(framer_->error_code());
461 CheckHeaders();
462 saved_data_.clear();
463 } else {
464 EXPECT_DFATAL(
465 headers_stream_->WritePushPromise(stream_id, promised_stream_id,
466 headers_.Clone(), nullptr),
467 "Client shouldn't send PUSH_PROMISE");
468 }
469 }
470 }
471
472 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
473 for (QuicStreamId stream_id = kClientDataStreamId1;
474 stream_id < kClientDataStreamId3; stream_id += 2) {
475 for (bool fin : {false, true}) {
476 for (SpdyPriority priority = 0; priority < 7; ++priority) {
477 // Replace with "WriteHeadersAndSaveData"
478 SpdySerializedFrame frame;
479 if (perspective() == Perspective::IS_SERVER) {
480 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
481 headers_frame.set_fin(fin);
482 headers_frame.set_has_priority(true);
483 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
484 frame = framer_->SerializeFrame(headers_frame);
485 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
486 } else {
487 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
488 headers_frame.set_fin(fin);
489 frame = framer_->SerializeFrame(headers_frame);
490 }
491 EXPECT_CALL(session_,
492 OnStreamHeaderList(stream_id, fin, frame.size(), _))
493 .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
494 stream_frame_.data_buffer = frame.data();
495 stream_frame_.data_length = frame.size();
496 headers_stream_->OnStreamFrame(stream_frame_);
497 stream_frame_.offset += frame.size();
498 CheckHeaders();
499 }
500 }
501 }
502 }
503
504 TEST_P(QuicHeadersStreamTest, ProcessPushPromise) {
505 if (perspective() == Perspective::IS_SERVER)
506 return;
507 for (QuicStreamId stream_id = kClientDataStreamId1;
508 stream_id < kClientDataStreamId3; stream_id += 2) {
509 QuicStreamId promised_stream_id = NextPromisedStreamId();
510 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id,
511 headers_.Clone());
512 SpdySerializedFrame frame(framer_->SerializeFrame(push_promise));
513 if (perspective() == Perspective::IS_SERVER) {
514 EXPECT_CALL(*connection_,
515 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
516 "PUSH_PROMISE not supported.", _))
517 .WillRepeatedly(InvokeWithoutArgs(
518 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
519 } else {
520 EXPECT_CALL(session_, OnPromiseHeaderList(stream_id, promised_stream_id,
521 frame.size(), _))
522 .WillOnce(
523 Invoke(this, &QuicHeadersStreamTest::SavePromiseHeaderList));
524 }
525 stream_frame_.data_buffer = frame.data();
526 stream_frame_.data_length = frame.size();
527 headers_stream_->OnStreamFrame(stream_frame_);
528 if (perspective() == Perspective::IS_CLIENT) {
529 stream_frame_.offset += frame.size();
530 CheckHeaders();
531 }
532 }
533 }
534
535 TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) {
536 if (!FLAGS_quic_measure_headers_hol_blocking_time) {
537 return;
538 }
539 EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(0);
540 testing::InSequence seq;
541 bool fin = true;
542 for (int stream_num = 0; stream_num < 10; stream_num++) {
543 QuicStreamId stream_id = QuicClientDataStreamId(stream_num);
544 // Replace with "WriteHeadersAndSaveData"
545 SpdySerializedFrame frame;
546 if (perspective() == Perspective::IS_SERVER) {
547 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
548 headers_frame.set_fin(fin);
549 headers_frame.set_has_priority(true);
550 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
551 frame = framer_->SerializeFrame(headers_frame);
552 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
553 } else {
554 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
555 headers_frame.set_fin(fin);
556 frame = framer_->SerializeFrame(headers_frame);
557 }
558 EXPECT_CALL(session_, OnStreamHeaderList(stream_id, fin, frame.size(), _))
559 .Times(1);
560 stream_frame_.data_buffer = frame.data();
561 stream_frame_.data_length = frame.size();
562 headers_stream_->OnStreamFrame(stream_frame_);
563 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
564 stream_frame_.offset += frame.size();
565 }
566 }
567
568 TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) {
569 QuicStreamId stream_id;
570 bool fin = true;
571 QuicStreamFrame stream_frames[10];
572 SpdySerializedFrame frames[10];
573 // First create all the frames in order
574 {
575 InSequence seq;
576 for (int stream_num = 0; stream_num < 10; ++stream_num) {
577 stream_id = QuicClientDataStreamId(stream_num);
578 if (perspective() == Perspective::IS_SERVER) {
579 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
580 headers_frame.set_fin(fin);
581 headers_frame.set_has_priority(true);
582 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
583 frames[stream_num] = framer_->SerializeFrame(headers_frame);
584 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)).Times(1);
585 } else {
586 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
587 headers_frame.set_fin(fin);
588 frames[stream_num] = framer_->SerializeFrame(headers_frame);
589 }
590 stream_frames[stream_num].stream_id = stream_frame_.stream_id;
591 stream_frames[stream_num].offset = stream_frame_.offset;
592 stream_frames[stream_num].data_buffer = frames[stream_num].data();
593 stream_frames[stream_num].data_length = frames[stream_num].size();
594 DVLOG(1) << "make frame for stream " << stream_num << " offset "
595 << stream_frames[stream_num].offset;
596 stream_frame_.offset += frames[stream_num].size();
597 EXPECT_CALL(session_, OnStreamHeaderList(stream_id, fin, _, _)).Times(1);
598 }
599 }
600
601 // Actually writing the frames in reverse order will cause HOL blocking.
602 EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(9);
603
604 for (int stream_num = 9; stream_num >= 0; --stream_num) {
605 DVLOG(1) << "OnStreamFrame for stream " << stream_num << " offset "
606 << stream_frames[stream_num].offset;
607 headers_stream_->OnStreamFrame(stream_frames[stream_num]);
608 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
609 }
610 }
611
612 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
613 // We want to create a frame that is more than the SPDY Framer's max control
614 // frame size, which is 16K, but less than the HPACK decoders max decode
615 // buffer size, which is 32K.
616 headers_["key0"] = string(1 << 13, '.');
617 headers_["key1"] = string(1 << 13, '.');
618 headers_["key2"] = string(1 << 13, '.');
619 for (QuicStreamId stream_id = kClientDataStreamId1;
620 stream_id < kClientDataStreamId3; stream_id += 2) {
621 for (bool fin : {false, true}) {
622 for (SpdyPriority priority = 0; priority < 7; ++priority) {
623 // Replace with "WriteHeadersAndSaveData"
624 SpdySerializedFrame frame;
625 if (perspective() == Perspective::IS_SERVER) {
626 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
627 headers_frame.set_fin(fin);
628 headers_frame.set_has_priority(true);
629 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
630 frame = framer_->SerializeFrame(headers_frame);
631 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
632 } else {
633 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
634 headers_frame.set_fin(fin);
635 frame = framer_->SerializeFrame(headers_frame);
636 }
637 EXPECT_CALL(session_,
638 OnStreamHeaderList(stream_id, fin, frame.size(), _))
639 .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
640 stream_frame_.data_buffer = frame.data();
641 stream_frame_.data_length = frame.size();
642 headers_stream_->OnStreamFrame(stream_frame_);
643 stream_frame_.offset += frame.size();
644 CheckHeaders();
645 }
646 }
647 }
648 }
649
650 TEST_P(QuicHeadersStreamTest, ProcessBadData) {
651 const char kBadData[] = "blah blah blah";
652 EXPECT_CALL(*connection_,
653 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
654 .Times(::testing::AnyNumber());
655 stream_frame_.data_buffer = kBadData;
656 stream_frame_.data_length = strlen(kBadData);
657 headers_stream_->OnStreamFrame(stream_frame_);
658 }
659
660 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
661 SpdyDataIR data(2, "ping");
662 SpdySerializedFrame frame(framer_->SerializeFrame(data));
663
664 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
665 "SPDY DATA frame received.", _))
666 .WillOnce(InvokeWithoutArgs(
667 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
668 stream_frame_.data_buffer = frame.data();
669 stream_frame_.data_length = frame.size();
670 headers_stream_->OnStreamFrame(stream_frame_);
671 }
672
673 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrameForceHolBlocking) {
674 if (version() <= QUIC_VERSION_35) {
675 return;
676 }
677 QuicSpdySessionPeer::SetForceHolBlocking(&session_, true);
678 SpdyDataIR data(2, "ping");
679 SpdySerializedFrame frame(framer_->SerializeFrame(data));
680 EXPECT_CALL(session_, OnStreamFrameData(2, _, 4, false));
681 stream_frame_.data_buffer = frame.data();
682 stream_frame_.data_length = frame.size();
683 headers_stream_->OnStreamFrame(stream_frame_);
684 }
685
686 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrameEmptyWithFin) {
687 if (version() <= QUIC_VERSION_35) {
688 return;
689 }
690 QuicSpdySessionPeer::SetForceHolBlocking(&session_, true);
691 SpdyDataIR data(2, "");
692 data.set_fin(true);
693 SpdySerializedFrame frame(framer_->SerializeFrame(data));
694 EXPECT_CALL(session_, OnStreamFrameData(2, _, 0, true));
695 stream_frame_.data_buffer = frame.data();
696 stream_frame_.data_length = frame.size();
697 headers_stream_->OnStreamFrame(stream_frame_);
698 }
699
700 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
701 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR);
702 SpdySerializedFrame frame(framer_->SerializeFrame(data));
703 EXPECT_CALL(*connection_,
704 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
705 "SPDY RST_STREAM frame received.", _))
706 .WillOnce(InvokeWithoutArgs(
707 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
708 stream_frame_.data_buffer = frame.data();
709 stream_frame_.data_length = frame.size();
710 headers_stream_->OnStreamFrame(stream_frame_);
711 }
712
713 TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
714 FLAGS_quic_respect_http2_settings_frame = false;
715 SpdySettingsIR data;
716 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, 0);
717 SpdySerializedFrame frame(framer_->SerializeFrame(data));
718 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
719 "SPDY SETTINGS frame received.", _))
720 .WillOnce(InvokeWithoutArgs(
721 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
722 stream_frame_.data_buffer = frame.data();
723 stream_frame_.data_length = frame.size();
724 headers_stream_->OnStreamFrame(stream_frame_);
725 }
726
727 TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameSupportedFields) {
728 FLAGS_quic_respect_http2_settings_frame = true;
729 const uint32_t kTestHeaderTableSize = 1000;
730 SpdySettingsIR data;
731 // Respect supported settings frames SETTINGS_HEADER_TABLE_SIZE.
732 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, kTestHeaderTableSize);
733 SpdySerializedFrame frame(framer_->SerializeFrame(data));
734 stream_frame_.data_buffer = frame.data();
735 stream_frame_.data_length = frame.size();
736 headers_stream_->OnStreamFrame(stream_frame_);
737 EXPECT_EQ(kTestHeaderTableSize,
738 QuicHeadersStreamPeer::GetSpdyFramer(headers_stream_)
739 .header_encoder_table_size());
740 }
741
742 TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
743 FLAGS_quic_respect_http2_settings_frame = true;
744 SpdySettingsIR data;
745 // Does not support SETTINGS_MAX_HEADER_LIST_SIZE,
746 // SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_INITIAL_WINDOW_SIZE,
747 // SETTINGS_ENABLE_PUSH and SETTINGS_MAX_FRAME_SIZE.
748 data.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, true, true, 2000);
749 data.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, true, true, 100);
750 data.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, true, true, 100);
751 data.AddSetting(SETTINGS_ENABLE_PUSH, true, true, 1);
752 data.AddSetting(SETTINGS_MAX_FRAME_SIZE, true, true, 1250);
753 SpdySerializedFrame frame(framer_->SerializeFrame(data));
754 EXPECT_CALL(
755 *connection_,
756 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
757 "Unsupported field of HTTP/2 SETTINGS frame: " +
758 base::IntToString(SETTINGS_MAX_HEADER_LIST_SIZE),
759 _));
760 EXPECT_CALL(
761 *connection_,
762 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
763 "Unsupported field of HTTP/2 SETTINGS frame: " +
764 base::IntToString(SETTINGS_MAX_CONCURRENT_STREAMS),
765 _));
766 EXPECT_CALL(
767 *connection_,
768 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
769 "Unsupported field of HTTP/2 SETTINGS frame: " +
770 base::IntToString(SETTINGS_INITIAL_WINDOW_SIZE),
771 _));
772 EXPECT_CALL(*connection_,
773 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
774 "Unsupported field of HTTP/2 SETTINGS frame: " +
775 base::IntToString(SETTINGS_ENABLE_PUSH),
776 _));
777 EXPECT_CALL(*connection_,
778 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
779 "Unsupported field of HTTP/2 SETTINGS frame: " +
780 base::IntToString(SETTINGS_MAX_FRAME_SIZE),
781 _));
782 stream_frame_.data_buffer = frame.data();
783 stream_frame_.data_length = frame.size();
784 headers_stream_->OnStreamFrame(stream_frame_);
785 }
786
787 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
788 SpdyPingIR data(1);
789 SpdySerializedFrame frame(framer_->SerializeFrame(data));
790 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
791 "SPDY PING frame received.", _))
792 .WillOnce(InvokeWithoutArgs(
793 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
794 stream_frame_.data_buffer = frame.data();
795 stream_frame_.data_length = frame.size();
796 headers_stream_->OnStreamFrame(stream_frame_);
797 }
798
799 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
800 SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
801 SpdySerializedFrame frame(framer_->SerializeFrame(data));
802 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
803 "SPDY GOAWAY frame received.", _))
804 .WillOnce(InvokeWithoutArgs(
805 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
806 stream_frame_.data_buffer = frame.data();
807 stream_frame_.data_length = frame.size();
808 headers_stream_->OnStreamFrame(stream_frame_);
809 }
810
811 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
812 SpdyWindowUpdateIR data(1, 1);
813 SpdySerializedFrame frame(framer_->SerializeFrame(data));
814 EXPECT_CALL(*connection_,
815 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
816 "SPDY WINDOW_UPDATE frame received.", _))
817 .WillOnce(InvokeWithoutArgs(
818 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
819 stream_frame_.data_buffer = frame.data();
820 stream_frame_.data_length = frame.size();
821 headers_stream_->OnStreamFrame(stream_frame_);
822 }
823
824 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
825 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
826 headers_stream_));
827 }
828
829 TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) {
830 if (FLAGS_use_nested_spdy_framer_decoder)
831 return;
832
833 StrictMock<MockHpackDebugVisitor>* hpack_decoder_visitor =
834 hpack_decoder_visitor_.get();
835 headers_stream_->SetHpackDecoderDebugVisitor(
836 std::move(hpack_decoder_visitor_));
837
838 // Create some headers we expect to generate entries in HPACK's
839 // dynamic table, in addition to content-length.
840 headers_["key0"] = string(1 << 1, '.');
841 headers_["key1"] = string(1 << 2, '.');
842 headers_["key2"] = string(1 << 3, '.');
843 {
844 testing::InSequence seq;
845 // Number of indexed representations generated in headers below.
846 for (int i = 1; i < 28; i++) {
847 EXPECT_CALL(*hpack_decoder_visitor,
848 OnUseEntry(QuicTime::Delta::FromMilliseconds(i)))
849 .Times(4);
850 }
851 }
852 for (QuicStreamId stream_id = kClientDataStreamId1;
853 stream_id < kClientDataStreamId3; stream_id += 2) {
854 for (bool fin : {false, true}) {
855 for (SpdyPriority priority = 0; priority < 7; ++priority) {
856 // Replace with "WriteHeadersAndSaveData"
857 SpdySerializedFrame frame;
858 if (perspective() == Perspective::IS_SERVER) {
859 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
860 headers_frame.set_fin(fin);
861 headers_frame.set_has_priority(true);
862 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
863 frame = framer_->SerializeFrame(headers_frame);
864 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
865 } else {
866 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
867 headers_frame.set_fin(fin);
868 frame = framer_->SerializeFrame(headers_frame);
869 }
870 EXPECT_CALL(session_,
871 OnStreamHeaderList(stream_id, fin, frame.size(), _))
872 .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
873 stream_frame_.data_buffer = frame.data();
874 stream_frame_.data_length = frame.size();
875 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
876 headers_stream_->OnStreamFrame(stream_frame_);
877 stream_frame_.offset += frame.size();
878 CheckHeaders();
879 }
880 }
881 }
882 }
883
884 TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) {
885 StrictMock<MockHpackDebugVisitor>* hpack_encoder_visitor =
886 hpack_encoder_visitor_.get();
887 headers_stream_->SetHpackEncoderDebugVisitor(
888 std::move(hpack_encoder_visitor_));
889
890 if (perspective() == Perspective::IS_SERVER) {
891 testing::InSequence seq;
892 for (int i = 1; i < 4; i++) {
893 EXPECT_CALL(*hpack_encoder_visitor,
894 OnUseEntry(QuicTime::Delta::FromMilliseconds(i)));
895 }
896 } else {
897 testing::InSequence seq;
898 for (int i = 1; i < 28; i++) {
899 EXPECT_CALL(*hpack_encoder_visitor,
900 OnUseEntry(QuicTime::Delta::FromMilliseconds(i)));
901 }
902 }
903 for (QuicStreamId stream_id = kClientDataStreamId1;
904 stream_id < kClientDataStreamId3; stream_id += 2) {
905 for (bool fin : {false, true}) {
906 if (perspective() == Perspective::IS_SERVER) {
907 WriteHeadersAndExpectSynReply(stream_id, fin);
908 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
909 } else {
910 for (SpdyPriority priority = 0; priority < 7; ++priority) {
911 // TODO(rch): implement priorities correctly.
912 WriteHeadersAndExpectSynStream(stream_id, fin, 0);
913 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
914 }
915 }
916 }
917 }
918 }
919
920 TEST_P(QuicHeadersStreamTest, WritevStreamData) {
921 QuicStreamId id = kClientDataStreamId1;
922 QuicStreamOffset offset = 0;
923 struct iovec iov;
924 string data;
925
926 // This test will issue a write that will require fragmenting into
927 // multiple HTTP/2 DATA frames.
928 const int kMinDataFrames = 4;
929 const size_t data_len =
930 kSpdyInitialFrameSizeLimit * kMinDataFrames + 1024;
931 // Set headers stream send window large enough for data written below.
932 headers_stream_->flow_controller()->UpdateSendWindowOffset(data_len * 2 * 4);
933 test::GenerateBody(&data, data_len);
934
935 for (bool fin : {true, false}) {
936 for (bool use_ack_listener : {true, false}) {
937 scoped_refptr<ForceHolAckListener> ack_listener;
938 if (use_ack_listener) {
939 ack_listener = new ForceHolAckListener();
940 }
941 EXPECT_CALL(session_,
942 WritevData(headers_stream_, kHeadersStreamId, _, _, false, _))
943 .WillRepeatedly(WithArgs<2, 5>(Invoke(
944 this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener)));
945
946 QuicConsumedData consumed_data = headers_stream_->WritevStreamData(
947 id, MakeIOVector(data, &iov), offset, fin, ack_listener.get());
948
949 EXPECT_EQ(consumed_data.bytes_consumed, data_len);
950 EXPECT_EQ(consumed_data.fin_consumed, fin);
951 // Now process the written data with the SPDY framer, and verify
952 // that the original data is unchanged.
953 EXPECT_CALL(visitor_, OnDataFrameHeader(id, _, _))
954 .Times(AtLeast(kMinDataFrames));
955 EXPECT_CALL(visitor_, OnStreamFrameData(id, _, _))
956 .WillRepeatedly(WithArgs<1, 2>(
957 Invoke(this, &QuicHeadersStreamTest::SavePayload)));
958 if (fin) {
959 EXPECT_CALL(visitor_, OnStreamEnd(id));
960 }
961 framer_->ProcessInput(saved_data_.data(), saved_data_.length());
962 EXPECT_EQ(saved_payloads_, data);
963
964 if (use_ack_listener) {
965 // Notice, acked bytes doesn't include extra bytes used by
966 // HTTP/2 DATA frame headers.
967 EXPECT_EQ(ack_listener->total_acked_bytes(), data_len);
968 }
969 saved_data_.clear();
970 saved_payloads_.clear();
971 }
972 }
973 }
974
975 } // namespace
976 } // namespace test
977 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_headers_stream.cc ('k') | net/quic/quic_http_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698