| Index: net/spdy/bidirectional_stream_spdy_impl_unittest.cc
|
| diff --git a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
|
| deleted file mode 100644
|
| index a37ad01336641ed7b101ca9d606f6b06e82abcc6..0000000000000000000000000000000000000000
|
| --- a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
|
| +++ /dev/null
|
| @@ -1,520 +0,0 @@
|
| -// Copyright 2016 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/spdy/bidirectional_stream_spdy_impl.h"
|
| -
|
| -#include <memory>
|
| -
|
| -#include "base/macros.h"
|
| -#include "base/memory/ptr_util.h"
|
| -#include "base/run_loop.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "base/time/time.h"
|
| -#include "base/timer/mock_timer.h"
|
| -#include "net/base/load_timing_info.h"
|
| -#include "net/base/load_timing_info_test_util.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/http/http_request_info.h"
|
| -#include "net/http/http_response_headers.h"
|
| -#include "net/http/http_response_info.h"
|
| -#include "net/log/test_net_log.h"
|
| -#include "net/socket/socket_test_util.h"
|
| -#include "net/spdy/platform/api/spdy_string.h"
|
| -#include "net/spdy/spdy_session.h"
|
| -#include "net/spdy/spdy_test_util_common.h"
|
| -#include "net/test/cert_test_util.h"
|
| -#include "net/test/gtest_util.h"
|
| -#include "net/test/test_data_directory.h"
|
| -#include "testing/gmock/include/gmock/gmock.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -using net::test::IsError;
|
| -using net::test::IsOk;
|
| -
|
| -namespace net {
|
| -
|
| -namespace {
|
| -
|
| -const char kBodyData[] = "Body data";
|
| -const size_t kBodyDataSize = arraysize(kBodyData);
|
| -// Size of the buffer to be allocated for each read.
|
| -const size_t kReadBufferSize = 4096;
|
| -
|
| -// Tests the load timing of a stream that's connected and is not the first
|
| -// request sent on a connection.
|
| -void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
|
| - EXPECT_TRUE(load_timing_info.socket_reused);
|
| - EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
|
| -
|
| - ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
|
| - ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
|
| -}
|
| -
|
| -// Tests the load timing of a stream that's connected and using a fresh
|
| -// connection.
|
| -void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info) {
|
| - EXPECT_FALSE(load_timing_info.socket_reused);
|
| - EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
|
| -
|
| - ExpectConnectTimingHasTimes(
|
| - load_timing_info.connect_timing,
|
| - CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
|
| - ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
|
| -}
|
| -
|
| -class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
|
| - public:
|
| - TestDelegateBase(base::WeakPtr<SpdySession> session,
|
| - IOBuffer* read_buf,
|
| - int read_buf_len)
|
| - : stream_(new BidirectionalStreamSpdyImpl(session, NetLogSource())),
|
| - read_buf_(read_buf),
|
| - read_buf_len_(read_buf_len),
|
| - loop_(nullptr),
|
| - error_(OK),
|
| - bytes_read_(0),
|
| - on_data_read_count_(0),
|
| - on_data_sent_count_(0),
|
| - do_not_start_read_(false),
|
| - run_until_completion_(false),
|
| - not_expect_callback_(false),
|
| - on_failed_called_(false) {}
|
| -
|
| - ~TestDelegateBase() override {}
|
| -
|
| - void OnStreamReady(bool request_headers_sent) override {
|
| - CHECK(!on_failed_called_);
|
| - }
|
| -
|
| - void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
|
| - CHECK(!on_failed_called_);
|
| - CHECK(!not_expect_callback_);
|
| - response_headers_ = response_headers.Clone();
|
| - if (!do_not_start_read_)
|
| - StartOrContinueReading();
|
| - }
|
| -
|
| - void OnDataRead(int bytes_read) override {
|
| - CHECK(!on_failed_called_);
|
| - CHECK(!not_expect_callback_);
|
| - on_data_read_count_++;
|
| - CHECK_GE(bytes_read, OK);
|
| - bytes_read_ += bytes_read;
|
| - data_received_.append(read_buf_->data(), bytes_read);
|
| - if (!do_not_start_read_)
|
| - StartOrContinueReading();
|
| - }
|
| -
|
| - void OnDataSent() override {
|
| - CHECK(!on_failed_called_);
|
| - CHECK(!not_expect_callback_);
|
| - on_data_sent_count_++;
|
| - }
|
| -
|
| - void OnTrailersReceived(const SpdyHeaderBlock& trailers) override {
|
| - CHECK(!on_failed_called_);
|
| - trailers_ = trailers.Clone();
|
| - if (run_until_completion_)
|
| - loop_->Quit();
|
| - }
|
| -
|
| - void OnFailed(int error) override {
|
| - CHECK(!on_failed_called_);
|
| - CHECK(!not_expect_callback_);
|
| - CHECK_NE(OK, error);
|
| - error_ = error;
|
| - on_failed_called_ = true;
|
| - if (run_until_completion_)
|
| - loop_->Quit();
|
| - }
|
| -
|
| - void Start(const BidirectionalStreamRequestInfo* request,
|
| - const NetLogWithSource& net_log) {
|
| - stream_->Start(request, net_log,
|
| - /*send_request_headers_automatically=*/false, this,
|
| - base::MakeUnique<base::Timer>(false, false));
|
| - not_expect_callback_ = false;
|
| - }
|
| -
|
| - void SendData(IOBuffer* data, int length, bool end_of_stream) {
|
| - not_expect_callback_ = true;
|
| - stream_->SendData(data, length, end_of_stream);
|
| - not_expect_callback_ = false;
|
| - }
|
| -
|
| - void SendvData(const std::vector<scoped_refptr<IOBuffer>>& data,
|
| - const std::vector<int>& length,
|
| - bool end_of_stream) {
|
| - not_expect_callback_ = true;
|
| - stream_->SendvData(data, length, end_of_stream);
|
| - not_expect_callback_ = false;
|
| - }
|
| -
|
| - // Sets whether the delegate should wait until the completion of the stream.
|
| - void SetRunUntilCompletion(bool run_until_completion) {
|
| - run_until_completion_ = run_until_completion;
|
| - loop_.reset(new base::RunLoop);
|
| - }
|
| -
|
| - // Wait until the stream reaches completion.
|
| - void WaitUntilCompletion() { loop_->Run(); }
|
| -
|
| - // Starts or continues read data from |stream_| until there is no more
|
| - // byte can be read synchronously.
|
| - void StartOrContinueReading() {
|
| - int rv = ReadData();
|
| - while (rv > 0) {
|
| - rv = ReadData();
|
| - }
|
| - if (run_until_completion_ && rv == 0)
|
| - loop_->Quit();
|
| - }
|
| -
|
| - // Calls ReadData on the |stream_| and updates internal states.
|
| - int ReadData() {
|
| - int rv = stream_->ReadData(read_buf_.get(), read_buf_len_);
|
| - if (rv > 0) {
|
| - data_received_.append(read_buf_->data(), rv);
|
| - bytes_read_ += rv;
|
| - }
|
| - return rv;
|
| - }
|
| -
|
| - NextProto GetProtocol() const { return stream_->GetProtocol(); }
|
| -
|
| - int64_t GetTotalReceivedBytes() const {
|
| - return stream_->GetTotalReceivedBytes();
|
| - }
|
| -
|
| - int64_t GetTotalSentBytes() const {
|
| - return stream_->GetTotalSentBytes();
|
| - }
|
| -
|
| - bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
|
| - return stream_->GetLoadTimingInfo(load_timing_info);
|
| - }
|
| -
|
| - // Const getters for internal states.
|
| - const SpdyString& data_received() const { return data_received_; }
|
| - int bytes_read() const { return bytes_read_; }
|
| - int error() const { return error_; }
|
| - const SpdyHeaderBlock& response_headers() const { return response_headers_; }
|
| - const SpdyHeaderBlock& trailers() const { return trailers_; }
|
| - int on_data_read_count() const { return on_data_read_count_; }
|
| - int on_data_sent_count() const { return on_data_sent_count_; }
|
| - bool on_failed_called() const { return on_failed_called_; }
|
| -
|
| - // Sets whether the delegate should automatically start reading.
|
| - void set_do_not_start_read(bool do_not_start_read) {
|
| - do_not_start_read_ = do_not_start_read;
|
| - }
|
| -
|
| - private:
|
| - std::unique_ptr<BidirectionalStreamSpdyImpl> stream_;
|
| - scoped_refptr<IOBuffer> read_buf_;
|
| - int read_buf_len_;
|
| - SpdyString data_received_;
|
| - std::unique_ptr<base::RunLoop> loop_;
|
| - SpdyHeaderBlock response_headers_;
|
| - SpdyHeaderBlock trailers_;
|
| - int error_;
|
| - int bytes_read_;
|
| - int on_data_read_count_;
|
| - int on_data_sent_count_;
|
| - bool do_not_start_read_;
|
| - bool run_until_completion_;
|
| - bool not_expect_callback_;
|
| - bool on_failed_called_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(TestDelegateBase);
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -class BidirectionalStreamSpdyImplTest : public testing::TestWithParam<bool> {
|
| - public:
|
| - BidirectionalStreamSpdyImplTest()
|
| - : default_url_(kDefaultUrl),
|
| - host_port_pair_(HostPortPair::FromURL(default_url_)),
|
| - key_(host_port_pair_, ProxyServer::Direct(), PRIVACY_MODE_DISABLED),
|
| - ssl_data_(SSLSocketDataProvider(ASYNC, OK)) {
|
| - ssl_data_.next_proto = kProtoHTTP2;
|
| - ssl_data_.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
|
| - }
|
| -
|
| - protected:
|
| - void TearDown() override {
|
| - if (sequenced_data_) {
|
| - EXPECT_TRUE(sequenced_data_->AllReadDataConsumed());
|
| - EXPECT_TRUE(sequenced_data_->AllWriteDataConsumed());
|
| - }
|
| - }
|
| -
|
| - // Initializes the session using SequencedSocketData.
|
| - void InitSession(MockRead* reads,
|
| - size_t reads_count,
|
| - MockWrite* writes,
|
| - size_t writes_count) {
|
| - ASSERT_TRUE(ssl_data_.cert.get());
|
| - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data_);
|
| - sequenced_data_.reset(
|
| - new SequencedSocketData(reads, reads_count, writes, writes_count));
|
| - session_deps_.socket_factory->AddSocketDataProvider(sequenced_data_.get());
|
| - session_deps_.net_log = net_log_.bound().net_log();
|
| - http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
|
| - session_ =
|
| - CreateSecureSpdySession(http_session_.get(), key_, net_log_.bound());
|
| - }
|
| -
|
| - BoundTestNetLog net_log_;
|
| - SpdyTestUtil spdy_util_;
|
| - SpdySessionDependencies session_deps_;
|
| - const GURL default_url_;
|
| - const HostPortPair host_port_pair_;
|
| - const SpdySessionKey key_;
|
| - std::unique_ptr<SequencedSocketData> sequenced_data_;
|
| - std::unique_ptr<HttpNetworkSession> http_session_;
|
| - base::WeakPtr<SpdySession> session_;
|
| -
|
| - private:
|
| - SSLSocketDataProvider ssl_data_;
|
| -};
|
| -
|
| -TEST_F(BidirectionalStreamSpdyImplTest, SimplePostRequest) {
|
| - SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
|
| - kDefaultUrl, 1, kBodyDataSize, LOW, nullptr, 0));
|
| - SpdySerializedFrame data_frame(spdy_util_.ConstructSpdyDataFrame(
|
| - 1, kBodyData, kBodyDataSize, /*fin=*/true));
|
| - MockWrite writes[] = {
|
| - CreateMockWrite(req, 0), CreateMockWrite(data_frame, 3),
|
| - };
|
| - SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
|
| - SpdySerializedFrame response_body_frame(
|
| - spdy_util_.ConstructSpdyDataFrame(1, /*fin=*/true));
|
| - MockRead reads[] = {
|
| - CreateMockRead(resp, 1),
|
| - MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
|
| - CreateMockRead(response_body_frame, 4), MockRead(ASYNC, 0, 5),
|
| - };
|
| - InitSession(reads, arraysize(reads), writes, arraysize(writes));
|
| -
|
| - BidirectionalStreamRequestInfo request_info;
|
| - request_info.method = "POST";
|
| - request_info.url = default_url_;
|
| - request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
|
| - base::SizeTToString(kBodyDataSize));
|
| -
|
| - scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
|
| - std::unique_ptr<TestDelegateBase> delegate(
|
| - new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
|
| - delegate->SetRunUntilCompletion(true);
|
| - delegate->Start(&request_info, net_log_.bound());
|
| - sequenced_data_->RunUntilPaused();
|
| -
|
| - scoped_refptr<StringIOBuffer> write_buffer(
|
| - new StringIOBuffer(SpdyString(kBodyData, kBodyDataSize)));
|
| - delegate->SendData(write_buffer.get(), write_buffer->size(), true);
|
| - sequenced_data_->Resume();
|
| - base::RunLoop().RunUntilIdle();
|
| - delegate->WaitUntilCompletion();
|
| - LoadTimingInfo load_timing_info;
|
| - EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
|
| - TestLoadTimingNotReused(load_timing_info);
|
| -
|
| - EXPECT_EQ(1, delegate->on_data_read_count());
|
| - EXPECT_EQ(1, delegate->on_data_sent_count());
|
| - EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
|
| - EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
|
| - delegate->GetTotalSentBytes());
|
| - EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
|
| - delegate->GetTotalReceivedBytes());
|
| -}
|
| -
|
| -TEST_F(BidirectionalStreamSpdyImplTest, LoadTimingTwoRequests) {
|
| - SpdySerializedFrame req(
|
| - spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/1, LOW, true));
|
| - SpdySerializedFrame req2(
|
| - spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/3, LOW, true));
|
| - MockWrite writes[] = {
|
| - CreateMockWrite(req, 0), CreateMockWrite(req2, 2),
|
| - };
|
| - SpdySerializedFrame resp(
|
| - spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/1));
|
| - SpdySerializedFrame resp2(
|
| - spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/3));
|
| - SpdySerializedFrame resp_body(
|
| - spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/1, /*fin=*/true));
|
| - SpdySerializedFrame resp_body2(
|
| - spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/3, /*fin=*/true));
|
| - MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(resp_body, 3),
|
| - CreateMockRead(resp2, 4), CreateMockRead(resp_body2, 5),
|
| - MockRead(ASYNC, 0, 6)};
|
| - InitSession(reads, arraysize(reads), writes, arraysize(writes));
|
| -
|
| - BidirectionalStreamRequestInfo request_info;
|
| - request_info.method = "GET";
|
| - request_info.url = default_url_;
|
| - request_info.end_stream_on_headers = true;
|
| -
|
| - scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
|
| - scoped_refptr<IOBuffer> read_buffer2(new IOBuffer(kReadBufferSize));
|
| - std::unique_ptr<TestDelegateBase> delegate(
|
| - new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
|
| - std::unique_ptr<TestDelegateBase> delegate2(
|
| - new TestDelegateBase(session_, read_buffer2.get(), kReadBufferSize));
|
| - delegate->SetRunUntilCompletion(true);
|
| - delegate2->SetRunUntilCompletion(true);
|
| - delegate->Start(&request_info, net_log_.bound());
|
| - delegate2->Start(&request_info, net_log_.bound());
|
| -
|
| - base::RunLoop().RunUntilIdle();
|
| - delegate->WaitUntilCompletion();
|
| - delegate2->WaitUntilCompletion();
|
| - LoadTimingInfo load_timing_info;
|
| - EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
|
| - TestLoadTimingNotReused(load_timing_info);
|
| - LoadTimingInfo load_timing_info2;
|
| - EXPECT_TRUE(delegate2->GetLoadTimingInfo(&load_timing_info2));
|
| - TestLoadTimingReused(load_timing_info2);
|
| -}
|
| -
|
| -TEST_F(BidirectionalStreamSpdyImplTest, SendDataAfterStreamFailed) {
|
| - SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
|
| - kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0));
|
| - SpdySerializedFrame rst(
|
| - spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR));
|
| -
|
| - MockWrite writes[] = {
|
| - CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
|
| - };
|
| -
|
| - const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
|
| - SpdySerializedFrame resp(
|
| - spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1, 1));
|
| -
|
| - MockRead reads[] = {
|
| - CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3),
|
| - };
|
| -
|
| - InitSession(reads, arraysize(reads), writes, arraysize(writes));
|
| -
|
| - BidirectionalStreamRequestInfo request_info;
|
| - request_info.method = "POST";
|
| - request_info.url = default_url_;
|
| - request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
|
| - base::SizeTToString(kBodyDataSize * 3));
|
| -
|
| - scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
|
| - std::unique_ptr<TestDelegateBase> delegate(
|
| - new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
|
| - delegate->SetRunUntilCompletion(true);
|
| - delegate->Start(&request_info, net_log_.bound());
|
| - base::RunLoop().RunUntilIdle();
|
| -
|
| - EXPECT_TRUE(delegate->on_failed_called());
|
| -
|
| - // Try to send data after OnFailed(), should not get called back.
|
| - scoped_refptr<StringIOBuffer> buf(new StringIOBuffer("dummy"));
|
| - delegate->SendData(buf.get(), buf->size(), false);
|
| - base::RunLoop().RunUntilIdle();
|
| -
|
| - EXPECT_THAT(delegate->error(), IsError(ERR_SPDY_PROTOCOL_ERROR));
|
| - EXPECT_EQ(0, delegate->on_data_read_count());
|
| - EXPECT_EQ(0, delegate->on_data_sent_count());
|
| - EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
|
| - // BidirectionalStreamSpdyStreamJob does not count the bytes sent for |rst|
|
| - // because it is sent after SpdyStream::Delegate::OnClose is called.
|
| - EXPECT_EQ(CountWriteBytes(writes, 1), delegate->GetTotalSentBytes());
|
| - EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
|
| - delegate->GetTotalReceivedBytes());
|
| -}
|
| -
|
| -INSTANTIATE_TEST_CASE_P(BidirectionalStreamSpdyImplTests,
|
| - BidirectionalStreamSpdyImplTest,
|
| - ::testing::Bool());
|
| -
|
| -// Tests that when received RST_STREAM with NO_ERROR, BidirectionalStream does
|
| -// not crash when processing pending writes. See crbug.com/650438.
|
| -TEST_P(BidirectionalStreamSpdyImplTest, RstWithNoErrorBeforeSendIsComplete) {
|
| - bool is_test_sendv = GetParam();
|
| - SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
|
| - kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0));
|
| - MockWrite writes[] = {CreateMockWrite(req, 0)};
|
| -
|
| - SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
|
| - SpdySerializedFrame rst(
|
| - spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_NO_ERROR));
|
| - MockRead reads[] = {CreateMockRead(resp, 1),
|
| - MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
|
| - CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
|
| -
|
| - InitSession(reads, arraysize(reads), writes, arraysize(writes));
|
| -
|
| - BidirectionalStreamRequestInfo request_info;
|
| - request_info.method = "POST";
|
| - request_info.url = default_url_;
|
| - request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
|
| - base::SizeTToString(kBodyDataSize * 3));
|
| -
|
| - scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
|
| - std::unique_ptr<TestDelegateBase> delegate(
|
| - new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
|
| - delegate->SetRunUntilCompletion(true);
|
| - delegate->Start(&request_info, net_log_.bound());
|
| - sequenced_data_->RunUntilPaused();
|
| - // Make a write pending before receiving RST_STREAM.
|
| - scoped_refptr<StringIOBuffer> write_buffer(
|
| - new StringIOBuffer(SpdyString(kBodyData, kBodyDataSize)));
|
| - delegate->SendData(write_buffer.get(), write_buffer->size(), false);
|
| - sequenced_data_->Resume();
|
| - base::RunLoop().RunUntilIdle();
|
| -
|
| - // Make sure OnClose() without an error completes any pending write().
|
| - EXPECT_EQ(1, delegate->on_data_sent_count());
|
| - EXPECT_FALSE(delegate->on_failed_called());
|
| -
|
| - if (is_test_sendv) {
|
| - std::vector<scoped_refptr<IOBuffer>> three_buffers = {
|
| - write_buffer.get(), write_buffer.get(), write_buffer.get()};
|
| - std::vector<int> three_lengths = {
|
| - write_buffer->size(), write_buffer->size(), write_buffer->size()};
|
| - delegate->SendvData(three_buffers, three_lengths, /*end_of_stream=*/true);
|
| - base::RunLoop().RunUntilIdle();
|
| - } else {
|
| - for (size_t j = 0; j < 3; j++) {
|
| - delegate->SendData(write_buffer.get(), write_buffer->size(),
|
| - /*end_of_stream=*/j == 2);
|
| - base::RunLoop().RunUntilIdle();
|
| - }
|
| - }
|
| - delegate->WaitUntilCompletion();
|
| - LoadTimingInfo load_timing_info;
|
| - EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
|
| - TestLoadTimingNotReused(load_timing_info);
|
| -
|
| - EXPECT_THAT(delegate->error(), IsError(OK));
|
| - EXPECT_EQ(1, delegate->on_data_read_count());
|
| - EXPECT_EQ(is_test_sendv ? 2 : 4, delegate->on_data_sent_count());
|
| - EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
|
| - EXPECT_EQ(CountWriteBytes(writes, 1), delegate->GetTotalSentBytes());
|
| - // Should not count RST stream.
|
| - EXPECT_EQ(CountReadBytes(reads, arraysize(reads) - 2),
|
| - delegate->GetTotalReceivedBytes());
|
| -
|
| - // Now call SendData again should produce an error because end of stream
|
| - // flag has been written.
|
| - if (is_test_sendv) {
|
| - std::vector<scoped_refptr<IOBuffer>> buffer = {write_buffer.get()};
|
| - std::vector<int> buffer_size = {write_buffer->size()};
|
| - delegate->SendvData(buffer, buffer_size, true);
|
| - } else {
|
| - delegate->SendData(write_buffer.get(), write_buffer->size(), true);
|
| - }
|
| - base::RunLoop().RunUntilIdle();
|
| - EXPECT_THAT(delegate->error(), IsError(ERR_UNEXPECTED));
|
| - EXPECT_TRUE(delegate->on_failed_called());
|
| - EXPECT_EQ(is_test_sendv ? 2 : 4, delegate->on_data_sent_count());
|
| -}
|
| -
|
| -} // namespace net
|
|
|