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