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