blob: ce0c3de5872d37bdc2aa110324a82f7df0a546f3 [file] [log] [blame]
[email protected]3d587372013-06-01 04:31:451// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]4f386422010-07-20 04:19:492// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Bence Béky94658bf2018-05-11 19:22:585#include "net/spdy/spdy_stream.h"
avid0181f32015-12-10 19:41:476
dchengc7eeda422015-12-26 03:56:487#include <stdint.h>
danakjaee3e1ec2016-04-16 00:23:188
diannahu46ab1812016-12-26 21:27:079#include <algorithm>
[email protected]3d587372013-06-01 04:31:4510#include <cstddef>
avid0181f32015-12-10 19:41:4711#include <limits>
danakjaee3e1ec2016-04-16 00:23:1812#include <memory>
Bence Béky4e83f492018-05-13 23:14:2513#include <string>
dchengc7eeda422015-12-26 03:56:4814#include <utility>
[email protected]3d587372013-06-01 04:31:4515#include <vector>
16
Sebastien Marchand6d0558fd2019-01-25 16:49:3717#include "base/bind.h"
[email protected]3b63f8f42011-03-28 01:54:1518#include "base/memory/ref_counted.h"
mmenkee24011922015-12-17 22:12:5919#include "base/run_loop.h"
Bence Béky4e83f492018-05-13 23:14:2520#include "base/strings/string_piece.h"
Gabriel Charetted87f10f2022-03-31 00:44:2221#include "base/time/time.h"
[email protected]1bbabc82013-03-25 21:11:0222#include "net/base/request_priority.h"
Ben Schwartz3ff4dc1e62021-04-27 21:15:2323#include "net/dns/public/secure_dns_policy.h"
Bence Béky5b1e4ce72018-01-11 14:55:1524#include "net/http/http_request_info.h"
mikecirone8b85c432016-09-08 19:11:0025#include "net/log/net_log_event_type.h"
mmenke16a7cbdd2015-04-24 23:00:5626#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4627#include "net/log/test_net_log_util.h"
Paul Jensena457017a2018-01-19 23:52:0428#include "net/socket/socket_tag.h"
[email protected]6fe2e992013-06-12 03:38:4329#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5830#include "net/spdy/buffered_spdy_framer.h"
31#include "net/spdy/http2_push_promise_index.h"
32#include "net/spdy/spdy_http_utils.h"
33#include "net/spdy/spdy_session.h"
34#include "net/spdy/spdy_session_pool.h"
35#include "net/spdy/spdy_stream_test_util.h"
36#include "net/spdy/spdy_test_util_common.h"
bnc032658ba2016-09-26 18:17:1537#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0138#include "net/test/gtest_util.h"
bnc032658ba2016-09-26 18:17:1539#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4040#include "net/test/test_with_task_environment.h"
Ryan Hamiltonea4fa192022-04-12 18:30:4941#include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
robpercival214763f2016-07-01 23:27:0142#include "testing/gmock/include/gmock/gmock.h"
[email protected]4f386422010-07-20 04:19:4943#include "testing/gtest/include/gtest/gtest.h"
44
[email protected]4f386422010-07-20 04:19:4945// TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
[email protected]b9ec6882011-07-01 07:40:2646//
Tsuyoshi Horo4f516be2022-06-14 11:53:1347namespace net::test {
[email protected]34a4dea2013-03-13 00:42:3048
[email protected]4f386422010-07-20 04:19:4949namespace {
50
bnca2fbdc9b2016-11-22 21:14:2651const char kPushUrl[] = "https://www.example.org/push";
[email protected]cbdd73162013-03-18 23:27:3352const char kPostBody[] = "\0hello!\xff";
Daniel Cheng5feb16f2022-02-28 06:52:0753const size_t kPostBodyLength = std::size(kPostBody);
Bence Béky4e83f492018-05-13 23:14:2554const base::StringPiece kPostBodyStringPiece(kPostBody, kPostBodyLength);
[email protected]39d13d942012-07-19 16:48:2055
bnca2fbdc9b2016-11-22 21:14:2656static base::TimeTicks g_time_now;
57
58base::TimeTicks InstantaneousReads() {
59 return g_time_now;
60}
61
Hiroki Nakagawad67642b592020-12-10 13:26:3562// Creates a MockRead from the given serialized frame except for the last byte.
63MockRead ReadFrameExceptForLastByte(const spdy::SpdySerializedFrame& frame) {
64 CHECK_GE(frame.size(), 2u);
65 return MockRead(ASYNC, frame.data(), frame.size() - 1);
66}
67
68// Creates a MockRead from the last byte of the given serialized frame.
69MockRead LastByteOfReadFrame(const spdy::SpdySerializedFrame& frame) {
70 CHECK_GE(frame.size(), 2u);
71 return MockRead(ASYNC, frame.data() + frame.size() - 1, 1);
72}
73
rdsmithebb50aa2015-11-12 03:44:3874} // namespace
75
Hiroki Nakagawad67642b592020-12-10 13:26:3576class SpdyStreamTest : public ::testing::Test, public WithTaskEnvironment {
[email protected]4f386422010-07-20 04:19:4977 protected:
[email protected]d2de7da2013-05-22 07:49:5678 // A function that takes a SpdyStream and the number of bytes which
79 // will unstall the next frame completely.
Anna Malova924d79d2020-03-04 17:09:3280 typedef base::OnceCallback<void(const base::WeakPtr<SpdyStream>&, int32_t)>
[email protected]d2de7da2013-05-22 07:49:5681 UnstallFunction;
82
Hiroki Nakagawad67642b592020-12-10 13:26:3583 explicit SpdyStreamTest(base::test::TaskEnvironment::TimeSource time_source =
84 base::test::TaskEnvironment::TimeSource::DEFAULT)
85 : WithTaskEnvironment(time_source),
86 url_(kDefaultUrl),
bnca2fbdc9b2016-11-22 21:14:2687 session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)),
bnca2fbdc9b2016-11-22 21:14:2688 ssl_(SYNCHRONOUS, OK) {}
rdsmithebb50aa2015-11-12 03:44:3889
Chris Watkins61914cb2017-12-01 19:59:0090 ~SpdyStreamTest() override = default;
[email protected]4f386422010-07-20 04:19:4991
[email protected]795cbf82013-07-22 09:37:2792 base::WeakPtr<SpdySession> CreateDefaultSpdySession() {
bnca2fbdc9b2016-11-22 21:14:2693 SpdySessionKey key(HostPortPair::FromURL(url_), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1194 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3495 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
Ben Schwartz3ff4dc1e62021-04-27 21:15:2396 NetworkIsolationKey(), SecureDnsPolicy::kAllow);
Bence Béky0ef1556e2017-06-30 19:52:5297 return CreateSpdySession(session_.get(), key, NetLogWithSource());
[email protected]34a4dea2013-03-13 00:42:3098 }
99
fdoray92e35a72016-06-10 15:54:55100 void TearDown() override { base::RunLoop().RunUntilIdle(); }
[email protected]4f386422010-07-20 04:19:49101
[email protected]d2de7da2013-05-22 07:49:56102 void RunResumeAfterUnstallRequestResponseTest(
Anna Malova924d79d2020-03-04 17:09:32103 UnstallFunction unstall_function);
[email protected]d2de7da2013-05-22 07:49:56104
Anna Malova924d79d2020-03-04 17:09:32105 void RunResumeAfterUnstallBidirectionalTest(UnstallFunction unstall_function);
[email protected]d2de7da2013-05-22 07:49:56106
[email protected]3d587372013-06-01 04:31:45107 // Add{Read,Write}() populates lists that are eventually passed to a
108 // SocketData class. |frame| must live for the whole test.
109
Ryan Hamilton0239aac2018-05-19 00:03:13110 void AddRead(const spdy::SpdySerializedFrame& frame) {
[email protected]3d587372013-06-01 04:31:45111 reads_.push_back(CreateMockRead(frame, offset_++));
112 }
113
Ryan Hamilton0239aac2018-05-19 00:03:13114 void AddWrite(const spdy::SpdySerializedFrame& frame) {
[email protected]3d587372013-06-01 04:31:45115 writes_.push_back(CreateMockWrite(frame, offset_++));
116 }
117
Hiroki Nakagawad67642b592020-12-10 13:26:35118 void AddMockRead(MockRead read) {
119 read.sequence_number = offset_++;
120 reads_.push_back(std::move(read));
121 }
122
[email protected]3d587372013-06-01 04:31:45123 void AddReadEOF() {
124 reads_.push_back(MockRead(ASYNC, 0, offset_++));
125 }
126
mmenkee24011922015-12-17 22:12:59127 void AddWritePause() {
128 writes_.push_back(MockWrite(ASYNC, ERR_IO_PENDING, offset_++));
129 }
130
131 void AddReadPause() {
132 reads_.push_back(MockRead(ASYNC, ERR_IO_PENDING, offset_++));
133 }
134
Ryan Sleevib8d7ea02018-05-07 20:01:01135 base::span<const MockRead> GetReads() { return reads_; }
136 base::span<const MockWrite> GetWrites() { return writes_; }
[email protected]3d587372013-06-01 04:31:45137
caseqe8340bc92016-04-20 00:02:57138 void ActivatePushStream(SpdySession* session, SpdyStream* stream) {
139 std::unique_ptr<SpdyStream> activated =
140 session->ActivateCreatedStream(stream);
141 activated->set_stream_id(2);
142 session->InsertActivatedStream(std::move(activated));
143 }
144
bnc032658ba2016-09-26 18:17:15145 void AddSSLSocketData() {
146 // Load a cert that is valid for
147 // www.example.org, mail.example.org, and mail.example.com.
Ryan Sleevi4f832092017-11-21 23:25:49148 ssl_.ssl_info.cert =
149 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
150 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15151 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
152 }
153
Bence Béky7bf94362018-01-10 13:19:36154 static size_t num_pushed_streams(base::WeakPtr<SpdySession> session) {
155 return session->num_pushed_streams_;
156 }
157
Patrick Meenan8b7432fb2022-01-12 14:07:27158 int32_t unacked_recv_window_bytes(base::WeakPtr<SpdyStream> stream) {
159 return stream->unacked_recv_window_bytes_;
160 }
161
Bence Béky7bf94362018-01-10 13:19:36162 static SpdySessionPool* spdy_session_pool(
163 base::WeakPtr<SpdySession> session) {
164 return session->pool_;
165 }
166
bnca2fbdc9b2016-11-22 21:14:26167 const GURL url_;
[email protected]a4a67772013-05-08 22:56:07168 SpdyTestUtil spdy_util_;
[email protected]34a4dea2013-03-13 00:42:30169 SpdySessionDependencies session_deps_;
danakjaee3e1ec2016-04-16 00:23:18170 std::unique_ptr<HttpNetworkSession> session_;
[email protected]3d587372013-06-01 04:31:45171
172 private:
173 // Used by Add{Read,Write}() above.
174 std::vector<MockWrite> writes_;
175 std::vector<MockRead> reads_;
Tsuyoshi Horob2022b52022-06-09 01:44:07176 int offset_ = 0;
bnc032658ba2016-09-26 18:17:15177 SSLSocketDataProvider ssl_;
[email protected]4f386422010-07-20 04:19:49178};
179
bncd16676a2016-07-20 16:23:01180TEST_F(SpdyStreamTest, SendDataAfterOpen) {
Ryan Hamilton0239aac2018-05-19 00:03:13181 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bnca2fbdc9b2016-11-22 21:14:26182 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:41183 AddWrite(req);
[email protected]3d587372013-06-01 04:31:45184
Ryan Hamilton0239aac2018-05-19 00:03:13185 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:41186 AddRead(resp);
[email protected]3d587372013-06-01 04:31:45187
Ryan Hamilton0239aac2018-05-19 00:03:13188 spdy::SpdySerializedFrame msg(
Bence Békyd74f4382018-02-20 18:26:19189 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
bncdf80d44fd2016-07-15 20:27:41190 AddWrite(msg);
[email protected]4f386422010-07-20 04:19:49191
Ryan Hamilton0239aac2018-05-19 00:03:13192 spdy::SpdySerializedFrame echo(
Bence Békyd74f4382018-02-20 18:26:19193 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
bncdf80d44fd2016-07-15 20:27:41194 AddRead(echo);
[email protected]4f386422010-07-20 04:19:49195
[email protected]3d587372013-06-01 04:31:45196 AddReadEOF();
197
Ryan Sleevib8d7ea02018-05-07 20:01:01198 SequencedSocketData data(GetReads(), GetWrites());
[email protected]d973e99a2012-02-17 21:02:36199 MockConnect connect_data(SYNCHRONOUS, OK);
[email protected]dd54bd82012-07-19 23:44:57200 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:59201 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4f386422010-07-20 04:19:49202
bnc032658ba2016-09-26 18:17:15203 AddSSLSocketData();
204
[email protected]795cbf82013-07-22 09:37:27205 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]e3861ca2013-03-02 01:00:45206
tfarina42834112016-09-22 13:38:20207 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:26208 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:52209 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18210 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]4f386422010-07-20 04:19:49211
[email protected]194cfcf2013-05-23 21:44:44212 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
[email protected]34a4dea2013-03-13 00:42:30213 stream->SetDelegate(&delegate);
[email protected]4f386422010-07-20 04:19:49214
Bence Béky4c325e52020-10-22 20:48:01215 spdy::Http2HeaderBlock headers(
bnca2fbdc9b2016-11-22 21:14:26216 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
217 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
218 IsError(ERR_IO_PENDING));
[email protected]4f386422010-07-20 04:19:49219
robpercival214763f2016-07-01 23:27:01220 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
[email protected]4f386422010-07-20 04:19:49221
[email protected]34a4dea2013-03-13 00:42:30222 EXPECT_TRUE(delegate.send_headers_completed());
Ryan Hamilton0239aac2018-05-19 00:03:13223 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
Bence Béky4e83f492018-05-13 23:14:25224 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
[email protected]09a8d9172013-04-17 19:23:49225 delegate.TakeReceivedData());
rch37de576c2015-05-17 20:28:17226 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]4f386422010-07-20 04:19:49227}
228
Stefano Duo62d36c42022-01-17 13:24:02229TEST_F(SpdyStreamTest, BrokenConnectionDetectionSuccessfulRequest) {
230 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
231 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
232 AddWrite(req);
233
234 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
235 AddRead(resp);
236
237 spdy::SpdySerializedFrame msg(
238 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
239 AddWrite(msg);
240
241 spdy::SpdySerializedFrame echo(
242 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
243 AddRead(echo);
244
245 AddReadPause();
246 AddReadEOF();
247
248 SequencedSocketData data(GetReads(), GetWrites());
249 MockConnect connect_data(SYNCHRONOUS, OK);
250 data.set_connect_data(connect_data);
251 session_deps_.socket_factory->AddSocketDataProvider(&data);
252
253 AddSSLSocketData();
254
255 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
256
257 ASSERT_FALSE(session->IsBrokenConnectionDetectionEnabled());
258 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
259 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource(),
260 true, base::Seconds(10));
261 ASSERT_TRUE(stream);
262 ASSERT_TRUE(session->IsBrokenConnectionDetectionEnabled());
263 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
264 stream->SetDelegate(&delegate);
265
266 spdy::Http2HeaderBlock headers(
267 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
268 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
269 IsError(ERR_IO_PENDING));
270
271 base::RunLoop().RunUntilIdle();
272 ASSERT_TRUE(session->IsBrokenConnectionDetectionEnabled());
273
274 data.Resume();
275 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
276 ASSERT_FALSE(session->IsBrokenConnectionDetectionEnabled());
277}
278
xunjieli294da722015-08-11 19:15:02279// Delegate that receives trailers.
280class StreamDelegateWithTrailers : public test::StreamDelegateWithBody {
281 public:
282 StreamDelegateWithTrailers(const base::WeakPtr<SpdyStream>& stream,
Bence Béky4e83f492018-05-13 23:14:25283 base::StringPiece data)
xunjieli294da722015-08-11 19:15:02284 : StreamDelegateWithBody(stream, data) {}
285
Chris Watkins61914cb2017-12-01 19:59:00286 ~StreamDelegateWithTrailers() override = default;
xunjieli294da722015-08-11 19:15:02287
Bence Béky4c325e52020-10-22 20:48:01288 void OnTrailers(const spdy::Http2HeaderBlock& trailers) override {
bnc94893a72016-06-30 13:45:25289 trailers_ = trailers.Clone();
xunjieli294da722015-08-11 19:15:02290 }
291
Bence Béky4c325e52020-10-22 20:48:01292 const spdy::Http2HeaderBlock& trailers() const { return trailers_; }
xunjieli294da722015-08-11 19:15:02293
294 private:
Bence Béky4c325e52020-10-22 20:48:01295 spdy::Http2HeaderBlock trailers_;
xunjieli294da722015-08-11 19:15:02296};
297
bnca2fbdc9b2016-11-22 21:14:26298// Regression test for https://crbug.com/481033.
bncd16676a2016-07-20 16:23:01299TEST_F(SpdyStreamTest, Trailers) {
Ryan Hamilton0239aac2018-05-19 00:03:13300 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bnca2fbdc9b2016-11-22 21:14:26301 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:41302 AddWrite(req);
xunjieli294da722015-08-11 19:15:02303
Ryan Hamilton0239aac2018-05-19 00:03:13304 spdy::SpdySerializedFrame msg(
Bence Békyd74f4382018-02-20 18:26:19305 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
bncdf80d44fd2016-07-15 20:27:41306 AddWrite(msg);
xunjieli294da722015-08-11 19:15:02307
Ryan Hamilton0239aac2018-05-19 00:03:13308 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:41309 AddRead(resp);
xunjieli294da722015-08-11 19:15:02310
Ryan Hamilton0239aac2018-05-19 00:03:13311 spdy::SpdySerializedFrame echo(
Bence Békyd74f4382018-02-20 18:26:19312 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
bncdf80d44fd2016-07-15 20:27:41313 AddRead(echo);
xunjieli294da722015-08-11 19:15:02314
Bence Béky4c325e52020-10-22 20:48:01315 spdy::Http2HeaderBlock late_headers;
bnc38dcd392016-02-09 23:19:49316 late_headers["foo"] = "bar";
Ryan Hamilton0239aac2018-05-19 00:03:13317 spdy::SpdySerializedFrame trailers(spdy_util_.ConstructSpdyResponseHeaders(
bncdf80d44fd2016-07-15 20:27:41318 1, std::move(late_headers), false));
319 AddRead(trailers);
xunjieli294da722015-08-11 19:15:02320
321 AddReadEOF();
322
Ryan Sleevib8d7ea02018-05-07 20:01:01323 SequencedSocketData data(GetReads(), GetWrites());
xunjieli294da722015-08-11 19:15:02324 MockConnect connect_data(SYNCHRONOUS, OK);
325 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:59326 session_deps_.socket_factory->AddSocketDataProvider(&data);
xunjieli294da722015-08-11 19:15:02327
bnc032658ba2016-09-26 18:17:15328 AddSSLSocketData();
329
xunjieli294da722015-08-11 19:15:02330 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
331
332 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:26333 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:52334 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18335 EXPECT_EQ(kDefaultUrl, stream->url().spec());
xunjieli294da722015-08-11 19:15:02336
337 StreamDelegateWithTrailers delegate(stream, kPostBodyStringPiece);
338 stream->SetDelegate(&delegate);
339
Bence Béky4c325e52020-10-22 20:48:01340 spdy::Http2HeaderBlock headers(
bnca2fbdc9b2016-11-22 21:14:26341 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
342 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
343 IsError(ERR_IO_PENDING));
xunjieli294da722015-08-11 19:15:02344
robpercival214763f2016-07-01 23:27:01345 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
xunjieli294da722015-08-11 19:15:02346
347 EXPECT_TRUE(delegate.send_headers_completed());
Ryan Hamilton0239aac2018-05-19 00:03:13348 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
Bence Béky4c325e52020-10-22 20:48:01349 const spdy::Http2HeaderBlock& received_trailers = delegate.trailers();
350 spdy::Http2HeaderBlock::const_iterator it = received_trailers.find("foo");
xunjieli294da722015-08-11 19:15:02351 EXPECT_EQ("bar", it->second);
Bence Béky4e83f492018-05-13 23:14:25352 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
xunjieli294da722015-08-11 19:15:02353 delegate.TakeReceivedData());
354 EXPECT_TRUE(data.AllWriteDataConsumed());
355}
356
bncd16676a2016-07-20 16:23:01357TEST_F(SpdyStreamTest, PushedStream) {
Ryan Hamilton0239aac2018-05-19 00:03:13358 spdy::SpdySerializedFrame req(
359 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnca2fbdc9b2016-11-22 21:14:26360 AddWrite(req);
361
Ryan Hamilton0239aac2018-05-19 00:03:13362 spdy::SpdySerializedFrame reply(
363 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnca2fbdc9b2016-11-22 21:14:26364 AddRead(reply);
365
Ryan Hamilton0239aac2018-05-19 00:03:13366 spdy::SpdySerializedFrame push(
bnca2fbdc9b2016-11-22 21:14:26367 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushUrl));
368 AddRead(push);
369
Ryan Hamilton0239aac2018-05-19 00:03:13370 spdy::SpdySerializedFrame priority(
tombergan5d22c182017-01-11 02:05:35371 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
372 AddWrite(priority);
373
bnca2fbdc9b2016-11-22 21:14:26374 AddReadPause();
375
Bence Béky4e83f492018-05-13 23:14:25376 base::StringPiece pushed_msg("foo");
Ryan Hamilton0239aac2018-05-19 00:03:13377 spdy::SpdySerializedFrame pushed_body(
Bence Békyd74f4382018-02-20 18:26:19378 spdy_util_.ConstructSpdyDataFrame(2, pushed_msg, true));
bnca2fbdc9b2016-11-22 21:14:26379 AddRead(pushed_body);
380
Bence Béky4e83f492018-05-13 23:14:25381 base::StringPiece msg("bar");
Ryan Hamilton0239aac2018-05-19 00:03:13382 spdy::SpdySerializedFrame body(
383 spdy_util_.ConstructSpdyDataFrame(1, msg, true));
bnca2fbdc9b2016-11-22 21:14:26384 AddRead(body);
385
[email protected]6d116e1a2013-06-24 07:42:15386 AddReadEOF();
387
Ryan Sleevib8d7ea02018-05-07 20:01:01388 SequencedSocketData data(GetReads(), GetWrites());
[email protected]0e861e92012-03-15 18:42:19389 MockConnect connect_data(SYNCHRONOUS, OK);
[email protected]dd54bd82012-07-19 23:44:57390 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:59391 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]0e861e92012-03-15 18:42:19392
bnc032658ba2016-09-26 18:17:15393 AddSSLSocketData();
394
bnca2fbdc9b2016-11-22 21:14:26395 g_time_now = base::TimeTicks::Now();
396 session_deps_.time_func = InstantaneousReads;
397 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
[email protected]a7a265ef2010-12-08 18:05:57398
bnca2fbdc9b2016-11-22 21:14:26399 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
400
401 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
402 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
403 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18404 EXPECT_EQ(kDefaultUrl, stream->url().spec());
bnca2fbdc9b2016-11-22 21:14:26405
406 StreamDelegateDoNothing delegate(stream);
407 stream->SetDelegate(&delegate);
caseqe8340bc92016-04-20 00:02:57408
Bence Béky4c325e52020-10-22 20:48:01409 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:13410 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnca2fbdc9b2016-11-22 21:14:26411 EXPECT_THAT(
412 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
413 IsError(ERR_IO_PENDING));
[email protected]6cd63ba2014-06-12 16:14:56414
bnca2fbdc9b2016-11-22 21:14:26415 data.RunUntilPaused();
[email protected]a7a265ef2010-12-08 18:05:57416
Ben Schwartz3ff4dc1e62021-04-27 21:15:23417 const SpdySessionKey key(HostPortPair::FromURL(url_), ProxyServer::Direct(),
418 PRIVACY_MODE_DISABLED,
419 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
420 NetworkIsolationKey(), SecureDnsPolicy::kAllow);
Bence Béky5b1e4ce72018-01-11 14:55:15421 const GURL pushed_url(kPushUrl);
422 HttpRequestInfo push_request;
423 push_request.url = pushed_url;
424 push_request.method = "GET";
Bence Béky7bf94362018-01-10 13:19:36425 base::WeakPtr<SpdySession> session_with_pushed_stream;
Ryan Hamilton0239aac2018-05-19 00:03:13426 spdy::SpdyStreamId pushed_stream_id;
Bence Béky7bf94362018-01-10 13:19:36427 spdy_session_pool(session)->push_promise_index()->ClaimPushedStream(
Bence Béky5b1e4ce72018-01-11 14:55:15428 key, pushed_url, push_request, &session_with_pushed_stream,
429 &pushed_stream_id);
Bence Béky7bf94362018-01-10 13:19:36430 EXPECT_EQ(session.get(), session_with_pushed_stream.get());
431 EXPECT_EQ(2u, pushed_stream_id);
432
bnc4e6e77482017-01-22 12:59:43433 SpdyStream* push_stream;
Bence Béky5b1e4ce72018-01-11 14:55:15434 EXPECT_THAT(session->GetPushedStream(pushed_url, pushed_stream_id, IDLE,
Bence Békyc6834652018-10-03 00:47:39435 &push_stream),
tombergan5d22c182017-01-11 02:05:35436 IsOk());
bnca2fbdc9b2016-11-22 21:14:26437 ASSERT_TRUE(push_stream);
Bence Béky39d74292018-03-02 04:31:18438 EXPECT_EQ(kPushUrl, push_stream->url().spec());
caseqe8340bc92016-04-20 00:02:57439
440 LoadTimingInfo load_timing_info;
bnca2fbdc9b2016-11-22 21:14:26441 EXPECT_TRUE(push_stream->GetLoadTimingInfo(&load_timing_info));
442 EXPECT_EQ(g_time_now, load_timing_info.push_start);
caseqe8340bc92016-04-20 00:02:57443 EXPECT_TRUE(load_timing_info.push_end.is_null());
444
bnc4e6e77482017-01-22 12:59:43445 StreamDelegateDoNothing push_delegate(push_stream->GetWeakPtr());
bnca2fbdc9b2016-11-22 21:14:26446 push_stream->SetDelegate(&push_delegate);
[email protected]6d116e1a2013-06-24 07:42:15447
bnca2fbdc9b2016-11-22 21:14:26448 data.Resume();
[email protected]6d116e1a2013-06-24 07:42:15449
bnca2fbdc9b2016-11-22 21:14:26450 EXPECT_TRUE(push_stream->GetLoadTimingInfo(&load_timing_info));
451 EXPECT_EQ(g_time_now, load_timing_info.push_start);
452 EXPECT_FALSE(load_timing_info.push_end.is_null());
453
454 EXPECT_THAT(delegate.WaitForClose(), IsOk());
Ryan Hamilton0239aac2018-05-19 00:03:13455 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
bnca2fbdc9b2016-11-22 21:14:26456 EXPECT_EQ(msg, delegate.TakeReceivedData());
[email protected]6d116e1a2013-06-24 07:42:15457
bnca2fbdc9b2016-11-22 21:14:26458 EXPECT_THAT(push_delegate.WaitForClose(), IsOk());
Ryan Hamilton0239aac2018-05-19 00:03:13459 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
bnca2fbdc9b2016-11-22 21:14:26460 EXPECT_EQ(pushed_msg, push_delegate.TakeReceivedData());
Bence Békya60ed842018-04-26 23:45:44461
462 // Finish async network reads and writes.
463 base::RunLoop().RunUntilIdle();
464
465 EXPECT_TRUE(data.AllWriteDataConsumed());
466 EXPECT_TRUE(data.AllReadDataConsumed());
[email protected]a7a265ef2010-12-08 18:05:57467}
468
bncd16676a2016-07-20 16:23:01469TEST_F(SpdyStreamTest, StreamError) {
Ryan Hamilton0239aac2018-05-19 00:03:13470 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bnca2fbdc9b2016-11-22 21:14:26471 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:41472 AddWrite(req);
[email protected]3d587372013-06-01 04:31:45473
Ryan Hamilton0239aac2018-05-19 00:03:13474 spdy::SpdySerializedFrame resp(
475 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41476 AddRead(resp);
[email protected]3d587372013-06-01 04:31:45477
Ryan Hamilton0239aac2018-05-19 00:03:13478 spdy::SpdySerializedFrame msg(
Bence Békyd74f4382018-02-20 18:26:19479 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
bncdf80d44fd2016-07-15 20:27:41480 AddWrite(msg);
[email protected]3d587372013-06-01 04:31:45481
Ryan Hamilton0239aac2018-05-19 00:03:13482 spdy::SpdySerializedFrame echo(
Bence Békyd74f4382018-02-20 18:26:19483 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
bncdf80d44fd2016-07-15 20:27:41484 AddRead(echo);
[email protected]3d587372013-06-01 04:31:45485
486 AddReadEOF();
[email protected]d245c342012-02-23 20:49:15487
Matt Reichhoff0049a0b72021-10-20 20:44:26488 RecordingNetLogObserver net_log_observer;
[email protected]d245c342012-02-23 20:49:15489
Ryan Sleevib8d7ea02018-05-07 20:01:01490 SequencedSocketData data(GetReads(), GetWrites());
[email protected]d245c342012-02-23 20:49:15491 MockConnect connect_data(SYNCHRONOUS, OK);
[email protected]dd54bd82012-07-19 23:44:57492 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:59493 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]d245c342012-02-23 20:49:15494
bnc032658ba2016-09-26 18:17:15495 AddSSLSocketData();
496
[email protected]795cbf82013-07-22 09:37:27497 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]d245c342012-02-23 20:49:15498
bnca2fbdc9b2016-11-22 21:14:26499 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
Matt Reichhoff0049a0b72021-10-20 20:44:26500 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST,
501 NetLogWithSource::Make(NetLogSourceType::NONE));
wezca1070932016-05-26 20:30:52502 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18503 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]d245c342012-02-23 20:49:15504
[email protected]194cfcf2013-05-23 21:44:44505 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
[email protected]34a4dea2013-03-13 00:42:30506 stream->SetDelegate(&delegate);
[email protected]d245c342012-02-23 20:49:15507
Bence Béky4c325e52020-10-22 20:48:01508 spdy::Http2HeaderBlock headers(
bnca2fbdc9b2016-11-22 21:14:26509 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
510 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
511 IsError(ERR_IO_PENDING));
[email protected]d245c342012-02-23 20:49:15512
robpercival214763f2016-07-01 23:27:01513 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
[email protected]218f4b62012-07-20 20:12:41514
Ryan Hamilton0239aac2018-05-19 00:03:13515 const spdy::SpdyStreamId stream_id = delegate.stream_id();
[email protected]c92f4b4542012-07-26 23:53:21516
[email protected]34a4dea2013-03-13 00:42:30517 EXPECT_TRUE(delegate.send_headers_completed());
Ryan Hamilton0239aac2018-05-19 00:03:13518 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
Bence Béky4e83f492018-05-13 23:14:25519 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
[email protected]09a8d9172013-04-17 19:23:49520 delegate.TakeReceivedData());
rch37de576c2015-05-17 20:28:17521 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d245c342012-02-23 20:49:15522
523 // Check that the NetLog was filled reasonably.
Matt Reichhoff0049a0b72021-10-20 20:44:26524 auto entries = net_log_observer.GetEntries();
[email protected]d245c342012-02-23 20:49:15525 EXPECT_LT(0u, entries.size());
526
527 // Check that we logged SPDY_STREAM_ERROR correctly.
ttuttle859dc7a2015-04-23 19:42:29528 int pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00529 entries, 0, NetLogEventType::HTTP2_STREAM_ERROR, NetLogEventPhase::NONE);
[email protected]d245c342012-02-23 20:49:15530
Eric Roman79cc7552019-07-19 02:17:54531 EXPECT_EQ(static_cast<int>(stream_id),
532 GetIntegerValueFromParams(entries[pos], "stream_id"));
[email protected]d245c342012-02-23 20:49:15533}
[email protected]a7a265ef2010-12-08 18:05:57534
bnca2fbdc9b2016-11-22 21:14:26535// Make sure that large blocks of data are properly split up into frame-sized
536// chunks for a request/response (i.e., an HTTP-like) stream.
bncd16676a2016-07-20 16:23:01537TEST_F(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
Ryan Hamilton0239aac2018-05-19 00:03:13538 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bnca2fbdc9b2016-11-22 21:14:26539 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:41540 AddWrite(req);
[email protected]3d587372013-06-01 04:31:45541
Bence Béky4e83f492018-05-13 23:14:25542 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
Ryan Hamilton0239aac2018-05-19 00:03:13543 spdy::SpdySerializedFrame chunk(
Bence Békyd74f4382018-02-20 18:26:19544 spdy_util_.ConstructSpdyDataFrame(1, chunk_data, false));
bncdf80d44fd2016-07-15 20:27:41545 AddWrite(chunk);
546 AddWrite(chunk);
[email protected]3d587372013-06-01 04:31:45547
Ryan Hamilton0239aac2018-05-19 00:03:13548 spdy::SpdySerializedFrame last_chunk(
Bence Békyd74f4382018-02-20 18:26:19549 spdy_util_.ConstructSpdyDataFrame(1, chunk_data, true));
bncdf80d44fd2016-07-15 20:27:41550 AddWrite(last_chunk);
[email protected]aa19cfc2013-05-23 16:41:38551
Ryan Hamilton0239aac2018-05-19 00:03:13552 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:41553 AddRead(resp);
[email protected]aa19cfc2013-05-23 16:41:38554
[email protected]3d587372013-06-01 04:31:45555 AddReadEOF();
556
Ryan Sleevib8d7ea02018-05-07 20:01:01557 SequencedSocketData data(GetReads(), GetWrites());
[email protected]aa19cfc2013-05-23 16:41:38558 MockConnect connect_data(SYNCHRONOUS, OK);
559 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:59560 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]aa19cfc2013-05-23 16:41:38561
bnc032658ba2016-09-26 18:17:15562 AddSSLSocketData();
563
[email protected]795cbf82013-07-22 09:37:27564 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]aa19cfc2013-05-23 16:41:38565
tfarina42834112016-09-22 13:38:20566 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:26567 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:52568 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18569 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]aa19cfc2013-05-23 16:41:38570
Bence Béky4e83f492018-05-13 23:14:25571 std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
[email protected]aa19cfc2013-05-23 16:41:38572 StreamDelegateWithBody delegate(stream, body_data);
573 stream->SetDelegate(&delegate);
574
Bence Béky4c325e52020-10-22 20:48:01575 spdy::Http2HeaderBlock headers(
bnca2fbdc9b2016-11-22 21:14:26576 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
577 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
578 IsError(ERR_IO_PENDING));
[email protected]aa19cfc2013-05-23 16:41:38579
robpercival214763f2016-07-01 23:27:01580 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
[email protected]aa19cfc2013-05-23 16:41:38581
582 EXPECT_TRUE(delegate.send_headers_completed());
Ryan Hamilton0239aac2018-05-19 00:03:13583 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
Bence Béky4e83f492018-05-13 23:14:25584 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
rch37de576c2015-05-17 20:28:17585 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]aa19cfc2013-05-23 16:41:38586}
587
bnca2fbdc9b2016-11-22 21:14:26588// Make sure that large blocks of data are properly split up into frame-sized
589// chunks for a bidirectional (i.e., non-HTTP-like) stream.
bncd16676a2016-07-20 16:23:01590TEST_F(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
Ryan Hamilton0239aac2018-05-19 00:03:13591 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bnca2fbdc9b2016-11-22 21:14:26592 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:41593 AddWrite(req);
[email protected]3d587372013-06-01 04:31:45594
Ryan Hamilton0239aac2018-05-19 00:03:13595 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:41596 AddRead(resp);
[email protected]3d587372013-06-01 04:31:45597
Bence Béky4e83f492018-05-13 23:14:25598 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
Ryan Hamilton0239aac2018-05-19 00:03:13599 spdy::SpdySerializedFrame chunk(
Bence Békyd74f4382018-02-20 18:26:19600 spdy_util_.ConstructSpdyDataFrame(1, chunk_data, false));
bncdf80d44fd2016-07-15 20:27:41601 AddWrite(chunk);
602 AddWrite(chunk);
603 AddWrite(chunk);
[email protected]aa19cfc2013-05-23 16:41:38604
[email protected]3d587372013-06-01 04:31:45605 AddReadEOF();
[email protected]aa19cfc2013-05-23 16:41:38606
Ryan Sleevib8d7ea02018-05-07 20:01:01607 SequencedSocketData data(GetReads(), GetWrites());
[email protected]aa19cfc2013-05-23 16:41:38608 MockConnect connect_data(SYNCHRONOUS, OK);
609 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:59610 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]aa19cfc2013-05-23 16:41:38611
bnc032658ba2016-09-26 18:17:15612 AddSSLSocketData();
613
[email protected]795cbf82013-07-22 09:37:27614 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]aa19cfc2013-05-23 16:41:38615
tfarina42834112016-09-22 13:38:20616 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:26617 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:52618 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18619 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]aa19cfc2013-05-23 16:41:38620
Bence Béky4e83f492018-05-13 23:14:25621 std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
[email protected]194cfcf2013-05-23 21:44:44622 StreamDelegateSendImmediate delegate(stream, body_data);
[email protected]aa19cfc2013-05-23 16:41:38623 stream->SetDelegate(&delegate);
624
Bence Béky4c325e52020-10-22 20:48:01625 spdy::Http2HeaderBlock headers(
bnca2fbdc9b2016-11-22 21:14:26626 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
627 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
628 IsError(ERR_IO_PENDING));
[email protected]aa19cfc2013-05-23 16:41:38629
robpercival214763f2016-07-01 23:27:01630 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
[email protected]aa19cfc2013-05-23 16:41:38631
632 EXPECT_TRUE(delegate.send_headers_completed());
Ryan Hamilton0239aac2018-05-19 00:03:13633 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
Bence Béky4e83f492018-05-13 23:14:25634 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
rch37de576c2015-05-17 20:28:17635 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]aa19cfc2013-05-23 16:41:38636}
637
bnca2fbdc9b2016-11-22 21:14:26638// Receiving a header with uppercase ASCII should result in a protocol error.
bncd16676a2016-07-20 16:23:01639TEST_F(SpdyStreamTest, UpperCaseHeaders) {
Ryan Hamilton0239aac2018-05-19 00:03:13640 spdy::SpdySerializedFrame req(
641 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnca2fbdc9b2016-11-22 21:14:26642 AddWrite(req);
[email protected]6d116e1a2013-06-24 07:42:15643
644 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
Ryan Hamilton0239aac2018-05-19 00:03:13645 spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(
Daniel Cheng5feb16f2022-02-28 06:52:07646 kExtraHeaders, std::size(kExtraHeaders) / 2, 1));
bncdf80d44fd2016-07-15 20:27:41647 AddRead(reply);
[email protected]6d116e1a2013-06-24 07:42:15648
Ryan Hamilton0239aac2018-05-19 00:03:13649 spdy::SpdySerializedFrame rst(
650 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
bncdf80d44fd2016-07-15 20:27:41651 AddWrite(rst);
[email protected]6d116e1a2013-06-24 07:42:15652
653 AddReadEOF();
654
Ryan Sleevib8d7ea02018-05-07 20:01:01655 SequencedSocketData data(GetReads(), GetWrites());
[email protected]6d116e1a2013-06-24 07:42:15656 MockConnect connect_data(SYNCHRONOUS, OK);
657 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:59658 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6d116e1a2013-06-24 07:42:15659
bnc032658ba2016-09-26 18:17:15660 AddSSLSocketData();
661
[email protected]795cbf82013-07-22 09:37:27662 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]6d116e1a2013-06-24 07:42:15663
tfarina42834112016-09-22 13:38:20664 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:26665 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:52666 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18667 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]6d116e1a2013-06-24 07:42:15668
669 StreamDelegateDoNothing delegate(stream);
670 stream->SetDelegate(&delegate);
671
Bence Béky4c325e52020-10-22 20:48:01672 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:13673 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnca2fbdc9b2016-11-22 21:14:26674 EXPECT_THAT(
675 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
676 IsError(ERR_IO_PENDING));
[email protected]6d116e1a2013-06-24 07:42:15677
Bence Békyd0d69502019-06-25 19:47:18678 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
bnc4c214312016-11-28 16:49:15679
bnceb9aa7112017-01-05 01:03:46680 // Finish async network reads and writes.
681 base::RunLoop().RunUntilIdle();
682
bnc4c214312016-11-28 16:49:15683 EXPECT_TRUE(data.AllWriteDataConsumed());
684 EXPECT_TRUE(data.AllReadDataConsumed());
[email protected]6d116e1a2013-06-24 07:42:15685}
686
bnca2fbdc9b2016-11-22 21:14:26687// Receiving a header with uppercase ASCII should result in a protocol error
688// even for a push stream.
bncd16676a2016-07-20 16:23:01689TEST_F(SpdyStreamTest, UpperCaseHeadersOnPush) {
Ryan Hamilton0239aac2018-05-19 00:03:13690 spdy::SpdySerializedFrame req(
691 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnca2fbdc9b2016-11-22 21:14:26692 AddWrite(req);
[email protected]6d116e1a2013-06-24 07:42:15693
Ryan Hamilton0239aac2018-05-19 00:03:13694 spdy::SpdySerializedFrame reply(
695 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41696 AddRead(reply);
[email protected]6d116e1a2013-06-24 07:42:15697
bnc4c214312016-11-28 16:49:15698 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
Ryan Hamilton0239aac2018-05-19 00:03:13699 spdy::SpdySerializedFrame push(spdy_util_.ConstructSpdyPush(
Daniel Cheng5feb16f2022-02-28 06:52:07700 kExtraHeaders, std::size(kExtraHeaders) / 2, 2, 1, kPushUrl));
bncdf80d44fd2016-07-15 20:27:41701 AddRead(push);
[email protected]6d116e1a2013-06-24 07:42:15702
Ryan Hamilton0239aac2018-05-19 00:03:13703 spdy::SpdySerializedFrame priority(
tombergan5d22c182017-01-11 02:05:35704 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
705 AddWrite(priority);
706
Ryan Hamilton0239aac2018-05-19 00:03:13707 spdy::SpdySerializedFrame rst(
708 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_PROTOCOL_ERROR));
bncdf80d44fd2016-07-15 20:27:41709 AddWrite(rst);
[email protected]6d116e1a2013-06-24 07:42:15710
mmenkee24011922015-12-17 22:12:59711 AddReadPause();
712
[email protected]6d116e1a2013-06-24 07:42:15713 AddReadEOF();
714
Ryan Sleevib8d7ea02018-05-07 20:01:01715 SequencedSocketData data(GetReads(), GetWrites());
[email protected]6d116e1a2013-06-24 07:42:15716 MockConnect connect_data(SYNCHRONOUS, OK);
717 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:59718 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6d116e1a2013-06-24 07:42:15719
bnc032658ba2016-09-26 18:17:15720 AddSSLSocketData();
721
[email protected]795cbf82013-07-22 09:37:27722 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]6d116e1a2013-06-24 07:42:15723
tfarina42834112016-09-22 13:38:20724 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:26725 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:52726 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18727 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]6d116e1a2013-06-24 07:42:15728
729 StreamDelegateDoNothing delegate(stream);
730 stream->SetDelegate(&delegate);
731
Bence Béky4c325e52020-10-22 20:48:01732 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:13733 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnca2fbdc9b2016-11-22 21:14:26734 EXPECT_THAT(
735 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
736 IsError(ERR_IO_PENDING));
[email protected]6d116e1a2013-06-24 07:42:15737
mmenkee24011922015-12-17 22:12:59738 data.RunUntilPaused();
[email protected]6d116e1a2013-06-24 07:42:15739
Bence Béky7bf94362018-01-10 13:19:36740 EXPECT_EQ(0u, num_pushed_streams(session));
[email protected]6d116e1a2013-06-24 07:42:15741
mmenkee24011922015-12-17 22:12:59742 data.Resume();
[email protected]6d116e1a2013-06-24 07:42:15743
robpercival214763f2016-07-01 23:27:01744 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
bnc4c214312016-11-28 16:49:15745
746 EXPECT_TRUE(data.AllWriteDataConsumed());
747 EXPECT_TRUE(data.AllReadDataConsumed());
[email protected]6d116e1a2013-06-24 07:42:15748}
749
bnc4c214312016-11-28 16:49:15750TEST_F(SpdyStreamTest, HeadersMustHaveStatus) {
Ryan Hamilton0239aac2018-05-19 00:03:13751 spdy::SpdySerializedFrame req(
752 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnc4c214312016-11-28 16:49:15753 AddWrite(req);
754
755 // Response headers without ":status" header field: protocol error.
Bence Béky4c325e52020-10-22 20:48:01756 spdy::Http2HeaderBlock header_block_without_status;
Ryan Hamilton0239aac2018-05-19 00:03:13757 header_block_without_status[spdy::kHttp2MethodHeader] = "GET";
758 header_block_without_status[spdy::kHttp2AuthorityHeader] = "www.example.org";
759 header_block_without_status[spdy::kHttp2SchemeHeader] = "https";
760 header_block_without_status[spdy::kHttp2PathHeader] = "/";
761 spdy::SpdySerializedFrame reply(
bnc4c214312016-11-28 16:49:15762 spdy_util_.ConstructSpdyReply(1, std::move(header_block_without_status)));
763 AddRead(reply);
764
Ryan Hamilton0239aac2018-05-19 00:03:13765 spdy::SpdySerializedFrame rst(
766 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
bnc4c214312016-11-28 16:49:15767 AddWrite(rst);
768
769 AddReadEOF();
770
Ryan Sleevib8d7ea02018-05-07 20:01:01771 SequencedSocketData data(GetReads(), GetWrites());
bnc4c214312016-11-28 16:49:15772 MockConnect connect_data(SYNCHRONOUS, OK);
773 data.set_connect_data(connect_data);
774 session_deps_.socket_factory->AddSocketDataProvider(&data);
775
776 AddSSLSocketData();
777
778 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
779
780 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
781 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
782 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18783 EXPECT_EQ(kDefaultUrl, stream->url().spec());
bnc4c214312016-11-28 16:49:15784
785 StreamDelegateDoNothing delegate(stream);
786 stream->SetDelegate(&delegate);
787
Bence Béky4c325e52020-10-22 20:48:01788 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:13789 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc4c214312016-11-28 16:49:15790 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
791 NO_MORE_DATA_TO_SEND));
bnc4c214312016-11-28 16:49:15792
Bence Békyd0d69502019-06-25 19:47:18793 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
bnc4c214312016-11-28 16:49:15794
bnceb9aa7112017-01-05 01:03:46795 // Finish async network reads and writes.
796 base::RunLoop().RunUntilIdle();
797
bnc4c214312016-11-28 16:49:15798 EXPECT_TRUE(data.AllWriteDataConsumed());
799 EXPECT_TRUE(data.AllReadDataConsumed());
800}
801
802TEST_F(SpdyStreamTest, HeadersMustHaveStatusOnPushedStream) {
Ryan Hamilton0239aac2018-05-19 00:03:13803 spdy::SpdySerializedFrame req(
804 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnca2fbdc9b2016-11-22 21:14:26805 AddWrite(req);
[email protected]6d116e1a2013-06-24 07:42:15806
Ryan Hamilton0239aac2018-05-19 00:03:13807 spdy::SpdySerializedFrame reply(
808 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41809 AddRead(reply);
[email protected]6d116e1a2013-06-24 07:42:15810
Ryan Hamilton0239aac2018-05-19 00:03:13811 spdy::SpdySerializedFrame push_promise(spdy_util_.ConstructSpdyPushPromise(
Bence Békyf1d78522018-01-11 01:16:50812 1, 2, spdy_util_.ConstructGetHeaderBlock(kPushUrl)));
bnc4c214312016-11-28 16:49:15813 AddRead(push_promise);
[email protected]6d116e1a2013-06-24 07:42:15814
Ryan Hamilton0239aac2018-05-19 00:03:13815 spdy::SpdySerializedFrame priority(
tombergan5d22c182017-01-11 02:05:35816 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
817 AddWrite(priority);
818
bnc4c214312016-11-28 16:49:15819 // Response headers without ":status" header field: protocol error.
Bence Béky4c325e52020-10-22 20:48:01820 spdy::Http2HeaderBlock header_block_without_status;
Ryan Hamilton0239aac2018-05-19 00:03:13821 header_block_without_status[spdy::kHttp2MethodHeader] = "GET";
822 header_block_without_status[spdy::kHttp2AuthorityHeader] = "www.example.org";
823 header_block_without_status[spdy::kHttp2SchemeHeader] = "https";
824 header_block_without_status[spdy::kHttp2PathHeader] = "/";
825 spdy::SpdySerializedFrame pushed_reply(
bnc4c214312016-11-28 16:49:15826 spdy_util_.ConstructSpdyReply(2, std::move(header_block_without_status)));
827 AddRead(pushed_reply);
mmenkee24011922015-12-17 22:12:59828
Ryan Hamilton0239aac2018-05-19 00:03:13829 spdy::SpdySerializedFrame rst(
830 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_PROTOCOL_ERROR));
bncdf80d44fd2016-07-15 20:27:41831 AddWrite(rst);
[email protected]6d116e1a2013-06-24 07:42:15832
Ryan Hamilton0239aac2018-05-19 00:03:13833 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:19834 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
bnc4c214312016-11-28 16:49:15835 AddRead(body);
836
[email protected]6d116e1a2013-06-24 07:42:15837 AddReadEOF();
838
Ryan Sleevib8d7ea02018-05-07 20:01:01839 SequencedSocketData data(GetReads(), GetWrites());
[email protected]6d116e1a2013-06-24 07:42:15840 MockConnect connect_data(SYNCHRONOUS, OK);
841 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:59842 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6d116e1a2013-06-24 07:42:15843
bnc032658ba2016-09-26 18:17:15844 AddSSLSocketData();
845
[email protected]795cbf82013-07-22 09:37:27846 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]6d116e1a2013-06-24 07:42:15847
tfarina42834112016-09-22 13:38:20848 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:26849 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:52850 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18851 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]6d116e1a2013-06-24 07:42:15852
853 StreamDelegateDoNothing delegate(stream);
854 stream->SetDelegate(&delegate);
855
Bence Béky4c325e52020-10-22 20:48:01856 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:13857 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnca2fbdc9b2016-11-22 21:14:26858 EXPECT_THAT(
859 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
860 IsError(ERR_IO_PENDING));
[email protected]6d116e1a2013-06-24 07:42:15861
bnc4c214312016-11-28 16:49:15862 EXPECT_THAT(delegate.WaitForClose(), IsOk());
Ryan Hamilton0239aac2018-05-19 00:03:13863 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
Bence Béky4e83f492018-05-13 23:14:25864 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
bnc4c214312016-11-28 16:49:15865 delegate.TakeReceivedData());
[email protected]6d116e1a2013-06-24 07:42:15866
bnceb9aa7112017-01-05 01:03:46867 // Finish async network reads and writes.
868 base::RunLoop().RunUntilIdle();
869
bnc4c214312016-11-28 16:49:15870 EXPECT_TRUE(data.AllWriteDataConsumed());
871 EXPECT_TRUE(data.AllReadDataConsumed());
[email protected]6d116e1a2013-06-24 07:42:15872}
873
bnc4c214312016-11-28 16:49:15874TEST_F(SpdyStreamTest, HeadersMustPreceedData) {
Ryan Hamilton0239aac2018-05-19 00:03:13875 spdy::SpdySerializedFrame req(
876 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnc4c214312016-11-28 16:49:15877 AddWrite(req);
878
879 // Response body not preceeded by headers: protocol error.
Ryan Hamilton0239aac2018-05-19 00:03:13880 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:19881 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
bnc4c214312016-11-28 16:49:15882 AddRead(body);
883
Ryan Hamilton0239aac2018-05-19 00:03:13884 spdy::SpdySerializedFrame rst(
885 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
bnc4c214312016-11-28 16:49:15886 AddWrite(rst);
887
888 AddReadEOF();
889
Ryan Sleevib8d7ea02018-05-07 20:01:01890 SequencedSocketData data(GetReads(), GetWrites());
bnc4c214312016-11-28 16:49:15891 MockConnect connect_data(SYNCHRONOUS, OK);
892 data.set_connect_data(connect_data);
893 session_deps_.socket_factory->AddSocketDataProvider(&data);
894
895 AddSSLSocketData();
896
897 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
898
899 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
900 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
901 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18902 EXPECT_EQ(kDefaultUrl, stream->url().spec());
bnc4c214312016-11-28 16:49:15903
904 StreamDelegateDoNothing delegate(stream);
905 stream->SetDelegate(&delegate);
906
Bence Béky4c325e52020-10-22 20:48:01907 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:13908 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc4c214312016-11-28 16:49:15909 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
910 NO_MORE_DATA_TO_SEND));
bnc4c214312016-11-28 16:49:15911
Bence Békyd0d69502019-06-25 19:47:18912 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
bnc4c214312016-11-28 16:49:15913}
914
915TEST_F(SpdyStreamTest, HeadersMustPreceedDataOnPushedStream) {
Ryan Hamilton0239aac2018-05-19 00:03:13916 spdy::SpdySerializedFrame req(
917 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnca2fbdc9b2016-11-22 21:14:26918 AddWrite(req);
[email protected]6d116e1a2013-06-24 07:42:15919
Ryan Hamilton0239aac2018-05-19 00:03:13920 spdy::SpdySerializedFrame reply(
921 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41922 AddRead(reply);
[email protected]6d116e1a2013-06-24 07:42:15923
Ryan Hamilton0239aac2018-05-19 00:03:13924 spdy::SpdySerializedFrame push_promise(spdy_util_.ConstructSpdyPushPromise(
Bence Békyf1d78522018-01-11 01:16:50925 1, 2, spdy_util_.ConstructGetHeaderBlock(kPushUrl)));
bnc4c214312016-11-28 16:49:15926 AddRead(push_promise);
[email protected]6d116e1a2013-06-24 07:42:15927
Ryan Hamilton0239aac2018-05-19 00:03:13928 spdy::SpdySerializedFrame priority(
tombergan5d22c182017-01-11 02:05:35929 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
930 AddWrite(priority);
931
Ryan Hamilton0239aac2018-05-19 00:03:13932 spdy::SpdySerializedFrame pushed_body(
Bence Békyd74f4382018-02-20 18:26:19933 spdy_util_.ConstructSpdyDataFrame(2, kPostBodyStringPiece, true));
bnc4c214312016-11-28 16:49:15934 AddRead(pushed_body);
mmenkee24011922015-12-17 22:12:59935
Ryan Hamilton0239aac2018-05-19 00:03:13936 spdy::SpdySerializedFrame rst(
937 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_PROTOCOL_ERROR));
bncdf80d44fd2016-07-15 20:27:41938 AddWrite(rst);
[email protected]6d116e1a2013-06-24 07:42:15939
Ryan Hamilton0239aac2018-05-19 00:03:13940 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:19941 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
bnc4c214312016-11-28 16:49:15942 AddRead(body);
943
[email protected]6d116e1a2013-06-24 07:42:15944 AddReadEOF();
945
Ryan Sleevib8d7ea02018-05-07 20:01:01946 SequencedSocketData data(GetReads(), GetWrites());
[email protected]6d116e1a2013-06-24 07:42:15947 MockConnect connect_data(SYNCHRONOUS, OK);
948 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:59949 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6d116e1a2013-06-24 07:42:15950
bnc032658ba2016-09-26 18:17:15951 AddSSLSocketData();
952
[email protected]795cbf82013-07-22 09:37:27953 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]6d116e1a2013-06-24 07:42:15954
tfarina42834112016-09-22 13:38:20955 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:26956 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:52957 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:18958 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]6d116e1a2013-06-24 07:42:15959
960 StreamDelegateDoNothing delegate(stream);
961 stream->SetDelegate(&delegate);
962
Bence Béky4c325e52020-10-22 20:48:01963 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:13964 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnca2fbdc9b2016-11-22 21:14:26965 EXPECT_THAT(
966 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
967 IsError(ERR_IO_PENDING));
[email protected]6d116e1a2013-06-24 07:42:15968
bnc4c214312016-11-28 16:49:15969 EXPECT_THAT(delegate.WaitForClose(), IsOk());
Ryan Hamilton0239aac2018-05-19 00:03:13970 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy::kHttp2StatusHeader));
Bence Béky4e83f492018-05-13 23:14:25971 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
bnc4c214312016-11-28 16:49:15972 delegate.TakeReceivedData());
[email protected]6d116e1a2013-06-24 07:42:15973
bnceb9aa7112017-01-05 01:03:46974 // Finish async network reads and writes.
975 base::RunLoop().RunUntilIdle();
976
bnc4c214312016-11-28 16:49:15977 EXPECT_TRUE(data.AllWriteDataConsumed());
978 EXPECT_TRUE(data.AllReadDataConsumed());
979}
[email protected]6d116e1a2013-06-24 07:42:15980
bnc4c214312016-11-28 16:49:15981TEST_F(SpdyStreamTest, TrailersMustNotFollowTrailers) {
Ryan Hamilton0239aac2018-05-19 00:03:13982 spdy::SpdySerializedFrame req(
983 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnc4c214312016-11-28 16:49:15984 AddWrite(req);
[email protected]6d116e1a2013-06-24 07:42:15985
Ryan Hamilton0239aac2018-05-19 00:03:13986 spdy::SpdySerializedFrame reply(
987 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc4c214312016-11-28 16:49:15988 AddRead(reply);
[email protected]6d116e1a2013-06-24 07:42:15989
Ryan Hamilton0239aac2018-05-19 00:03:13990 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:19991 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
bnc4c214312016-11-28 16:49:15992 AddRead(body);
[email protected]6d116e1a2013-06-24 07:42:15993
Bence Béky4c325e52020-10-22 20:48:01994 spdy::Http2HeaderBlock trailers_block;
bnc4c214312016-11-28 16:49:15995 trailers_block["foo"] = "bar";
Ryan Hamilton0239aac2018-05-19 00:03:13996 spdy::SpdySerializedFrame first_trailers(
997 spdy_util_.ConstructSpdyResponseHeaders(1, std::move(trailers_block),
998 false));
bnc4c214312016-11-28 16:49:15999 AddRead(first_trailers);
1000
1001 // Trailers following trailers: procotol error.
Ryan Hamilton0239aac2018-05-19 00:03:131002 spdy::SpdySerializedFrame second_trailers(
1003 spdy_util_.ConstructSpdyResponseHeaders(1, std::move(trailers_block),
1004 true));
bnc4c214312016-11-28 16:49:151005 AddRead(second_trailers);
1006
Ryan Hamilton0239aac2018-05-19 00:03:131007 spdy::SpdySerializedFrame rst(
1008 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
bnc4c214312016-11-28 16:49:151009 AddWrite(rst);
1010
1011 AddReadEOF();
1012
Ryan Sleevib8d7ea02018-05-07 20:01:011013 SequencedSocketData data(GetReads(), GetWrites());
bnc4c214312016-11-28 16:49:151014 MockConnect connect_data(SYNCHRONOUS, OK);
1015 data.set_connect_data(connect_data);
1016 session_deps_.socket_factory->AddSocketDataProvider(&data);
1017
1018 AddSSLSocketData();
1019
1020 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1021
1022 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1023 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1024 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:181025 EXPECT_EQ(kDefaultUrl, stream->url().spec());
bnc4c214312016-11-28 16:49:151026
1027 StreamDelegateDoNothing delegate(stream);
1028 stream->SetDelegate(&delegate);
1029
Bence Béky4c325e52020-10-22 20:48:011030 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:131031 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc4c214312016-11-28 16:49:151032 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1033 NO_MORE_DATA_TO_SEND));
bnc4c214312016-11-28 16:49:151034
Bence Békyd0d69502019-06-25 19:47:181035 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
bnc4c214312016-11-28 16:49:151036
bnceb9aa7112017-01-05 01:03:461037 // Finish async network reads and writes.
1038 base::RunLoop().RunUntilIdle();
1039
bnc4c214312016-11-28 16:49:151040 EXPECT_TRUE(data.AllWriteDataConsumed());
1041 EXPECT_TRUE(data.AllReadDataConsumed());
1042}
1043
1044TEST_F(SpdyStreamTest, DataMustNotFollowTrailers) {
Ryan Hamilton0239aac2018-05-19 00:03:131045 spdy::SpdySerializedFrame req(
1046 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnc4c214312016-11-28 16:49:151047 AddWrite(req);
1048
Ryan Hamilton0239aac2018-05-19 00:03:131049 spdy::SpdySerializedFrame reply(
1050 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc4c214312016-11-28 16:49:151051 AddRead(reply);
1052
Ryan Hamilton0239aac2018-05-19 00:03:131053 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:191054 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
bnc4c214312016-11-28 16:49:151055 AddRead(body);
1056
Bence Béky4c325e52020-10-22 20:48:011057 spdy::Http2HeaderBlock trailers_block;
bnc4c214312016-11-28 16:49:151058 trailers_block["foo"] = "bar";
Ryan Hamilton0239aac2018-05-19 00:03:131059 spdy::SpdySerializedFrame trailers(spdy_util_.ConstructSpdyResponseHeaders(
bnc4c214312016-11-28 16:49:151060 1, std::move(trailers_block), false));
1061 AddRead(trailers);
1062
1063 // DATA frame following trailers: protocol error.
1064 AddRead(body);
1065
Ryan Hamilton0239aac2018-05-19 00:03:131066 spdy::SpdySerializedFrame rst(
1067 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
bnc4c214312016-11-28 16:49:151068 AddWrite(rst);
1069
1070 AddReadEOF();
1071
Ryan Sleevib8d7ea02018-05-07 20:01:011072 SequencedSocketData data(GetReads(), GetWrites());
bnc4c214312016-11-28 16:49:151073 MockConnect connect_data(SYNCHRONOUS, OK);
1074 data.set_connect_data(connect_data);
1075 session_deps_.socket_factory->AddSocketDataProvider(&data);
1076
1077 AddSSLSocketData();
1078
1079 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1080
1081 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1082 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1083 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:181084 EXPECT_EQ(kDefaultUrl, stream->url().spec());
bnc4c214312016-11-28 16:49:151085
1086 StreamDelegateDoNothing delegate(stream);
1087 stream->SetDelegate(&delegate);
1088
Bence Béky4c325e52020-10-22 20:48:011089 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:131090 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc4c214312016-11-28 16:49:151091 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1092 NO_MORE_DATA_TO_SEND));
bnc4c214312016-11-28 16:49:151093
Bence Békyd0d69502019-06-25 19:47:181094 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
bnc4c214312016-11-28 16:49:151095
bnceb9aa7112017-01-05 01:03:461096 // Finish async network reads and writes.
1097 base::RunLoop().RunUntilIdle();
1098
bnc4c214312016-11-28 16:49:151099 EXPECT_TRUE(data.AllWriteDataConsumed());
1100 EXPECT_TRUE(data.AllReadDataConsumed());
[email protected]6d116e1a2013-06-24 07:42:151101}
1102
Hiroki Nakagawad67642b592020-12-10 13:26:351103class SpdyStreamTestWithMockClock : public SpdyStreamTest {
1104 public:
1105 SpdyStreamTestWithMockClock()
1106 : SpdyStreamTest(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
1107
1108 void Initialize() {
1109 // Set up the sequenced socket data.
1110 data_ = std::make_unique<SequencedSocketData>(GetReads(), GetWrites());
1111 MockConnect connect_data(SYNCHRONOUS, OK);
1112 data_->set_connect_data(connect_data);
1113 session_deps_.socket_factory->AddSocketDataProvider(data_.get());
1114
1115 AddSSLSocketData();
1116
1117 // Set up the SPDY stream.
1118 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1119 stream_ = CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
1120 url_, LOWEST, NetLogWithSource());
1121 ASSERT_TRUE(stream_);
1122 EXPECT_EQ(kDefaultUrl, stream_->url().spec());
1123
1124 DCHECK(!delegate_);
1125 delegate_ = std::make_unique<StreamDelegateDoNothing>(stream_);
1126 stream_->SetDelegate(delegate_.get());
1127 }
1128
1129 void RunUntilNextPause() {
1130 if (data_->IsPaused())
1131 data_->Resume();
1132 data_->RunUntilPaused();
1133 }
1134
1135 int RunUntilClose() {
1136 if (data_->IsPaused())
1137 data_->Resume();
1138 return delegate_->WaitForClose();
1139 }
1140
1141 SequencedSocketData& data() { return *data_; }
1142 base::WeakPtr<SpdyStream> stream() { return stream_; }
1143 StreamDelegateDoNothing& delegate() { return *delegate_; }
1144
1145 private:
1146 std::unique_ptr<SequencedSocketData> data_;
1147 base::WeakPtr<SpdyStream> stream_;
1148 std::unique_ptr<StreamDelegateDoNothing> delegate_;
1149};
1150
1151// Test that the response start time is recorded for non-informational response.
1152TEST_F(SpdyStreamTestWithMockClock, NonInformationalResponseStart) {
1153 // Set up the request.
Ryan Hamilton0239aac2018-05-19 00:03:131154 spdy::SpdySerializedFrame req(
1155 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncc9f762a2016-12-06 20:38:231156 AddWrite(req);
1157
Hiroki Nakagawad67642b592020-12-10 13:26:351158 // Set up the response headers.
1159 spdy::SpdySerializedFrame reply(
1160 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1161 // Separate the headers into 2 fragments and add pauses between the fragments
1162 // so that the test runner can advance the mock clock to test timing
1163 // information.
1164 AddMockRead(ReadFrameExceptForLastByte(reply));
1165 AddReadPause();
1166 AddMockRead(LastByteOfReadFrame(reply));
1167 AddReadPause();
1168
1169 // Set up the response body.
1170 spdy::SpdySerializedFrame body(
1171 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
1172 AddRead(body);
1173 AddReadEOF();
1174
1175 // Set up the sequenced socket data and the spdy stream.
1176 Initialize();
1177
1178 // Send a request.
1179 spdy::Http2HeaderBlock headers(
1180 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1181 EXPECT_EQ(ERR_IO_PENDING, stream()->SendRequestHeaders(std::move(headers),
1182 NO_MORE_DATA_TO_SEND));
Peter Kastinge5a38ed2021-10-02 03:06:351183 AdvanceClock(base::Seconds(1));
Hiroki Nakagawad67642b592020-12-10 13:26:351184
1185 // The receive headers start time should be captured at this time.
1186 base::TimeTicks expected_receive_headers_start_time = base::TimeTicks::Now();
1187
1188 // Read the first header fragment.
1189 RunUntilNextPause();
Peter Kastinge5a38ed2021-10-02 03:06:351190 AdvanceClock(base::Seconds(1));
Hiroki Nakagawad67642b592020-12-10 13:26:351191 // Read the second header fragment.
1192 RunUntilNextPause();
Peter Kastinge5a38ed2021-10-02 03:06:351193 AdvanceClock(base::Seconds(1));
Hiroki Nakagawad67642b592020-12-10 13:26:351194 EXPECT_EQ("200", delegate().GetResponseHeaderValue(spdy::kHttp2StatusHeader));
1195
1196 // Read the response body.
1197 EXPECT_THAT(RunUntilClose(), IsOk());
1198 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
1199 delegate().TakeReceivedData());
1200
1201 // Finish async network reads and writes.
1202 base::RunLoop().RunUntilIdle();
1203 EXPECT_TRUE(data().AllWriteDataConsumed());
1204 EXPECT_TRUE(data().AllReadDataConsumed());
1205
1206 // No informational responses were served. The response start time should be
1207 // equal to the non-informational response start time.
1208 const LoadTimingInfo& load_timing_info = delegate().GetLoadTimingInfo();
1209 EXPECT_EQ(load_timing_info.receive_headers_start,
1210 expected_receive_headers_start_time);
1211 EXPECT_EQ(load_timing_info.receive_non_informational_headers_start,
1212 expected_receive_headers_start_time);
1213}
1214
1215TEST_F(SpdyStreamTestWithMockClock, InformationalHeaders) {
1216 // Set up the request.
1217 spdy::SpdySerializedFrame req(
1218 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1219 AddWrite(req);
1220
1221 // Set up the informational response headers.
Bence Béky4c325e52020-10-22 20:48:011222 spdy::Http2HeaderBlock informational_headers;
bncc9f762a2016-12-06 20:38:231223 informational_headers[":status"] = "100";
Ryan Hamilton0239aac2018-05-19 00:03:131224 spdy::SpdySerializedFrame informational_response(
bncc9f762a2016-12-06 20:38:231225 spdy_util_.ConstructSpdyResponseHeaders(
1226 1, std::move(informational_headers), false));
Hiroki Nakagawad67642b592020-12-10 13:26:351227 // Separate the headers into 2 fragments and add pauses between the fragments
1228 // so that the test runner can advance the mock clock to test timing
1229 // information.
1230 AddMockRead(ReadFrameExceptForLastByte(informational_response));
1231 AddReadPause();
1232 AddMockRead(LastByteOfReadFrame(informational_response));
1233 AddReadPause();
bncc9f762a2016-12-06 20:38:231234
Hiroki Nakagawad67642b592020-12-10 13:26:351235 // Set up the non-informational response headers and body.
Ryan Hamilton0239aac2018-05-19 00:03:131236 spdy::SpdySerializedFrame reply(
1237 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncc9f762a2016-12-06 20:38:231238 AddRead(reply);
Hiroki Nakagawad67642b592020-12-10 13:26:351239 AddReadPause();
Ryan Hamilton0239aac2018-05-19 00:03:131240 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:191241 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
bncc9f762a2016-12-06 20:38:231242 AddRead(body);
bncc9f762a2016-12-06 20:38:231243 AddReadEOF();
1244
Hiroki Nakagawad67642b592020-12-10 13:26:351245 // Set up the sequenced socket data and the spdy stream.
1246 Initialize();
bncc9f762a2016-12-06 20:38:231247
Hiroki Nakagawad67642b592020-12-10 13:26:351248 // Send a request.
Bence Béky4c325e52020-10-22 20:48:011249 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:131250 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
Hiroki Nakagawad67642b592020-12-10 13:26:351251 EXPECT_EQ(ERR_IO_PENDING, stream()->SendRequestHeaders(std::move(headers),
1252 NO_MORE_DATA_TO_SEND));
Peter Kastinge5a38ed2021-10-02 03:06:351253 AdvanceClock(base::Seconds(1));
bncc9f762a2016-12-06 20:38:231254
Hiroki Nakagawad67642b592020-12-10 13:26:351255 // The receive headers start time should be captured at this time.
1256 base::TimeTicks expected_receive_headers_start_time = base::TimeTicks::Now();
1257
1258 // Read the first header fragment of the informational response.
1259 RunUntilNextPause();
Peter Kastinge5a38ed2021-10-02 03:06:351260 AdvanceClock(base::Seconds(1));
Hiroki Nakagawad67642b592020-12-10 13:26:351261 // Read the second header fragment of the informational response.
1262 RunUntilNextPause();
Peter Kastinge5a38ed2021-10-02 03:06:351263 AdvanceClock(base::Seconds(1));
Hiroki Nakagawad67642b592020-12-10 13:26:351264 // We don't check the status code of the informational headers here because
1265 // SpdyStream doesn't propagate it to the delegate.
1266
1267 // The receive non-informational headers start time should be captured at this
1268 // time.
1269 base::TimeTicks expected_receive_non_informational_headers_start_time =
1270 base::TimeTicks::Now();
1271
1272 // Read the non-informational response headers.
1273 RunUntilNextPause();
Peter Kastinge5a38ed2021-10-02 03:06:351274 AdvanceClock(base::Seconds(1));
Hiroki Nakagawad67642b592020-12-10 13:26:351275 EXPECT_EQ("200", delegate().GetResponseHeaderValue(spdy::kHttp2StatusHeader));
1276
1277 // Read the response body.
1278 EXPECT_THAT(RunUntilClose(), IsOk());
Bence Béky4e83f492018-05-13 23:14:251279 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
Hiroki Nakagawad67642b592020-12-10 13:26:351280 delegate().TakeReceivedData());
bncc9f762a2016-12-06 20:38:231281
bnceb9aa7112017-01-05 01:03:461282 // Finish async network reads and writes.
1283 base::RunLoop().RunUntilIdle();
Hiroki Nakagawad67642b592020-12-10 13:26:351284 EXPECT_TRUE(data().AllWriteDataConsumed());
1285 EXPECT_TRUE(data().AllReadDataConsumed());
bnceb9aa7112017-01-05 01:03:461286
Hiroki Nakagawad67642b592020-12-10 13:26:351287 const LoadTimingInfo& load_timing_info = delegate().GetLoadTimingInfo();
1288 // The response start time should be captured at the time the first header
1289 // fragment of the informational response is received.
1290 EXPECT_EQ(load_timing_info.receive_headers_start,
1291 expected_receive_headers_start_time);
1292 // The non-informational response start time should be captured at the time
1293 // the first header fragment of the non-informational response is received.
1294 EXPECT_EQ(load_timing_info.receive_non_informational_headers_start,
1295 expected_receive_non_informational_headers_start_time);
1296 // The first response start time should be earlier than the non-informational
1297 // response start time.
1298 EXPECT_LT(load_timing_info.receive_headers_start,
1299 load_timing_info.receive_non_informational_headers_start);
bncc9f762a2016-12-06 20:38:231300}
1301
Kenichi Ishibashi74155532021-03-13 01:38:061302// Tests that timing information of 103 Eary Hints responses are collected and
1303// callbacks are called as expected.
Hiroki Nakagawad67642b592020-12-10 13:26:351304TEST_F(SpdyStreamTestWithMockClock, EarlyHints) {
1305 // Set up the request.
Hiroki Nakagawae40cd1e2020-06-17 04:49:411306 spdy::SpdySerializedFrame req(
1307 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1308 AddWrite(req);
1309
Kenichi Ishibashi74155532021-03-13 01:38:061310 // Set up two early hints response headers.
1311 const char kLinkHeaderValue1[] = "</image.jpg>; rel=preload; as=image";
1312 spdy::Http2HeaderBlock informational_headers1;
1313 informational_headers1[":status"] = "103";
1314 informational_headers1["link"] = kLinkHeaderValue1;
1315 spdy::SpdySerializedFrame informational_response1(
Hiroki Nakagawae40cd1e2020-06-17 04:49:411316 spdy_util_.ConstructSpdyResponseHeaders(
Kenichi Ishibashi74155532021-03-13 01:38:061317 1, std::move(informational_headers1), false));
1318
1319 const char kLinkHeaderValue2[] = "</style.css>; rel=preload; as=stylesheet";
1320 spdy::Http2HeaderBlock informational_headers2;
1321 informational_headers2[":status"] = "103";
1322 informational_headers2["link"] = kLinkHeaderValue2;
1323 spdy::SpdySerializedFrame informational_response2(
1324 spdy_util_.ConstructSpdyResponseHeaders(
1325 1, std::move(informational_headers2), false));
1326
1327 // Add the headers to make sure that multiple informational responses don't
1328 // confuse the timing information.
Hiroki Nakagawad67642b592020-12-10 13:26:351329 const int kNumberOfInformationalResponses = 2;
Kenichi Ishibashi74155532021-03-13 01:38:061330 // Separate the headers into 2 fragments and add pauses between the
1331 // fragments so that the test runner can advance the mock clock to test
1332 // timing information.
1333 AddMockRead(ReadFrameExceptForLastByte(informational_response1));
1334 AddReadPause();
1335 AddMockRead(LastByteOfReadFrame(informational_response1));
1336 AddReadPause();
1337
1338 AddMockRead(ReadFrameExceptForLastByte(informational_response2));
1339 AddReadPause();
1340 AddMockRead(LastByteOfReadFrame(informational_response2));
1341 AddReadPause();
Hiroki Nakagawae40cd1e2020-06-17 04:49:411342
Hiroki Nakagawad67642b592020-12-10 13:26:351343 // Set up the non-informational response headers and body.
Hiroki Nakagawae40cd1e2020-06-17 04:49:411344 spdy::SpdySerializedFrame reply(
1345 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1346 AddRead(reply);
Hiroki Nakagawad67642b592020-12-10 13:26:351347 AddReadPause();
Hiroki Nakagawae40cd1e2020-06-17 04:49:411348 spdy::SpdySerializedFrame body(
1349 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
1350 AddRead(body);
Hiroki Nakagawae40cd1e2020-06-17 04:49:411351 AddReadEOF();
1352
Hiroki Nakagawad67642b592020-12-10 13:26:351353 // Set up the sequenced socket data and the spdy stream.
1354 Initialize();
Hiroki Nakagawae40cd1e2020-06-17 04:49:411355
Hiroki Nakagawad67642b592020-12-10 13:26:351356 // Send a request.
Bence Béky4c325e52020-10-22 20:48:011357 spdy::Http2HeaderBlock headers(
Hiroki Nakagawae40cd1e2020-06-17 04:49:411358 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
Hiroki Nakagawad67642b592020-12-10 13:26:351359 EXPECT_EQ(ERR_IO_PENDING, stream()->SendRequestHeaders(std::move(headers),
1360 NO_MORE_DATA_TO_SEND));
Peter Kastinge5a38ed2021-10-02 03:06:351361 AdvanceClock(base::Seconds(1));
Hiroki Nakagawae40cd1e2020-06-17 04:49:411362
Hiroki Nakagawad67642b592020-12-10 13:26:351363 // The receive headers start time should be captured at this time.
1364 base::TimeTicks expected_receive_headers_start_time = base::TimeTicks::Now();
1365
1366 // Read the header fragments of the informational responses.
1367 for (int i = 0; i < kNumberOfInformationalResponses; ++i) {
1368 RunUntilNextPause();
Peter Kastinge5a38ed2021-10-02 03:06:351369 AdvanceClock(base::Seconds(1));
Hiroki Nakagawad67642b592020-12-10 13:26:351370 RunUntilNextPause();
Peter Kastinge5a38ed2021-10-02 03:06:351371 AdvanceClock(base::Seconds(1));
Hiroki Nakagawad67642b592020-12-10 13:26:351372 }
Kenichi Ishibashi74155532021-03-13 01:38:061373
1374 // Check the callback was called twice with 103 status code.
1375 const std::vector<spdy::Http2HeaderBlock>& early_hints =
1376 delegate().early_hints();
1377 EXPECT_EQ(early_hints.size(),
1378 static_cast<size_t>(kNumberOfInformationalResponses));
1379 {
1380 const spdy::Http2HeaderBlock& hint = delegate().early_hints()[0];
1381 spdy::Http2HeaderBlock::const_iterator status_iterator =
1382 hint.find(spdy::kHttp2StatusHeader);
1383 ASSERT_TRUE(status_iterator != hint.end());
1384 EXPECT_EQ(status_iterator->second, "103");
1385
1386 spdy::Http2HeaderBlock::const_iterator link_header_iterator =
1387 hint.find("link");
1388 ASSERT_TRUE(link_header_iterator != hint.end());
1389 EXPECT_EQ(link_header_iterator->second, kLinkHeaderValue1);
1390 }
1391 {
1392 const spdy::Http2HeaderBlock& hint = delegate().early_hints()[1];
1393 spdy::Http2HeaderBlock::const_iterator status_iterator =
1394 hint.find(spdy::kHttp2StatusHeader);
1395 ASSERT_TRUE(status_iterator != hint.end());
1396 EXPECT_EQ(status_iterator->second, "103");
1397
1398 spdy::Http2HeaderBlock::const_iterator link_header_iterator =
1399 hint.find("link");
1400 ASSERT_TRUE(link_header_iterator != hint.end());
1401 EXPECT_EQ(link_header_iterator->second, kLinkHeaderValue2);
1402 }
Hiroki Nakagawad67642b592020-12-10 13:26:351403
1404 // The receive non-informational headers start time should be captured at this
1405 // time.
1406 base::TimeTicks expected_receive_non_informational_headers_start_time =
1407 base::TimeTicks::Now();
1408
1409 // Read the non-informational response headers.
1410 RunUntilNextPause();
Peter Kastinge5a38ed2021-10-02 03:06:351411 AdvanceClock(base::Seconds(1));
Hiroki Nakagawad67642b592020-12-10 13:26:351412 EXPECT_EQ("200", delegate().GetResponseHeaderValue(spdy::kHttp2StatusHeader));
1413
1414 // Read the response body.
1415 EXPECT_THAT(RunUntilClose(), IsOk());
Hiroki Nakagawae40cd1e2020-06-17 04:49:411416 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
Hiroki Nakagawad67642b592020-12-10 13:26:351417 delegate().TakeReceivedData());
Hiroki Nakagawae40cd1e2020-06-17 04:49:411418
1419 // Finish async network reads and writes.
1420 base::RunLoop().RunUntilIdle();
Hiroki Nakagawad67642b592020-12-10 13:26:351421 EXPECT_TRUE(data().AllWriteDataConsumed());
1422 EXPECT_TRUE(data().AllReadDataConsumed());
Hiroki Nakagawae40cd1e2020-06-17 04:49:411423
Hiroki Nakagawad67642b592020-12-10 13:26:351424 const LoadTimingInfo& load_timing_info = delegate().GetLoadTimingInfo();
1425 // The response start time should be captured at the time the first header
1426 // fragment of the first informational response is received.
1427 EXPECT_EQ(load_timing_info.receive_headers_start,
1428 expected_receive_headers_start_time);
1429 // The first early hints time should be recorded as well.
1430 EXPECT_EQ(load_timing_info.first_early_hints_time,
1431 expected_receive_headers_start_time);
1432 // The non-informational response start time should be captured at the time
1433 // the first header fragment of the non-informational response is received.
1434 EXPECT_EQ(load_timing_info.receive_non_informational_headers_start,
1435 expected_receive_non_informational_headers_start_time);
1436 // The response start time should be earlier than the non-informational
1437 // response start time.
1438 EXPECT_LT(load_timing_info.receive_headers_start,
1439 load_timing_info.receive_non_informational_headers_start);
Hiroki Nakagawae40cd1e2020-06-17 04:49:411440}
1441
bnc4ce149622017-03-30 03:31:011442TEST_F(SpdyStreamTest, StatusMustBeNumber) {
Ryan Hamilton0239aac2018-05-19 00:03:131443 spdy::SpdySerializedFrame req(
1444 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncc9f762a2016-12-06 20:38:231445 AddWrite(req);
1446
Bence Béky4c325e52020-10-22 20:48:011447 spdy::Http2HeaderBlock incorrect_headers;
bncc9f762a2016-12-06 20:38:231448 incorrect_headers[":status"] = "nan";
Ryan Hamilton0239aac2018-05-19 00:03:131449 spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
bncc9f762a2016-12-06 20:38:231450 1, std::move(incorrect_headers), false));
1451 AddRead(reply);
1452
Ryan Hamilton0239aac2018-05-19 00:03:131453 spdy::SpdySerializedFrame rst(
1454 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
bncc9f762a2016-12-06 20:38:231455 AddWrite(rst);
1456
1457 AddReadEOF();
1458
Ryan Sleevib8d7ea02018-05-07 20:01:011459 SequencedSocketData data(GetReads(), GetWrites());
bncc9f762a2016-12-06 20:38:231460 MockConnect connect_data(SYNCHRONOUS, OK);
1461 data.set_connect_data(connect_data);
1462 session_deps_.socket_factory->AddSocketDataProvider(&data);
1463
1464 AddSSLSocketData();
1465
1466 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1467
1468 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1469 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1470 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:181471 EXPECT_EQ(kDefaultUrl, stream->url().spec());
bncc9f762a2016-12-06 20:38:231472
1473 StreamDelegateDoNothing delegate(stream);
1474 stream->SetDelegate(&delegate);
1475
Bence Béky4c325e52020-10-22 20:48:011476 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:131477 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bncc9f762a2016-12-06 20:38:231478 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1479 NO_MORE_DATA_TO_SEND));
bncc9f762a2016-12-06 20:38:231480
Bence Békyd0d69502019-06-25 19:47:181481 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
bncc9f762a2016-12-06 20:38:231482
bnceb9aa7112017-01-05 01:03:461483 // Finish async network reads and writes.
1484 base::RunLoop().RunUntilIdle();
1485
bncc9f762a2016-12-06 20:38:231486 EXPECT_TRUE(data.AllWriteDataConsumed());
1487 EXPECT_TRUE(data.AllReadDataConsumed());
1488}
1489
bnc4ce149622017-03-30 03:31:011490TEST_F(SpdyStreamTest, StatusCannotHaveExtraText) {
Ryan Hamilton0239aac2018-05-19 00:03:131491 spdy::SpdySerializedFrame req(
1492 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnc50ee38e2016-12-08 01:23:541493 AddWrite(req);
1494
Bence Béky4c325e52020-10-22 20:48:011495 spdy::Http2HeaderBlock headers_with_status_text;
bnc50ee38e2016-12-08 01:23:541496 headers_with_status_text[":status"] =
1497 "200 Some random extra text describing status";
Ryan Hamilton0239aac2018-05-19 00:03:131498 spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
bnc50ee38e2016-12-08 01:23:541499 1, std::move(headers_with_status_text), false));
1500 AddRead(reply);
1501
Ryan Hamilton0239aac2018-05-19 00:03:131502 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:191503 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
bnc50ee38e2016-12-08 01:23:541504 AddRead(body);
1505
Ryan Hamilton0239aac2018-05-19 00:03:131506 spdy::SpdySerializedFrame rst(
1507 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
bnc4ce149622017-03-30 03:31:011508 AddWrite(rst);
1509
bnc50ee38e2016-12-08 01:23:541510 AddReadEOF();
1511
Ryan Sleevib8d7ea02018-05-07 20:01:011512 SequencedSocketData data(GetReads(), GetWrites());
bnc50ee38e2016-12-08 01:23:541513 MockConnect connect_data(SYNCHRONOUS, OK);
1514 data.set_connect_data(connect_data);
1515 session_deps_.socket_factory->AddSocketDataProvider(&data);
1516
1517 AddSSLSocketData();
1518
1519 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1520
1521 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1522 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1523 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:181524 EXPECT_EQ(kDefaultUrl, stream->url().spec());
bnc50ee38e2016-12-08 01:23:541525
1526 StreamDelegateDoNothing delegate(stream);
1527 stream->SetDelegate(&delegate);
1528
Bence Béky4c325e52020-10-22 20:48:011529 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:131530 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc50ee38e2016-12-08 01:23:541531 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1532 NO_MORE_DATA_TO_SEND));
bnc50ee38e2016-12-08 01:23:541533
Bence Békyd0d69502019-06-25 19:47:181534 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
bnc4ce149622017-03-30 03:31:011535
1536 // Finish async network reads and writes.
1537 base::RunLoop().RunUntilIdle();
1538
1539 EXPECT_TRUE(data.AllWriteDataConsumed());
1540 EXPECT_TRUE(data.AllReadDataConsumed());
1541}
1542
1543TEST_F(SpdyStreamTest, StatusMustBePresent) {
Ryan Hamilton0239aac2018-05-19 00:03:131544 spdy::SpdySerializedFrame req(
1545 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnc4ce149622017-03-30 03:31:011546 AddWrite(req);
1547
Bence Béky4c325e52020-10-22 20:48:011548 spdy::Http2HeaderBlock headers_without_status;
Ryan Hamilton0239aac2018-05-19 00:03:131549 spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
bnc4ce149622017-03-30 03:31:011550 1, std::move(headers_without_status), false));
1551 AddRead(reply);
1552
Ryan Hamilton0239aac2018-05-19 00:03:131553 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:191554 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
bnc4ce149622017-03-30 03:31:011555 AddRead(body);
1556
Ryan Hamilton0239aac2018-05-19 00:03:131557 spdy::SpdySerializedFrame rst(
1558 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
bnc4ce149622017-03-30 03:31:011559 AddWrite(rst);
1560
1561 AddReadEOF();
1562
Ryan Sleevib8d7ea02018-05-07 20:01:011563 SequencedSocketData data(GetReads(), GetWrites());
bnc4ce149622017-03-30 03:31:011564 MockConnect connect_data(SYNCHRONOUS, OK);
1565 data.set_connect_data(connect_data);
1566 session_deps_.socket_factory->AddSocketDataProvider(&data);
1567
1568 AddSSLSocketData();
1569
1570 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1571
1572 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1573 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1574 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:181575 EXPECT_EQ(kDefaultUrl, stream->url().spec());
bnc4ce149622017-03-30 03:31:011576
1577 StreamDelegateDoNothing delegate(stream);
1578 stream->SetDelegate(&delegate);
1579
Bence Béky4c325e52020-10-22 20:48:011580 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:131581 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc4ce149622017-03-30 03:31:011582 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1583 NO_MORE_DATA_TO_SEND));
bnc4ce149622017-03-30 03:31:011584
Bence Békyd0d69502019-06-25 19:47:181585 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_PROTOCOL_ERROR));
bnc50ee38e2016-12-08 01:23:541586
bnceb9aa7112017-01-05 01:03:461587 // Finish async network reads and writes.
1588 base::RunLoop().RunUntilIdle();
1589
bnc50ee38e2016-12-08 01:23:541590 EXPECT_TRUE(data.AllWriteDataConsumed());
1591 EXPECT_TRUE(data.AllReadDataConsumed());
1592}
1593
bnca2fbdc9b2016-11-22 21:14:261594// Call IncreaseSendWindowSize on a stream with a large enough delta to overflow
1595// an int32_t. The SpdyStream should handle that case gracefully.
bncd16676a2016-07-20 16:23:011596TEST_F(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
Ryan Hamilton0239aac2018-05-19 00:03:131597 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bnca2fbdc9b2016-11-22 21:14:261598 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411599 AddWrite(req);
[email protected]3d587372013-06-01 04:31:451600
mmenkee24011922015-12-17 22:12:591601 AddReadPause();
1602
[email protected]1e5ebd82013-02-20 20:07:241603 // Triggered by the overflowing call to IncreaseSendWindowSize
1604 // below.
Ryan Hamilton0239aac2018-05-19 00:03:131605 spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream(
1606 1, spdy::ERROR_CODE_FLOW_CONTROL_ERROR));
bncdf80d44fd2016-07-15 20:27:411607 AddWrite(rst);
[email protected]3d587372013-06-01 04:31:451608
1609 AddReadEOF();
[email protected]1e5ebd82013-02-20 20:07:241610
Ryan Sleevib8d7ea02018-05-07 20:01:011611 SequencedSocketData data(GetReads(), GetWrites());
[email protected]1e5ebd82013-02-20 20:07:241612 MockConnect connect_data(SYNCHRONOUS, OK);
1613 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:591614 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1e5ebd82013-02-20 20:07:241615
bnc032658ba2016-09-26 18:17:151616 AddSSLSocketData();
1617
[email protected]795cbf82013-07-22 09:37:271618 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]1e5ebd82013-02-20 20:07:241619
bnca2fbdc9b2016-11-22 21:14:261620 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
Matt Reichhoff0049a0b72021-10-20 20:44:261621 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST,
1622 NetLogWithSource::Make(NetLogSourceType::NONE));
wezca1070932016-05-26 20:30:521623 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:181624 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1625
[email protected]194cfcf2013-05-23 21:44:441626 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
[email protected]1c6b12a2013-03-21 00:59:111627 stream->SetDelegate(&delegate);
[email protected]1e5ebd82013-02-20 20:07:241628
Bence Béky4c325e52020-10-22 20:48:011629 spdy::Http2HeaderBlock headers(
bnca2fbdc9b2016-11-22 21:14:261630 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1631 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1632 IsError(ERR_IO_PENDING));
[email protected]1c12c062013-05-14 23:13:481633
mmenkee24011922015-12-17 22:12:591634 data.RunUntilPaused();
[email protected]1e5ebd82013-02-20 20:07:241635
avid0181f32015-12-10 19:41:471636 int32_t old_send_window_size = stream->send_window_size();
[email protected]1e5ebd82013-02-20 20:07:241637 ASSERT_GT(old_send_window_size, 0);
avid0181f32015-12-10 19:41:471638 int32_t delta_window_size =
1639 std::numeric_limits<int32_t>::max() - old_send_window_size + 1;
[email protected]1e5ebd82013-02-20 20:07:241640 stream->IncreaseSendWindowSize(delta_window_size);
bnca2fbdc9b2016-11-22 21:14:261641 EXPECT_FALSE(stream);
[email protected]1e5ebd82013-02-20 20:07:241642
mmenkee24011922015-12-17 22:12:591643 data.Resume();
1644 base::RunLoop().RunUntilIdle();
[email protected]1c12c062013-05-14 23:13:481645
Bence Békyd0d69502019-06-25 19:47:181646 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_FLOW_CONTROL_ERROR));
[email protected]1e5ebd82013-02-20 20:07:241647}
1648
[email protected]d2de7da2013-05-22 07:49:561649// Functions used with
1650// RunResumeAfterUnstall{RequestResponse,Bidirectional}Test().
1651
1652void StallStream(const base::WeakPtr<SpdyStream>& stream) {
1653 // Reduce the send window size to 0 to stall.
1654 while (stream->send_window_size() > 0) {
1655 stream->DecreaseSendWindowSize(
1656 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
1657 }
1658}
1659
1660void IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
avid0181f32015-12-10 19:41:471661 int32_t delta_window_size) {
[email protected]d2de7da2013-05-22 07:49:561662 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1663 stream->IncreaseSendWindowSize(delta_window_size);
1664 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1665}
1666
1667void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
avid0181f32015-12-10 19:41:471668 int32_t delta_window_size) {
[email protected]d2de7da2013-05-22 07:49:561669 // Make sure that negative adjustments are handled properly.
1670 EXPECT_TRUE(stream->send_stalled_by_flow_control());
Bence Béky05dcb0382017-09-15 20:07:581671 EXPECT_TRUE(stream->AdjustSendWindowSize(-delta_window_size));
[email protected]d2de7da2013-05-22 07:49:561672 EXPECT_TRUE(stream->send_stalled_by_flow_control());
Bence Béky05dcb0382017-09-15 20:07:581673 EXPECT_TRUE(stream->AdjustSendWindowSize(+delta_window_size));
[email protected]d2de7da2013-05-22 07:49:561674 EXPECT_TRUE(stream->send_stalled_by_flow_control());
Bence Béky05dcb0382017-09-15 20:07:581675 EXPECT_TRUE(stream->AdjustSendWindowSize(+delta_window_size));
[email protected]d2de7da2013-05-22 07:49:561676 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1677}
1678
1679// Given an unstall function, runs a test to make sure that a
1680// request/response (i.e., an HTTP-like) stream resumes after a stall
1681// and unstall.
[email protected]3d587372013-06-01 04:31:451682void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
Anna Malova924d79d2020-03-04 17:09:321683 UnstallFunction unstall_function) {
Ryan Hamilton0239aac2018-05-19 00:03:131684 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bnca2fbdc9b2016-11-22 21:14:261685 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411686 AddWrite(req);
[email protected]3d587372013-06-01 04:31:451687
Ryan Hamilton0239aac2018-05-19 00:03:131688 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:191689 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
bncdf80d44fd2016-07-15 20:27:411690 AddWrite(body);
[email protected]34a4dea2013-03-13 00:42:301691
Ryan Hamilton0239aac2018-05-19 00:03:131692 spdy::SpdySerializedFrame resp(
1693 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411694 AddRead(resp);
[email protected]34a4dea2013-03-13 00:42:301695
[email protected]3d587372013-06-01 04:31:451696 AddReadEOF();
1697
Ryan Sleevib8d7ea02018-05-07 20:01:011698 SequencedSocketData data(GetReads(), GetWrites());
[email protected]34a4dea2013-03-13 00:42:301699 MockConnect connect_data(SYNCHRONOUS, OK);
1700 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:591701 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]34a4dea2013-03-13 00:42:301702
bnc032658ba2016-09-26 18:17:151703 AddSSLSocketData();
1704
[email protected]795cbf82013-07-22 09:37:271705 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]34a4dea2013-03-13 00:42:301706
tfarina42834112016-09-22 13:38:201707 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:261708 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:521709 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:181710 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]34a4dea2013-03-13 00:42:301711
[email protected]d26ff352013-05-13 08:48:281712 StreamDelegateWithBody delegate(stream, kPostBodyStringPiece);
[email protected]34a4dea2013-03-13 00:42:301713 stream->SetDelegate(&delegate);
1714
[email protected]1c6b12a2013-03-21 00:59:111715 EXPECT_FALSE(stream->send_stalled_by_flow_control());
[email protected]34a4dea2013-03-13 00:42:301716
Bence Béky4c325e52020-10-22 20:48:011717 spdy::Http2HeaderBlock headers(
bnca2fbdc9b2016-11-22 21:14:261718 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1719 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1720 IsError(ERR_IO_PENDING));
[email protected]34a4dea2013-03-13 00:42:301721
[email protected]d2de7da2013-05-22 07:49:561722 StallStream(stream);
1723
mmenkee24011922015-12-17 22:12:591724 base::RunLoop().RunUntilIdle();
[email protected]34a4dea2013-03-13 00:42:301725
[email protected]1c6b12a2013-03-21 00:59:111726 EXPECT_TRUE(stream->send_stalled_by_flow_control());
[email protected]34a4dea2013-03-13 00:42:301727
Anna Malova924d79d2020-03-04 17:09:321728 std::move(unstall_function).Run(stream, kPostBodyLength);
[email protected]34a4dea2013-03-13 00:42:301729
[email protected]1c6b12a2013-03-21 00:59:111730 EXPECT_FALSE(stream->send_stalled_by_flow_control());
[email protected]34a4dea2013-03-13 00:42:301731
robpercival214763f2016-07-01 23:27:011732 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
[email protected]34a4dea2013-03-13 00:42:301733
1734 EXPECT_TRUE(delegate.send_headers_completed());
1735 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
Bence Béky4e83f492018-05-13 23:14:251736 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
rch37de576c2015-05-17 20:28:171737 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]cbdd73162013-03-18 23:27:331738}
1739
bncd16676a2016-07-20 16:23:011740TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) {
[email protected]d2de7da2013-05-22 07:49:561741 RunResumeAfterUnstallRequestResponseTest(
Anna Malova924d79d2020-03-04 17:09:321742 base::BindOnce(&IncreaseStreamSendWindowSize));
[email protected]d2de7da2013-05-22 07:49:561743}
1744
bncd16676a2016-07-20 16:23:011745TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) {
[email protected]d2de7da2013-05-22 07:49:561746 RunResumeAfterUnstallRequestResponseTest(
Anna Malova924d79d2020-03-04 17:09:321747 base::BindOnce(&AdjustStreamSendWindowSize));
[email protected]d2de7da2013-05-22 07:49:561748}
1749
bnca2fbdc9b2016-11-22 21:14:261750// Given an unstall function, runs a test to make sure that a bidirectional
1751// (i.e., non-HTTP-like) stream resumes after a stall and unstall.
[email protected]3d587372013-06-01 04:31:451752void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
Anna Malova924d79d2020-03-04 17:09:321753 UnstallFunction unstall_function) {
Ryan Hamilton0239aac2018-05-19 00:03:131754 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bnca2fbdc9b2016-11-22 21:14:261755 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411756 AddWrite(req);
[email protected]3d587372013-06-01 04:31:451757
mmenkee24011922015-12-17 22:12:591758 AddReadPause();
1759
Ryan Hamilton0239aac2018-05-19 00:03:131760 spdy::SpdySerializedFrame resp(
1761 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411762 AddRead(resp);
[email protected]3d587372013-06-01 04:31:451763
Ryan Hamilton0239aac2018-05-19 00:03:131764 spdy::SpdySerializedFrame msg(
Bence Békyd74f4382018-02-20 18:26:191765 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
bncdf80d44fd2016-07-15 20:27:411766 AddWrite(msg);
[email protected]cbdd73162013-03-18 23:27:331767
Ryan Hamilton0239aac2018-05-19 00:03:131768 spdy::SpdySerializedFrame echo(
Bence Békyd74f4382018-02-20 18:26:191769 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
bncdf80d44fd2016-07-15 20:27:411770 AddRead(echo);
[email protected]cbdd73162013-03-18 23:27:331771
[email protected]3d587372013-06-01 04:31:451772 AddReadEOF();
1773
Ryan Sleevib8d7ea02018-05-07 20:01:011774 SequencedSocketData data(GetReads(), GetWrites());
[email protected]cbdd73162013-03-18 23:27:331775 MockConnect connect_data(SYNCHRONOUS, OK);
1776 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:591777 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]cbdd73162013-03-18 23:27:331778
bnc032658ba2016-09-26 18:17:151779 AddSSLSocketData();
1780
[email protected]795cbf82013-07-22 09:37:271781 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
[email protected]cbdd73162013-03-18 23:27:331782
tfarina42834112016-09-22 13:38:201783 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:261784 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:521785 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:181786 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]cbdd73162013-03-18 23:27:331787
[email protected]194cfcf2013-05-23 21:44:441788 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
[email protected]cbdd73162013-03-18 23:27:331789 stream->SetDelegate(&delegate);
1790
Bence Béky4c325e52020-10-22 20:48:011791 spdy::Http2HeaderBlock headers(
bnca2fbdc9b2016-11-22 21:14:261792 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1793 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1794 IsError(ERR_IO_PENDING));
[email protected]cbdd73162013-03-18 23:27:331795
mmenkee24011922015-12-17 22:12:591796 data.RunUntilPaused();
[email protected]cbdd73162013-03-18 23:27:331797
[email protected]1c6b12a2013-03-21 00:59:111798 EXPECT_FALSE(stream->send_stalled_by_flow_control());
[email protected]cbdd73162013-03-18 23:27:331799
[email protected]d2de7da2013-05-22 07:49:561800 StallStream(stream);
[email protected]cbdd73162013-03-18 23:27:331801
mmenkee24011922015-12-17 22:12:591802 data.Resume();
1803 base::RunLoop().RunUntilIdle();
[email protected]cbdd73162013-03-18 23:27:331804
[email protected]1c6b12a2013-03-21 00:59:111805 EXPECT_TRUE(stream->send_stalled_by_flow_control());
[email protected]cbdd73162013-03-18 23:27:331806
Anna Malova924d79d2020-03-04 17:09:321807 std::move(unstall_function).Run(stream, kPostBodyLength);
[email protected]cbdd73162013-03-18 23:27:331808
[email protected]1c6b12a2013-03-21 00:59:111809 EXPECT_FALSE(stream->send_stalled_by_flow_control());
[email protected]cbdd73162013-03-18 23:27:331810
robpercival214763f2016-07-01 23:27:011811 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
[email protected]cbdd73162013-03-18 23:27:331812
1813 EXPECT_TRUE(delegate.send_headers_completed());
1814 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
Bence Béky4e83f492018-05-13 23:14:251815 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
[email protected]09a8d9172013-04-17 19:23:491816 delegate.TakeReceivedData());
rch37de576c2015-05-17 20:28:171817 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d2de7da2013-05-22 07:49:561818}
1819
bncd16676a2016-07-20 16:23:011820TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) {
[email protected]d2de7da2013-05-22 07:49:561821 RunResumeAfterUnstallBidirectionalTest(
Anna Malova924d79d2020-03-04 17:09:321822 base::BindOnce(&IncreaseStreamSendWindowSize));
[email protected]d2de7da2013-05-22 07:49:561823}
1824
bncd16676a2016-07-20 16:23:011825TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
[email protected]d2de7da2013-05-22 07:49:561826 RunResumeAfterUnstallBidirectionalTest(
Anna Malova924d79d2020-03-04 17:09:321827 base::BindOnce(&AdjustStreamSendWindowSize));
[email protected]34a4dea2013-03-13 00:42:301828}
1829
[email protected]533f0de2013-12-09 23:03:361830// Test calculation of amount of bytes received from network.
bncd16676a2016-07-20 16:23:011831TEST_F(SpdyStreamTest, ReceivedBytes) {
Ryan Hamilton0239aac2018-05-19 00:03:131832 spdy::SpdySerializedFrame req(
1833 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnca2fbdc9b2016-11-22 21:14:261834 AddWrite(req);
[email protected]533f0de2013-12-09 23:03:361835
mmenkee24011922015-12-17 22:12:591836 AddReadPause();
1837
Ryan Hamilton0239aac2018-05-19 00:03:131838 spdy::SpdySerializedFrame reply(
1839 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411840 AddRead(reply);
[email protected]533f0de2013-12-09 23:03:361841
mmenkee24011922015-12-17 22:12:591842 AddReadPause();
1843
Ryan Hamilton0239aac2018-05-19 00:03:131844 spdy::SpdySerializedFrame msg(
Bence Békyd74f4382018-02-20 18:26:191845 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
bncdf80d44fd2016-07-15 20:27:411846 AddRead(msg);
[email protected]533f0de2013-12-09 23:03:361847
mmenkee24011922015-12-17 22:12:591848 AddReadPause();
1849
[email protected]533f0de2013-12-09 23:03:361850 AddReadEOF();
1851
Ryan Sleevib8d7ea02018-05-07 20:01:011852 SequencedSocketData data(GetReads(), GetWrites());
[email protected]533f0de2013-12-09 23:03:361853 MockConnect connect_data(SYNCHRONOUS, OK);
1854 data.set_connect_data(connect_data);
mmenkee24011922015-12-17 22:12:591855 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]533f0de2013-12-09 23:03:361856
bnc032658ba2016-09-26 18:17:151857 AddSSLSocketData();
1858
[email protected]533f0de2013-12-09 23:03:361859 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1860
tfarina42834112016-09-22 13:38:201861 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
bnca2fbdc9b2016-11-22 21:14:261862 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
wezca1070932016-05-26 20:30:521863 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:181864 EXPECT_EQ(kDefaultUrl, stream->url().spec());
[email protected]533f0de2013-12-09 23:03:361865
1866 StreamDelegateDoNothing delegate(stream);
1867 stream->SetDelegate(&delegate);
1868
Bence Béky4c325e52020-10-22 20:48:011869 spdy::Http2HeaderBlock headers(
Ryan Hamilton0239aac2018-05-19 00:03:131870 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnca2fbdc9b2016-11-22 21:14:261871 EXPECT_THAT(
1872 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
1873 IsError(ERR_IO_PENDING));
[email protected]533f0de2013-12-09 23:03:361874
bncdf80d44fd2016-07-15 20:27:411875 int64_t reply_frame_len = reply.size();
Ryan Hamilton0239aac2018-05-19 00:03:131876 int64_t data_header_len = spdy::kDataFrameMinimumSize;
avid0181f32015-12-10 19:41:471877 int64_t data_frame_len = data_header_len + kPostBodyLength;
1878 int64_t response_len = reply_frame_len + data_frame_len;
[email protected]533f0de2013-12-09 23:03:361879
1880 EXPECT_EQ(0, stream->raw_received_bytes());
[email protected]533f0de2013-12-09 23:03:361881
bnca2fbdc9b2016-11-22 21:14:261882 // REQUEST
mmenkee24011922015-12-17 22:12:591883 data.RunUntilPaused();
1884 EXPECT_EQ(0, stream->raw_received_bytes());
1885
1886 // REPLY
1887 data.Resume();
1888 data.RunUntilPaused();
1889 EXPECT_EQ(reply_frame_len, stream->raw_received_bytes());
1890
1891 // DATA
1892 data.Resume();
1893 data.RunUntilPaused();
1894 EXPECT_EQ(response_len, stream->raw_received_bytes());
1895
1896 // FIN
1897 data.Resume();
robpercival214763f2016-07-01 23:27:011898 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
[email protected]533f0de2013-12-09 23:03:361899}
1900
Bence Békycf3fd8a42018-02-09 20:15:471901// Regression test for https://crbug.com/810763.
1902TEST_F(SpdyStreamTest, DataOnHalfClosedRemoveStream) {
Ryan Hamilton0239aac2018-05-19 00:03:131903 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
Bence Békycf3fd8a42018-02-09 20:15:471904 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
1905 AddWrite(req);
1906
Bence Béky4c325e52020-10-22 20:48:011907 spdy::Http2HeaderBlock response_headers;
Ryan Hamilton0239aac2018-05-19 00:03:131908 response_headers[spdy::kHttp2StatusHeader] = "200";
1909 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Békycf3fd8a42018-02-09 20:15:471910 1, std::move(response_headers), /* fin = */ true));
1911 AddRead(resp);
1912
Ryan Hamilton0239aac2018-05-19 00:03:131913 spdy::SpdySerializedFrame data_frame(
Bence Békyd74f4382018-02-20 18:26:191914 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
Bence Békycf3fd8a42018-02-09 20:15:471915 AddRead(data_frame);
1916
Ryan Hamilton0239aac2018-05-19 00:03:131917 spdy::SpdySerializedFrame rst(
1918 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_STREAM_CLOSED));
Bence Békycf3fd8a42018-02-09 20:15:471919 AddWrite(rst);
1920
1921 AddReadEOF();
1922
Ryan Sleevib8d7ea02018-05-07 20:01:011923 SequencedSocketData data(GetReads(), GetWrites());
Bence Békycf3fd8a42018-02-09 20:15:471924 MockConnect connect_data(SYNCHRONOUS, OK);
1925 data.set_connect_data(connect_data);
1926 session_deps_.socket_factory->AddSocketDataProvider(&data);
1927
1928 AddSSLSocketData();
1929
1930 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1931
1932 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1933 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
1934 ASSERT_TRUE(stream);
Bence Béky39d74292018-03-02 04:31:181935 EXPECT_EQ(kDefaultUrl, stream->url().spec());
Bence Békycf3fd8a42018-02-09 20:15:471936
1937 StreamDelegateDoNothing delegate(stream);
1938 stream->SetDelegate(&delegate);
1939
Bence Béky4c325e52020-10-22 20:48:011940 spdy::Http2HeaderBlock headers(
Bence Békycf3fd8a42018-02-09 20:15:471941 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1942 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1943 IsError(ERR_IO_PENDING));
Bence Békycf3fd8a42018-02-09 20:15:471944
Bence Békyd0d69502019-06-25 19:47:181945 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_HTTP2_STREAM_CLOSED));
Bence Békycf3fd8a42018-02-09 20:15:471946
1947 base::RunLoop().RunUntilIdle();
1948
1949 EXPECT_TRUE(data.AllReadDataConsumed());
1950 EXPECT_TRUE(data.AllWriteDataConsumed());
1951}
1952
Adam Rice16955aae2021-03-01 13:57:551953TEST_F(SpdyStreamTest, DelegateIsInformedOfEOF) {
1954 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1955 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
1956 AddWrite(req);
1957
1958 spdy::Http2HeaderBlock response_headers;
1959 response_headers[spdy::kHttp2StatusHeader] = "200";
1960 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
1961 1, std::move(response_headers), /* fin = */ true));
1962 AddRead(resp);
1963
1964 spdy::SpdySerializedFrame data_frame(
1965 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
1966 AddRead(data_frame);
1967
1968 spdy::SpdySerializedFrame rst(
1969 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_STREAM_CLOSED));
1970 AddWrite(rst);
1971
1972 AddReadEOF();
1973
1974 SequencedSocketData data(GetReads(), GetWrites());
1975 MockConnect connect_data(SYNCHRONOUS, OK);
1976 data.set_connect_data(connect_data);
1977 session_deps_.socket_factory->AddSocketDataProvider(&data);
1978
1979 AddSSLSocketData();
1980
1981 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1982
1983 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1984 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
1985 ASSERT_TRUE(stream);
1986 EXPECT_EQ(kDefaultUrl, stream->url().spec());
1987
1988 StreamDelegateDetectEOF delegate(stream);
1989 stream->SetDelegate(&delegate);
1990
1991 spdy::Http2HeaderBlock headers(
1992 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1993 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1994 IsError(ERR_IO_PENDING));
1995
1996 base::RunLoop().RunUntilIdle();
1997
1998 EXPECT_TRUE(delegate.eof_detected());
1999
2000 EXPECT_TRUE(data.AllReadDataConsumed());
2001 EXPECT_TRUE(data.AllWriteDataConsumed());
2002}
2003
Patrick Meenan8b7432fb2022-01-12 14:07:272004// A small read should trigger sending a receive window update and dropping the
2005// count of unacknowledged bytes to zero only after
2006// kDefaultTimeToBufferSmallWindowUpdates time has passed.
2007TEST_F(SpdyStreamTestWithMockClock, FlowControlSlowReads) {
2008 spdy::SpdySerializedFrame req(
2009 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2010 AddWrite(req);
2011
2012 AddReadPause();
2013
2014 spdy::SpdySerializedFrame reply(
2015 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2016 AddRead(reply);
2017
2018 AddReadPause();
2019
2020 spdy::SpdySerializedFrame msg(
2021 spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, false));
2022 AddRead(msg);
2023
2024 AddReadPause();
2025
2026 AddReadEOF();
2027
2028 SequencedSocketData data(GetReads(), GetWrites());
2029 MockConnect connect_data(SYNCHRONOUS, OK);
2030 data.set_connect_data(connect_data);
2031 session_deps_.socket_factory->AddSocketDataProvider(&data);
2032
2033 AddSSLSocketData();
2034
2035 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
2036 session->SetTimeToBufferSmallWindowUpdates(
2037 kDefaultTimeToBufferSmallWindowUpdates);
2038
2039 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
2040 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
2041 ASSERT_TRUE(stream);
2042 EXPECT_EQ(kDefaultUrl, stream->url().spec());
2043
2044 StreamDelegateConsumeData delegate(stream);
2045 stream->SetDelegate(&delegate);
2046
2047 EXPECT_EQ(0, unacked_recv_window_bytes(stream));
2048
2049 spdy::Http2HeaderBlock headers(
2050 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2051 EXPECT_THAT(
2052 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
2053 IsError(ERR_IO_PENDING));
2054
2055 // REQUEST
2056 data.RunUntilPaused();
2057
2058 // REPLY
2059 data.Resume();
2060 data.RunUntilPaused();
2061
2062 // Delay long enough for the receive window to send an update on read,
2063 // draining the unacked_recv_window_bytes back to zero.
2064 AdvanceClock(kDefaultTimeToBufferSmallWindowUpdates);
2065
2066 // DATA
2067 data.Resume();
2068 data.RunUntilPaused();
2069
2070 EXPECT_EQ(0, unacked_recv_window_bytes(stream));
2071
2072 // FIN
2073 data.Resume();
2074 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
2075}
2076
Tsuyoshi Horo4f516be2022-06-14 11:53:132077} // namespace net::test