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