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