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