| Index: net/spdy/spdy_stream_unittest.cc
|
| diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc
|
| deleted file mode 100644
|
| index b8638d9be61c66883cf91b96acd3654c336cd666..0000000000000000000000000000000000000000
|
| --- a/net/spdy/spdy_stream_unittest.cc
|
| +++ /dev/null
|
| @@ -1,1040 +0,0 @@
|
| -// Copyright 2013 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 <cstddef>
|
| -#include <string>
|
| -#include <vector>
|
| -
|
| -#include "base/memory/ref_counted.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/stl_util.h"
|
| -#include "base/strings/string_piece.h"
|
| -#include "net/base/completion_callback.h"
|
| -#include "net/base/net_log_unittest.h"
|
| -#include "net/base/request_priority.h"
|
| -#include "net/socket/next_proto.h"
|
| -#include "net/socket/socket_test_util.h"
|
| -#include "net/spdy/buffered_spdy_framer.h"
|
| -#include "net/spdy/spdy_http_utils.h"
|
| -#include "net/spdy/spdy_protocol.h"
|
| -#include "net/spdy/spdy_session.h"
|
| -#include "net/spdy/spdy_stream.h"
|
| -#include "net/spdy/spdy_stream_test_util.h"
|
| -#include "net/spdy/spdy_test_util_common.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -// TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
|
| -//
|
| -namespace net {
|
| -
|
| -namespace test {
|
| -
|
| -namespace {
|
| -
|
| -const char kStreamUrl[] = "http://www.google.com/";
|
| -const char kPostBody[] = "\0hello!\xff";
|
| -const size_t kPostBodyLength = arraysize(kPostBody);
|
| -const base::StringPiece kPostBodyStringPiece(kPostBody, kPostBodyLength);
|
| -
|
| -class SpdyStreamTest : public ::testing::Test,
|
| - public ::testing::WithParamInterface<NextProto> {
|
| - protected:
|
| - // A function that takes a SpdyStream and the number of bytes which
|
| - // will unstall the next frame completely.
|
| - typedef base::Callback<void(const base::WeakPtr<SpdyStream>&, int32)>
|
| - UnstallFunction;
|
| -
|
| - SpdyStreamTest()
|
| - : spdy_util_(GetParam()),
|
| - session_deps_(GetParam()),
|
| - offset_(0) {}
|
| -
|
| - base::WeakPtr<SpdySession> CreateDefaultSpdySession() {
|
| - SpdySessionKey key(HostPortPair("www.google.com", 80),
|
| - ProxyServer::Direct(),
|
| - PRIVACY_MODE_DISABLED);
|
| - return CreateInsecureSpdySession(session_, key, BoundNetLog());
|
| - }
|
| -
|
| - void TearDown() override { base::MessageLoop::current()->RunUntilIdle(); }
|
| -
|
| - void RunResumeAfterUnstallRequestResponseTest(
|
| - const UnstallFunction& unstall_function);
|
| -
|
| - void RunResumeAfterUnstallBidirectionalTest(
|
| - const UnstallFunction& unstall_function);
|
| -
|
| - // Add{Read,Write}() populates lists that are eventually passed to a
|
| - // SocketData class. |frame| must live for the whole test.
|
| -
|
| - void AddRead(const SpdyFrame& frame) {
|
| - reads_.push_back(CreateMockRead(frame, offset_++));
|
| - }
|
| -
|
| - void AddWrite(const SpdyFrame& frame) {
|
| - writes_.push_back(CreateMockWrite(frame, offset_++));
|
| - }
|
| -
|
| - void AddReadEOF() {
|
| - reads_.push_back(MockRead(ASYNC, 0, offset_++));
|
| - }
|
| -
|
| - MockRead* GetReads() {
|
| - return vector_as_array(&reads_);
|
| - }
|
| -
|
| - size_t GetNumReads() const {
|
| - return reads_.size();
|
| - }
|
| -
|
| - MockWrite* GetWrites() {
|
| - return vector_as_array(&writes_);
|
| - }
|
| -
|
| - int GetNumWrites() const {
|
| - return writes_.size();
|
| - }
|
| -
|
| - SpdyTestUtil spdy_util_;
|
| - SpdySessionDependencies session_deps_;
|
| - scoped_refptr<HttpNetworkSession> session_;
|
| -
|
| - private:
|
| - // Used by Add{Read,Write}() above.
|
| - std::vector<MockWrite> writes_;
|
| - std::vector<MockRead> reads_;
|
| - int offset_;
|
| -};
|
| -
|
| -INSTANTIATE_TEST_CASE_P(
|
| - NextProto,
|
| - SpdyStreamTest,
|
| - testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
|
| -
|
| -TEST_P(SpdyStreamTest, SendDataAfterOpen) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> req(
|
| - spdy_util_.ConstructSpdyPost(
|
| - kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
|
| - AddWrite(*req);
|
| -
|
| - scoped_ptr<SpdyFrame> resp(
|
| - spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
|
| - AddRead(*resp);
|
| -
|
| - scoped_ptr<SpdyFrame> msg(
|
| - spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
|
| - AddWrite(*msg);
|
| -
|
| - scoped_ptr<SpdyFrame> echo(
|
| - spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
|
| - AddRead(*echo);
|
| -
|
| - AddReadEOF();
|
| -
|
| - OrderedSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
|
| -
|
| - EXPECT_TRUE(delegate.send_headers_completed());
|
| - EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
|
| - EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
|
| - delegate.TakeReceivedData());
|
| - EXPECT_TRUE(data.at_write_eof());
|
| -}
|
| -
|
| -TEST_P(SpdyStreamTest, PushedStream) {
|
| - session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
|
| -
|
| - AddReadEOF();
|
| -
|
| - OrderedSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> spdy_session(CreateDefaultSpdySession());
|
| -
|
| - // Conjure up a stream.
|
| - SpdyStream stream(SPDY_PUSH_STREAM, spdy_session, GURL(), DEFAULT_PRIORITY,
|
| - SpdySession::GetInitialWindowSize(kProtoSPDY31),
|
| - SpdySession::GetInitialWindowSize(kProtoSPDY31),
|
| - BoundNetLog());
|
| - stream.set_stream_id(2);
|
| - EXPECT_FALSE(stream.HasUrlFromHeaders());
|
| -
|
| - // Set required request headers.
|
| - SpdyHeaderBlock request_headers;
|
| - spdy_util_.AddUrlToHeaderBlock(kStreamUrl, &request_headers);
|
| - stream.OnPushPromiseHeadersReceived(request_headers);
|
| -
|
| - // Send some basic response headers.
|
| - SpdyHeaderBlock response;
|
| - response[spdy_util_.GetStatusKey()] = "200";
|
| - response[spdy_util_.GetVersionKey()] = "OK";
|
| - stream.OnInitialResponseHeadersReceived(
|
| - response, base::Time::Now(), base::TimeTicks::Now());
|
| -
|
| - // And some more headers.
|
| - // TODO(baranovich): not valid for HTTP 2.
|
| - SpdyHeaderBlock headers;
|
| - headers["alpha"] = "beta";
|
| - stream.OnAdditionalResponseHeadersReceived(headers);
|
| -
|
| - EXPECT_TRUE(stream.HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream.GetUrlFromHeaders().spec());
|
| -
|
| - StreamDelegateDoNothing delegate(stream.GetWeakPtr());
|
| - stream.SetDelegate(&delegate);
|
| -
|
| - base::MessageLoop::current()->RunUntilIdle();
|
| -
|
| - EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
|
| - EXPECT_EQ("beta", delegate.GetResponseHeaderValue("alpha"));
|
| -
|
| - EXPECT_TRUE(spdy_session == NULL);
|
| -}
|
| -
|
| -TEST_P(SpdyStreamTest, StreamError) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> req(
|
| - spdy_util_.ConstructSpdyPost(
|
| - kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
|
| - AddWrite(*req);
|
| -
|
| - scoped_ptr<SpdyFrame> resp(
|
| - spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
|
| - AddRead(*resp);
|
| -
|
| - scoped_ptr<SpdyFrame> msg(
|
| - spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
|
| - AddWrite(*msg);
|
| -
|
| - scoped_ptr<SpdyFrame> echo(
|
| - spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
|
| - AddRead(*echo);
|
| -
|
| - AddReadEOF();
|
| -
|
| - CapturingBoundNetLog log;
|
| -
|
| - OrderedSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
|
| -
|
| - const SpdyStreamId stream_id = delegate.stream_id();
|
| -
|
| - EXPECT_TRUE(delegate.send_headers_completed());
|
| - EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
|
| - EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
|
| - delegate.TakeReceivedData());
|
| - EXPECT_TRUE(data.at_write_eof());
|
| -
|
| - // Check that the NetLog was filled reasonably.
|
| - net::CapturingNetLog::CapturedEntryList entries;
|
| - log.GetEntries(&entries);
|
| - EXPECT_LT(0u, entries.size());
|
| -
|
| - // Check that we logged SPDY_STREAM_ERROR correctly.
|
| - int pos = net::ExpectLogContainsSomewhere(
|
| - entries, 0,
|
| - net::NetLog::TYPE_SPDY_STREAM_ERROR,
|
| - net::NetLog::PHASE_NONE);
|
| -
|
| - int stream_id2;
|
| - ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &stream_id2));
|
| - EXPECT_EQ(static_cast<int>(stream_id), stream_id2);
|
| -}
|
| -
|
| -// Make sure that large blocks of data are properly split up into
|
| -// frame-sized chunks for a request/response (i.e., an HTTP-like)
|
| -// stream.
|
| -TEST_P(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> req(
|
| - spdy_util_.ConstructSpdyPost(
|
| - kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
|
| - AddWrite(*req);
|
| -
|
| - std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
|
| - scoped_ptr<SpdyFrame> chunk(
|
| - spdy_util_.ConstructSpdyBodyFrame(
|
| - 1, chunk_data.data(), chunk_data.length(), false));
|
| - AddWrite(*chunk);
|
| - AddWrite(*chunk);
|
| -
|
| - scoped_ptr<SpdyFrame> last_chunk(
|
| - spdy_util_.ConstructSpdyBodyFrame(
|
| - 1, chunk_data.data(), chunk_data.length(), true));
|
| - AddWrite(*last_chunk);
|
| -
|
| - scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
|
| - AddRead(*resp);
|
| -
|
| - AddReadEOF();
|
| -
|
| - OrderedSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
|
| - StreamDelegateWithBody delegate(stream, body_data);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
|
| -
|
| - EXPECT_TRUE(delegate.send_headers_completed());
|
| - EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
|
| - EXPECT_EQ(std::string(), delegate.TakeReceivedData());
|
| - EXPECT_TRUE(data.at_write_eof());
|
| -}
|
| -
|
| -// Make sure that large blocks of data are properly split up into
|
| -// frame-sized chunks for a bidirectional (i.e., non-HTTP-like)
|
| -// stream.
|
| -TEST_P(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> req(
|
| - spdy_util_.ConstructSpdyPost(
|
| - kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
|
| - AddWrite(*req);
|
| -
|
| - scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
|
| - AddRead(*resp);
|
| -
|
| - std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
|
| - scoped_ptr<SpdyFrame> chunk(
|
| - spdy_util_.ConstructSpdyBodyFrame(
|
| - 1, chunk_data.data(), chunk_data.length(), false));
|
| - AddWrite(*chunk);
|
| - AddWrite(*chunk);
|
| - AddWrite(*chunk);
|
| -
|
| - AddReadEOF();
|
| -
|
| - OrderedSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
|
| - StreamDelegateSendImmediate delegate(stream, body_data);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
|
| -
|
| - EXPECT_TRUE(delegate.send_headers_completed());
|
| - EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
|
| - EXPECT_EQ(std::string(), delegate.TakeReceivedData());
|
| - EXPECT_TRUE(data.at_write_eof());
|
| -}
|
| -
|
| -// Receiving a header with uppercase ASCII should result in a protocol
|
| -// error.
|
| -TEST_P(SpdyStreamTest, UpperCaseHeaders) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ =
|
| - SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> syn(
|
| - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
|
| - AddWrite(*syn);
|
| -
|
| - const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
|
| - scoped_ptr<SpdyFrame>
|
| - reply(spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
|
| - AddRead(*reply);
|
| -
|
| - scoped_ptr<SpdyFrame> rst(
|
| - spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
|
| - AddWrite(*rst);
|
| -
|
| - AddReadEOF();
|
| -
|
| - DeterministicSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - StreamDelegateDoNothing delegate(stream);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - data.RunFor(4);
|
| -
|
| - EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
|
| -}
|
| -
|
| -// Receiving a header with uppercase ASCII should result in a protocol
|
| -// error even for a push stream.
|
| -TEST_P(SpdyStreamTest, UpperCaseHeadersOnPush) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ =
|
| - SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> syn(
|
| - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
|
| - AddWrite(*syn);
|
| -
|
| - scoped_ptr<SpdyFrame>
|
| - reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
|
| - AddRead(*reply);
|
| -
|
| - const char* const extra_headers[] = {"X-UpperCase", "yes"};
|
| - scoped_ptr<SpdyFrame>
|
| - push(spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kStreamUrl));
|
| - AddRead(*push);
|
| -
|
| - scoped_ptr<SpdyFrame> rst(
|
| - spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
|
| - AddWrite(*rst);
|
| -
|
| - AddReadEOF();
|
| -
|
| - DeterministicSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - StreamDelegateDoNothing delegate(stream);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - data.RunFor(4);
|
| -
|
| - base::WeakPtr<SpdyStream> push_stream;
|
| - EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
|
| - EXPECT_FALSE(push_stream);
|
| -
|
| - data.RunFor(1);
|
| -
|
| - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
|
| -}
|
| -
|
| -// Receiving a header with uppercase ASCII in a HEADERS frame should
|
| -// result in a protocol error.
|
| -TEST_P(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ =
|
| - SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> syn(
|
| - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
|
| - AddWrite(*syn);
|
| -
|
| - scoped_ptr<SpdyFrame>
|
| - reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
|
| - AddRead(*reply);
|
| -
|
| - scoped_ptr<SpdyFrame>
|
| - push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
|
| - AddRead(*push);
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
|
| - (*late_headers)["X-UpperCase"] = "yes";
|
| - scoped_ptr<SpdyFrame> headers_frame(
|
| - spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
|
| - false,
|
| - 2,
|
| - LOWEST,
|
| - HEADERS,
|
| - CONTROL_FLAG_NONE,
|
| - 0));
|
| - AddRead(*headers_frame);
|
| -
|
| - scoped_ptr<SpdyFrame> rst(
|
| - spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
|
| - AddWrite(*rst);
|
| -
|
| - AddReadEOF();
|
| -
|
| - DeterministicSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - StreamDelegateDoNothing delegate(stream);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - data.RunFor(3);
|
| -
|
| - base::WeakPtr<SpdyStream> push_stream;
|
| - EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
|
| - EXPECT_TRUE(push_stream);
|
| -
|
| - data.RunFor(1);
|
| -
|
| - EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
|
| - EXPECT_FALSE(push_stream);
|
| -
|
| - data.RunFor(2);
|
| -
|
| - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
|
| -}
|
| -
|
| -// Receiving a duplicate header in a HEADERS frame should result in a
|
| -// protocol error.
|
| -TEST_P(SpdyStreamTest, DuplicateHeaders) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ =
|
| - SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> syn(
|
| - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
|
| - AddWrite(*syn);
|
| -
|
| - scoped_ptr<SpdyFrame>
|
| - reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
|
| - AddRead(*reply);
|
| -
|
| - scoped_ptr<SpdyFrame>
|
| - push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
|
| - AddRead(*push);
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
|
| - (*late_headers)[spdy_util_.GetStatusKey()] = "500 Server Error";
|
| - scoped_ptr<SpdyFrame> headers_frame(
|
| - spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
|
| - false,
|
| - 2,
|
| - LOWEST,
|
| - HEADERS,
|
| - CONTROL_FLAG_NONE,
|
| - 0));
|
| - AddRead(*headers_frame);
|
| -
|
| - scoped_ptr<SpdyFrame> rst(
|
| - spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
|
| - AddWrite(*rst);
|
| -
|
| - AddReadEOF();
|
| -
|
| - DeterministicSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - StreamDelegateDoNothing delegate(stream);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - data.RunFor(3);
|
| -
|
| - base::WeakPtr<SpdyStream> push_stream;
|
| - EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
|
| - EXPECT_TRUE(push_stream);
|
| -
|
| - data.RunFor(1);
|
| -
|
| - EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
|
| - EXPECT_FALSE(push_stream);
|
| -
|
| - data.RunFor(2);
|
| -
|
| - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
|
| -}
|
| -
|
| -// The tests below are only for SPDY/3 and above.
|
| -
|
| -// Call IncreaseSendWindowSize on a stream with a large enough delta
|
| -// to overflow an int32. The SpdyStream should handle that case
|
| -// gracefully.
|
| -TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
|
| - session_ =
|
| - SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> req(
|
| - spdy_util_.ConstructSpdyPost(
|
| - kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
|
| - AddWrite(*req);
|
| -
|
| - // Triggered by the overflowing call to IncreaseSendWindowSize
|
| - // below.
|
| - scoped_ptr<SpdyFrame> rst(
|
| - spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
|
| - AddWrite(*rst);
|
| -
|
| - AddReadEOF();
|
| -
|
| - CapturingBoundNetLog log;
|
| -
|
| - DeterministicSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| - GURL url(kStreamUrl);
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| - StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - data.RunFor(1);
|
| -
|
| - int32 old_send_window_size = stream->send_window_size();
|
| - ASSERT_GT(old_send_window_size, 0);
|
| - int32 delta_window_size = kint32max - old_send_window_size + 1;
|
| - stream->IncreaseSendWindowSize(delta_window_size);
|
| - EXPECT_EQ(NULL, stream.get());
|
| -
|
| - data.RunFor(2);
|
| -
|
| - EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
|
| -}
|
| -
|
| -// Functions used with
|
| -// RunResumeAfterUnstall{RequestResponse,Bidirectional}Test().
|
| -
|
| -void StallStream(const base::WeakPtr<SpdyStream>& stream) {
|
| - // Reduce the send window size to 0 to stall.
|
| - while (stream->send_window_size() > 0) {
|
| - stream->DecreaseSendWindowSize(
|
| - std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
|
| - }
|
| -}
|
| -
|
| -void IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
|
| - int32 delta_window_size) {
|
| - EXPECT_TRUE(stream->send_stalled_by_flow_control());
|
| - stream->IncreaseSendWindowSize(delta_window_size);
|
| - EXPECT_FALSE(stream->send_stalled_by_flow_control());
|
| -}
|
| -
|
| -void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
|
| - int32 delta_window_size) {
|
| - // Make sure that negative adjustments are handled properly.
|
| - EXPECT_TRUE(stream->send_stalled_by_flow_control());
|
| - stream->AdjustSendWindowSize(-delta_window_size);
|
| - EXPECT_TRUE(stream->send_stalled_by_flow_control());
|
| - stream->AdjustSendWindowSize(+delta_window_size);
|
| - EXPECT_TRUE(stream->send_stalled_by_flow_control());
|
| - stream->AdjustSendWindowSize(+delta_window_size);
|
| - EXPECT_FALSE(stream->send_stalled_by_flow_control());
|
| -}
|
| -
|
| -// Given an unstall function, runs a test to make sure that a
|
| -// request/response (i.e., an HTTP-like) stream resumes after a stall
|
| -// and unstall.
|
| -void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
|
| - const UnstallFunction& unstall_function) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ =
|
| - SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> req(
|
| - spdy_util_.ConstructSpdyPost(
|
| - kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
|
| - AddWrite(*req);
|
| -
|
| - scoped_ptr<SpdyFrame> body(
|
| - spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, true));
|
| - AddWrite(*body);
|
| -
|
| - scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
|
| - AddRead(*resp);
|
| -
|
| - AddReadEOF();
|
| -
|
| - DeterministicSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - StreamDelegateWithBody delegate(stream, kPostBodyStringPiece);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| - EXPECT_FALSE(stream->send_stalled_by_flow_control());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - StallStream(stream);
|
| -
|
| - data.RunFor(1);
|
| -
|
| - EXPECT_TRUE(stream->send_stalled_by_flow_control());
|
| -
|
| - unstall_function.Run(stream, kPostBodyLength);
|
| -
|
| - EXPECT_FALSE(stream->send_stalled_by_flow_control());
|
| -
|
| - data.RunFor(3);
|
| -
|
| - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
|
| -
|
| - EXPECT_TRUE(delegate.send_headers_completed());
|
| - EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
|
| - EXPECT_EQ(std::string(), delegate.TakeReceivedData());
|
| - EXPECT_TRUE(data.at_write_eof());
|
| -}
|
| -
|
| -TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) {
|
| - RunResumeAfterUnstallRequestResponseTest(
|
| - base::Bind(&IncreaseStreamSendWindowSize));
|
| -}
|
| -
|
| -TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) {
|
| - RunResumeAfterUnstallRequestResponseTest(
|
| - base::Bind(&AdjustStreamSendWindowSize));
|
| -}
|
| -
|
| -// Given an unstall function, runs a test to make sure that a
|
| -// bidirectional (i.e., non-HTTP-like) stream resumes after a stall
|
| -// and unstall.
|
| -void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
|
| - const UnstallFunction& unstall_function) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ =
|
| - SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> req(
|
| - spdy_util_.ConstructSpdyPost(
|
| - kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
|
| - AddWrite(*req);
|
| -
|
| - scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
|
| - AddRead(*resp);
|
| -
|
| - scoped_ptr<SpdyFrame> msg(
|
| - spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
|
| - AddWrite(*msg);
|
| -
|
| - scoped_ptr<SpdyFrame> echo(
|
| - spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
|
| - AddRead(*echo);
|
| -
|
| - AddReadEOF();
|
| -
|
| - DeterministicSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - data.RunFor(1);
|
| -
|
| - EXPECT_FALSE(stream->send_stalled_by_flow_control());
|
| -
|
| - StallStream(stream);
|
| -
|
| - data.RunFor(1);
|
| -
|
| - EXPECT_TRUE(stream->send_stalled_by_flow_control());
|
| -
|
| - unstall_function.Run(stream, kPostBodyLength);
|
| -
|
| - EXPECT_FALSE(stream->send_stalled_by_flow_control());
|
| -
|
| - data.RunFor(3);
|
| -
|
| - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
|
| -
|
| - EXPECT_TRUE(delegate.send_headers_completed());
|
| - EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
|
| - EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
|
| - delegate.TakeReceivedData());
|
| - EXPECT_TRUE(data.at_write_eof());
|
| -}
|
| -
|
| -TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) {
|
| - RunResumeAfterUnstallBidirectionalTest(
|
| - base::Bind(&IncreaseStreamSendWindowSize));
|
| -}
|
| -
|
| -TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
|
| - RunResumeAfterUnstallBidirectionalTest(
|
| - base::Bind(&AdjustStreamSendWindowSize));
|
| -}
|
| -
|
| -// Test calculation of amount of bytes received from network.
|
| -TEST_P(SpdyStreamTest, ReceivedBytes) {
|
| - GURL url(kStreamUrl);
|
| -
|
| - session_ =
|
| - SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
|
| -
|
| - scoped_ptr<SpdyFrame> syn(
|
| - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
|
| - AddWrite(*syn);
|
| -
|
| - scoped_ptr<SpdyFrame>
|
| - reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
|
| - AddRead(*reply);
|
| -
|
| - scoped_ptr<SpdyFrame> msg(
|
| - spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
|
| - AddRead(*msg);
|
| -
|
| - AddReadEOF();
|
| -
|
| - DeterministicSocketData data(GetReads(), GetNumReads(),
|
| - GetWrites(), GetNumWrites());
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - data.set_connect_data(connect_data);
|
| -
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
|
| -
|
| - base::WeakPtr<SpdyStream> stream =
|
| - CreateStreamSynchronously(
|
| - SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
|
| - ASSERT_TRUE(stream.get() != NULL);
|
| -
|
| - StreamDelegateDoNothing delegate(stream);
|
| - stream->SetDelegate(&delegate);
|
| -
|
| - EXPECT_FALSE(stream->HasUrlFromHeaders());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(
|
| - spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
|
| - EXPECT_EQ(ERR_IO_PENDING,
|
| - stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
|
| - EXPECT_TRUE(stream->HasUrlFromHeaders());
|
| - EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
|
| -
|
| - int64 reply_frame_len = reply->size();
|
| - int64 data_header_len = spdy_util_.CreateFramer(false)
|
| - ->GetDataFrameMinimumSize();
|
| - int64 data_frame_len = data_header_len + kPostBodyLength;
|
| - int64 response_len = reply_frame_len + data_frame_len;
|
| -
|
| - EXPECT_EQ(0, stream->raw_received_bytes());
|
| - data.RunFor(1); // SYN
|
| - EXPECT_EQ(0, stream->raw_received_bytes());
|
| - data.RunFor(1); // REPLY
|
| - EXPECT_EQ(reply_frame_len, stream->raw_received_bytes());
|
| - data.RunFor(1); // DATA
|
| - EXPECT_EQ(response_len, stream->raw_received_bytes());
|
| - data.RunFor(1); // FIN
|
| -
|
| - EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -} // namespace test
|
| -
|
| -} // namespace net
|
|
|