blob: 334782008d1d2f965a6db6beaa1351a17a11df2f [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
5#include "net/spdy/bidirectional_stream_spdy_impl.h"
6
7#include <memory>
8#include <string>
9
10#include "base/macros.h"
11#include "base/memory/ptr_util.h"
12#include "base/run_loop.h"
13#include "base/strings/string_number_conversions.h"
14#include "base/strings/string_piece.h"
15#include "base/time/time.h"
16#include "base/timer/mock_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"
mikecironef22f9812016-10-04 03:40:1923#include "net/log/net_log_source.h"
xunjieli707f8952016-06-06 15:22:0624#include "net/log/test_net_log.h"
25#include "net/socket/socket_test_util.h"
26#include "net/spdy/spdy_session.h"
27#include "net/spdy/spdy_test_util_common.h"
28#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"
robpercival214763f2016-07-01 23:27:0131#include "testing/gmock/include/gmock/gmock.h"
xunjieli707f8952016-06-06 15:22:0632#include "testing/gtest/include/gtest/gtest.h"
33
robpercival214763f2016-07-01 23:27:0134using net::test::IsError;
35using net::test::IsOk;
36
xunjieli707f8952016-06-06 15:22:0637namespace net {
38
39namespace {
40
41const char kBodyData[] = "Body data";
42const size_t kBodyDataSize = arraysize(kBodyData);
43// Size of the buffer to be allocated for each read.
44const size_t kReadBufferSize = 4096;
45
xunjieli6d0b944d2016-09-21 01:53:5746// Tests the load timing of a stream that's connected and is not the first
47// request sent on a connection.
48void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
49 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:1950 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
xunjieli6d0b944d2016-09-21 01:53:5751
52 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
53 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
54}
55
56// Tests the load timing of a stream that's connected and using a fresh
57// connection.
58void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info) {
59 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:1960 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
xunjieli6d0b944d2016-09-21 01:53:5761
62 ExpectConnectTimingHasTimes(
63 load_timing_info.connect_timing,
64 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
65 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
66}
67
xunjieli707f8952016-06-06 15:22:0668class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
69 public:
70 TestDelegateBase(base::WeakPtr<SpdySession> session,
71 IOBuffer* read_buf,
72 int read_buf_len)
73 : stream_(new BidirectionalStreamSpdyImpl(session)),
74 read_buf_(read_buf),
75 read_buf_len_(read_buf_len),
76 loop_(nullptr),
77 error_(OK),
78 bytes_read_(0),
79 on_data_read_count_(0),
80 on_data_sent_count_(0),
81 do_not_start_read_(false),
82 run_until_completion_(false),
83 not_expect_callback_(false),
84 on_failed_called_(false) {}
85
86 ~TestDelegateBase() override {}
87
88 void OnStreamReady(bool request_headers_sent) override {
89 CHECK(!on_failed_called_);
90 }
91
92 void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
93 CHECK(!on_failed_called_);
94 CHECK(!not_expect_callback_);
bnc94893a72016-06-30 13:45:2595 response_headers_ = response_headers.Clone();
xunjieli707f8952016-06-06 15:22:0696 if (!do_not_start_read_)
97 StartOrContinueReading();
98 }
99
100 void OnDataRead(int bytes_read) override {
101 CHECK(!on_failed_called_);
102 CHECK(!not_expect_callback_);
103 on_data_read_count_++;
104 CHECK_GE(bytes_read, OK);
105 bytes_read_ += bytes_read;
106 data_received_.append(read_buf_->data(), bytes_read);
107 if (!do_not_start_read_)
108 StartOrContinueReading();
109 }
110
111 void OnDataSent() override {
112 CHECK(!on_failed_called_);
113 CHECK(!not_expect_callback_);
114 on_data_sent_count_++;
115 }
116
117 void OnTrailersReceived(const SpdyHeaderBlock& trailers) override {
118 CHECK(!on_failed_called_);
bnc94893a72016-06-30 13:45:25119 trailers_ = trailers.Clone();
xunjieli707f8952016-06-06 15:22:06120 if (run_until_completion_)
121 loop_->Quit();
122 }
123
124 void OnFailed(int error) override {
125 CHECK(!on_failed_called_);
126 CHECK(!not_expect_callback_);
127 CHECK_NE(OK, error);
128 error_ = error;
129 on_failed_called_ = true;
130 if (run_until_completion_)
131 loop_->Quit();
132 }
133
134 void Start(const BidirectionalStreamRequestInfo* request,
tfarina42834112016-09-22 13:38:20135 const NetLogWithSource& net_log) {
xunjieli707f8952016-06-06 15:22:06136 stream_->Start(request, net_log,
137 /*send_request_headers_automatically=*/false, this,
ricea2deef682016-09-09 08:04:07138 base::MakeUnique<base::Timer>(false, false));
xunjieli707f8952016-06-06 15:22:06139 not_expect_callback_ = false;
140 }
141
142 void SendData(IOBuffer* data, int length, bool end_of_stream) {
143 not_expect_callback_ = true;
144 stream_->SendData(data, length, end_of_stream);
145 not_expect_callback_ = false;
146 }
147
148 void SendvData(const std::vector<scoped_refptr<IOBuffer>>& data,
149 const std::vector<int>& length,
150 bool end_of_stream) {
151 not_expect_callback_ = true;
152 stream_->SendvData(data, length, end_of_stream);
153 not_expect_callback_ = false;
154 }
155
156 // Sets whether the delegate should wait until the completion of the stream.
157 void SetRunUntilCompletion(bool run_until_completion) {
158 run_until_completion_ = run_until_completion;
159 loop_.reset(new base::RunLoop);
160 }
161
xunjieli6d0b944d2016-09-21 01:53:57162 // Wait until the stream reaches completion.
163 void WaitUntilCompletion() { loop_->Run(); }
164
xunjieli707f8952016-06-06 15:22:06165 // Starts or continues read data from |stream_| until there is no more
166 // byte can be read synchronously.
167 void StartOrContinueReading() {
168 int rv = ReadData();
169 while (rv > 0) {
170 rv = ReadData();
171 }
172 if (run_until_completion_ && rv == 0)
173 loop_->Quit();
174 }
175
176 // Calls ReadData on the |stream_| and updates internal states.
177 int ReadData() {
178 int rv = stream_->ReadData(read_buf_.get(), read_buf_len_);
179 if (rv > 0) {
180 data_received_.append(read_buf_->data(), rv);
181 bytes_read_ += rv;
182 }
183 return rv;
184 }
185
186 NextProto GetProtocol() const { return stream_->GetProtocol(); }
187
188 int64_t GetTotalReceivedBytes() const {
xunjieli9ff75c562016-08-10 20:26:16189 return stream_->GetTotalReceivedBytes();
xunjieli707f8952016-06-06 15:22:06190 }
191
xunjieli9ff75c562016-08-10 20:26:16192 int64_t GetTotalSentBytes() const {
xunjieli9ff75c562016-08-10 20:26:16193 return stream_->GetTotalSentBytes();
xunjieli6d0b944d2016-09-21 01:53:57194 }
195
196 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
197 return stream_->GetLoadTimingInfo(load_timing_info);
xunjieli9ff75c562016-08-10 20:26:16198 }
xunjieli707f8952016-06-06 15:22:06199
200 // Const getters for internal states.
201 const std::string& data_received() const { return data_received_; }
202 int bytes_read() const { return bytes_read_; }
203 int error() const { return error_; }
bnc94893a72016-06-30 13:45:25204 const SpdyHeaderBlock& response_headers() const { return response_headers_; }
205 const SpdyHeaderBlock& trailers() const { return trailers_; }
xunjieli707f8952016-06-06 15:22:06206 int on_data_read_count() const { return on_data_read_count_; }
207 int on_data_sent_count() const { return on_data_sent_count_; }
208 bool on_failed_called() const { return on_failed_called_; }
209
210 // Sets whether the delegate should automatically start reading.
211 void set_do_not_start_read(bool do_not_start_read) {
212 do_not_start_read_ = do_not_start_read;
213 }
214
xunjieli707f8952016-06-06 15:22:06215 private:
216 std::unique_ptr<BidirectionalStreamSpdyImpl> stream_;
217 scoped_refptr<IOBuffer> read_buf_;
218 int read_buf_len_;
219 std::string data_received_;
220 std::unique_ptr<base::RunLoop> loop_;
221 SpdyHeaderBlock response_headers_;
222 SpdyHeaderBlock trailers_;
223 int error_;
224 int bytes_read_;
225 int on_data_read_count_;
226 int on_data_sent_count_;
227 bool do_not_start_read_;
228 bool run_until_completion_;
229 bool not_expect_callback_;
230 bool on_failed_called_;
231
232 DISALLOW_COPY_AND_ASSIGN(TestDelegateBase);
233};
234
235} // namespace
236
xunjieli4f8b6bb62016-10-31 23:16:00237class BidirectionalStreamSpdyImplTest : public testing::TestWithParam<bool> {
xunjieli707f8952016-06-06 15:22:06238 public:
239 BidirectionalStreamSpdyImplTest()
bncd16676a2016-07-20 16:23:01240 : default_url_(kDefaultUrl),
bnc3d9035b32016-06-30 18:18:48241 host_port_pair_(HostPortPair::FromURL(default_url_)),
242 key_(host_port_pair_, ProxyServer::Direct(), PRIVACY_MODE_DISABLED),
xunjieli707f8952016-06-06 15:22:06243 ssl_data_(SSLSocketDataProvider(ASYNC, OK)) {
bnc3cf2a592016-08-11 14:48:36244 ssl_data_.next_proto = kProtoHTTP2;
xunjieli707f8952016-06-06 15:22:06245 ssl_data_.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
246 }
247
248 protected:
249 void TearDown() override {
250 if (sequenced_data_) {
251 EXPECT_TRUE(sequenced_data_->AllReadDataConsumed());
252 EXPECT_TRUE(sequenced_data_->AllWriteDataConsumed());
253 }
254 }
255
256 // Initializes the session using SequencedSocketData.
257 void InitSession(MockRead* reads,
258 size_t reads_count,
259 MockWrite* writes,
bnc3d9035b32016-06-30 18:18:48260 size_t writes_count) {
xunjieli707f8952016-06-06 15:22:06261 ASSERT_TRUE(ssl_data_.cert.get());
262 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data_);
263 sequenced_data_.reset(
264 new SequencedSocketData(reads, reads_count, writes, writes_count));
265 session_deps_.socket_factory->AddSocketDataProvider(sequenced_data_.get());
266 session_deps_.net_log = net_log_.bound().net_log();
267 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
268 session_ =
bnc3d9035b32016-06-30 18:18:48269 CreateSecureSpdySession(http_session_.get(), key_, net_log_.bound());
xunjieli707f8952016-06-06 15:22:06270 }
271
272 BoundTestNetLog net_log_;
273 SpdyTestUtil spdy_util_;
274 SpdySessionDependencies session_deps_;
bnc3d9035b32016-06-30 18:18:48275 const GURL default_url_;
276 const HostPortPair host_port_pair_;
277 const SpdySessionKey key_;
xunjieli707f8952016-06-06 15:22:06278 std::unique_ptr<SequencedSocketData> sequenced_data_;
279 std::unique_ptr<HttpNetworkSession> http_session_;
280 base::WeakPtr<SpdySession> session_;
281
282 private:
283 SSLSocketDataProvider ssl_data_;
284};
285
xunjieli6d0b944d2016-09-21 01:53:57286TEST_F(BidirectionalStreamSpdyImplTest, SimplePostRequest) {
287 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
288 kDefaultUrl, 1, kBodyDataSize, LOW, nullptr, 0));
289 SpdySerializedFrame data_frame(spdy_util_.ConstructSpdyDataFrame(
290 1, kBodyData, kBodyDataSize, /*fin=*/true));
291 MockWrite writes[] = {
292 CreateMockWrite(req, 0), CreateMockWrite(data_frame, 3),
293 };
294 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
295 SpdySerializedFrame response_body_frame(
296 spdy_util_.ConstructSpdyDataFrame(1, /*fin=*/true));
297 MockRead reads[] = {
298 CreateMockRead(resp, 1),
299 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
300 CreateMockRead(response_body_frame, 4), MockRead(ASYNC, 0, 5),
301 };
302 InitSession(reads, arraysize(reads), writes, arraysize(writes));
303
304 BidirectionalStreamRequestInfo request_info;
305 request_info.method = "POST";
306 request_info.url = default_url_;
307 request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
308 base::SizeTToString(kBodyDataSize));
309
310 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
311 std::unique_ptr<TestDelegateBase> delegate(
312 new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
313 delegate->SetRunUntilCompletion(true);
314 delegate->Start(&request_info, net_log_.bound());
315 sequenced_data_->RunUntilPaused();
316
317 scoped_refptr<StringIOBuffer> write_buffer(
318 new StringIOBuffer(std::string(kBodyData, kBodyDataSize)));
319 delegate->SendData(write_buffer.get(), write_buffer->size(), true);
320 sequenced_data_->Resume();
321 base::RunLoop().RunUntilIdle();
322 delegate->WaitUntilCompletion();
323 LoadTimingInfo load_timing_info;
324 EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
325 TestLoadTimingNotReused(load_timing_info);
326
327 EXPECT_EQ(1, delegate->on_data_read_count());
328 EXPECT_EQ(1, delegate->on_data_sent_count());
329 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
330 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
331 delegate->GetTotalSentBytes());
332 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
333 delegate->GetTotalReceivedBytes());
334}
335
336TEST_F(BidirectionalStreamSpdyImplTest, LoadTimingTwoRequests) {
337 SpdySerializedFrame req(
338 spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/1, LOW, true));
339 SpdySerializedFrame req2(
340 spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/3, LOW, true));
341 MockWrite writes[] = {
342 CreateMockWrite(req, 0), CreateMockWrite(req2, 2),
343 };
344 SpdySerializedFrame resp(
345 spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/1));
346 SpdySerializedFrame resp2(
347 spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/3));
348 SpdySerializedFrame resp_body(
349 spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/1, /*fin=*/true));
350 SpdySerializedFrame resp_body2(
351 spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/3, /*fin=*/true));
352 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(resp_body, 3),
353 CreateMockRead(resp2, 4), CreateMockRead(resp_body2, 5),
354 MockRead(ASYNC, 0, 6)};
355 InitSession(reads, arraysize(reads), writes, arraysize(writes));
356
357 BidirectionalStreamRequestInfo request_info;
358 request_info.method = "GET";
359 request_info.url = default_url_;
360 request_info.end_stream_on_headers = true;
361
362 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
363 scoped_refptr<IOBuffer> read_buffer2(new IOBuffer(kReadBufferSize));
364 std::unique_ptr<TestDelegateBase> delegate(
365 new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
366 std::unique_ptr<TestDelegateBase> delegate2(
367 new TestDelegateBase(session_, read_buffer2.get(), kReadBufferSize));
368 delegate->SetRunUntilCompletion(true);
369 delegate2->SetRunUntilCompletion(true);
370 delegate->Start(&request_info, net_log_.bound());
371 delegate2->Start(&request_info, net_log_.bound());
372
373 base::RunLoop().RunUntilIdle();
374 delegate->WaitUntilCompletion();
375 delegate2->WaitUntilCompletion();
376 LoadTimingInfo load_timing_info;
377 EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
378 TestLoadTimingNotReused(load_timing_info);
379 LoadTimingInfo load_timing_info2;
380 EXPECT_TRUE(delegate2->GetLoadTimingInfo(&load_timing_info2));
381 TestLoadTimingReused(load_timing_info2);
382}
383
xunjieli707f8952016-06-06 15:22:06384TEST_F(BidirectionalStreamSpdyImplTest, SendDataAfterStreamFailed) {
bncdf80d44fd2016-07-15 20:27:41385 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bnc3d9035b32016-06-30 18:18:48386 kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:41387 SpdySerializedFrame rst(
xunjieli707f8952016-06-06 15:22:06388 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
389
390 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41391 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
xunjieli707f8952016-06-06 15:22:06392 };
393
394 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
bncdf80d44fd2016-07-15 20:27:41395 SpdySerializedFrame resp(
bnc42331402016-07-25 13:36:15396 spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1, 1));
xunjieli707f8952016-06-06 15:22:06397
398 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41399 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3),
xunjieli707f8952016-06-06 15:22:06400 };
401
bnc3d9035b32016-06-30 18:18:48402 InitSession(reads, arraysize(reads), writes, arraysize(writes));
xunjieli707f8952016-06-06 15:22:06403
404 BidirectionalStreamRequestInfo request_info;
405 request_info.method = "POST";
bnc3d9035b32016-06-30 18:18:48406 request_info.url = default_url_;
xunjieli707f8952016-06-06 15:22:06407 request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
408 base::SizeTToString(kBodyDataSize * 3));
409
410 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
411 std::unique_ptr<TestDelegateBase> delegate(
412 new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
413 delegate->SetRunUntilCompletion(true);
414 delegate->Start(&request_info, net_log_.bound());
415 base::RunLoop().RunUntilIdle();
416
417 EXPECT_TRUE(delegate->on_failed_called());
418
419 // Try to send data after OnFailed(), should not get called back.
420 scoped_refptr<StringIOBuffer> buf(new StringIOBuffer("dummy"));
421 delegate->SendData(buf.get(), buf->size(), false);
422 base::RunLoop().RunUntilIdle();
423
robpercival214763f2016-07-01 23:27:01424 EXPECT_THAT(delegate->error(), IsError(ERR_SPDY_PROTOCOL_ERROR));
xunjieli707f8952016-06-06 15:22:06425 EXPECT_EQ(0, delegate->on_data_read_count());
426 EXPECT_EQ(0, delegate->on_data_sent_count());
427 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
428 // BidirectionalStreamSpdyStreamJob does not count the bytes sent for |rst|
429 // because it is sent after SpdyStream::Delegate::OnClose is called.
430 EXPECT_EQ(CountWriteBytes(writes, 1), delegate->GetTotalSentBytes());
431 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
432 delegate->GetTotalReceivedBytes());
433}
434
xunjieli4f8b6bb62016-10-31 23:16:00435INSTANTIATE_TEST_CASE_P(BidirectionalStreamSpdyImplTests,
436 BidirectionalStreamSpdyImplTest,
437 ::testing::Bool());
438
439// Tests that when received RST_STREAM with NO_ERROR, BidirectionalStream does
440// not crash when processing pending writes. See crbug.com/650438.
441TEST_P(BidirectionalStreamSpdyImplTest, RstWithNoErrorBeforeSendIsComplete) {
442 bool is_test_sendv = GetParam();
443 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
444 kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0));
445 MockWrite writes[] = {CreateMockWrite(req, 0)};
446
447 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
448 SpdySerializedFrame rst(
449 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_NO_ERROR));
450 MockRead reads[] = {CreateMockRead(resp, 1),
451 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
452 CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
453
454 InitSession(reads, arraysize(reads), writes, arraysize(writes));
455
456 BidirectionalStreamRequestInfo request_info;
457 request_info.method = "POST";
458 request_info.url = default_url_;
459 request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
460 base::SizeTToString(kBodyDataSize * 3));
461
462 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
463 std::unique_ptr<TestDelegateBase> delegate(
464 new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
465 delegate->SetRunUntilCompletion(true);
466 delegate->Start(&request_info, net_log_.bound());
467 sequenced_data_->RunUntilPaused();
468 // Make a write pending before receiving RST_STREAM.
469 scoped_refptr<StringIOBuffer> write_buffer(
470 new StringIOBuffer(std::string(kBodyData, kBodyDataSize)));
471 delegate->SendData(write_buffer.get(), write_buffer->size(), false);
472 sequenced_data_->Resume();
473 base::RunLoop().RunUntilIdle();
474
475 // Make sure OnClose() without an error completes any pending write().
476 EXPECT_EQ(1, delegate->on_data_sent_count());
477 EXPECT_FALSE(delegate->on_failed_called());
478
479 if (is_test_sendv) {
480 std::vector<scoped_refptr<IOBuffer>> three_buffers = {
481 write_buffer.get(), write_buffer.get(), write_buffer.get()};
482 std::vector<int> three_lengths = {
483 write_buffer->size(), write_buffer->size(), write_buffer->size()};
484 delegate->SendvData(three_buffers, three_lengths, /*end_of_stream=*/true);
485 base::RunLoop().RunUntilIdle();
486 } else {
487 for (size_t j = 0; j < 3; j++) {
488 delegate->SendData(write_buffer.get(), write_buffer->size(),
489 /*end_of_stream=*/j == 2);
490 base::RunLoop().RunUntilIdle();
491 }
492 }
493 delegate->WaitUntilCompletion();
494 LoadTimingInfo load_timing_info;
495 EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
496 TestLoadTimingNotReused(load_timing_info);
497
498 EXPECT_THAT(delegate->error(), IsError(OK));
499 EXPECT_EQ(1, delegate->on_data_read_count());
500 EXPECT_EQ(is_test_sendv ? 2 : 4, delegate->on_data_sent_count());
501 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
502 EXPECT_EQ(CountWriteBytes(writes, 1), delegate->GetTotalSentBytes());
503 // Should not count RST stream.
504 EXPECT_EQ(CountReadBytes(reads, arraysize(reads) - 2),
505 delegate->GetTotalReceivedBytes());
506
507 // Now call SendData again should produce an error because end of stream
508 // flag has been written.
509 if (is_test_sendv) {
510 std::vector<scoped_refptr<IOBuffer>> buffer = {write_buffer.get()};
511 std::vector<int> buffer_size = {write_buffer->size()};
512 delegate->SendvData(buffer, buffer_size, true);
513 } else {
514 delegate->SendData(write_buffer.get(), write_buffer->size(), true);
515 }
516 base::RunLoop().RunUntilIdle();
517 EXPECT_THAT(delegate->error(), IsError(ERR_UNEXPECTED));
518 EXPECT_TRUE(delegate->on_failed_called());
519 EXPECT_EQ(is_test_sendv ? 2 : 4, delegate->on_data_sent_count());
520}
521
xunjieli707f8952016-06-06 15:22:06522} // namespace net