Chromium Code Reviews| Index: net/spdy/spdy_stream_unittest.cc |
| diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc |
| index b87634f5c2ce26ad87b585c253e6824b8302e8f0..ee6a287e46bc861b46079107312ae84f7df75fe6 100644 |
| --- a/net/spdy/spdy_stream_unittest.cc |
| +++ b/net/spdy/spdy_stream_unittest.cc |
| @@ -175,6 +175,92 @@ TEST_P(SpdyStreamTest, SendDataAfterOpen) { |
| EXPECT_TRUE(data.AllWriteDataConsumed()); |
| } |
| +// Delegate that receives trailers. |
| +class StreamDelegateWithTrailers : public test::StreamDelegateWithBody { |
| + public: |
| + StreamDelegateWithTrailers(const base::WeakPtr<SpdyStream>& stream, |
| + base::StringPiece data) |
| + : StreamDelegateWithBody(stream, data) {} |
| + |
| + ~StreamDelegateWithTrailers() override {} |
| + |
| + void OnTrailers(const SpdyHeaderBlock& trailers) override { |
| + trailers_ = trailers; |
| + } |
| + |
| + const SpdyHeaderBlock& GetTrailers() { return trailers_; } |
|
Ryan Hamilton
2015/08/10 17:23:25
nit: the style guide would suggest this be called
xunjieli
2015/08/10 20:31:07
Done.
|
| + |
| + private: |
| + SpdyHeaderBlock trailers_; |
| +}; |
| + |
| +// Regression test for crbug.com/481033. |
| +TEST_P(SpdyStreamTest, Trailers) { |
| + 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> msg( |
| + spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, true)); |
| + AddWrite(*msg); |
| + |
| + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); |
| + AddRead(*resp); |
| + |
| + scoped_ptr<SpdyFrame> echo( |
| + spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false)); |
| + AddRead(*echo); |
| + |
| + const char* const kExtraHeaders[] = {"foo", "bar"}; |
| + scoped_ptr<SpdyFrame> trailers( |
| + spdy_util_.ConstructSpdyHeaderFrame(1, kExtraHeaders, 1)); |
| + AddRead(*trailers); |
| + |
| + 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); |
| + |
| + StreamDelegateWithTrailers 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(GetNumReads() + GetNumWrites()); |
| + EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); |
|
Ryan Hamilton
2015/08/10 17:23:25
If the last IO state is the read of EOF, it would
|
| + |
| + EXPECT_TRUE(delegate.send_headers_completed()); |
| + EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
| + const SpdyHeaderBlock& received_trailers = delegate.GetTrailers(); |
| + SpdyHeaderBlock::const_iterator it = received_trailers.find("foo"); |
| + EXPECT_EQ("bar", it->second); |
| + EXPECT_EQ(std::string(kPostBody, kPostBodyLength), |
| + delegate.TakeReceivedData()); |
| + EXPECT_TRUE(data.AllWriteDataConsumed()); |
| +} |
| + |
| TEST_P(SpdyStreamTest, PushedStream) { |
| session_ = |
| SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); |