1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "net/spdy/spdy_stream.h"
11
12 #include <stdint.h>
13
14 #include <algorithm>
15 #include <cstddef>
16 #include <limits>
17 #include <memory>
18 #include <string>
19 #include <string_view>
20 #include <utility>
21 #include <vector>
22
23 #include "base/functional/bind.h"
24 #include "base/memory/ref_counted.h"
25 #include "base/run_loop.h"
26 #include "base/time/time.h"
27 #include "net/base/request_priority.h"
28 #include "net/base/session_usage.h"
29 #include "net/dns/public/secure_dns_policy.h"
30 #include "net/http/http_request_info.h"
31 #include "net/log/net_log_event_type.h"
32 #include "net/log/test_net_log.h"
33 #include "net/log/test_net_log_util.h"
34 #include "net/socket/socket_tag.h"
35 #include "net/socket/socket_test_util.h"
36 #include "net/spdy/buffered_spdy_framer.h"
37 #include "net/spdy/spdy_http_utils.h"
38 #include "net/spdy/spdy_session.h"
39 #include "net/spdy/spdy_session_pool.h"
40 #include "net/spdy/spdy_stream_test_util.h"
41 #include "net/spdy/spdy_test_util_common.h"
42 #include "net/test/cert_test_util.h"
43 #include "net/test/gtest_util.h"
44 #include "net/test/test_data_directory.h"
45 #include "net/test/test_with_task_environment.h"
46 #include "net/third_party/quiche/src/quiche/common/http/http_header_block.h"
47 #include "net/third_party/quiche/src/quiche/http2/core/spdy_protocol.h"
48 #include "testing/gmock/include/gmock/gmock.h"
49 #include "testing/gtest/include/gtest/gtest.h"
50
51 // TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
52 //
53 namespace net::test {
54
55 namespace {
56
57 const char kPostBody[] = "\0hello!\xff";
58 const size_t kPostBodyLength = std::size(kPostBody);
59 const std::string_view kPostBodyStringPiece(kPostBody, kPostBodyLength);
60
61 // Creates a MockRead from the given serialized frame except for the last byte.
ReadFrameExceptForLastByte(const spdy::SpdySerializedFrame & frame)62 MockRead ReadFrameExceptForLastByte(const spdy::SpdySerializedFrame& frame) {
63 CHECK_GE(frame.size(), 2u);
64 return MockRead(ASYNC, frame.data(), frame.size() - 1);
65 }
66
67 // Creates a MockRead from the last byte of the given serialized frame.
LastByteOfReadFrame(const spdy::SpdySerializedFrame & frame)68 MockRead LastByteOfReadFrame(const spdy::SpdySerializedFrame& frame) {
69 CHECK_GE(frame.size(), 2u);
70 return MockRead(ASYNC, frame.data() + frame.size() - 1, 1);
71 }
72
73 } // namespace
74
75 class SpdyStreamTest : public ::testing::Test, public WithTaskEnvironment {
76 protected:
77 // A function that takes a SpdyStream and the number of bytes which
78 // will unstall the next frame completely.
79 typedef base::OnceCallback<void(const base::WeakPtr<SpdyStream>&, int32_t)>
80 UnstallFunction;
81
SpdyStreamTest(base::test::TaskEnvironment::TimeSource time_source=base::test::TaskEnvironment::TimeSource::DEFAULT)82 explicit SpdyStreamTest(base::test::TaskEnvironment::TimeSource time_source =
83 base::test::TaskEnvironment::TimeSource::DEFAULT)
84 : WithTaskEnvironment(time_source),
85 url_(kDefaultUrl),
86 session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)),
87 ssl_(SYNCHRONOUS, OK) {}
88
89 ~SpdyStreamTest() override = default;
90
CreateDefaultSpdySession()91 base::WeakPtr<SpdySession> CreateDefaultSpdySession() {
92 SpdySessionKey key(HostPortPair::FromURL(url_), PRIVACY_MODE_DISABLED,
93 ProxyChain::Direct(), SessionUsage::kDestination,
94 SocketTag(), NetworkAnonymizationKey(),
95 SecureDnsPolicy::kAllow,
96 /*disable_cert_verification_network_fetches=*/false);
97 return CreateSpdySession(session_.get(), key, NetLogWithSource());
98 }
99
TearDown()100 void TearDown() override { base::RunLoop().RunUntilIdle(); }
101
102 void RunResumeAfterUnstallRequestResponseTest(
103 UnstallFunction unstall_function);
104
105 void RunResumeAfterUnstallBidirectionalTest(UnstallFunction unstall_function);
106
107 // Add{Read,Write}() populates lists that are eventually passed to a
108 // SocketData class. |frame| must live for the whole test.
109
AddRead(const spdy::SpdySerializedFrame & frame)110 void AddRead(const spdy::SpdySerializedFrame& frame) {
111 reads_.push_back(CreateMockRead(frame, offset_++));
112 }
113
AddWrite(const spdy::SpdySerializedFrame & frame)114 void AddWrite(const spdy::SpdySerializedFrame& frame) {
115 writes_.push_back(CreateMockWrite(frame, offset_++));
116 }
117
AddMockRead(MockRead read)118 void AddMockRead(MockRead read) {
119 read.sequence_number = offset_++;
120 reads_.push_back(std::move(read));
121 }
122
AddReadEOF()123 void AddReadEOF() { reads_.emplace_back(ASYNC, 0, offset_++); }
124
AddWritePause()125 void AddWritePause() {
126 writes_.emplace_back(ASYNC, ERR_IO_PENDING, offset_++);
127 }
128
AddReadPause()129 void AddReadPause() { reads_.emplace_back(ASYNC, ERR_IO_PENDING, offset_++); }
130
GetReads()131 base::span<const MockRead> GetReads() { return reads_; }
GetWrites()132 base::span<const MockWrite> GetWrites() { return writes_; }
133
ActivatePushStream(SpdySession * session,SpdyStream * stream)134 void ActivatePushStream(SpdySession* session, SpdyStream* stream) {
135 std::unique_ptr<SpdyStream> activated =
136 session->ActivateCreatedStream(stream);
137 activated->set_stream_id(2);
138 session->InsertActivatedStream(std::move(activated));
139 }
140
AddSSLSocketData()141 void AddSSLSocketData() {
142 // Load a cert that is valid for
143 // www.example.org, mail.example.org, and mail.example.com.
144 ssl_.ssl_info.cert =
145 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
146 ASSERT_TRUE(ssl_.ssl_info.cert);
147 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
148 }
149
unacked_recv_window_bytes(base::WeakPtr<SpdyStream> stream)150 int32_t unacked_recv_window_bytes(base::WeakPtr<SpdyStream> stream) {
151 return stream->unacked_recv_window_bytes_;
152 }
153
spdy_session_pool(base::WeakPtr<SpdySession> session)154 static SpdySessionPool* spdy_session_pool(
155 base::WeakPtr<SpdySession> session) {
156 return session->pool_;
157 }
158
159 const GURL url_;
160 SpdyTestUtil spdy_util_;
161 SpdySessionDependencies session_deps_;
162 std::unique_ptr<HttpNetworkSession> session_;
163
164 private:
165 // Used by Add{Read,Write}() above.
166 std::vector<MockWrite> writes_;
167 std::vector<MockRead> reads_;
168 int offset_ = 0;
169 SSLSocketDataProvider ssl_;
170 };
171
TEST_F(SpdyStreamTest,SendDataAfterOpen)172 TEST_F(SpdyStreamTest, SendDataAfterOpen) {
173 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
174 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
175 AddWrite(req);
176
177 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
178 AddRead(resp);
179
180 spdy::SpdySerializedFrame msg(
181 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
182 AddWrite(msg);
183
184 spdy::SpdySerializedFrame echo(
185 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
186 AddRead(echo);
187
188 AddReadEOF();
189
190 SequencedSocketData data(GetReads(), GetWrites());
191 MockConnect connect_data(SYNCHRONOUS, OK);
192 data.set_connect_data(connect_data);
193 session_deps_.socket_factory->AddSocketDataProvider(&data);
194
195 AddSSLSocketData();
196
197 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
198
199 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
200 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
201 ASSERT_TRUE(stream);
202 EXPECT_EQ(kDefaultUrl, stream->url().spec());
203
204 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
205 stream->SetDelegate(&delegate);
206
207 quiche::HttpHeaderBlock headers(
208 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
209 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
210 IsError(ERR_IO_PENDING));
211
212 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
213
214 EXPECT_TRUE(delegate.send_headers_completed());
215 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
216 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
217 delegate.TakeReceivedData());
218 EXPECT_TRUE(data.AllWriteDataConsumed());
219 }
220
TEST_F(SpdyStreamTest,BrokenConnectionDetectionSuccessfulRequest)221 TEST_F(SpdyStreamTest, BrokenConnectionDetectionSuccessfulRequest) {
222 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
223 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
224 AddWrite(req);
225
226 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
227 AddRead(resp);
228
229 spdy::SpdySerializedFrame msg(
230 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
231 AddWrite(msg);
232
233 spdy::SpdySerializedFrame echo(
234 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
235 AddRead(echo);
236
237 AddReadPause();
238 AddReadEOF();
239
240 SequencedSocketData data(GetReads(), GetWrites());
241 MockConnect connect_data(SYNCHRONOUS, OK);
242 data.set_connect_data(connect_data);
243 session_deps_.socket_factory->AddSocketDataProvider(&data);
244
245 AddSSLSocketData();
246
247 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
248
249 ASSERT_FALSE(session->IsBrokenConnectionDetectionEnabled());
250 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
251 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource(),
252 true, base::Seconds(10));
253 ASSERT_TRUE(stream);
254 ASSERT_TRUE(session->IsBrokenConnectionDetectionEnabled());
255 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
256 stream->SetDelegate(&delegate);
257
258 quiche::HttpHeaderBlock headers(
259 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
260 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
261 IsError(ERR_IO_PENDING));
262
263 base::RunLoop().RunUntilIdle();
264 ASSERT_TRUE(session->IsBrokenConnectionDetectionEnabled());
265
266 data.Resume();
267 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
268 ASSERT_FALSE(session->IsBrokenConnectionDetectionEnabled());
269 }
270
271 // Delegate that receives trailers.
272 class StreamDelegateWithTrailers : public test::StreamDelegateWithBody {
273 public:
StreamDelegateWithTrailers(const base::WeakPtr<SpdyStream> & stream,std::string_view data)274 StreamDelegateWithTrailers(const base::WeakPtr<SpdyStream>& stream,
275 std::string_view data)
276 : StreamDelegateWithBody(stream, data) {}
277
278 ~StreamDelegateWithTrailers() override = default;
279
OnTrailers(const quiche::HttpHeaderBlock & trailers)280 void OnTrailers(const quiche::HttpHeaderBlock& trailers) override {
281 trailers_ = trailers.Clone();
282 }
283
trailers() const284 const quiche::HttpHeaderBlock& trailers() const { return trailers_; }
285
286 private:
287 quiche::HttpHeaderBlock trailers_;
288 };
289
290 // Regression test for https://crbug.com/481033.
TEST_F(SpdyStreamTest,Trailers)291 TEST_F(SpdyStreamTest, Trailers) {
292 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
293 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
294 AddWrite(req);
295
296 spdy::SpdySerializedFrame msg(
297 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
298 AddWrite(msg);
299
300 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
301 AddRead(resp);
302
303 spdy::SpdySerializedFrame echo(
304 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
305 AddRead(echo);
306
307 quiche::HttpHeaderBlock late_headers;
308 late_headers["foo"] = "bar";
309 spdy::SpdySerializedFrame trailers(spdy_util_.ConstructSpdyResponseHeaders(
310 1, std::move(late_headers), false));
311 AddRead(trailers);
312
313 AddReadEOF();
314
315 SequencedSocketData data(GetReads(), GetWrites());
316 MockConnect connect_data(SYNCHRONOUS, OK);
317 data.set_connect_data(connect_data);
318 session_deps_.socket_factory->AddSocketDataProvider(&data);
319
320 AddSSLSocketData();
321
322 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
323
324 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
325 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
326 ASSERT_TRUE(stream);
327 EXPECT_EQ(kDefaultUrl, stream->url().spec());
328
329 StreamDelegateWithTrailers delegate(stream, kPostBodyStringPiece);
330 stream->SetDelegate(&delegate);
331
332 quiche::HttpHeaderBlock headers(
333 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
334 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
335 IsError(ERR_IO_PENDING));
336
337 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
338
339 EXPECT_TRUE(delegate.send_headers_completed());
340 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
341 const quiche::HttpHeaderBlock& received_trailers = delegate.trailers();
342 quiche::HttpHeaderBlock::const_iterator it = received_trailers.find("foo");
343 EXPECT_EQ("bar", it->second);
344 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
345 delegate.TakeReceivedData());
346 EXPECT_TRUE(data.AllWriteDataConsumed());
347 }
348
TEST_F(SpdyStreamTest,StreamError)349 TEST_F(SpdyStreamTest, StreamError) {
350 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
351 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
352 AddWrite(req);
353
354 spdy::SpdySerializedFrame resp(
355 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
356 AddRead(resp);
357
358 spdy::SpdySerializedFrame msg(
359 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
360 AddWrite(msg);
361
362 spdy::SpdySerializedFrame echo(
363 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
364 AddRead(echo);
365
366 AddReadEOF();
367
368 RecordingNetLogObserver net_log_observer;
369
370 SequencedSocketData data(GetReads(), GetWrites());
371 MockConnect connect_data(SYNCHRONOUS, OK);
372 data.set_connect_data(connect_data);
373 session_deps_.socket_factory->AddSocketDataProvider(&data);
374
375 AddSSLSocketData();
376
377 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
378
379 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
380 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST,
381 NetLogWithSource::Make(NetLogSourceType::NONE));
382 ASSERT_TRUE(stream);
383 EXPECT_EQ(kDefaultUrl, stream->url().spec());
384
385 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
386 stream->SetDelegate(&delegate);
387
388 quiche::HttpHeaderBlock headers(
389 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
390 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
391 IsError(ERR_IO_PENDING));
392
393 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
394
395 const spdy::SpdyStreamId stream_id = delegate.stream_id();
396
397 EXPECT_TRUE(delegate.send_headers_completed());
398 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
399 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
400 delegate.TakeReceivedData());
401 EXPECT_TRUE(data.AllWriteDataConsumed());
402
403 // Check that the NetLog was filled reasonably.
404 auto entries = net_log_observer.GetEntries();
405 EXPECT_LT(0u, entries.size());
406
407 // Check that we logged SPDY_STREAM_ERROR correctly.
408 int pos = ExpectLogContainsSomewhere(
409 entries, 0, NetLogEventType::HTTP2_STREAM_ERROR, NetLogEventPhase::NONE);
410
411 EXPECT_EQ(static_cast<int>(stream_id),
412 GetIntegerValueFromParams(entries[pos], "stream_id"));
413 }
414
415 // Make sure that large blocks of data are properly split up into frame-sized
416 // chunks for a request/response (i.e., an HTTP-like) stream.
TEST_F(SpdyStreamTest,SendLargeDataAfterOpenRequestResponse)417 TEST_F(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
418 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
419 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
420 AddWrite(req);
421
422 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
423 spdy::SpdySerializedFrame chunk(
424 spdy_util_.ConstructSpdyDataFrame(1, chunk_data, false));
425 AddWrite(chunk);
426 AddWrite(chunk);
427
428 spdy::SpdySerializedFrame last_chunk(
429 spdy_util_.ConstructSpdyDataFrame(1, chunk_data, true));
430 AddWrite(last_chunk);
431
432 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
433 AddRead(resp);
434
435 AddReadEOF();
436
437 SequencedSocketData data(GetReads(), GetWrites());
438 MockConnect connect_data(SYNCHRONOUS, OK);
439 data.set_connect_data(connect_data);
440 session_deps_.socket_factory->AddSocketDataProvider(&data);
441
442 AddSSLSocketData();
443
444 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
445
446 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
447 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
448 ASSERT_TRUE(stream);
449 EXPECT_EQ(kDefaultUrl, stream->url().spec());
450
451 std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
452 StreamDelegateWithBody delegate(stream, body_data);
453 stream->SetDelegate(&delegate);
454
455 quiche::HttpHeaderBlock headers(
456 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
457 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
458 IsError(ERR_IO_PENDING));
459
460 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
461
462 EXPECT_TRUE(delegate.send_headers_completed());
463 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
464 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
465 EXPECT_TRUE(data.AllWriteDataConsumed());
466 }
467
468 // Make sure that large blocks of data are properly split up into frame-sized
469 // chunks for a bidirectional (i.e., non-HTTP-like) stream.
TEST_F(SpdyStreamTest,SendLargeDataAfterOpenBidirectional)470 TEST_F(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
471 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
472 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
473 AddWrite(req);
474
475 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
476 AddRead(resp);
477
478 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
479 spdy::SpdySerializedFrame chunk(
480 spdy_util_.ConstructSpdyDataFrame(1, chunk_data, false));
481 AddWrite(chunk);
482 AddWrite(chunk);
483 AddWrite(chunk);
484
485 AddReadEOF();
486
487 SequencedSocketData data(GetReads(), GetWrites());
488 MockConnect connect_data(SYNCHRONOUS, OK);
489 data.set_connect_data(connect_data);
490 session_deps_.socket_factory->AddSocketDataProvider(&data);
491
492 AddSSLSocketData();
493
494 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
495
496 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
497 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
498 ASSERT_TRUE(stream);
499 EXPECT_EQ(kDefaultUrl, stream->url().spec());
500
501 std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
502 StreamDelegateSendImmediate delegate(stream, body_data);
503 stream->SetDelegate(&delegate);
504
505 quiche::HttpHeaderBlock headers(
506 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
507 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
508 IsError(ERR_IO_PENDING));
509
510 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
511
512 EXPECT_TRUE(delegate.send_headers_completed());
513 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
514 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
515 EXPECT_TRUE(data.AllWriteDataConsumed());
516 }
517
518 // Receiving a header with uppercase ASCII should result in a protocol error.
TEST_F(SpdyStreamTest,UpperCaseHeaders)519 TEST_F(SpdyStreamTest, UpperCaseHeaders) {
520 spdy::SpdySerializedFrame req(
521 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
522 AddWrite(req);
523
524 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
525 spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(
526 kExtraHeaders, std::size(kExtraHeaders) / 2, 1));
527 AddRead(reply);
528
529 spdy::SpdySerializedFrame rst(
530 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
531 AddWrite(rst);
532
533 AddReadEOF();
534
535 SequencedSocketData data(GetReads(), GetWrites());
536 MockConnect connect_data(SYNCHRONOUS, OK);
537 data.set_connect_data(connect_data);
538 session_deps_.socket_factory->AddSocketDataProvider(&data);
539
540 AddSSLSocketData();
541
542 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
543
544 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
545 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
546 ASSERT_TRUE(stream);
547 EXPECT_EQ(kDefaultUrl, stream->url().spec());
548
549 StreamDelegateDoNothing delegate(stream);
550 stream->SetDelegate(&delegate);
551
552 quiche::HttpHeaderBlock headers(
553 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
554 EXPECT_THAT(
555 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
556 IsError(ERR_IO_PENDING));
557
558 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
559
560 // Finish async network reads and writes.
561 base::RunLoop().RunUntilIdle();
562
563 EXPECT_TRUE(data.AllWriteDataConsumed());
564 EXPECT_TRUE(data.AllReadDataConsumed());
565 }
566
TEST_F(SpdyStreamTest,HeadersMustHaveStatus)567 TEST_F(SpdyStreamTest, HeadersMustHaveStatus) {
568 spdy::SpdySerializedFrame req(
569 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
570 AddWrite(req);
571
572 // Response headers without ":status" header field: protocol error.
573 quiche::HttpHeaderBlock header_block_without_status;
574 header_block_without_status[spdy::kHttp2MethodHeader] = "GET";
575 header_block_without_status[spdy::kHttp2AuthorityHeader] = "www.example.org";
576 header_block_without_status[spdy::kHttp2SchemeHeader] = "https";
577 header_block_without_status[spdy::kHttp2PathHeader] = "/";
578 spdy::SpdySerializedFrame reply(
579 spdy_util_.ConstructSpdyReply(1, std::move(header_block_without_status)));
580 AddRead(reply);
581
582 spdy::SpdySerializedFrame rst(
583 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
584 AddWrite(rst);
585
586 AddReadEOF();
587
588 SequencedSocketData data(GetReads(), GetWrites());
589 MockConnect connect_data(SYNCHRONOUS, OK);
590 data.set_connect_data(connect_data);
591 session_deps_.socket_factory->AddSocketDataProvider(&data);
592
593 AddSSLSocketData();
594
595 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
596
597 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
598 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
599 ASSERT_TRUE(stream);
600 EXPECT_EQ(kDefaultUrl, stream->url().spec());
601
602 StreamDelegateDoNothing delegate(stream);
603 stream->SetDelegate(&delegate);
604
605 quiche::HttpHeaderBlock headers(
606 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
607 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
608 NO_MORE_DATA_TO_SEND));
609
610 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
611
612 // Finish async network reads and writes.
613 base::RunLoop().RunUntilIdle();
614
615 EXPECT_TRUE(data.AllWriteDataConsumed());
616 EXPECT_TRUE(data.AllReadDataConsumed());
617 }
618
TEST_F(SpdyStreamTest,TrailersMustNotFollowTrailers)619 TEST_F(SpdyStreamTest, TrailersMustNotFollowTrailers) {
620 spdy::SpdySerializedFrame req(
621 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
622 AddWrite(req);
623
624 spdy::SpdySerializedFrame reply(
625 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
626 AddRead(reply);
627
628 spdy::SpdySerializedFrame body(
629 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
630 AddRead(body);
631
632 quiche::HttpHeaderBlock trailers_block;
633 trailers_block["foo"] = "bar";
634 spdy::SpdySerializedFrame first_trailers(
635 spdy_util_.ConstructSpdyResponseHeaders(1, std::move(trailers_block),
636 false));
637 AddRead(first_trailers);
638
639 // Trailers following trailers: procotol error.
640 spdy::SpdySerializedFrame second_trailers(
641 spdy_util_.ConstructSpdyResponseHeaders(1, std::move(trailers_block),
642 true));
643 AddRead(second_trailers);
644
645 spdy::SpdySerializedFrame rst(
646 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
647 AddWrite(rst);
648
649 AddReadEOF();
650
651 SequencedSocketData data(GetReads(), GetWrites());
652 MockConnect connect_data(SYNCHRONOUS, OK);
653 data.set_connect_data(connect_data);
654 session_deps_.socket_factory->AddSocketDataProvider(&data);
655
656 AddSSLSocketData();
657
658 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
659
660 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
661 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
662 ASSERT_TRUE(stream);
663 EXPECT_EQ(kDefaultUrl, stream->url().spec());
664
665 StreamDelegateDoNothing delegate(stream);
666 stream->SetDelegate(&delegate);
667
668 quiche::HttpHeaderBlock headers(
669 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
670 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
671 NO_MORE_DATA_TO_SEND));
672
673 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
674
675 // Finish async network reads and writes.
676 base::RunLoop().RunUntilIdle();
677
678 EXPECT_TRUE(data.AllWriteDataConsumed());
679 EXPECT_TRUE(data.AllReadDataConsumed());
680 }
681
TEST_F(SpdyStreamTest,DataMustNotFollowTrailers)682 TEST_F(SpdyStreamTest, DataMustNotFollowTrailers) {
683 spdy::SpdySerializedFrame req(
684 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
685 AddWrite(req);
686
687 spdy::SpdySerializedFrame reply(
688 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
689 AddRead(reply);
690
691 spdy::SpdySerializedFrame body(
692 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
693 AddRead(body);
694
695 quiche::HttpHeaderBlock trailers_block;
696 trailers_block["foo"] = "bar";
697 spdy::SpdySerializedFrame trailers(spdy_util_.ConstructSpdyResponseHeaders(
698 1, std::move(trailers_block), false));
699 AddRead(trailers);
700
701 // DATA frame following trailers: protocol error.
702 AddRead(body);
703
704 spdy::SpdySerializedFrame rst(
705 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
706 AddWrite(rst);
707
708 AddReadEOF();
709
710 SequencedSocketData data(GetReads(), GetWrites());
711 MockConnect connect_data(SYNCHRONOUS, OK);
712 data.set_connect_data(connect_data);
713 session_deps_.socket_factory->AddSocketDataProvider(&data);
714
715 AddSSLSocketData();
716
717 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
718
719 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
720 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
721 ASSERT_TRUE(stream);
722 EXPECT_EQ(kDefaultUrl, stream->url().spec());
723
724 StreamDelegateDoNothing delegate(stream);
725 stream->SetDelegate(&delegate);
726
727 quiche::HttpHeaderBlock headers(
728 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
729 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
730 NO_MORE_DATA_TO_SEND));
731
732 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
733
734 // Finish async network reads and writes.
735 base::RunLoop().RunUntilIdle();
736
737 EXPECT_TRUE(data.AllWriteDataConsumed());
738 EXPECT_TRUE(data.AllReadDataConsumed());
739 }
740
741 class SpdyStreamTestWithMockClock : public SpdyStreamTest {
742 public:
SpdyStreamTestWithMockClock()743 SpdyStreamTestWithMockClock()
744 : SpdyStreamTest(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
745
Initialize()746 void Initialize() {
747 // Set up the sequenced socket data.
748 data_ = std::make_unique<SequencedSocketData>(GetReads(), GetWrites());
749 MockConnect connect_data(SYNCHRONOUS, OK);
750 data_->set_connect_data(connect_data);
751 session_deps_.socket_factory->AddSocketDataProvider(data_.get());
752
753 AddSSLSocketData();
754
755 // Set up the SPDY stream.
756 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
757 stream_ = CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
758 url_, LOWEST, NetLogWithSource());
759 ASSERT_TRUE(stream_);
760 EXPECT_EQ(kDefaultUrl, stream_->url().spec());
761
762 DCHECK(!delegate_);
763 delegate_ = std::make_unique<StreamDelegateDoNothing>(stream_);
764 stream_->SetDelegate(delegate_.get());
765 }
766
RunUntilNextPause()767 void RunUntilNextPause() {
768 if (data_->IsPaused())
769 data_->Resume();
770 data_->RunUntilPaused();
771 }
772
RunUntilClose()773 int RunUntilClose() {
774 if (data_->IsPaused())
775 data_->Resume();
776 return delegate_->WaitForClose();
777 }
778
data()779 SequencedSocketData& data() { return *data_; }
stream()780 base::WeakPtr<SpdyStream> stream() { return stream_; }
delegate()781 StreamDelegateDoNothing& delegate() { return *delegate_; }
782
783 private:
784 std::unique_ptr<SequencedSocketData> data_;
785 base::WeakPtr<SpdyStream> stream_;
786 std::unique_ptr<StreamDelegateDoNothing> delegate_;
787 };
788
789 // Test that the response start time is recorded for non-informational response.
TEST_F(SpdyStreamTestWithMockClock,NonInformationalResponseStart)790 TEST_F(SpdyStreamTestWithMockClock, NonInformationalResponseStart) {
791 // Set up the request.
792 spdy::SpdySerializedFrame req(
793 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
794 AddWrite(req);
795
796 // Set up the response headers.
797 spdy::SpdySerializedFrame reply(
798 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
799 // Separate the headers into 2 fragments and add pauses between the fragments
800 // so that the test runner can advance the mock clock to test timing
801 // information.
802 AddMockRead(ReadFrameExceptForLastByte(reply));
803 AddReadPause();
804 AddMockRead(LastByteOfReadFrame(reply));
805 AddReadPause();
806
807 // Set up the response body.
808 spdy::SpdySerializedFrame body(
809 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
810 AddRead(body);
811 AddReadEOF();
812
813 // Set up the sequenced socket data and the spdy stream.
814 Initialize();
815
816 // Send a request.
817 quiche::HttpHeaderBlock headers(
818 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
819 EXPECT_EQ(ERR_IO_PENDING, stream()->SendRequestHeaders(std::move(headers),
820 NO_MORE_DATA_TO_SEND));
821 AdvanceClock(base::Seconds(1));
822
823 // The receive headers start time should be captured at this time.
824 base::TimeTicks expected_receive_headers_start_time = base::TimeTicks::Now();
825
826 // Read the first header fragment.
827 RunUntilNextPause();
828 AdvanceClock(base::Seconds(1));
829 // Read the second header fragment.
830 RunUntilNextPause();
831 AdvanceClock(base::Seconds(1));
832 EXPECT_EQ("200", delegate().GetResponseHeaderValue(spdy::kHttp2StatusHeader));
833
834 // Read the response body.
835 EXPECT_THAT(RunUntilClose(), IsOk());
836 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
837 delegate().TakeReceivedData());
838
839 // Finish async network reads and writes.
840 base::RunLoop().RunUntilIdle();
841 EXPECT_TRUE(data().AllWriteDataConsumed());
842 EXPECT_TRUE(data().AllReadDataConsumed());
843
844 // No informational responses were served. The response start time should be
845 // equal to the non-informational response start time.
846 const LoadTimingInfo& load_timing_info = delegate().GetLoadTimingInfo();
847 EXPECT_EQ(load_timing_info.receive_headers_start,
848 expected_receive_headers_start_time);
849 EXPECT_EQ(load_timing_info.receive_non_informational_headers_start,
850 expected_receive_headers_start_time);
851 }
852
TEST_F(SpdyStreamTestWithMockClock,InformationalHeaders)853 TEST_F(SpdyStreamTestWithMockClock, InformationalHeaders) {
854 // Set up the request.
855 spdy::SpdySerializedFrame req(
856 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
857 AddWrite(req);
858
859 // Set up the informational response headers.
860 quiche::HttpHeaderBlock informational_headers;
861 informational_headers[":status"] = "100";
862 spdy::SpdySerializedFrame informational_response(
863 spdy_util_.ConstructSpdyResponseHeaders(
864 1, std::move(informational_headers), false));
865 // Separate the headers into 2 fragments and add pauses between the fragments
866 // so that the test runner can advance the mock clock to test timing
867 // information.
868 AddMockRead(ReadFrameExceptForLastByte(informational_response));
869 AddReadPause();
870 AddMockRead(LastByteOfReadFrame(informational_response));
871 AddReadPause();
872
873 // Set up the non-informational response headers and body.
874 spdy::SpdySerializedFrame reply(
875 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
876 AddRead(reply);
877 AddReadPause();
878 spdy::SpdySerializedFrame body(
879 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
880 AddRead(body);
881 AddReadEOF();
882
883 // Set up the sequenced socket data and the spdy stream.
884 Initialize();
885
886 // Send a request.
887 quiche::HttpHeaderBlock headers(
888 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
889 EXPECT_EQ(ERR_IO_PENDING, stream()->SendRequestHeaders(std::move(headers),
890 NO_MORE_DATA_TO_SEND));
891 AdvanceClock(base::Seconds(1));
892
893 // The receive headers start time should be captured at this time.
894 base::TimeTicks expected_receive_headers_start_time = base::TimeTicks::Now();
895
896 // Read the first header fragment of the informational response.
897 RunUntilNextPause();
898 AdvanceClock(base::Seconds(1));
899 // Read the second header fragment of the informational response.
900 RunUntilNextPause();
901 AdvanceClock(base::Seconds(1));
902 // We don't check the status code of the informational headers here because
903 // SpdyStream doesn't propagate it to the delegate.
904
905 // The receive non-informational headers start time should be captured at this
906 // time.
907 base::TimeTicks expected_receive_non_informational_headers_start_time =
908 base::TimeTicks::Now();
909
910 // Read the non-informational response headers.
911 RunUntilNextPause();
912 AdvanceClock(base::Seconds(1));
913 EXPECT_EQ("200", delegate().GetResponseHeaderValue(spdy::kHttp2StatusHeader));
914
915 // Read the response body.
916 EXPECT_THAT(RunUntilClose(), IsOk());
917 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
918 delegate().TakeReceivedData());
919
920 // Finish async network reads and writes.
921 base::RunLoop().RunUntilIdle();
922 EXPECT_TRUE(data().AllWriteDataConsumed());
923 EXPECT_TRUE(data().AllReadDataConsumed());
924
925 const LoadTimingInfo& load_timing_info = delegate().GetLoadTimingInfo();
926 // The response start time should be captured at the time the first header
927 // fragment of the informational response is received.
928 EXPECT_EQ(load_timing_info.receive_headers_start,
929 expected_receive_headers_start_time);
930 // The non-informational response start time should be captured at the time
931 // the first header fragment of the non-informational response is received.
932 EXPECT_EQ(load_timing_info.receive_non_informational_headers_start,
933 expected_receive_non_informational_headers_start_time);
934 // The first response start time should be earlier than the non-informational
935 // response start time.
936 EXPECT_LT(load_timing_info.receive_headers_start,
937 load_timing_info.receive_non_informational_headers_start);
938 }
939
940 // Tests that timing information of 103 Eary Hints responses are collected and
941 // callbacks are called as expected.
TEST_F(SpdyStreamTestWithMockClock,EarlyHints)942 TEST_F(SpdyStreamTestWithMockClock, EarlyHints) {
943 // Set up the request.
944 spdy::SpdySerializedFrame req(
945 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
946 AddWrite(req);
947
948 // Set up two early hints response headers.
949 const char kLinkHeaderValue1[] = "</image.jpg>; rel=preload; as=image";
950 quiche::HttpHeaderBlock informational_headers1;
951 informational_headers1[":status"] = "103";
952 informational_headers1["link"] = kLinkHeaderValue1;
953 spdy::SpdySerializedFrame informational_response1(
954 spdy_util_.ConstructSpdyResponseHeaders(
955 1, std::move(informational_headers1), false));
956
957 const char kLinkHeaderValue2[] = "</style.css>; rel=preload; as=stylesheet";
958 quiche::HttpHeaderBlock informational_headers2;
959 informational_headers2[":status"] = "103";
960 informational_headers2["link"] = kLinkHeaderValue2;
961 spdy::SpdySerializedFrame informational_response2(
962 spdy_util_.ConstructSpdyResponseHeaders(
963 1, std::move(informational_headers2), false));
964
965 // Add the headers to make sure that multiple informational responses don't
966 // confuse the timing information.
967 const int kNumberOfInformationalResponses = 2;
968 // Separate the headers into 2 fragments and add pauses between the
969 // fragments so that the test runner can advance the mock clock to test
970 // timing information.
971 AddMockRead(ReadFrameExceptForLastByte(informational_response1));
972 AddReadPause();
973 AddMockRead(LastByteOfReadFrame(informational_response1));
974 AddReadPause();
975
976 AddMockRead(ReadFrameExceptForLastByte(informational_response2));
977 AddReadPause();
978 AddMockRead(LastByteOfReadFrame(informational_response2));
979 AddReadPause();
980
981 // Set up the non-informational response headers and body.
982 spdy::SpdySerializedFrame reply(
983 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
984 AddRead(reply);
985 AddReadPause();
986 spdy::SpdySerializedFrame body(
987 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
988 AddRead(body);
989 AddReadEOF();
990
991 // Set up the sequenced socket data and the spdy stream.
992 Initialize();
993
994 // Send a request.
995 quiche::HttpHeaderBlock headers(
996 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
997 EXPECT_EQ(ERR_IO_PENDING, stream()->SendRequestHeaders(std::move(headers),
998 NO_MORE_DATA_TO_SEND));
999 AdvanceClock(base::Seconds(1));
1000
1001 // The receive headers start time should be captured at this time.
1002 base::TimeTicks expected_receive_headers_start_time = base::TimeTicks::Now();
1003
1004 // Read the header fragments of the informational responses.
1005 for (int i = 0; i < kNumberOfInformationalResponses; ++i) {
1006 RunUntilNextPause();
1007 AdvanceClock(base::Seconds(1));
1008 RunUntilNextPause();
1009 AdvanceClock(base::Seconds(1));
1010 }
1011
1012 // Check the callback was called twice with 103 status code.
1013 const std::vector<quiche::HttpHeaderBlock>& early_hints =
1014 delegate().early_hints();
1015 EXPECT_EQ(early_hints.size(),
1016 static_cast<size_t>(kNumberOfInformationalResponses));
1017 {
1018 const quiche::HttpHeaderBlock& hint = delegate().early_hints()[0];
1019 quiche::HttpHeaderBlock::const_iterator status_iterator =
1020 hint.find(spdy::kHttp2StatusHeader);
1021 ASSERT_TRUE(status_iterator != hint.end());
1022 EXPECT_EQ(status_iterator->second, "103");
1023
1024 quiche::HttpHeaderBlock::const_iterator link_header_iterator =
1025 hint.find("link");
1026 ASSERT_TRUE(link_header_iterator != hint.end());
1027 EXPECT_EQ(link_header_iterator->second, kLinkHeaderValue1);
1028 }
1029 {
1030 const quiche::HttpHeaderBlock& hint = delegate().early_hints()[1];
1031 quiche::HttpHeaderBlock::const_iterator status_iterator =
1032 hint.find(spdy::kHttp2StatusHeader);
1033 ASSERT_TRUE(status_iterator != hint.end());
1034 EXPECT_EQ(status_iterator->second, "103");
1035
1036 quiche::HttpHeaderBlock::const_iterator link_header_iterator =
1037 hint.find("link");
1038 ASSERT_TRUE(link_header_iterator != hint.end());
1039 EXPECT_EQ(link_header_iterator->second, kLinkHeaderValue2);
1040 }
1041
1042 // The receive non-informational headers start time should be captured at this
1043 // time.
1044 base::TimeTicks expected_receive_non_informational_headers_start_time =
1045 base::TimeTicks::Now();
1046
1047 // Read the non-informational response headers.
1048 RunUntilNextPause();
1049 AdvanceClock(base::Seconds(1));
1050 EXPECT_EQ("200", delegate().GetResponseHeaderValue(spdy::kHttp2StatusHeader));
1051
1052 // Read the response body.
1053 EXPECT_THAT(RunUntilClose(), IsOk());
1054 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
1055 delegate().TakeReceivedData());
1056
1057 // Finish async network reads and writes.
1058 base::RunLoop().RunUntilIdle();
1059 EXPECT_TRUE(data().AllWriteDataConsumed());
1060 EXPECT_TRUE(data().AllReadDataConsumed());
1061
1062 const LoadTimingInfo& load_timing_info = delegate().GetLoadTimingInfo();
1063 // The response start time should be captured at the time the first header
1064 // fragment of the first informational response is received.
1065 EXPECT_EQ(load_timing_info.receive_headers_start,
1066 expected_receive_headers_start_time);
1067 // The first early hints time should be recorded as well.
1068 EXPECT_EQ(load_timing_info.first_early_hints_time,
1069 expected_receive_headers_start_time);
1070 // The non-informational response start time should be captured at the time
1071 // the first header fragment of the non-informational response is received.
1072 EXPECT_EQ(load_timing_info.receive_non_informational_headers_start,
1073 expected_receive_non_informational_headers_start_time);
1074 // The response start time should be earlier than the non-informational
1075 // response start time.
1076 EXPECT_LT(load_timing_info.receive_headers_start,
1077 load_timing_info.receive_non_informational_headers_start);
1078 }
1079
TEST_F(SpdyStreamTest,StatusMustBeNumber)1080 TEST_F(SpdyStreamTest, StatusMustBeNumber) {
1081 spdy::SpdySerializedFrame req(
1082 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1083 AddWrite(req);
1084
1085 quiche::HttpHeaderBlock incorrect_headers;
1086 incorrect_headers[":status"] = "nan";
1087 spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
1088 1, std::move(incorrect_headers), false));
1089 AddRead(reply);
1090
1091 spdy::SpdySerializedFrame rst(
1092 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
1093 AddWrite(rst);
1094
1095 AddReadEOF();
1096
1097 SequencedSocketData data(GetReads(), GetWrites());
1098 MockConnect connect_data(SYNCHRONOUS, OK);
1099 data.set_connect_data(connect_data);
1100 session_deps_.socket_factory->AddSocketDataProvider(&data);
1101
1102 AddSSLSocketData();
1103
1104 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1105
1106 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1107 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1108 ASSERT_TRUE(stream);
1109 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1110
1111 StreamDelegateDoNothing delegate(stream);
1112 stream->SetDelegate(&delegate);
1113
1114 quiche::HttpHeaderBlock headers(
1115 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1116 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1117 NO_MORE_DATA_TO_SEND));
1118
1119 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
1120
1121 // Finish async network reads and writes.
1122 base::RunLoop().RunUntilIdle();
1123
1124 EXPECT_TRUE(data.AllWriteDataConsumed());
1125 EXPECT_TRUE(data.AllReadDataConsumed());
1126 }
1127
TEST_F(SpdyStreamTest,StatusCannotHaveExtraText)1128 TEST_F(SpdyStreamTest, StatusCannotHaveExtraText) {
1129 spdy::SpdySerializedFrame req(
1130 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1131 AddWrite(req);
1132
1133 quiche::HttpHeaderBlock headers_with_status_text;
1134 headers_with_status_text[":status"] =
1135 "200 Some random extra text describing status";
1136 spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
1137 1, std::move(headers_with_status_text), false));
1138 AddRead(reply);
1139
1140 spdy::SpdySerializedFrame body(
1141 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
1142 AddRead(body);
1143
1144 spdy::SpdySerializedFrame rst(
1145 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
1146 AddWrite(rst);
1147
1148 AddReadEOF();
1149
1150 SequencedSocketData data(GetReads(), GetWrites());
1151 MockConnect connect_data(SYNCHRONOUS, OK);
1152 data.set_connect_data(connect_data);
1153 session_deps_.socket_factory->AddSocketDataProvider(&data);
1154
1155 AddSSLSocketData();
1156
1157 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1158
1159 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1160 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1161 ASSERT_TRUE(stream);
1162 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1163
1164 StreamDelegateDoNothing delegate(stream);
1165 stream->SetDelegate(&delegate);
1166
1167 quiche::HttpHeaderBlock headers(
1168 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1169 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1170 NO_MORE_DATA_TO_SEND));
1171
1172 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
1173
1174 // Finish async network reads and writes.
1175 base::RunLoop().RunUntilIdle();
1176
1177 EXPECT_TRUE(data.AllWriteDataConsumed());
1178 EXPECT_TRUE(data.AllReadDataConsumed());
1179 }
1180
TEST_F(SpdyStreamTest,StatusMustBePresent)1181 TEST_F(SpdyStreamTest, StatusMustBePresent) {
1182 spdy::SpdySerializedFrame req(
1183 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1184 AddWrite(req);
1185
1186 quiche::HttpHeaderBlock headers_without_status;
1187 spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
1188 1, std::move(headers_without_status), false));
1189 AddRead(reply);
1190
1191 spdy::SpdySerializedFrame body(
1192 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
1193 AddRead(body);
1194
1195 spdy::SpdySerializedFrame rst(
1196 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
1197 AddWrite(rst);
1198
1199 AddReadEOF();
1200
1201 SequencedSocketData data(GetReads(), GetWrites());
1202 MockConnect connect_data(SYNCHRONOUS, OK);
1203 data.set_connect_data(connect_data);
1204 session_deps_.socket_factory->AddSocketDataProvider(&data);
1205
1206 AddSSLSocketData();
1207
1208 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1209
1210 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1211 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1212 ASSERT_TRUE(stream);
1213 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1214
1215 StreamDelegateDoNothing delegate(stream);
1216 stream->SetDelegate(&delegate);
1217
1218 quiche::HttpHeaderBlock headers(
1219 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1220 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1221 NO_MORE_DATA_TO_SEND));
1222
1223 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
1224
1225 // Finish async network reads and writes.
1226 base::RunLoop().RunUntilIdle();
1227
1228 EXPECT_TRUE(data.AllWriteDataConsumed());
1229 EXPECT_TRUE(data.AllReadDataConsumed());
1230 }
1231
1232 // Call IncreaseSendWindowSize on a stream with a large enough delta to overflow
1233 // an int32_t. The SpdyStream should handle that case gracefully.
TEST_F(SpdyStreamTest,IncreaseSendWindowSizeOverflow)1234 TEST_F(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
1235 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1236 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
1237 AddWrite(req);
1238
1239 AddReadPause();
1240
1241 // Triggered by the overflowing call to IncreaseSendWindowSize
1242 // below.
1243 spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream(
1244 1, spdy::ERROR_CODE_FLOW_CONTROL_ERROR));
1245 AddWrite(rst);
1246
1247 AddReadEOF();
1248
1249 SequencedSocketData data(GetReads(), GetWrites());
1250 MockConnect connect_data(SYNCHRONOUS, OK);
1251 data.set_connect_data(connect_data);
1252 session_deps_.socket_factory->AddSocketDataProvider(&data);
1253
1254 AddSSLSocketData();
1255
1256 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1257
1258 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1259 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST,
1260 NetLogWithSource::Make(NetLogSourceType::NONE));
1261 ASSERT_TRUE(stream);
1262 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1263
1264 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
1265 stream->SetDelegate(&delegate);
1266
1267 quiche::HttpHeaderBlock headers(
1268 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1269 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1270 IsError(ERR_IO_PENDING));
1271
1272 data.RunUntilPaused();
1273
1274 int32_t old_send_window_size = stream->send_window_size();
1275 ASSERT_GT(old_send_window_size, 0);
1276 int32_t delta_window_size =
1277 std::numeric_limits<int32_t>::max() - old_send_window_size + 1;
1278 stream->IncreaseSendWindowSize(delta_window_size);
1279 EXPECT_FALSE(stream);
1280
1281 data.Resume();
1282 base::RunLoop().RunUntilIdle();
1283
1284 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_FLOW_CONTROL_ERROR));
1285 }
1286
1287 // Functions used with
1288 // RunResumeAfterUnstall{RequestResponse,Bidirectional}Test().
1289
StallStream(const base::WeakPtr<SpdyStream> & stream)1290 void StallStream(const base::WeakPtr<SpdyStream>& stream) {
1291 // Reduce the send window size to 0 to stall.
1292 while (stream->send_window_size() > 0) {
1293 stream->DecreaseSendWindowSize(
1294 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
1295 }
1296 }
1297
IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream> & stream,int32_t delta_window_size)1298 void IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
1299 int32_t delta_window_size) {
1300 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1301 stream->IncreaseSendWindowSize(delta_window_size);
1302 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1303 }
1304
AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream> & stream,int32_t delta_window_size)1305 void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
1306 int32_t delta_window_size) {
1307 // Make sure that negative adjustments are handled properly.
1308 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1309 EXPECT_TRUE(stream->AdjustSendWindowSize(-delta_window_size));
1310 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1311 EXPECT_TRUE(stream->AdjustSendWindowSize(+delta_window_size));
1312 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1313 EXPECT_TRUE(stream->AdjustSendWindowSize(+delta_window_size));
1314 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1315 }
1316
1317 // Given an unstall function, runs a test to make sure that a
1318 // request/response (i.e., an HTTP-like) stream resumes after a stall
1319 // and unstall.
RunResumeAfterUnstallRequestResponseTest(UnstallFunction unstall_function)1320 void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
1321 UnstallFunction unstall_function) {
1322 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1323 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
1324 AddWrite(req);
1325
1326 spdy::SpdySerializedFrame body(
1327 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
1328 AddWrite(body);
1329
1330 spdy::SpdySerializedFrame resp(
1331 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1332 AddRead(resp);
1333
1334 AddReadEOF();
1335
1336 SequencedSocketData data(GetReads(), GetWrites());
1337 MockConnect connect_data(SYNCHRONOUS, OK);
1338 data.set_connect_data(connect_data);
1339 session_deps_.socket_factory->AddSocketDataProvider(&data);
1340
1341 AddSSLSocketData();
1342
1343 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1344
1345 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1346 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1347 ASSERT_TRUE(stream);
1348 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1349
1350 StreamDelegateWithBody delegate(stream, kPostBodyStringPiece);
1351 stream->SetDelegate(&delegate);
1352
1353 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1354
1355 quiche::HttpHeaderBlock headers(
1356 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1357 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1358 IsError(ERR_IO_PENDING));
1359
1360 StallStream(stream);
1361
1362 base::RunLoop().RunUntilIdle();
1363
1364 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1365
1366 std::move(unstall_function).Run(stream, kPostBodyLength);
1367
1368 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1369
1370 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
1371
1372 EXPECT_TRUE(delegate.send_headers_completed());
1373 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
1374 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
1375 EXPECT_TRUE(data.AllWriteDataConsumed());
1376 }
1377
TEST_F(SpdyStreamTest,ResumeAfterSendWindowSizeIncreaseRequestResponse)1378 TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) {
1379 RunResumeAfterUnstallRequestResponseTest(
1380 base::BindOnce(&IncreaseStreamSendWindowSize));
1381 }
1382
TEST_F(SpdyStreamTest,ResumeAfterSendWindowSizeAdjustRequestResponse)1383 TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) {
1384 RunResumeAfterUnstallRequestResponseTest(
1385 base::BindOnce(&AdjustStreamSendWindowSize));
1386 }
1387
1388 // Given an unstall function, runs a test to make sure that a bidirectional
1389 // (i.e., non-HTTP-like) stream resumes after a stall and unstall.
RunResumeAfterUnstallBidirectionalTest(UnstallFunction unstall_function)1390 void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
1391 UnstallFunction unstall_function) {
1392 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1393 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
1394 AddWrite(req);
1395
1396 AddReadPause();
1397
1398 spdy::SpdySerializedFrame resp(
1399 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1400 AddRead(resp);
1401
1402 spdy::SpdySerializedFrame msg(
1403 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
1404 AddWrite(msg);
1405
1406 spdy::SpdySerializedFrame echo(
1407 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
1408 AddRead(echo);
1409
1410 AddReadEOF();
1411
1412 SequencedSocketData data(GetReads(), GetWrites());
1413 MockConnect connect_data(SYNCHRONOUS, OK);
1414 data.set_connect_data(connect_data);
1415 session_deps_.socket_factory->AddSocketDataProvider(&data);
1416
1417 AddSSLSocketData();
1418
1419 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1420
1421 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1422 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
1423 ASSERT_TRUE(stream);
1424 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1425
1426 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
1427 stream->SetDelegate(&delegate);
1428
1429 quiche::HttpHeaderBlock headers(
1430 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1431 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1432 IsError(ERR_IO_PENDING));
1433
1434 data.RunUntilPaused();
1435
1436 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1437
1438 StallStream(stream);
1439
1440 data.Resume();
1441 base::RunLoop().RunUntilIdle();
1442
1443 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1444
1445 std::move(unstall_function).Run(stream, kPostBodyLength);
1446
1447 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1448
1449 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
1450
1451 EXPECT_TRUE(delegate.send_headers_completed());
1452 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
1453 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
1454 delegate.TakeReceivedData());
1455 EXPECT_TRUE(data.AllWriteDataConsumed());
1456 }
1457
TEST_F(SpdyStreamTest,ResumeAfterSendWindowSizeIncreaseBidirectional)1458 TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) {
1459 RunResumeAfterUnstallBidirectionalTest(
1460 base::BindOnce(&IncreaseStreamSendWindowSize));
1461 }
1462
TEST_F(SpdyStreamTest,ResumeAfterSendWindowSizeAdjustBidirectional)1463 TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
1464 RunResumeAfterUnstallBidirectionalTest(
1465 base::BindOnce(&AdjustStreamSendWindowSize));
1466 }
1467
1468 // Test calculation of amount of bytes received from network.
TEST_F(SpdyStreamTest,ReceivedBytes)1469 TEST_F(SpdyStreamTest, ReceivedBytes) {
1470 spdy::SpdySerializedFrame req(
1471 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1472 AddWrite(req);
1473
1474 AddReadPause();
1475
1476 spdy::SpdySerializedFrame reply(
1477 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1478 AddRead(reply);
1479
1480 AddReadPause();
1481
1482 spdy::SpdySerializedFrame msg(
1483 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
1484 AddRead(msg);
1485
1486 AddReadPause();
1487
1488 AddReadEOF();
1489
1490 SequencedSocketData data(GetReads(), GetWrites());
1491 MockConnect connect_data(SYNCHRONOUS, OK);
1492 data.set_connect_data(connect_data);
1493 session_deps_.socket_factory->AddSocketDataProvider(&data);
1494
1495 AddSSLSocketData();
1496
1497 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1498
1499 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1500 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1501 ASSERT_TRUE(stream);
1502 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1503
1504 StreamDelegateDoNothing delegate(stream);
1505 stream->SetDelegate(&delegate);
1506
1507 quiche::HttpHeaderBlock headers(
1508 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1509 EXPECT_THAT(
1510 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
1511 IsError(ERR_IO_PENDING));
1512
1513 int64_t reply_frame_len = reply.size();
1514 int64_t data_header_len = spdy::kDataFrameMinimumSize;
1515 int64_t data_frame_len = data_header_len + kPostBodyLength;
1516 int64_t response_len = reply_frame_len + data_frame_len;
1517
1518 EXPECT_EQ(0, stream->raw_received_bytes());
1519
1520 // REQUEST
1521 data.RunUntilPaused();
1522 EXPECT_EQ(0, stream->raw_received_bytes());
1523
1524 // REPLY
1525 data.Resume();
1526 data.RunUntilPaused();
1527 EXPECT_EQ(reply_frame_len, stream->raw_received_bytes());
1528
1529 // DATA
1530 data.Resume();
1531 data.RunUntilPaused();
1532 EXPECT_EQ(response_len, stream->raw_received_bytes());
1533
1534 // FIN
1535 data.Resume();
1536 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
1537 }
1538
1539 // Regression test for https://crbug.com/810763.
TEST_F(SpdyStreamTest,DataOnHalfClosedRemoveStream)1540 TEST_F(SpdyStreamTest, DataOnHalfClosedRemoveStream) {
1541 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1542 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
1543 AddWrite(req);
1544
1545 quiche::HttpHeaderBlock response_headers;
1546 response_headers[spdy::kHttp2StatusHeader] = "200";
1547 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
1548 1, std::move(response_headers), /* fin = */ true));
1549 AddRead(resp);
1550
1551 spdy::SpdySerializedFrame data_frame(
1552 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
1553 AddRead(data_frame);
1554
1555 spdy::SpdySerializedFrame rst(
1556 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_STREAM_CLOSED));
1557 AddWrite(rst);
1558
1559 AddReadEOF();
1560
1561 SequencedSocketData data(GetReads(), GetWrites());
1562 MockConnect connect_data(SYNCHRONOUS, OK);
1563 data.set_connect_data(connect_data);
1564 session_deps_.socket_factory->AddSocketDataProvider(&data);
1565
1566 AddSSLSocketData();
1567
1568 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1569
1570 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1571 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
1572 ASSERT_TRUE(stream);
1573 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1574
1575 StreamDelegateDoNothing delegate(stream);
1576 stream->SetDelegate(&delegate);
1577
1578 quiche::HttpHeaderBlock headers(
1579 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1580 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1581 IsError(ERR_IO_PENDING));
1582
1583 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_STREAM_CLOSED));
1584
1585 base::RunLoop().RunUntilIdle();
1586
1587 EXPECT_TRUE(data.AllReadDataConsumed());
1588 EXPECT_TRUE(data.AllWriteDataConsumed());
1589 }
1590
TEST_F(SpdyStreamTest,DelegateIsInformedOfEOF)1591 TEST_F(SpdyStreamTest, DelegateIsInformedOfEOF) {
1592 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1593 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
1594 AddWrite(req);
1595
1596 quiche::HttpHeaderBlock response_headers;
1597 response_headers[spdy::kHttp2StatusHeader] = "200";
1598 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
1599 1, std::move(response_headers), /* fin = */ true));
1600 AddRead(resp);
1601
1602 spdy::SpdySerializedFrame data_frame(
1603 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
1604 AddRead(data_frame);
1605
1606 spdy::SpdySerializedFrame rst(
1607 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_STREAM_CLOSED));
1608 AddWrite(rst);
1609
1610 AddReadEOF();
1611
1612 SequencedSocketData data(GetReads(), GetWrites());
1613 MockConnect connect_data(SYNCHRONOUS, OK);
1614 data.set_connect_data(connect_data);
1615 session_deps_.socket_factory->AddSocketDataProvider(&data);
1616
1617 AddSSLSocketData();
1618
1619 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1620
1621 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1622 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
1623 ASSERT_TRUE(stream);
1624 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1625
1626 StreamDelegateDetectEOF delegate(stream);
1627 stream->SetDelegate(&delegate);
1628
1629 quiche::HttpHeaderBlock headers(
1630 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1631 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1632 IsError(ERR_IO_PENDING));
1633
1634 base::RunLoop().RunUntilIdle();
1635
1636 EXPECT_TRUE(delegate.eof_detected());
1637
1638 EXPECT_TRUE(data.AllReadDataConsumed());
1639 EXPECT_TRUE(data.AllWriteDataConsumed());
1640 }
1641
1642 // A small read should trigger sending a receive window update and dropping the
1643 // count of unacknowledged bytes to zero only after
1644 // kDefaultTimeToBufferSmallWindowUpdates time has passed.
TEST_F(SpdyStreamTestWithMockClock,FlowControlSlowReads)1645 TEST_F(SpdyStreamTestWithMockClock, FlowControlSlowReads) {
1646 spdy::SpdySerializedFrame req(
1647 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1648 AddWrite(req);
1649
1650 AddReadPause();
1651
1652 spdy::SpdySerializedFrame reply(
1653 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1654 AddRead(reply);
1655
1656 AddReadPause();
1657
1658 spdy::SpdySerializedFrame msg(
1659 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
1660 AddRead(msg);
1661
1662 AddReadPause();
1663
1664 AddReadEOF();
1665
1666 SequencedSocketData data(GetReads(), GetWrites());
1667 MockConnect connect_data(SYNCHRONOUS, OK);
1668 data.set_connect_data(connect_data);
1669 session_deps_.socket_factory->AddSocketDataProvider(&data);
1670
1671 AddSSLSocketData();
1672
1673 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1674 session->SetTimeToBufferSmallWindowUpdates(
1675 kDefaultTimeToBufferSmallWindowUpdates);
1676
1677 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1678 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1679 ASSERT_TRUE(stream);
1680 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1681
1682 StreamDelegateConsumeData delegate(stream);
1683 stream->SetDelegate(&delegate);
1684
1685 EXPECT_EQ(0, unacked_recv_window_bytes(stream));
1686
1687 quiche::HttpHeaderBlock headers(
1688 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1689 EXPECT_THAT(
1690 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
1691 IsError(ERR_IO_PENDING));
1692
1693 // REQUEST
1694 data.RunUntilPaused();
1695
1696 // REPLY
1697 data.Resume();
1698 data.RunUntilPaused();
1699
1700 // Delay long enough for the receive window to send an update on read,
1701 // draining the unacked_recv_window_bytes back to zero.
1702 AdvanceClock(kDefaultTimeToBufferSmallWindowUpdates);
1703
1704 // DATA
1705 data.Resume();
1706 data.RunUntilPaused();
1707
1708 EXPECT_EQ(0, unacked_recv_window_bytes(stream));
1709
1710 // FIN
1711 data.Resume();
1712 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
1713 }
1714
1715 } // namespace net::test
1716