1 // Copyright 2012 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_session.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <tuple>
10 #include <utility>
11
12 #include "base/base64.h"
13 #include "base/functional/bind.h"
14 #include "base/functional/callback.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/run_loop.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/task/single_thread_task_runner.h"
19 #include "base/test/metrics/histogram_tester.h"
20 #include "base/test/scoped_feature_list.h"
21 #include "base/test/task_environment.h"
22 #include "base/time/time.h"
23 #include "build/build_config.h"
24 #include "net/base/features.h"
25 #include "net/base/hex_utils.h"
26 #include "net/base/host_port_pair.h"
27 #include "net/base/io_buffer.h"
28 #include "net/base/ip_endpoint.h"
29 #include "net/base/network_anonymization_key.h"
30 #include "net/base/privacy_mode.h"
31 #include "net/base/proxy_chain.h"
32 #include "net/base/proxy_delegate.h"
33 #include "net/base/proxy_server.h"
34 #include "net/base/request_priority.h"
35 #include "net/base/schemeful_site.h"
36 #include "net/base/test_completion_callback.h"
37 #include "net/base/test_data_stream.h"
38 #include "net/cert/ct_policy_status.h"
39 #include "net/dns/public/host_resolver_results.h"
40 #include "net/dns/public/secure_dns_policy.h"
41 #include "net/http/http_request_info.h"
42 #include "net/http/transport_security_state_test_util.h"
43 #include "net/log/net_log.h"
44 #include "net/log/net_log_event_type.h"
45 #include "net/log/net_log_source.h"
46 #include "net/log/test_net_log.h"
47 #include "net/log/test_net_log_util.h"
48 #include "net/nqe/network_quality_estimator_test_util.h"
49 #include "net/socket/client_socket_pool.h"
50 #include "net/socket/client_socket_pool_manager.h"
51 #include "net/socket/socket_tag.h"
52 #include "net/socket/socket_test_util.h"
53 #include "net/socket/transport_connect_job.h"
54 #include "net/spdy/alps_decoder.h"
55 #include "net/spdy/spdy_http_utils.h"
56 #include "net/spdy/spdy_session_pool.h"
57 #include "net/spdy/spdy_session_test_util.h"
58 #include "net/spdy/spdy_stream.h"
59 #include "net/spdy/spdy_stream_test_util.h"
60 #include "net/spdy/spdy_test_util_common.h"
61 #include "net/test/cert_test_util.h"
62 #include "net/test/gtest_util.h"
63 #include "net/test/test_data_directory.h"
64 #include "net/test/test_with_task_environment.h"
65 #include "net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.h"
66 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
67 #include "testing/gmock/include/gmock/gmock.h"
68 #include "testing/platform_test.h"
69 #include "third_party/abseil-cpp/absl/types/optional.h"
70 #include "url/gurl.h"
71 #include "url/scheme_host_port.h"
72 #include "url/url_constants.h"
73
74 using net::test::IsError;
75 using net::test::IsOk;
76 using testing::_;
77
78 namespace net {
79
80 namespace {
81
82 const char kBodyData[] = "Body data";
83 const size_t kBodyDataSize = std::size(kBodyData);
84 const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
85
86 static base::TimeDelta g_time_delta;
87 static base::TimeTicks g_time_now;
88
TheNearFuture()89 base::TimeTicks TheNearFuture() {
90 return base::TimeTicks::Now() + g_time_delta;
91 }
92
SlowReads()93 base::TimeTicks SlowReads() {
94 g_time_delta += base::Milliseconds(2 * kYieldAfterDurationMilliseconds);
95 return base::TimeTicks::Now() + g_time_delta;
96 }
97
InstantaneousReads()98 base::TimeTicks InstantaneousReads() {
99 return g_time_now;
100 }
101
102 class MockRequireCTDelegate : public TransportSecurityState::RequireCTDelegate {
103 public:
104 MOCK_METHOD3(IsCTRequiredForHost,
105 CTRequirementLevel(const std::string& host,
106 const X509Certificate* chain,
107 const HashValueVector& hashes));
108 };
109
110 // SpdySessionRequest::Delegate implementation that does nothing. The test it's
111 // used in need to create a session request to trigger the creation of a session
112 // alias, but doesn't care about when or if OnSpdySessionAvailable() is invoked.
113 class SpdySessionRequestDelegate
114 : public SpdySessionPool::SpdySessionRequest::Delegate {
115 public:
116 SpdySessionRequestDelegate() = default;
117
118 SpdySessionRequestDelegate(const SpdySessionRequestDelegate&) = delete;
119 SpdySessionRequestDelegate& operator=(const SpdySessionRequestDelegate&) =
120 delete;
121
122 ~SpdySessionRequestDelegate() override = default;
123
OnSpdySessionAvailable(base::WeakPtr<SpdySession> spdy_session)124 void OnSpdySessionAvailable(
125 base::WeakPtr<SpdySession> spdy_session) override {}
126 };
127
128 } // namespace
129
130 class SpdySessionTest : public PlatformTest, public WithTaskEnvironment {
131 public:
132 // Functions used with RunResumeAfterUnstallTest().
133
StallSessionOnly(SpdyStream * stream)134 void StallSessionOnly(SpdyStream* stream) { StallSessionSend(); }
135
StallStreamOnly(SpdyStream * stream)136 void StallStreamOnly(SpdyStream* stream) { StallStreamSend(stream); }
137
StallSessionStream(SpdyStream * stream)138 void StallSessionStream(SpdyStream* stream) {
139 StallSessionSend();
140 StallStreamSend(stream);
141 }
142
StallStreamSession(SpdyStream * stream)143 void StallStreamSession(SpdyStream* stream) {
144 StallStreamSend(stream);
145 StallSessionSend();
146 }
147
UnstallSessionOnly(SpdyStream * stream,int32_t delta_window_size)148 void UnstallSessionOnly(SpdyStream* stream, int32_t delta_window_size) {
149 UnstallSessionSend(delta_window_size);
150 }
151
UnstallStreamOnly(SpdyStream * stream,int32_t delta_window_size)152 void UnstallStreamOnly(SpdyStream* stream, int32_t delta_window_size) {
153 UnstallStreamSend(stream, delta_window_size);
154 }
155
UnstallSessionStream(SpdyStream * stream,int32_t delta_window_size)156 void UnstallSessionStream(SpdyStream* stream, int32_t delta_window_size) {
157 UnstallSessionSend(delta_window_size);
158 UnstallStreamSend(stream, delta_window_size);
159 }
160
UnstallStreamSession(SpdyStream * stream,int32_t delta_window_size)161 void UnstallStreamSession(SpdyStream* stream, int32_t delta_window_size) {
162 UnstallStreamSend(stream, delta_window_size);
163 UnstallSessionSend(delta_window_size);
164 }
165
166 protected:
167 // Used by broken connection detection tests.
168 static constexpr base::TimeDelta kHeartbeatInterval = base::Seconds(10);
169
SpdySessionTest(base::test::TaskEnvironment::TimeSource time_source=base::test::TaskEnvironment::TimeSource::DEFAULT)170 explicit SpdySessionTest(base::test::TaskEnvironment::TimeSource time_source =
171 base::test::TaskEnvironment::TimeSource::DEFAULT)
172 : WithTaskEnvironment(time_source),
173 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
174 HttpNetworkSession::NORMAL_SOCKET_POOL)),
175 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
176 HttpNetworkSession::NORMAL_SOCKET_POOL)),
177 test_url_(kDefaultUrl),
178 test_server_(test_url_),
179 key_(HostPortPair::FromURL(test_url_),
180 ProxyChain::Direct(),
181 PRIVACY_MODE_DISABLED,
182 SpdySessionKey::IsProxySession::kFalse,
183 SocketTag(),
184 NetworkAnonymizationKey(),
185 SecureDnsPolicy::kAllow),
186 ssl_(SYNCHRONOUS, OK) {}
187
~SpdySessionTest()188 ~SpdySessionTest() override {
189 // Important to restore the per-pool limit first, since the pool limit must
190 // always be greater than group limit, and the tests reduce both limits.
191 ClientSocketPoolManager::set_max_sockets_per_pool(
192 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
193 ClientSocketPoolManager::set_max_sockets_per_group(
194 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
195 }
196
SetUp()197 void SetUp() override {
198 g_time_delta = base::TimeDelta();
199 g_time_now = base::TimeTicks::Now();
200 session_deps_.net_log = NetLog::Get();
201 session_deps_.enable_server_push_cancellation = true;
202 }
203
CreateNetworkSession()204 void CreateNetworkSession() {
205 DCHECK(!http_session_);
206 DCHECK(!spdy_session_pool_);
207 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
208 spdy_session_pool_ = http_session_->spdy_session_pool();
209 }
210
AddSSLSocketData()211 void AddSSLSocketData() {
212 ssl_.ssl_info.cert =
213 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
214 ASSERT_TRUE(ssl_.ssl_info.cert);
215 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
216 }
217
CreateSpdySession()218 void CreateSpdySession() {
219 DCHECK(!session_);
220 session_ = ::net::CreateSpdySession(http_session_.get(), key_,
221 net_log_with_source_);
222 }
223
StallSessionSend()224 void StallSessionSend() {
225 // Reduce the send window size to 0 to stall.
226 while (session_send_window_size() > 0) {
227 DecreaseSendWindowSize(
228 std::min(kMaxSpdyFrameChunkSize, session_send_window_size()));
229 }
230 }
231
UnstallSessionSend(int32_t delta_window_size)232 void UnstallSessionSend(int32_t delta_window_size) {
233 IncreaseSendWindowSize(delta_window_size);
234 }
235
StallStreamSend(SpdyStream * stream)236 void StallStreamSend(SpdyStream* stream) {
237 // Reduce the send window size to 0 to stall.
238 while (stream->send_window_size() > 0) {
239 stream->DecreaseSendWindowSize(
240 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
241 }
242 }
243
UnstallStreamSend(SpdyStream * stream,int32_t delta_window_size)244 void UnstallStreamSend(SpdyStream* stream, int32_t delta_window_size) {
245 stream->IncreaseSendWindowSize(delta_window_size);
246 }
247
248 void RunResumeAfterUnstallTest(
249 base::OnceCallback<void(SpdyStream*)> stall_function,
250 base::OnceCallback<void(SpdyStream*, int32_t)> unstall_function);
251
252 // SpdySession private methods.
253
MaybeSendPrefacePing()254 void MaybeSendPrefacePing() { session_->MaybeSendPrefacePing(); }
255
WritePingFrame(spdy::SpdyPingId unique_id,bool is_ack)256 void WritePingFrame(spdy::SpdyPingId unique_id, bool is_ack) {
257 session_->WritePingFrame(unique_id, is_ack);
258 }
259
CheckPingStatus(base::TimeTicks last_check_time)260 void CheckPingStatus(base::TimeTicks last_check_time) {
261 session_->CheckPingStatus(last_check_time);
262 }
263
OnUnknownFrame(spdy::SpdyStreamId stream_id,uint8_t frame_type)264 bool OnUnknownFrame(spdy::SpdyStreamId stream_id, uint8_t frame_type) {
265 return session_->OnUnknownFrame(stream_id, frame_type);
266 }
267
IncreaseSendWindowSize(int delta_window_size)268 void IncreaseSendWindowSize(int delta_window_size) {
269 session_->IncreaseSendWindowSize(delta_window_size);
270 }
271
DecreaseSendWindowSize(int32_t delta_window_size)272 void DecreaseSendWindowSize(int32_t delta_window_size) {
273 session_->DecreaseSendWindowSize(delta_window_size);
274 }
275
IncreaseRecvWindowSize(int delta_window_size)276 void IncreaseRecvWindowSize(int delta_window_size) {
277 session_->IncreaseRecvWindowSize(delta_window_size);
278 }
279
DecreaseRecvWindowSize(int32_t delta_window_size)280 void DecreaseRecvWindowSize(int32_t delta_window_size) {
281 session_->DecreaseRecvWindowSize(delta_window_size);
282 }
283
284 // Accessors for SpdySession private members.
285
set_in_io_loop(bool in_io_loop)286 void set_in_io_loop(bool in_io_loop) { session_->in_io_loop_ = in_io_loop; }
287
set_stream_hi_water_mark(spdy::SpdyStreamId stream_hi_water_mark)288 void set_stream_hi_water_mark(spdy::SpdyStreamId stream_hi_water_mark) {
289 session_->stream_hi_water_mark_ = stream_hi_water_mark;
290 }
291
max_concurrent_streams()292 size_t max_concurrent_streams() { return session_->max_concurrent_streams_; }
293
set_max_concurrent_streams(size_t max_concurrent_streams)294 void set_max_concurrent_streams(size_t max_concurrent_streams) {
295 session_->max_concurrent_streams_ = max_concurrent_streams;
296 }
297
ping_in_flight()298 bool ping_in_flight() { return session_->ping_in_flight_; }
299
next_ping_id()300 spdy::SpdyPingId next_ping_id() { return session_->next_ping_id_; }
301
last_read_time()302 base::TimeTicks last_read_time() { return session_->last_read_time_; }
303
check_ping_status_pending()304 bool check_ping_status_pending() {
305 return session_->check_ping_status_pending_;
306 }
307
session_send_window_size()308 int32_t session_send_window_size() {
309 return session_->session_send_window_size_;
310 }
311
session_recv_window_size()312 int32_t session_recv_window_size() {
313 return session_->session_recv_window_size_;
314 }
315
set_session_recv_window_size(int32_t session_recv_window_size)316 void set_session_recv_window_size(int32_t session_recv_window_size) {
317 session_->session_recv_window_size_ = session_recv_window_size;
318 }
319
session_unacked_recv_window_bytes()320 int32_t session_unacked_recv_window_bytes() {
321 return session_->session_unacked_recv_window_bytes_;
322 }
323
stream_initial_send_window_size()324 int32_t stream_initial_send_window_size() {
325 return session_->stream_initial_send_window_size_;
326 }
327
set_connection_at_risk_of_loss_time(base::TimeDelta duration)328 void set_connection_at_risk_of_loss_time(base::TimeDelta duration) {
329 session_->connection_at_risk_of_loss_time_ = duration;
330 }
331
332 // Quantities derived from SpdySession private members.
333
pending_create_stream_queue_size(RequestPriority priority)334 size_t pending_create_stream_queue_size(RequestPriority priority) {
335 DCHECK_GE(priority, MINIMUM_PRIORITY);
336 DCHECK_LE(priority, MAXIMUM_PRIORITY);
337 return session_->pending_create_stream_queues_[priority].size();
338 }
339
num_active_streams()340 size_t num_active_streams() { return session_->active_streams_.size(); }
341
num_created_streams()342 size_t num_created_streams() { return session_->created_streams_.size(); }
343
header_encoder_table_size() const344 uint32_t header_encoder_table_size() const {
345 return session_->buffered_spdy_framer_->header_encoder_table_size();
346 }
347
348 RecordingNetLogObserver net_log_observer_;
349 NetLogWithSource net_log_with_source_{
350 NetLogWithSource::Make(NetLogSourceType::NONE)};
351
352 // Original socket limits. Some tests set these. Safest to always restore
353 // them once each test has been run.
354 int old_max_group_sockets_;
355 int old_max_pool_sockets_;
356
357 SpdyTestUtil spdy_util_;
358 SpdySessionDependencies session_deps_;
359 std::unique_ptr<HttpNetworkSession> http_session_;
360 base::WeakPtr<SpdySession> session_;
361 raw_ptr<SpdySessionPool> spdy_session_pool_ = nullptr;
362 const GURL test_url_;
363 const url::SchemeHostPort test_server_;
364 SpdySessionKey key_;
365 SSLSocketDataProvider ssl_;
366 };
367
368 class SpdySessionTestWithMockTime : public SpdySessionTest {
369 protected:
SpdySessionTestWithMockTime()370 SpdySessionTestWithMockTime()
371 : SpdySessionTest(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
372 };
373
374 // Try to create a SPDY session that will fail during
375 // initialization. Nothing should blow up.
TEST_F(SpdySessionTest,InitialReadError)376 TEST_F(SpdySessionTest, InitialReadError) {
377 MockRead reads[] = {MockRead(ASYNC, ERR_CONNECTION_CLOSED, 0)};
378 SequencedSocketData data(reads, base::span<MockWrite>());
379 session_deps_.socket_factory->AddSocketDataProvider(&data);
380
381 AddSSLSocketData();
382
383 CreateNetworkSession();
384 CreateSpdySession();
385
386 EXPECT_TRUE(session_);
387 // Flush the read.
388 base::RunLoop().RunUntilIdle();
389 EXPECT_FALSE(session_);
390 }
391
392 namespace {
393
394 // A helper class that vends a callback that, when fired, destroys a
395 // given SpdyStreamRequest.
396 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
397 public:
398 StreamRequestDestroyingCallback() = default;
399
400 ~StreamRequestDestroyingCallback() override = default;
401
SetRequestToDestroy(std::unique_ptr<SpdyStreamRequest> request)402 void SetRequestToDestroy(std::unique_ptr<SpdyStreamRequest> request) {
403 request_ = std::move(request);
404 }
405
MakeCallback()406 CompletionOnceCallback MakeCallback() {
407 return base::BindOnce(&StreamRequestDestroyingCallback::OnComplete,
408 base::Unretained(this));
409 }
410
411 private:
OnComplete(int result)412 void OnComplete(int result) {
413 request_.reset();
414 SetResult(result);
415 }
416
417 std::unique_ptr<SpdyStreamRequest> request_;
418 };
419
420 } // namespace
421
422 // Request kH2InitialMaxConcurrentStreamsParam.Get() streams. Request two more
423 // streams, but have the callback for one destroy the second stream
424 // request. Close the session. Nothing should blow up. This is a
425 // regression test for http://crbug.com/250841 .
TEST_F(SpdySessionTest,PendingStreamCancellingAnother)426 TEST_F(SpdySessionTest, PendingStreamCancellingAnother) {
427 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
428
429 SequencedSocketData data(reads, base::span<MockWrite>());
430 session_deps_.socket_factory->AddSocketDataProvider(&data);
431
432 AddSSLSocketData();
433
434 CreateNetworkSession();
435 CreateSpdySession();
436
437 // Create the maximum number of concurrent streams.
438 for (int i = 0; i < kH2InitialMaxConcurrentStreams.Get(); ++i) {
439 base::WeakPtr<SpdyStream> spdy_stream =
440 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_,
441 test_url_, MEDIUM, NetLogWithSource());
442 ASSERT_TRUE(spdy_stream);
443 }
444
445 SpdyStreamRequest request1;
446 auto request2 = std::make_unique<SpdyStreamRequest>();
447
448 StreamRequestDestroyingCallback callback1;
449 ASSERT_EQ(ERR_IO_PENDING,
450 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_,
451 test_url_, false, MEDIUM, SocketTag(),
452 NetLogWithSource(), callback1.MakeCallback(),
453 TRAFFIC_ANNOTATION_FOR_TESTS));
454
455 // |callback2| is never called.
456 TestCompletionCallback callback2;
457 ASSERT_EQ(ERR_IO_PENDING,
458 request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_,
459 test_url_, false, MEDIUM, SocketTag(),
460 NetLogWithSource(), callback2.callback(),
461 TRAFFIC_ANNOTATION_FOR_TESTS));
462
463 callback1.SetRequestToDestroy(std::move(request2));
464
465 session_->CloseSessionOnError(ERR_ABORTED, "Aborting session");
466
467 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_ABORTED));
468 }
469
470 // A session receiving a GOAWAY frame with no active streams should close.
TEST_F(SpdySessionTest,GoAwayWithNoActiveStreams)471 TEST_F(SpdySessionTest, GoAwayWithNoActiveStreams) {
472 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1));
473 MockRead reads[] = {
474 CreateMockRead(goaway, 0),
475 };
476 SequencedSocketData data(reads, base::span<MockWrite>());
477 session_deps_.socket_factory->AddSocketDataProvider(&data);
478
479 AddSSLSocketData();
480
481 CreateNetworkSession();
482 CreateSpdySession();
483
484 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
485
486 // Read and process the GOAWAY frame.
487 base::RunLoop().RunUntilIdle();
488 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
489 EXPECT_FALSE(session_);
490 }
491
492 // A session receiving a GOAWAY frame immediately with no active
493 // streams should then close.
TEST_F(SpdySessionTest,GoAwayImmediatelyWithNoActiveStreams)494 TEST_F(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
495 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1));
496 MockRead reads[] = {
497 CreateMockRead(goaway, 0, SYNCHRONOUS), MockRead(ASYNC, 0, 1) // EOF
498 };
499 SequencedSocketData data(reads, base::span<MockWrite>());
500 session_deps_.socket_factory->AddSocketDataProvider(&data);
501
502 AddSSLSocketData();
503
504 CreateNetworkSession();
505 CreateSpdySession();
506 base::RunLoop().RunUntilIdle();
507
508 EXPECT_FALSE(session_);
509 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
510 EXPECT_FALSE(data.AllReadDataConsumed());
511 }
512
513 // A session receiving a GOAWAY frame with active streams should close
514 // when the last active stream is closed.
TEST_F(SpdySessionTest,GoAwayWithActiveStreams)515 TEST_F(SpdySessionTest, GoAwayWithActiveStreams) {
516 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1));
517 MockRead reads[] = {
518 MockRead(ASYNC, ERR_IO_PENDING, 2), CreateMockRead(goaway, 3),
519 MockRead(ASYNC, ERR_IO_PENDING, 4), MockRead(ASYNC, 0, 5) // EOF
520 };
521 spdy::SpdySerializedFrame req1(
522 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
523 spdy::SpdySerializedFrame req2(
524 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM));
525 MockWrite writes[] = {
526 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
527 };
528 SequencedSocketData data(reads, writes);
529 session_deps_.socket_factory->AddSocketDataProvider(&data);
530
531 AddSSLSocketData();
532
533 CreateNetworkSession();
534 CreateSpdySession();
535
536 base::WeakPtr<SpdyStream> spdy_stream1 =
537 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
538 test_url_, MEDIUM, NetLogWithSource());
539 test::StreamDelegateDoNothing delegate1(spdy_stream1);
540 spdy_stream1->SetDelegate(&delegate1);
541
542 base::WeakPtr<SpdyStream> spdy_stream2 =
543 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
544 test_url_, MEDIUM, NetLogWithSource());
545 test::StreamDelegateDoNothing delegate2(spdy_stream2);
546 spdy_stream2->SetDelegate(&delegate2);
547
548 spdy::Http2HeaderBlock headers(
549 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
550 spdy::Http2HeaderBlock headers2(headers.Clone());
551
552 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
553 spdy_stream2->SendRequestHeaders(std::move(headers2), NO_MORE_DATA_TO_SEND);
554
555 base::RunLoop().RunUntilIdle();
556
557 EXPECT_EQ(1u, spdy_stream1->stream_id());
558 EXPECT_EQ(3u, spdy_stream2->stream_id());
559
560 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
561
562 // Read and process the GOAWAY frame.
563 data.Resume();
564 base::RunLoop().RunUntilIdle();
565
566 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
567
568 EXPECT_FALSE(session_->IsStreamActive(3));
569 EXPECT_FALSE(spdy_stream2);
570 EXPECT_TRUE(session_->IsStreamActive(1));
571
572 EXPECT_TRUE(session_->IsGoingAway());
573
574 // Should close the session.
575 spdy_stream1->Close();
576 EXPECT_FALSE(spdy_stream1);
577
578 EXPECT_TRUE(session_);
579 data.Resume();
580 base::RunLoop().RunUntilIdle();
581 EXPECT_FALSE(session_);
582 }
583
584 // Regression test for https://crbug.com/547130.
TEST_F(SpdySessionTest,GoAwayWithActiveAndCreatedStream)585 TEST_F(SpdySessionTest, GoAwayWithActiveAndCreatedStream) {
586 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(0));
587 MockRead reads[] = {
588 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(goaway, 2),
589 };
590
591 // No |req2|, because the second stream will never get activated.
592 spdy::SpdySerializedFrame req1(
593 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
594 MockWrite writes[] = {
595 CreateMockWrite(req1, 0),
596 };
597 SequencedSocketData data(reads, writes);
598 session_deps_.socket_factory->AddSocketDataProvider(&data);
599
600 AddSSLSocketData();
601
602 CreateNetworkSession();
603 CreateSpdySession();
604
605 base::WeakPtr<SpdyStream> spdy_stream1 =
606 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
607 test_url_, MEDIUM, NetLogWithSource());
608 test::StreamDelegateDoNothing delegate1(spdy_stream1);
609 spdy_stream1->SetDelegate(&delegate1);
610 spdy::Http2HeaderBlock headers1(
611 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
612 spdy_stream1->SendRequestHeaders(std::move(headers1), NO_MORE_DATA_TO_SEND);
613
614 EXPECT_EQ(0u, spdy_stream1->stream_id());
615
616 // Active stream 1.
617 base::RunLoop().RunUntilIdle();
618 EXPECT_EQ(1u, spdy_stream1->stream_id());
619 EXPECT_TRUE(session_->IsStreamActive(1));
620
621 // Create stream corresponding to the next request.
622 base::WeakPtr<SpdyStream> spdy_stream2 =
623 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
624 test_url_, MEDIUM, NetLogWithSource());
625
626 EXPECT_EQ(0u, spdy_stream2->stream_id());
627
628 // Read and process the GOAWAY frame before the second stream could be
629 // activated.
630 data.Resume();
631 base::RunLoop().RunUntilIdle();
632
633 EXPECT_FALSE(session_);
634
635 EXPECT_TRUE(data.AllWriteDataConsumed());
636 EXPECT_TRUE(data.AllReadDataConsumed());
637 }
638
639 // Have a session receive two GOAWAY frames, with the last one causing
640 // the last active stream to be closed. The session should then be
641 // closed after the second GOAWAY frame.
TEST_F(SpdySessionTest,GoAwayTwice)642 TEST_F(SpdySessionTest, GoAwayTwice) {
643 spdy::SpdySerializedFrame goaway1(spdy_util_.ConstructSpdyGoAway(1));
644 spdy::SpdySerializedFrame goaway2(spdy_util_.ConstructSpdyGoAway(0));
645 MockRead reads[] = {
646 MockRead(ASYNC, ERR_IO_PENDING, 2), CreateMockRead(goaway1, 3),
647 MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(goaway2, 5),
648 MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7) // EOF
649 };
650 spdy::SpdySerializedFrame req1(
651 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
652 spdy::SpdySerializedFrame req2(
653 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM));
654 MockWrite writes[] = {
655 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
656 };
657 SequencedSocketData data(reads, writes);
658 session_deps_.socket_factory->AddSocketDataProvider(&data);
659
660 AddSSLSocketData();
661
662 CreateNetworkSession();
663 CreateSpdySession();
664
665 base::WeakPtr<SpdyStream> spdy_stream1 =
666 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
667 test_url_, MEDIUM, NetLogWithSource());
668 test::StreamDelegateDoNothing delegate1(spdy_stream1);
669 spdy_stream1->SetDelegate(&delegate1);
670
671 base::WeakPtr<SpdyStream> spdy_stream2 =
672 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
673 test_url_, MEDIUM, NetLogWithSource());
674 test::StreamDelegateDoNothing delegate2(spdy_stream2);
675 spdy_stream2->SetDelegate(&delegate2);
676
677 spdy::Http2HeaderBlock headers(
678 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
679 spdy::Http2HeaderBlock headers2(headers.Clone());
680
681 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
682 spdy_stream2->SendRequestHeaders(std::move(headers2), NO_MORE_DATA_TO_SEND);
683
684 base::RunLoop().RunUntilIdle();
685
686 EXPECT_EQ(1u, spdy_stream1->stream_id());
687 EXPECT_EQ(3u, spdy_stream2->stream_id());
688
689 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
690
691 // Read and process the first GOAWAY frame.
692 data.Resume();
693 base::RunLoop().RunUntilIdle();
694
695 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
696
697 EXPECT_FALSE(session_->IsStreamActive(3));
698 EXPECT_FALSE(spdy_stream2);
699 EXPECT_TRUE(session_->IsStreamActive(1));
700 EXPECT_TRUE(session_->IsGoingAway());
701
702 // Read and process the second GOAWAY frame, which should close the
703 // session.
704 data.Resume();
705 base::RunLoop().RunUntilIdle();
706 EXPECT_FALSE(session_);
707 }
708
709 // Have a session with active streams receive a GOAWAY frame and then
710 // close it. It should handle the close properly (i.e., not try to
711 // make itself unavailable in its pool twice).
TEST_F(SpdySessionTest,GoAwayWithActiveStreamsThenClose)712 TEST_F(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
713 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1));
714 MockRead reads[] = {
715 MockRead(ASYNC, ERR_IO_PENDING, 2), CreateMockRead(goaway, 3),
716 MockRead(ASYNC, ERR_IO_PENDING, 4), MockRead(ASYNC, 0, 5) // EOF
717 };
718 spdy::SpdySerializedFrame req1(
719 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
720 spdy::SpdySerializedFrame req2(
721 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM));
722 MockWrite writes[] = {
723 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
724 };
725 SequencedSocketData data(reads, writes);
726 session_deps_.socket_factory->AddSocketDataProvider(&data);
727
728 AddSSLSocketData();
729
730 CreateNetworkSession();
731 CreateSpdySession();
732
733 base::WeakPtr<SpdyStream> spdy_stream1 =
734 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
735 test_url_, MEDIUM, NetLogWithSource());
736 test::StreamDelegateDoNothing delegate1(spdy_stream1);
737 spdy_stream1->SetDelegate(&delegate1);
738
739 base::WeakPtr<SpdyStream> spdy_stream2 =
740 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
741 test_url_, MEDIUM, NetLogWithSource());
742 test::StreamDelegateDoNothing delegate2(spdy_stream2);
743 spdy_stream2->SetDelegate(&delegate2);
744
745 spdy::Http2HeaderBlock headers(
746 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
747 spdy::Http2HeaderBlock headers2(headers.Clone());
748
749 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
750 spdy_stream2->SendRequestHeaders(std::move(headers2), NO_MORE_DATA_TO_SEND);
751
752 base::RunLoop().RunUntilIdle();
753
754 EXPECT_EQ(1u, spdy_stream1->stream_id());
755 EXPECT_EQ(3u, spdy_stream2->stream_id());
756
757 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
758
759 // Read and process the GOAWAY frame.
760 data.Resume();
761 base::RunLoop().RunUntilIdle();
762
763 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
764
765 EXPECT_FALSE(session_->IsStreamActive(3));
766 EXPECT_FALSE(spdy_stream2);
767 EXPECT_TRUE(session_->IsStreamActive(1));
768 EXPECT_TRUE(session_->IsGoingAway());
769
770 session_->CloseSessionOnError(ERR_ABORTED, "Aborting session");
771 EXPECT_FALSE(spdy_stream1);
772
773 data.Resume();
774 base::RunLoop().RunUntilIdle();
775 EXPECT_FALSE(session_);
776 }
777
778 // Process a joint read buffer which causes the session to begin draining, and
779 // then processes a GOAWAY. The session should gracefully drain. Regression test
780 // for crbug.com/379469
TEST_F(SpdySessionTest,GoAwayWhileDraining)781 TEST_F(SpdySessionTest, GoAwayWhileDraining) {
782 spdy::SpdySerializedFrame req(
783 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
784 MockWrite writes[] = {
785 CreateMockWrite(req, 0),
786 };
787
788 spdy::SpdySerializedFrame resp(
789 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
790 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1));
791 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
792 size_t joint_size = goaway.size() * 2 + body.size();
793
794 // Compose interleaved |goaway| and |body| frames into a single read.
795 auto buffer = std::make_unique<char[]>(joint_size);
796 {
797 size_t out = 0;
798 memcpy(&buffer[out], goaway.data(), goaway.size());
799 out += goaway.size();
800 memcpy(&buffer[out], body.data(), body.size());
801 out += body.size();
802 memcpy(&buffer[out], goaway.data(), goaway.size());
803 out += goaway.size();
804 ASSERT_EQ(out, joint_size);
805 }
806 spdy::SpdySerializedFrame joint_frames(buffer.get(), joint_size, false);
807
808 MockRead reads[] = {
809 CreateMockRead(resp, 1), CreateMockRead(joint_frames, 2),
810 MockRead(ASYNC, 0, 3) // EOF
811 };
812
813 SequencedSocketData data(reads, writes);
814 session_deps_.socket_factory->AddSocketDataProvider(&data);
815
816 AddSSLSocketData();
817
818 CreateNetworkSession();
819 CreateSpdySession();
820
821 base::WeakPtr<SpdyStream> spdy_stream =
822 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
823 test_url_, MEDIUM, NetLogWithSource());
824 test::StreamDelegateDoNothing delegate(spdy_stream);
825 spdy_stream->SetDelegate(&delegate);
826
827 spdy::Http2HeaderBlock headers(
828 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
829 spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
830
831 base::RunLoop().RunUntilIdle();
832
833 // Stream and session closed gracefully.
834 EXPECT_TRUE(delegate.StreamIsClosed());
835 EXPECT_THAT(delegate.WaitForClose(), IsOk());
836 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
837 EXPECT_FALSE(session_);
838 }
839
840 // Try to create a stream after receiving a GOAWAY frame. It should
841 // fail.
TEST_F(SpdySessionTest,CreateStreamAfterGoAway)842 TEST_F(SpdySessionTest, CreateStreamAfterGoAway) {
843 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1));
844 MockRead reads[] = {
845 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(goaway, 2),
846 MockRead(ASYNC, ERR_IO_PENDING, 3), MockRead(ASYNC, 0, 4) // EOF
847 };
848 spdy::SpdySerializedFrame req(
849 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
850 MockWrite writes[] = {
851 CreateMockWrite(req, 0),
852 };
853 SequencedSocketData data(reads, writes);
854 session_deps_.socket_factory->AddSocketDataProvider(&data);
855
856 AddSSLSocketData();
857
858 CreateNetworkSession();
859 CreateSpdySession();
860
861 base::WeakPtr<SpdyStream> spdy_stream =
862 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
863 test_url_, MEDIUM, NetLogWithSource());
864 test::StreamDelegateDoNothing delegate(spdy_stream);
865 spdy_stream->SetDelegate(&delegate);
866
867 spdy::Http2HeaderBlock headers(
868 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
869 spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
870
871 base::RunLoop().RunUntilIdle();
872
873 EXPECT_EQ(1u, spdy_stream->stream_id());
874
875 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
876
877 // Read and process the GOAWAY frame.
878 data.Resume();
879 base::RunLoop().RunUntilIdle();
880
881 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
882 EXPECT_TRUE(session_->IsStreamActive(1));
883
884 SpdyStreamRequest stream_request;
885 int rv = stream_request.StartRequest(
886 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, false, MEDIUM,
887 SocketTag(), NetLogWithSource(), CompletionOnceCallback(),
888 TRAFFIC_ANNOTATION_FOR_TESTS);
889 EXPECT_THAT(rv, IsError(ERR_FAILED));
890
891 EXPECT_TRUE(session_);
892 data.Resume();
893 base::RunLoop().RunUntilIdle();
894 EXPECT_FALSE(session_);
895 }
896
897 // Receiving a HEADERS frame after a GOAWAY frame should result in
898 // the stream being refused.
TEST_F(SpdySessionTest,HeadersAfterGoAway)899 TEST_F(SpdySessionTest, HeadersAfterGoAway) {
900 spdy::SpdySerializedFrame goaway_received(spdy_util_.ConstructSpdyGoAway(1));
901 spdy::SpdySerializedFrame push(spdy_util_.ConstructSpdyPushPromise(1, 2, {}));
902 MockRead reads[] = {
903 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(goaway_received, 2),
904 MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(push, 4),
905 MockRead(ASYNC, 0, 6) // EOF
906 };
907 spdy::SpdySerializedFrame req(
908 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
909 spdy::SpdySerializedFrame goaway_sent(spdy_util_.ConstructSpdyGoAway(
910 0, spdy::ERROR_CODE_PROTOCOL_ERROR, "PUSH_PROMISE received"));
911 MockWrite writes[] = {CreateMockWrite(req, 0),
912 CreateMockWrite(goaway_sent, 5)};
913 SequencedSocketData data(reads, writes);
914 session_deps_.socket_factory->AddSocketDataProvider(&data);
915
916 AddSSLSocketData();
917
918 CreateNetworkSession();
919 CreateSpdySession();
920
921 base::WeakPtr<SpdyStream> spdy_stream =
922 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
923 test_url_, MEDIUM, NetLogWithSource());
924 test::StreamDelegateDoNothing delegate(spdy_stream);
925 spdy_stream->SetDelegate(&delegate);
926
927 spdy::Http2HeaderBlock headers(
928 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
929 spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
930
931 base::RunLoop().RunUntilIdle();
932
933 EXPECT_EQ(1u, spdy_stream->stream_id());
934
935 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
936
937 // Read and process the GOAWAY frame.
938 data.Resume();
939 base::RunLoop().RunUntilIdle();
940
941 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
942 EXPECT_TRUE(session_->IsStreamActive(1));
943
944 // Read and process the HEADERS frame, the subsequent RST_STREAM,
945 // and EOF.
946 data.Resume();
947 base::RunLoop().RunUntilIdle();
948 EXPECT_FALSE(session_);
949 }
950
951 // A session observing a network change with active streams should close
952 // when the last active stream is closed.
TEST_F(SpdySessionTest,NetworkChangeWithActiveStreams)953 TEST_F(SpdySessionTest, NetworkChangeWithActiveStreams) {
954 MockRead reads[] = {
955 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
956 };
957 spdy::SpdySerializedFrame req1(
958 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
959 MockWrite writes[] = {
960 CreateMockWrite(req1, 0),
961 };
962 SequencedSocketData data(reads, writes);
963 session_deps_.socket_factory->AddSocketDataProvider(&data);
964
965 AddSSLSocketData();
966
967 CreateNetworkSession();
968 CreateSpdySession();
969
970 base::WeakPtr<SpdyStream> spdy_stream =
971 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
972 test_url_, MEDIUM, NetLogWithSource());
973 test::StreamDelegateDoNothing delegate(spdy_stream);
974 spdy_stream->SetDelegate(&delegate);
975
976 spdy::Http2HeaderBlock headers(
977 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
978
979 spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
980
981 base::RunLoop().RunUntilIdle();
982
983 EXPECT_EQ(1u, spdy_stream->stream_id());
984
985 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
986
987 spdy_session_pool_->OnIPAddressChanged();
988
989 // The SpdySessionPool behavior differs based on how the OSs reacts to
990 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
991 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
992 // For OSs where the TCP connections will close upon relevant network
993 // changes, SpdySessionPool doesn't need to force them to close, so in these
994 // cases verify the session has become unavailable but remains open and the
995 // pre-existing stream is still active.
996 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
997
998 EXPECT_TRUE(session_->IsGoingAway());
999
1000 EXPECT_TRUE(session_->IsStreamActive(1));
1001
1002 // Should close the session.
1003 spdy_stream->Close();
1004 #endif
1005 EXPECT_FALSE(spdy_stream);
1006
1007 data.Resume();
1008 base::RunLoop().RunUntilIdle();
1009 EXPECT_FALSE(session_);
1010 }
1011
TEST_F(SpdySessionTestWithMockTime,ClientPing)1012 TEST_F(SpdySessionTestWithMockTime, ClientPing) {
1013 session_deps_.enable_ping = true;
1014
1015 spdy::SpdySerializedFrame read_ping(spdy_util_.ConstructSpdyPing(1, true));
1016 MockRead reads[] = {
1017 CreateMockRead(read_ping, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1018 MockRead(ASYNC, 0, 3) // EOF
1019 };
1020 spdy::SpdySerializedFrame write_ping(spdy_util_.ConstructSpdyPing(1, false));
1021 MockWrite writes[] = {
1022 CreateMockWrite(write_ping, 0),
1023 };
1024 SequencedSocketData data(reads, writes);
1025 session_deps_.socket_factory->AddSocketDataProvider(&data);
1026
1027 AddSSLSocketData();
1028
1029 CreateNetworkSession();
1030 TestNetworkQualityEstimator estimator;
1031
1032 spdy_session_pool_->set_network_quality_estimator(&estimator);
1033
1034 CreateSpdySession();
1035
1036 base::WeakPtr<SpdyStream> spdy_stream1 =
1037 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1038 MEDIUM, NetLogWithSource());
1039 ASSERT_TRUE(spdy_stream1);
1040 test::StreamDelegateSendImmediate delegate(spdy_stream1, "");
1041 spdy_stream1->SetDelegate(&delegate);
1042
1043 base::TimeTicks before_ping_time = base::TimeTicks::Now();
1044
1045 // Negative value means a preface ping will always be sent.
1046 set_connection_at_risk_of_loss_time(base::Seconds(-1));
1047
1048 // Send a PING frame. This posts CheckPingStatus() with delay.
1049 MaybeSendPrefacePing();
1050
1051 EXPECT_TRUE(ping_in_flight());
1052 EXPECT_EQ(2u, next_ping_id());
1053 EXPECT_TRUE(check_ping_status_pending());
1054
1055 // MaybeSendPrefacePing() should not send another PING frame if there is
1056 // already one in flight.
1057 MaybeSendPrefacePing();
1058
1059 EXPECT_TRUE(ping_in_flight());
1060 EXPECT_EQ(2u, next_ping_id());
1061 EXPECT_TRUE(check_ping_status_pending());
1062
1063 // Run posted CheckPingStatus() task.
1064 FastForwardUntilNoTasksRemain();
1065 base::RunLoop().RunUntilIdle();
1066
1067 EXPECT_FALSE(ping_in_flight());
1068 EXPECT_EQ(2u, next_ping_id());
1069 EXPECT_FALSE(check_ping_status_pending());
1070 EXPECT_GE(last_read_time(), before_ping_time);
1071
1072 data.Resume();
1073 base::RunLoop().RunUntilIdle();
1074
1075 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
1076
1077 EXPECT_TRUE(MainThreadIsIdle());
1078 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1079 EXPECT_FALSE(session_);
1080 EXPECT_FALSE(spdy_stream1);
1081
1082 EXPECT_TRUE(data.AllWriteDataConsumed());
1083 EXPECT_TRUE(data.AllReadDataConsumed());
1084
1085 EXPECT_LE(1u, estimator.ping_rtt_received_count());
1086 }
1087
TEST_F(SpdySessionTest,ServerPing)1088 TEST_F(SpdySessionTest, ServerPing) {
1089 spdy::SpdySerializedFrame read_ping(spdy_util_.ConstructSpdyPing(2, false));
1090 MockRead reads[] = {
1091 CreateMockRead(read_ping), MockRead(SYNCHRONOUS, 0, 0) // EOF
1092 };
1093 spdy::SpdySerializedFrame write_ping(spdy_util_.ConstructSpdyPing(2, true));
1094 MockWrite writes[] = {
1095 CreateMockWrite(write_ping),
1096 };
1097 StaticSocketDataProvider data(reads, writes);
1098 session_deps_.socket_factory->AddSocketDataProvider(&data);
1099
1100 AddSSLSocketData();
1101
1102 CreateNetworkSession();
1103 CreateSpdySession();
1104
1105 base::WeakPtr<SpdyStream> spdy_stream1 =
1106 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1107 MEDIUM, NetLogWithSource());
1108 ASSERT_TRUE(spdy_stream1);
1109 test::StreamDelegateSendImmediate delegate(spdy_stream1, "");
1110 spdy_stream1->SetDelegate(&delegate);
1111
1112 // Flush the read completion task.
1113 base::RunLoop().RunUntilIdle();
1114
1115 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1116
1117 EXPECT_FALSE(session_);
1118 EXPECT_FALSE(spdy_stream1);
1119 }
1120
1121 // Cause a ping to be sent out while producing a write. The write loop
1122 // should handle this properly, i.e. another DoWriteLoop task should
1123 // not be posted. This is a regression test for
1124 // http://crbug.com/261043 .
TEST_F(SpdySessionTest,PingAndWriteLoop)1125 TEST_F(SpdySessionTest, PingAndWriteLoop) {
1126 session_deps_.enable_ping = true;
1127 session_deps_.time_func = TheNearFuture;
1128
1129 spdy::SpdySerializedFrame write_ping(spdy_util_.ConstructSpdyPing(1, false));
1130 spdy::SpdySerializedFrame req(
1131 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1132 MockWrite writes[] = {
1133 CreateMockWrite(req, 0), CreateMockWrite(write_ping, 1),
1134 };
1135
1136 MockRead reads[] = {
1137 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
1138 };
1139
1140 SequencedSocketData data(reads, writes);
1141 session_deps_.socket_factory->AddSocketDataProvider(&data);
1142
1143 AddSSLSocketData();
1144
1145 CreateNetworkSession();
1146 CreateSpdySession();
1147
1148 base::WeakPtr<SpdyStream> spdy_stream =
1149 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1150 test_url_, LOWEST, NetLogWithSource());
1151 test::StreamDelegateDoNothing delegate(spdy_stream);
1152 spdy_stream->SetDelegate(&delegate);
1153
1154 spdy::Http2HeaderBlock headers(
1155 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1156 spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1157
1158 // Shift time so that a ping will be sent out.
1159 g_time_delta = base::Seconds(11);
1160
1161 base::RunLoop().RunUntilIdle();
1162 session_->CloseSessionOnError(ERR_ABORTED, "Aborting");
1163
1164 data.Resume();
1165 base::RunLoop().RunUntilIdle();
1166 EXPECT_FALSE(session_);
1167 }
1168
TEST_F(SpdySessionTestWithMockTime,DetectBrokenConnectionPing)1169 TEST_F(SpdySessionTestWithMockTime, DetectBrokenConnectionPing) {
1170 session_deps_.enable_ping = true;
1171
1172 spdy::SpdySerializedFrame read_ping1(spdy_util_.ConstructSpdyPing(1, true));
1173 spdy::SpdySerializedFrame read_ping2(spdy_util_.ConstructSpdyPing(2, true));
1174 MockRead reads[] = {
1175 MockRead(ASYNC, ERR_IO_PENDING, 1),
1176 CreateMockRead(read_ping1, 2),
1177 MockRead(ASYNC, ERR_IO_PENDING, 3),
1178 MockRead(ASYNC, ERR_IO_PENDING, 5),
1179 CreateMockRead(read_ping2, 6),
1180 MockRead(ASYNC, ERR_IO_PENDING, 7),
1181 MockRead(ASYNC, 0, 8) // EOF
1182 };
1183 spdy::SpdySerializedFrame write_ping1(spdy_util_.ConstructSpdyPing(1, false));
1184 spdy::SpdySerializedFrame write_ping2(spdy_util_.ConstructSpdyPing(2, false));
1185 MockWrite writes[] = {CreateMockWrite(write_ping1, 0),
1186 CreateMockWrite(write_ping2, 4)};
1187 SequencedSocketData data(reads, writes);
1188 session_deps_.socket_factory->AddSocketDataProvider(&data);
1189
1190 AddSSLSocketData();
1191
1192 CreateNetworkSession();
1193 TestNetworkQualityEstimator estimator;
1194
1195 spdy_session_pool_->set_network_quality_estimator(&estimator);
1196
1197 CreateSpdySession();
1198
1199 constexpr base::TimeDelta kHeartbeatInterval = base::Seconds(15);
1200 ASSERT_FALSE(session_->IsBrokenConnectionDetectionEnabled());
1201 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1202 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM,
1203 NetLogWithSource(), true, kHeartbeatInterval);
1204 ASSERT_TRUE(spdy_stream1);
1205 ASSERT_TRUE(session_->IsBrokenConnectionDetectionEnabled());
1206 test::StreamDelegateSendImmediate delegate(spdy_stream1, "");
1207 spdy_stream1->SetDelegate(&delegate);
1208
1209 // Negative value means a preface ping will always be sent.
1210 set_connection_at_risk_of_loss_time(base::Seconds(-1));
1211
1212 // Initially there should be no PING in flight or check pending.
1213 EXPECT_FALSE(ping_in_flight());
1214 EXPECT_FALSE(check_ping_status_pending());
1215 // After kHeartbeatInterval time has passed the first PING should be in flight
1216 // and its status check pending.
1217 FastForwardBy(kHeartbeatInterval);
1218 EXPECT_TRUE(ping_in_flight());
1219 EXPECT_TRUE(check_ping_status_pending());
1220
1221 // Consume the PING ack.
1222 data.Resume();
1223 base::RunLoop run_loop;
1224 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1225 FROM_HERE, run_loop.QuitClosure());
1226 run_loop.Run();
1227 EXPECT_FALSE(ping_in_flight());
1228 EXPECT_TRUE(check_ping_status_pending());
1229 // Consume the pending check_ping_status callback, we should be back to the
1230 // starting state.
1231 FastForwardBy(NextMainThreadPendingTaskDelay());
1232 EXPECT_FALSE(ping_in_flight());
1233 EXPECT_FALSE(check_ping_status_pending());
1234
1235 // Unblock data and trigger the next heartbeat.
1236 data.Resume();
1237 FastForwardBy(NextMainThreadPendingTaskDelay());
1238 EXPECT_TRUE(ping_in_flight());
1239 EXPECT_TRUE(check_ping_status_pending());
1240
1241 // Consume PING ack and check_ping_status callback.
1242 data.Resume();
1243 FastForwardBy(NextMainThreadPendingTaskDelay());
1244 EXPECT_FALSE(ping_in_flight());
1245 EXPECT_FALSE(check_ping_status_pending());
1246
1247 data.Resume();
1248 base::RunLoop().RunUntilIdle();
1249 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
1250
1251 EXPECT_TRUE(MainThreadIsIdle());
1252 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1253 EXPECT_FALSE(session_);
1254 EXPECT_FALSE(spdy_stream1);
1255
1256 EXPECT_TRUE(data.AllWriteDataConsumed());
1257 EXPECT_TRUE(data.AllReadDataConsumed());
1258
1259 EXPECT_EQ(2u, estimator.ping_rtt_received_count());
1260 }
1261
TEST_F(SpdySessionTest,StreamIdSpaceExhausted)1262 TEST_F(SpdySessionTest, StreamIdSpaceExhausted) {
1263 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
1264 // fixed to allow for two stream ID assignments, and three concurrent
1265 // streams. Four streams are started, and two are activated. Verify the
1266 // session goes away, and that the created (but not activated) and
1267 // stalled streams are aborted. Also verify the activated streams complete,
1268 // at which point the session closes.
1269
1270 spdy::SpdySerializedFrame req1(
1271 spdy_util_.ConstructSpdyGet(nullptr, 0, kLastStreamId - 2, MEDIUM));
1272 spdy::SpdySerializedFrame req2(
1273 spdy_util_.ConstructSpdyGet(nullptr, 0, kLastStreamId, MEDIUM));
1274
1275 MockWrite writes[] = {
1276 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
1277 };
1278
1279 spdy::SpdySerializedFrame resp1(
1280 spdy_util_.ConstructSpdyGetReply(nullptr, 0, kLastStreamId - 2));
1281 spdy::SpdySerializedFrame resp2(
1282 spdy_util_.ConstructSpdyGetReply(nullptr, 0, kLastStreamId));
1283
1284 spdy::SpdySerializedFrame body1(
1285 spdy_util_.ConstructSpdyDataFrame(kLastStreamId - 2, true));
1286 spdy::SpdySerializedFrame body2(
1287 spdy_util_.ConstructSpdyDataFrame(kLastStreamId, true));
1288
1289 MockRead reads[] = {
1290 CreateMockRead(resp1, 2), CreateMockRead(resp2, 3),
1291 MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(body1, 5),
1292 CreateMockRead(body2, 6), MockRead(ASYNC, 0, 7) // EOF
1293 };
1294
1295 SequencedSocketData data(reads, writes);
1296 session_deps_.socket_factory->AddSocketDataProvider(&data);
1297
1298 AddSSLSocketData();
1299
1300 CreateNetworkSession();
1301 CreateSpdySession();
1302
1303 // Fix stream_hi_water_mark_ to allow for two stream activations.
1304 set_stream_hi_water_mark(kLastStreamId - 2);
1305 // Fix max_concurrent_streams to allow for three stream creations.
1306 set_max_concurrent_streams(3);
1307
1308 // Create three streams synchronously, and begin a fourth (which is stalled).
1309 base::WeakPtr<SpdyStream> stream1 =
1310 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1311 test_url_, MEDIUM, NetLogWithSource());
1312 test::StreamDelegateDoNothing delegate1(stream1);
1313 stream1->SetDelegate(&delegate1);
1314
1315 base::WeakPtr<SpdyStream> stream2 =
1316 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1317 test_url_, MEDIUM, NetLogWithSource());
1318 test::StreamDelegateDoNothing delegate2(stream2);
1319 stream2->SetDelegate(&delegate2);
1320
1321 base::WeakPtr<SpdyStream> stream3 =
1322 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1323 test_url_, MEDIUM, NetLogWithSource());
1324 test::StreamDelegateDoNothing delegate3(stream3);
1325 stream3->SetDelegate(&delegate3);
1326
1327 SpdyStreamRequest request4;
1328 TestCompletionCallback callback4;
1329 EXPECT_EQ(ERR_IO_PENDING,
1330 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_,
1331 test_url_, false, MEDIUM, SocketTag(),
1332 NetLogWithSource(), callback4.callback(),
1333 TRAFFIC_ANNOTATION_FOR_TESTS));
1334
1335 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1336 EXPECT_EQ(0u, num_active_streams());
1337 EXPECT_EQ(3u, num_created_streams());
1338 EXPECT_EQ(1u, pending_create_stream_queue_size(MEDIUM));
1339
1340 // Activate stream 1. One ID remains available.
1341 stream1->SendRequestHeaders(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl),
1342 NO_MORE_DATA_TO_SEND);
1343 base::RunLoop().RunUntilIdle();
1344
1345 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1346 EXPECT_EQ(1u, num_active_streams());
1347 EXPECT_EQ(2u, num_created_streams());
1348 EXPECT_EQ(1u, pending_create_stream_queue_size(MEDIUM));
1349
1350 // Activate stream 2. ID space is exhausted.
1351 stream2->SendRequestHeaders(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl),
1352 NO_MORE_DATA_TO_SEND);
1353 base::RunLoop().RunUntilIdle();
1354
1355 // Active streams remain active.
1356 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1357 EXPECT_EQ(2u, num_active_streams());
1358
1359 // Session is going away. Created and stalled streams were aborted.
1360 EXPECT_TRUE(session_->IsGoingAway());
1361 EXPECT_THAT(delegate3.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
1362 EXPECT_THAT(callback4.WaitForResult(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
1363 EXPECT_EQ(0u, num_created_streams());
1364 EXPECT_EQ(0u, pending_create_stream_queue_size(MEDIUM));
1365
1366 // Read responses on remaining active streams.
1367 data.Resume();
1368 base::RunLoop().RunUntilIdle();
1369 EXPECT_THAT(delegate1.WaitForClose(), IsOk());
1370 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1371 EXPECT_THAT(delegate2.WaitForClose(), IsOk());
1372 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1373
1374 // Session was destroyed.
1375 EXPECT_FALSE(session_);
1376 }
1377
1378 // Regression test for https://crbug.com/481009.
TEST_F(SpdySessionTest,MaxConcurrentStreamsZero)1379 TEST_F(SpdySessionTest, MaxConcurrentStreamsZero) {
1380
1381 // Receive SETTINGS frame that sets max_concurrent_streams to zero.
1382 spdy::SettingsMap settings_zero;
1383 settings_zero[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = 0;
1384 spdy::SpdySerializedFrame settings_frame_zero(
1385 spdy_util_.ConstructSpdySettings(settings_zero));
1386
1387 // Acknowledge it.
1388 spdy::SpdySerializedFrame settings_ack0(
1389 spdy_util_.ConstructSpdySettingsAck());
1390
1391 // Receive SETTINGS frame that sets max_concurrent_streams to one.
1392 spdy::SettingsMap settings_one;
1393 settings_one[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = 1;
1394 spdy::SpdySerializedFrame settings_frame_one(
1395 spdy_util_.ConstructSpdySettings(settings_one));
1396
1397 // Acknowledge it.
1398 spdy::SpdySerializedFrame settings_ack1(
1399 spdy_util_.ConstructSpdySettingsAck());
1400
1401 // Request and response.
1402 spdy::SpdySerializedFrame req(
1403 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
1404
1405 spdy::SpdySerializedFrame resp(
1406 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1407
1408 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
1409
1410 MockRead reads[] = {CreateMockRead(settings_frame_zero, 0),
1411 MockRead(ASYNC, ERR_IO_PENDING, 2),
1412 CreateMockRead(settings_frame_one, 3),
1413 CreateMockRead(resp, 6),
1414 CreateMockRead(body, 7),
1415 MockRead(ASYNC, 0, 8)};
1416
1417 MockWrite writes[] = {CreateMockWrite(settings_ack0, 1),
1418 CreateMockWrite(settings_ack1, 4),
1419 CreateMockWrite(req, 5)};
1420
1421 SequencedSocketData data(reads, writes);
1422 session_deps_.socket_factory->AddSocketDataProvider(&data);
1423
1424 AddSSLSocketData();
1425
1426 // Create session.
1427 CreateNetworkSession();
1428 CreateSpdySession();
1429
1430 // Receive SETTINGS frame that sets max_concurrent_streams to zero.
1431 base::RunLoop().RunUntilIdle();
1432 EXPECT_EQ(0u, max_concurrent_streams());
1433
1434 // Start request.
1435 SpdyStreamRequest request;
1436 TestCompletionCallback callback;
1437 int rv =
1438 request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
1439 false, MEDIUM, SocketTag(), NetLogWithSource(),
1440 callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
1441 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1442
1443 // Stream is stalled.
1444 EXPECT_EQ(1u, pending_create_stream_queue_size(MEDIUM));
1445 EXPECT_EQ(0u, num_created_streams());
1446
1447 // Receive SETTINGS frame that sets max_concurrent_streams to one.
1448 data.Resume();
1449 base::RunLoop().RunUntilIdle();
1450 EXPECT_EQ(1u, max_concurrent_streams());
1451
1452 // Stream is created.
1453 EXPECT_EQ(0u, pending_create_stream_queue_size(MEDIUM));
1454 EXPECT_EQ(1u, num_created_streams());
1455
1456 EXPECT_THAT(callback.WaitForResult(), IsOk());
1457
1458 // Send request.
1459 base::WeakPtr<SpdyStream> stream = request.ReleaseStream();
1460 test::StreamDelegateDoNothing delegate(stream);
1461 stream->SetDelegate(&delegate);
1462 spdy::Http2HeaderBlock headers(
1463 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1464 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1465
1466 EXPECT_THAT(delegate.WaitForClose(), IsOk());
1467 EXPECT_EQ("hello!", delegate.TakeReceivedData());
1468
1469 // Finish async network reads/writes.
1470 base::RunLoop().RunUntilIdle();
1471 EXPECT_TRUE(data.AllWriteDataConsumed());
1472 EXPECT_TRUE(data.AllReadDataConsumed());
1473
1474 // Session is destroyed.
1475 EXPECT_FALSE(session_);
1476 }
1477
1478 // Verifies that an unstalled pending stream creation racing with a new stream
1479 // creation doesn't violate the maximum stream concurrency. Regression test for
1480 // crbug.com/373858.
TEST_F(SpdySessionTest,UnstallRacesWithStreamCreation)1481 TEST_F(SpdySessionTest, UnstallRacesWithStreamCreation) {
1482 MockRead reads[] = {
1483 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1484 };
1485
1486 StaticSocketDataProvider data(reads, base::span<MockWrite>());
1487 session_deps_.socket_factory->AddSocketDataProvider(&data);
1488
1489 AddSSLSocketData();
1490
1491 CreateNetworkSession();
1492 CreateSpdySession();
1493
1494 // Fix max_concurrent_streams to allow for one open stream.
1495 set_max_concurrent_streams(1);
1496
1497 // Create two streams: one synchronously, and one which stalls.
1498 base::WeakPtr<SpdyStream> stream1 =
1499 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1500 test_url_, MEDIUM, NetLogWithSource());
1501
1502 SpdyStreamRequest request2;
1503 TestCompletionCallback callback2;
1504 EXPECT_EQ(ERR_IO_PENDING,
1505 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_,
1506 test_url_, false, MEDIUM, SocketTag(),
1507 NetLogWithSource(), callback2.callback(),
1508 TRAFFIC_ANNOTATION_FOR_TESTS));
1509
1510 EXPECT_EQ(1u, num_created_streams());
1511 EXPECT_EQ(1u, pending_create_stream_queue_size(MEDIUM));
1512
1513 // Cancel the first stream. A callback to unstall the second stream was
1514 // posted. Don't run it yet.
1515 stream1->Cancel(ERR_ABORTED);
1516
1517 EXPECT_EQ(0u, num_created_streams());
1518 EXPECT_EQ(0u, pending_create_stream_queue_size(MEDIUM));
1519
1520 // Create a third stream prior to the second stream's callback.
1521 base::WeakPtr<SpdyStream> stream3 =
1522 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1523 test_url_, MEDIUM, NetLogWithSource());
1524
1525 EXPECT_EQ(1u, num_created_streams());
1526 EXPECT_EQ(0u, pending_create_stream_queue_size(MEDIUM));
1527
1528 // Now run the message loop. The unstalled stream will re-stall itself.
1529 base::RunLoop().RunUntilIdle();
1530 EXPECT_EQ(1u, num_created_streams());
1531 EXPECT_EQ(1u, pending_create_stream_queue_size(MEDIUM));
1532
1533 // Cancel the third stream and run the message loop. Verify that the second
1534 // stream creation now completes.
1535 stream3->Cancel(ERR_ABORTED);
1536 base::RunLoop().RunUntilIdle();
1537
1538 EXPECT_EQ(1u, num_created_streams());
1539 EXPECT_EQ(0u, pending_create_stream_queue_size(MEDIUM));
1540 EXPECT_THAT(callback2.WaitForResult(), IsOk());
1541 }
1542
TEST_F(SpdySessionTestWithMockTime,FailedPing)1543 TEST_F(SpdySessionTestWithMockTime, FailedPing) {
1544 session_deps_.enable_ping = true;
1545 session_deps_.time_func = TheNearFuture;
1546
1547 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)}; // Stall forever.
1548 spdy::SpdySerializedFrame write_ping(spdy_util_.ConstructSpdyPing(1, false));
1549 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
1550 0, spdy::ERROR_CODE_PROTOCOL_ERROR, "Failed ping."));
1551 MockWrite writes[] = {CreateMockWrite(write_ping), CreateMockWrite(goaway)};
1552
1553 StaticSocketDataProvider data(reads, writes);
1554 session_deps_.socket_factory->AddSocketDataProvider(&data);
1555
1556 AddSSLSocketData();
1557
1558 CreateNetworkSession();
1559 CreateSpdySession();
1560
1561 base::WeakPtr<SpdyStream> spdy_stream1 =
1562 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1563 MEDIUM, NetLogWithSource());
1564 ASSERT_TRUE(spdy_stream1);
1565 test::StreamDelegateSendImmediate delegate(spdy_stream1, "");
1566 spdy_stream1->SetDelegate(&delegate);
1567
1568 // Negative value means a preface ping will always be sent.
1569 set_connection_at_risk_of_loss_time(base::Seconds(-1));
1570
1571 // Send a PING frame. This posts CheckPingStatus() with delay.
1572 MaybeSendPrefacePing();
1573 EXPECT_TRUE(ping_in_flight());
1574 EXPECT_EQ(2u, next_ping_id());
1575 EXPECT_TRUE(check_ping_status_pending());
1576
1577 // Assert session is not closed.
1578 EXPECT_TRUE(session_->IsAvailable());
1579 EXPECT_LT(0u, num_active_streams() + num_created_streams());
1580 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1581
1582 // Run CheckPingStatus() and make it believe hung_interval has passed.
1583 g_time_delta = base::Seconds(15);
1584 FastForwardUntilNoTasksRemain();
1585 base::RunLoop().RunUntilIdle();
1586
1587 // Since no response to PING has been received,
1588 // CheckPingStatus() closes the connection.
1589 EXPECT_TRUE(MainThreadIsIdle());
1590 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1591 EXPECT_FALSE(session_);
1592 EXPECT_FALSE(spdy_stream1);
1593
1594 EXPECT_TRUE(data.AllWriteDataConsumed());
1595 EXPECT_TRUE(data.AllReadDataConsumed());
1596 }
1597
1598 // Regression test for https://crbug.com/784975.
TEST_F(SpdySessionTestWithMockTime,NoPingSentWhenCheckPingPending)1599 TEST_F(SpdySessionTestWithMockTime, NoPingSentWhenCheckPingPending) {
1600 session_deps_.enable_ping = true;
1601 session_deps_.time_func = TheNearFuture;
1602
1603 spdy::SpdySerializedFrame read_ping(spdy_util_.ConstructSpdyPing(1, true));
1604 MockRead reads[] = {CreateMockRead(read_ping, 1),
1605 MockRead(ASYNC, ERR_IO_PENDING, 2),
1606 MockRead(ASYNC, 0, 3)};
1607
1608 spdy::SpdySerializedFrame write_ping0(spdy_util_.ConstructSpdyPing(1, false));
1609 MockWrite writes[] = {CreateMockWrite(write_ping0, 0)};
1610
1611 SequencedSocketData data(reads, writes);
1612 session_deps_.socket_factory->AddSocketDataProvider(&data);
1613 AddSSLSocketData();
1614
1615 CreateNetworkSession();
1616 CreateSpdySession();
1617
1618 // Negative value means a preface ping will always be sent.
1619 set_connection_at_risk_of_loss_time(base::Seconds(-1));
1620
1621 base::WeakPtr<SpdyStream> spdy_stream1 =
1622 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1623 MEDIUM, NetLogWithSource());
1624 ASSERT_TRUE(spdy_stream1);
1625 test::StreamDelegateSendImmediate delegate(spdy_stream1, "");
1626 spdy_stream1->SetDelegate(&delegate);
1627
1628 EXPECT_FALSE(ping_in_flight());
1629 EXPECT_EQ(1u, next_ping_id());
1630 EXPECT_FALSE(check_ping_status_pending());
1631
1632 // Send preface ping and post CheckPingStatus() task with delay.
1633 MaybeSendPrefacePing();
1634
1635 EXPECT_TRUE(ping_in_flight());
1636 EXPECT_EQ(2u, next_ping_id());
1637 EXPECT_TRUE(check_ping_status_pending());
1638
1639 // Read PING ACK.
1640 base::RunLoop().RunUntilIdle();
1641
1642 EXPECT_FALSE(ping_in_flight());
1643 EXPECT_TRUE(check_ping_status_pending());
1644
1645 // Fast forward mock time so that normally another ping would be sent out.
1646 // However, since CheckPingStatus() is still pending, no new ping is sent.
1647 g_time_delta = base::Seconds(15);
1648 MaybeSendPrefacePing();
1649
1650 EXPECT_FALSE(ping_in_flight());
1651 EXPECT_EQ(2u, next_ping_id());
1652 EXPECT_TRUE(check_ping_status_pending());
1653
1654 // Run CheckPingStatus().
1655 FastForwardUntilNoTasksRemain();
1656 base::RunLoop().RunUntilIdle();
1657
1658 EXPECT_FALSE(check_ping_status_pending());
1659
1660 // Read EOF.
1661 data.Resume();
1662 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
1663
1664 // Finish going away.
1665 base::RunLoop().RunUntilIdle();
1666
1667 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1668 EXPECT_FALSE(session_);
1669
1670 EXPECT_TRUE(data.AllWriteDataConsumed());
1671 EXPECT_TRUE(data.AllReadDataConsumed());
1672 }
1673
1674 // Request kH2InitialMaxConcurrentStreamsParam.Get() + 1 streams. Receive a
1675 // settings frame increasing the max concurrent streams by 1. Make
1676 // sure nothing blows up. This is a regression test for
1677 // http://crbug.com/57331 .
TEST_F(SpdySessionTest,OnSettings)1678 TEST_F(SpdySessionTest, OnSettings) {
1679 const spdy::SpdySettingsId kSpdySettingsId =
1680 spdy::SETTINGS_MAX_CONCURRENT_STREAMS;
1681
1682 spdy::SettingsMap new_settings;
1683 const uint32_t max_concurrent_streams =
1684 kH2InitialMaxConcurrentStreams.Get() + 1;
1685 new_settings[kSpdySettingsId] = max_concurrent_streams;
1686 spdy::SpdySerializedFrame settings_frame(
1687 spdy_util_.ConstructSpdySettings(new_settings));
1688 MockRead reads[] = {
1689 CreateMockRead(settings_frame, 0), MockRead(ASYNC, ERR_IO_PENDING, 2),
1690 MockRead(ASYNC, 0, 3),
1691 };
1692
1693 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
1694 MockWrite writes[] = {CreateMockWrite(settings_ack, 1)};
1695
1696 SequencedSocketData data(reads, writes);
1697 session_deps_.socket_factory->AddSocketDataProvider(&data);
1698
1699 AddSSLSocketData();
1700
1701 CreateNetworkSession();
1702 CreateSpdySession();
1703
1704 // Create the maximum number of concurrent streams.
1705 for (int i = 0; i < kH2InitialMaxConcurrentStreams.Get(); ++i) {
1706 base::WeakPtr<SpdyStream> spdy_stream =
1707 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_,
1708 test_url_, MEDIUM, NetLogWithSource());
1709 ASSERT_TRUE(spdy_stream);
1710 }
1711
1712 StreamReleaserCallback stream_releaser;
1713 SpdyStreamRequest request;
1714 ASSERT_EQ(ERR_IO_PENDING,
1715 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1716 false, MEDIUM, SocketTag(), NetLogWithSource(),
1717 stream_releaser.MakeCallback(&request),
1718 TRAFFIC_ANNOTATION_FOR_TESTS));
1719
1720 base::RunLoop().RunUntilIdle();
1721 EXPECT_THAT(stream_releaser.WaitForResult(), IsOk());
1722
1723 data.Resume();
1724 base::RunLoop().RunUntilIdle();
1725 EXPECT_FALSE(session_);
1726
1727 EXPECT_TRUE(data.AllWriteDataConsumed());
1728 EXPECT_TRUE(data.AllReadDataConsumed());
1729 }
1730
1731 // Create one more stream than maximum number of concurrent streams,
1732 // so that one of them is pending. Cancel one stream, which should trigger the
1733 // creation of the pending stream. Then cancel that one immediately as well,
1734 // and make sure this does not lead to a crash.
1735 // This is a regression test for https://crbug.com/63532.
TEST_F(SpdySessionTest,CancelPendingCreateStream)1736 TEST_F(SpdySessionTest, CancelPendingCreateStream) {
1737 MockRead reads[] = {
1738 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1739 };
1740
1741 StaticSocketDataProvider data(reads, base::span<MockWrite>());
1742 session_deps_.socket_factory->AddSocketDataProvider(&data);
1743
1744 AddSSLSocketData();
1745
1746 CreateNetworkSession();
1747 CreateSpdySession();
1748
1749 // Leave room for only one more stream to be created.
1750 for (int i = 0; i < kH2InitialMaxConcurrentStreams.Get() - 1; ++i) {
1751 base::WeakPtr<SpdyStream> spdy_stream =
1752 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_,
1753 test_url_, MEDIUM, NetLogWithSource());
1754 ASSERT_TRUE(spdy_stream);
1755 }
1756
1757 // Create 2 more streams. First will succeed. Second will be pending.
1758 base::WeakPtr<SpdyStream> spdy_stream1 =
1759 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1760 MEDIUM, NetLogWithSource());
1761 ASSERT_TRUE(spdy_stream1);
1762
1763 // Use unique_ptr to let us invalidate the memory when we want to, to trigger
1764 // an error in memory corruption detectors if the callback is invoked when
1765 // it's not supposed to be.
1766 auto callback = std::make_unique<TestCompletionCallback>();
1767
1768 SpdyStreamRequest request;
1769 ASSERT_THAT(
1770 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1771 false, MEDIUM, SocketTag(), NetLogWithSource(),
1772 callback->callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
1773 IsError(ERR_IO_PENDING));
1774
1775 // Release the first one, this will allow the second to be created.
1776 spdy_stream1->Cancel(ERR_ABORTED);
1777 EXPECT_FALSE(spdy_stream1);
1778
1779 request.CancelRequest();
1780 callback.reset();
1781
1782 // Should not crash when running the pending callback.
1783 base::RunLoop().RunUntilIdle();
1784 }
1785
TEST_F(SpdySessionTest,ChangeStreamRequestPriority)1786 TEST_F(SpdySessionTest, ChangeStreamRequestPriority) {
1787 MockRead reads[] = {
1788 MockRead(ASYNC, ERR_IO_PENDING) // Stall forever.
1789 };
1790
1791 StaticSocketDataProvider data(reads, base::span<MockWrite>());
1792 session_deps_.socket_factory->AddSocketDataProvider(&data);
1793
1794 AddSSLSocketData();
1795
1796 CreateNetworkSession();
1797 CreateSpdySession();
1798
1799 set_max_concurrent_streams(1);
1800
1801 TestCompletionCallback callback1;
1802 SpdyStreamRequest request1;
1803 ASSERT_EQ(OK, request1.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_,
1804 test_url_, false, LOWEST, SocketTag(),
1805 NetLogWithSource(), callback1.callback(),
1806 TRAFFIC_ANNOTATION_FOR_TESTS));
1807 TestCompletionCallback callback2;
1808 SpdyStreamRequest request2;
1809 ASSERT_EQ(ERR_IO_PENDING,
1810 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_,
1811 test_url_, false, LOWEST, SocketTag(),
1812 NetLogWithSource(), callback2.callback(),
1813 TRAFFIC_ANNOTATION_FOR_TESTS));
1814
1815 request1.SetPriority(HIGHEST);
1816 request2.SetPriority(MEDIUM);
1817
1818 ASSERT_EQ(0u, pending_create_stream_queue_size(HIGHEST));
1819 // Priority of queued request is changed.
1820 ASSERT_EQ(1u, pending_create_stream_queue_size(MEDIUM));
1821 ASSERT_EQ(0u, pending_create_stream_queue_size(LOWEST));
1822
1823 base::WeakPtr<SpdyStream> stream1 = request1.ReleaseStream();
1824 // Priority of stream is updated if request has been fulfilled.
1825 ASSERT_EQ(HIGHEST, stream1->priority());
1826 }
1827
1828 // Attempts to extract a NetLogSource from a set of event parameters. Returns
1829 // true and writes the result to |source| on success. Returns false and
1830 // makes |source| an invalid source on failure.
NetLogSourceFromEventParameters(const base::Value::Dict * event_params,NetLogSource * source)1831 bool NetLogSourceFromEventParameters(const base::Value::Dict* event_params,
1832 NetLogSource* source) {
1833 const base::Value::Dict* source_dict = nullptr;
1834 int source_id = -1;
1835 int source_type = static_cast<int>(NetLogSourceType::COUNT);
1836 if (!event_params) {
1837 *source = NetLogSource();
1838 return false;
1839 }
1840 source_dict = event_params->FindDict("source_dependency");
1841 if (!source_dict) {
1842 *source = NetLogSource();
1843 return false;
1844 }
1845 absl::optional<int> opt_int;
1846 opt_int = source_dict->FindInt("id");
1847 if (!opt_int) {
1848 *source = NetLogSource();
1849 return false;
1850 }
1851 source_id = opt_int.value();
1852 opt_int = source_dict->FindInt("type");
1853 if (!opt_int) {
1854 *source = NetLogSource();
1855 return false;
1856 }
1857 source_type = opt_int.value();
1858
1859 DCHECK_GE(source_id, 0);
1860 DCHECK_LT(source_type, static_cast<int>(NetLogSourceType::COUNT));
1861 *source = NetLogSource(static_cast<NetLogSourceType>(source_type), source_id);
1862 return true;
1863 }
1864
TEST_F(SpdySessionTest,Initialize)1865 TEST_F(SpdySessionTest, Initialize) {
1866 MockRead reads[] = {
1867 MockRead(ASYNC, 0, 0) // EOF
1868 };
1869
1870 StaticSocketDataProvider data(reads, base::span<MockWrite>());
1871 session_deps_.socket_factory->AddSocketDataProvider(&data);
1872
1873 AddSSLSocketData();
1874
1875 CreateNetworkSession();
1876 CreateSpdySession();
1877 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1878
1879 // Flush the read completion task.
1880 base::RunLoop().RunUntilIdle();
1881
1882 auto entries = net_log_observer_.GetEntries();
1883 EXPECT_LT(0u, entries.size());
1884
1885 // Check that we logged HTTP2_SESSION_INITIALIZED correctly.
1886 int pos = ExpectLogContainsSomewhere(
1887 entries, 0, NetLogEventType::HTTP2_SESSION_INITIALIZED,
1888 NetLogEventPhase::NONE);
1889 EXPECT_LT(0, pos);
1890
1891 NetLogSource socket_source;
1892 EXPECT_TRUE(
1893 NetLogSourceFromEventParameters(&entries[pos].params, &socket_source));
1894 EXPECT_TRUE(socket_source.IsValid());
1895 EXPECT_NE(net_log_with_source_.source().id, socket_source.id);
1896 }
1897
TEST_F(SpdySessionTest,NetLogOnSessionGoaway)1898 TEST_F(SpdySessionTest, NetLogOnSessionGoaway) {
1899 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
1900 42, spdy::ERROR_CODE_ENHANCE_YOUR_CALM, "foo"));
1901 MockRead reads[] = {
1902 CreateMockRead(goaway), MockRead(SYNCHRONOUS, 0, 0) // EOF
1903 };
1904
1905 StaticSocketDataProvider data(reads, base::span<MockWrite>());
1906 session_deps_.socket_factory->AddSocketDataProvider(&data);
1907
1908 AddSSLSocketData();
1909
1910 CreateNetworkSession();
1911 CreateSpdySession();
1912 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1913
1914 // Flush the read completion task.
1915 base::RunLoop().RunUntilIdle();
1916
1917 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1918 EXPECT_FALSE(session_);
1919
1920 // Check that the NetLog was filled reasonably.
1921 auto entries = net_log_observer_.GetEntries();
1922 EXPECT_LT(0u, entries.size());
1923
1924 int pos = ExpectLogContainsSomewhere(
1925 entries, 0, NetLogEventType::HTTP2_SESSION_RECV_GOAWAY,
1926 NetLogEventPhase::NONE);
1927 ASSERT_EQ(0, GetIntegerValueFromParams(entries[pos], "active_streams"));
1928 ASSERT_EQ("11 (ENHANCE_YOUR_CALM)",
1929 GetStringValueFromParams(entries[pos], "error_code"));
1930 ASSERT_EQ("foo", GetStringValueFromParams(entries[pos], "debug_data"));
1931
1932 // Check that we logged SPDY_SESSION_CLOSE correctly.
1933 pos = ExpectLogContainsSomewhere(
1934 entries, 0, NetLogEventType::HTTP2_SESSION_CLOSE, NetLogEventPhase::NONE);
1935 EXPECT_THAT(GetNetErrorCodeFromParams(entries[pos]), IsOk());
1936 }
1937
TEST_F(SpdySessionTest,NetLogOnSessionEOF)1938 TEST_F(SpdySessionTest, NetLogOnSessionEOF) {
1939 MockRead reads[] = {
1940 MockRead(SYNCHRONOUS, 0, 0) // EOF
1941 };
1942
1943 StaticSocketDataProvider data(reads, base::span<MockWrite>());
1944 session_deps_.socket_factory->AddSocketDataProvider(&data);
1945
1946 AddSSLSocketData();
1947
1948 CreateNetworkSession();
1949 CreateSpdySession();
1950 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1951
1952 // Flush the read completion task.
1953 base::RunLoop().RunUntilIdle();
1954
1955 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1956 EXPECT_FALSE(session_);
1957
1958 // Check that the NetLog was filled reasonably.
1959 auto entries = net_log_observer_.GetEntries();
1960 EXPECT_LT(0u, entries.size());
1961
1962 // Check that we logged SPDY_SESSION_CLOSE correctly.
1963 int pos = ExpectLogContainsSomewhere(
1964 entries, 0, NetLogEventType::HTTP2_SESSION_CLOSE, NetLogEventPhase::NONE);
1965
1966 if (pos < static_cast<int>(entries.size())) {
1967 ASSERT_THAT(GetNetErrorCodeFromParams(entries[pos]),
1968 IsError(ERR_CONNECTION_CLOSED));
1969 } else {
1970 ADD_FAILURE();
1971 }
1972 }
1973
TEST_F(SpdySessionTest,HeadersCompressionHistograms)1974 TEST_F(SpdySessionTest, HeadersCompressionHistograms) {
1975 spdy::SpdySerializedFrame req(
1976 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
1977 MockWrite writes[] = {
1978 CreateMockWrite(req, 0),
1979 };
1980 MockRead reads[] = {
1981 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
1982 };
1983 SequencedSocketData data(reads, writes);
1984 session_deps_.socket_factory->AddSocketDataProvider(&data);
1985
1986 AddSSLSocketData();
1987
1988 CreateNetworkSession();
1989 CreateSpdySession();
1990
1991 base::WeakPtr<SpdyStream> spdy_stream =
1992 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1993 test_url_, MEDIUM, NetLogWithSource());
1994 test::StreamDelegateDoNothing delegate(spdy_stream);
1995 spdy_stream->SetDelegate(&delegate);
1996
1997 spdy::Http2HeaderBlock headers(
1998 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1999 spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
2000
2001 // Write request headers & capture resulting histogram update.
2002 base::HistogramTester histogram_tester;
2003
2004 base::RunLoop().RunUntilIdle();
2005 // Regression test of compression performance under the request fixture.
2006 histogram_tester.ExpectBucketCount("Net.SpdyHeadersCompressionPercentage", 76,
2007 1);
2008
2009 // Read and process EOF.
2010 EXPECT_TRUE(session_);
2011 data.Resume();
2012 base::RunLoop().RunUntilIdle();
2013 EXPECT_FALSE(session_);
2014 }
2015
2016 // Queue up a low-priority HEADERS followed by a high-priority
2017 // one. The high priority one should still send first and receive
2018 // first.
TEST_F(SpdySessionTest,OutOfOrderHeaders)2019 TEST_F(SpdySessionTest, OutOfOrderHeaders) {
2020 // Construct the request.
2021 spdy::SpdySerializedFrame req_highest(
2022 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
2023 spdy::SpdySerializedFrame req_lowest(
2024 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
2025 MockWrite writes[] = {
2026 CreateMockWrite(req_highest, 0), CreateMockWrite(req_lowest, 1),
2027 };
2028
2029 spdy::SpdySerializedFrame resp_highest(
2030 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2031 spdy::SpdySerializedFrame body_highest(
2032 spdy_util_.ConstructSpdyDataFrame(1, true));
2033 spdy::SpdySerializedFrame resp_lowest(
2034 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
2035 spdy::SpdySerializedFrame body_lowest(
2036 spdy_util_.ConstructSpdyDataFrame(3, true));
2037 MockRead reads[] = {
2038 CreateMockRead(resp_highest, 2), CreateMockRead(body_highest, 3),
2039 CreateMockRead(resp_lowest, 4), CreateMockRead(body_lowest, 5),
2040 MockRead(ASYNC, 0, 6) // EOF
2041 };
2042
2043 SequencedSocketData data(reads, writes);
2044 session_deps_.socket_factory->AddSocketDataProvider(&data);
2045
2046 AddSSLSocketData();
2047
2048 CreateNetworkSession();
2049 CreateSpdySession();
2050
2051 base::WeakPtr<SpdyStream> spdy_stream_lowest =
2052 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2053 test_url_, LOWEST, NetLogWithSource());
2054 ASSERT_TRUE(spdy_stream_lowest);
2055 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
2056 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
2057 spdy_stream_lowest->SetDelegate(&delegate_lowest);
2058
2059 base::WeakPtr<SpdyStream> spdy_stream_highest =
2060 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2061 test_url_, HIGHEST, NetLogWithSource());
2062 ASSERT_TRUE(spdy_stream_highest);
2063 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
2064 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
2065 spdy_stream_highest->SetDelegate(&delegate_highest);
2066
2067 // Queue the lower priority one first.
2068
2069 spdy::Http2HeaderBlock headers_lowest(
2070 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2071 spdy_stream_lowest->SendRequestHeaders(std::move(headers_lowest),
2072 NO_MORE_DATA_TO_SEND);
2073
2074 spdy::Http2HeaderBlock headers_highest(
2075 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2076 spdy_stream_highest->SendRequestHeaders(std::move(headers_highest),
2077 NO_MORE_DATA_TO_SEND);
2078
2079 base::RunLoop().RunUntilIdle();
2080
2081 EXPECT_FALSE(spdy_stream_lowest);
2082 EXPECT_FALSE(spdy_stream_highest);
2083 EXPECT_EQ(3u, delegate_lowest.stream_id());
2084 EXPECT_EQ(1u, delegate_highest.stream_id());
2085 }
2086
TEST_F(SpdySessionTest,CancelStream)2087 TEST_F(SpdySessionTest, CancelStream) {
2088 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
2089 // Request 2, at LOWEST priority, will be a full request and will be id 1.
2090 spdy::SpdySerializedFrame req2(
2091 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2092 MockWrite writes[] = {
2093 CreateMockWrite(req2, 0),
2094 };
2095
2096 spdy::SpdySerializedFrame resp2(
2097 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2098 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
2099 MockRead reads[] = {
2100 CreateMockRead(resp2, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
2101 CreateMockRead(body2, 3), MockRead(ASYNC, 0, 4) // EOF
2102 };
2103
2104 SequencedSocketData data(reads, writes);
2105 session_deps_.socket_factory->AddSocketDataProvider(&data);
2106
2107 AddSSLSocketData();
2108
2109 CreateNetworkSession();
2110 CreateSpdySession();
2111
2112 base::WeakPtr<SpdyStream> spdy_stream1 =
2113 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2114 test_url_, HIGHEST, NetLogWithSource());
2115 ASSERT_TRUE(spdy_stream1);
2116 EXPECT_EQ(0u, spdy_stream1->stream_id());
2117 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2118 spdy_stream1->SetDelegate(&delegate1);
2119
2120 base::WeakPtr<SpdyStream> spdy_stream2 =
2121 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2122 test_url_, LOWEST, NetLogWithSource());
2123 ASSERT_TRUE(spdy_stream2);
2124 EXPECT_EQ(0u, spdy_stream2->stream_id());
2125 test::StreamDelegateDoNothing delegate2(spdy_stream2);
2126 spdy_stream2->SetDelegate(&delegate2);
2127
2128 spdy::Http2HeaderBlock headers(
2129 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2130 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
2131
2132 spdy::Http2HeaderBlock headers2(
2133 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2134 spdy_stream2->SendRequestHeaders(std::move(headers2), NO_MORE_DATA_TO_SEND);
2135
2136 EXPECT_EQ(0u, spdy_stream1->stream_id());
2137
2138 spdy_stream1->Cancel(ERR_ABORTED);
2139 EXPECT_FALSE(spdy_stream1);
2140
2141 EXPECT_EQ(0u, delegate1.stream_id());
2142
2143 base::RunLoop().RunUntilIdle();
2144
2145 EXPECT_EQ(0u, delegate1.stream_id());
2146 EXPECT_EQ(1u, delegate2.stream_id());
2147
2148 spdy_stream2->Cancel(ERR_ABORTED);
2149 EXPECT_FALSE(spdy_stream2);
2150 }
2151
2152 // Create two streams that are set to re-close themselves on close,
2153 // and then close the session. Nothing should blow up. Also a
2154 // regression test for http://crbug.com/139518 .
TEST_F(SpdySessionTest,CloseSessionWithTwoCreatedSelfClosingStreams)2155 TEST_F(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
2156 // No actual data will be sent.
2157 MockWrite writes[] = {
2158 MockWrite(ASYNC, 0, 1) // EOF
2159 };
2160
2161 MockRead reads[] = {
2162 MockRead(ASYNC, 0, 0) // EOF
2163 };
2164 SequencedSocketData data(reads, writes);
2165 session_deps_.socket_factory->AddSocketDataProvider(&data);
2166
2167 AddSSLSocketData();
2168
2169 CreateNetworkSession();
2170 CreateSpdySession();
2171
2172 base::WeakPtr<SpdyStream> spdy_stream1 =
2173 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
2174 HIGHEST, NetLogWithSource());
2175 ASSERT_TRUE(spdy_stream1);
2176 EXPECT_EQ(0u, spdy_stream1->stream_id());
2177
2178 base::WeakPtr<SpdyStream> spdy_stream2 =
2179 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
2180 LOWEST, NetLogWithSource());
2181 ASSERT_TRUE(spdy_stream2);
2182 EXPECT_EQ(0u, spdy_stream2->stream_id());
2183
2184 test::ClosingDelegate delegate1(spdy_stream1);
2185 spdy_stream1->SetDelegate(&delegate1);
2186
2187 test::ClosingDelegate delegate2(spdy_stream2);
2188 spdy_stream2->SetDelegate(&delegate2);
2189
2190 spdy::Http2HeaderBlock headers(
2191 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2192 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
2193
2194 spdy::Http2HeaderBlock headers2(
2195 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2196 spdy_stream2->SendRequestHeaders(std::move(headers2), NO_MORE_DATA_TO_SEND);
2197
2198 // Ensure that the streams have not yet been activated and assigned an id.
2199 EXPECT_EQ(0u, spdy_stream1->stream_id());
2200 EXPECT_EQ(0u, spdy_stream2->stream_id());
2201
2202 // Ensure we don't crash while closing the session.
2203 session_->CloseSessionOnError(ERR_ABORTED, std::string());
2204
2205 EXPECT_FALSE(spdy_stream1);
2206 EXPECT_FALSE(spdy_stream2);
2207
2208 EXPECT_TRUE(delegate1.StreamIsClosed());
2209 EXPECT_TRUE(delegate2.StreamIsClosed());
2210
2211 base::RunLoop().RunUntilIdle();
2212 EXPECT_FALSE(session_);
2213 }
2214
2215 // Create two streams that are set to close each other on close, and
2216 // then close the session. Nothing should blow up.
TEST_F(SpdySessionTest,CloseSessionWithTwoCreatedMutuallyClosingStreams)2217 TEST_F(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
2218 SequencedSocketData data;
2219 session_deps_.socket_factory->AddSocketDataProvider(&data);
2220
2221 AddSSLSocketData();
2222
2223 CreateNetworkSession();
2224 CreateSpdySession();
2225
2226 base::WeakPtr<SpdyStream> spdy_stream1 =
2227 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
2228 HIGHEST, NetLogWithSource());
2229 ASSERT_TRUE(spdy_stream1);
2230 EXPECT_EQ(0u, spdy_stream1->stream_id());
2231
2232 base::WeakPtr<SpdyStream> spdy_stream2 =
2233 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
2234 LOWEST, NetLogWithSource());
2235 ASSERT_TRUE(spdy_stream2);
2236 EXPECT_EQ(0u, spdy_stream2->stream_id());
2237
2238 // Make |spdy_stream1| close |spdy_stream2|.
2239 test::ClosingDelegate delegate1(spdy_stream2);
2240 spdy_stream1->SetDelegate(&delegate1);
2241
2242 // Make |spdy_stream2| close |spdy_stream1|.
2243 test::ClosingDelegate delegate2(spdy_stream1);
2244 spdy_stream2->SetDelegate(&delegate2);
2245
2246 spdy::Http2HeaderBlock headers(
2247 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2248 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
2249
2250 spdy::Http2HeaderBlock headers2(
2251 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2252 spdy_stream2->SendRequestHeaders(std::move(headers2), NO_MORE_DATA_TO_SEND);
2253
2254 // Ensure that the streams have not yet been activated and assigned an id.
2255 EXPECT_EQ(0u, spdy_stream1->stream_id());
2256 EXPECT_EQ(0u, spdy_stream2->stream_id());
2257
2258 // Ensure we don't crash while closing the session.
2259 session_->CloseSessionOnError(ERR_ABORTED, std::string());
2260
2261 EXPECT_FALSE(spdy_stream1);
2262 EXPECT_FALSE(spdy_stream2);
2263
2264 EXPECT_TRUE(delegate1.StreamIsClosed());
2265 EXPECT_TRUE(delegate2.StreamIsClosed());
2266
2267 base::RunLoop().RunUntilIdle();
2268 EXPECT_FALSE(session_);
2269 }
2270
2271 // Create two streams that are set to re-close themselves on close,
2272 // activate them, and then close the session. Nothing should blow up.
TEST_F(SpdySessionTest,CloseSessionWithTwoActivatedSelfClosingStreams)2273 TEST_F(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2274 spdy::SpdySerializedFrame req1(
2275 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
2276 spdy::SpdySerializedFrame req2(
2277 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM));
2278 MockWrite writes[] = {
2279 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
2280 };
2281
2282 MockRead reads[] = {
2283 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
2284 };
2285
2286 SequencedSocketData data(reads, writes);
2287 session_deps_.socket_factory->AddSocketDataProvider(&data);
2288
2289 AddSSLSocketData();
2290
2291 CreateNetworkSession();
2292 CreateSpdySession();
2293
2294 base::WeakPtr<SpdyStream> spdy_stream1 =
2295 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2296 test_url_, MEDIUM, NetLogWithSource());
2297 ASSERT_TRUE(spdy_stream1);
2298 EXPECT_EQ(0u, spdy_stream1->stream_id());
2299
2300 base::WeakPtr<SpdyStream> spdy_stream2 =
2301 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2302 test_url_, MEDIUM, NetLogWithSource());
2303 ASSERT_TRUE(spdy_stream2);
2304 EXPECT_EQ(0u, spdy_stream2->stream_id());
2305
2306 test::ClosingDelegate delegate1(spdy_stream1);
2307 spdy_stream1->SetDelegate(&delegate1);
2308
2309 test::ClosingDelegate delegate2(spdy_stream2);
2310 spdy_stream2->SetDelegate(&delegate2);
2311
2312 spdy::Http2HeaderBlock headers(
2313 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2314 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
2315
2316 spdy::Http2HeaderBlock headers2(
2317 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2318 spdy_stream2->SendRequestHeaders(std::move(headers2), NO_MORE_DATA_TO_SEND);
2319
2320 // Ensure that the streams have not yet been activated and assigned an id.
2321 EXPECT_EQ(0u, spdy_stream1->stream_id());
2322 EXPECT_EQ(0u, spdy_stream2->stream_id());
2323
2324 base::RunLoop().RunUntilIdle();
2325
2326 EXPECT_EQ(1u, spdy_stream1->stream_id());
2327 EXPECT_EQ(3u, spdy_stream2->stream_id());
2328
2329 // Ensure we don't crash while closing the session.
2330 session_->CloseSessionOnError(ERR_ABORTED, std::string());
2331
2332 EXPECT_FALSE(spdy_stream1);
2333 EXPECT_FALSE(spdy_stream2);
2334
2335 EXPECT_TRUE(delegate1.StreamIsClosed());
2336 EXPECT_TRUE(delegate2.StreamIsClosed());
2337
2338 EXPECT_TRUE(session_);
2339 data.Resume();
2340 base::RunLoop().RunUntilIdle();
2341 EXPECT_FALSE(session_);
2342 }
2343
2344 // Create two streams that are set to close each other on close,
2345 // activate them, and then close the session. Nothing should blow up.
TEST_F(SpdySessionTest,CloseSessionWithTwoActivatedMutuallyClosingStreams)2346 TEST_F(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2347 spdy::SpdySerializedFrame req1(
2348 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
2349 spdy::SpdySerializedFrame req2(
2350 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM));
2351 MockWrite writes[] = {
2352 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
2353 };
2354
2355 MockRead reads[] = {
2356 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
2357 };
2358
2359 SequencedSocketData data(reads, writes);
2360 session_deps_.socket_factory->AddSocketDataProvider(&data);
2361
2362 AddSSLSocketData();
2363
2364 CreateNetworkSession();
2365 CreateSpdySession();
2366
2367 base::WeakPtr<SpdyStream> spdy_stream1 =
2368 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2369 test_url_, MEDIUM, NetLogWithSource());
2370 ASSERT_TRUE(spdy_stream1);
2371 EXPECT_EQ(0u, spdy_stream1->stream_id());
2372
2373 base::WeakPtr<SpdyStream> spdy_stream2 =
2374 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2375 test_url_, MEDIUM, NetLogWithSource());
2376 ASSERT_TRUE(spdy_stream2);
2377 EXPECT_EQ(0u, spdy_stream2->stream_id());
2378
2379 // Make |spdy_stream1| close |spdy_stream2|.
2380 test::ClosingDelegate delegate1(spdy_stream2);
2381 spdy_stream1->SetDelegate(&delegate1);
2382
2383 // Make |spdy_stream2| close |spdy_stream1|.
2384 test::ClosingDelegate delegate2(spdy_stream1);
2385 spdy_stream2->SetDelegate(&delegate2);
2386
2387 spdy::Http2HeaderBlock headers(
2388 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2389 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
2390
2391 spdy::Http2HeaderBlock headers2(
2392 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2393 spdy_stream2->SendRequestHeaders(std::move(headers2), NO_MORE_DATA_TO_SEND);
2394
2395 // Ensure that the streams have not yet been activated and assigned an id.
2396 EXPECT_EQ(0u, spdy_stream1->stream_id());
2397 EXPECT_EQ(0u, spdy_stream2->stream_id());
2398
2399 base::RunLoop().RunUntilIdle();
2400
2401 EXPECT_EQ(1u, spdy_stream1->stream_id());
2402 EXPECT_EQ(3u, spdy_stream2->stream_id());
2403
2404 // Ensure we don't crash while closing the session.
2405 session_->CloseSessionOnError(ERR_ABORTED, std::string());
2406
2407 EXPECT_FALSE(spdy_stream1);
2408 EXPECT_FALSE(spdy_stream2);
2409
2410 EXPECT_TRUE(delegate1.StreamIsClosed());
2411 EXPECT_TRUE(delegate2.StreamIsClosed());
2412
2413 EXPECT_TRUE(session_);
2414 data.Resume();
2415 base::RunLoop().RunUntilIdle();
2416 EXPECT_FALSE(session_);
2417 }
2418
2419 // Delegate that closes a given session when the stream is closed.
2420 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2421 public:
SessionClosingDelegate(const base::WeakPtr<SpdyStream> & stream,const base::WeakPtr<SpdySession> & session_to_close)2422 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2423 const base::WeakPtr<SpdySession>& session_to_close)
2424 : StreamDelegateDoNothing(stream),
2425 session_to_close_(session_to_close) {}
2426
2427 ~SessionClosingDelegate() override = default;
2428
OnClose(int status)2429 void OnClose(int status) override {
2430 session_to_close_->CloseSessionOnError(ERR_HTTP2_PROTOCOL_ERROR, "Error");
2431 }
2432
2433 private:
2434 base::WeakPtr<SpdySession> session_to_close_;
2435 };
2436
2437 // Close an activated stream that closes its session. Nothing should
2438 // blow up. This is a regression test for https://crbug.com/263691.
TEST_F(SpdySessionTest,CloseActivatedStreamThatClosesSession)2439 TEST_F(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2440 spdy::SpdySerializedFrame req(
2441 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
2442 spdy::SpdySerializedFrame rst(
2443 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
2444 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
2445 0, spdy::ERROR_CODE_PROTOCOL_ERROR, "Error"));
2446 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2447 // despite being queued second.
2448 MockWrite writes[] = {
2449 CreateMockWrite(req, 0), CreateMockWrite(goaway, 1),
2450 CreateMockWrite(rst, 3),
2451 };
2452
2453 MockRead reads[] = {
2454 MockRead(ASYNC, 0, 2) // EOF
2455 };
2456 SequencedSocketData data(reads, writes);
2457 session_deps_.socket_factory->AddSocketDataProvider(&data);
2458
2459 AddSSLSocketData();
2460
2461 CreateNetworkSession();
2462 CreateSpdySession();
2463
2464 base::WeakPtr<SpdyStream> spdy_stream =
2465 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2466 test_url_, MEDIUM, NetLogWithSource());
2467 ASSERT_TRUE(spdy_stream);
2468 EXPECT_EQ(0u, spdy_stream->stream_id());
2469
2470 SessionClosingDelegate delegate(spdy_stream, session_);
2471 spdy_stream->SetDelegate(&delegate);
2472
2473 spdy::Http2HeaderBlock headers(
2474 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2475 spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
2476
2477 EXPECT_EQ(0u, spdy_stream->stream_id());
2478
2479 base::RunLoop().RunUntilIdle();
2480
2481 EXPECT_EQ(1u, spdy_stream->stream_id());
2482
2483 // Ensure we don't crash while closing the stream (which closes the
2484 // session).
2485 spdy_stream->Cancel(ERR_ABORTED);
2486
2487 EXPECT_FALSE(spdy_stream);
2488 EXPECT_TRUE(delegate.StreamIsClosed());
2489
2490 // Write the RST_STREAM & GOAWAY.
2491 base::RunLoop().RunUntilIdle();
2492 EXPECT_TRUE(data.AllWriteDataConsumed());
2493 EXPECT_TRUE(data.AllReadDataConsumed());
2494 }
2495
TEST_F(SpdySessionTest,VerifyDomainAuthentication)2496 TEST_F(SpdySessionTest, VerifyDomainAuthentication) {
2497 SequencedSocketData data;
2498 session_deps_.socket_factory->AddSocketDataProvider(&data);
2499
2500 AddSSLSocketData();
2501
2502 CreateNetworkSession();
2503 CreateSpdySession();
2504
2505 EXPECT_TRUE(session_->VerifyDomainAuthentication("www.example.org"));
2506 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.org"));
2507 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.com"));
2508 EXPECT_FALSE(session_->VerifyDomainAuthentication("mail.google.com"));
2509 }
2510
TEST_F(SpdySessionTest,CloseTwoStalledCreateStream)2511 TEST_F(SpdySessionTest, CloseTwoStalledCreateStream) {
2512 // TODO(rtenneti): Define a helper class/methods and move the common code in
2513 // this file.
2514 spdy::SettingsMap new_settings;
2515 const spdy::SpdySettingsId kSpdySettingsId1 =
2516 spdy::SETTINGS_MAX_CONCURRENT_STREAMS;
2517 const uint32_t max_concurrent_streams = 1;
2518 new_settings[kSpdySettingsId1] = max_concurrent_streams;
2519
2520 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
2521 spdy::SpdySerializedFrame req1(
2522 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2523 spdy_util_.UpdateWithStreamDestruction(1);
2524 spdy::SpdySerializedFrame req2(
2525 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
2526 spdy_util_.UpdateWithStreamDestruction(3);
2527 spdy::SpdySerializedFrame req3(
2528 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST));
2529 MockWrite writes[] = {
2530 CreateMockWrite(settings_ack, 1), CreateMockWrite(req1, 2),
2531 CreateMockWrite(req2, 5), CreateMockWrite(req3, 8),
2532 };
2533
2534 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2535 // streams to 1.
2536 spdy::SpdySerializedFrame settings_frame(
2537 spdy_util_.ConstructSpdySettings(new_settings));
2538
2539 spdy::SpdySerializedFrame resp1(
2540 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2541 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
2542
2543 spdy::SpdySerializedFrame resp2(
2544 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
2545 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
2546
2547 spdy::SpdySerializedFrame resp3(
2548 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
2549 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true));
2550
2551 MockRead reads[] = {
2552 CreateMockRead(settings_frame, 0),
2553 CreateMockRead(resp1, 3),
2554 CreateMockRead(body1, 4),
2555 CreateMockRead(resp2, 6),
2556 CreateMockRead(body2, 7),
2557 CreateMockRead(resp3, 9),
2558 CreateMockRead(body3, 10),
2559 MockRead(ASYNC, ERR_IO_PENDING, 11),
2560 MockRead(ASYNC, 0, 12) // EOF
2561 };
2562
2563 SequencedSocketData data(reads, writes);
2564 session_deps_.socket_factory->AddSocketDataProvider(&data);
2565
2566 AddSSLSocketData();
2567
2568 CreateNetworkSession();
2569 CreateSpdySession();
2570
2571 // Read the settings frame.
2572 base::RunLoop().RunUntilIdle();
2573
2574 base::WeakPtr<SpdyStream> spdy_stream1 =
2575 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2576 test_url_, LOWEST, NetLogWithSource());
2577 ASSERT_TRUE(spdy_stream1);
2578 EXPECT_EQ(0u, spdy_stream1->stream_id());
2579 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2580 spdy_stream1->SetDelegate(&delegate1);
2581
2582 TestCompletionCallback callback2;
2583 SpdyStreamRequest request2;
2584 ASSERT_EQ(ERR_IO_PENDING,
2585 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_,
2586 test_url_, false, LOWEST, SocketTag(),
2587 NetLogWithSource(), callback2.callback(),
2588 TRAFFIC_ANNOTATION_FOR_TESTS));
2589
2590 TestCompletionCallback callback3;
2591 SpdyStreamRequest request3;
2592 ASSERT_EQ(ERR_IO_PENDING,
2593 request3.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_,
2594 test_url_, false, LOWEST, SocketTag(),
2595 NetLogWithSource(), callback3.callback(),
2596 TRAFFIC_ANNOTATION_FOR_TESTS));
2597
2598 EXPECT_EQ(0u, num_active_streams());
2599 EXPECT_EQ(1u, num_created_streams());
2600 EXPECT_EQ(2u, pending_create_stream_queue_size(LOWEST));
2601
2602 spdy::Http2HeaderBlock headers(
2603 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2604 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
2605
2606 // Run until 1st stream is activated and then closed.
2607 EXPECT_EQ(0u, delegate1.stream_id());
2608 base::RunLoop().RunUntilIdle();
2609 EXPECT_FALSE(spdy_stream1);
2610 EXPECT_EQ(1u, delegate1.stream_id());
2611
2612 EXPECT_EQ(0u, num_active_streams());
2613 EXPECT_EQ(1u, pending_create_stream_queue_size(LOWEST));
2614
2615 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2616 // create the 2nd stream.
2617 base::RunLoop().RunUntilIdle();
2618
2619 EXPECT_EQ(0u, num_active_streams());
2620 EXPECT_EQ(1u, num_created_streams());
2621 EXPECT_EQ(1u, pending_create_stream_queue_size(LOWEST));
2622
2623 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2624 test::StreamDelegateDoNothing delegate2(stream2);
2625 stream2->SetDelegate(&delegate2);
2626 spdy::Http2HeaderBlock headers2(
2627 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2628 stream2->SendRequestHeaders(std::move(headers2), NO_MORE_DATA_TO_SEND);
2629
2630 // Run until 2nd stream is activated and then closed.
2631 EXPECT_EQ(0u, delegate2.stream_id());
2632 base::RunLoop().RunUntilIdle();
2633 EXPECT_FALSE(stream2);
2634 EXPECT_EQ(3u, delegate2.stream_id());
2635
2636 EXPECT_EQ(0u, num_active_streams());
2637 EXPECT_EQ(0u, pending_create_stream_queue_size(LOWEST));
2638
2639 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2640 // create the 3rd stream.
2641 base::RunLoop().RunUntilIdle();
2642
2643 EXPECT_EQ(0u, num_active_streams());
2644 EXPECT_EQ(1u, num_created_streams());
2645 EXPECT_EQ(0u, pending_create_stream_queue_size(LOWEST));
2646
2647 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2648 test::StreamDelegateDoNothing delegate3(stream3);
2649 stream3->SetDelegate(&delegate3);
2650 spdy::Http2HeaderBlock headers3(
2651 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2652 stream3->SendRequestHeaders(std::move(headers3), NO_MORE_DATA_TO_SEND);
2653
2654 // Run until 2nd stream is activated and then closed.
2655 EXPECT_EQ(0u, delegate3.stream_id());
2656 base::RunLoop().RunUntilIdle();
2657 EXPECT_FALSE(stream3);
2658 EXPECT_EQ(5u, delegate3.stream_id());
2659
2660 EXPECT_EQ(0u, num_active_streams());
2661 EXPECT_EQ(0u, num_created_streams());
2662 EXPECT_EQ(0u, pending_create_stream_queue_size(LOWEST));
2663
2664 data.Resume();
2665 base::RunLoop().RunUntilIdle();
2666 }
2667
TEST_F(SpdySessionTest,CancelTwoStalledCreateStream)2668 TEST_F(SpdySessionTest, CancelTwoStalledCreateStream) {
2669 MockRead reads[] = {
2670 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2671 };
2672
2673 StaticSocketDataProvider data(reads, base::span<MockWrite>());
2674 session_deps_.socket_factory->AddSocketDataProvider(&data);
2675
2676 AddSSLSocketData();
2677
2678 CreateNetworkSession();
2679 CreateSpdySession();
2680
2681 // Leave room for only one more stream to be created.
2682 for (int i = 0; i < kH2InitialMaxConcurrentStreams.Get() - 1; ++i) {
2683 base::WeakPtr<SpdyStream> spdy_stream =
2684 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_,
2685 test_url_, MEDIUM, NetLogWithSource());
2686 ASSERT_TRUE(spdy_stream);
2687 }
2688
2689 base::WeakPtr<SpdyStream> spdy_stream1 =
2690 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
2691 LOWEST, NetLogWithSource());
2692 ASSERT_TRUE(spdy_stream1);
2693 EXPECT_EQ(0u, spdy_stream1->stream_id());
2694
2695 TestCompletionCallback callback2;
2696 SpdyStreamRequest request2;
2697 ASSERT_EQ(ERR_IO_PENDING,
2698 request2.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_,
2699 test_url_, false, LOWEST, SocketTag(),
2700 NetLogWithSource(), callback2.callback(),
2701 TRAFFIC_ANNOTATION_FOR_TESTS));
2702
2703 TestCompletionCallback callback3;
2704 SpdyStreamRequest request3;
2705 ASSERT_EQ(ERR_IO_PENDING,
2706 request3.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_,
2707 test_url_, false, LOWEST, SocketTag(),
2708 NetLogWithSource(), callback3.callback(),
2709 TRAFFIC_ANNOTATION_FOR_TESTS));
2710
2711 EXPECT_EQ(0u, num_active_streams());
2712 EXPECT_EQ(static_cast<size_t>(kH2InitialMaxConcurrentStreams.Get()),
2713 num_created_streams());
2714 EXPECT_EQ(2u, pending_create_stream_queue_size(LOWEST));
2715
2716 // Cancel the first stream; this will allow the second stream to be created.
2717 EXPECT_TRUE(spdy_stream1);
2718 spdy_stream1->Cancel(ERR_ABORTED);
2719 EXPECT_FALSE(spdy_stream1);
2720
2721 EXPECT_THAT(callback2.WaitForResult(), IsOk());
2722 EXPECT_EQ(0u, num_active_streams());
2723 EXPECT_EQ(static_cast<size_t>(kH2InitialMaxConcurrentStreams.Get()),
2724 num_created_streams());
2725 EXPECT_EQ(1u, pending_create_stream_queue_size(LOWEST));
2726
2727 // Cancel the second stream; this will allow the third stream to be created.
2728 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2729 spdy_stream2->Cancel(ERR_ABORTED);
2730 EXPECT_FALSE(spdy_stream2);
2731
2732 EXPECT_THAT(callback3.WaitForResult(), IsOk());
2733 EXPECT_EQ(0u, num_active_streams());
2734 EXPECT_EQ(static_cast<size_t>(kH2InitialMaxConcurrentStreams.Get()),
2735 num_created_streams());
2736 EXPECT_EQ(0u, pending_create_stream_queue_size(LOWEST));
2737
2738 // Cancel the third stream.
2739 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2740 spdy_stream3->Cancel(ERR_ABORTED);
2741 EXPECT_FALSE(spdy_stream3);
2742 EXPECT_EQ(0u, num_active_streams());
2743 EXPECT_EQ(static_cast<size_t>(kH2InitialMaxConcurrentStreams.Get()) - 1,
2744 num_created_streams());
2745 EXPECT_EQ(0u, pending_create_stream_queue_size(LOWEST));
2746 }
2747
2748 // Test that SpdySession::DoReadLoop reads data from the socket
2749 // without yielding. This test makes 32k - 1 bytes of data available
2750 // on the socket for reading. It then verifies that it has read all
2751 // the available data without yielding.
TEST_F(SpdySessionTest,ReadDataWithoutYielding)2752 TEST_F(SpdySessionTest, ReadDataWithoutYielding) {
2753 session_deps_.time_func = InstantaneousReads;
2754
2755 spdy::SpdySerializedFrame req1(
2756 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
2757 MockWrite writes[] = {
2758 CreateMockWrite(req1, 0),
2759 };
2760
2761 // Build buffer of size kYieldAfterBytesRead / 4
2762 // (-spdy_data_frame_size).
2763 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2764 const int kPayloadSize = kYieldAfterBytesRead / 4 - spdy::kFrameHeaderSize;
2765 TestDataStream test_stream;
2766 auto payload = base::MakeRefCounted<IOBufferWithSize>(kPayloadSize);
2767 char* payload_data = payload->data();
2768 test_stream.GetBytes(payload_data, kPayloadSize);
2769
2770 spdy::SpdySerializedFrame partial_data_frame(
2771 spdy_util_.ConstructSpdyDataFrame(
2772 1, base::StringPiece(payload_data, kPayloadSize), /*fin=*/false));
2773 spdy::SpdySerializedFrame finish_data_frame(spdy_util_.ConstructSpdyDataFrame(
2774 1, base::StringPiece(payload_data, kPayloadSize - 1), /*fin=*/true));
2775
2776 spdy::SpdySerializedFrame resp1(
2777 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2778
2779 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2780 // bytes.
2781 MockRead reads[] = {
2782 CreateMockRead(resp1, 1),
2783 MockRead(ASYNC, ERR_IO_PENDING, 2),
2784 CreateMockRead(partial_data_frame, 3),
2785 CreateMockRead(partial_data_frame, 4, SYNCHRONOUS),
2786 CreateMockRead(partial_data_frame, 5, SYNCHRONOUS),
2787 CreateMockRead(finish_data_frame, 6, SYNCHRONOUS),
2788 MockRead(ASYNC, 0, 7) // EOF
2789 };
2790
2791 // Create SpdySession and SpdyStream and send the request.
2792 SequencedSocketData data(reads, writes);
2793 session_deps_.socket_factory->AddSocketDataProvider(&data);
2794
2795 AddSSLSocketData();
2796
2797 CreateNetworkSession();
2798 CreateSpdySession();
2799
2800 base::WeakPtr<SpdyStream> spdy_stream1 =
2801 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2802 test_url_, MEDIUM, NetLogWithSource());
2803 ASSERT_TRUE(spdy_stream1);
2804 EXPECT_EQ(0u, spdy_stream1->stream_id());
2805 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2806 spdy_stream1->SetDelegate(&delegate1);
2807
2808 spdy::Http2HeaderBlock headers1(
2809 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2810 spdy_stream1->SendRequestHeaders(std::move(headers1), NO_MORE_DATA_TO_SEND);
2811
2812 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2813 // post a task.
2814 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2815
2816 // Run until 1st read.
2817 EXPECT_EQ(0u, delegate1.stream_id());
2818 base::RunLoop().RunUntilIdle();
2819 EXPECT_EQ(1u, delegate1.stream_id());
2820 EXPECT_EQ(0u, observer.executed_count());
2821
2822 // Read all the data and verify SpdySession::DoReadLoop has not
2823 // posted a task.
2824 data.Resume();
2825 base::RunLoop().RunUntilIdle();
2826 EXPECT_FALSE(spdy_stream1);
2827
2828 // Verify task observer's executed_count is zero, which indicates DoRead read
2829 // all the available data.
2830 EXPECT_EQ(0u, observer.executed_count());
2831 EXPECT_TRUE(data.AllWriteDataConsumed());
2832 EXPECT_TRUE(data.AllReadDataConsumed());
2833 }
2834
2835 // Test that SpdySession::DoReadLoop yields if more than
2836 // |kYieldAfterDurationMilliseconds| has passed. This test uses a mock time
2837 // function that makes the response frame look very slow to read.
TEST_F(SpdySessionTest,TestYieldingSlowReads)2838 TEST_F(SpdySessionTest, TestYieldingSlowReads) {
2839 session_deps_.time_func = SlowReads;
2840
2841 spdy::SpdySerializedFrame req1(
2842 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
2843 MockWrite writes[] = {
2844 CreateMockWrite(req1, 0),
2845 };
2846
2847 spdy::SpdySerializedFrame resp1(
2848 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2849
2850 MockRead reads[] = {
2851 CreateMockRead(resp1, 1), MockRead(ASYNC, 0, 2) // EOF
2852 };
2853
2854 // Create SpdySession and SpdyStream and send the request.
2855 SequencedSocketData data(reads, writes);
2856 session_deps_.socket_factory->AddSocketDataProvider(&data);
2857
2858 AddSSLSocketData();
2859
2860 CreateNetworkSession();
2861 CreateSpdySession();
2862
2863 base::WeakPtr<SpdyStream> spdy_stream1 =
2864 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2865 test_url_, MEDIUM, NetLogWithSource());
2866 ASSERT_TRUE(spdy_stream1);
2867 EXPECT_EQ(0u, spdy_stream1->stream_id());
2868 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2869 spdy_stream1->SetDelegate(&delegate1);
2870
2871 spdy::Http2HeaderBlock headers1(
2872 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2873 spdy_stream1->SendRequestHeaders(std::move(headers1), NO_MORE_DATA_TO_SEND);
2874
2875 // Set up the TaskObserver to verify that SpdySession::DoReadLoop posts a
2876 // task.
2877 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2878
2879 EXPECT_EQ(0u, delegate1.stream_id());
2880 EXPECT_EQ(0u, observer.executed_count());
2881
2882 // Read all the data and verify that SpdySession::DoReadLoop has posted a
2883 // task.
2884 base::RunLoop().RunUntilIdle();
2885 EXPECT_EQ(1u, delegate1.stream_id());
2886 EXPECT_FALSE(spdy_stream1);
2887
2888 // Verify task that the observer's executed_count is 1, which indicates DoRead
2889 // has posted only one task and thus yielded though there is data available
2890 // for it to read.
2891 EXPECT_EQ(1u, observer.executed_count());
2892 EXPECT_TRUE(data.AllWriteDataConsumed());
2893 EXPECT_TRUE(data.AllReadDataConsumed());
2894 }
2895
2896 // Regression test for https://crbug.com/531570.
2897 // Test the case where DoRead() takes long but returns synchronously.
TEST_F(SpdySessionTest,TestYieldingSlowSynchronousReads)2898 TEST_F(SpdySessionTest, TestYieldingSlowSynchronousReads) {
2899 session_deps_.time_func = SlowReads;
2900
2901 spdy::SpdySerializedFrame req1(
2902 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
2903 MockWrite writes[] = {
2904 CreateMockWrite(req1, 0),
2905 };
2906
2907 spdy::SpdySerializedFrame partial_data_frame(
2908 spdy_util_.ConstructSpdyDataFrame(1, "foo ", /*fin=*/false));
2909 spdy::SpdySerializedFrame finish_data_frame(
2910 spdy_util_.ConstructSpdyDataFrame(1, "bar", /*fin=*/true));
2911
2912 spdy::SpdySerializedFrame resp1(
2913 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2914
2915 MockRead reads[] = {
2916 CreateMockRead(resp1, 1),
2917 MockRead(ASYNC, ERR_IO_PENDING, 2),
2918 CreateMockRead(partial_data_frame, 3, ASYNC),
2919 CreateMockRead(partial_data_frame, 4, SYNCHRONOUS),
2920 CreateMockRead(partial_data_frame, 5, SYNCHRONOUS),
2921 CreateMockRead(finish_data_frame, 6, SYNCHRONOUS),
2922 MockRead(ASYNC, 0, 7) // EOF
2923 };
2924
2925 // Create SpdySession and SpdyStream and send the request.
2926 SequencedSocketData data(reads, writes);
2927 session_deps_.socket_factory->AddSocketDataProvider(&data);
2928
2929 AddSSLSocketData();
2930
2931 CreateNetworkSession();
2932 CreateSpdySession();
2933
2934 base::WeakPtr<SpdyStream> spdy_stream1 =
2935 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
2936 test_url_, MEDIUM, NetLogWithSource());
2937 ASSERT_TRUE(spdy_stream1);
2938 EXPECT_EQ(0u, spdy_stream1->stream_id());
2939 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2940 spdy_stream1->SetDelegate(&delegate1);
2941
2942 spdy::Http2HeaderBlock headers1(
2943 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2944 spdy_stream1->SendRequestHeaders(std::move(headers1), NO_MORE_DATA_TO_SEND);
2945
2946 // Run until 1st read.
2947 EXPECT_EQ(0u, delegate1.stream_id());
2948 base::RunLoop().RunUntilIdle();
2949 EXPECT_EQ(1u, delegate1.stream_id());
2950
2951 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
2952 data.Resume();
2953 base::RunLoop().RunUntilIdle();
2954 EXPECT_EQ("foo foo foo bar", delegate1.TakeReceivedData());
2955 EXPECT_FALSE(spdy_stream1);
2956
2957 EXPECT_TRUE(data.AllWriteDataConsumed());
2958 EXPECT_TRUE(data.AllReadDataConsumed());
2959 }
2960
2961 // Test that SpdySession::DoReadLoop yields while reading the
2962 // data. This test makes 32k + 1 bytes of data available on the socket
2963 // for reading. It then verifies that DoRead has yielded even though
2964 // there is data available for it to read (i.e, socket()->Read didn't
2965 // return ERR_IO_PENDING during socket reads).
TEST_F(SpdySessionTest,TestYieldingDuringReadData)2966 TEST_F(SpdySessionTest, TestYieldingDuringReadData) {
2967 session_deps_.time_func = InstantaneousReads;
2968
2969 spdy::SpdySerializedFrame req1(
2970 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
2971 MockWrite writes[] = {
2972 CreateMockWrite(req1, 0),
2973 };
2974
2975 // Build buffer of size kYieldAfterBytesRead / 4
2976 // (-spdy_data_frame_size).
2977 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2978 const int kPayloadSize = kYieldAfterBytesRead / 4 - spdy::kFrameHeaderSize;
2979 TestDataStream test_stream;
2980 auto payload = base::MakeRefCounted<IOBufferWithSize>(kPayloadSize);
2981 char* payload_data = payload->data();
2982 test_stream.GetBytes(payload_data, kPayloadSize);
2983
2984 spdy::SpdySerializedFrame partial_data_frame(
2985 spdy_util_.ConstructSpdyDataFrame(
2986 1, base::StringPiece(payload_data, kPayloadSize), /*fin=*/false));
2987 spdy::SpdySerializedFrame finish_data_frame(
2988 spdy_util_.ConstructSpdyDataFrame(1, "h", /*fin=*/true));
2989
2990 spdy::SpdySerializedFrame resp1(
2991 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2992
2993 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2994 MockRead reads[] = {
2995 CreateMockRead(resp1, 1),
2996 MockRead(ASYNC, ERR_IO_PENDING, 2),
2997 CreateMockRead(partial_data_frame, 3),
2998 CreateMockRead(partial_data_frame, 4, SYNCHRONOUS),
2999 CreateMockRead(partial_data_frame, 5, SYNCHRONOUS),
3000 CreateMockRead(partial_data_frame, 6, SYNCHRONOUS),
3001 CreateMockRead(finish_data_frame, 7, SYNCHRONOUS),
3002 MockRead(ASYNC, 0, 8) // EOF
3003 };
3004
3005 // Create SpdySession and SpdyStream and send the request.
3006 SequencedSocketData data(reads, writes);
3007 session_deps_.socket_factory->AddSocketDataProvider(&data);
3008
3009 AddSSLSocketData();
3010
3011 CreateNetworkSession();
3012 CreateSpdySession();
3013
3014 base::WeakPtr<SpdyStream> spdy_stream1 =
3015 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
3016 test_url_, MEDIUM, NetLogWithSource());
3017 ASSERT_TRUE(spdy_stream1);
3018 EXPECT_EQ(0u, spdy_stream1->stream_id());
3019 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3020 spdy_stream1->SetDelegate(&delegate1);
3021
3022 spdy::Http2HeaderBlock headers1(
3023 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
3024 spdy_stream1->SendRequestHeaders(std::move(headers1), NO_MORE_DATA_TO_SEND);
3025
3026 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a task.
3027 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
3028
3029 // Run until 1st read.
3030 EXPECT_EQ(0u, delegate1.stream_id());
3031 base::RunLoop().RunUntilIdle();
3032 EXPECT_EQ(1u, delegate1.stream_id());
3033 EXPECT_EQ(0u, observer.executed_count());
3034
3035 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
3036 data.Resume();
3037 base::RunLoop().RunUntilIdle();
3038 EXPECT_FALSE(spdy_stream1);
3039
3040 // Verify task observer's executed_count is 1, which indicates DoRead has
3041 // posted only one task and thus yielded though there is data available for it
3042 // to read.
3043 EXPECT_EQ(1u, observer.executed_count());
3044 EXPECT_TRUE(data.AllWriteDataConsumed());
3045 EXPECT_TRUE(data.AllReadDataConsumed());
3046 }
3047
3048 // Test that SpdySession::DoReadLoop() tests interactions of yielding
3049 // + async, by doing the following MockReads.
3050 //
3051 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
3052 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
3053 //
3054 // The above reads 26K synchronously. Since that is less that 32K, we
3055 // will attempt to read again. However, that DoRead() will return
3056 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
3057 // yield. When we come back, DoRead() will read the results from the
3058 // async read, and rest of the data synchronously.
TEST_F(SpdySessionTest,TestYieldingDuringAsyncReadData)3059 TEST_F(SpdySessionTest, TestYieldingDuringAsyncReadData) {
3060 session_deps_.time_func = InstantaneousReads;
3061
3062 spdy::SpdySerializedFrame req1(
3063 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
3064 MockWrite writes[] = {
3065 CreateMockWrite(req1, 0),
3066 };
3067
3068 // Build buffer of size kYieldAfterBytesRead / 4
3069 // (-spdy_data_frame_size).
3070 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
3071 TestDataStream test_stream;
3072 const int kEightKPayloadSize =
3073 kYieldAfterBytesRead / 4 - spdy::kFrameHeaderSize;
3074 auto eightk_payload =
3075 base::MakeRefCounted<IOBufferWithSize>(kEightKPayloadSize);
3076 char* eightk_payload_data = eightk_payload->data();
3077 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
3078
3079 // Build buffer of 2k size.
3080 TestDataStream test_stream2;
3081 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
3082 auto twok_payload = base::MakeRefCounted<IOBufferWithSize>(kTwoKPayloadSize);
3083 char* twok_payload_data = twok_payload->data();
3084 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
3085
3086 spdy::SpdySerializedFrame eightk_data_frame(spdy_util_.ConstructSpdyDataFrame(
3087 1, base::StringPiece(eightk_payload_data, kEightKPayloadSize),
3088 /*fin=*/false));
3089 spdy::SpdySerializedFrame twok_data_frame(spdy_util_.ConstructSpdyDataFrame(
3090 1, base::StringPiece(twok_payload_data, kTwoKPayloadSize),
3091 /*fin=*/false));
3092 spdy::SpdySerializedFrame finish_data_frame(
3093 spdy_util_.ConstructSpdyDataFrame(1, "h", /*fin=*/true));
3094
3095 spdy::SpdySerializedFrame resp1(
3096 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3097
3098 MockRead reads[] = {
3099 CreateMockRead(resp1, 1),
3100 MockRead(ASYNC, ERR_IO_PENDING, 2),
3101 CreateMockRead(eightk_data_frame, 3),
3102 CreateMockRead(eightk_data_frame, 4, SYNCHRONOUS),
3103 CreateMockRead(eightk_data_frame, 5, SYNCHRONOUS),
3104 CreateMockRead(twok_data_frame, 6, SYNCHRONOUS),
3105 CreateMockRead(eightk_data_frame, 7, ASYNC),
3106 CreateMockRead(eightk_data_frame, 8, SYNCHRONOUS),
3107 CreateMockRead(eightk_data_frame, 9, SYNCHRONOUS),
3108 CreateMockRead(eightk_data_frame, 10, SYNCHRONOUS),
3109 CreateMockRead(twok_data_frame, 11, SYNCHRONOUS),
3110 CreateMockRead(finish_data_frame, 12, SYNCHRONOUS),
3111 MockRead(ASYNC, 0, 13) // EOF
3112 };
3113
3114 // Create SpdySession and SpdyStream and send the request.
3115 SequencedSocketData data(reads, writes);
3116 session_deps_.socket_factory->AddSocketDataProvider(&data);
3117
3118 AddSSLSocketData();
3119
3120 CreateNetworkSession();
3121 CreateSpdySession();
3122
3123 base::WeakPtr<SpdyStream> spdy_stream1 =
3124 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
3125 test_url_, MEDIUM, NetLogWithSource());
3126 ASSERT_TRUE(spdy_stream1);
3127 EXPECT_EQ(0u, spdy_stream1->stream_id());
3128 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3129 spdy_stream1->SetDelegate(&delegate1);
3130
3131 spdy::Http2HeaderBlock headers1(
3132 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
3133 spdy_stream1->SendRequestHeaders(std::move(headers1), NO_MORE_DATA_TO_SEND);
3134
3135 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
3136 // posting of tasks.
3137 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
3138
3139 // Run until 1st read.
3140 EXPECT_EQ(0u, delegate1.stream_id());
3141 base::RunLoop().RunUntilIdle();
3142 EXPECT_EQ(1u, delegate1.stream_id());
3143 EXPECT_EQ(0u, observer.executed_count());
3144
3145 // Read all the data and verify SpdySession::DoReadLoop has posted a
3146 // task.
3147 data.Resume();
3148 base::RunLoop().RunUntilIdle();
3149 EXPECT_FALSE(spdy_stream1);
3150
3151 // Verify task observer's executed_count is 1, which indicates DoRead has
3152 // posted only one task and thus yielded though there is data available for
3153 // it to read.
3154 EXPECT_EQ(1u, observer.executed_count());
3155 EXPECT_TRUE(data.AllWriteDataConsumed());
3156 EXPECT_TRUE(data.AllReadDataConsumed());
3157 }
3158
3159 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
3160 // nothing blows up.
TEST_F(SpdySessionTest,GoAwayWhileInDoReadLoop)3161 TEST_F(SpdySessionTest, GoAwayWhileInDoReadLoop) {
3162 spdy::SpdySerializedFrame req1(
3163 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
3164 MockWrite writes[] = {
3165 CreateMockWrite(req1, 0),
3166 };
3167
3168 spdy::SpdySerializedFrame resp1(
3169 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3170 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
3171 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(0));
3172
3173 MockRead reads[] = {
3174 CreateMockRead(resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
3175 CreateMockRead(body1, 3), CreateMockRead(goaway, 4),
3176 };
3177
3178 // Create SpdySession and SpdyStream and send the request.
3179 SequencedSocketData data(reads, writes);
3180 session_deps_.socket_factory->AddSocketDataProvider(&data);
3181
3182 AddSSLSocketData();
3183
3184 CreateNetworkSession();
3185 CreateSpdySession();
3186
3187 base::WeakPtr<SpdyStream> spdy_stream1 =
3188 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
3189 test_url_, MEDIUM, NetLogWithSource());
3190 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3191 spdy_stream1->SetDelegate(&delegate1);
3192 ASSERT_TRUE(spdy_stream1);
3193 EXPECT_EQ(0u, spdy_stream1->stream_id());
3194
3195 spdy::Http2HeaderBlock headers1(
3196 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
3197 spdy_stream1->SendRequestHeaders(std::move(headers1), NO_MORE_DATA_TO_SEND);
3198
3199 // Run until 1st read.
3200 EXPECT_EQ(0u, spdy_stream1->stream_id());
3201 base::RunLoop().RunUntilIdle();
3202 EXPECT_EQ(1u, spdy_stream1->stream_id());
3203
3204 // Run until GoAway.
3205 data.Resume();
3206 base::RunLoop().RunUntilIdle();
3207 EXPECT_FALSE(spdy_stream1);
3208 EXPECT_TRUE(data.AllWriteDataConsumed());
3209 EXPECT_TRUE(data.AllReadDataConsumed());
3210 EXPECT_FALSE(session_);
3211 }
3212
3213 // Within this framework, a SpdySession should be initialized with
3214 // flow control disabled for protocol version 2, with flow control
3215 // enabled only for streams for protocol version 3, and with flow
3216 // control enabled for streams and sessions for higher versions.
TEST_F(SpdySessionTest,ProtocolNegotiation)3217 TEST_F(SpdySessionTest, ProtocolNegotiation) {
3218 MockRead reads[] = {
3219 MockRead(SYNCHRONOUS, 0, 0) // EOF
3220 };
3221 StaticSocketDataProvider data(reads, base::span<MockWrite>());
3222 session_deps_.socket_factory->AddSocketDataProvider(&data);
3223
3224 CreateNetworkSession();
3225 session_ = CreateFakeSpdySession(spdy_session_pool_, key_);
3226
3227 EXPECT_EQ(kDefaultInitialWindowSize, session_send_window_size());
3228 EXPECT_EQ(kDefaultInitialWindowSize, session_recv_window_size());
3229 EXPECT_EQ(0, session_unacked_recv_window_bytes());
3230 }
3231
3232 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3233 // pointers to the idle session are currently held.
TEST_F(SpdySessionTest,CloseOneIdleConnection)3234 TEST_F(SpdySessionTest, CloseOneIdleConnection) {
3235 ClientSocketPoolManager::set_max_sockets_per_group(
3236 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3237 ClientSocketPoolManager::set_max_sockets_per_pool(
3238 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3239
3240 MockRead reads[] = {
3241 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3242 };
3243 StaticSocketDataProvider data(reads, base::span<MockWrite>());
3244 session_deps_.socket_factory->AddSocketDataProvider(&data);
3245 session_deps_.socket_factory->AddSocketDataProvider(&data);
3246
3247 AddSSLSocketData();
3248
3249 CreateNetworkSession();
3250
3251 ClientSocketPool* pool = http_session_->GetSocketPool(
3252 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
3253
3254 // Create an idle SPDY session.
3255 CreateSpdySession();
3256 EXPECT_FALSE(pool->IsStalled());
3257
3258 // Trying to create a new connection should cause the pool to be stalled, and
3259 // post a task asynchronously to try and close the session.
3260 TestCompletionCallback callback2;
3261 auto connection2 = std::make_unique<ClientSocketHandle>();
3262 EXPECT_EQ(ERR_IO_PENDING,
3263 connection2->Init(
3264 ClientSocketPool::GroupId(
3265 url::SchemeHostPort(url::kHttpScheme, "2.com", 80),
3266 PrivacyMode::PRIVACY_MODE_DISABLED,
3267 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow),
3268 ClientSocketPool::SocketParams::CreateForHttpForTesting(),
3269 absl::nullopt /* proxy_annotation_tag */, DEFAULT_PRIORITY,
3270 SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
3271 callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
3272 pool, NetLogWithSource()));
3273 EXPECT_TRUE(pool->IsStalled());
3274
3275 // The socket pool should close the connection asynchronously and establish a
3276 // new connection.
3277 EXPECT_THAT(callback2.WaitForResult(), IsOk());
3278 EXPECT_FALSE(pool->IsStalled());
3279 EXPECT_FALSE(session_);
3280 }
3281
3282 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3283 // pointers to the idle session are currently held, in the case the SPDY session
3284 // has an alias.
TEST_F(SpdySessionTest,CloseOneIdleConnectionWithAlias)3285 TEST_F(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3286 ClientSocketPoolManager::set_max_sockets_per_group(
3287 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3288 ClientSocketPoolManager::set_max_sockets_per_pool(
3289 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3290
3291 MockRead reads[] = {
3292 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3293 };
3294 StaticSocketDataProvider data(reads, base::span<MockWrite>());
3295 session_deps_.socket_factory->AddSocketDataProvider(&data);
3296 session_deps_.socket_factory->AddSocketDataProvider(&data);
3297
3298 AddSSLSocketData();
3299
3300 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3301 "www.example.org", "192.168.0.2", std::string());
3302
3303 CreateNetworkSession();
3304
3305 ClientSocketPool* pool = http_session_->GetSocketPool(
3306 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
3307
3308 // Create an idle SPDY session.
3309 SpdySessionKey key1(HostPortPair("www.example.org", 80), ProxyChain::Direct(),
3310 PRIVACY_MODE_DISABLED,
3311 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
3312 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
3313 base::WeakPtr<SpdySession> session1 =
3314 ::net::CreateSpdySession(http_session_.get(), key1, NetLogWithSource());
3315 EXPECT_FALSE(pool->IsStalled());
3316
3317 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3318 SpdySessionKey key2(HostPortPair("mail.example.org", 80),
3319 ProxyChain::Direct(), PRIVACY_MODE_DISABLED,
3320 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
3321 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
3322 std::unique_ptr<SpdySessionPool::SpdySessionRequest> request;
3323 bool is_blocking_request_for_session = false;
3324 SpdySessionRequestDelegate request_delegate;
3325 EXPECT_FALSE(spdy_session_pool_->RequestSession(
3326 key2, /* enable_ip_based_pooling = */ true,
3327 /* is_websocket = */ false, NetLogWithSource(),
3328 /* on_blocking_request_destroyed_callback = */ base::RepeatingClosure(),
3329 &request_delegate, &request, &is_blocking_request_for_session));
3330 EXPECT_TRUE(request);
3331
3332 HostResolverEndpointResult endpoint;
3333 endpoint.ip_endpoints = {IPEndPoint(IPAddress(192, 168, 0, 2), 80)};
3334 // Simulate DNS resolution completing, which should set up an alias.
3335 EXPECT_EQ(OnHostResolutionCallbackResult::kMayBeDeletedAsync,
3336 spdy_session_pool_->OnHostResolutionComplete(
3337 key2, /* is_websocket = */ false, {endpoint},
3338 /*aliases=*/{}));
3339
3340 // Get a session for |key2|, which should return the session created earlier.
3341 base::WeakPtr<SpdySession> session2 =
3342 spdy_session_pool_->FindAvailableSession(
3343 key2, /* enable_ip_based_pooling = */ true,
3344 /* is_websocket = */ false, NetLogWithSource());
3345 EXPECT_TRUE(session2);
3346 ASSERT_EQ(session1.get(), session2.get());
3347 EXPECT_FALSE(pool->IsStalled());
3348
3349 // Trying to create a new connection should cause the pool to be stalled, and
3350 // post a task asynchronously to try and close the session.
3351 TestCompletionCallback callback3;
3352 auto connection3 = std::make_unique<ClientSocketHandle>();
3353 EXPECT_EQ(ERR_IO_PENDING,
3354 connection3->Init(
3355 ClientSocketPool::GroupId(
3356 url::SchemeHostPort(url::kHttpScheme, "3.com", 80),
3357 PrivacyMode::PRIVACY_MODE_DISABLED,
3358 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow),
3359 ClientSocketPool::SocketParams::CreateForHttpForTesting(),
3360 absl::nullopt /* proxy_annotation_tag */, DEFAULT_PRIORITY,
3361 SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
3362 callback3.callback(), ClientSocketPool::ProxyAuthCallback(),
3363 pool, NetLogWithSource()));
3364 EXPECT_TRUE(pool->IsStalled());
3365
3366 // The socket pool should close the connection asynchronously and establish a
3367 // new connection.
3368 EXPECT_THAT(callback3.WaitForResult(), IsOk());
3369 EXPECT_FALSE(pool->IsStalled());
3370 EXPECT_FALSE(session1);
3371 EXPECT_FALSE(session2);
3372 }
3373
3374 // Tests that when a SPDY session becomes idle, it closes itself if there is
3375 // a lower layer pool stalled on the per-pool socket limit.
TEST_F(SpdySessionTest,CloseSessionOnIdleWhenPoolStalled)3376 TEST_F(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3377 ClientSocketPoolManager::set_max_sockets_per_group(
3378 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3379 ClientSocketPoolManager::set_max_sockets_per_pool(
3380 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3381
3382 MockRead reads[] = {
3383 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3384 };
3385 spdy::SpdySerializedFrame req1(
3386 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3387 spdy::SpdySerializedFrame cancel1(
3388 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
3389 MockWrite writes[] = {
3390 CreateMockWrite(req1, 1), CreateMockWrite(cancel1, 1),
3391 };
3392 StaticSocketDataProvider data(reads, writes);
3393 session_deps_.socket_factory->AddSocketDataProvider(&data);
3394
3395 MockRead http_reads[] = {
3396 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3397 };
3398 StaticSocketDataProvider http_data(http_reads, base::span<MockWrite>());
3399 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3400
3401 AddSSLSocketData();
3402
3403 CreateNetworkSession();
3404
3405 ClientSocketPool* pool = http_session_->GetSocketPool(
3406 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
3407
3408 // Create a SPDY session.
3409 CreateSpdySession();
3410 EXPECT_FALSE(pool->IsStalled());
3411
3412 // Create a stream using the session, and send a request.
3413
3414 TestCompletionCallback callback1;
3415 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
3416 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, DEFAULT_PRIORITY,
3417 NetLogWithSource());
3418 ASSERT_TRUE(spdy_stream1.get());
3419 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3420 spdy_stream1->SetDelegate(&delegate1);
3421
3422 spdy::Http2HeaderBlock headers1(
3423 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
3424 EXPECT_EQ(ERR_IO_PENDING, spdy_stream1->SendRequestHeaders(
3425 std::move(headers1), NO_MORE_DATA_TO_SEND));
3426
3427 base::RunLoop().RunUntilIdle();
3428
3429 // Trying to create a new connection should cause the pool to be stalled, and
3430 // post a task asynchronously to try and close the session.
3431 TestCompletionCallback callback2;
3432 auto connection2 = std::make_unique<ClientSocketHandle>();
3433 EXPECT_EQ(ERR_IO_PENDING,
3434 connection2->Init(
3435 ClientSocketPool::GroupId(
3436 url::SchemeHostPort(url::kHttpScheme, "2.com", 80),
3437 PrivacyMode::PRIVACY_MODE_DISABLED,
3438 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow),
3439 ClientSocketPool::SocketParams::CreateForHttpForTesting(),
3440 absl::nullopt /* proxy_annotation_tag */, DEFAULT_PRIORITY,
3441 SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
3442 callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
3443 pool, NetLogWithSource()));
3444 EXPECT_TRUE(pool->IsStalled());
3445
3446 // Running the message loop should cause the socket pool to ask the SPDY
3447 // session to close an idle socket, but since the socket is in use, nothing
3448 // happens.
3449 base::RunLoop().RunUntilIdle();
3450 EXPECT_TRUE(pool->IsStalled());
3451 EXPECT_FALSE(callback2.have_result());
3452
3453 // Cancelling the request should result in the session's socket being
3454 // closed, since the pool is stalled.
3455 ASSERT_TRUE(spdy_stream1.get());
3456 spdy_stream1->Cancel(ERR_ABORTED);
3457 base::RunLoop().RunUntilIdle();
3458 ASSERT_FALSE(pool->IsStalled());
3459 EXPECT_THAT(callback2.WaitForResult(), IsOk());
3460 }
3461
3462 // Verify that SpdySessionKey and therefore SpdySession is different when
3463 // privacy mode is enabled or disabled.
TEST_F(SpdySessionTest,SpdySessionKeyPrivacyMode)3464 TEST_F(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3465 CreateNetworkSession();
3466
3467 HostPortPair host_port_pair("www.example.org", 443);
3468 SpdySessionKey key_privacy_enabled(
3469 host_port_pair, ProxyChain::Direct(), PRIVACY_MODE_ENABLED,
3470 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
3471 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
3472 SpdySessionKey key_privacy_disabled(
3473 host_port_pair, ProxyChain::Direct(), PRIVACY_MODE_DISABLED,
3474 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
3475 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
3476
3477 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3478 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3479
3480 // Add SpdySession with PrivacyMode Enabled to the pool.
3481 base::WeakPtr<SpdySession> session_privacy_enabled =
3482 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3483
3484 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3485 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3486
3487 // Add SpdySession with PrivacyMode Disabled to the pool.
3488 base::WeakPtr<SpdySession> session_privacy_disabled =
3489 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3490
3491 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3492 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3493
3494 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3495 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3496 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3497
3498 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3499 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3500 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3501 }
3502
3503 // Delegate that creates another stream when its stream is closed.
3504 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3505 public:
StreamCreatingDelegate(const base::WeakPtr<SpdyStream> & stream,const base::WeakPtr<SpdySession> & session)3506 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3507 const base::WeakPtr<SpdySession>& session)
3508 : StreamDelegateDoNothing(stream),
3509 session_(session) {}
3510
3511 ~StreamCreatingDelegate() override = default;
3512
OnClose(int status)3513 void OnClose(int status) override {
3514 GURL url(kDefaultUrl);
3515 std::ignore =
3516 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_, url,
3517 MEDIUM, NetLogWithSource());
3518 }
3519
3520 private:
3521 const base::WeakPtr<SpdySession> session_;
3522 };
3523
3524 // Create another stream in response to a stream being reset. Nothing
3525 // should blow up. This is a regression test for
3526 // http://crbug.com/263690 .
TEST_F(SpdySessionTest,CreateStreamOnStreamReset)3527 TEST_F(SpdySessionTest, CreateStreamOnStreamReset) {
3528 spdy::SpdySerializedFrame req(
3529 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
3530 MockWrite writes[] = {
3531 CreateMockWrite(req, 0),
3532 };
3533
3534 spdy::SpdySerializedFrame rst(
3535 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_REFUSED_STREAM));
3536 MockRead reads[] = {
3537 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(rst, 2),
3538 MockRead(ASYNC, ERR_IO_PENDING, 3), MockRead(ASYNC, 0, 4) // EOF
3539 };
3540 SequencedSocketData data(reads, writes);
3541 session_deps_.socket_factory->AddSocketDataProvider(&data);
3542
3543 AddSSLSocketData();
3544
3545 CreateNetworkSession();
3546 CreateSpdySession();
3547
3548 base::WeakPtr<SpdyStream> spdy_stream =
3549 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
3550 test_url_, MEDIUM, NetLogWithSource());
3551 ASSERT_TRUE(spdy_stream);
3552 EXPECT_EQ(0u, spdy_stream->stream_id());
3553
3554 StreamCreatingDelegate delegate(spdy_stream, session_);
3555 spdy_stream->SetDelegate(&delegate);
3556
3557 spdy::Http2HeaderBlock headers(
3558 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
3559 spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
3560
3561 EXPECT_EQ(0u, spdy_stream->stream_id());
3562
3563 base::RunLoop().RunUntilIdle();
3564
3565 EXPECT_EQ(1u, spdy_stream->stream_id());
3566
3567 // Cause the stream to be reset, which should cause another stream
3568 // to be created.
3569 data.Resume();
3570 base::RunLoop().RunUntilIdle();
3571
3572 EXPECT_FALSE(spdy_stream);
3573 EXPECT_TRUE(delegate.StreamIsClosed());
3574 EXPECT_EQ(0u, num_active_streams());
3575 EXPECT_EQ(1u, num_created_streams());
3576
3577 data.Resume();
3578 base::RunLoop().RunUntilIdle();
3579 EXPECT_FALSE(session_);
3580 }
3581
TEST_F(SpdySessionTest,UpdateStreamsSendWindowSize)3582 TEST_F(SpdySessionTest, UpdateStreamsSendWindowSize) {
3583 // Set spdy::SETTINGS_INITIAL_WINDOW_SIZE to a small number so that
3584 // WINDOW_UPDATE gets sent.
3585 spdy::SettingsMap new_settings;
3586 int32_t window_size = 1;
3587 new_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = window_size;
3588
3589 // Set up the socket so we read a SETTINGS frame that sets
3590 // INITIAL_WINDOW_SIZE.
3591 spdy::SpdySerializedFrame settings_frame(
3592 spdy_util_.ConstructSpdySettings(new_settings));
3593 MockRead reads[] = {
3594 CreateMockRead(settings_frame, 0), MockRead(ASYNC, ERR_IO_PENDING, 1),
3595 MockRead(ASYNC, 0, 2) // EOF
3596 };
3597
3598 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
3599 MockWrite writes[] = {
3600 CreateMockWrite(settings_ack, 3),
3601 };
3602
3603 SequencedSocketData data(reads, writes);
3604 session_deps_.socket_factory->AddSocketDataProvider(&data);
3605
3606 AddSSLSocketData();
3607
3608 CreateNetworkSession();
3609 CreateSpdySession();
3610 base::WeakPtr<SpdyStream> spdy_stream1 =
3611 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
3612 MEDIUM, NetLogWithSource());
3613 ASSERT_TRUE(spdy_stream1);
3614 TestCompletionCallback callback1;
3615 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3616
3617 // Process the SETTINGS frame.
3618 base::RunLoop().RunUntilIdle();
3619 EXPECT_EQ(stream_initial_send_window_size(), window_size);
3620 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3621
3622 // Release the first one, this will allow the second to be created.
3623 spdy_stream1->Cancel(ERR_ABORTED);
3624 EXPECT_FALSE(spdy_stream1);
3625
3626 base::WeakPtr<SpdyStream> spdy_stream2 =
3627 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
3628 MEDIUM, NetLogWithSource());
3629 ASSERT_TRUE(spdy_stream2);
3630 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3631 spdy_stream2->Cancel(ERR_ABORTED);
3632 EXPECT_FALSE(spdy_stream2);
3633
3634 EXPECT_TRUE(session_);
3635 data.Resume();
3636 base::RunLoop().RunUntilIdle();
3637 EXPECT_FALSE(session_);
3638 }
3639
3640 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3641 // adjust the session receive window size. In addition,
3642 // SpdySession::IncreaseRecvWindowSize should trigger
3643 // sending a WINDOW_UPDATE frame for a large enough delta.
TEST_F(SpdySessionTest,AdjustRecvWindowSize)3644 TEST_F(SpdySessionTest, AdjustRecvWindowSize) {
3645 const int32_t initial_window_size = kDefaultInitialWindowSize;
3646 const int32_t delta_window_size = 100;
3647
3648 MockRead reads[] = {
3649 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
3650 };
3651 spdy::SpdySerializedFrame window_update(spdy_util_.ConstructSpdyWindowUpdate(
3652 spdy::kSessionFlowControlStreamId,
3653 initial_window_size + delta_window_size));
3654 MockWrite writes[] = {
3655 CreateMockWrite(window_update, 0),
3656 };
3657 SequencedSocketData data(reads, writes);
3658 session_deps_.socket_factory->AddSocketDataProvider(&data);
3659
3660 AddSSLSocketData();
3661
3662 CreateNetworkSession();
3663 CreateSpdySession();
3664
3665 EXPECT_EQ(initial_window_size, session_recv_window_size());
3666 EXPECT_EQ(0, session_unacked_recv_window_bytes());
3667
3668 IncreaseRecvWindowSize(delta_window_size);
3669 EXPECT_EQ(initial_window_size + delta_window_size,
3670 session_recv_window_size());
3671 EXPECT_EQ(delta_window_size, session_unacked_recv_window_bytes());
3672
3673 // Should trigger sending a WINDOW_UPDATE frame.
3674 IncreaseRecvWindowSize(initial_window_size);
3675 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3676 session_recv_window_size());
3677 EXPECT_EQ(0, session_unacked_recv_window_bytes());
3678
3679 base::RunLoop().RunUntilIdle();
3680
3681 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3682 set_in_io_loop(true);
3683 DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3684 initial_window_size);
3685 set_in_io_loop(false);
3686 EXPECT_EQ(0, session_recv_window_size());
3687 EXPECT_EQ(0, session_unacked_recv_window_bytes());
3688
3689 EXPECT_TRUE(session_);
3690 data.Resume();
3691 base::RunLoop().RunUntilIdle();
3692 EXPECT_FALSE(session_);
3693 }
3694
3695 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3696 // adjust the session receive window size. In addition,
3697 // SpdySession::IncreaseRecvWindowSize should trigger
3698 // sending a WINDOW_UPDATE frame for a small delta after
3699 // kDefaultTimeToBufferSmallWindowUpdates time has passed.
TEST_F(SpdySessionTestWithMockTime,FlowControlSlowReads)3700 TEST_F(SpdySessionTestWithMockTime, FlowControlSlowReads) {
3701 MockRead reads[] = {
3702 MockRead(SYNCHRONOUS, 0, 0) // EOF
3703 };
3704 StaticSocketDataProvider data(reads, base::span<MockWrite>());
3705 session_deps_.socket_factory->AddSocketDataProvider(&data);
3706
3707 CreateNetworkSession();
3708 session_ = CreateFakeSpdySession(spdy_session_pool_, key_);
3709
3710 // Re-enable the time-based window update buffering. The test harness
3711 // disables it by default to prevent flakiness.
3712 session_->SetTimeToBufferSmallWindowUpdates(
3713 kDefaultTimeToBufferSmallWindowUpdates);
3714
3715 const int32_t initial_window_size = kDefaultInitialWindowSize;
3716 const int32_t delta_window_size = 100;
3717
3718 EXPECT_EQ(initial_window_size, session_recv_window_size());
3719 EXPECT_EQ(0, session_unacked_recv_window_bytes());
3720
3721 // Receive data, consuming some of the receive window.
3722 set_in_io_loop(true);
3723 DecreaseRecvWindowSize(delta_window_size);
3724 set_in_io_loop(false);
3725
3726 EXPECT_EQ(initial_window_size - delta_window_size,
3727 session_recv_window_size());
3728 EXPECT_EQ(0, session_unacked_recv_window_bytes());
3729
3730 // Consume the data, returning some of the receive window (locally)
3731 IncreaseRecvWindowSize(delta_window_size);
3732 EXPECT_EQ(initial_window_size, session_recv_window_size());
3733 EXPECT_EQ(delta_window_size, session_unacked_recv_window_bytes());
3734
3735 // Receive data, consuming some of the receive window.
3736 set_in_io_loop(true);
3737 DecreaseRecvWindowSize(delta_window_size);
3738 set_in_io_loop(false);
3739
3740 // Window updates after a configured time second should force a WINDOW_UPDATE,
3741 // draining the unacked window bytes.
3742 AdvanceClock(kDefaultTimeToBufferSmallWindowUpdates);
3743 IncreaseRecvWindowSize(delta_window_size);
3744 EXPECT_EQ(initial_window_size, session_recv_window_size());
3745 EXPECT_EQ(0, session_unacked_recv_window_bytes());
3746 }
3747
3748 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3749 // adjust the session send window size when the "enable_spdy_31" flag
3750 // is set.
TEST_F(SpdySessionTest,AdjustSendWindowSize)3751 TEST_F(SpdySessionTest, AdjustSendWindowSize) {
3752 MockRead reads[] = {
3753 MockRead(SYNCHRONOUS, 0, 0) // EOF
3754 };
3755 StaticSocketDataProvider data(reads, base::span<MockWrite>());
3756 session_deps_.socket_factory->AddSocketDataProvider(&data);
3757
3758 CreateNetworkSession();
3759 session_ = CreateFakeSpdySession(spdy_session_pool_, key_);
3760
3761 const int32_t initial_window_size = kDefaultInitialWindowSize;
3762 const int32_t delta_window_size = 100;
3763
3764 EXPECT_EQ(initial_window_size, session_send_window_size());
3765
3766 IncreaseSendWindowSize(delta_window_size);
3767 EXPECT_EQ(initial_window_size + delta_window_size,
3768 session_send_window_size());
3769
3770 DecreaseSendWindowSize(delta_window_size);
3771 EXPECT_EQ(initial_window_size, session_send_window_size());
3772 }
3773
3774 // Incoming data for an inactive stream should not cause the session
3775 // receive window size to decrease, but it should cause the unacked
3776 // bytes to increase.
TEST_F(SpdySessionTest,SessionFlowControlInactiveStream)3777 TEST_F(SpdySessionTest, SessionFlowControlInactiveStream) {
3778 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyDataFrame(1, false));
3779 MockRead reads[] = {
3780 CreateMockRead(resp, 0), MockRead(ASYNC, ERR_IO_PENDING, 1),
3781 MockRead(ASYNC, 0, 2) // EOF
3782 };
3783 SequencedSocketData data(reads, base::span<MockWrite>());
3784 session_deps_.socket_factory->AddSocketDataProvider(&data);
3785
3786 AddSSLSocketData();
3787
3788 CreateNetworkSession();
3789 CreateSpdySession();
3790
3791 EXPECT_EQ(kDefaultInitialWindowSize, session_recv_window_size());
3792 EXPECT_EQ(0, session_unacked_recv_window_bytes());
3793
3794 base::RunLoop().RunUntilIdle();
3795
3796 EXPECT_EQ(kDefaultInitialWindowSize, session_recv_window_size());
3797 EXPECT_EQ(kUploadDataSize, session_unacked_recv_window_bytes());
3798
3799 EXPECT_TRUE(session_);
3800 data.Resume();
3801 base::RunLoop().RunUntilIdle();
3802 EXPECT_FALSE(session_);
3803 }
3804
3805 // The frame header is not included in flow control, but frame payload
3806 // (including optional pad length and padding) is.
TEST_F(SpdySessionTest,SessionFlowControlPadding)3807 TEST_F(SpdySessionTest, SessionFlowControlPadding) {
3808 const int padding_length = 42;
3809 spdy::SpdySerializedFrame resp(
3810 spdy_util_.ConstructSpdyDataFrame(1, kUploadData, false, padding_length));
3811 MockRead reads[] = {
3812 CreateMockRead(resp, 0), MockRead(ASYNC, ERR_IO_PENDING, 1),
3813 MockRead(ASYNC, 0, 2) // EOF
3814 };
3815 SequencedSocketData data(reads, base::span<MockWrite>());
3816 session_deps_.socket_factory->AddSocketDataProvider(&data);
3817
3818 AddSSLSocketData();
3819
3820 CreateNetworkSession();
3821 CreateSpdySession();
3822
3823 EXPECT_EQ(kDefaultInitialWindowSize, session_recv_window_size());
3824 EXPECT_EQ(0, session_unacked_recv_window_bytes());
3825
3826 base::RunLoop().RunUntilIdle();
3827
3828 EXPECT_EQ(kDefaultInitialWindowSize, session_recv_window_size());
3829 EXPECT_EQ(kUploadDataSize + padding_length,
3830 session_unacked_recv_window_bytes());
3831
3832 data.Resume();
3833 base::RunLoop().RunUntilIdle();
3834 EXPECT_FALSE(session_);
3835 }
3836
3837 // Peer sends more data than stream level receiving flow control window.
TEST_F(SpdySessionTest,StreamFlowControlTooMuchData)3838 TEST_F(SpdySessionTest, StreamFlowControlTooMuchData) {
3839 const int32_t stream_max_recv_window_size = 1024;
3840 const int32_t data_frame_size = 2 * stream_max_recv_window_size;
3841
3842 spdy::SpdySerializedFrame req(
3843 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3844 spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream(
3845 1, spdy::ERROR_CODE_FLOW_CONTROL_ERROR));
3846 MockWrite writes[] = {
3847 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
3848 };
3849
3850 spdy::SpdySerializedFrame resp(
3851 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3852 const std::string payload(data_frame_size, 'a');
3853 spdy::SpdySerializedFrame data_frame(
3854 spdy_util_.ConstructSpdyDataFrame(1, payload, false));
3855 MockRead reads[] = {
3856 CreateMockRead(resp, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
3857 CreateMockRead(data_frame, 3), MockRead(ASYNC, ERR_IO_PENDING, 5),
3858 MockRead(ASYNC, 0, 6),
3859 };
3860
3861 SequencedSocketData data(reads, writes);
3862 session_deps_.socket_factory->AddSocketDataProvider(&data);
3863
3864 AddSSLSocketData();
3865
3866 session_deps_.http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] =
3867 stream_max_recv_window_size;
3868 CreateNetworkSession();
3869
3870 CreateSpdySession();
3871
3872 base::WeakPtr<SpdyStream> spdy_stream =
3873 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
3874 test_url_, LOWEST, NetLogWithSource());
3875 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3876
3877 test::StreamDelegateDoNothing delegate(spdy_stream);
3878 spdy_stream->SetDelegate(&delegate);
3879
3880 spdy::Http2HeaderBlock headers(
3881 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
3882 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3883 std::move(headers), NO_MORE_DATA_TO_SEND));
3884
3885 // Request and response.
3886 base::RunLoop().RunUntilIdle();
3887 EXPECT_EQ(1u, spdy_stream->stream_id());
3888
3889 // Too large data frame causes flow control error, should close stream.
3890 data.Resume();
3891 base::RunLoop().RunUntilIdle();
3892 EXPECT_FALSE(spdy_stream);
3893
3894 EXPECT_TRUE(session_);
3895 data.Resume();
3896 base::RunLoop().RunUntilIdle();
3897 EXPECT_FALSE(session_);
3898 }
3899
3900 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3901 // deltas in the receiving window size when checking incoming frames for flow
3902 // control errors at session level.
TEST_F(SpdySessionTest,SessionFlowControlTooMuchDataTwoDataFrames)3903 TEST_F(SpdySessionTest, SessionFlowControlTooMuchDataTwoDataFrames) {
3904 const int32_t session_max_recv_window_size = 500;
3905 const int32_t first_data_frame_size = 200;
3906 const int32_t second_data_frame_size = 400;
3907
3908 // First data frame should not trigger a WINDOW_UPDATE.
3909 ASSERT_GT(session_max_recv_window_size / 2, first_data_frame_size);
3910 // Second data frame would be fine had there been a WINDOW_UPDATE.
3911 ASSERT_GT(session_max_recv_window_size, second_data_frame_size);
3912 // But in fact, the two data frames together overflow the receiving window at
3913 // session level.
3914 ASSERT_LT(session_max_recv_window_size,
3915 first_data_frame_size + second_data_frame_size);
3916
3917 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
3918 0, spdy::ERROR_CODE_FLOW_CONTROL_ERROR,
3919 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3920 "than the receive window size of 300"));
3921 MockWrite writes[] = {
3922 CreateMockWrite(goaway, 4),
3923 };
3924
3925 const std::string first_data_frame(first_data_frame_size, 'a');
3926 spdy::SpdySerializedFrame first(
3927 spdy_util_.ConstructSpdyDataFrame(1, first_data_frame, false));
3928 const std::string second_data_frame(second_data_frame_size, 'b');
3929 spdy::SpdySerializedFrame second(
3930 spdy_util_.ConstructSpdyDataFrame(1, second_data_frame, false));
3931 MockRead reads[] = {
3932 CreateMockRead(first, 0), MockRead(ASYNC, ERR_IO_PENDING, 1),
3933 CreateMockRead(second, 2), MockRead(ASYNC, 0, 3),
3934 };
3935 SequencedSocketData data(reads, writes);
3936 session_deps_.socket_factory->AddSocketDataProvider(&data);
3937
3938 AddSSLSocketData();
3939
3940 CreateNetworkSession();
3941 CreateSpdySession();
3942 // Setting session level receiving window size to smaller than initial is not
3943 // possible via SpdySessionPoolPeer.
3944 set_session_recv_window_size(session_max_recv_window_size);
3945
3946 // First data frame is immediately consumed and does not trigger
3947 // WINDOW_UPDATE.
3948 base::RunLoop().RunUntilIdle();
3949 EXPECT_EQ(first_data_frame_size, session_unacked_recv_window_bytes());
3950 EXPECT_EQ(session_max_recv_window_size, session_recv_window_size());
3951 EXPECT_TRUE(session_->IsAvailable());
3952
3953 // Second data frame overflows receiving window, causes session to close.
3954 data.Resume();
3955 base::RunLoop().RunUntilIdle();
3956 EXPECT_TRUE(session_->IsDraining());
3957 }
3958
3959 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3960 // deltas in the receiving window size when checking incoming data frames for
3961 // flow control errors at stream level.
TEST_F(SpdySessionTest,StreamFlowControlTooMuchDataTwoDataFrames)3962 TEST_F(SpdySessionTest, StreamFlowControlTooMuchDataTwoDataFrames) {
3963 const int32_t stream_max_recv_window_size = 500;
3964 const int32_t first_data_frame_size = 200;
3965 const int32_t second_data_frame_size = 400;
3966
3967 // First data frame should not trigger a WINDOW_UPDATE.
3968 ASSERT_GT(stream_max_recv_window_size / 2, first_data_frame_size);
3969 // Second data frame would be fine had there been a WINDOW_UPDATE.
3970 ASSERT_GT(stream_max_recv_window_size, second_data_frame_size);
3971 // But in fact, they should overflow the receiving window at stream level.
3972 ASSERT_LT(stream_max_recv_window_size,
3973 first_data_frame_size + second_data_frame_size);
3974
3975 spdy::SpdySerializedFrame req(
3976 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3977 spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream(
3978 1, spdy::ERROR_CODE_FLOW_CONTROL_ERROR));
3979 MockWrite writes[] = {
3980 CreateMockWrite(req, 0), CreateMockWrite(rst, 6),
3981 };
3982
3983 spdy::SpdySerializedFrame resp(
3984 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3985 const std::string first_data_frame(first_data_frame_size, 'a');
3986 spdy::SpdySerializedFrame first(
3987 spdy_util_.ConstructSpdyDataFrame(1, first_data_frame, false));
3988 const std::string second_data_frame(second_data_frame_size, 'b');
3989 spdy::SpdySerializedFrame second(
3990 spdy_util_.ConstructSpdyDataFrame(1, second_data_frame, false));
3991 MockRead reads[] = {
3992 CreateMockRead(resp, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
3993 CreateMockRead(first, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
3994 CreateMockRead(second, 5), MockRead(ASYNC, ERR_IO_PENDING, 7),
3995 MockRead(ASYNC, 0, 8),
3996 };
3997
3998 SequencedSocketData data(reads, writes);
3999 session_deps_.socket_factory->AddSocketDataProvider(&data);
4000
4001 AddSSLSocketData();
4002
4003 session_deps_.http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] =
4004 stream_max_recv_window_size;
4005 CreateNetworkSession();
4006
4007 CreateSpdySession();
4008
4009 base::WeakPtr<SpdyStream> spdy_stream =
4010 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
4011 test_url_, LOWEST, NetLogWithSource());
4012 test::StreamDelegateDoNothing delegate(spdy_stream);
4013 spdy_stream->SetDelegate(&delegate);
4014
4015 spdy::Http2HeaderBlock headers(
4016 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
4017 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
4018 std::move(headers), NO_MORE_DATA_TO_SEND));
4019
4020 // Request and response.
4021 base::RunLoop().RunUntilIdle();
4022 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
4023 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
4024
4025 // First data frame.
4026 data.Resume();
4027 base::RunLoop().RunUntilIdle();
4028 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
4029 EXPECT_EQ(stream_max_recv_window_size - first_data_frame_size,
4030 spdy_stream->recv_window_size());
4031
4032 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
4033 std::string received_data = delegate.TakeReceivedData();
4034 EXPECT_EQ(static_cast<size_t>(first_data_frame_size), received_data.size());
4035 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
4036
4037 // Second data frame overflows receiving window, causes the stream to close.
4038 data.Resume();
4039 base::RunLoop().RunUntilIdle();
4040 EXPECT_FALSE(spdy_stream.get());
4041
4042 // RST_STREAM
4043 EXPECT_TRUE(session_);
4044 data.Resume();
4045 base::RunLoop().RunUntilIdle();
4046 EXPECT_FALSE(session_);
4047 }
4048
4049 // A delegate that drops any received data.
4050 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
4051 public:
DropReceivedDataDelegate(const base::WeakPtr<SpdyStream> & stream,base::StringPiece data)4052 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
4053 base::StringPiece data)
4054 : StreamDelegateSendImmediate(stream, data) {}
4055
4056 ~DropReceivedDataDelegate() override = default;
4057
4058 // Drop any received data.
OnDataReceived(std::unique_ptr<SpdyBuffer> buffer)4059 void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) override {}
4060 };
4061
4062 // Send data back and forth but use a delegate that drops its received
4063 // data. The receive window should still increase to its original
4064 // value, i.e. we shouldn't "leak" receive window bytes.
TEST_F(SpdySessionTest,SessionFlowControlNoReceiveLeaks)4065 TEST_F(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
4066 const int32_t kMsgDataSize = 100;
4067 const std::string msg_data(kMsgDataSize, 'a');
4068
4069 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
4070 kDefaultUrl, 1, kMsgDataSize, MEDIUM, nullptr, 0));
4071 spdy::SpdySerializedFrame msg(
4072 spdy_util_.ConstructSpdyDataFrame(1, msg_data, false));
4073 MockWrite writes[] = {
4074 CreateMockWrite(req, 0), CreateMockWrite(msg, 2),
4075 };
4076
4077 spdy::SpdySerializedFrame resp(
4078 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4079 spdy::SpdySerializedFrame echo(
4080 spdy_util_.ConstructSpdyDataFrame(1, msg_data, false));
4081 spdy::SpdySerializedFrame window_update(spdy_util_.ConstructSpdyWindowUpdate(
4082 spdy::kSessionFlowControlStreamId, kMsgDataSize));
4083 MockRead reads[] = {
4084 CreateMockRead(resp, 1), CreateMockRead(echo, 3),
4085 MockRead(ASYNC, ERR_IO_PENDING, 4), MockRead(ASYNC, 0, 5) // EOF
4086 };
4087
4088 // Create SpdySession and SpdyStream and send the request.
4089 SequencedSocketData data(reads, writes);
4090 session_deps_.socket_factory->AddSocketDataProvider(&data);
4091
4092 AddSSLSocketData();
4093
4094 CreateNetworkSession();
4095 CreateSpdySession();
4096
4097 base::WeakPtr<SpdyStream> stream =
4098 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
4099 MEDIUM, NetLogWithSource());
4100 ASSERT_TRUE(stream);
4101 EXPECT_EQ(0u, stream->stream_id());
4102
4103 DropReceivedDataDelegate delegate(stream, msg_data);
4104 stream->SetDelegate(&delegate);
4105
4106 spdy::Http2HeaderBlock headers(
4107 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kMsgDataSize));
4108 EXPECT_EQ(ERR_IO_PENDING,
4109 stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
4110
4111 const int32_t initial_window_size = kDefaultInitialWindowSize;
4112 EXPECT_EQ(initial_window_size, session_recv_window_size());
4113 EXPECT_EQ(0, session_unacked_recv_window_bytes());
4114
4115 base::RunLoop().RunUntilIdle();
4116
4117 EXPECT_EQ(initial_window_size, session_recv_window_size());
4118 EXPECT_EQ(kMsgDataSize, session_unacked_recv_window_bytes());
4119
4120 stream->Close();
4121 EXPECT_FALSE(stream);
4122
4123 EXPECT_THAT(delegate.WaitForClose(), IsOk());
4124
4125 EXPECT_EQ(initial_window_size, session_recv_window_size());
4126 EXPECT_EQ(kMsgDataSize, session_unacked_recv_window_bytes());
4127
4128 data.Resume();
4129 base::RunLoop().RunUntilIdle();
4130 EXPECT_FALSE(session_);
4131 }
4132
4133 // Send data back and forth but close the stream before its data frame
4134 // can be written to the socket. The send window should then increase
4135 // to its original value, i.e. we shouldn't "leak" send window bytes.
TEST_F(SpdySessionTest,SessionFlowControlNoSendLeaks)4136 TEST_F(SpdySessionTest, SessionFlowControlNoSendLeaks) {
4137 const int32_t kMsgDataSize = 100;
4138 const std::string msg_data(kMsgDataSize, 'a');
4139
4140 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
4141 kDefaultUrl, 1, kMsgDataSize, MEDIUM, nullptr, 0));
4142 MockWrite writes[] = {
4143 CreateMockWrite(req, 0),
4144 };
4145
4146 spdy::SpdySerializedFrame resp(
4147 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4148 MockRead reads[] = {
4149 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
4150 MockRead(ASYNC, 0, 3) // EOF
4151 };
4152
4153 // Create SpdySession and SpdyStream and send the request.
4154 SequencedSocketData data(reads, writes);
4155 session_deps_.socket_factory->AddSocketDataProvider(&data);
4156
4157 AddSSLSocketData();
4158
4159 CreateNetworkSession();
4160 CreateSpdySession();
4161
4162 base::WeakPtr<SpdyStream> stream =
4163 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
4164 MEDIUM, NetLogWithSource());
4165 ASSERT_TRUE(stream);
4166 EXPECT_EQ(0u, stream->stream_id());
4167
4168 test::StreamDelegateSendImmediate delegate(stream, msg_data);
4169 stream->SetDelegate(&delegate);
4170
4171 spdy::Http2HeaderBlock headers(
4172 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kMsgDataSize));
4173 EXPECT_EQ(ERR_IO_PENDING,
4174 stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
4175
4176 const int32_t initial_window_size = kDefaultInitialWindowSize;
4177 EXPECT_EQ(initial_window_size, session_send_window_size());
4178
4179 // Write request.
4180 base::RunLoop().RunUntilIdle();
4181
4182 EXPECT_EQ(initial_window_size, session_send_window_size());
4183
4184 // Read response, but do not run the message loop, so that the body is not
4185 // written to the socket.
4186 data.Resume();
4187
4188 EXPECT_EQ(initial_window_size - kMsgDataSize, session_send_window_size());
4189
4190 // Closing the stream should increase the session's send window.
4191 stream->Close();
4192 EXPECT_FALSE(stream);
4193
4194 EXPECT_EQ(initial_window_size, session_send_window_size());
4195
4196 EXPECT_THAT(delegate.WaitForClose(), IsOk());
4197
4198 base::RunLoop().RunUntilIdle();
4199 EXPECT_FALSE(session_);
4200
4201 EXPECT_TRUE(data.AllWriteDataConsumed());
4202 EXPECT_TRUE(data.AllReadDataConsumed());
4203 }
4204
4205 // Send data back and forth; the send and receive windows should
4206 // change appropriately.
TEST_F(SpdySessionTest,SessionFlowControlEndToEnd)4207 TEST_F(SpdySessionTest, SessionFlowControlEndToEnd) {
4208 const int32_t kMsgDataSize = 100;
4209 const std::string msg_data(kMsgDataSize, 'a');
4210
4211 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
4212 kDefaultUrl, 1, kMsgDataSize, MEDIUM, nullptr, 0));
4213 spdy::SpdySerializedFrame msg(
4214 spdy_util_.ConstructSpdyDataFrame(1, msg_data, false));
4215 MockWrite writes[] = {
4216 CreateMockWrite(req, 0), CreateMockWrite(msg, 2),
4217 };
4218
4219 spdy::SpdySerializedFrame resp(
4220 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4221 spdy::SpdySerializedFrame echo(
4222 spdy_util_.ConstructSpdyDataFrame(1, msg_data, false));
4223 spdy::SpdySerializedFrame window_update(spdy_util_.ConstructSpdyWindowUpdate(
4224 spdy::kSessionFlowControlStreamId, kMsgDataSize));
4225 MockRead reads[] = {
4226 CreateMockRead(resp, 1),
4227 MockRead(ASYNC, ERR_IO_PENDING, 3),
4228 CreateMockRead(echo, 4),
4229 MockRead(ASYNC, ERR_IO_PENDING, 5),
4230 CreateMockRead(window_update, 6),
4231 MockRead(ASYNC, ERR_IO_PENDING, 7),
4232 MockRead(ASYNC, 0, 8) // EOF
4233 };
4234
4235 // Create SpdySession and SpdyStream and send the request.
4236 SequencedSocketData data(reads, writes);
4237 session_deps_.socket_factory->AddSocketDataProvider(&data);
4238
4239 AddSSLSocketData();
4240
4241 CreateNetworkSession();
4242 CreateSpdySession();
4243
4244 base::WeakPtr<SpdyStream> stream =
4245 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
4246 MEDIUM, NetLogWithSource());
4247 ASSERT_TRUE(stream);
4248 EXPECT_EQ(0u, stream->stream_id());
4249
4250 test::StreamDelegateSendImmediate delegate(stream, msg_data);
4251 stream->SetDelegate(&delegate);
4252
4253 spdy::Http2HeaderBlock headers(
4254 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kMsgDataSize));
4255 EXPECT_EQ(ERR_IO_PENDING,
4256 stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
4257
4258 const int32_t initial_window_size = kDefaultInitialWindowSize;
4259 EXPECT_EQ(initial_window_size, session_send_window_size());
4260 EXPECT_EQ(initial_window_size, session_recv_window_size());
4261 EXPECT_EQ(0, session_unacked_recv_window_bytes());
4262
4263 // Send request and message.
4264 base::RunLoop().RunUntilIdle();
4265
4266 EXPECT_EQ(initial_window_size - kMsgDataSize, session_send_window_size());
4267 EXPECT_EQ(initial_window_size, session_recv_window_size());
4268 EXPECT_EQ(0, session_unacked_recv_window_bytes());
4269
4270 // Read echo.
4271 data.Resume();
4272 base::RunLoop().RunUntilIdle();
4273
4274 EXPECT_EQ(initial_window_size - kMsgDataSize, session_send_window_size());
4275 EXPECT_EQ(initial_window_size - kMsgDataSize, session_recv_window_size());
4276 EXPECT_EQ(0, session_unacked_recv_window_bytes());
4277
4278 // Read window update.
4279 data.Resume();
4280 base::RunLoop().RunUntilIdle();
4281
4282 EXPECT_EQ(initial_window_size, session_send_window_size());
4283 EXPECT_EQ(initial_window_size - kMsgDataSize, session_recv_window_size());
4284 EXPECT_EQ(0, session_unacked_recv_window_bytes());
4285
4286 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
4287
4288 // Draining the delegate's read queue should increase the session's
4289 // receive window.
4290 EXPECT_EQ(initial_window_size, session_send_window_size());
4291 EXPECT_EQ(initial_window_size, session_recv_window_size());
4292 EXPECT_EQ(kMsgDataSize, session_unacked_recv_window_bytes());
4293
4294 stream->Close();
4295 EXPECT_FALSE(stream);
4296
4297 EXPECT_THAT(delegate.WaitForClose(), IsOk());
4298
4299 EXPECT_EQ(initial_window_size, session_send_window_size());
4300 EXPECT_EQ(initial_window_size, session_recv_window_size());
4301 EXPECT_EQ(kMsgDataSize, session_unacked_recv_window_bytes());
4302
4303 data.Resume();
4304 base::RunLoop().RunUntilIdle();
4305 EXPECT_FALSE(session_);
4306 }
4307
4308 // Given a stall function and an unstall function, runs a test to make
4309 // sure that a stream resumes after unstall.
RunResumeAfterUnstallTest(base::OnceCallback<void (SpdyStream *)> stall_function,base::OnceCallback<void (SpdyStream *,int32_t)> unstall_function)4310 void SpdySessionTest::RunResumeAfterUnstallTest(
4311 base::OnceCallback<void(SpdyStream*)> stall_function,
4312 base::OnceCallback<void(SpdyStream*, int32_t)> unstall_function) {
4313 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
4314 kDefaultUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4315 spdy::SpdySerializedFrame body(
4316 spdy_util_.ConstructSpdyDataFrame(1, kBodyDataStringPiece, true));
4317 MockWrite writes[] = {
4318 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
4319 };
4320
4321 spdy::SpdySerializedFrame resp(
4322 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4323 spdy::SpdySerializedFrame echo(
4324 spdy_util_.ConstructSpdyDataFrame(1, kBodyDataStringPiece, false));
4325 MockRead reads[] = {
4326 CreateMockRead(resp, 2), MockRead(ASYNC, 0, 3) // EOF
4327 };
4328
4329 SequencedSocketData data(reads, writes);
4330 session_deps_.socket_factory->AddSocketDataProvider(&data);
4331
4332 AddSSLSocketData();
4333
4334 CreateNetworkSession();
4335 CreateSpdySession();
4336
4337 base::WeakPtr<SpdyStream> stream =
4338 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
4339 test_url_, LOWEST, NetLogWithSource());
4340 ASSERT_TRUE(stream);
4341
4342 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
4343 stream->SetDelegate(&delegate);
4344
4345 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4346
4347 spdy::Http2HeaderBlock headers(
4348 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kBodyDataSize));
4349 EXPECT_EQ(ERR_IO_PENDING,
4350 stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND));
4351 EXPECT_EQ(kDefaultUrl, stream->url().spec());
4352
4353 std::move(stall_function).Run(stream.get());
4354
4355 base::RunLoop().RunUntilIdle();
4356
4357 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4358
4359 std::move(unstall_function).Run(stream.get(), kBodyDataSize);
4360
4361 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4362
4363 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
4364
4365 EXPECT_TRUE(delegate.send_headers_completed());
4366 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4367 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4368
4369 // Run SpdySession::PumpWriteLoop which destroys |session_|.
4370 base::RunLoop().RunUntilIdle();
4371
4372 EXPECT_FALSE(session_);
4373 EXPECT_TRUE(data.AllWriteDataConsumed());
4374 }
4375
4376 // Run the resume-after-unstall test with all possible stall and
4377 // unstall sequences.
4378
TEST_F(SpdySessionTest,ResumeAfterUnstallSession)4379 TEST_F(SpdySessionTest, ResumeAfterUnstallSession) {
4380 RunResumeAfterUnstallTest(base::BindOnce(&SpdySessionTest::StallSessionOnly,
4381 base::Unretained(this)),
4382 base::BindOnce(&SpdySessionTest::UnstallSessionOnly,
4383 base::Unretained(this)));
4384 }
4385
4386 // Equivalent to
4387 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
TEST_F(SpdySessionTest,ResumeAfterUnstallStream)4388 TEST_F(SpdySessionTest, ResumeAfterUnstallStream) {
4389 RunResumeAfterUnstallTest(
4390 base::BindOnce(&SpdySessionTest::StallStreamOnly, base::Unretained(this)),
4391 base::BindOnce(&SpdySessionTest::UnstallStreamOnly,
4392 base::Unretained(this)));
4393 }
4394
TEST_F(SpdySessionTest,StallSessionStreamResumeAfterUnstallSessionStream)4395 TEST_F(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4396 RunResumeAfterUnstallTest(
4397 base::BindOnce(&SpdySessionTest::StallSessionStream,
4398 base::Unretained(this)),
4399 base::BindOnce(&SpdySessionTest::UnstallSessionStream,
4400 base::Unretained(this)));
4401 }
4402
TEST_F(SpdySessionTest,StallStreamSessionResumeAfterUnstallSessionStream)4403 TEST_F(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4404 RunResumeAfterUnstallTest(
4405 base::BindOnce(&SpdySessionTest::StallStreamSession,
4406 base::Unretained(this)),
4407 base::BindOnce(&SpdySessionTest::UnstallSessionStream,
4408 base::Unretained(this)));
4409 }
4410
TEST_F(SpdySessionTest,StallStreamSessionResumeAfterUnstallStreamSession)4411 TEST_F(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4412 RunResumeAfterUnstallTest(
4413 base::BindOnce(&SpdySessionTest::StallStreamSession,
4414 base::Unretained(this)),
4415 base::BindOnce(&SpdySessionTest::UnstallStreamSession,
4416 base::Unretained(this)));
4417 }
4418
TEST_F(SpdySessionTest,StallSessionStreamResumeAfterUnstallStreamSession)4419 TEST_F(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4420 RunResumeAfterUnstallTest(
4421 base::BindOnce(&SpdySessionTest::StallSessionStream,
4422 base::Unretained(this)),
4423 base::BindOnce(&SpdySessionTest::UnstallStreamSession,
4424 base::Unretained(this)));
4425 }
4426
4427 // Cause a stall by reducing the flow control send window to 0. The
4428 // streams should resume in priority order when that window is then
4429 // increased.
TEST_F(SpdySessionTest,ResumeByPriorityAfterSendWindowSizeIncrease)4430 TEST_F(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4431 spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyPost(
4432 kDefaultUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4433 spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyPost(
4434 kDefaultUrl, 3, kBodyDataSize, MEDIUM, nullptr, 0));
4435 spdy::SpdySerializedFrame body1(
4436 spdy_util_.ConstructSpdyDataFrame(1, kBodyDataStringPiece, true));
4437 spdy::SpdySerializedFrame body2(
4438 spdy_util_.ConstructSpdyDataFrame(3, kBodyDataStringPiece, true));
4439 MockWrite writes[] = {
4440 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
4441 CreateMockWrite(body2, 2), CreateMockWrite(body1, 3),
4442 };
4443
4444 spdy::SpdySerializedFrame resp1(
4445 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4446 spdy::SpdySerializedFrame resp2(
4447 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
4448 MockRead reads[] = {
4449 CreateMockRead(resp1, 4), CreateMockRead(resp2, 5),
4450 MockRead(ASYNC, 0, 6) // EOF
4451 };
4452
4453 SequencedSocketData data(reads, writes);
4454 session_deps_.socket_factory->AddSocketDataProvider(&data);
4455
4456 AddSSLSocketData();
4457
4458 CreateNetworkSession();
4459 CreateSpdySession();
4460
4461 base::WeakPtr<SpdyStream> stream1 =
4462 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
4463 test_url_, LOWEST, NetLogWithSource());
4464 ASSERT_TRUE(stream1);
4465
4466 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4467 stream1->SetDelegate(&delegate1);
4468
4469 base::WeakPtr<SpdyStream> stream2 =
4470 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
4471 test_url_, MEDIUM, NetLogWithSource());
4472 ASSERT_TRUE(stream2);
4473
4474 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4475 stream2->SetDelegate(&delegate2);
4476
4477 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4478 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4479
4480 StallSessionSend();
4481
4482 spdy::Http2HeaderBlock headers1(
4483 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kBodyDataSize));
4484 EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequestHeaders(std::move(headers1),
4485 MORE_DATA_TO_SEND));
4486 EXPECT_EQ(kDefaultUrl, stream1->url().spec());
4487
4488 base::RunLoop().RunUntilIdle();
4489 EXPECT_EQ(1u, stream1->stream_id());
4490 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4491
4492 spdy::Http2HeaderBlock headers2(
4493 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kBodyDataSize));
4494 EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequestHeaders(std::move(headers2),
4495 MORE_DATA_TO_SEND));
4496 EXPECT_EQ(kDefaultUrl, stream2->url().spec());
4497
4498 base::RunLoop().RunUntilIdle();
4499 EXPECT_EQ(3u, stream2->stream_id());
4500 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4501
4502 // This should unstall only stream2.
4503 UnstallSessionSend(kBodyDataSize);
4504
4505 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4506 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4507
4508 base::RunLoop().RunUntilIdle();
4509
4510 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4511 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4512
4513 // This should then unstall stream1.
4514 UnstallSessionSend(kBodyDataSize);
4515
4516 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4517 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4518
4519 base::RunLoop().RunUntilIdle();
4520
4521 EXPECT_THAT(delegate1.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
4522 EXPECT_THAT(delegate2.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
4523
4524 EXPECT_TRUE(delegate1.send_headers_completed());
4525 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4526 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4527
4528 EXPECT_TRUE(delegate2.send_headers_completed());
4529 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4530 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4531
4532 EXPECT_FALSE(session_);
4533 EXPECT_TRUE(data.AllWriteDataConsumed());
4534 EXPECT_TRUE(data.AllReadDataConsumed());
4535 }
4536
4537 // An upload stream is stalled when the session gets unstalled, then the session
4538 // is stalled again when the stream gets unstalled. The stream should not fail.
4539 // Regression test for https://crbug.com/761919.
TEST_F(SpdySessionTest,ResumeSessionWithStalledStream)4540 TEST_F(SpdySessionTest, ResumeSessionWithStalledStream) {
4541 spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyPost(
4542 kDefaultUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4543 spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyPost(
4544 kDefaultUrl, 3, kBodyDataSize, LOWEST, nullptr, 0));
4545 spdy::SpdySerializedFrame body1(
4546 spdy_util_.ConstructSpdyDataFrame(3, kBodyDataStringPiece, true));
4547 spdy::SpdySerializedFrame body2(
4548 spdy_util_.ConstructSpdyDataFrame(1, kBodyDataStringPiece, true));
4549 MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
4550 CreateMockWrite(body1, 2), CreateMockWrite(body2, 3)};
4551
4552 spdy::SpdySerializedFrame resp1(
4553 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4554 spdy::SpdySerializedFrame resp2(
4555 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
4556 MockRead reads[] = {CreateMockRead(resp1, 4), CreateMockRead(resp2, 5),
4557 MockRead(ASYNC, 0, 6)};
4558
4559 SequencedSocketData data(reads, writes);
4560 session_deps_.socket_factory->AddSocketDataProvider(&data);
4561
4562 AddSSLSocketData();
4563
4564 CreateNetworkSession();
4565 CreateSpdySession();
4566
4567 base::WeakPtr<SpdyStream> stream1 =
4568 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
4569 test_url_, LOWEST, NetLogWithSource());
4570 ASSERT_TRUE(stream1);
4571
4572 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4573 stream1->SetDelegate(&delegate1);
4574
4575 base::WeakPtr<SpdyStream> stream2 =
4576 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
4577 test_url_, LOWEST, NetLogWithSource());
4578 ASSERT_TRUE(stream2);
4579
4580 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4581 stream2->SetDelegate(&delegate2);
4582
4583 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4584 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4585
4586 StallSessionSend();
4587
4588 spdy::Http2HeaderBlock headers1(
4589 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kBodyDataSize));
4590 EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequestHeaders(std::move(headers1),
4591 MORE_DATA_TO_SEND));
4592 EXPECT_EQ(kDefaultUrl, stream1->url().spec());
4593
4594 base::RunLoop().RunUntilIdle();
4595 EXPECT_EQ(1u, stream1->stream_id());
4596 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4597
4598 spdy::Http2HeaderBlock headers2(
4599 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kBodyDataSize));
4600 EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequestHeaders(std::move(headers2),
4601 MORE_DATA_TO_SEND));
4602 EXPECT_EQ(kDefaultUrl, stream2->url().spec());
4603
4604 base::RunLoop().RunUntilIdle();
4605 EXPECT_EQ(3u, stream2->stream_id());
4606 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4607
4608 StallStreamSend(stream1.get());
4609
4610 // At this point, both |session| and |stream1| are stalled
4611 // by their respective flow control mechanisms. Now unstall the session.
4612 // This calls session->ResumeSendStalledStreams(), which calls
4613 // stream1->PossiblyResumeIfSendStalled(). However, |stream1| is stalled, so
4614 // no data are sent on that stream. At this point, |stream1| should not be
4615 // removed from session_->stream_send_unstall_queue_.
4616 // Then stream2->PossiblyResumeIfSendStalled() is called,
4617 // data are sent on |stream2|, and |session_| stalls again.
4618 UnstallSessionSend(kBodyDataSize);
4619
4620 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4621 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4622
4623 // Make sure that the session is stalled. Otherwise
4624 // stream1->PossiblyResumeIfSendStalled() would resume the stream as soon as
4625 // the stream is unstalled, hiding the bug.
4626 EXPECT_TRUE(session_->IsSendStalled());
4627 UnstallStreamSend(stream1.get(), kBodyDataSize);
4628
4629 // Finally, unstall session.
4630 UnstallSessionSend(kBodyDataSize);
4631
4632 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4633 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4634
4635 base::RunLoop().RunUntilIdle();
4636
4637 EXPECT_THAT(delegate1.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
4638 EXPECT_THAT(delegate2.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
4639
4640 EXPECT_TRUE(delegate1.send_headers_completed());
4641 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4642 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4643
4644 EXPECT_TRUE(delegate2.send_headers_completed());
4645 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4646 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4647
4648 EXPECT_FALSE(session_);
4649 EXPECT_TRUE(data.AllWriteDataConsumed());
4650 EXPECT_TRUE(data.AllReadDataConsumed());
4651 }
4652
4653 class StreamBrokenConnectionDetectionCheckDelegate
4654 : public test::StreamDelegateDoNothing {
4655 public:
StreamBrokenConnectionDetectionCheckDelegate(const base::WeakPtr<SpdyStream> & stream,const base::WeakPtr<SpdySession> & session,bool expected_is_broken_connection_detection_enabled)4656 StreamBrokenConnectionDetectionCheckDelegate(
4657 const base::WeakPtr<SpdyStream>& stream,
4658 const base::WeakPtr<SpdySession>& session,
4659 bool expected_is_broken_connection_detection_enabled)
4660 : StreamDelegateDoNothing(stream),
4661 session_(session),
4662 expected_is_broken_connection_detection_enabled_(
4663 expected_is_broken_connection_detection_enabled) {}
4664
4665 ~StreamBrokenConnectionDetectionCheckDelegate() override = default;
4666
OnClose(int status)4667 void OnClose(int status) override {
4668 ASSERT_EQ(expected_is_broken_connection_detection_enabled_,
4669 session_->IsBrokenConnectionDetectionEnabled());
4670 }
4671
4672 private:
4673 const base::WeakPtr<SpdySession> session_;
4674 bool expected_is_broken_connection_detection_enabled_;
4675 };
4676
TEST_F(SpdySessionTest,BrokenConnectionDetectionEOF)4677 TEST_F(SpdySessionTest, BrokenConnectionDetectionEOF) {
4678 MockRead reads[] = {
4679 MockRead(ASYNC, 0, 0), // EOF
4680 };
4681
4682 SequencedSocketData data(reads, base::span<MockWrite>());
4683 session_deps_.socket_factory->AddSocketDataProvider(&data);
4684
4685 AddSSLSocketData();
4686
4687 CreateNetworkSession();
4688 CreateSpdySession();
4689
4690 ASSERT_FALSE(session_->IsBrokenConnectionDetectionEnabled());
4691 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
4692 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM,
4693 NetLogWithSource(), true, kHeartbeatInterval);
4694 ASSERT_TRUE(stream);
4695 ASSERT_TRUE(session_->IsBrokenConnectionDetectionEnabled());
4696 StreamBrokenConnectionDetectionCheckDelegate delegate(stream, session_,
4697 false);
4698 stream->SetDelegate(&delegate);
4699
4700 // Let the delegate run and check broken connection detection status during
4701 // OnClose().
4702 base::RunLoop().RunUntilIdle();
4703 ASSERT_FALSE(session_);
4704 }
4705
TEST_F(SpdySessionTest,BrokenConnectionDetectionCloseSession)4706 TEST_F(SpdySessionTest, BrokenConnectionDetectionCloseSession) {
4707 MockRead reads[] = {
4708 MockRead(ASYNC, 0, 0), // EOF
4709 };
4710
4711 SequencedSocketData data(reads, base::span<MockWrite>());
4712 session_deps_.socket_factory->AddSocketDataProvider(&data);
4713
4714 AddSSLSocketData();
4715
4716 CreateNetworkSession();
4717 CreateSpdySession();
4718
4719 ASSERT_FALSE(session_->IsBrokenConnectionDetectionEnabled());
4720 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
4721 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM,
4722 NetLogWithSource(), true, kHeartbeatInterval);
4723 ASSERT_TRUE(stream);
4724 ASSERT_TRUE(session_->IsBrokenConnectionDetectionEnabled());
4725 StreamBrokenConnectionDetectionCheckDelegate delegate(stream, session_,
4726 false);
4727 stream->SetDelegate(&delegate);
4728
4729 session_->CloseSessionOnError(ERR_ABORTED, "Aborting session");
4730 ASSERT_FALSE(session_->IsBrokenConnectionDetectionEnabled());
4731
4732 base::RunLoop().RunUntilIdle();
4733 ASSERT_FALSE(session_);
4734 }
4735
TEST_F(SpdySessionTest,BrokenConnectionDetectionCloseStream)4736 TEST_F(SpdySessionTest, BrokenConnectionDetectionCloseStream) {
4737 MockRead reads[] = {
4738 MockRead(ASYNC, 0, 0), // EOF
4739 };
4740
4741 SequencedSocketData data(reads, base::span<MockWrite>());
4742 session_deps_.socket_factory->AddSocketDataProvider(&data);
4743
4744 AddSSLSocketData();
4745
4746 CreateNetworkSession();
4747 CreateSpdySession();
4748
4749 ASSERT_FALSE(session_->IsBrokenConnectionDetectionEnabled());
4750 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
4751 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM,
4752 NetLogWithSource(), true, kHeartbeatInterval);
4753 ASSERT_TRUE(stream);
4754 ASSERT_TRUE(session_->IsBrokenConnectionDetectionEnabled());
4755 StreamBrokenConnectionDetectionCheckDelegate delegate(stream, session_,
4756 false);
4757 stream->SetDelegate(&delegate);
4758
4759 stream->Close();
4760 ASSERT_FALSE(session_->IsBrokenConnectionDetectionEnabled());
4761
4762 base::RunLoop().RunUntilIdle();
4763 ASSERT_FALSE(session_);
4764 }
4765
TEST_F(SpdySessionTest,BrokenConnectionDetectionCancelStream)4766 TEST_F(SpdySessionTest, BrokenConnectionDetectionCancelStream) {
4767 MockRead reads[] = {
4768 MockRead(ASYNC, 0, 0),
4769 };
4770
4771 SequencedSocketData data(reads, base::span<MockWrite>());
4772 session_deps_.socket_factory->AddSocketDataProvider(&data);
4773
4774 AddSSLSocketData();
4775
4776 CreateNetworkSession();
4777 CreateSpdySession();
4778
4779 ASSERT_FALSE(session_->IsBrokenConnectionDetectionEnabled());
4780 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
4781 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM,
4782 NetLogWithSource(), true, kHeartbeatInterval);
4783 ASSERT_TRUE(stream);
4784 ASSERT_TRUE(session_->IsBrokenConnectionDetectionEnabled());
4785 StreamBrokenConnectionDetectionCheckDelegate delegate(stream, session_,
4786 false);
4787 stream->SetDelegate(&delegate);
4788
4789 stream->Cancel(ERR_ABORTED);
4790 ASSERT_FALSE(session_->IsBrokenConnectionDetectionEnabled());
4791
4792 base::RunLoop().RunUntilIdle();
4793 ASSERT_FALSE(session_);
4794 }
4795
4796 // When multiple streams request broken connection detection, only the last one
4797 // to complete should disable the connection status check.
TEST_F(SpdySessionTest,BrokenConnectionDetectionMultipleRequests)4798 TEST_F(SpdySessionTest, BrokenConnectionDetectionMultipleRequests) {
4799 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1));
4800 MockRead reads[] = {
4801 MockRead(ASYNC, ERR_IO_PENDING, 2), CreateMockRead(goaway, 3),
4802 MockRead(ASYNC, ERR_IO_PENDING, 4), MockRead(ASYNC, 0, 5) // EOF
4803 };
4804 spdy::SpdySerializedFrame req1(
4805 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
4806 spdy::SpdySerializedFrame req2(
4807 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM));
4808 MockWrite writes[] = {
4809 CreateMockWrite(req1, 0),
4810 CreateMockWrite(req2, 1),
4811 };
4812 SequencedSocketData data(reads, writes);
4813 session_deps_.socket_factory->AddSocketDataProvider(&data);
4814
4815 AddSSLSocketData();
4816
4817 CreateNetworkSession();
4818 CreateSpdySession();
4819
4820 EXPECT_FALSE(session_->IsBrokenConnectionDetectionEnabled());
4821 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4822 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM,
4823 NetLogWithSource(), true, kHeartbeatInterval);
4824 EXPECT_TRUE(spdy_stream1);
4825 EXPECT_TRUE(session_->IsBrokenConnectionDetectionEnabled());
4826 StreamBrokenConnectionDetectionCheckDelegate delegate1(spdy_stream1, session_,
4827 false);
4828 spdy_stream1->SetDelegate(&delegate1);
4829
4830 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4831 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM,
4832 NetLogWithSource(), true, kHeartbeatInterval);
4833 EXPECT_TRUE(spdy_stream2);
4834 EXPECT_TRUE(session_->IsBrokenConnectionDetectionEnabled());
4835 StreamBrokenConnectionDetectionCheckDelegate delegate2(spdy_stream2, session_,
4836 true);
4837 spdy_stream2->SetDelegate(&delegate2);
4838
4839 spdy::Http2HeaderBlock headers(
4840 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
4841 spdy::Http2HeaderBlock headers2(headers.Clone());
4842
4843 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
4844 spdy_stream2->SendRequestHeaders(std::move(headers2), NO_MORE_DATA_TO_SEND);
4845
4846 base::RunLoop().RunUntilIdle();
4847
4848 EXPECT_TRUE(session_->IsBrokenConnectionDetectionEnabled());
4849 EXPECT_EQ(1u, spdy_stream1->stream_id());
4850 EXPECT_EQ(3u, spdy_stream2->stream_id());
4851
4852 // Read and process the GOAWAY frame.
4853 data.Resume();
4854 base::RunLoop().RunUntilIdle();
4855
4856 EXPECT_TRUE(session_->IsBrokenConnectionDetectionEnabled());
4857 EXPECT_FALSE(session_->IsStreamActive(3));
4858 EXPECT_FALSE(spdy_stream2);
4859 EXPECT_TRUE(session_->IsStreamActive(1));
4860 EXPECT_TRUE(session_->IsGoingAway());
4861
4862 // Should close the session.
4863 spdy_stream1->Close();
4864 EXPECT_FALSE(spdy_stream1);
4865
4866 EXPECT_TRUE(session_);
4867 EXPECT_FALSE(session_->IsBrokenConnectionDetectionEnabled());
4868 data.Resume();
4869 base::RunLoop().RunUntilIdle();
4870 EXPECT_FALSE(session_);
4871 }
4872
4873 // Delegate that closes a given stream after sending its body.
4874 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4875 public:
StreamClosingDelegate(const base::WeakPtr<SpdyStream> & stream,base::StringPiece data)4876 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4877 base::StringPiece data)
4878 : StreamDelegateWithBody(stream, data) {}
4879
4880 ~StreamClosingDelegate() override = default;
4881
set_stream_to_close(const base::WeakPtr<SpdyStream> & stream_to_close)4882 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4883 stream_to_close_ = stream_to_close;
4884 }
4885
OnDataSent()4886 void OnDataSent() override {
4887 test::StreamDelegateWithBody::OnDataSent();
4888 if (stream_to_close_.get()) {
4889 stream_to_close_->Close();
4890 EXPECT_FALSE(stream_to_close_);
4891 }
4892 }
4893
4894 private:
4895 base::WeakPtr<SpdyStream> stream_to_close_;
4896 };
4897
4898 // Cause a stall by reducing the flow control send window to
4899 // 0. Unstalling the session should properly handle deleted streams.
TEST_F(SpdySessionTest,SendWindowSizeIncreaseWithDeletedStreams)4900 TEST_F(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4901 spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyPost(
4902 kDefaultUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4903 spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyPost(
4904 kDefaultUrl, 3, kBodyDataSize, LOWEST, nullptr, 0));
4905 spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyPost(
4906 kDefaultUrl, 5, kBodyDataSize, LOWEST, nullptr, 0));
4907 spdy::SpdySerializedFrame body2(
4908 spdy_util_.ConstructSpdyDataFrame(3, kBodyDataStringPiece, true));
4909 MockWrite writes[] = {
4910 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
4911 CreateMockWrite(req3, 2), CreateMockWrite(body2, 3),
4912 };
4913
4914 spdy::SpdySerializedFrame resp2(
4915 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
4916 MockRead reads[] = {
4917 CreateMockRead(resp2, 4), MockRead(ASYNC, ERR_IO_PENDING, 5),
4918 MockRead(ASYNC, 0, 6) // EOF
4919 };
4920
4921 SequencedSocketData data(reads, writes);
4922 session_deps_.socket_factory->AddSocketDataProvider(&data);
4923
4924 AddSSLSocketData();
4925
4926 CreateNetworkSession();
4927 CreateSpdySession();
4928
4929 base::WeakPtr<SpdyStream> stream1 =
4930 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
4931 test_url_, LOWEST, NetLogWithSource());
4932 ASSERT_TRUE(stream1);
4933
4934 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4935 stream1->SetDelegate(&delegate1);
4936
4937 base::WeakPtr<SpdyStream> stream2 =
4938 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
4939 test_url_, LOWEST, NetLogWithSource());
4940 ASSERT_TRUE(stream2);
4941
4942 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4943 stream2->SetDelegate(&delegate2);
4944
4945 base::WeakPtr<SpdyStream> stream3 =
4946 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
4947 test_url_, LOWEST, NetLogWithSource());
4948 ASSERT_TRUE(stream3);
4949
4950 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4951 stream3->SetDelegate(&delegate3);
4952
4953 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4954 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4955 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4956
4957 StallSessionSend();
4958
4959 spdy::Http2HeaderBlock headers1(
4960 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kBodyDataSize));
4961 EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequestHeaders(std::move(headers1),
4962 MORE_DATA_TO_SEND));
4963 EXPECT_EQ(kDefaultUrl, stream1->url().spec());
4964
4965 base::RunLoop().RunUntilIdle();
4966 EXPECT_EQ(1u, stream1->stream_id());
4967 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4968
4969 spdy::Http2HeaderBlock headers2(
4970 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kBodyDataSize));
4971 EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequestHeaders(std::move(headers2),
4972 MORE_DATA_TO_SEND));
4973 EXPECT_EQ(kDefaultUrl, stream2->url().spec());
4974
4975 base::RunLoop().RunUntilIdle();
4976 EXPECT_EQ(3u, stream2->stream_id());
4977 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4978
4979 spdy::Http2HeaderBlock headers3(
4980 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kBodyDataSize));
4981 EXPECT_EQ(ERR_IO_PENDING, stream3->SendRequestHeaders(std::move(headers3),
4982 MORE_DATA_TO_SEND));
4983 EXPECT_EQ(kDefaultUrl, stream3->url().spec());
4984
4985 base::RunLoop().RunUntilIdle();
4986 EXPECT_EQ(5u, stream3->stream_id());
4987 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4988
4989 spdy::SpdyStreamId stream_id1 = stream1->stream_id();
4990 spdy::SpdyStreamId stream_id2 = stream2->stream_id();
4991 spdy::SpdyStreamId stream_id3 = stream3->stream_id();
4992
4993 // Close stream1 preemptively.
4994 session_->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4995 EXPECT_FALSE(stream1);
4996
4997 EXPECT_FALSE(session_->IsStreamActive(stream_id1));
4998 EXPECT_TRUE(session_->IsStreamActive(stream_id2));
4999 EXPECT_TRUE(session_->IsStreamActive(stream_id3));
5000
5001 // Unstall stream2, which should then close stream3.
5002 delegate2.set_stream_to_close(stream3);
5003 UnstallSessionSend(kBodyDataSize);
5004
5005 base::RunLoop().RunUntilIdle();
5006 EXPECT_FALSE(stream3);
5007
5008 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
5009 EXPECT_FALSE(session_->IsStreamActive(stream_id1));
5010 EXPECT_TRUE(session_->IsStreamActive(stream_id2));
5011 EXPECT_FALSE(session_->IsStreamActive(stream_id3));
5012
5013 data.Resume();
5014 base::RunLoop().RunUntilIdle();
5015 EXPECT_FALSE(stream2);
5016 EXPECT_FALSE(session_);
5017
5018 EXPECT_THAT(delegate1.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
5019 EXPECT_THAT(delegate2.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
5020 EXPECT_THAT(delegate3.WaitForClose(), IsOk());
5021
5022 EXPECT_TRUE(delegate1.send_headers_completed());
5023 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
5024
5025 EXPECT_TRUE(delegate2.send_headers_completed());
5026 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
5027 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
5028
5029 EXPECT_TRUE(delegate3.send_headers_completed());
5030 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
5031
5032 EXPECT_TRUE(data.AllWriteDataConsumed());
5033 }
5034
5035 // Cause a stall by reducing the flow control send window to
5036 // 0. Unstalling the session should properly handle the session itself
5037 // being closed.
TEST_F(SpdySessionTest,SendWindowSizeIncreaseWithDeletedSession)5038 TEST_F(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
5039 spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyPost(
5040 kDefaultUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
5041 spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyPost(
5042 kDefaultUrl, 3, kBodyDataSize, LOWEST, nullptr, 0));
5043 spdy::SpdySerializedFrame body1(
5044 spdy_util_.ConstructSpdyDataFrame(1, kBodyDataStringPiece, false));
5045 MockWrite writes[] = {
5046 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
5047 };
5048
5049 MockRead reads[] = {
5050 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
5051 };
5052
5053 SequencedSocketData data(reads, writes);
5054 session_deps_.socket_factory->AddSocketDataProvider(&data);
5055
5056 AddSSLSocketData();
5057
5058 CreateNetworkSession();
5059 CreateSpdySession();
5060
5061 base::WeakPtr<SpdyStream> stream1 =
5062 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
5063 test_url_, LOWEST, NetLogWithSource());
5064 ASSERT_TRUE(stream1);
5065
5066 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
5067 stream1->SetDelegate(&delegate1);
5068
5069 base::WeakPtr<SpdyStream> stream2 =
5070 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
5071 test_url_, LOWEST, NetLogWithSource());
5072 ASSERT_TRUE(stream2);
5073
5074 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
5075 stream2->SetDelegate(&delegate2);
5076
5077 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
5078 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
5079
5080 StallSessionSend();
5081
5082 spdy::Http2HeaderBlock headers1(
5083 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kBodyDataSize));
5084 EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequestHeaders(std::move(headers1),
5085 MORE_DATA_TO_SEND));
5086 EXPECT_EQ(kDefaultUrl, stream1->url().spec());
5087
5088 base::RunLoop().RunUntilIdle();
5089 EXPECT_EQ(1u, stream1->stream_id());
5090 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
5091
5092 spdy::Http2HeaderBlock headers2(
5093 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kBodyDataSize));
5094 EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequestHeaders(std::move(headers2),
5095 MORE_DATA_TO_SEND));
5096 EXPECT_EQ(kDefaultUrl, stream2->url().spec());
5097
5098 base::RunLoop().RunUntilIdle();
5099 EXPECT_EQ(3u, stream2->stream_id());
5100 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
5101
5102 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
5103
5104 // Unstall stream1.
5105 UnstallSessionSend(kBodyDataSize);
5106
5107 // Close the session (since we can't do it from within the delegate
5108 // method, since it's in the stream's loop).
5109 session_->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
5110 data.Resume();
5111 base::RunLoop().RunUntilIdle();
5112 EXPECT_FALSE(session_);
5113
5114 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
5115
5116 EXPECT_THAT(delegate1.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
5117 EXPECT_THAT(delegate2.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
5118
5119 EXPECT_TRUE(delegate1.send_headers_completed());
5120 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
5121
5122 EXPECT_TRUE(delegate2.send_headers_completed());
5123 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
5124
5125 EXPECT_TRUE(data.AllWriteDataConsumed());
5126 }
5127
TEST_F(SpdySessionTest,GoAwayOnSessionFlowControlError)5128 TEST_F(SpdySessionTest, GoAwayOnSessionFlowControlError) {
5129 spdy::SpdySerializedFrame req(
5130 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5131 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
5132 0, spdy::ERROR_CODE_FLOW_CONTROL_ERROR,
5133 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
5134 "the receive window size of 1"));
5135 MockWrite writes[] = {
5136 CreateMockWrite(req, 0), CreateMockWrite(goaway, 4),
5137 };
5138
5139 spdy::SpdySerializedFrame resp(
5140 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5141 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
5142 MockRead reads[] = {
5143 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
5144 CreateMockRead(body, 3),
5145 };
5146
5147 SequencedSocketData data(reads, writes);
5148 session_deps_.socket_factory->AddSocketDataProvider(&data);
5149
5150 AddSSLSocketData();
5151
5152 CreateNetworkSession();
5153 CreateSpdySession();
5154
5155 base::WeakPtr<SpdyStream> spdy_stream =
5156 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
5157 test_url_, LOWEST, NetLogWithSource());
5158 ASSERT_TRUE(spdy_stream);
5159 test::StreamDelegateDoNothing delegate(spdy_stream);
5160 spdy_stream->SetDelegate(&delegate);
5161
5162 spdy::Http2HeaderBlock headers(
5163 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
5164 spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
5165
5166 // Write request.
5167 base::RunLoop().RunUntilIdle();
5168
5169 // Put session on the edge of overflowing it's recv window.
5170 set_session_recv_window_size(1);
5171
5172 // Read response headers & body. Body overflows the session window, and a
5173 // goaway is written.
5174 data.Resume();
5175 base::RunLoop().RunUntilIdle();
5176
5177 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_FLOW_CONTROL_ERROR));
5178 EXPECT_FALSE(session_);
5179 }
5180
TEST_F(SpdySessionTest,RejectInvalidUnknownFrames)5181 TEST_F(SpdySessionTest, RejectInvalidUnknownFrames) {
5182 MockRead reads[] = {
5183 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
5184 };
5185
5186 StaticSocketDataProvider data(reads, base::span<MockWrite>());
5187 session_deps_.socket_factory->AddSocketDataProvider(&data);
5188
5189 AddSSLSocketData();
5190
5191 CreateNetworkSession();
5192 CreateSpdySession();
5193
5194 set_stream_hi_water_mark(5);
5195 // Low client (odd) ids are fine.
5196 EXPECT_TRUE(OnUnknownFrame(3, 0));
5197 // Client id exceeding watermark.
5198 EXPECT_FALSE(OnUnknownFrame(9, 0));
5199
5200 // Frames on push streams are rejected.
5201 EXPECT_FALSE(OnUnknownFrame(2, 0));
5202 }
5203
TEST_F(SpdySessionTest,EnableWebSocket)5204 TEST_F(SpdySessionTest, EnableWebSocket) {
5205 spdy::SettingsMap settings_map;
5206 settings_map[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
5207 spdy::SpdySerializedFrame settings(
5208 spdy_util_.ConstructSpdySettings(settings_map));
5209 MockRead reads[] = {CreateMockRead(settings, 0),
5210 MockRead(ASYNC, ERR_IO_PENDING, 2),
5211 MockRead(ASYNC, 0, 3)};
5212
5213 spdy::SpdySerializedFrame ack(spdy_util_.ConstructSpdySettingsAck());
5214 MockWrite writes[] = {CreateMockWrite(ack, 1)};
5215
5216 SequencedSocketData data(reads, writes);
5217 session_deps_.socket_factory->AddSocketDataProvider(&data);
5218
5219 AddSSLSocketData();
5220
5221 CreateNetworkSession();
5222 CreateSpdySession();
5223
5224 EXPECT_FALSE(session_->support_websocket());
5225
5226 // Read SETTINGS frame.
5227 base::RunLoop().RunUntilIdle();
5228
5229 EXPECT_TRUE(session_->support_websocket());
5230
5231 // Read EOF.
5232 data.Resume();
5233 base::RunLoop().RunUntilIdle();
5234
5235 EXPECT_TRUE(data.AllWriteDataConsumed());
5236 EXPECT_TRUE(data.AllReadDataConsumed());
5237 EXPECT_FALSE(session_);
5238 }
5239
TEST_F(SpdySessionTest,DisableWebSocketDoesNothing)5240 TEST_F(SpdySessionTest, DisableWebSocketDoesNothing) {
5241 spdy::SettingsMap settings_map;
5242 settings_map[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 0;
5243 spdy::SpdySerializedFrame settings(
5244 spdy_util_.ConstructSpdySettings(settings_map));
5245 MockRead reads[] = {CreateMockRead(settings, 0),
5246 MockRead(ASYNC, ERR_IO_PENDING, 2),
5247 MockRead(ASYNC, 0, 3)};
5248
5249 spdy::SpdySerializedFrame ack(spdy_util_.ConstructSpdySettingsAck());
5250 MockWrite writes[] = {CreateMockWrite(ack, 1)};
5251
5252 SequencedSocketData data(reads, writes);
5253 session_deps_.socket_factory->AddSocketDataProvider(&data);
5254
5255 AddSSLSocketData();
5256
5257 CreateNetworkSession();
5258 CreateSpdySession();
5259
5260 EXPECT_FALSE(session_->support_websocket());
5261
5262 // Read SETTINGS frame.
5263 base::RunLoop().RunUntilIdle();
5264
5265 EXPECT_FALSE(session_->support_websocket());
5266
5267 // Read EOF.
5268 data.Resume();
5269 base::RunLoop().RunUntilIdle();
5270
5271 EXPECT_TRUE(data.AllWriteDataConsumed());
5272 EXPECT_TRUE(data.AllReadDataConsumed());
5273 EXPECT_FALSE(session_);
5274 }
5275
TEST_F(SpdySessionTest,EnableWebSocketThenDisableIsProtocolError)5276 TEST_F(SpdySessionTest, EnableWebSocketThenDisableIsProtocolError) {
5277 spdy::SettingsMap settings_map1;
5278 settings_map1[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
5279 spdy::SpdySerializedFrame settings1(
5280 spdy_util_.ConstructSpdySettings(settings_map1));
5281 spdy::SettingsMap settings_map2;
5282 settings_map2[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 0;
5283 spdy::SpdySerializedFrame settings2(
5284 spdy_util_.ConstructSpdySettings(settings_map2));
5285 MockRead reads[] = {CreateMockRead(settings1, 0),
5286 MockRead(ASYNC, ERR_IO_PENDING, 2),
5287 CreateMockRead(settings2, 3)};
5288
5289 spdy::SpdySerializedFrame ack1(spdy_util_.ConstructSpdySettingsAck());
5290 spdy::SpdySerializedFrame ack2(spdy_util_.ConstructSpdySettingsAck());
5291 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
5292 0, spdy::ERROR_CODE_PROTOCOL_ERROR,
5293 "Invalid value for spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL."));
5294 MockWrite writes[] = {CreateMockWrite(ack1, 1), CreateMockWrite(ack2, 4),
5295 CreateMockWrite(goaway, 5)};
5296
5297 SequencedSocketData data(reads, writes);
5298 session_deps_.socket_factory->AddSocketDataProvider(&data);
5299
5300 AddSSLSocketData();
5301
5302 CreateNetworkSession();
5303 CreateSpdySession();
5304
5305 EXPECT_FALSE(session_->support_websocket());
5306
5307 // Read first SETTINGS frame.
5308 base::RunLoop().RunUntilIdle();
5309
5310 EXPECT_TRUE(session_->support_websocket());
5311
5312 // Read second SETTINGS frame.
5313 data.Resume();
5314 base::RunLoop().RunUntilIdle();
5315
5316 EXPECT_TRUE(data.AllWriteDataConsumed());
5317 EXPECT_TRUE(data.AllReadDataConsumed());
5318 EXPECT_FALSE(session_);
5319 }
5320
TEST_F(SpdySessionTest,GreaseFrameTypeAfterSettings)5321 TEST_F(SpdySessionTest, GreaseFrameTypeAfterSettings) {
5322 const uint8_t type = 0x0b;
5323 const uint8_t flags = 0xcc;
5324 const std::string payload("foo");
5325 session_deps_.greased_http2_frame =
5326 absl::optional<net::SpdySessionPool::GreasedHttp2Frame>(
5327 {type, flags, payload});
5328
5329 // Connection preface.
5330 spdy::SpdySerializedFrame preface(
5331 const_cast<char*>(spdy::kHttp2ConnectionHeaderPrefix),
5332 spdy::kHttp2ConnectionHeaderPrefixSize,
5333 /* owns_buffer = */ false);
5334
5335 // Initial SETTINGS frame.
5336 spdy::SettingsMap expected_settings;
5337 expected_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
5338 expected_settings[spdy::SETTINGS_MAX_HEADER_LIST_SIZE] =
5339 kSpdyMaxHeaderListSize;
5340 expected_settings[spdy::SETTINGS_ENABLE_PUSH] = 0;
5341 spdy::SpdySerializedFrame settings_frame(
5342 spdy_util_.ConstructSpdySettings(expected_settings));
5343
5344 spdy::SpdySerializedFrame combined_frame =
5345 CombineFrames({&preface, &settings_frame});
5346
5347 // Greased frame sent on stream 0 after initial SETTINGS frame.
5348 uint8_t kRawFrameData[] = {
5349 0x00, 0x00, 0x03, // length
5350 0x0b, // type
5351 0xcc, // flags
5352 0x00, 0x00, 0x00, 0x00, // stream ID
5353 'f', 'o', 'o' // payload
5354 };
5355 spdy::SpdySerializedFrame grease(reinterpret_cast<char*>(kRawFrameData),
5356 std::size(kRawFrameData),
5357 /* owns_buffer = */ false);
5358
5359 MockWrite writes[] = {CreateMockWrite(combined_frame, 0),
5360 CreateMockWrite(grease, 1)};
5361
5362 MockRead reads[] = {MockRead(ASYNC, 0, 2)};
5363
5364 SequencedSocketData data(reads, writes);
5365 session_deps_.socket_factory->AddSocketDataProvider(&data);
5366 AddSSLSocketData();
5367 CreateNetworkSession();
5368
5369 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
5370 pool_peer.SetEnableSendingInitialData(true);
5371
5372 CreateSpdySession();
5373 base::RunLoop().RunUntilIdle();
5374
5375 EXPECT_TRUE(data.AllWriteDataConsumed());
5376 EXPECT_TRUE(data.AllReadDataConsumed());
5377 }
5378
5379 enum ReadIfReadySupport {
5380 // ReadIfReady() is implemented by the underlying transport.
5381 READ_IF_READY_SUPPORTED,
5382 // ReadIfReady() is unimplemented by the underlying transport.
5383 READ_IF_READY_NOT_SUPPORTED,
5384 };
5385
5386 class SpdySessionReadIfReadyTest
5387 : public SpdySessionTest,
5388 public testing::WithParamInterface<ReadIfReadySupport> {
5389 public:
SetUp()5390 void SetUp() override {
5391 if (GetParam() == READ_IF_READY_SUPPORTED) {
5392 session_deps_.socket_factory->set_enable_read_if_ready(true);
5393 }
5394 SpdySessionTest::SetUp();
5395 }
5396 };
5397
5398 INSTANTIATE_TEST_SUITE_P(All,
5399 SpdySessionReadIfReadyTest,
5400 testing::Values(READ_IF_READY_SUPPORTED,
5401 READ_IF_READY_NOT_SUPPORTED));
5402
5403 // Tests basic functionality of ReadIfReady() when it is enabled or disabled.
TEST_P(SpdySessionReadIfReadyTest,ReadIfReady)5404 TEST_P(SpdySessionReadIfReadyTest, ReadIfReady) {
5405 spdy::SpdySerializedFrame req(
5406 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
5407 MockWrite writes[] = {
5408 CreateMockWrite(req, 0),
5409 };
5410
5411 spdy::SpdySerializedFrame resp(
5412 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5413 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
5414 MockRead reads[] = {
5415 CreateMockRead(resp, 1), CreateMockRead(body, 2),
5416 MockRead(ASYNC, 0, 3) // EOF
5417 };
5418
5419 SequencedSocketData data(reads, writes);
5420 session_deps_.socket_factory->AddSocketDataProvider(&data);
5421
5422 AddSSLSocketData();
5423
5424 CreateNetworkSession();
5425 CreateSpdySession();
5426
5427 base::WeakPtr<SpdyStream> spdy_stream =
5428 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
5429 test_url_, HIGHEST, NetLogWithSource());
5430 ASSERT_TRUE(spdy_stream);
5431 EXPECT_EQ(0u, spdy_stream->stream_id());
5432 test::StreamDelegateDoNothing delegate(spdy_stream);
5433 spdy_stream->SetDelegate(&delegate);
5434
5435 spdy::Http2HeaderBlock headers(
5436 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
5437 spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
5438
5439 base::RunLoop().RunUntilIdle();
5440
5441 EXPECT_FALSE(spdy_stream);
5442 EXPECT_EQ(1u, delegate.stream_id());
5443 }
5444
5445 class SendInitialSettingsOnNewSpdySessionTest : public SpdySessionTest {
5446 protected:
RunInitialSettingsTest(const spdy::SettingsMap expected_settings)5447 void RunInitialSettingsTest(const spdy::SettingsMap expected_settings) {
5448 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
5449
5450 spdy::SpdySerializedFrame preface(
5451 const_cast<char*>(spdy::kHttp2ConnectionHeaderPrefix),
5452 spdy::kHttp2ConnectionHeaderPrefixSize,
5453 /* owns_buffer = */ false);
5454 spdy::SpdySerializedFrame settings_frame(
5455 spdy_util_.ConstructSpdySettings(expected_settings));
5456
5457 spdy::SpdySerializedFrame combined_frame =
5458 CombineFrames({&preface, &settings_frame});
5459 MockWrite writes[] = {CreateMockWrite(combined_frame, 0)};
5460
5461 StaticSocketDataProvider data(reads, writes);
5462 session_deps_.socket_factory->AddSocketDataProvider(&data);
5463 AddSSLSocketData();
5464
5465 CreateNetworkSession();
5466
5467 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
5468 pool_peer.SetEnableSendingInitialData(true);
5469
5470 CreateSpdySession();
5471
5472 base::RunLoop().RunUntilIdle();
5473 EXPECT_TRUE(data.AllWriteDataConsumed());
5474 }
5475 };
5476
5477 // Setting values when Params::http2_settings is empty. Note that
5478 // spdy::SETTINGS_INITIAL_WINDOW_SIZE is sent in production, because it is set
5479 // to a non-default value, but it is not sent in tests, because the protocol
5480 // default value is used in tests.
TEST_F(SendInitialSettingsOnNewSpdySessionTest,Empty)5481 TEST_F(SendInitialSettingsOnNewSpdySessionTest, Empty) {
5482 spdy::SettingsMap expected_settings;
5483 expected_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
5484 expected_settings[spdy::SETTINGS_MAX_HEADER_LIST_SIZE] =
5485 kSpdyMaxHeaderListSize;
5486 expected_settings[spdy::SETTINGS_ENABLE_PUSH] = 0;
5487 RunInitialSettingsTest(expected_settings);
5488 }
5489
5490 // When a setting is set to the protocol default value,
5491 // no corresponding value is sent on the wire.
TEST_F(SendInitialSettingsOnNewSpdySessionTest,ProtocolDefault)5492 TEST_F(SendInitialSettingsOnNewSpdySessionTest, ProtocolDefault) {
5493 // SETTINGS_ENABLE_PUSH is always overridden with value 0.
5494 session_deps_.http2_settings[spdy::SETTINGS_ENABLE_PUSH] = 1;
5495
5496 // Explicitly set protocol default values for the following settings.
5497 session_deps_.http2_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = 4096;
5498 session_deps_.http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] =
5499 64 * 1024 - 1;
5500
5501 spdy::SettingsMap expected_settings;
5502 expected_settings[spdy::SETTINGS_MAX_HEADER_LIST_SIZE] =
5503 kSpdyMaxHeaderListSize;
5504 expected_settings[spdy::SETTINGS_ENABLE_PUSH] = 0;
5505 RunInitialSettingsTest(expected_settings);
5506 }
5507
5508 // Values set in Params::http2_settings overwrite Chromium's default values.
TEST_F(SendInitialSettingsOnNewSpdySessionTest,OverwriteValues)5509 TEST_F(SendInitialSettingsOnNewSpdySessionTest, OverwriteValues) {
5510 session_deps_.http2_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = 16 * 1024;
5511 session_deps_.http2_settings[spdy::SETTINGS_ENABLE_PUSH] = 0;
5512 session_deps_.http2_settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = 42;
5513 session_deps_.http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = 32 * 1024;
5514 session_deps_.http2_settings[spdy::SETTINGS_MAX_HEADER_LIST_SIZE] =
5515 101 * 1024;
5516
5517 spdy::SettingsMap expected_settings;
5518 expected_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = 16 * 1024;
5519 expected_settings[spdy::SETTINGS_ENABLE_PUSH] = 0;
5520 expected_settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = 42;
5521 expected_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = 32 * 1024;
5522 expected_settings[spdy::SETTINGS_MAX_HEADER_LIST_SIZE] = 101 * 1024;
5523 RunInitialSettingsTest(expected_settings);
5524 }
5525
5526 // Unknown parameters should still be sent to the server.
TEST_F(SendInitialSettingsOnNewSpdySessionTest,UnknownSettings)5527 TEST_F(SendInitialSettingsOnNewSpdySessionTest, UnknownSettings) {
5528 // The following parameters are not defined in the HTTP/2 specification.
5529 session_deps_.http2_settings[7] = 1234;
5530 session_deps_.http2_settings[25] = 5678;
5531
5532 spdy::SettingsMap expected_settings;
5533 expected_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
5534 expected_settings[spdy::SETTINGS_MAX_HEADER_LIST_SIZE] =
5535 kSpdyMaxHeaderListSize;
5536 expected_settings[spdy::SETTINGS_ENABLE_PUSH] = 0;
5537 expected_settings[7] = 1234;
5538 expected_settings[25] = 5678;
5539 RunInitialSettingsTest(expected_settings);
5540 }
5541
5542 class AltSvcFrameTest : public SpdySessionTest {
5543 public:
AltSvcFrameTest()5544 AltSvcFrameTest()
5545 : alternative_service_(
5546 quic::AlpnForVersion(DefaultSupportedQuicVersions().front()),
5547 "alternative.example.org",
5548 443,
5549 86400,
5550 spdy::SpdyAltSvcWireFormat::VersionVector()) {
5551 // Since the default |alternative_service_| is QUIC, need to enable QUIC for
5552 // the not added tests to be meaningful.
5553 session_deps_.enable_quic = true;
5554 }
5555
AddSocketData(const spdy::SpdyAltSvcIR & altsvc_ir)5556 void AddSocketData(const spdy::SpdyAltSvcIR& altsvc_ir) {
5557 altsvc_frame_ = spdy_util_.SerializeFrame(altsvc_ir);
5558 reads_.push_back(CreateMockRead(altsvc_frame_, 0));
5559 reads_.emplace_back(ASYNC, 0, 1);
5560
5561 data_ =
5562 std::make_unique<SequencedSocketData>(reads_, base::span<MockWrite>());
5563 session_deps_.socket_factory->AddSocketDataProvider(data_.get());
5564 }
5565
CreateSpdySession()5566 void CreateSpdySession() {
5567 session_ =
5568 ::net::CreateSpdySession(http_session_.get(), key_, NetLogWithSource());
5569 }
5570
5571 spdy::SpdyAltSvcWireFormat::AlternativeService alternative_service_;
5572
5573 private:
5574 spdy::SpdySerializedFrame altsvc_frame_;
5575 std::vector<MockRead> reads_;
5576 std::unique_ptr<SequencedSocketData> data_;
5577 };
5578
TEST_F(AltSvcFrameTest,ProcessAltSvcFrame)5579 TEST_F(AltSvcFrameTest, ProcessAltSvcFrame) {
5580 const char origin[] = "https://mail.example.org";
5581 spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 0);
5582 altsvc_ir.add_altsvc(alternative_service_);
5583 altsvc_ir.set_origin(origin);
5584 AddSocketData(altsvc_ir);
5585 AddSSLSocketData();
5586
5587 CreateNetworkSession();
5588 CreateSpdySession();
5589
5590 base::RunLoop().RunUntilIdle();
5591
5592 const url::SchemeHostPort session_origin("https", test_url_.host(),
5593 test_url_.EffectiveIntPort());
5594 AlternativeServiceInfoVector altsvc_info_vector =
5595 spdy_session_pool_->http_server_properties()->GetAlternativeServiceInfos(
5596 session_origin, NetworkAnonymizationKey());
5597 ASSERT_TRUE(altsvc_info_vector.empty());
5598
5599 altsvc_info_vector =
5600 spdy_session_pool_->http_server_properties()->GetAlternativeServiceInfos(
5601 url::SchemeHostPort(GURL(origin)), NetworkAnonymizationKey());
5602 ASSERT_EQ(1u, altsvc_info_vector.size());
5603 AlternativeService alternative_service(kProtoQUIC, "alternative.example.org",
5604 443u);
5605 EXPECT_EQ(alternative_service, altsvc_info_vector[0].alternative_service());
5606 }
5607
5608 // Regression test for https://crbug.com/736063.
TEST_F(AltSvcFrameTest,IgnoreQuicAltSvcWithUnsupportedVersion)5609 TEST_F(AltSvcFrameTest, IgnoreQuicAltSvcWithUnsupportedVersion) {
5610 session_deps_.enable_quic = true;
5611
5612 // Note that this test only uses the legacy Google-specific Alt-Svc format.
5613 const char origin[] = "https://mail.example.org";
5614 spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 0);
5615 spdy::SpdyAltSvcWireFormat::AlternativeService quic_alternative_service(
5616 "quic", "alternative.example.org", 443, 86400,
5617 spdy::SpdyAltSvcWireFormat::VersionVector());
5618 quic_alternative_service.version.push_back(/* invalid QUIC version */ 1);
5619 altsvc_ir.add_altsvc(quic_alternative_service);
5620 altsvc_ir.set_origin(origin);
5621 AddSocketData(altsvc_ir);
5622 AddSSLSocketData();
5623
5624 CreateNetworkSession();
5625 CreateSpdySession();
5626
5627 base::RunLoop().RunUntilIdle();
5628
5629 const url::SchemeHostPort session_origin("https", test_url_.host(),
5630 test_url_.EffectiveIntPort());
5631 AlternativeServiceInfoVector altsvc_info_vector =
5632 spdy_session_pool_->http_server_properties()->GetAlternativeServiceInfos(
5633 session_origin, NetworkAnonymizationKey());
5634 ASSERT_TRUE(altsvc_info_vector.empty());
5635
5636 altsvc_info_vector =
5637 spdy_session_pool_->http_server_properties()->GetAlternativeServiceInfos(
5638 url::SchemeHostPort(GURL(origin)), NetworkAnonymizationKey());
5639 ASSERT_EQ(0u, altsvc_info_vector.size());
5640 }
5641
TEST_F(AltSvcFrameTest,DoNotProcessAltSvcFrameForOriginNotCoveredByCert)5642 TEST_F(AltSvcFrameTest, DoNotProcessAltSvcFrameForOriginNotCoveredByCert) {
5643 session_deps_.enable_quic = true;
5644
5645 const char origin[] = "https://invalid.example.org";
5646 spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 0);
5647 altsvc_ir.add_altsvc(alternative_service_);
5648 altsvc_ir.set_origin(origin);
5649 AddSocketData(altsvc_ir);
5650 AddSSLSocketData();
5651
5652 CreateNetworkSession();
5653 CreateSpdySession();
5654
5655 base::RunLoop().RunUntilIdle();
5656
5657 const url::SchemeHostPort session_origin("https", test_url_.host(),
5658 test_url_.EffectiveIntPort());
5659 ASSERT_TRUE(spdy_session_pool_->http_server_properties()
5660 ->GetAlternativeServiceInfos(session_origin,
5661 NetworkAnonymizationKey())
5662 .empty());
5663
5664 ASSERT_TRUE(
5665 spdy_session_pool_->http_server_properties()
5666 ->GetAlternativeServiceInfos(url::SchemeHostPort(GURL(origin)),
5667 NetworkAnonymizationKey())
5668 .empty());
5669 }
5670
5671 // An ALTSVC frame on stream 0 with empty origin MUST be ignored.
5672 // (RFC 7838 Section 4)
TEST_F(AltSvcFrameTest,DoNotProcessAltSvcFrameWithEmptyOriginOnStreamZero)5673 TEST_F(AltSvcFrameTest, DoNotProcessAltSvcFrameWithEmptyOriginOnStreamZero) {
5674 spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 0);
5675 altsvc_ir.add_altsvc(alternative_service_);
5676 AddSocketData(altsvc_ir);
5677 AddSSLSocketData();
5678
5679 CreateNetworkSession();
5680 CreateSpdySession();
5681
5682 base::RunLoop().RunUntilIdle();
5683
5684 const url::SchemeHostPort session_origin("https", test_url_.host(),
5685 test_url_.EffectiveIntPort());
5686 ASSERT_TRUE(spdy_session_pool_->http_server_properties()
5687 ->GetAlternativeServiceInfos(session_origin,
5688 NetworkAnonymizationKey())
5689 .empty());
5690 }
5691
5692 // An ALTSVC frame on a stream other than stream 0 with non-empty origin MUST be
5693 // ignored. (RFC 7838 Section 4)
TEST_F(AltSvcFrameTest,DoNotProcessAltSvcFrameWithNonEmptyOriginOnNonZeroStream)5694 TEST_F(AltSvcFrameTest,
5695 DoNotProcessAltSvcFrameWithNonEmptyOriginOnNonZeroStream) {
5696 spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 1);
5697 altsvc_ir.add_altsvc(alternative_service_);
5698 altsvc_ir.set_origin("https://mail.example.org");
5699 AddSocketData(altsvc_ir);
5700 AddSSLSocketData();
5701
5702 CreateNetworkSession();
5703 CreateSpdySession();
5704
5705 base::RunLoop().RunUntilIdle();
5706
5707 const url::SchemeHostPort session_origin("https", test_url_.host(),
5708 test_url_.EffectiveIntPort());
5709 ASSERT_TRUE(spdy_session_pool_->http_server_properties()
5710 ->GetAlternativeServiceInfos(session_origin,
5711 NetworkAnonymizationKey())
5712 .empty());
5713 }
5714
TEST_F(AltSvcFrameTest,ProcessAltSvcFrameOnActiveStream)5715 TEST_F(AltSvcFrameTest, ProcessAltSvcFrameOnActiveStream) {
5716 spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 1);
5717 altsvc_ir.add_altsvc(alternative_service_);
5718
5719 spdy::SpdySerializedFrame altsvc_frame(spdy_util_.SerializeFrame(altsvc_ir));
5720 spdy::SpdySerializedFrame rst(
5721 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_REFUSED_STREAM));
5722 MockRead reads[] = {
5723 CreateMockRead(altsvc_frame, 1), CreateMockRead(rst, 2),
5724 MockRead(ASYNC, 0, 3) // EOF
5725 };
5726
5727 const char request_origin[] = "https://mail.example.org";
5728 spdy::SpdySerializedFrame req(
5729 spdy_util_.ConstructSpdyGet(request_origin, 1, MEDIUM));
5730 MockWrite writes[] = {
5731 CreateMockWrite(req, 0),
5732 };
5733 SequencedSocketData data(reads, writes);
5734 session_deps_.socket_factory->AddSocketDataProvider(&data);
5735
5736 AddSSLSocketData();
5737
5738 CreateNetworkSession();
5739 CreateSpdySession();
5740
5741 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
5742 SPDY_REQUEST_RESPONSE_STREAM, session_, GURL(request_origin), MEDIUM,
5743 NetLogWithSource());
5744 test::StreamDelegateDoNothing delegate1(spdy_stream1);
5745 spdy_stream1->SetDelegate(&delegate1);
5746
5747 spdy::Http2HeaderBlock headers(
5748 spdy_util_.ConstructGetHeaderBlock(request_origin));
5749
5750 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
5751
5752 base::RunLoop().RunUntilIdle();
5753
5754 const url::SchemeHostPort session_origin("https", test_url_.host(),
5755 test_url_.EffectiveIntPort());
5756 ASSERT_TRUE(spdy_session_pool_->http_server_properties()
5757 ->GetAlternativeServiceInfos(session_origin,
5758 NetworkAnonymizationKey())
5759 .empty());
5760
5761 AlternativeServiceInfoVector altsvc_info_vector =
5762 spdy_session_pool_->http_server_properties()->GetAlternativeServiceInfos(
5763 url::SchemeHostPort(GURL(request_origin)), NetworkAnonymizationKey());
5764 ASSERT_EQ(1u, altsvc_info_vector.size());
5765 EXPECT_EQ(kProtoQUIC, altsvc_info_vector[0].alternative_service().protocol);
5766 EXPECT_EQ("alternative.example.org",
5767 altsvc_info_vector[0].alternative_service().host);
5768 EXPECT_EQ(443u, altsvc_info_vector[0].alternative_service().port);
5769 }
5770
TEST_F(AltSvcFrameTest,ProcessAltSvcFrameOnActiveStreamWithNetworkAnonymizationKey)5771 TEST_F(AltSvcFrameTest,
5772 ProcessAltSvcFrameOnActiveStreamWithNetworkAnonymizationKey) {
5773 base::test::ScopedFeatureList feature_list;
5774 feature_list.InitWithFeatures(
5775 // enabled_features
5776 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
5777 // Need to partition connections by NetworkAnonymizationKey for
5778 // SpdySessionKeys to include NetworkAnonymizationKeys.
5779 features::kPartitionConnectionsByNetworkIsolationKey},
5780 // disabled_features
5781 {});
5782 // Since HttpServerProperties caches the feature value, have to create a new
5783 // one.
5784 session_deps_.http_server_properties =
5785 std::make_unique<HttpServerProperties>();
5786
5787 const SchemefulSite kSite1(GURL("https://foo.test/"));
5788 const auto kNetworkAnonymizationKey1 =
5789 NetworkAnonymizationKey::CreateSameSite(kSite1);
5790 const SchemefulSite kSite2(GURL("https://bar.test/"));
5791 const auto kNetworkAnonymizationKey2 =
5792 NetworkAnonymizationKey::CreateSameSite(kSite2);
5793 key_ = SpdySessionKey(HostPortPair::FromURL(test_url_), ProxyChain::Direct(),
5794 PRIVACY_MODE_DISABLED,
5795 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
5796 kNetworkAnonymizationKey1, SecureDnsPolicy::kAllow);
5797
5798 spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 1);
5799 altsvc_ir.add_altsvc(alternative_service_);
5800
5801 spdy::SpdySerializedFrame altsvc_frame(spdy_util_.SerializeFrame(altsvc_ir));
5802 spdy::SpdySerializedFrame rst(
5803 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_REFUSED_STREAM));
5804 MockRead reads[] = {
5805 CreateMockRead(altsvc_frame, 1), CreateMockRead(rst, 2),
5806 MockRead(ASYNC, 0, 3) // EOF
5807 };
5808
5809 const char request_origin[] = "https://mail.example.org";
5810 spdy::SpdySerializedFrame req(
5811 spdy_util_.ConstructSpdyGet(request_origin, 1, MEDIUM));
5812 MockWrite writes[] = {
5813 CreateMockWrite(req, 0),
5814 };
5815 SequencedSocketData data(reads, writes);
5816 session_deps_.socket_factory->AddSocketDataProvider(&data);
5817
5818 AddSSLSocketData();
5819
5820 CreateNetworkSession();
5821 CreateSpdySession();
5822
5823 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
5824 SPDY_REQUEST_RESPONSE_STREAM, session_, GURL(request_origin), MEDIUM,
5825 NetLogWithSource());
5826 test::StreamDelegateDoNothing delegate1(spdy_stream1);
5827 spdy_stream1->SetDelegate(&delegate1);
5828
5829 spdy::Http2HeaderBlock headers(
5830 spdy_util_.ConstructGetHeaderBlock(request_origin));
5831
5832 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
5833
5834 base::RunLoop().RunUntilIdle();
5835
5836 const url::SchemeHostPort session_origin("https", test_url_.host(),
5837 test_url_.EffectiveIntPort());
5838 ASSERT_TRUE(spdy_session_pool_->http_server_properties()
5839 ->GetAlternativeServiceInfos(session_origin,
5840 NetworkAnonymizationKey())
5841 .empty());
5842
5843 AlternativeServiceInfoVector altsvc_info_vector =
5844 spdy_session_pool_->http_server_properties()->GetAlternativeServiceInfos(
5845 url::SchemeHostPort(GURL(request_origin)), kNetworkAnonymizationKey1);
5846 ASSERT_EQ(1u, altsvc_info_vector.size());
5847 EXPECT_EQ(kProtoQUIC, altsvc_info_vector[0].alternative_service().protocol);
5848 EXPECT_EQ("alternative.example.org",
5849 altsvc_info_vector[0].alternative_service().host);
5850 EXPECT_EQ(443u, altsvc_info_vector[0].alternative_service().port);
5851
5852 // Make sure the alternative service information is only associated with
5853 // kNetworkAnonymizationKey1.
5854 EXPECT_TRUE(spdy_session_pool_->http_server_properties()
5855 ->GetAlternativeServiceInfos(
5856 url::SchemeHostPort(GURL(request_origin)),
5857 kNetworkAnonymizationKey2)
5858 .empty());
5859 EXPECT_TRUE(spdy_session_pool_->http_server_properties()
5860 ->GetAlternativeServiceInfos(
5861 url::SchemeHostPort(GURL(request_origin)),
5862 NetworkAnonymizationKey())
5863 .empty());
5864 }
5865
TEST_F(AltSvcFrameTest,DoNotProcessAltSvcFrameOnStreamWithInsecureOrigin)5866 TEST_F(AltSvcFrameTest, DoNotProcessAltSvcFrameOnStreamWithInsecureOrigin) {
5867 spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 1);
5868 altsvc_ir.add_altsvc(alternative_service_);
5869
5870 spdy::SpdySerializedFrame altsvc_frame(spdy_util_.SerializeFrame(altsvc_ir));
5871 spdy::SpdySerializedFrame rst(
5872 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_REFUSED_STREAM));
5873 MockRead reads[] = {
5874 CreateMockRead(altsvc_frame, 1), CreateMockRead(rst, 2),
5875 MockRead(ASYNC, 0, 3) // EOF
5876 };
5877
5878 const char request_origin[] = "http://mail.example.org";
5879 spdy::SpdySerializedFrame req(
5880 spdy_util_.ConstructSpdyGet(request_origin, 1, MEDIUM));
5881 MockWrite writes[] = {
5882 CreateMockWrite(req, 0),
5883 };
5884 SequencedSocketData data(reads, writes);
5885 session_deps_.socket_factory->AddSocketDataProvider(&data);
5886
5887 AddSSLSocketData();
5888
5889 CreateNetworkSession();
5890 CreateSpdySession();
5891
5892 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
5893 SPDY_REQUEST_RESPONSE_STREAM, session_, GURL(request_origin), MEDIUM,
5894 NetLogWithSource());
5895 test::StreamDelegateDoNothing delegate1(spdy_stream1);
5896 spdy_stream1->SetDelegate(&delegate1);
5897
5898 spdy::Http2HeaderBlock headers(
5899 spdy_util_.ConstructGetHeaderBlock(request_origin));
5900
5901 spdy_stream1->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
5902
5903 base::RunLoop().RunUntilIdle();
5904
5905 const url::SchemeHostPort session_origin("https", test_url_.host(),
5906 test_url_.EffectiveIntPort());
5907 ASSERT_TRUE(spdy_session_pool_->http_server_properties()
5908 ->GetAlternativeServiceInfos(session_origin,
5909 NetworkAnonymizationKey())
5910 .empty());
5911
5912 ASSERT_TRUE(spdy_session_pool_->http_server_properties()
5913 ->GetAlternativeServiceInfos(
5914 url::SchemeHostPort(GURL(request_origin)),
5915 NetworkAnonymizationKey())
5916 .empty());
5917 }
5918
TEST_F(AltSvcFrameTest,DoNotProcessAltSvcFrameOnNonExistentStream)5919 TEST_F(AltSvcFrameTest, DoNotProcessAltSvcFrameOnNonExistentStream) {
5920 spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 1);
5921 altsvc_ir.add_altsvc(alternative_service_);
5922 AddSocketData(altsvc_ir);
5923 AddSSLSocketData();
5924
5925 CreateNetworkSession();
5926 CreateSpdySession();
5927
5928 base::RunLoop().RunUntilIdle();
5929
5930 const url::SchemeHostPort session_origin("https", test_url_.host(),
5931 test_url_.EffectiveIntPort());
5932 ASSERT_TRUE(spdy_session_pool_->http_server_properties()
5933 ->GetAlternativeServiceInfos(session_origin,
5934 NetworkAnonymizationKey())
5935 .empty());
5936 }
5937
5938 // Regression test for https://crbug.com/810404.
TEST_F(AltSvcFrameTest,InvalidOrigin)5939 TEST_F(AltSvcFrameTest, InvalidOrigin) {
5940 // This origin parses to an invalid GURL with https scheme.
5941 const std::string origin("https:?");
5942 const GURL origin_gurl(origin);
5943 EXPECT_FALSE(origin_gurl.is_valid());
5944 EXPECT_TRUE(origin_gurl.host().empty());
5945 EXPECT_TRUE(origin_gurl.SchemeIs(url::kHttpsScheme));
5946
5947 spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 0);
5948 altsvc_ir.add_altsvc(alternative_service_);
5949 altsvc_ir.set_origin(origin);
5950 AddSocketData(altsvc_ir);
5951 AddSSLSocketData();
5952
5953 CreateNetworkSession();
5954 CreateSpdySession();
5955
5956 base::RunLoop().RunUntilIdle();
5957
5958 const url::SchemeHostPort session_origin("https", test_url_.host(),
5959 test_url_.EffectiveIntPort());
5960 AlternativeServiceInfoVector altsvc_info_vector =
5961 spdy_session_pool_->http_server_properties()->GetAlternativeServiceInfos(
5962 session_origin, NetworkAnonymizationKey());
5963 EXPECT_TRUE(altsvc_info_vector.empty());
5964 }
5965
TEST(MapFramerErrorToProtocolError,MapsValues)5966 TEST(MapFramerErrorToProtocolError, MapsValues) {
5967 CHECK_EQ(SPDY_ERROR_INVALID_CONTROL_FRAME,
5968 MapFramerErrorToProtocolError(
5969 http2::Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME));
5970 CHECK_EQ(SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
5971 MapFramerErrorToProtocolError(
5972 http2::Http2DecoderAdapter::SPDY_INVALID_DATA_FRAME_FLAGS));
5973 CHECK_EQ(SPDY_ERROR_HPACK_NAME_HUFFMAN_ERROR,
5974 MapFramerErrorToProtocolError(
5975 http2::Http2DecoderAdapter::SPDY_HPACK_NAME_HUFFMAN_ERROR));
5976 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
5977 MapFramerErrorToProtocolError(
5978 http2::Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME));
5979 }
5980
TEST(MapFramerErrorToNetError,MapsValue)5981 TEST(MapFramerErrorToNetError, MapsValue) {
5982 CHECK_EQ(ERR_HTTP2_PROTOCOL_ERROR,
5983 MapFramerErrorToNetError(
5984 http2::Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME));
5985 CHECK_EQ(ERR_HTTP2_COMPRESSION_ERROR,
5986 MapFramerErrorToNetError(
5987 http2::Http2DecoderAdapter::SPDY_DECOMPRESS_FAILURE));
5988 CHECK_EQ(ERR_HTTP2_FRAME_SIZE_ERROR,
5989 MapFramerErrorToNetError(
5990 http2::Http2DecoderAdapter::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5991 CHECK_EQ(ERR_HTTP2_FRAME_SIZE_ERROR,
5992 MapFramerErrorToNetError(
5993 http2::Http2DecoderAdapter::SPDY_OVERSIZED_PAYLOAD));
5994 }
5995
TEST(MapRstStreamStatusToProtocolError,MapsValues)5996 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5997 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5998 MapRstStreamStatusToProtocolError(spdy::ERROR_CODE_PROTOCOL_ERROR));
5999 CHECK_EQ(
6000 STATUS_CODE_FRAME_SIZE_ERROR,
6001 MapRstStreamStatusToProtocolError(spdy::ERROR_CODE_FRAME_SIZE_ERROR));
6002 CHECK_EQ(
6003 STATUS_CODE_ENHANCE_YOUR_CALM,
6004 MapRstStreamStatusToProtocolError(spdy::ERROR_CODE_ENHANCE_YOUR_CALM));
6005 CHECK_EQ(
6006 STATUS_CODE_INADEQUATE_SECURITY,
6007 MapRstStreamStatusToProtocolError(spdy::ERROR_CODE_INADEQUATE_SECURITY));
6008 CHECK_EQ(
6009 STATUS_CODE_HTTP_1_1_REQUIRED,
6010 MapRstStreamStatusToProtocolError(spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
6011 }
6012
TEST(MapNetErrorToGoAwayStatus,MapsValue)6013 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
6014 CHECK_EQ(spdy::ERROR_CODE_INADEQUATE_SECURITY,
6015 MapNetErrorToGoAwayStatus(ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY));
6016 CHECK_EQ(spdy::ERROR_CODE_FLOW_CONTROL_ERROR,
6017 MapNetErrorToGoAwayStatus(ERR_HTTP2_FLOW_CONTROL_ERROR));
6018 CHECK_EQ(spdy::ERROR_CODE_PROTOCOL_ERROR,
6019 MapNetErrorToGoAwayStatus(ERR_HTTP2_PROTOCOL_ERROR));
6020 CHECK_EQ(spdy::ERROR_CODE_COMPRESSION_ERROR,
6021 MapNetErrorToGoAwayStatus(ERR_HTTP2_COMPRESSION_ERROR));
6022 CHECK_EQ(spdy::ERROR_CODE_FRAME_SIZE_ERROR,
6023 MapNetErrorToGoAwayStatus(ERR_HTTP2_FRAME_SIZE_ERROR));
6024 CHECK_EQ(spdy::ERROR_CODE_PROTOCOL_ERROR,
6025 MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
6026 }
6027
6028 namespace {
6029
6030 class TestSSLConfigService : public SSLConfigService {
6031 public:
6032 TestSSLConfigService() = default;
6033 ~TestSSLConfigService() override = default;
6034
GetSSLContextConfig()6035 SSLContextConfig GetSSLContextConfig() override { return config_; }
6036
6037 // Returns true if |hostname| is in domains_for_pooling_. This is a simpler
6038 // implementation than the production implementation in SSLConfigServiceMojo.
CanShareConnectionWithClientCerts(const std::string & hostname) const6039 bool CanShareConnectionWithClientCerts(
6040 const std::string& hostname) const override {
6041 for (const std::string& domain : domains_for_pooling_) {
6042 if (domain == hostname) {
6043 return true;
6044 }
6045 }
6046 return false;
6047 }
6048
SetDomainsForPooling(const std::vector<std::string> & domains)6049 void SetDomainsForPooling(const std::vector<std::string>& domains) {
6050 domains_for_pooling_ = domains;
6051 }
6052
6053 private:
6054 SSLContextConfig config_;
6055 std::vector<std::string> domains_for_pooling_;
6056 };
6057
6058 } // namespace
6059
TEST(CanPoolTest,CanPool)6060 TEST(CanPoolTest, CanPool) {
6061 // Load a cert that is valid for:
6062 // www.example.org
6063 // mail.example.org
6064 // mail.example.com
6065
6066 TransportSecurityState tss;
6067 TestSSLConfigService ssl_config_service;
6068 SSLInfo ssl_info;
6069 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
6070 "spdy_pooling.pem");
6071
6072 EXPECT_TRUE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6073 "www.example.org", "www.example.org",
6074 NetworkAnonymizationKey()));
6075 EXPECT_TRUE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6076 "www.example.org", "mail.example.org",
6077 NetworkAnonymizationKey()));
6078 EXPECT_TRUE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6079 "www.example.org", "mail.example.com",
6080 NetworkAnonymizationKey()));
6081 EXPECT_FALSE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6082 "www.example.org", "mail.google.com",
6083 NetworkAnonymizationKey()));
6084 }
6085
TEST(CanPoolTest,CanNotPoolWithCertErrors)6086 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
6087 // Load a cert that is valid for:
6088 // www.example.org
6089 // mail.example.org
6090 // mail.example.com
6091
6092 TransportSecurityState tss;
6093 TestSSLConfigService ssl_config_service;
6094 SSLInfo ssl_info;
6095 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
6096 "spdy_pooling.pem");
6097 ssl_info.cert_status = CERT_STATUS_REVOKED;
6098
6099 EXPECT_FALSE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6100 "www.example.org", "mail.example.org",
6101 NetworkAnonymizationKey()));
6102 }
6103
TEST(CanPoolTest,CanNotPoolWithClientCerts)6104 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
6105 // Load a cert that is valid for:
6106 // www.example.org
6107 // mail.example.org
6108 // mail.example.com
6109
6110 TransportSecurityState tss;
6111 TestSSLConfigService ssl_config_service;
6112 SSLInfo ssl_info;
6113 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
6114 "spdy_pooling.pem");
6115 ssl_info.client_cert_sent = true;
6116
6117 EXPECT_FALSE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6118 "www.example.org", "mail.example.org",
6119 NetworkAnonymizationKey()));
6120 }
6121
TEST(CanPoolTest,CanNotPoolWithBadPins)6122 TEST(CanPoolTest, CanNotPoolWithBadPins) {
6123 base::test::ScopedFeatureList scoped_feature_list_;
6124 scoped_feature_list_.InitAndEnableFeature(
6125 net::features::kStaticKeyPinningEnforcement);
6126 TransportSecurityState tss;
6127 tss.EnableStaticPinsForTesting();
6128 tss.SetPinningListAlwaysTimelyForTesting(true);
6129 ScopedTransportSecurityStateSource scoped_security_state_source;
6130
6131 TestSSLConfigService ssl_config_service;
6132 SSLInfo ssl_info;
6133 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
6134 "spdy_pooling.pem");
6135 ssl_info.is_issued_by_known_root = true;
6136 uint8_t bad_pin = 3;
6137 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
6138
6139 EXPECT_FALSE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6140 "www.example.org", "example.test",
6141 NetworkAnonymizationKey()));
6142 }
6143
TEST(CanPoolTest,CanNotPoolWithBadCTWhenCTRequired)6144 TEST(CanPoolTest, CanNotPoolWithBadCTWhenCTRequired) {
6145 using testing::Return;
6146 using CTRequirementLevel =
6147 TransportSecurityState::RequireCTDelegate::CTRequirementLevel;
6148
6149 TestSSLConfigService ssl_config_service;
6150 SSLInfo ssl_info;
6151 ssl_info.cert =
6152 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
6153 ssl_info.is_issued_by_known_root = true;
6154 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(1));
6155 ssl_info.ct_policy_compliance =
6156 ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
6157
6158 MockRequireCTDelegate require_ct_delegate;
6159 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost("www.example.org", _, _))
6160 .WillRepeatedly(Return(CTRequirementLevel::NOT_REQUIRED));
6161 EXPECT_CALL(require_ct_delegate,
6162 IsCTRequiredForHost("mail.example.org", _, _))
6163 .WillRepeatedly(Return(CTRequirementLevel::REQUIRED));
6164
6165 TransportSecurityState tss;
6166 tss.SetRequireCTDelegate(&require_ct_delegate);
6167
6168 EXPECT_FALSE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6169 "www.example.org", "mail.example.org",
6170 NetworkAnonymizationKey()));
6171 }
6172
TEST(CanPoolTest,CanPoolWithBadCTWhenCTNotRequired)6173 TEST(CanPoolTest, CanPoolWithBadCTWhenCTNotRequired) {
6174 using testing::Return;
6175 using CTRequirementLevel =
6176 TransportSecurityState::RequireCTDelegate::CTRequirementLevel;
6177
6178 TestSSLConfigService ssl_config_service;
6179 SSLInfo ssl_info;
6180 ssl_info.cert =
6181 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
6182 ssl_info.is_issued_by_known_root = true;
6183 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(1));
6184 ssl_info.ct_policy_compliance =
6185 ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
6186
6187 MockRequireCTDelegate require_ct_delegate;
6188 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost("www.example.org", _, _))
6189 .WillRepeatedly(Return(CTRequirementLevel::NOT_REQUIRED));
6190 EXPECT_CALL(require_ct_delegate,
6191 IsCTRequiredForHost("mail.example.org", _, _))
6192 .WillRepeatedly(Return(CTRequirementLevel::NOT_REQUIRED));
6193
6194 TransportSecurityState tss;
6195 tss.SetRequireCTDelegate(&require_ct_delegate);
6196
6197 EXPECT_TRUE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6198 "www.example.org", "mail.example.org",
6199 NetworkAnonymizationKey()));
6200 }
6201
TEST(CanPoolTest,CanPoolWithGoodCTWhenCTRequired)6202 TEST(CanPoolTest, CanPoolWithGoodCTWhenCTRequired) {
6203 using testing::Return;
6204 using CTRequirementLevel =
6205 TransportSecurityState::RequireCTDelegate::CTRequirementLevel;
6206
6207 TestSSLConfigService ssl_config_service;
6208 SSLInfo ssl_info;
6209 ssl_info.cert =
6210 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
6211 ssl_info.is_issued_by_known_root = true;
6212 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(1));
6213 ssl_info.ct_policy_compliance =
6214 ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS;
6215
6216 MockRequireCTDelegate require_ct_delegate;
6217 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost("www.example.org", _, _))
6218 .WillRepeatedly(Return(CTRequirementLevel::NOT_REQUIRED));
6219 EXPECT_CALL(require_ct_delegate,
6220 IsCTRequiredForHost("mail.example.org", _, _))
6221 .WillRepeatedly(Return(CTRequirementLevel::REQUIRED));
6222
6223 TransportSecurityState tss;
6224 tss.SetRequireCTDelegate(&require_ct_delegate);
6225
6226 EXPECT_TRUE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6227 "www.example.org", "mail.example.org",
6228 NetworkAnonymizationKey()));
6229 }
6230
TEST(CanPoolTest,CanPoolWithAcceptablePins)6231 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
6232 TransportSecurityState tss;
6233 tss.EnableStaticPinsForTesting();
6234 tss.SetPinningListAlwaysTimelyForTesting(true);
6235 ScopedTransportSecurityStateSource scoped_security_state_source;
6236
6237 TestSSLConfigService ssl_config_service;
6238 SSLInfo ssl_info;
6239 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
6240 "spdy_pooling.pem");
6241 ssl_info.is_issued_by_known_root = true;
6242 HashValue hash;
6243 // The expected value of GoodPin1 used by |scoped_security_state_source|.
6244 ASSERT_TRUE(
6245 hash.FromString("sha256/Nn8jk5By4Vkq6BeOVZ7R7AC6XUUBZsWmUbJR1f1Y5FY="));
6246 ssl_info.public_key_hashes.push_back(hash);
6247
6248 EXPECT_TRUE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6249 "www.example.org", "mail.example.org",
6250 NetworkAnonymizationKey()));
6251 }
6252
TEST(CanPoolTest,CanPoolWithClientCertsAndPolicy)6253 TEST(CanPoolTest, CanPoolWithClientCertsAndPolicy) {
6254 TransportSecurityState tss;
6255 SSLInfo ssl_info;
6256 ssl_info.cert =
6257 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
6258 ssl_info.client_cert_sent = true;
6259
6260 // Configure ssl_config_service so that CanShareConnectionWithClientCerts
6261 // returns true for www.example.org and mail.example.org.
6262 TestSSLConfigService ssl_config_service;
6263 ssl_config_service.SetDomainsForPooling(
6264 {"www.example.org", "mail.example.org"});
6265
6266 // Test that CanPool returns true when client certs are enabled and
6267 // CanShareConnectionWithClientCerts returns true for both hostnames, but not
6268 // just one hostname.
6269 EXPECT_TRUE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6270 "www.example.org", "mail.example.org",
6271 NetworkAnonymizationKey()));
6272 EXPECT_FALSE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6273 "www.example.org", "mail.example.com",
6274 NetworkAnonymizationKey()));
6275 EXPECT_FALSE(SpdySession::CanPool(&tss, ssl_info, ssl_config_service,
6276 "mail.example.com", "www.example.org",
6277 NetworkAnonymizationKey()));
6278 }
6279
6280 // Regression test for https://crbug.com/1115492.
TEST_F(SpdySessionTest,UpdateHeaderTableSize)6281 TEST_F(SpdySessionTest, UpdateHeaderTableSize) {
6282 spdy::SettingsMap settings;
6283 settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = 12345;
6284 spdy::SpdySerializedFrame settings_frame(
6285 spdy_util_.ConstructSpdySettings(settings));
6286 MockRead reads[] = {CreateMockRead(settings_frame, 0),
6287 MockRead(ASYNC, ERR_IO_PENDING, 2),
6288 MockRead(ASYNC, 0, 3)};
6289
6290 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
6291 MockWrite writes[] = {CreateMockWrite(settings_ack, 1)};
6292
6293 SequencedSocketData data(reads, writes);
6294 session_deps_.socket_factory->AddSocketDataProvider(&data);
6295
6296 AddSSLSocketData();
6297
6298 CreateNetworkSession();
6299 CreateSpdySession();
6300
6301 EXPECT_EQ(spdy::kDefaultHeaderTableSizeSetting, header_encoder_table_size());
6302 base::RunLoop().RunUntilIdle();
6303 EXPECT_EQ(12345u, header_encoder_table_size());
6304
6305 data.Resume();
6306 base::RunLoop().RunUntilIdle();
6307 EXPECT_TRUE(data.AllWriteDataConsumed());
6308 EXPECT_TRUE(data.AllReadDataConsumed());
6309 }
6310
TEST_F(SpdySessionTest,PriorityUpdateDisabled)6311 TEST_F(SpdySessionTest, PriorityUpdateDisabled) {
6312 session_deps_.enable_priority_update = false;
6313
6314 spdy::SettingsMap settings;
6315 settings[spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES] = 1;
6316 auto settings_frame = spdy_util_.ConstructSpdySettings(settings);
6317 auto settings_ack = spdy_util_.ConstructSpdySettingsAck();
6318
6319 MockRead reads[] = {CreateMockRead(settings_frame, 0),
6320 MockRead(ASYNC, ERR_IO_PENDING, 2),
6321 MockRead(ASYNC, 0, 3)};
6322 MockWrite writes[] = {CreateMockWrite(settings_ack, 1)};
6323 SequencedSocketData data(reads, writes);
6324
6325 session_deps_.socket_factory->AddSocketDataProvider(&data);
6326 AddSSLSocketData();
6327
6328 CreateNetworkSession();
6329 CreateSpdySession();
6330
6331 // HTTP/2 priorities enabled by default.
6332 // PRIORITY_UPDATE is disabled by |enable_priority_update| = false.
6333 EXPECT_TRUE(session_->ShouldSendHttp2Priority());
6334 EXPECT_FALSE(session_->ShouldSendPriorityUpdate());
6335
6336 // Receive SETTINGS frame.
6337 base::RunLoop().RunUntilIdle();
6338
6339 // Since |enable_priority_update| = false,
6340 // SETTINGS_DEPRECATE_HTTP2_PRIORITIES has no effect.
6341 EXPECT_TRUE(session_->ShouldSendHttp2Priority());
6342 EXPECT_FALSE(session_->ShouldSendPriorityUpdate());
6343
6344 data.Resume();
6345 base::RunLoop().RunUntilIdle();
6346 EXPECT_TRUE(data.AllWriteDataConsumed());
6347 EXPECT_TRUE(data.AllReadDataConsumed());
6348 }
6349
TEST_F(SpdySessionTest,PriorityUpdateEnabledHttp2PrioritiesDeprecated)6350 TEST_F(SpdySessionTest, PriorityUpdateEnabledHttp2PrioritiesDeprecated) {
6351 session_deps_.enable_priority_update = true;
6352
6353 spdy::SettingsMap settings;
6354 settings[spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES] = 1;
6355 auto settings_frame = spdy_util_.ConstructSpdySettings(settings);
6356 auto settings_ack = spdy_util_.ConstructSpdySettingsAck();
6357
6358 MockRead reads[] = {CreateMockRead(settings_frame, 0),
6359 MockRead(ASYNC, ERR_IO_PENDING, 2),
6360 MockRead(ASYNC, 0, 3)};
6361 MockWrite writes[] = {CreateMockWrite(settings_ack, 1)};
6362 SequencedSocketData data(reads, writes);
6363
6364 session_deps_.socket_factory->AddSocketDataProvider(&data);
6365 AddSSLSocketData();
6366
6367 CreateNetworkSession();
6368 CreateSpdySession();
6369
6370 // Both priority schemes are enabled until SETTINGS frame is received.
6371 EXPECT_TRUE(session_->ShouldSendHttp2Priority());
6372 EXPECT_TRUE(session_->ShouldSendPriorityUpdate());
6373
6374 // Receive SETTINGS frame.
6375 base::RunLoop().RunUntilIdle();
6376
6377 // SETTINGS_DEPRECATE_HTTP2_PRIORITIES = 1 disables HTTP/2 priorities.
6378 EXPECT_FALSE(session_->ShouldSendHttp2Priority());
6379 EXPECT_TRUE(session_->ShouldSendPriorityUpdate());
6380
6381 data.Resume();
6382 base::RunLoop().RunUntilIdle();
6383 EXPECT_TRUE(data.AllWriteDataConsumed());
6384 EXPECT_TRUE(data.AllReadDataConsumed());
6385 }
6386
TEST_F(SpdySessionTest,PriorityUpdateEnabledHttp2PrioritiesNotDeprecated)6387 TEST_F(SpdySessionTest, PriorityUpdateEnabledHttp2PrioritiesNotDeprecated) {
6388 session_deps_.enable_priority_update = true;
6389
6390 spdy::SettingsMap settings;
6391 settings[spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES] = 0;
6392 auto settings_frame = spdy_util_.ConstructSpdySettings(settings);
6393 auto settings_ack = spdy_util_.ConstructSpdySettingsAck();
6394
6395 MockRead reads[] = {CreateMockRead(settings_frame, 0),
6396 MockRead(ASYNC, ERR_IO_PENDING, 2),
6397 MockRead(ASYNC, 0, 3)};
6398 MockWrite writes[] = {CreateMockWrite(settings_ack, 1)};
6399 SequencedSocketData data(reads, writes);
6400
6401 session_deps_.socket_factory->AddSocketDataProvider(&data);
6402 AddSSLSocketData();
6403
6404 CreateNetworkSession();
6405 CreateSpdySession();
6406
6407 // Both priority schemes are enabled until SETTINGS frame is received.
6408 EXPECT_TRUE(session_->ShouldSendHttp2Priority());
6409 EXPECT_TRUE(session_->ShouldSendPriorityUpdate());
6410
6411 // Receive SETTINGS frame.
6412 base::RunLoop().RunUntilIdle();
6413
6414 // SETTINGS_DEPRECATE_HTTP2_PRIORITIES = 0 disables PRIORITY_UPDATE.
6415 EXPECT_TRUE(session_->ShouldSendHttp2Priority());
6416 EXPECT_FALSE(session_->ShouldSendPriorityUpdate());
6417
6418 data.Resume();
6419 base::RunLoop().RunUntilIdle();
6420 EXPECT_TRUE(data.AllWriteDataConsumed());
6421 EXPECT_TRUE(data.AllReadDataConsumed());
6422 }
6423
TEST_F(SpdySessionTest,SettingsDeprecateHttp2PrioritiesValueMustNotChange)6424 TEST_F(SpdySessionTest, SettingsDeprecateHttp2PrioritiesValueMustNotChange) {
6425 spdy::SettingsMap settings0;
6426 settings0[spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES] = 0;
6427 auto settings_frame0 = spdy_util_.ConstructSpdySettings(settings0);
6428 spdy::SettingsMap settings1;
6429 settings1[spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES] = 1;
6430 auto settings_frame1 = spdy_util_.ConstructSpdySettings(settings1);
6431 MockRead reads[] = {
6432 CreateMockRead(settings_frame1, 0), MockRead(ASYNC, ERR_IO_PENDING, 2),
6433 CreateMockRead(settings_frame1, 3), MockRead(ASYNC, ERR_IO_PENDING, 5),
6434 CreateMockRead(settings_frame0, 6)};
6435
6436 auto settings_ack = spdy_util_.ConstructSpdySettingsAck();
6437 auto goaway = spdy_util_.ConstructSpdyGoAway(
6438 0, spdy::ERROR_CODE_PROTOCOL_ERROR,
6439 "spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES value changed after first "
6440 "SETTINGS frame.");
6441 MockWrite writes[] = {
6442 CreateMockWrite(settings_ack, 1), CreateMockWrite(settings_ack, 4),
6443 CreateMockWrite(settings_ack, 7), CreateMockWrite(goaway, 8)};
6444
6445 SequencedSocketData data(reads, writes);
6446
6447 session_deps_.socket_factory->AddSocketDataProvider(&data);
6448 AddSSLSocketData();
6449
6450 CreateNetworkSession();
6451 CreateSpdySession();
6452
6453 base::RunLoop().RunUntilIdle();
6454 data.Resume();
6455 base::RunLoop().RunUntilIdle();
6456 data.Resume();
6457 base::RunLoop().RunUntilIdle();
6458 EXPECT_TRUE(data.AllWriteDataConsumed());
6459 EXPECT_TRUE(data.AllReadDataConsumed());
6460 }
6461
TEST_F(SpdySessionTest,AlpsEmpty)6462 TEST_F(SpdySessionTest, AlpsEmpty) {
6463 base::HistogramTester histogram_tester;
6464
6465 ssl_.peer_application_settings = "";
6466
6467 SequencedSocketData data;
6468 session_deps_.socket_factory->AddSocketDataProvider(&data);
6469 AddSSLSocketData();
6470
6471 CreateNetworkSession();
6472 CreateSpdySession();
6473
6474 histogram_tester.ExpectUniqueSample(
6475 "Net.SpdySession.AlpsDecoderStatus",
6476 static_cast<int>(AlpsDecoder::Error::kNoError), 1);
6477 histogram_tester.ExpectUniqueSample(
6478 "Net.SpdySession.AlpsSettingParameterCount", 0, 1);
6479 const int kNoEntries = 0;
6480 histogram_tester.ExpectUniqueSample("Net.SpdySession.AlpsAcceptChEntries",
6481 kNoEntries, 1);
6482
6483 histogram_tester.ExpectTotalCount("Net.SpdySession.AcceptChForOrigin", 0);
6484 EXPECT_EQ("", session_->GetAcceptChViaAlps(
6485 url::SchemeHostPort(GURL("https://www.example.org"))));
6486 histogram_tester.ExpectUniqueSample("Net.SpdySession.AcceptChForOrigin",
6487 false, 1);
6488 }
6489
TEST_F(SpdySessionTest,AlpsSettings)6490 TEST_F(SpdySessionTest, AlpsSettings) {
6491 base::HistogramTester histogram_tester;
6492
6493 spdy::SettingsMap settings;
6494 settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = 12345;
6495 spdy::SpdySerializedFrame settings_frame(
6496 spdy_util_.ConstructSpdySettings(settings));
6497 ssl_.peer_application_settings =
6498 std::string(settings_frame.data(), settings_frame.size());
6499
6500 SequencedSocketData data;
6501 session_deps_.socket_factory->AddSocketDataProvider(&data);
6502 AddSSLSocketData();
6503
6504 CreateNetworkSession();
6505 CreateSpdySession();
6506
6507 EXPECT_EQ(12345u, header_encoder_table_size());
6508
6509 histogram_tester.ExpectUniqueSample(
6510 "Net.SpdySession.AlpsDecoderStatus",
6511 static_cast<int>(AlpsDecoder::Error::kNoError), 1);
6512 histogram_tester.ExpectUniqueSample(
6513 "Net.SpdySession.AlpsSettingParameterCount", 1, 1);
6514 }
6515
TEST_F(SpdySessionTest,AlpsAcceptCh)6516 TEST_F(SpdySessionTest, AlpsAcceptCh) {
6517 base::HistogramTester histogram_tester;
6518
6519 ssl_.peer_application_settings = HexDecode(
6520 "00001e" // length
6521 "89" // type ACCEPT_CH
6522 "00" // flags
6523 "00000000" // stream ID
6524 "0017" // origin length
6525 "68747470733a2f2f7777772e" //
6526 "6578616d706c652e636f6d" // origin "https://www.example.com"
6527 "0003" // value length
6528 "666f6f"); // value "foo"
6529
6530 SequencedSocketData data;
6531 session_deps_.socket_factory->AddSocketDataProvider(&data);
6532 AddSSLSocketData();
6533
6534 CreateNetworkSession();
6535 CreateSpdySession();
6536
6537 histogram_tester.ExpectUniqueSample(
6538 "Net.SpdySession.AlpsDecoderStatus",
6539 static_cast<int>(AlpsDecoder::Error::kNoError), 1);
6540 const int kOnlyValidEntries = 1;
6541 histogram_tester.ExpectUniqueSample("Net.SpdySession.AlpsAcceptChEntries",
6542 kOnlyValidEntries, 1);
6543
6544 histogram_tester.ExpectTotalCount("Net.SpdySession.AcceptChForOrigin", 0);
6545
6546 EXPECT_EQ("foo", session_->GetAcceptChViaAlps(
6547 url::SchemeHostPort(GURL("https://www.example.com"))));
6548 histogram_tester.ExpectUniqueSample("Net.SpdySession.AcceptChForOrigin", true,
6549 1);
6550
6551 EXPECT_EQ("", session_->GetAcceptChViaAlps(
6552 url::SchemeHostPort(GURL("https://www.example.org"))));
6553 histogram_tester.ExpectTotalCount("Net.SpdySession.AcceptChForOrigin", 2);
6554 histogram_tester.ExpectBucketCount("Net.SpdySession.AcceptChForOrigin", true,
6555 1);
6556 histogram_tester.ExpectBucketCount("Net.SpdySession.AcceptChForOrigin", false,
6557 1);
6558 }
6559
TEST_F(SpdySessionTest,AlpsAcceptChInvalidOrigin)6560 TEST_F(SpdySessionTest, AlpsAcceptChInvalidOrigin) {
6561 base::HistogramTester histogram_tester;
6562
6563 // "www.example.com" is not a valid origin, because it does not have a scheme.
6564 ssl_.peer_application_settings = HexDecode(
6565 "000017" // length
6566 "89" // type ACCEPT_CH
6567 "00" // flags
6568 "00000000" // stream ID
6569 "0010" // origin length
6570 "2f7777772e6578616d706c652e636f6d" // origin "www.example.com"
6571 "0003" // value length
6572 "666f6f"); // value "foo"
6573
6574 SequencedSocketData data;
6575 session_deps_.socket_factory->AddSocketDataProvider(&data);
6576 AddSSLSocketData();
6577
6578 CreateNetworkSession();
6579 CreateSpdySession();
6580
6581 // Invalid origin error is not considered fatal for the connection.
6582 EXPECT_TRUE(session_->IsAvailable());
6583
6584 histogram_tester.ExpectUniqueSample(
6585 "Net.SpdySession.AlpsDecoderStatus",
6586 static_cast<int>(AlpsDecoder::Error::kNoError), 1);
6587 const int kOnlyInvalidEntries = 2;
6588 histogram_tester.ExpectUniqueSample("Net.SpdySession.AlpsAcceptChEntries",
6589 kOnlyInvalidEntries, 1);
6590 }
6591
6592 // Test that ConfirmHandshake() correctly handles the client aborting the
6593 // connection. See https://crbug.com/1211639.
TEST_F(SpdySessionTest,ConfirmHandshakeAfterClose)6594 TEST_F(SpdySessionTest, ConfirmHandshakeAfterClose) {
6595 base::HistogramTester histogram_tester;
6596
6597 session_deps_.enable_early_data = true;
6598 // Arrange for StreamSocket::ConfirmHandshake() to hang.
6599 ssl_.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
6600 SequencedSocketData data;
6601 session_deps_.socket_factory->AddSocketDataProvider(&data);
6602 AddSSLSocketData();
6603
6604 CreateNetworkSession();
6605 CreateSpdySession();
6606
6607 TestCompletionCallback callback1;
6608 int rv1 = session_->ConfirmHandshake(callback1.callback());
6609 EXPECT_THAT(rv1, IsError(ERR_IO_PENDING));
6610
6611 // Abort the session. Although the underlying StreamSocket::ConfirmHandshake()
6612 // operation never completes, SpdySession::ConfirmHandshake() is signaled when
6613 // the session is discarded.
6614 session_->CloseSessionOnError(ERR_ABORTED, "Aborting session");
6615 EXPECT_THAT(callback1.GetResult(rv1), IsError(ERR_ABORTED));
6616
6617 // Subsequent calls to SpdySession::ConfirmHandshake() fail gracefully. This
6618 // tests that SpdySession honors StreamSocket::ConfirmHandshake() invariants.
6619 // (MockSSLClientSocket::ConfirmHandshake() checks it internally.)
6620 TestCompletionCallback callback2;
6621 int rv2 = session_->ConfirmHandshake(callback2.callback());
6622 EXPECT_THAT(rv2, IsError(ERR_CONNECTION_CLOSED));
6623 }
6624
6625 } // namespace net
6626