blob: 5373ba3879d12724dfd7c5d4b6e592463c9bd886 [file] [log] [blame]
xunjieli707f8952016-06-06 15:22:061// 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
Bence Béky94658bf2018-05-11 19:22:585#include "net/spdy/bidirectional_stream_spdy_impl.h"
xunjieli707f8952016-06-06 15:22:066
Bence Béky4e83f492018-05-13 23:14:257#include <string>
8
Ryan Sleevib8d7ea02018-05-07 20:01:019#include "base/containers/span.h"
xunjieli707f8952016-06-06 15:22:0610#include "base/run_loop.h"
Avi Drissman4365a4782018-12-28 19:26:2411#include "base/stl_util.h"
xunjieli707f8952016-06-06 15:22:0612#include "base/strings/string_number_conversions.h"
Bence Békyd74f4382018-02-20 18:26:1913#include "base/strings/string_piece.h"
xunjieli707f8952016-06-06 15:22:0614#include "base/time/time.h"
15#include "base/timer/mock_timer.h"
Sebastien Marchandefda77e532019-01-25 22:53:5216#include "base/timer/timer.h"
xunjieli6d0b944d2016-09-21 01:53:5717#include "net/base/load_timing_info.h"
18#include "net/base/load_timing_info_test_util.h"
xunjieli707f8952016-06-06 15:22:0619#include "net/base/net_errors.h"
xunjieli707f8952016-06-06 15:22:0620#include "net/http/http_request_info.h"
21#include "net/http/http_response_headers.h"
22#include "net/http/http_response_info.h"
xunjieli707f8952016-06-06 15:22:0623#include "net/log/test_net_log.h"
Paul Jensena457017a2018-01-19 23:52:0424#include "net/socket/socket_tag.h"
xunjieli707f8952016-06-06 15:22:0625#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5826#include "net/spdy/spdy_session.h"
27#include "net/spdy/spdy_test_util_common.h"
xunjieli707f8952016-06-06 15:22:0628#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0129#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4330#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:0131#include "net/test/test_with_scoped_task_environment.h"
Ramin Halavati3c96c6d2018-03-11 13:29:4432#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
robpercival214763f2016-07-01 23:27:0133#include "testing/gmock/include/gmock/gmock.h"
xunjieli707f8952016-06-06 15:22:0634#include "testing/gtest/include/gtest/gtest.h"
35
robpercival214763f2016-07-01 23:27:0136using net::test::IsError;
37using net::test::IsOk;
38
xunjieli707f8952016-06-06 15:22:0639namespace net {
40
41namespace {
42
43const char kBodyData[] = "Body data";
Avi Drissman4365a4782018-12-28 19:26:2444const size_t kBodyDataSize = base::size(kBodyData);
xunjieli707f8952016-06-06 15:22:0645// Size of the buffer to be allocated for each read.
46const size_t kReadBufferSize = 4096;
47
xunjieli6d0b944d2016-09-21 01:53:5748// Tests the load timing of a stream that's connected and is not the first
49// request sent on a connection.
50void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
51 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:1952 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
xunjieli6d0b944d2016-09-21 01:53:5753
54 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
55 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
56}
57
58// Tests the load timing of a stream that's connected and using a fresh
59// connection.
60void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info) {
61 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:1962 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
xunjieli6d0b944d2016-09-21 01:53:5763
64 ExpectConnectTimingHasTimes(
65 load_timing_info.connect_timing,
66 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
67 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
68}
69
xunjieli707f8952016-06-06 15:22:0670class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
71 public:
72 TestDelegateBase(base::WeakPtr<SpdySession> session,
73 IOBuffer* read_buf,
74 int read_buf_len)
Jeremy Roman0579ed62017-08-29 15:56:1975 : stream_(std::make_unique<BidirectionalStreamSpdyImpl>(session,
bnc3f6a8552017-05-17 13:40:3476 NetLogSource())),
xunjieli707f8952016-06-06 15:22:0677 read_buf_(read_buf),
78 read_buf_len_(read_buf_len),
79 loop_(nullptr),
80 error_(OK),
81 bytes_read_(0),
82 on_data_read_count_(0),
83 on_data_sent_count_(0),
84 do_not_start_read_(false),
85 run_until_completion_(false),
86 not_expect_callback_(false),
87 on_failed_called_(false) {}
88
Chris Watkins61914cb2017-12-01 19:59:0089 ~TestDelegateBase() override = default;
xunjieli707f8952016-06-06 15:22:0690
91 void OnStreamReady(bool request_headers_sent) override {
92 CHECK(!on_failed_called_);
93 }
94
Ryan Hamilton0239aac2018-05-19 00:03:1395 void OnHeadersReceived(
96 const spdy::SpdyHeaderBlock& response_headers) override {
xunjieli707f8952016-06-06 15:22:0697 CHECK(!on_failed_called_);
98 CHECK(!not_expect_callback_);
bnc94893a72016-06-30 13:45:2599 response_headers_ = response_headers.Clone();
xunjieli707f8952016-06-06 15:22:06100 if (!do_not_start_read_)
101 StartOrContinueReading();
102 }
103
104 void OnDataRead(int bytes_read) override {
105 CHECK(!on_failed_called_);
106 CHECK(!not_expect_callback_);
107 on_data_read_count_++;
108 CHECK_GE(bytes_read, OK);
109 bytes_read_ += bytes_read;
110 data_received_.append(read_buf_->data(), bytes_read);
111 if (!do_not_start_read_)
112 StartOrContinueReading();
113 }
114
115 void OnDataSent() override {
116 CHECK(!on_failed_called_);
117 CHECK(!not_expect_callback_);
118 on_data_sent_count_++;
119 }
120
Ryan Hamilton0239aac2018-05-19 00:03:13121 void OnTrailersReceived(const spdy::SpdyHeaderBlock& trailers) override {
xunjieli707f8952016-06-06 15:22:06122 CHECK(!on_failed_called_);
bnc94893a72016-06-30 13:45:25123 trailers_ = trailers.Clone();
xunjieli707f8952016-06-06 15:22:06124 if (run_until_completion_)
125 loop_->Quit();
126 }
127
128 void OnFailed(int error) override {
129 CHECK(!on_failed_called_);
130 CHECK(!not_expect_callback_);
131 CHECK_NE(OK, error);
132 error_ = error;
133 on_failed_called_ = true;
134 if (run_until_completion_)
135 loop_->Quit();
136 }
137
138 void Start(const BidirectionalStreamRequestInfo* request,
tfarina42834112016-09-22 13:38:20139 const NetLogWithSource& net_log) {
xunjieli707f8952016-06-06 15:22:06140 stream_->Start(request, net_log,
141 /*send_request_headers_automatically=*/false, this,
tzik08d8d6e2018-07-09 04:11:47142 std::make_unique<base::OneShotTimer>(),
Ramin Halavati3c96c6d2018-03-11 13:29:44143 TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli707f8952016-06-06 15:22:06144 not_expect_callback_ = false;
145 }
146
147 void SendData(IOBuffer* data, int length, bool end_of_stream) {
rchad39988f2017-06-02 05:34:32148 SendvData({data}, {length}, end_of_stream);
xunjieli707f8952016-06-06 15:22:06149 }
150
151 void SendvData(const std::vector<scoped_refptr<IOBuffer>>& data,
152 const std::vector<int>& length,
153 bool end_of_stream) {
154 not_expect_callback_ = true;
155 stream_->SendvData(data, length, end_of_stream);
156 not_expect_callback_ = false;
157 }
158
159 // Sets whether the delegate should wait until the completion of the stream.
160 void SetRunUntilCompletion(bool run_until_completion) {
161 run_until_completion_ = run_until_completion;
Jeremy Roman0579ed62017-08-29 15:56:19162 loop_ = std::make_unique<base::RunLoop>();
xunjieli707f8952016-06-06 15:22:06163 }
164
xunjieli6d0b944d2016-09-21 01:53:57165 // Wait until the stream reaches completion.
166 void WaitUntilCompletion() { loop_->Run(); }
167
xunjieli707f8952016-06-06 15:22:06168 // Starts or continues read data from |stream_| until there is no more
169 // byte can be read synchronously.
170 void StartOrContinueReading() {
171 int rv = ReadData();
172 while (rv > 0) {
173 rv = ReadData();
174 }
175 if (run_until_completion_ && rv == 0)
176 loop_->Quit();
177 }
178
179 // Calls ReadData on the |stream_| and updates internal states.
180 int ReadData() {
181 int rv = stream_->ReadData(read_buf_.get(), read_buf_len_);
182 if (rv > 0) {
183 data_received_.append(read_buf_->data(), rv);
184 bytes_read_ += rv;
185 }
186 return rv;
187 }
188
189 NextProto GetProtocol() const { return stream_->GetProtocol(); }
190
191 int64_t GetTotalReceivedBytes() const {
xunjieli9ff75c562016-08-10 20:26:16192 return stream_->GetTotalReceivedBytes();
xunjieli707f8952016-06-06 15:22:06193 }
194
xunjieli9ff75c562016-08-10 20:26:16195 int64_t GetTotalSentBytes() const {
xunjieli9ff75c562016-08-10 20:26:16196 return stream_->GetTotalSentBytes();
xunjieli6d0b944d2016-09-21 01:53:57197 }
198
199 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
200 return stream_->GetLoadTimingInfo(load_timing_info);
xunjieli9ff75c562016-08-10 20:26:16201 }
xunjieli707f8952016-06-06 15:22:06202
203 // Const getters for internal states.
Bence Béky4e83f492018-05-13 23:14:25204 const std::string& data_received() const { return data_received_; }
xunjieli707f8952016-06-06 15:22:06205 int bytes_read() const { return bytes_read_; }
206 int error() const { return error_; }
Ryan Hamilton0239aac2018-05-19 00:03:13207 const spdy::SpdyHeaderBlock& response_headers() const {
208 return response_headers_;
209 }
210 const spdy::SpdyHeaderBlock& trailers() const { return trailers_; }
xunjieli707f8952016-06-06 15:22:06211 int on_data_read_count() const { return on_data_read_count_; }
212 int on_data_sent_count() const { return on_data_sent_count_; }
213 bool on_failed_called() const { return on_failed_called_; }
214
215 // Sets whether the delegate should automatically start reading.
216 void set_do_not_start_read(bool do_not_start_read) {
217 do_not_start_read_ = do_not_start_read;
218 }
219
xunjieli707f8952016-06-06 15:22:06220 private:
221 std::unique_ptr<BidirectionalStreamSpdyImpl> stream_;
222 scoped_refptr<IOBuffer> read_buf_;
223 int read_buf_len_;
Bence Béky4e83f492018-05-13 23:14:25224 std::string data_received_;
xunjieli707f8952016-06-06 15:22:06225 std::unique_ptr<base::RunLoop> loop_;
Ryan Hamilton0239aac2018-05-19 00:03:13226 spdy::SpdyHeaderBlock response_headers_;
227 spdy::SpdyHeaderBlock trailers_;
xunjieli707f8952016-06-06 15:22:06228 int error_;
229 int bytes_read_;
230 int on_data_read_count_;
231 int on_data_sent_count_;
232 bool do_not_start_read_;
233 bool run_until_completion_;
234 bool not_expect_callback_;
235 bool on_failed_called_;
236
237 DISALLOW_COPY_AND_ASSIGN(TestDelegateBase);
238};
239
240} // namespace
241
Bence Béky98447b12018-05-08 03:14:01242class BidirectionalStreamSpdyImplTest : public testing::TestWithParam<bool>,
243 public WithScopedTaskEnvironment {
xunjieli707f8952016-06-06 15:22:06244 public:
245 BidirectionalStreamSpdyImplTest()
bncd16676a2016-07-20 16:23:01246 : default_url_(kDefaultUrl),
bnc3d9035b32016-06-30 18:18:48247 host_port_pair_(HostPortPair::FromURL(default_url_)),
Paul Jensena457017a2018-01-19 23:52:04248 key_(host_port_pair_,
249 ProxyServer::Direct(),
250 PRIVACY_MODE_DISABLED,
Matt Menke2436b2f2018-12-11 18:07:11251 SpdySessionKey::IsProxySession::kFalse,
Paul Jensena457017a2018-01-19 23:52:04252 SocketTag()),
xunjieli707f8952016-06-06 15:22:06253 ssl_data_(SSLSocketDataProvider(ASYNC, OK)) {
bnc3cf2a592016-08-11 14:48:36254 ssl_data_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49255 ssl_data_.ssl_info.cert =
256 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
xunjieli707f8952016-06-06 15:22:06257 }
258
259 protected:
260 void TearDown() override {
261 if (sequenced_data_) {
262 EXPECT_TRUE(sequenced_data_->AllReadDataConsumed());
263 EXPECT_TRUE(sequenced_data_->AllWriteDataConsumed());
264 }
265 }
266
267 // Initializes the session using SequencedSocketData.
Ryan Sleevib8d7ea02018-05-07 20:01:01268 void InitSession(base::span<const MockRead> reads,
269 base::span<const MockWrite> writes) {
Ryan Sleevi4f832092017-11-21 23:25:49270 ASSERT_TRUE(ssl_data_.ssl_info.cert.get());
xunjieli707f8952016-06-06 15:22:06271 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data_);
Ryan Sleevib8d7ea02018-05-07 20:01:01272 sequenced_data_ = std::make_unique<SequencedSocketData>(reads, writes);
xunjieli707f8952016-06-06 15:22:06273 session_deps_.socket_factory->AddSocketDataProvider(sequenced_data_.get());
274 session_deps_.net_log = net_log_.bound().net_log();
275 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
Bence Béky0ef1556e2017-06-30 19:52:52276 session_ = CreateSpdySession(http_session_.get(), key_, net_log_.bound());
xunjieli707f8952016-06-06 15:22:06277 }
278
279 BoundTestNetLog net_log_;
280 SpdyTestUtil spdy_util_;
281 SpdySessionDependencies session_deps_;
bnc3d9035b32016-06-30 18:18:48282 const GURL default_url_;
283 const HostPortPair host_port_pair_;
284 const SpdySessionKey key_;
xunjieli707f8952016-06-06 15:22:06285 std::unique_ptr<SequencedSocketData> sequenced_data_;
286 std::unique_ptr<HttpNetworkSession> http_session_;
287 base::WeakPtr<SpdySession> session_;
288
289 private:
290 SSLSocketDataProvider ssl_data_;
291};
292
xunjieli6d0b944d2016-09-21 01:53:57293TEST_F(BidirectionalStreamSpdyImplTest, SimplePostRequest) {
Ryan Hamilton0239aac2018-05-19 00:03:13294 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
xunjieli6d0b944d2016-09-21 01:53:57295 kDefaultUrl, 1, kBodyDataSize, LOW, nullptr, 0));
Ryan Hamilton0239aac2018-05-19 00:03:13296 spdy::SpdySerializedFrame data_frame(spdy_util_.ConstructSpdyDataFrame(
Bence Békyd74f4382018-02-20 18:26:19297 1, base::StringPiece(kBodyData, kBodyDataSize), /*fin=*/true));
xunjieli6d0b944d2016-09-21 01:53:57298 MockWrite writes[] = {
299 CreateMockWrite(req, 0), CreateMockWrite(data_frame, 3),
300 };
Ryan Hamilton0239aac2018-05-19 00:03:13301 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
302 spdy::SpdySerializedFrame response_body_frame(
xunjieli6d0b944d2016-09-21 01:53:57303 spdy_util_.ConstructSpdyDataFrame(1, /*fin=*/true));
304 MockRead reads[] = {
305 CreateMockRead(resp, 1),
306 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
307 CreateMockRead(response_body_frame, 4), MockRead(ASYNC, 0, 5),
308 };
Ryan Sleevib8d7ea02018-05-07 20:01:01309 InitSession(reads, writes);
xunjieli6d0b944d2016-09-21 01:53:57310
311 BidirectionalStreamRequestInfo request_info;
312 request_info.method = "POST";
313 request_info.url = default_url_;
314 request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
Brett Wilson5accd242017-11-30 22:07:32315 base::NumberToString(kBodyDataSize));
xunjieli6d0b944d2016-09-21 01:53:57316
Victor Costan9c7302b2018-08-27 16:39:44317 scoped_refptr<IOBuffer> read_buffer =
318 base::MakeRefCounted<IOBuffer>(kReadBufferSize);
Jeremy Roman0579ed62017-08-29 15:56:19319 auto delegate = std::make_unique<TestDelegateBase>(
bnc3f6a8552017-05-17 13:40:34320 session_, read_buffer.get(), kReadBufferSize);
xunjieli6d0b944d2016-09-21 01:53:57321 delegate->SetRunUntilCompletion(true);
322 delegate->Start(&request_info, net_log_.bound());
323 sequenced_data_->RunUntilPaused();
324
Victor Costan9c7302b2018-08-27 16:39:44325 scoped_refptr<StringIOBuffer> write_buffer =
326 base::MakeRefCounted<StringIOBuffer>(
327 std::string(kBodyData, kBodyDataSize));
xunjieli6d0b944d2016-09-21 01:53:57328 delegate->SendData(write_buffer.get(), write_buffer->size(), true);
329 sequenced_data_->Resume();
330 base::RunLoop().RunUntilIdle();
331 delegate->WaitUntilCompletion();
332 LoadTimingInfo load_timing_info;
333 EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
334 TestLoadTimingNotReused(load_timing_info);
335
336 EXPECT_EQ(1, delegate->on_data_read_count());
337 EXPECT_EQ(1, delegate->on_data_sent_count());
338 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
Ryan Sleevib8d7ea02018-05-07 20:01:01339 EXPECT_EQ(CountWriteBytes(writes), delegate->GetTotalSentBytes());
340 EXPECT_EQ(CountReadBytes(reads), delegate->GetTotalReceivedBytes());
xunjieli6d0b944d2016-09-21 01:53:57341}
342
343TEST_F(BidirectionalStreamSpdyImplTest, LoadTimingTwoRequests) {
Ryan Hamilton0239aac2018-05-19 00:03:13344 spdy::SpdySerializedFrame req(
Bence Béky27ad0a12018-02-08 00:35:48345 spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/1, LOW));
Ryan Hamilton0239aac2018-05-19 00:03:13346 spdy::SpdySerializedFrame req2(
Bence Béky27ad0a12018-02-08 00:35:48347 spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/3, LOW));
xunjieli6d0b944d2016-09-21 01:53:57348 MockWrite writes[] = {
349 CreateMockWrite(req, 0), CreateMockWrite(req2, 2),
350 };
Ryan Hamilton0239aac2018-05-19 00:03:13351 spdy::SpdySerializedFrame resp(
xunjieli6d0b944d2016-09-21 01:53:57352 spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/1));
Ryan Hamilton0239aac2018-05-19 00:03:13353 spdy::SpdySerializedFrame resp2(
xunjieli6d0b944d2016-09-21 01:53:57354 spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/3));
Ryan Hamilton0239aac2018-05-19 00:03:13355 spdy::SpdySerializedFrame resp_body(
xunjieli6d0b944d2016-09-21 01:53:57356 spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/1, /*fin=*/true));
Ryan Hamilton0239aac2018-05-19 00:03:13357 spdy::SpdySerializedFrame resp_body2(
xunjieli6d0b944d2016-09-21 01:53:57358 spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/3, /*fin=*/true));
359 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(resp_body, 3),
360 CreateMockRead(resp2, 4), CreateMockRead(resp_body2, 5),
361 MockRead(ASYNC, 0, 6)};
Ryan Sleevib8d7ea02018-05-07 20:01:01362 InitSession(reads, writes);
xunjieli6d0b944d2016-09-21 01:53:57363
364 BidirectionalStreamRequestInfo request_info;
365 request_info.method = "GET";
366 request_info.url = default_url_;
367 request_info.end_stream_on_headers = true;
368
Victor Costan9c7302b2018-08-27 16:39:44369 scoped_refptr<IOBuffer> read_buffer =
370 base::MakeRefCounted<IOBuffer>(kReadBufferSize);
371 scoped_refptr<IOBuffer> read_buffer2 =
372 base::MakeRefCounted<IOBuffer>(kReadBufferSize);
Jeremy Roman0579ed62017-08-29 15:56:19373 auto delegate = std::make_unique<TestDelegateBase>(
bnc3f6a8552017-05-17 13:40:34374 session_, read_buffer.get(), kReadBufferSize);
Jeremy Roman0579ed62017-08-29 15:56:19375 auto delegate2 = std::make_unique<TestDelegateBase>(
bnc3f6a8552017-05-17 13:40:34376 session_, read_buffer2.get(), kReadBufferSize);
xunjieli6d0b944d2016-09-21 01:53:57377 delegate->SetRunUntilCompletion(true);
378 delegate2->SetRunUntilCompletion(true);
379 delegate->Start(&request_info, net_log_.bound());
380 delegate2->Start(&request_info, net_log_.bound());
381
382 base::RunLoop().RunUntilIdle();
383 delegate->WaitUntilCompletion();
384 delegate2->WaitUntilCompletion();
385 LoadTimingInfo load_timing_info;
386 EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
387 TestLoadTimingNotReused(load_timing_info);
388 LoadTimingInfo load_timing_info2;
389 EXPECT_TRUE(delegate2->GetLoadTimingInfo(&load_timing_info2));
390 TestLoadTimingReused(load_timing_info2);
391}
392
xunjieli707f8952016-06-06 15:22:06393TEST_F(BidirectionalStreamSpdyImplTest, SendDataAfterStreamFailed) {
Ryan Hamilton0239aac2018-05-19 00:03:13394 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bnc3d9035b32016-06-30 18:18:48395 kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0));
Ryan Hamilton0239aac2018-05-19 00:03:13396 spdy::SpdySerializedFrame rst(
397 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
xunjieli707f8952016-06-06 15:22:06398
399 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41400 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
xunjieli707f8952016-06-06 15:22:06401 };
402
403 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
Ryan Hamilton0239aac2018-05-19 00:03:13404 spdy::SpdySerializedFrame resp(
bnc42331402016-07-25 13:36:15405 spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1, 1));
xunjieli707f8952016-06-06 15:22:06406
407 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41408 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3),
xunjieli707f8952016-06-06 15:22:06409 };
410
Ryan Sleevib8d7ea02018-05-07 20:01:01411 InitSession(reads, writes);
xunjieli707f8952016-06-06 15:22:06412
413 BidirectionalStreamRequestInfo request_info;
414 request_info.method = "POST";
bnc3d9035b32016-06-30 18:18:48415 request_info.url = default_url_;
xunjieli707f8952016-06-06 15:22:06416 request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
Brett Wilson5accd242017-11-30 22:07:32417 base::NumberToString(kBodyDataSize * 3));
xunjieli707f8952016-06-06 15:22:06418
Victor Costan9c7302b2018-08-27 16:39:44419 scoped_refptr<IOBuffer> read_buffer =
420 base::MakeRefCounted<IOBuffer>(kReadBufferSize);
Jeremy Roman0579ed62017-08-29 15:56:19421 auto delegate = std::make_unique<TestDelegateBase>(
bnc3f6a8552017-05-17 13:40:34422 session_, read_buffer.get(), kReadBufferSize);
xunjieli707f8952016-06-06 15:22:06423 delegate->SetRunUntilCompletion(true);
424 delegate->Start(&request_info, net_log_.bound());
425 base::RunLoop().RunUntilIdle();
426
427 EXPECT_TRUE(delegate->on_failed_called());
428
429 // Try to send data after OnFailed(), should not get called back.
Victor Costan9c7302b2018-08-27 16:39:44430 scoped_refptr<StringIOBuffer> buf =
431 base::MakeRefCounted<StringIOBuffer>("dummy");
xunjieli707f8952016-06-06 15:22:06432 delegate->SendData(buf.get(), buf->size(), false);
433 base::RunLoop().RunUntilIdle();
434
Bence Békyd0d69502019-06-25 19:47:18435 EXPECT_THAT(delegate->error(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
xunjieli707f8952016-06-06 15:22:06436 EXPECT_EQ(0, delegate->on_data_read_count());
437 EXPECT_EQ(0, delegate->on_data_sent_count());
438 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
439 // BidirectionalStreamSpdyStreamJob does not count the bytes sent for |rst|
440 // because it is sent after SpdyStream::Delegate::OnClose is called.
Ryan Sleevib8d7ea02018-05-07 20:01:01441 EXPECT_EQ(CountWriteBytes(base::make_span(writes, 1)),
442 delegate->GetTotalSentBytes());
Minjeong Leebbd225772017-11-28 14:37:25443 EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
xunjieli707f8952016-06-06 15:22:06444}
445
Victor Costan2309ea02019-02-13 21:35:47446INSTANTIATE_TEST_SUITE_P(BidirectionalStreamSpdyImplTests,
447 BidirectionalStreamSpdyImplTest,
448 ::testing::Bool());
xunjieli4f8b6bb62016-10-31 23:16:00449
450// Tests that when received RST_STREAM with NO_ERROR, BidirectionalStream does
451// not crash when processing pending writes. See crbug.com/650438.
452TEST_P(BidirectionalStreamSpdyImplTest, RstWithNoErrorBeforeSendIsComplete) {
453 bool is_test_sendv = GetParam();
Ryan Hamilton0239aac2018-05-19 00:03:13454 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
xunjieli4f8b6bb62016-10-31 23:16:00455 kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0));
456 MockWrite writes[] = {CreateMockWrite(req, 0)};
457
Ryan Hamilton0239aac2018-05-19 00:03:13458 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
459 spdy::SpdySerializedFrame rst(
460 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR));
xunjieli4f8b6bb62016-10-31 23:16:00461 MockRead reads[] = {CreateMockRead(resp, 1),
462 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
463 CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
464
Ryan Sleevib8d7ea02018-05-07 20:01:01465 InitSession(reads, writes);
xunjieli4f8b6bb62016-10-31 23:16:00466
467 BidirectionalStreamRequestInfo request_info;
468 request_info.method = "POST";
469 request_info.url = default_url_;
470 request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
Brett Wilson5accd242017-11-30 22:07:32471 base::NumberToString(kBodyDataSize * 3));
xunjieli4f8b6bb62016-10-31 23:16:00472
Victor Costan9c7302b2018-08-27 16:39:44473 scoped_refptr<IOBuffer> read_buffer =
474 base::MakeRefCounted<IOBuffer>(kReadBufferSize);
Jeremy Roman0579ed62017-08-29 15:56:19475 auto delegate = std::make_unique<TestDelegateBase>(
bnc3f6a8552017-05-17 13:40:34476 session_, read_buffer.get(), kReadBufferSize);
xunjieli4f8b6bb62016-10-31 23:16:00477 delegate->SetRunUntilCompletion(true);
478 delegate->Start(&request_info, net_log_.bound());
479 sequenced_data_->RunUntilPaused();
480 // Make a write pending before receiving RST_STREAM.
Victor Costan9c7302b2018-08-27 16:39:44481 scoped_refptr<StringIOBuffer> write_buffer =
482 base::MakeRefCounted<StringIOBuffer>(
483 std::string(kBodyData, kBodyDataSize));
xunjieli4f8b6bb62016-10-31 23:16:00484 delegate->SendData(write_buffer.get(), write_buffer->size(), false);
485 sequenced_data_->Resume();
486 base::RunLoop().RunUntilIdle();
487
488 // Make sure OnClose() without an error completes any pending write().
489 EXPECT_EQ(1, delegate->on_data_sent_count());
490 EXPECT_FALSE(delegate->on_failed_called());
491
492 if (is_test_sendv) {
493 std::vector<scoped_refptr<IOBuffer>> three_buffers = {
494 write_buffer.get(), write_buffer.get(), write_buffer.get()};
495 std::vector<int> three_lengths = {
496 write_buffer->size(), write_buffer->size(), write_buffer->size()};
497 delegate->SendvData(three_buffers, three_lengths, /*end_of_stream=*/true);
498 base::RunLoop().RunUntilIdle();
499 } else {
500 for (size_t j = 0; j < 3; j++) {
501 delegate->SendData(write_buffer.get(), write_buffer->size(),
502 /*end_of_stream=*/j == 2);
503 base::RunLoop().RunUntilIdle();
504 }
505 }
506 delegate->WaitUntilCompletion();
507 LoadTimingInfo load_timing_info;
508 EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
509 TestLoadTimingNotReused(load_timing_info);
510
511 EXPECT_THAT(delegate->error(), IsError(OK));
512 EXPECT_EQ(1, delegate->on_data_read_count());
513 EXPECT_EQ(is_test_sendv ? 2 : 4, delegate->on_data_sent_count());
514 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
Ryan Sleevib8d7ea02018-05-07 20:01:01515 EXPECT_EQ(CountWriteBytes(base::make_span(writes, 1)),
516 delegate->GetTotalSentBytes());
xunjieli4f8b6bb62016-10-31 23:16:00517 // Should not count RST stream.
Ryan Sleevib8d7ea02018-05-07 20:01:01518 EXPECT_EQ(CountReadBytes(base::make_span(reads).first(base::size(reads) - 2)),
xunjieli4f8b6bb62016-10-31 23:16:00519 delegate->GetTotalReceivedBytes());
520
521 // Now call SendData again should produce an error because end of stream
522 // flag has been written.
523 if (is_test_sendv) {
524 std::vector<scoped_refptr<IOBuffer>> buffer = {write_buffer.get()};
525 std::vector<int> buffer_size = {write_buffer->size()};
526 delegate->SendvData(buffer, buffer_size, true);
527 } else {
528 delegate->SendData(write_buffer.get(), write_buffer->size(), true);
529 }
530 base::RunLoop().RunUntilIdle();
531 EXPECT_THAT(delegate->error(), IsError(ERR_UNEXPECTED));
532 EXPECT_TRUE(delegate->on_failed_called());
533 EXPECT_EQ(is_test_sendv ? 2 : 4, delegate->on_data_sent_count());
534}
535
xunjieli707f8952016-06-06 15:22:06536} // namespace net