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