bidirectional_stream_spdy_impl_unittest.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. // Copyright 2016 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. #include "net/spdy/bidirectional_stream_spdy_impl.h"
  5. #include <string>
  6. #include "base/containers/span.h"
  7. #include "base/run_loop.h"
  8. #include "base/strings/string_number_conversions.h"
  9. #include "base/strings/string_piece.h"
  10. #include "base/time/time.h"
  11. #include "base/timer/mock_timer.h"
  12. #include "base/timer/timer.h"
  13. #include "net/base/load_timing_info.h"
  14. #include "net/base/load_timing_info_test_util.h"
  15. #include "net/base/net_errors.h"
  16. #include "net/dns/public/secure_dns_policy.h"
  17. #include "net/http/http_request_info.h"
  18. #include "net/http/http_response_headers.h"
  19. #include "net/http/http_response_info.h"
  20. #include "net/log/net_log.h"
  21. #include "net/socket/socket_tag.h"
  22. #include "net/socket/socket_test_util.h"
  23. #include "net/spdy/spdy_session.h"
  24. #include "net/spdy/spdy_test_util_common.h"
  25. #include "net/test/cert_test_util.h"
  26. #include "net/test/gtest_util.h"
  27. #include "net/test/test_data_directory.h"
  28. #include "net/test/test_with_task_environment.h"
  29. #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
  30. #include "testing/gmock/include/gmock/gmock.h"
  31. #include "testing/gtest/include/gtest/gtest.h"
  32. using net::test::IsError;
  33. using net::test::IsOk;
  34. namespace net {
  35. namespace {
  36. const char kBodyData[] = "Body data";
  37. const size_t kBodyDataSize = std::size(kBodyData);
  38. // Size of the buffer to be allocated for each read.
  39. const size_t kReadBufferSize = 4096;
  40. // Tests the load timing of a stream that's connected and is not the first
  41. // request sent on a connection.
  42. void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
  43. EXPECT_TRUE(load_timing_info.socket_reused);
  44. EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
  45. ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
  46. ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
  47. }
  48. // Tests the load timing of a stream that's connected and using a fresh
  49. // connection.
  50. void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info) {
  51. EXPECT_FALSE(load_timing_info.socket_reused);
  52. EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
  53. ExpectConnectTimingHasTimes(
  54. load_timing_info.connect_timing,
  55. CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
  56. ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
  57. }
  58. class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
  59. public:
  60. TestDelegateBase(base::WeakPtr<SpdySession> session,
  61. IOBuffer* read_buf,
  62. int read_buf_len)
  63. : stream_(std::make_unique<BidirectionalStreamSpdyImpl>(session,
  64. NetLogSource())),
  65. read_buf_(read_buf),
  66. read_buf_len_(read_buf_len) {}
  67. TestDelegateBase(const TestDelegateBase&) = delete;
  68. TestDelegateBase& operator=(const TestDelegateBase&) = delete;
  69. ~TestDelegateBase() override = default;
  70. void OnStreamReady(bool request_headers_sent) override {
  71. CHECK(!on_failed_called_);
  72. }
  73. void OnHeadersReceived(
  74. const spdy::Http2HeaderBlock& response_headers) override {
  75. CHECK(!on_failed_called_);
  76. CHECK(!not_expect_callback_);
  77. response_headers_ = response_headers.Clone();
  78. if (!do_not_start_read_)
  79. StartOrContinueReading();
  80. }
  81. void OnDataRead(int bytes_read) override {
  82. CHECK(!on_failed_called_);
  83. CHECK(!not_expect_callback_);
  84. on_data_read_count_++;
  85. CHECK_GE(bytes_read, OK);
  86. bytes_read_ += bytes_read;
  87. data_received_.append(read_buf_->data(), bytes_read);
  88. if (!do_not_start_read_)
  89. StartOrContinueReading();
  90. }
  91. void OnDataSent() override {
  92. CHECK(!on_failed_called_);
  93. CHECK(!not_expect_callback_);
  94. on_data_sent_count_++;
  95. }
  96. void OnTrailersReceived(const spdy::Http2HeaderBlock& trailers) override {
  97. CHECK(!on_failed_called_);
  98. trailers_ = trailers.Clone();
  99. if (run_until_completion_)
  100. loop_->Quit();
  101. }
  102. void OnFailed(int error) override {
  103. CHECK(!on_failed_called_);
  104. CHECK(!not_expect_callback_);
  105. CHECK_NE(OK, error);
  106. error_ = error;
  107. on_failed_called_ = true;
  108. if (run_until_completion_)
  109. loop_->Quit();
  110. }
  111. void Start(const BidirectionalStreamRequestInfo* request,
  112. const NetLogWithSource& net_log) {
  113. stream_->Start(request, net_log,
  114. /*send_request_headers_automatically=*/false, this,
  115. std::make_unique<base::OneShotTimer>(),
  116. TRAFFIC_ANNOTATION_FOR_TESTS);
  117. not_expect_callback_ = false;
  118. }
  119. void SendData(IOBuffer* data, int length, bool end_of_stream) {
  120. SendvData({data}, {length}, end_of_stream);
  121. }
  122. void SendvData(const std::vector<scoped_refptr<IOBuffer>>& data,
  123. const std::vector<int>& length,
  124. bool end_of_stream) {
  125. not_expect_callback_ = true;
  126. stream_->SendvData(data, length, end_of_stream);
  127. not_expect_callback_ = false;
  128. }
  129. // Sets whether the delegate should wait until the completion of the stream.
  130. void SetRunUntilCompletion(bool run_until_completion) {
  131. run_until_completion_ = run_until_completion;
  132. loop_ = std::make_unique<base::RunLoop>();
  133. }
  134. // Wait until the stream reaches completion.
  135. void WaitUntilCompletion() { loop_->Run(); }
  136. // Starts or continues read data from |stream_| until there is no more
  137. // byte can be read synchronously.
  138. void StartOrContinueReading() {
  139. int rv = ReadData();
  140. while (rv > 0) {
  141. rv = ReadData();
  142. }
  143. if (run_until_completion_ && rv == 0)
  144. loop_->Quit();
  145. }
  146. // Calls ReadData on the |stream_| and updates internal states.
  147. int ReadData() {
  148. int rv = stream_->ReadData(read_buf_.get(), read_buf_len_);
  149. if (rv > 0) {
  150. data_received_.append(read_buf_->data(), rv);
  151. bytes_read_ += rv;
  152. }
  153. return rv;
  154. }
  155. NextProto GetProtocol() const { return stream_->GetProtocol(); }
  156. int64_t GetTotalReceivedBytes() const {
  157. return stream_->GetTotalReceivedBytes();
  158. }
  159. int64_t GetTotalSentBytes() const {
  160. return stream_->GetTotalSentBytes();
  161. }
  162. bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
  163. return stream_->GetLoadTimingInfo(load_timing_info);
  164. }
  165. // Const getters for internal states.
  166. const std::string& data_received() const { return data_received_; }
  167. int bytes_read() const { return bytes_read_; }
  168. int error() const { return error_; }
  169. const spdy::Http2HeaderBlock& response_headers() const {
  170. return response_headers_;
  171. }
  172. const spdy::Http2HeaderBlock& trailers() const { return trailers_; }
  173. int on_data_read_count() const { return on_data_read_count_; }
  174. int on_data_sent_count() const { return on_data_sent_count_; }
  175. bool on_failed_called() const { return on_failed_called_; }
  176. // Sets whether the delegate should automatically start reading.
  177. void set_do_not_start_read(bool do_not_start_read) {
  178. do_not_start_read_ = do_not_start_read;
  179. }
  180. private:
  181. std::unique_ptr<BidirectionalStreamSpdyImpl> stream_;
  182. scoped_refptr<IOBuffer> read_buf_;
  183. int read_buf_len_;
  184. std::string data_received_;
  185. std::unique_ptr<base::RunLoop> loop_;
  186. spdy::Http2HeaderBlock response_headers_;
  187. spdy::Http2HeaderBlock trailers_;
  188. int error_ = OK;
  189. int bytes_read_ = 0;
  190. int on_data_read_count_ = 0;
  191. int on_data_sent_count_ = 0;
  192. bool do_not_start_read_ = false;
  193. bool run_until_completion_ = false;
  194. bool not_expect_callback_ = false;
  195. bool on_failed_called_ = false;
  196. };
  197. } // namespace
  198. class BidirectionalStreamSpdyImplTest : public testing::TestWithParam<bool>,
  199. public WithTaskEnvironment {
  200. public:
  201. BidirectionalStreamSpdyImplTest()
  202. : default_url_(kDefaultUrl),
  203. host_port_pair_(HostPortPair::FromURL(default_url_)),
  204. key_(host_port_pair_,
  205. ProxyServer::Direct(),
  206. PRIVACY_MODE_DISABLED,
  207. SpdySessionKey::IsProxySession::kFalse,
  208. SocketTag(),
  209. NetworkIsolationKey(),
  210. SecureDnsPolicy::kAllow),
  211. ssl_data_(SSLSocketDataProvider(ASYNC, OK)) {
  212. ssl_data_.next_proto = kProtoHTTP2;
  213. ssl_data_.ssl_info.cert =
  214. ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
  215. }
  216. bool IsBrokenConnectionDetectionEnabled() const {
  217. if (!session_)
  218. return false;
  219. return session_->IsBrokenConnectionDetectionEnabled();
  220. }
  221. protected:
  222. void TearDown() override {
  223. if (sequenced_data_) {
  224. EXPECT_TRUE(sequenced_data_->AllReadDataConsumed());
  225. EXPECT_TRUE(sequenced_data_->AllWriteDataConsumed());
  226. }
  227. }
  228. // Initializes the session using SequencedSocketData.
  229. void InitSession(base::span<const MockRead> reads,
  230. base::span<const MockWrite> writes) {
  231. ASSERT_TRUE(ssl_data_.ssl_info.cert.get());
  232. session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data_);
  233. sequenced_data_ = std::make_unique<SequencedSocketData>(reads, writes);
  234. session_deps_.socket_factory->AddSocketDataProvider(sequenced_data_.get());
  235. session_deps_.net_log = NetLog::Get();
  236. http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
  237. session_ =
  238. CreateSpdySession(http_session_.get(), key_, net_log_with_source_);
  239. }
  240. NetLogWithSource net_log_with_source_{
  241. NetLogWithSource::Make(NetLogSourceType::NONE)};
  242. SpdyTestUtil spdy_util_;
  243. SpdySessionDependencies session_deps_;
  244. const GURL default_url_;
  245. const HostPortPair host_port_pair_;
  246. const SpdySessionKey key_;
  247. std::unique_ptr<SequencedSocketData> sequenced_data_;
  248. std::unique_ptr<HttpNetworkSession> http_session_;
  249. base::WeakPtr<SpdySession> session_;
  250. private:
  251. SSLSocketDataProvider ssl_data_;
  252. };
  253. TEST_F(BidirectionalStreamSpdyImplTest, SimplePostRequest) {
  254. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
  255. kDefaultUrl, 1, kBodyDataSize, LOW, nullptr, 0));
  256. spdy::SpdySerializedFrame data_frame(spdy_util_.ConstructSpdyDataFrame(
  257. 1, base::StringPiece(kBodyData, kBodyDataSize), /*fin=*/true));
  258. MockWrite writes[] = {
  259. CreateMockWrite(req, 0), CreateMockWrite(data_frame, 3),
  260. };
  261. spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
  262. spdy::SpdySerializedFrame response_body_frame(
  263. spdy_util_.ConstructSpdyDataFrame(1, /*fin=*/true));
  264. MockRead reads[] = {
  265. CreateMockRead(resp, 1),
  266. MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
  267. CreateMockRead(response_body_frame, 4), MockRead(ASYNC, 0, 5),
  268. };
  269. InitSession(reads, writes);
  270. BidirectionalStreamRequestInfo request_info;
  271. request_info.method = "POST";
  272. request_info.url = default_url_;
  273. request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
  274. base::NumberToString(kBodyDataSize));
  275. scoped_refptr<IOBuffer> read_buffer =
  276. base::MakeRefCounted<IOBuffer>(kReadBufferSize);
  277. auto delegate = std::make_unique<TestDelegateBase>(
  278. session_, read_buffer.get(), kReadBufferSize);
  279. delegate->SetRunUntilCompletion(true);
  280. delegate->Start(&request_info, net_log_with_source_);
  281. sequenced_data_->RunUntilPaused();
  282. scoped_refptr<StringIOBuffer> write_buffer =
  283. base::MakeRefCounted<StringIOBuffer>(
  284. std::string(kBodyData, kBodyDataSize));
  285. delegate->SendData(write_buffer.get(), write_buffer->size(), true);
  286. sequenced_data_->Resume();
  287. base::RunLoop().RunUntilIdle();
  288. delegate->WaitUntilCompletion();
  289. LoadTimingInfo load_timing_info;
  290. EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
  291. TestLoadTimingNotReused(load_timing_info);
  292. EXPECT_EQ(1, delegate->on_data_read_count());
  293. EXPECT_EQ(1, delegate->on_data_sent_count());
  294. EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
  295. EXPECT_EQ(CountWriteBytes(writes), delegate->GetTotalSentBytes());
  296. EXPECT_EQ(CountReadBytes(reads), delegate->GetTotalReceivedBytes());
  297. }
  298. TEST_F(BidirectionalStreamSpdyImplTest, LoadTimingTwoRequests) {
  299. spdy::SpdySerializedFrame req(
  300. spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/1, LOW));
  301. spdy::SpdySerializedFrame req2(
  302. spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/3, LOW));
  303. MockWrite writes[] = {
  304. CreateMockWrite(req, 0), CreateMockWrite(req2, 2),
  305. };
  306. spdy::SpdySerializedFrame resp(
  307. spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/1));
  308. spdy::SpdySerializedFrame resp2(
  309. spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/3));
  310. spdy::SpdySerializedFrame resp_body(
  311. spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/1, /*fin=*/true));
  312. spdy::SpdySerializedFrame resp_body2(
  313. spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/3, /*fin=*/true));
  314. MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(resp_body, 3),
  315. CreateMockRead(resp2, 4), CreateMockRead(resp_body2, 5),
  316. MockRead(ASYNC, 0, 6)};
  317. InitSession(reads, writes);
  318. BidirectionalStreamRequestInfo request_info;
  319. request_info.method = "GET";
  320. request_info.url = default_url_;
  321. request_info.end_stream_on_headers = true;
  322. scoped_refptr<IOBuffer> read_buffer =
  323. base::MakeRefCounted<IOBuffer>(kReadBufferSize);
  324. scoped_refptr<IOBuffer> read_buffer2 =
  325. base::MakeRefCounted<IOBuffer>(kReadBufferSize);
  326. auto delegate = std::make_unique<TestDelegateBase>(
  327. session_, read_buffer.get(), kReadBufferSize);
  328. auto delegate2 = std::make_unique<TestDelegateBase>(
  329. session_, read_buffer2.get(), kReadBufferSize);
  330. delegate->SetRunUntilCompletion(true);
  331. delegate2->SetRunUntilCompletion(true);
  332. delegate->Start(&request_info, net_log_with_source_);
  333. delegate2->Start(&request_info, net_log_with_source_);
  334. base::RunLoop().RunUntilIdle();
  335. delegate->WaitUntilCompletion();
  336. delegate2->WaitUntilCompletion();
  337. LoadTimingInfo load_timing_info;
  338. EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
  339. TestLoadTimingNotReused(load_timing_info);
  340. LoadTimingInfo load_timing_info2;
  341. EXPECT_TRUE(delegate2->GetLoadTimingInfo(&load_timing_info2));
  342. TestLoadTimingReused(load_timing_info2);
  343. }
  344. TEST_F(BidirectionalStreamSpdyImplTest, SendDataAfterStreamFailed) {
  345. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
  346. kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0));
  347. spdy::SpdySerializedFrame rst(
  348. spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
  349. MockWrite writes[] = {
  350. CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
  351. };
  352. const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
  353. spdy::SpdySerializedFrame resp(
  354. spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1, 1));
  355. MockRead reads[] = {
  356. CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3),
  357. };
  358. InitSession(reads, writes);
  359. BidirectionalStreamRequestInfo request_info;
  360. request_info.method = "POST";
  361. request_info.url = default_url_;
  362. request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
  363. base::NumberToString(kBodyDataSize * 3));
  364. scoped_refptr<IOBuffer> read_buffer =
  365. base::MakeRefCounted<IOBuffer>(kReadBufferSize);
  366. auto delegate = std::make_unique<TestDelegateBase>(
  367. session_, read_buffer.get(), kReadBufferSize);
  368. delegate->SetRunUntilCompletion(true);
  369. delegate->Start(&request_info, net_log_with_source_);
  370. base::RunLoop().RunUntilIdle();
  371. EXPECT_TRUE(delegate->on_failed_called());
  372. // Try to send data after OnFailed(), should not get called back.
  373. scoped_refptr<StringIOBuffer> buf =
  374. base::MakeRefCounted<StringIOBuffer>("dummy");
  375. delegate->SendData(buf.get(), buf->size(), false);
  376. base::RunLoop().RunUntilIdle();
  377. EXPECT_THAT(delegate->error(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
  378. EXPECT_EQ(0, delegate->on_data_read_count());
  379. EXPECT_EQ(0, delegate->on_data_sent_count());
  380. EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
  381. // BidirectionalStreamSpdyStreamJob does not count the bytes sent for |rst|
  382. // because it is sent after SpdyStream::Delegate::OnClose is called.
  383. EXPECT_EQ(CountWriteBytes(base::make_span(writes, 1)),
  384. delegate->GetTotalSentBytes());
  385. EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
  386. }
  387. INSTANTIATE_TEST_SUITE_P(BidirectionalStreamSpdyImplTests,
  388. BidirectionalStreamSpdyImplTest,
  389. ::testing::Bool());
  390. // Tests that when received RST_STREAM with NO_ERROR, BidirectionalStream does
  391. // not crash when processing pending writes. See crbug.com/650438.
  392. TEST_P(BidirectionalStreamSpdyImplTest, RstWithNoErrorBeforeSendIsComplete) {
  393. bool is_test_sendv = GetParam();
  394. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
  395. kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0));
  396. MockWrite writes[] = {CreateMockWrite(req, 0)};
  397. spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
  398. spdy::SpdySerializedFrame rst(
  399. spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR));
  400. MockRead reads[] = {CreateMockRead(resp, 1),
  401. MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
  402. CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
  403. InitSession(reads, writes);
  404. BidirectionalStreamRequestInfo request_info;
  405. request_info.method = "POST";
  406. request_info.url = default_url_;
  407. request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
  408. base::NumberToString(kBodyDataSize * 3));
  409. scoped_refptr<IOBuffer> read_buffer =
  410. base::MakeRefCounted<IOBuffer>(kReadBufferSize);
  411. auto delegate = std::make_unique<TestDelegateBase>(
  412. session_, read_buffer.get(), kReadBufferSize);
  413. delegate->SetRunUntilCompletion(true);
  414. delegate->Start(&request_info, net_log_with_source_);
  415. sequenced_data_->RunUntilPaused();
  416. // Make a write pending before receiving RST_STREAM.
  417. scoped_refptr<StringIOBuffer> write_buffer =
  418. base::MakeRefCounted<StringIOBuffer>(
  419. std::string(kBodyData, kBodyDataSize));
  420. delegate->SendData(write_buffer.get(), write_buffer->size(), false);
  421. sequenced_data_->Resume();
  422. base::RunLoop().RunUntilIdle();
  423. // Make sure OnClose() without an error completes any pending write().
  424. EXPECT_EQ(1, delegate->on_data_sent_count());
  425. EXPECT_FALSE(delegate->on_failed_called());
  426. if (is_test_sendv) {
  427. std::vector<scoped_refptr<IOBuffer>> three_buffers = {
  428. write_buffer.get(), write_buffer.get(), write_buffer.get()};
  429. std::vector<int> three_lengths = {
  430. write_buffer->size(), write_buffer->size(), write_buffer->size()};
  431. delegate->SendvData(three_buffers, three_lengths, /*end_of_stream=*/true);
  432. base::RunLoop().RunUntilIdle();
  433. } else {
  434. for (size_t j = 0; j < 3; j++) {
  435. delegate->SendData(write_buffer.get(), write_buffer->size(),
  436. /*end_of_stream=*/j == 2);
  437. base::RunLoop().RunUntilIdle();
  438. }
  439. }
  440. delegate->WaitUntilCompletion();
  441. LoadTimingInfo load_timing_info;
  442. EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
  443. TestLoadTimingNotReused(load_timing_info);
  444. EXPECT_THAT(delegate->error(), IsError(OK));
  445. EXPECT_EQ(1, delegate->on_data_read_count());
  446. EXPECT_EQ(is_test_sendv ? 2 : 4, delegate->on_data_sent_count());
  447. EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
  448. EXPECT_EQ(CountWriteBytes(base::make_span(writes, 1)),
  449. delegate->GetTotalSentBytes());
  450. // Should not count RST stream.
  451. EXPECT_EQ(CountReadBytes(base::make_span(reads).first(std::size(reads) - 2)),
  452. delegate->GetTotalReceivedBytes());
  453. // Now call SendData again should produce an error because end of stream
  454. // flag has been written.
  455. if (is_test_sendv) {
  456. std::vector<scoped_refptr<IOBuffer>> buffer = {write_buffer.get()};
  457. std::vector<int> buffer_size = {write_buffer->size()};
  458. delegate->SendvData(buffer, buffer_size, true);
  459. } else {
  460. delegate->SendData(write_buffer.get(), write_buffer->size(), true);
  461. }
  462. base::RunLoop().RunUntilIdle();
  463. EXPECT_THAT(delegate->error(), IsError(ERR_UNEXPECTED));
  464. EXPECT_TRUE(delegate->on_failed_called());
  465. EXPECT_EQ(is_test_sendv ? 2 : 4, delegate->on_data_sent_count());
  466. }
  467. TEST_F(BidirectionalStreamSpdyImplTest, RequestDetectBrokenConnection) {
  468. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
  469. kDefaultUrl, 1, kBodyDataSize, LOW, nullptr, 0));
  470. spdy::SpdySerializedFrame data_frame(spdy_util_.ConstructSpdyDataFrame(
  471. 1, base::StringPiece(kBodyData, kBodyDataSize), /*fin=*/true));
  472. MockWrite writes[] = {
  473. CreateMockWrite(req, 0),
  474. CreateMockWrite(data_frame, 3),
  475. };
  476. spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
  477. spdy::SpdySerializedFrame response_body_frame(
  478. spdy_util_.ConstructSpdyDataFrame(1, /*fin=*/true));
  479. MockRead reads[] = {
  480. CreateMockRead(resp, 1),
  481. MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
  482. CreateMockRead(response_body_frame, 4),
  483. MockRead(ASYNC, 0, 5),
  484. };
  485. InitSession(reads, writes);
  486. EXPECT_FALSE(IsBrokenConnectionDetectionEnabled());
  487. BidirectionalStreamRequestInfo request_info;
  488. request_info.method = "POST";
  489. request_info.url = default_url_;
  490. request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
  491. base::NumberToString(kBodyDataSize));
  492. request_info.detect_broken_connection = true;
  493. request_info.heartbeat_interval = base::Seconds(1);
  494. scoped_refptr<IOBuffer> read_buffer =
  495. base::MakeRefCounted<IOBuffer>(kReadBufferSize);
  496. auto delegate = std::make_unique<TestDelegateBase>(
  497. session_, read_buffer.get(), kReadBufferSize);
  498. delegate->SetRunUntilCompletion(true);
  499. delegate->Start(&request_info, net_log_with_source_);
  500. sequenced_data_->RunUntilPaused();
  501. // Since we set request_info.detect_broken_connection to true, this should be
  502. // enabled for the bidi stream lifetime.
  503. EXPECT_TRUE(IsBrokenConnectionDetectionEnabled());
  504. scoped_refptr<StringIOBuffer> write_buffer =
  505. base::MakeRefCounted<StringIOBuffer>(
  506. std::string(kBodyData, kBodyDataSize));
  507. delegate->SendData(write_buffer.get(), write_buffer->size(), true);
  508. sequenced_data_->Resume();
  509. base::RunLoop().RunUntilIdle();
  510. delegate->WaitUntilCompletion();
  511. LoadTimingInfo load_timing_info;
  512. EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
  513. TestLoadTimingNotReused(load_timing_info);
  514. EXPECT_EQ(1, delegate->on_data_read_count());
  515. EXPECT_EQ(1, delegate->on_data_sent_count());
  516. EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
  517. EXPECT_EQ(CountWriteBytes(writes), delegate->GetTotalSentBytes());
  518. EXPECT_EQ(CountReadBytes(reads), delegate->GetTotalReceivedBytes());
  519. delegate.reset();
  520. // Once the bidi stream has been destroyed this should go back to being
  521. // disabled.
  522. EXPECT_FALSE(IsBrokenConnectionDetectionEnabled());
  523. }
  524. } // namespace net