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 50b2a1bd65d3948947d2d1400c7f5dd38358d915..0000000000000000000000000000000000000000 |
--- a/net/spdy/spdy_stream_unittest.cc |
+++ /dev/null |
@@ -1,1560 +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 "net/spdy/spdy_stream.h" |
- |
-#include <stdint.h> |
- |
-#include <algorithm> |
-#include <cstddef> |
-#include <limits> |
-#include <memory> |
-#include <utility> |
-#include <vector> |
- |
-#include "base/memory/ref_counted.h" |
-#include "base/run_loop.h" |
-#include "net/base/completion_callback.h" |
-#include "net/base/request_priority.h" |
-#include "net/log/net_log_event_type.h" |
-#include "net/log/test_net_log.h" |
-#include "net/log/test_net_log_entry.h" |
-#include "net/log/test_net_log_util.h" |
-#include "net/socket/socket_test_util.h" |
-#include "net/spdy/buffered_spdy_framer.h" |
-#include "net/spdy/platform/api/spdy_string_piece.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_test_util.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" |
- |
-// TODO(ukai): factor out common part with spdy_http_stream_unittest.cc |
-// |
-namespace net { |
- |
-namespace test { |
- |
-namespace { |
- |
-const char kPushUrl[] = "https://www.example.org/push"; |
-const char kPostBody[] = "\0hello!\xff"; |
-const size_t kPostBodyLength = arraysize(kPostBody); |
-const SpdyStringPiece kPostBodyStringPiece(kPostBody, kPostBodyLength); |
- |
-static base::TimeTicks g_time_now; |
- |
-base::TimeTicks InstantaneousReads() { |
- return g_time_now; |
-} |
- |
-} // namespace |
- |
-class SpdyStreamTest : public ::testing::Test { |
- 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_t)> |
- UnstallFunction; |
- |
- SpdyStreamTest() |
- : url_(kDefaultUrl), |
- session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)), |
- offset_(0), |
- ssl_(SYNCHRONOUS, OK) {} |
- |
- ~SpdyStreamTest() override {} |
- |
- base::WeakPtr<SpdySession> CreateDefaultSpdySession() { |
- SpdySessionKey key(HostPortPair::FromURL(url_), ProxyServer::Direct(), |
- PRIVACY_MODE_DISABLED); |
- return CreateSecureSpdySession(session_.get(), key, NetLogWithSource()); |
- } |
- |
- void TearDown() override { base::RunLoop().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 SpdySerializedFrame& frame) { |
- reads_.push_back(CreateMockRead(frame, offset_++)); |
- } |
- |
- void AddWrite(const SpdySerializedFrame& frame) { |
- writes_.push_back(CreateMockWrite(frame, offset_++)); |
- } |
- |
- void AddReadEOF() { |
- reads_.push_back(MockRead(ASYNC, 0, offset_++)); |
- } |
- |
- void AddWritePause() { |
- writes_.push_back(MockWrite(ASYNC, ERR_IO_PENDING, offset_++)); |
- } |
- |
- void AddReadPause() { |
- reads_.push_back(MockRead(ASYNC, ERR_IO_PENDING, offset_++)); |
- } |
- |
- MockRead* GetReads() { return reads_.data(); } |
- |
- size_t GetNumReads() const { |
- return reads_.size(); |
- } |
- |
- MockWrite* GetWrites() { return writes_.data(); } |
- |
- int GetNumWrites() const { |
- return writes_.size(); |
- } |
- |
- void ActivatePushStream(SpdySession* session, SpdyStream* stream) { |
- std::unique_ptr<SpdyStream> activated = |
- session->ActivateCreatedStream(stream); |
- activated->set_stream_id(2); |
- session->InsertActivatedStream(std::move(activated)); |
- } |
- |
- void AddSSLSocketData() { |
- // Load a cert that is valid for |
- // www.example.org, mail.example.org, and mail.example.com. |
- ssl_.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"); |
- ASSERT_TRUE(ssl_.cert); |
- session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_); |
- } |
- |
- const GURL url_; |
- SpdyTestUtil spdy_util_; |
- SpdySessionDependencies session_deps_; |
- std::unique_ptr<HttpNetworkSession> session_; |
- |
- private: |
- // Used by Add{Read,Write}() above. |
- std::vector<MockWrite> writes_; |
- std::vector<MockRead> reads_; |
- int offset_; |
- SSLSocketDataProvider ssl_; |
-}; |
- |
-TEST_F(SpdyStreamTest, SendDataAfterOpen) { |
- SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( |
- kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); |
- AddWrite(req); |
- |
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); |
- AddRead(resp); |
- |
- SpdySerializedFrame msg( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false)); |
- AddWrite(msg); |
- |
- SpdySerializedFrame echo( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false)); |
- AddRead(echo); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers( |
- spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength)); |
- EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED)); |
- |
- EXPECT_TRUE(delegate.send_headers_completed()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
- EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength), |
- delegate.TakeReceivedData()); |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
-} |
- |
-// Delegate that receives trailers. |
-class StreamDelegateWithTrailers : public test::StreamDelegateWithBody { |
- public: |
- StreamDelegateWithTrailers(const base::WeakPtr<SpdyStream>& stream, |
- SpdyStringPiece data) |
- : StreamDelegateWithBody(stream, data) {} |
- |
- ~StreamDelegateWithTrailers() override {} |
- |
- void OnTrailers(const SpdyHeaderBlock& trailers) override { |
- trailers_ = trailers.Clone(); |
- } |
- |
- const SpdyHeaderBlock& trailers() const { return trailers_; } |
- |
- private: |
- SpdyHeaderBlock trailers_; |
-}; |
- |
-// Regression test for https://crbug.com/481033. |
-TEST_F(SpdyStreamTest, Trailers) { |
- SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( |
- kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); |
- AddWrite(req); |
- |
- SpdySerializedFrame msg( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true)); |
- AddWrite(msg); |
- |
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); |
- AddRead(resp); |
- |
- SpdySerializedFrame echo( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false)); |
- AddRead(echo); |
- |
- SpdyHeaderBlock late_headers; |
- late_headers["foo"] = "bar"; |
- SpdySerializedFrame trailers(spdy_util_.ConstructSpdyResponseHeaders( |
- 1, std::move(late_headers), false)); |
- AddRead(trailers); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateWithTrailers delegate(stream, kPostBodyStringPiece); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers( |
- spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength)); |
- EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED)); |
- |
- EXPECT_TRUE(delegate.send_headers_completed()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
- const SpdyHeaderBlock& received_trailers = delegate.trailers(); |
- SpdyHeaderBlock::const_iterator it = received_trailers.find("foo"); |
- EXPECT_EQ("bar", it->second); |
- EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength), |
- delegate.TakeReceivedData()); |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, PushedStream) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(reply); |
- |
- SpdySerializedFrame push( |
- spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushUrl)); |
- AddRead(push); |
- |
- SpdySerializedFrame priority( |
- spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true)); |
- AddWrite(priority); |
- |
- AddReadPause(); |
- |
- SpdyStringPiece pushed_msg("foo"); |
- SpdySerializedFrame pushed_body(spdy_util_.ConstructSpdyDataFrame( |
- 2, pushed_msg.data(), pushed_msg.size(), true)); |
- AddRead(pushed_body); |
- |
- SpdyStringPiece msg("bar"); |
- SpdySerializedFrame body( |
- spdy_util_.ConstructSpdyDataFrame(1, msg.data(), msg.size(), true)); |
- AddRead(body); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- g_time_now = base::TimeTicks::Now(); |
- session_deps_.time_func = InstantaneousReads; |
- session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_THAT( |
- stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- data.RunUntilPaused(); |
- |
- SpdyStream* push_stream; |
- EXPECT_THAT(session->GetPushStream(GURL(kPushUrl), IDLE, &push_stream, |
- NetLogWithSource()), |
- IsOk()); |
- ASSERT_TRUE(push_stream); |
- EXPECT_EQ(kPushUrl, push_stream->GetUrlFromHeaders().spec()); |
- |
- LoadTimingInfo load_timing_info; |
- EXPECT_TRUE(push_stream->GetLoadTimingInfo(&load_timing_info)); |
- EXPECT_EQ(g_time_now, load_timing_info.push_start); |
- EXPECT_TRUE(load_timing_info.push_end.is_null()); |
- |
- StreamDelegateDoNothing push_delegate(push_stream->GetWeakPtr()); |
- push_stream->SetDelegate(&push_delegate); |
- |
- data.Resume(); |
- |
- EXPECT_TRUE(push_stream->GetLoadTimingInfo(&load_timing_info)); |
- EXPECT_EQ(g_time_now, load_timing_info.push_start); |
- EXPECT_FALSE(load_timing_info.push_end.is_null()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsOk()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
- EXPECT_EQ(msg, delegate.TakeReceivedData()); |
- |
- EXPECT_THAT(push_delegate.WaitForClose(), IsOk()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
- EXPECT_EQ(pushed_msg, push_delegate.TakeReceivedData()); |
-} |
- |
-TEST_F(SpdyStreamTest, StreamError) { |
- SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( |
- kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); |
- AddWrite(req); |
- |
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(resp); |
- |
- SpdySerializedFrame msg( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false)); |
- AddWrite(msg); |
- |
- SpdySerializedFrame echo( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false)); |
- AddRead(echo); |
- |
- AddReadEOF(); |
- |
- BoundTestNetLog log; |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, log.bound()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers( |
- spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength)); |
- EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED)); |
- |
- const SpdyStreamId stream_id = delegate.stream_id(); |
- |
- EXPECT_TRUE(delegate.send_headers_completed()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
- EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength), |
- delegate.TakeReceivedData()); |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- |
- // Check that the NetLog was filled reasonably. |
- TestNetLogEntry::List entries; |
- log.GetEntries(&entries); |
- EXPECT_LT(0u, entries.size()); |
- |
- // Check that we logged SPDY_STREAM_ERROR correctly. |
- int pos = ExpectLogContainsSomewhere( |
- entries, 0, NetLogEventType::HTTP2_STREAM_ERROR, NetLogEventPhase::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_F(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) { |
- SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( |
- kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); |
- AddWrite(req); |
- |
- SpdyString chunk_data(kMaxSpdyFrameChunkSize, 'x'); |
- SpdySerializedFrame chunk(spdy_util_.ConstructSpdyDataFrame( |
- 1, chunk_data.data(), chunk_data.length(), false)); |
- AddWrite(chunk); |
- AddWrite(chunk); |
- |
- SpdySerializedFrame last_chunk(spdy_util_.ConstructSpdyDataFrame( |
- 1, chunk_data.data(), chunk_data.length(), true)); |
- AddWrite(last_chunk); |
- |
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); |
- AddRead(resp); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- SpdyString body_data(3 * kMaxSpdyFrameChunkSize, 'x'); |
- StreamDelegateWithBody delegate(stream, body_data); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers( |
- spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength)); |
- EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED)); |
- |
- EXPECT_TRUE(delegate.send_headers_completed()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
- EXPECT_EQ(SpdyString(), delegate.TakeReceivedData()); |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
-} |
- |
-// 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_F(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) { |
- SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( |
- kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); |
- AddWrite(req); |
- |
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); |
- AddRead(resp); |
- |
- SpdyString chunk_data(kMaxSpdyFrameChunkSize, 'x'); |
- SpdySerializedFrame chunk(spdy_util_.ConstructSpdyDataFrame( |
- 1, chunk_data.data(), chunk_data.length(), false)); |
- AddWrite(chunk); |
- AddWrite(chunk); |
- AddWrite(chunk); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- SpdyString body_data(3 * kMaxSpdyFrameChunkSize, 'x'); |
- StreamDelegateSendImmediate delegate(stream, body_data); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers( |
- spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength)); |
- EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED)); |
- |
- EXPECT_TRUE(delegate.send_headers_completed()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
- EXPECT_EQ(SpdyString(), delegate.TakeReceivedData()); |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
-} |
- |
-// Receiving a header with uppercase ASCII should result in a protocol error. |
-TEST_F(SpdyStreamTest, UpperCaseHeaders) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- const char* const kExtraHeaders[] = {"X-UpperCase", "yes"}; |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply( |
- kExtraHeaders, arraysize(kExtraHeaders) / 2, 1)); |
- AddRead(reply); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_THAT( |
- stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR)); |
- |
- // Finish async network reads and writes. |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-// Receiving a header with uppercase ASCII should result in a protocol error |
-// even for a push stream. |
-TEST_F(SpdyStreamTest, UpperCaseHeadersOnPush) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(reply); |
- |
- const char* const kExtraHeaders[] = {"X-UpperCase", "yes"}; |
- SpdySerializedFrame push(spdy_util_.ConstructSpdyPush( |
- kExtraHeaders, arraysize(kExtraHeaders) / 2, 2, 1, kPushUrl)); |
- AddRead(push); |
- |
- SpdySerializedFrame priority( |
- spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true)); |
- AddWrite(priority); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(2, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- AddReadPause(); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_THAT( |
- stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- data.RunUntilPaused(); |
- |
- SpdyStream* push_stream; |
- EXPECT_THAT(session->GetPushStream(GURL(kPushUrl), IDLE, &push_stream, |
- NetLogWithSource()), |
- IsOk()); |
- EXPECT_FALSE(push_stream); |
- |
- data.Resume(); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED)); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, HeadersMustHaveStatus) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- // Response headers without ":status" header field: protocol error. |
- SpdyHeaderBlock header_block_without_status; |
- header_block_without_status[spdy_util_.GetMethodKey()] = "GET"; |
- header_block_without_status[spdy_util_.GetHostKey()] = "www.example.org"; |
- header_block_without_status[spdy_util_.GetSchemeKey()] = "https"; |
- header_block_without_status[spdy_util_.GetPathKey()] = "/"; |
- SpdySerializedFrame reply( |
- spdy_util_.ConstructSpdyReply(1, std::move(header_block_without_status))); |
- AddRead(reply); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers), |
- NO_MORE_DATA_TO_SEND)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR)); |
- |
- // Finish async network reads and writes. |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, HeadersMustHaveStatusOnPushedStream) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(reply); |
- |
- SpdySerializedFrame push_promise(spdy_util_.ConstructInitialSpdyPushFrame( |
- spdy_util_.ConstructGetHeaderBlock(kPushUrl), 2, 1)); |
- AddRead(push_promise); |
- |
- SpdySerializedFrame priority( |
- spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true)); |
- AddWrite(priority); |
- |
- // Response headers without ":status" header field: protocol error. |
- SpdyHeaderBlock header_block_without_status; |
- header_block_without_status[spdy_util_.GetMethodKey()] = "GET"; |
- header_block_without_status[spdy_util_.GetHostKey()] = "www.example.org"; |
- header_block_without_status[spdy_util_.GetSchemeKey()] = "https"; |
- header_block_without_status[spdy_util_.GetPathKey()] = "/"; |
- SpdySerializedFrame pushed_reply( |
- spdy_util_.ConstructSpdyReply(2, std::move(header_block_without_status))); |
- AddRead(pushed_reply); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(2, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- SpdySerializedFrame body( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true)); |
- AddRead(body); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_THAT( |
- stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsOk()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
- EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength), |
- delegate.TakeReceivedData()); |
- |
- // Finish async network reads and writes. |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, HeadersMustPreceedData) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- // Response body not preceeded by headers: protocol error. |
- SpdySerializedFrame body( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true)); |
- AddRead(body); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers), |
- NO_MORE_DATA_TO_SEND)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR)); |
-} |
- |
-TEST_F(SpdyStreamTest, HeadersMustPreceedDataOnPushedStream) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(reply); |
- |
- SpdySerializedFrame push_promise(spdy_util_.ConstructInitialSpdyPushFrame( |
- spdy_util_.ConstructGetHeaderBlock(kPushUrl), 2, 1)); |
- AddRead(push_promise); |
- |
- SpdySerializedFrame priority( |
- spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true)); |
- AddWrite(priority); |
- |
- SpdySerializedFrame pushed_body( |
- spdy_util_.ConstructSpdyDataFrame(2, kPostBody, kPostBodyLength, true)); |
- AddRead(pushed_body); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(2, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- SpdySerializedFrame body( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true)); |
- AddRead(body); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_THAT( |
- stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsOk()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
- EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength), |
- delegate.TakeReceivedData()); |
- |
- // Finish async network reads and writes. |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, TrailersMustNotFollowTrailers) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(reply); |
- |
- SpdySerializedFrame body( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false)); |
- AddRead(body); |
- |
- SpdyHeaderBlock trailers_block; |
- trailers_block["foo"] = "bar"; |
- SpdySerializedFrame first_trailers(spdy_util_.ConstructSpdyResponseHeaders( |
- 1, std::move(trailers_block), false)); |
- AddRead(first_trailers); |
- |
- // Trailers following trailers: procotol error. |
- SpdySerializedFrame second_trailers(spdy_util_.ConstructSpdyResponseHeaders( |
- 1, std::move(trailers_block), true)); |
- AddRead(second_trailers); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers), |
- NO_MORE_DATA_TO_SEND)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR)); |
- |
- // Finish async network reads and writes. |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, DataMustNotFollowTrailers) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(reply); |
- |
- SpdySerializedFrame body( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false)); |
- AddRead(body); |
- |
- SpdyHeaderBlock trailers_block; |
- trailers_block["foo"] = "bar"; |
- SpdySerializedFrame trailers(spdy_util_.ConstructSpdyResponseHeaders( |
- 1, std::move(trailers_block), false)); |
- AddRead(trailers); |
- |
- // DATA frame following trailers: protocol error. |
- AddRead(body); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers), |
- NO_MORE_DATA_TO_SEND)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR)); |
- |
- // Finish async network reads and writes. |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, InformationalHeaders) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- SpdyHeaderBlock informational_headers; |
- informational_headers[":status"] = "100"; |
- SpdySerializedFrame informational_response( |
- spdy_util_.ConstructSpdyResponseHeaders( |
- 1, std::move(informational_headers), false)); |
- AddRead(informational_response); |
- |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(reply); |
- |
- SpdySerializedFrame body( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true)); |
- AddRead(body); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers), |
- NO_MORE_DATA_TO_SEND)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsOk()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); |
- EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength), |
- delegate.TakeReceivedData()); |
- |
- // Finish async network reads and writes. |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, StatusMustBeNumber) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- SpdyHeaderBlock incorrect_headers; |
- incorrect_headers[":status"] = "nan"; |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders( |
- 1, std::move(incorrect_headers), false)); |
- AddRead(reply); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers), |
- NO_MORE_DATA_TO_SEND)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR)); |
- |
- // Finish async network reads and writes. |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, StatusCannotHaveExtraText) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- SpdyHeaderBlock headers_with_status_text; |
- headers_with_status_text[":status"] = |
- "200 Some random extra text describing status"; |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders( |
- 1, std::move(headers_with_status_text), false)); |
- AddRead(reply); |
- |
- SpdySerializedFrame body( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true)); |
- AddRead(body); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers), |
- NO_MORE_DATA_TO_SEND)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR)); |
- |
- // Finish async network reads and writes. |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, StatusMustBePresent) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- SpdyHeaderBlock headers_without_status; |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders( |
- 1, std::move(headers_without_status), false)); |
- AddRead(reply); |
- |
- SpdySerializedFrame body( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true)); |
- AddRead(body); |
- |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR)); |
- AddWrite(rst); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers), |
- NO_MORE_DATA_TO_SEND)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR)); |
- |
- // Finish async network reads and writes. |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
- EXPECT_TRUE(data.AllReadDataConsumed()); |
-} |
- |
-// Call IncreaseSendWindowSize on a stream with a large enough delta to overflow |
-// an int32_t. The SpdyStream should handle that case gracefully. |
-TEST_F(SpdyStreamTest, IncreaseSendWindowSizeOverflow) { |
- SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( |
- kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); |
- AddWrite(req); |
- |
- AddReadPause(); |
- |
- // Triggered by the overflowing call to IncreaseSendWindowSize |
- // below. |
- SpdySerializedFrame rst( |
- spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_FLOW_CONTROL_ERROR)); |
- AddWrite(rst); |
- |
- AddReadEOF(); |
- |
- BoundTestNetLog log; |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, log.bound()); |
- ASSERT_TRUE(stream); |
- StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece); |
- stream->SetDelegate(&delegate); |
- |
- SpdyHeaderBlock headers( |
- spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength)); |
- EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- data.RunUntilPaused(); |
- |
- int32_t old_send_window_size = stream->send_window_size(); |
- ASSERT_GT(old_send_window_size, 0); |
- int32_t delta_window_size = |
- std::numeric_limits<int32_t>::max() - old_send_window_size + 1; |
- stream->IncreaseSendWindowSize(delta_window_size); |
- EXPECT_FALSE(stream); |
- |
- data.Resume(); |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR)); |
-} |
- |
-// 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_t 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_t 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) { |
- SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( |
- kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); |
- AddWrite(req); |
- |
- SpdySerializedFrame body( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true)); |
- AddWrite(body); |
- |
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(resp); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateWithBody delegate(stream, kPostBodyStringPiece); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- EXPECT_FALSE(stream->send_stalled_by_flow_control()); |
- |
- SpdyHeaderBlock headers( |
- spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength)); |
- EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- StallStream(stream); |
- |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(stream->send_stalled_by_flow_control()); |
- |
- unstall_function.Run(stream, kPostBodyLength); |
- |
- EXPECT_FALSE(stream->send_stalled_by_flow_control()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED)); |
- |
- EXPECT_TRUE(delegate.send_headers_completed()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); |
- EXPECT_EQ(SpdyString(), delegate.TakeReceivedData()); |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) { |
- RunResumeAfterUnstallRequestResponseTest( |
- base::Bind(&IncreaseStreamSendWindowSize)); |
-} |
- |
-TEST_F(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) { |
- SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( |
- kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); |
- AddWrite(req); |
- |
- AddReadPause(); |
- |
- SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(resp); |
- |
- SpdySerializedFrame msg( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false)); |
- AddWrite(msg); |
- |
- SpdySerializedFrame echo( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false)); |
- AddRead(echo); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers( |
- spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength)); |
- EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- data.RunUntilPaused(); |
- |
- EXPECT_FALSE(stream->send_stalled_by_flow_control()); |
- |
- StallStream(stream); |
- |
- data.Resume(); |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_TRUE(stream->send_stalled_by_flow_control()); |
- |
- unstall_function.Run(stream, kPostBodyLength); |
- |
- EXPECT_FALSE(stream->send_stalled_by_flow_control()); |
- |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED)); |
- |
- EXPECT_TRUE(delegate.send_headers_completed()); |
- EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); |
- EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength), |
- delegate.TakeReceivedData()); |
- EXPECT_TRUE(data.AllWriteDataConsumed()); |
-} |
- |
-TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) { |
- RunResumeAfterUnstallBidirectionalTest( |
- base::Bind(&IncreaseStreamSendWindowSize)); |
-} |
- |
-TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) { |
- RunResumeAfterUnstallBidirectionalTest( |
- base::Bind(&AdjustStreamSendWindowSize)); |
-} |
- |
-// Test calculation of amount of bytes received from network. |
-TEST_F(SpdyStreamTest, ReceivedBytes) { |
- SpdySerializedFrame req( |
- spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true)); |
- AddWrite(req); |
- |
- AddReadPause(); |
- |
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); |
- AddRead(reply); |
- |
- AddReadPause(); |
- |
- SpdySerializedFrame msg( |
- spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false)); |
- AddRead(msg); |
- |
- AddReadPause(); |
- |
- AddReadEOF(); |
- |
- SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(), |
- GetNumWrites()); |
- MockConnect connect_data(SYNCHRONOUS, OK); |
- data.set_connect_data(connect_data); |
- session_deps_.socket_factory->AddSocketDataProvider(&data); |
- |
- AddSSLSocketData(); |
- |
- base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); |
- |
- base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( |
- SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource()); |
- ASSERT_TRUE(stream); |
- |
- StreamDelegateDoNothing delegate(stream); |
- stream->SetDelegate(&delegate); |
- |
- EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty()); |
- |
- SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); |
- EXPECT_THAT( |
- stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND), |
- IsError(ERR_IO_PENDING)); |
- EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec()); |
- |
- int64_t reply_frame_len = reply.size(); |
- int64_t data_header_len = kDataFrameMinimumSize; |
- int64_t data_frame_len = data_header_len + kPostBodyLength; |
- int64_t response_len = reply_frame_len + data_frame_len; |
- |
- EXPECT_EQ(0, stream->raw_received_bytes()); |
- |
- // REQUEST |
- data.RunUntilPaused(); |
- EXPECT_EQ(0, stream->raw_received_bytes()); |
- |
- // REPLY |
- data.Resume(); |
- data.RunUntilPaused(); |
- EXPECT_EQ(reply_frame_len, stream->raw_received_bytes()); |
- |
- // DATA |
- data.Resume(); |
- data.RunUntilPaused(); |
- EXPECT_EQ(response_len, stream->raw_received_bytes()); |
- |
- // FIN |
- data.Resume(); |
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED)); |
-} |
- |
-} // namespace test |
- |
-} // namespace net |