blob: bdd4179da8b72e094d9e5f3888a6321425ae3171 [file] [log] [blame]
Avi Drissman64595482022-09-14 20:52:291// Copyright 2012 The Chromium Authors
[email protected]a677f2b2009-11-22 00:43:002// 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_http_stream.h"
[email protected]61f3ddf2012-02-08 02:45:396
sclittlec8db2ff2015-09-02 22:02:387#include <stdint.h>
8
Eric Orthac661912022-01-10 21:44:179#include <set>
Bence Béky4e83f492018-05-13 23:14:2510#include <string>
11
Sebastien Marchand6d0558fd2019-01-25 16:49:3712#include "base/bind.h"
Keishi Hattori0e45c022021-11-27 09:25:5213#include "base/memory/raw_ptr.h"
[email protected]09356c652014-03-25 15:36:1014#include "base/run_loop.h"
Sean Maher5b9af51f2022-11-21 15:32:4715#include "base/task/single_thread_task_runner.h"
[email protected]6b2e61f2012-02-28 08:06:5416#include "crypto/ec_private_key.h"
17#include "crypto/ec_signature_creator.h"
[email protected]61f3ddf2012-02-08 02:45:3918#include "crypto/signature_creator.h"
mmenkecbc2b712014-10-09 20:29:0719#include "net/base/chunked_upload_data_stream.h"
[email protected]b258e0792013-01-12 07:11:5920#include "net/base/load_timing_info.h"
21#include "net/base/load_timing_info_test_util.h"
mmenkecbc2b712014-10-09 20:29:0722#include "net/base/test_completion_callback.h"
[email protected]6e7845ae2013-03-29 21:48:1123#include "net/cert/asn1_util.h"
Ben Schwartz3ff4dc1e62021-04-27 21:15:2324#include "net/dns/public/secure_dns_policy.h"
[email protected]9a963892012-11-01 11:48:1325#include "net/http/http_request_info.h"
[email protected]61f3ddf2012-02-08 02:45:3926#include "net/http/http_response_headers.h"
27#include "net/http/http_response_info.h"
mikecironef22f9812016-10-04 03:40:1928#include "net/log/net_log_with_source.h"
Paul Jensena457017a2018-01-19 23:52:0429#include "net/socket/socket_tag.h"
[email protected]6fe2e992013-06-12 03:38:4330#include "net/socket/socket_test_util.h"
Bence Béky94658bf2018-05-11 19:22:5831#include "net/spdy/spdy_http_utils.h"
32#include "net/spdy/spdy_test_util_common.h"
bnc032658ba2016-09-26 18:17:1533#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0134#include "net/test/gtest_util.h"
bnc032658ba2016-09-26 18:17:1535#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4036#include "net/test/test_with_task_environment.h"
Ramin Halavati216426e2018-03-12 22:13:3537#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
robpercival214763f2016-07-01 23:27:0138#include "testing/gmock/include/gmock/gmock.h"
[email protected]a677f2b2009-11-22 00:43:0039#include "testing/gtest/include/gtest/gtest.h"
40
Tsuyoshi Horo4f516be2022-06-14 11:53:1341namespace net::test {
bnca2fbdc9b2016-11-22 21:14:2642
[email protected]b258e0792013-01-12 07:11:5943namespace {
44
45// Tests the load timing of a stream that's connected and is not the first
46// request sent on a connection.
47void TestLoadTimingReused(const HttpStream& stream) {
48 LoadTimingInfo load_timing_info;
49 EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info));
50
51 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:1952 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]b258e0792013-01-12 07:11:5953
54 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
55 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
56}
57
58// Tests the load timing of a stream that's connected and using a fresh
59// connection.
60void TestLoadTimingNotReused(const HttpStream& stream) {
61 LoadTimingInfo load_timing_info;
62 EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info));
63
64 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:1965 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]b258e0792013-01-12 07:11:5966
bnc032658ba2016-09-26 18:17:1567 ExpectConnectTimingHasTimes(
68 load_timing_info.connect_timing,
69 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]b258e0792013-01-12 07:11:5970 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
71}
72
maksim.sisov167c3c02016-06-23 07:31:5273class ReadErrorUploadDataStream : public UploadDataStream {
74 public:
75 enum class FailureMode { SYNC, ASYNC };
76
77 explicit ReadErrorUploadDataStream(FailureMode mode)
Jeremy Romand54000b22019-07-08 18:40:1678 : UploadDataStream(true, 0), async_(mode) {}
maksim.sisov167c3c02016-06-23 07:31:5279
Peter Boström407869b2021-10-07 04:42:4880 ReadErrorUploadDataStream(const ReadErrorUploadDataStream&) = delete;
81 ReadErrorUploadDataStream& operator=(const ReadErrorUploadDataStream&) =
82 delete;
83
maksim.sisov167c3c02016-06-23 07:31:5284 private:
85 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
86
87 // UploadDataStream implementation:
tfarina42834112016-09-22 13:38:2088 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
maksim.sisov167c3c02016-06-23 07:31:5289
90 int ReadInternal(IOBuffer* buf, int buf_len) override {
91 if (async_ == FailureMode::ASYNC) {
Sean Maher5b9af51f2022-11-21 15:32:4792 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Bence Békya25e3f72018-02-13 21:13:3993 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
94 weak_factory_.GetWeakPtr()));
maksim.sisov167c3c02016-06-23 07:31:5295 return ERR_IO_PENDING;
96 }
97 return ERR_FAILED;
98 }
99
100 void ResetInternal() override {}
101
102 const FailureMode async_;
103
Jeremy Romand54000b22019-07-08 18:40:16104 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
maksim.sisov167c3c02016-06-23 07:31:52105};
106
bncaa171332016-07-20 14:47:36107class CancelStreamCallback : public TestCompletionCallbackBase {
108 public:
Bence Béky8ddc2492018-06-13 01:02:04109 explicit CancelStreamCallback(SpdyHttpStream* stream) : stream_(stream) {}
bncaa171332016-07-20 14:47:36110
Bence Béky8ddc2492018-06-13 01:02:04111 CompletionOnceCallback callback() {
112 return base::BindOnce(&CancelStreamCallback::CancelStream,
113 base::Unretained(this));
114 }
bncaa171332016-07-20 14:47:36115
116 private:
117 void CancelStream(int result) {
118 stream_->Cancel();
119 SetResult(result);
120 }
121
Keishi Hattori0e45c022021-11-27 09:25:52122 raw_ptr<SpdyHttpStream> stream_;
bncaa171332016-07-20 14:47:36123};
124
[email protected]b258e0792013-01-12 07:11:59125} // namespace
126
Gabriel Charette694c3c332019-08-19 14:53:05127class SpdyHttpStreamTest : public TestWithTaskEnvironment {
[email protected]6c6ea172010-07-27 20:04:03128 public:
[email protected]2aeef782013-06-21 18:30:56129 SpdyHttpStreamTest()
bnca2fbdc9b2016-11-22 21:14:26130 : url_(kDefaultUrl),
131 host_port_pair_(HostPortPair::FromURL(url_)),
Paul Jensena457017a2018-01-19 23:52:04132 key_(host_port_pair_,
133 ProxyServer::Direct(),
134 PRIVACY_MODE_DISABLED,
Matt Menke2436b2f2018-12-11 18:07:11135 SpdySessionKey::IsProxySession::kFalse,
dalyk51ab46b2019-10-15 15:14:34136 SocketTag(),
Brianna Goldsteind372b232022-09-25 17:24:17137 NetworkAnonymizationKey(),
Ben Schwartz3ff4dc1e62021-04-27 21:15:23138 SecureDnsPolicy::kAllow),
bnc032658ba2016-09-26 18:17:15139 ssl_(SYNCHRONOUS, OK) {
Matt Reichhoff36a1fd62021-10-12 22:52:20140 session_deps_.net_log = NetLog::Get();
[email protected]b258e0792013-01-12 07:11:59141 }
142
Chris Watkins61914cb2017-12-01 19:59:00143 ~SpdyHttpStreamTest() override = default;
rdsmithebb50aa2015-11-12 03:44:38144
[email protected]a677f2b2009-11-22 00:43:00145 protected:
dcheng67be2b1f2014-10-27 21:47:29146 void TearDown() override {
fdoray92e35a72016-06-10 15:54:55147 base::RunLoop().RunUntilIdle();
bnc78edcd52015-06-04 11:34:03148 EXPECT_TRUE(sequenced_data_->AllReadDataConsumed());
149 EXPECT_TRUE(sequenced_data_->AllWriteDataConsumed());
[email protected]a677f2b2009-11-22 00:43:00150 }
[email protected]39c48fc2012-03-12 18:42:12151
bnc78edcd52015-06-04 11:34:03152 // Initializes the session using SequencedSocketData.
Ryan Sleevib8d7ea02018-05-07 20:01:01153 void InitSession(base::span<const MockRead> reads,
154 base::span<const MockWrite> writes) {
155 sequenced_data_ = std::make_unique<SequencedSocketData>(reads, writes);
bnc78edcd52015-06-04 11:34:03156 session_deps_.socket_factory->AddSocketDataProvider(sequenced_data_.get());
bnc032658ba2016-09-26 18:17:15157
Ryan Sleevi4f832092017-11-21 23:25:49158 ssl_.ssl_info.cert =
159 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
160 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15161 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
162
bnc78edcd52015-06-04 11:34:03163 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
Bence Béky0ef1556e2017-06-30 19:52:52164 session_ = CreateSpdySession(http_session_.get(), key_, NetLogWithSource());
[email protected]b258e0792013-01-12 07:11:59165 }
166
[email protected]c10b20852013-05-15 21:29:20167 SpdyTestUtil spdy_util_;
[email protected]d2360a52010-07-26 04:48:13168 SpdySessionDependencies session_deps_;
bnca2fbdc9b2016-11-22 21:14:26169 const GURL url_;
bnc3d9035b32016-06-30 18:18:48170 const HostPortPair host_port_pair_;
171 const SpdySessionKey key_;
danakjaee3e1ec2016-04-16 00:23:18172 std::unique_ptr<SequencedSocketData> sequenced_data_;
173 std::unique_ptr<HttpNetworkSession> http_session_;
[email protected]795cbf82013-07-22 09:37:27174 base::WeakPtr<SpdySession> session_;
[email protected]dca629c2012-03-22 03:40:38175
176 private:
bnc032658ba2016-09-26 18:17:15177 SSLSocketDataProvider ssl_;
[email protected]a677f2b2009-11-22 00:43:00178};
179
bncd16676a2016-07-20 16:23:01180TEST_F(SpdyHttpStreamTest, SendRequest) {
Ryan Hamilton0239aac2018-05-19 00:03:13181 spdy::SpdySerializedFrame req(
182 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
[email protected]30c942b2010-07-21 16:59:59183 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41184 CreateMockWrite(req, 0),
[email protected]30c942b2010-07-21 16:59:59185 };
Ryan Hamilton0239aac2018-05-19 00:03:13186 spdy::SpdySerializedFrame resp(
187 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]30c942b2010-07-21 16:59:59188 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41189 CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
[email protected]30c942b2010-07-21 16:59:59190 };
[email protected]30c942b2010-07-21 16:59:59191
Ryan Sleevib8d7ea02018-05-07 20:01:01192 InitSession(reads, writes);
[email protected]30c942b2010-07-21 16:59:59193
[email protected]a677f2b2009-11-22 00:43:00194 HttpRequestInfo request;
195 request.method = "GET";
bnca2fbdc9b2016-11-22 21:14:26196 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:35197 request.traffic_annotation =
198 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]49639fa2011-12-20 23:22:41199 TestCompletionCallback callback;
[email protected]a7e41312009-12-16 23:18:14200 HttpResponseInfo response;
[email protected]b94f92d2010-10-27 16:45:20201 HttpRequestHeaders headers;
tfarina42834112016-09-22 13:38:20202 NetLogWithSource net_log;
Bence Békye8955cf22018-01-02 17:31:29203 auto http_stream = std::make_unique<SpdyHttpStream>(
Cammie Smith Barnes5191037b72021-03-01 22:06:53204 session_, kNoPushedStreamFound, net_log.source(),
Eric Orthac661912022-01-10 21:44:17205 /*dns_aliases=*/std::set<std::string>());
[email protected]b258e0792013-01-12 07:11:59206 // Make sure getting load timing information the stream early does not crash.
207 LoadTimingInfo load_timing_info;
208 EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info));
209
Ali Beyada0b1a1c2022-04-08 20:08:14210 http_stream->RegisterRequest(&request);
211 ASSERT_THAT(http_stream->InitializeStream(true, DEFAULT_PRIORITY, net_log,
212 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:26213 IsOk());
[email protected]b258e0792013-01-12 07:11:59214 EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info));
[email protected]d2360a52010-07-26 04:48:13215
bnca2fbdc9b2016-11-22 21:14:26216 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
217 IsError(ERR_IO_PENDING));
bnc3d9035b32016-06-30 18:18:48218 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]b258e0792013-01-12 07:11:59219 EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info));
[email protected]6c6ea172010-07-27 20:04:03220
[email protected]6c6ea172010-07-27 20:04:03221 callback.WaitForResult();
222
[email protected]b258e0792013-01-12 07:11:59223 // Can get timing information once the stream connects.
224 TestLoadTimingNotReused(*http_stream);
225
[email protected]58cebf8f2010-07-31 19:20:16226 // Because we abandoned the stream, we don't expect to find a session in the
227 // pool anymore.
bnc3d9035b32016-06-30 18:18:48228 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]b258e0792013-01-12 07:11:59229
230 TestLoadTimingNotReused(*http_stream);
231 http_stream->Close(true);
232 // Test that there's no crash when trying to get the load timing after the
233 // stream has been closed.
234 TestLoadTimingNotReused(*http_stream);
sclittlec8db2ff2015-09-02 22:02:38235
bncdf80d44fd2016-07-15 20:27:41236 EXPECT_EQ(static_cast<int64_t>(req.size()), http_stream->GetTotalSentBytes());
237 EXPECT_EQ(static_cast<int64_t>(resp.size()),
sclittlec8db2ff2015-09-02 22:02:38238 http_stream->GetTotalReceivedBytes());
[email protected]b258e0792013-01-12 07:11:59239}
240
Shivani Sharma32ade742017-11-15 21:47:04241TEST_F(SpdyHttpStreamTest, RequestInfoDestroyedBeforeRead) {
Ryan Hamilton0239aac2018-05-19 00:03:13242 spdy::SpdySerializedFrame req(
243 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Shivani Sharma32ade742017-11-15 21:47:04244 MockWrite writes[] = {CreateMockWrite(req, 0)};
Ryan Hamilton0239aac2018-05-19 00:03:13245 spdy::SpdySerializedFrame resp(
246 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
247 spdy::SpdySerializedFrame body(
248 spdy_util_.ConstructSpdyDataFrame(1, "", true));
Shivani Sharma32ade742017-11-15 21:47:04249 MockRead reads[] = {
250 CreateMockRead(resp, 1), CreateMockRead(body, 2),
251 MockRead(ASYNC, 0, 3) // EOF
252 };
253
Ryan Sleevib8d7ea02018-05-07 20:01:01254 InitSession(reads, writes);
Shivani Sharma32ade742017-11-15 21:47:04255
256 std::unique_ptr<HttpRequestInfo> request =
257 std::make_unique<HttpRequestInfo>();
258 request->method = "GET";
259 request->url = url_;
Ramin Halavati216426e2018-03-12 22:13:35260 request->traffic_annotation =
261 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharma32ade742017-11-15 21:47:04262 TestCompletionCallback callback;
263 HttpResponseInfo response;
264 HttpRequestHeaders headers;
265 NetLogWithSource net_log;
Bence Békye8955cf22018-01-02 17:31:29266 auto http_stream = std::make_unique<SpdyHttpStream>(
Cammie Smith Barnes5191037b72021-03-01 22:06:53267 session_, kNoPushedStreamFound, net_log.source(),
Eric Orthac661912022-01-10 21:44:17268 /*dns_aliases=*/std::set<std::string>());
Shivani Sharma32ade742017-11-15 21:47:04269
Ali Beyada0b1a1c2022-04-08 20:08:14270 http_stream->RegisterRequest(request.get());
271 ASSERT_THAT(http_stream->InitializeStream(true, DEFAULT_PRIORITY, net_log,
272 CompletionOnceCallback()),
273 IsOk());
Shivani Sharma32ade742017-11-15 21:47:04274 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
275 IsError(ERR_IO_PENDING));
276 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
277
278 EXPECT_LE(0, callback.WaitForResult());
279
280 TestLoadTimingNotReused(*http_stream);
281 LoadTimingInfo load_timing_info;
282 EXPECT_TRUE(http_stream->GetLoadTimingInfo(&load_timing_info));
283
284 // Perform all async reads.
285 base::RunLoop().RunUntilIdle();
286
287 // Destroy the request info before Read starts.
288 request.reset();
289
290 // Read stream to completion.
Victor Costan9c7302b2018-08-27 16:39:44291 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(1);
Shivani Sharma32ade742017-11-15 21:47:04292 ASSERT_EQ(0,
293 http_stream->ReadResponseBody(buf.get(), 1, callback.callback()));
294
295 // Stream 1 has been read to completion.
296 TestLoadTimingNotReused(*http_stream);
297
298 EXPECT_EQ(static_cast<int64_t>(req.size()), http_stream->GetTotalSentBytes());
299 EXPECT_EQ(static_cast<int64_t>(resp.size() + body.size()),
300 http_stream->GetTotalReceivedBytes());
301}
302
bncd16676a2016-07-20 16:23:01303TEST_F(SpdyHttpStreamTest, LoadTimingTwoRequests) {
Ryan Hamilton0239aac2018-05-19 00:03:13304 spdy::SpdySerializedFrame req1(
305 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
306 spdy::SpdySerializedFrame req2(
307 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
[email protected]b258e0792013-01-12 07:11:59308 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41309 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]b258e0792013-01-12 07:11:59310 };
Ryan Hamilton0239aac2018-05-19 00:03:13311 spdy::SpdySerializedFrame resp1(
312 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
313 spdy::SpdySerializedFrame body1(
314 spdy_util_.ConstructSpdyDataFrame(1, "", true));
315 spdy::SpdySerializedFrame resp2(
316 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
317 spdy::SpdySerializedFrame body2(
318 spdy_util_.ConstructSpdyDataFrame(3, "", true));
[email protected]b258e0792013-01-12 07:11:59319 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41320 CreateMockRead(resp1, 2), CreateMockRead(body1, 3),
321 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
322 MockRead(ASYNC, 0, 6) // EOF
[email protected]b258e0792013-01-12 07:11:59323 };
324
Ryan Sleevib8d7ea02018-05-07 20:01:01325 InitSession(reads, writes);
[email protected]b258e0792013-01-12 07:11:59326
327 HttpRequestInfo request1;
328 request1.method = "GET";
bnca2fbdc9b2016-11-22 21:14:26329 request1.url = url_;
Ramin Halavati216426e2018-03-12 22:13:35330 request1.traffic_annotation =
331 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b258e0792013-01-12 07:11:59332 TestCompletionCallback callback1;
333 HttpResponseInfo response1;
334 HttpRequestHeaders headers1;
bnc3d95ca92017-03-29 13:20:34335 NetLogWithSource net_log;
Bence Békye8955cf22018-01-02 17:31:29336 auto http_stream1 = std::make_unique<SpdyHttpStream>(
Cammie Smith Barnes5191037b72021-03-01 22:06:53337 session_, kNoPushedStreamFound, net_log.source(),
Eric Orthac661912022-01-10 21:44:17338 /*dns_aliases=*/std::set<std::string>());
[email protected]b258e0792013-01-12 07:11:59339
[email protected]b258e0792013-01-12 07:11:59340 HttpRequestInfo request2;
341 request2.method = "GET";
bnca2fbdc9b2016-11-22 21:14:26342 request2.url = url_;
Ramin Halavati216426e2018-03-12 22:13:35343 request2.traffic_annotation =
344 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b258e0792013-01-12 07:11:59345 TestCompletionCallback callback2;
346 HttpResponseInfo response2;
347 HttpRequestHeaders headers2;
Bence Békye8955cf22018-01-02 17:31:29348 auto http_stream2 = std::make_unique<SpdyHttpStream>(
Cammie Smith Barnes5191037b72021-03-01 22:06:53349 session_, kNoPushedStreamFound, net_log.source(),
Eric Orthac661912022-01-10 21:44:17350 /*dns_aliases=*/std::set<std::string>());
[email protected]b258e0792013-01-12 07:11:59351
[email protected]099bc7e2013-07-18 04:19:16352 // First write.
Ali Beyada0b1a1c2022-04-08 20:08:14353 http_stream1->RegisterRequest(&request1);
354 ASSERT_THAT(http_stream1->InitializeStream(true, DEFAULT_PRIORITY, net_log,
355 CompletionOnceCallback()),
bnc3d95ca92017-03-29 13:20:34356 IsOk());
bnca2fbdc9b2016-11-22 21:14:26357 EXPECT_THAT(
358 http_stream1->SendRequest(headers1, &response1, callback1.callback()),
359 IsError(ERR_IO_PENDING));
bnc3d9035b32016-06-30 18:18:48360 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]b258e0792013-01-12 07:11:59361
[email protected]b258e0792013-01-12 07:11:59362 EXPECT_LE(0, callback1.WaitForResult());
363
364 TestLoadTimingNotReused(*http_stream1);
365 LoadTimingInfo load_timing_info1;
366 LoadTimingInfo load_timing_info2;
367 EXPECT_TRUE(http_stream1->GetLoadTimingInfo(&load_timing_info1));
368 EXPECT_FALSE(http_stream2->GetLoadTimingInfo(&load_timing_info2));
369
370 // Second write.
Ali Beyada0b1a1c2022-04-08 20:08:14371 http_stream2->RegisterRequest(&request2);
372 ASSERT_THAT(http_stream2->InitializeStream(true, DEFAULT_PRIORITY, net_log,
373 CompletionOnceCallback()),
bnc3d95ca92017-03-29 13:20:34374 IsOk());
bnca2fbdc9b2016-11-22 21:14:26375 EXPECT_THAT(
376 http_stream2->SendRequest(headers2, &response2, callback2.callback()),
377 IsError(ERR_IO_PENDING));
bnc3d9035b32016-06-30 18:18:48378 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]099bc7e2013-07-18 04:19:16379
[email protected]b258e0792013-01-12 07:11:59380 EXPECT_LE(0, callback2.WaitForResult());
bnceb9aa7112017-01-05 01:03:46381
382 // Perform all async reads.
383 base::RunLoop().RunUntilIdle();
384
[email protected]b258e0792013-01-12 07:11:59385 TestLoadTimingReused(*http_stream2);
386 EXPECT_TRUE(http_stream2->GetLoadTimingInfo(&load_timing_info2));
387 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
388
[email protected]b258e0792013-01-12 07:11:59389 // Read stream 1 to completion, before making sure we can still read load
390 // timing from both streams.
Victor Costan9c7302b2018-08-27 16:39:44391 scoped_refptr<IOBuffer> buf1 = base::MakeRefCounted<IOBuffer>(1);
[email protected]90499482013-06-01 00:39:50392 ASSERT_EQ(
393 0, http_stream1->ReadResponseBody(buf1.get(), 1, callback1.callback()));
[email protected]b258e0792013-01-12 07:11:59394
395 // Stream 1 has been read to completion.
396 TestLoadTimingNotReused(*http_stream1);
sclittlec8db2ff2015-09-02 22:02:38397
bncdf80d44fd2016-07-15 20:27:41398 EXPECT_EQ(static_cast<int64_t>(req1.size()),
sclittlec8db2ff2015-09-02 22:02:38399 http_stream1->GetTotalSentBytes());
bncdf80d44fd2016-07-15 20:27:41400 EXPECT_EQ(static_cast<int64_t>(resp1.size() + body1.size()),
sclittlec8db2ff2015-09-02 22:02:38401 http_stream1->GetTotalReceivedBytes());
402
[email protected]b258e0792013-01-12 07:11:59403 // Stream 2 still has queued body data.
404 TestLoadTimingReused(*http_stream2);
sclittlec8db2ff2015-09-02 22:02:38405
bncdf80d44fd2016-07-15 20:27:41406 EXPECT_EQ(static_cast<int64_t>(req2.size()),
sclittlec8db2ff2015-09-02 22:02:38407 http_stream2->GetTotalSentBytes());
bncdf80d44fd2016-07-15 20:27:41408 EXPECT_EQ(static_cast<int64_t>(resp2.size() + body2.size()),
sclittlec8db2ff2015-09-02 22:02:38409 http_stream2->GetTotalReceivedBytes());
[email protected]0c9bf872011-03-04 17:53:22410}
411
bncd16676a2016-07-20 16:23:01412TEST_F(SpdyHttpStreamTest, SendChunkedPost) {
Ryan Hamilton0239aac2018-05-19 00:03:13413 spdy::SpdySerializedFrame req(
414 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
415 spdy::SpdySerializedFrame body(
416 spdy_util_.ConstructSpdyDataFrame(1, kUploadData,
417 /*fin=*/true));
bnc78edcd52015-06-04 11:34:03418 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41419 CreateMockWrite(req, 0), // request
420 CreateMockWrite(body, 1) // POST upload frame
bnc78edcd52015-06-04 11:34:03421 };
[email protected]d46715c2013-04-15 00:21:42422
Ryan Hamilton0239aac2018-05-19 00:03:13423 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bnc78edcd52015-06-04 11:34:03424 MockRead reads[] = {
bnceb9aa7112017-01-05 01:03:46425 CreateMockRead(resp, 2), CreateMockRead(body, 3, SYNCHRONOUS),
bnc78edcd52015-06-04 11:34:03426 MockRead(SYNCHRONOUS, 0, 4) // EOF
427 };
[email protected]0c9bf872011-03-04 17:53:22428
Ryan Sleevib8d7ea02018-05-07 20:01:01429 InitSession(reads, writes);
[email protected]0c9bf872011-03-04 17:53:22430
mmenkecbc2b712014-10-09 20:29:07431 ChunkedUploadDataStream upload_stream(0);
[email protected]34b345f92013-02-22 03:27:26432 const int kFirstChunkSize = kUploadDataSize/2;
mmenkecbc2b712014-10-09 20:29:07433 upload_stream.AppendData(kUploadData, kFirstChunkSize, false);
434 upload_stream.AppendData(kUploadData + kFirstChunkSize,
[email protected]34b345f92013-02-22 03:27:26435 kUploadDataSize - kFirstChunkSize, true);
[email protected]329b68b2012-11-14 17:54:27436
[email protected]0c9bf872011-03-04 17:53:22437 HttpRequestInfo request;
438 request.method = "POST";
bnca2fbdc9b2016-11-22 21:14:26439 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:35440 request.traffic_annotation =
441 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:27442 request.upload_data_stream = &upload_stream;
[email protected]9a963892012-11-01 11:48:13443
tfarina42834112016-09-22 13:38:20444 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
445 NetLogWithSource()),
446 IsOk());
[email protected]9a963892012-11-01 11:48:13447
[email protected]49639fa2011-12-20 23:22:41448 TestCompletionCallback callback;
[email protected]0c9bf872011-03-04 17:53:22449 HttpResponseInfo response;
450 HttpRequestHeaders headers;
tfarina42834112016-09-22 13:38:20451 NetLogWithSource net_log;
Cammie Smith Barnes5191037b72021-03-01 22:06:53452 SpdyHttpStream http_stream(session_, kNoPushedStreamFound, net_log.source(),
453 {} /* dns_aliases */);
Ali Beyada0b1a1c2022-04-08 20:08:14454 http_stream.RegisterRequest(&request);
455 ASSERT_THAT(http_stream.InitializeStream(false, DEFAULT_PRIORITY, net_log,
456 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:26457 IsOk());
[email protected]0c9bf872011-03-04 17:53:22458
bnca2fbdc9b2016-11-22 21:14:26459 EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
460 IsError(ERR_IO_PENDING));
bnc3d9035b32016-06-30 18:18:48461 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]0c9bf872011-03-04 17:53:22462
robpercival214763f2016-07-01 23:27:01463 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]0c9bf872011-03-04 17:53:22464
bncdf80d44fd2016-07-15 20:27:41465 EXPECT_EQ(static_cast<int64_t>(req.size() + body.size()),
sclittlec8db2ff2015-09-02 22:02:38466 http_stream.GetTotalSentBytes());
bncdf80d44fd2016-07-15 20:27:41467 EXPECT_EQ(static_cast<int64_t>(resp.size() + body.size()),
sclittlec8db2ff2015-09-02 22:02:38468 http_stream.GetTotalReceivedBytes());
469
mmenke00d40932015-08-21 21:19:54470 // Because the server closed the connection, we there shouldn't be a session
471 // in the pool anymore.
bnc3d9035b32016-06-30 18:18:48472 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]d2360a52010-07-26 04:48:13473}
474
maksim.sisov8d2df66d2016-06-20 07:07:11475// This unittest tests the request callback is properly called and handled.
bncd16676a2016-07-20 16:23:01476TEST_F(SpdyHttpStreamTest, SendChunkedPostLastEmpty) {
Ryan Hamilton0239aac2018-05-19 00:03:13477 spdy::SpdySerializedFrame req(
478 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
479 spdy::SpdySerializedFrame chunk(
480 spdy_util_.ConstructSpdyDataFrame(1, "", true));
maksim.sisov8d2df66d2016-06-20 07:07:11481 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41482 CreateMockWrite(req, 0), // request
483 CreateMockWrite(chunk, 1),
maksim.sisov8d2df66d2016-06-20 07:07:11484 };
485
Ryan Hamilton0239aac2018-05-19 00:03:13486 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
maksim.sisov8d2df66d2016-06-20 07:07:11487 MockRead reads[] = {
bnceb9aa7112017-01-05 01:03:46488 CreateMockRead(resp, 2), CreateMockRead(chunk, 3, SYNCHRONOUS),
maksim.sisov8d2df66d2016-06-20 07:07:11489 MockRead(SYNCHRONOUS, 0, 4) // EOF
490 };
491
Ryan Sleevib8d7ea02018-05-07 20:01:01492 InitSession(reads, writes);
maksim.sisov8d2df66d2016-06-20 07:07:11493
494 ChunkedUploadDataStream upload_stream(0);
495 upload_stream.AppendData(nullptr, 0, true);
496
497 HttpRequestInfo request;
498 request.method = "POST";
bnca2fbdc9b2016-11-22 21:14:26499 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:35500 request.traffic_annotation =
501 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov8d2df66d2016-06-20 07:07:11502 request.upload_data_stream = &upload_stream;
503
tfarina42834112016-09-22 13:38:20504 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
505 NetLogWithSource()),
506 IsOk());
maksim.sisov8d2df66d2016-06-20 07:07:11507
508 TestCompletionCallback callback;
509 HttpResponseInfo response;
510 HttpRequestHeaders headers;
tfarina42834112016-09-22 13:38:20511 NetLogWithSource net_log;
Cammie Smith Barnes5191037b72021-03-01 22:06:53512 SpdyHttpStream http_stream(session_, kNoPushedStreamFound, net_log.source(),
513 {} /* dns_aliases */);
Ali Beyada0b1a1c2022-04-08 20:08:14514 http_stream.RegisterRequest(&request);
515 ASSERT_THAT(http_stream.InitializeStream(false, DEFAULT_PRIORITY, net_log,
516 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:26517 IsOk());
518 EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
519 IsError(ERR_IO_PENDING));
bnc3d9035b32016-06-30 18:18:48520 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
maksim.sisov8d2df66d2016-06-20 07:07:11521
robpercival214763f2016-07-01 23:27:01522 EXPECT_THAT(callback.WaitForResult(), IsOk());
maksim.sisov8d2df66d2016-06-20 07:07:11523
bncdf80d44fd2016-07-15 20:27:41524 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk.size()),
maksim.sisov8d2df66d2016-06-20 07:07:11525 http_stream.GetTotalSentBytes());
bncdf80d44fd2016-07-15 20:27:41526 EXPECT_EQ(static_cast<int64_t>(resp.size() + chunk.size()),
maksim.sisov8d2df66d2016-06-20 07:07:11527 http_stream.GetTotalReceivedBytes());
528
529 // Because the server closed the connection, there shouldn't be a session
530 // in the pool anymore.
bnc3d9035b32016-06-30 18:18:48531 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
maksim.sisov8d2df66d2016-06-20 07:07:11532}
533
bncd16676a2016-07-20 16:23:01534TEST_F(SpdyHttpStreamTest, ConnectionClosedDuringChunkedPost) {
Ryan Hamilton0239aac2018-05-19 00:03:13535 spdy::SpdySerializedFrame req(
536 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
537 spdy::SpdySerializedFrame body(
538 spdy_util_.ConstructSpdyDataFrame(1, kUploadData,
539 /*fin=*/false));
mmenke00d40932015-08-21 21:19:54540 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41541 CreateMockWrite(req, 0), // Request
542 CreateMockWrite(body, 1) // First POST upload frame
mmenke00d40932015-08-21 21:19:54543 };
544
Ryan Hamilton0239aac2018-05-19 00:03:13545 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
mmenke00d40932015-08-21 21:19:54546 MockRead reads[] = {
547 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2) // Server hangs up early.
548 };
549
Ryan Sleevib8d7ea02018-05-07 20:01:01550 InitSession(reads, writes);
mmenke00d40932015-08-21 21:19:54551
552 ChunkedUploadDataStream upload_stream(0);
553 // Append first chunk.
554 upload_stream.AppendData(kUploadData, kUploadDataSize, false);
555
556 HttpRequestInfo request;
557 request.method = "POST";
bnca2fbdc9b2016-11-22 21:14:26558 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:35559 request.traffic_annotation =
560 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke00d40932015-08-21 21:19:54561 request.upload_data_stream = &upload_stream;
562
tfarina42834112016-09-22 13:38:20563 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
564 NetLogWithSource()),
565 IsOk());
mmenke00d40932015-08-21 21:19:54566
567 TestCompletionCallback callback;
568 HttpResponseInfo response;
569 HttpRequestHeaders headers;
tfarina42834112016-09-22 13:38:20570 NetLogWithSource net_log;
Cammie Smith Barnes5191037b72021-03-01 22:06:53571 SpdyHttpStream http_stream(session_, kNoPushedStreamFound, net_log.source(),
572 {} /* dns_aliases */);
Ali Beyada0b1a1c2022-04-08 20:08:14573 http_stream.RegisterRequest(&request);
574 ASSERT_THAT(http_stream.InitializeStream(false, DEFAULT_PRIORITY, net_log,
575 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:26576 IsOk());
mmenke00d40932015-08-21 21:19:54577
bnca2fbdc9b2016-11-22 21:14:26578 EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
579 IsError(ERR_IO_PENDING));
bnc3d9035b32016-06-30 18:18:48580 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
mmenke00d40932015-08-21 21:19:54581
robpercival214763f2016-07-01 23:27:01582 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
mmenke00d40932015-08-21 21:19:54583
bncdf80d44fd2016-07-15 20:27:41584 EXPECT_EQ(static_cast<int64_t>(req.size() + body.size()),
sclittlec8db2ff2015-09-02 22:02:38585 http_stream.GetTotalSentBytes());
586 EXPECT_EQ(0, http_stream.GetTotalReceivedBytes());
587
mmenke00d40932015-08-21 21:19:54588 // Because the server closed the connection, we there shouldn't be a session
589 // in the pool anymore.
bnc3d9035b32016-06-30 18:18:48590 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
mmenke00d40932015-08-21 21:19:54591
592 // Appending a second chunk now should not result in a crash.
593 upload_stream.AppendData(kUploadData, kUploadDataSize, true);
594 // Appending data is currently done synchronously, but seems best to be
595 // paranoid.
596 base::RunLoop().RunUntilIdle();
sclittlec8db2ff2015-09-02 22:02:38597
598 // The total sent and received bytes should be unchanged.
bncdf80d44fd2016-07-15 20:27:41599 EXPECT_EQ(static_cast<int64_t>(req.size() + body.size()),
sclittlec8db2ff2015-09-02 22:02:38600 http_stream.GetTotalSentBytes());
601 EXPECT_EQ(0, http_stream.GetTotalReceivedBytes());
mmenke00d40932015-08-21 21:19:54602}
603
[email protected]e37ce372012-07-12 01:00:40604// Test to ensure the SpdyStream state machine does not get confused when a
605// chunk becomes available while a write is pending.
bncd16676a2016-07-20 16:23:01606TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPost) {
[email protected]e37ce372012-07-12 01:00:40607 const char kUploadData1[] = "12345678";
Daniel Cheng5feb16f2022-02-28 06:52:07608 const int kUploadData1Size = std::size(kUploadData1) - 1;
Ryan Hamilton0239aac2018-05-19 00:03:13609 spdy::SpdySerializedFrame req(
610 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
611 spdy::SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false));
612 spdy::SpdySerializedFrame chunk2(
Bence Békyd74f4382018-02-20 18:26:19613 spdy_util_.ConstructSpdyDataFrame(1, kUploadData1, false));
Ryan Hamilton0239aac2018-05-19 00:03:13614 spdy::SpdySerializedFrame chunk3(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e37ce372012-07-12 01:00:40615 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41616 CreateMockWrite(req, 0),
617 CreateMockWrite(chunk1, 1), // POST upload frames
618 CreateMockWrite(chunk2, 2), CreateMockWrite(chunk3, 3),
[email protected]e37ce372012-07-12 01:00:40619 };
Ryan Hamilton0239aac2018-05-19 00:03:13620 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]e37ce372012-07-12 01:00:40621 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41622 CreateMockRead(resp, 4), CreateMockRead(chunk1, 5),
623 CreateMockRead(chunk2, 6), CreateMockRead(chunk3, 7),
624 MockRead(ASYNC, 0, 8) // EOF
[email protected]e37ce372012-07-12 01:00:40625 };
626
Ryan Sleevib8d7ea02018-05-07 20:01:01627 InitSession(reads, writes);
[email protected]e37ce372012-07-12 01:00:40628
mmenkecbc2b712014-10-09 20:29:07629 ChunkedUploadDataStream upload_stream(0);
[email protected]329b68b2012-11-14 17:54:27630
[email protected]e37ce372012-07-12 01:00:40631 HttpRequestInfo request;
632 request.method = "POST";
bnca2fbdc9b2016-11-22 21:14:26633 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:35634 request.traffic_annotation =
635 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:27636 request.upload_data_stream = &upload_stream;
[email protected]e37ce372012-07-12 01:00:40637
tfarina42834112016-09-22 13:38:20638 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
639 NetLogWithSource()),
640 IsOk());
mmenkecbc2b712014-10-09 20:29:07641 upload_stream.AppendData(kUploadData, kUploadDataSize, false);
[email protected]9a963892012-11-01 11:48:13642
tfarina42834112016-09-22 13:38:20643 NetLogWithSource net_log;
Bence Békye8955cf22018-01-02 17:31:29644 auto http_stream = std::make_unique<SpdyHttpStream>(
Cammie Smith Barnes5191037b72021-03-01 22:06:53645 session_, kNoPushedStreamFound, net_log.source(),
Eric Orthac661912022-01-10 21:44:17646 /*dns_aliases=*/std::set<std::string>());
Ali Beyada0b1a1c2022-04-08 20:08:14647 http_stream->RegisterRequest(&request);
648 ASSERT_THAT(http_stream->InitializeStream(false, DEFAULT_PRIORITY, net_log,
649 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:26650 IsOk());
[email protected]e37ce372012-07-12 01:00:40651
[email protected]b258e0792013-01-12 07:11:59652 TestCompletionCallback callback;
[email protected]e37ce372012-07-12 01:00:40653 HttpRequestHeaders headers;
654 HttpResponseInfo response;
655 // This will attempt to Write() the initial request and headers, which will
656 // complete asynchronously.
bnca2fbdc9b2016-11-22 21:14:26657 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
658 IsError(ERR_IO_PENDING));
bnc3d9035b32016-06-30 18:18:48659 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]e37ce372012-07-12 01:00:40660
661 // Complete the initial request write and the first chunk.
bnc78edcd52015-06-04 11:34:03662 base::RunLoop().RunUntilIdle();
maksim.sisov8d2df66d2016-06-20 07:07:11663 ASSERT_FALSE(callback.have_result());
[email protected]e37ce372012-07-12 01:00:40664
665 // Now append the final two chunks which will enqueue two more writes.
mmenkecbc2b712014-10-09 20:29:07666 upload_stream.AppendData(kUploadData1, kUploadData1Size, false);
667 upload_stream.AppendData(kUploadData, kUploadDataSize, true);
[email protected]e37ce372012-07-12 01:00:40668
bnc78edcd52015-06-04 11:34:03669 // Finish writing all the chunks and do all reads.
670 base::RunLoop().RunUntilIdle();
maksim.sisov8d2df66d2016-06-20 07:07:11671 ASSERT_TRUE(callback.have_result());
robpercival214763f2016-07-01 23:27:01672 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e37ce372012-07-12 01:00:40673
bncdf80d44fd2016-07-15 20:27:41674 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk1.size() + chunk2.size() +
675 chunk3.size()),
sclittlec8db2ff2015-09-02 22:02:38676 http_stream->GetTotalSentBytes());
bncdf80d44fd2016-07-15 20:27:41677 EXPECT_EQ(static_cast<int64_t>(resp.size() + chunk1.size() + chunk2.size() +
678 chunk3.size()),
sclittlec8db2ff2015-09-02 22:02:38679 http_stream->GetTotalReceivedBytes());
680
bnc78edcd52015-06-04 11:34:03681 // Check response headers.
robpercival214763f2016-07-01 23:27:01682 ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
[email protected]e37ce372012-07-12 01:00:40683
bnc78edcd52015-06-04 11:34:03684 // Check |chunk1| response.
Victor Costan9c7302b2018-08-27 16:39:44685 scoped_refptr<IOBuffer> buf1 =
686 base::MakeRefCounted<IOBuffer>(kUploadDataSize);
[email protected]e37ce372012-07-12 01:00:40687 ASSERT_EQ(kUploadDataSize,
[email protected]90499482013-06-01 00:39:50688 http_stream->ReadResponseBody(
689 buf1.get(), kUploadDataSize, callback.callback()));
Bence Béky4e83f492018-05-13 23:14:25690 EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
[email protected]e37ce372012-07-12 01:00:40691
bnc78edcd52015-06-04 11:34:03692 // Check |chunk2| response.
Victor Costan9c7302b2018-08-27 16:39:44693 scoped_refptr<IOBuffer> buf2 =
694 base::MakeRefCounted<IOBuffer>(kUploadData1Size);
[email protected]e37ce372012-07-12 01:00:40695 ASSERT_EQ(kUploadData1Size,
[email protected]90499482013-06-01 00:39:50696 http_stream->ReadResponseBody(
697 buf2.get(), kUploadData1Size, callback.callback()));
Bence Béky4e83f492018-05-13 23:14:25698 EXPECT_EQ(kUploadData1, std::string(buf2->data(), kUploadData1Size));
[email protected]e37ce372012-07-12 01:00:40699
bnc78edcd52015-06-04 11:34:03700 // Check |chunk3| response.
Victor Costan9c7302b2018-08-27 16:39:44701 scoped_refptr<IOBuffer> buf3 =
702 base::MakeRefCounted<IOBuffer>(kUploadDataSize);
[email protected]e37ce372012-07-12 01:00:40703 ASSERT_EQ(kUploadDataSize,
[email protected]90499482013-06-01 00:39:50704 http_stream->ReadResponseBody(
705 buf3.get(), kUploadDataSize, callback.callback()));
Bence Béky4e83f492018-05-13 23:14:25706 EXPECT_EQ(kUploadData, std::string(buf3->data(), kUploadDataSize));
[email protected]e37ce372012-07-12 01:00:40707
[email protected]e37ce372012-07-12 01:00:40708 ASSERT_TRUE(response.headers.get());
709 ASSERT_EQ(200, response.headers->response_code());
[email protected]e37ce372012-07-12 01:00:40710}
711
[email protected]ec89d0c2014-08-21 22:58:03712// Test that the SpdyStream state machine can handle sending a final empty data
713// frame when uploading a chunked data stream.
bncd16676a2016-07-20 16:23:01714TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPostWithEmptyFinalDataFrame) {
Ryan Hamilton0239aac2018-05-19 00:03:13715 spdy::SpdySerializedFrame req(
716 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
717 spdy::SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false));
718 spdy::SpdySerializedFrame chunk2(
719 spdy_util_.ConstructSpdyDataFrame(1, "", true));
[email protected]ec89d0c2014-08-21 22:58:03720 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41721 CreateMockWrite(req, 0),
722 CreateMockWrite(chunk1, 1), // POST upload frames
723 CreateMockWrite(chunk2, 2),
[email protected]ec89d0c2014-08-21 22:58:03724 };
Ryan Hamilton0239aac2018-05-19 00:03:13725 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]ec89d0c2014-08-21 22:58:03726 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41727 CreateMockRead(resp, 3), CreateMockRead(chunk1, 4),
728 CreateMockRead(chunk2, 5), MockRead(ASYNC, 0, 6) // EOF
[email protected]ec89d0c2014-08-21 22:58:03729 };
730
Ryan Sleevib8d7ea02018-05-07 20:01:01731 InitSession(reads, writes);
[email protected]ec89d0c2014-08-21 22:58:03732
mmenkecbc2b712014-10-09 20:29:07733 ChunkedUploadDataStream upload_stream(0);
[email protected]ec89d0c2014-08-21 22:58:03734
735 HttpRequestInfo request;
736 request.method = "POST";
bnca2fbdc9b2016-11-22 21:14:26737 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:35738 request.traffic_annotation =
739 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ec89d0c2014-08-21 22:58:03740 request.upload_data_stream = &upload_stream;
741
tfarina42834112016-09-22 13:38:20742 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
743 NetLogWithSource()),
744 IsOk());
mmenkecbc2b712014-10-09 20:29:07745 upload_stream.AppendData(kUploadData, kUploadDataSize, false);
[email protected]ec89d0c2014-08-21 22:58:03746
tfarina42834112016-09-22 13:38:20747 NetLogWithSource net_log;
Bence Békye8955cf22018-01-02 17:31:29748 auto http_stream = std::make_unique<SpdyHttpStream>(
Cammie Smith Barnes5191037b72021-03-01 22:06:53749 session_, kNoPushedStreamFound, net_log.source(),
Eric Orthac661912022-01-10 21:44:17750 /*dns_aliases=*/std::set<std::string>());
Ali Beyada0b1a1c2022-04-08 20:08:14751 http_stream->RegisterRequest(&request);
752 ASSERT_THAT(http_stream->InitializeStream(false, DEFAULT_PRIORITY, net_log,
753 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:26754 IsOk());
[email protected]ec89d0c2014-08-21 22:58:03755
756 TestCompletionCallback callback;
757 HttpRequestHeaders headers;
758 HttpResponseInfo response;
759 // This will attempt to Write() the initial request and headers, which will
760 // complete asynchronously.
bnca2fbdc9b2016-11-22 21:14:26761 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
762 IsError(ERR_IO_PENDING));
bnc3d9035b32016-06-30 18:18:48763 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]ec89d0c2014-08-21 22:58:03764
765 // Complete the initial request write and the first chunk.
bnc78edcd52015-06-04 11:34:03766 base::RunLoop().RunUntilIdle();
maksim.sisov8d2df66d2016-06-20 07:07:11767 ASSERT_FALSE(callback.have_result());
[email protected]ec89d0c2014-08-21 22:58:03768
bncdf80d44fd2016-07-15 20:27:41769 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk1.size()),
sclittlec8db2ff2015-09-02 22:02:38770 http_stream->GetTotalSentBytes());
771 EXPECT_EQ(0, http_stream->GetTotalReceivedBytes());
772
[email protected]ec89d0c2014-08-21 22:58:03773 // Now end the stream with an empty data frame and the FIN set.
maksim.sisov167c3c02016-06-23 07:31:52774 upload_stream.AppendData(nullptr, 0, true);
[email protected]ec89d0c2014-08-21 22:58:03775
bnc78edcd52015-06-04 11:34:03776 // Finish writing the final frame, and perform all reads.
777 base::RunLoop().RunUntilIdle();
maksim.sisov8d2df66d2016-06-20 07:07:11778 ASSERT_TRUE(callback.have_result());
robpercival214763f2016-07-01 23:27:01779 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]ec89d0c2014-08-21 22:58:03780
bnc78edcd52015-06-04 11:34:03781 // Check response headers.
robpercival214763f2016-07-01 23:27:01782 ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
[email protected]ec89d0c2014-08-21 22:58:03783
bncdf80d44fd2016-07-15 20:27:41784 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk1.size() + chunk2.size()),
sclittlec8db2ff2015-09-02 22:02:38785 http_stream->GetTotalSentBytes());
bncdf80d44fd2016-07-15 20:27:41786 EXPECT_EQ(static_cast<int64_t>(resp.size() + chunk1.size() + chunk2.size()),
787 http_stream->GetTotalReceivedBytes());
sclittlec8db2ff2015-09-02 22:02:38788
bnc78edcd52015-06-04 11:34:03789 // Check |chunk1| response.
Victor Costan9c7302b2018-08-27 16:39:44790 scoped_refptr<IOBuffer> buf1 =
791 base::MakeRefCounted<IOBuffer>(kUploadDataSize);
[email protected]ec89d0c2014-08-21 22:58:03792 ASSERT_EQ(kUploadDataSize,
793 http_stream->ReadResponseBody(
794 buf1.get(), kUploadDataSize, callback.callback()));
Bence Béky4e83f492018-05-13 23:14:25795 EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
[email protected]ec89d0c2014-08-21 22:58:03796
bnc78edcd52015-06-04 11:34:03797 // Check |chunk2| response.
[email protected]ec89d0c2014-08-21 22:58:03798 ASSERT_EQ(0,
799 http_stream->ReadResponseBody(
800 buf1.get(), kUploadDataSize, callback.callback()));
801
[email protected]ec89d0c2014-08-21 22:58:03802 ASSERT_TRUE(response.headers.get());
803 ASSERT_EQ(200, response.headers->response_code());
[email protected]ec89d0c2014-08-21 22:58:03804}
805
806// Test that the SpdyStream state machine handles a chunked upload with no
807// payload. Unclear if this is a case worth supporting.
bncd16676a2016-07-20 16:23:01808TEST_F(SpdyHttpStreamTest, ChunkedPostWithEmptyPayload) {
Ryan Hamilton0239aac2018-05-19 00:03:13809 spdy::SpdySerializedFrame req(
810 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
811 spdy::SpdySerializedFrame chunk(
812 spdy_util_.ConstructSpdyDataFrame(1, "", true));
[email protected]ec89d0c2014-08-21 22:58:03813 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41814 CreateMockWrite(req, 0), CreateMockWrite(chunk, 1),
[email protected]ec89d0c2014-08-21 22:58:03815 };
Ryan Hamilton0239aac2018-05-19 00:03:13816 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]ec89d0c2014-08-21 22:58:03817 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41818 CreateMockRead(resp, 2), CreateMockRead(chunk, 3),
819 MockRead(ASYNC, 0, 4) // EOF
[email protected]ec89d0c2014-08-21 22:58:03820 };
821
Ryan Sleevib8d7ea02018-05-07 20:01:01822 InitSession(reads, writes);
[email protected]ec89d0c2014-08-21 22:58:03823
mmenkecbc2b712014-10-09 20:29:07824 ChunkedUploadDataStream upload_stream(0);
[email protected]ec89d0c2014-08-21 22:58:03825
826 HttpRequestInfo request;
827 request.method = "POST";
bnca2fbdc9b2016-11-22 21:14:26828 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:35829 request.traffic_annotation =
830 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ec89d0c2014-08-21 22:58:03831 request.upload_data_stream = &upload_stream;
832
tfarina42834112016-09-22 13:38:20833 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
834 NetLogWithSource()),
835 IsOk());
mmenkecbc2b712014-10-09 20:29:07836 upload_stream.AppendData("", 0, true);
[email protected]ec89d0c2014-08-21 22:58:03837
tfarina42834112016-09-22 13:38:20838 NetLogWithSource net_log;
Bence Békye8955cf22018-01-02 17:31:29839 auto http_stream = std::make_unique<SpdyHttpStream>(
Cammie Smith Barnes5191037b72021-03-01 22:06:53840 session_, kNoPushedStreamFound, net_log.source(),
Eric Orthac661912022-01-10 21:44:17841 /*dns_aliases=*/std::set<std::string>());
Ali Beyada0b1a1c2022-04-08 20:08:14842 http_stream->RegisterRequest(&request);
843 ASSERT_THAT(http_stream->InitializeStream(false, DEFAULT_PRIORITY, net_log,
844 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:26845 IsOk());
[email protected]ec89d0c2014-08-21 22:58:03846
847 TestCompletionCallback callback;
848 HttpRequestHeaders headers;
849 HttpResponseInfo response;
850 // This will attempt to Write() the initial request and headers, which will
851 // complete asynchronously.
bnca2fbdc9b2016-11-22 21:14:26852 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
853 IsError(ERR_IO_PENDING));
bnc3d9035b32016-06-30 18:18:48854 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]ec89d0c2014-08-21 22:58:03855
856 // Complete writing request, followed by a FIN.
bnc78edcd52015-06-04 11:34:03857 base::RunLoop().RunUntilIdle();
[email protected]ec89d0c2014-08-21 22:58:03858 ASSERT_TRUE(callback.have_result());
robpercival214763f2016-07-01 23:27:01859 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]ec89d0c2014-08-21 22:58:03860
bncdf80d44fd2016-07-15 20:27:41861 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk.size()),
sclittlec8db2ff2015-09-02 22:02:38862 http_stream->GetTotalSentBytes());
bncdf80d44fd2016-07-15 20:27:41863 EXPECT_EQ(static_cast<int64_t>(resp.size() + chunk.size()),
sclittlec8db2ff2015-09-02 22:02:38864 http_stream->GetTotalReceivedBytes());
865
bnc78edcd52015-06-04 11:34:03866 // Check response headers.
robpercival214763f2016-07-01 23:27:01867 ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
[email protected]ec89d0c2014-08-21 22:58:03868
bnc78edcd52015-06-04 11:34:03869 // Check |chunk| response.
Victor Costan9c7302b2018-08-27 16:39:44870 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(1);
[email protected]ec89d0c2014-08-21 22:58:03871 ASSERT_EQ(0,
872 http_stream->ReadResponseBody(
873 buf.get(), 1, callback.callback()));
874
[email protected]ec89d0c2014-08-21 22:58:03875 ASSERT_TRUE(response.headers.get());
876 ASSERT_EQ(200, response.headers->response_code());
[email protected]ec89d0c2014-08-21 22:58:03877}
878
bnca2fbdc9b2016-11-22 21:14:26879// Test case for https://crbug.com/50058.
bncd16676a2016-07-20 16:23:01880TEST_F(SpdyHttpStreamTest, SpdyURLTest) {
bnca2fbdc9b2016-11-22 21:14:26881 const char* const full_url = "https://www.example.org/foo?query=what#anchor";
882 const char* const base_url = "https://www.example.org/foo?query=what";
Ryan Hamilton0239aac2018-05-19 00:03:13883 spdy::SpdySerializedFrame req(
884 spdy_util_.ConstructSpdyGet(base_url, 1, LOWEST));
[email protected]c638a85a2010-07-29 18:41:40885 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41886 CreateMockWrite(req, 0),
[email protected]c638a85a2010-07-29 18:41:40887 };
Ryan Hamilton0239aac2018-05-19 00:03:13888 spdy::SpdySerializedFrame resp(
889 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d2360a52010-07-26 04:48:13890 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41891 CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
[email protected]d2360a52010-07-26 04:48:13892 };
893
Ryan Sleevib8d7ea02018-05-07 20:01:01894 InitSession(reads, writes);
[email protected]d2360a52010-07-26 04:48:13895
896 HttpRequestInfo request;
897 request.method = "GET";
[email protected]c638a85a2010-07-29 18:41:40898 request.url = GURL(full_url);
Ramin Halavati216426e2018-03-12 22:13:35899 request.traffic_annotation =
900 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]49639fa2011-12-20 23:22:41901 TestCompletionCallback callback;
[email protected]d2360a52010-07-26 04:48:13902 HttpResponseInfo response;
[email protected]b94f92d2010-10-27 16:45:20903 HttpRequestHeaders headers;
tfarina42834112016-09-22 13:38:20904 NetLogWithSource net_log;
Bence Békye8955cf22018-01-02 17:31:29905 auto http_stream = std::make_unique<SpdyHttpStream>(
Cammie Smith Barnes5191037b72021-03-01 22:06:53906 session_, kNoPushedStreamFound, net_log.source(),
Eric Orthac661912022-01-10 21:44:17907 /*dns_aliases=*/std::set<std::string>());
Ali Beyada0b1a1c2022-04-08 20:08:14908 http_stream->RegisterRequest(&request);
909 ASSERT_THAT(http_stream->InitializeStream(true, DEFAULT_PRIORITY, net_log,
910 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:26911 IsOk());
[email protected]c638a85a2010-07-29 18:41:40912
bnca2fbdc9b2016-11-22 21:14:26913 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
914 IsError(ERR_IO_PENDING));
[email protected]d2360a52010-07-26 04:48:13915
Bence Béky39d74292018-03-02 04:31:18916 EXPECT_EQ(base_url, http_stream->stream()->url().spec());
[email protected]d2360a52010-07-26 04:48:13917
[email protected]0107dbd2010-08-02 20:54:07918 callback.WaitForResult();
919
bncdf80d44fd2016-07-15 20:27:41920 EXPECT_EQ(static_cast<int64_t>(req.size()), http_stream->GetTotalSentBytes());
921 EXPECT_EQ(static_cast<int64_t>(resp.size()),
sclittlec8db2ff2015-09-02 22:02:38922 http_stream->GetTotalReceivedBytes());
923
[email protected]0107dbd2010-08-02 20:54:07924 // Because we abandoned the stream, we don't expect to find a session in the
925 // pool anymore.
bnc3d9035b32016-06-30 18:18:48926 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]a677f2b2009-11-22 00:43:00927}
928
[email protected]d11b6912013-06-27 23:07:32929// Test the receipt of a WINDOW_UPDATE frame while waiting for a chunk to be
930// made available is handled correctly.
bncd16676a2016-07-20 16:23:01931TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) {
Ryan Hamilton0239aac2018-05-19 00:03:13932 spdy::SpdySerializedFrame req(
933 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
934 spdy::SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:32935 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41936 CreateMockWrite(req, 0), CreateMockWrite(chunk1, 1),
[email protected]d11b6912013-06-27 23:07:32937 };
Ryan Hamilton0239aac2018-05-19 00:03:13938 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
939 spdy::SpdySerializedFrame window_update(
[email protected]d11b6912013-06-27 23:07:32940 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
941 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41942 CreateMockRead(window_update, 2), MockRead(ASYNC, ERR_IO_PENDING, 3),
943 CreateMockRead(resp, 4), CreateMockRead(chunk1, 5),
bnc78edcd52015-06-04 11:34:03944 MockRead(ASYNC, 0, 6) // EOF
[email protected]d11b6912013-06-27 23:07:32945 };
946
Ryan Sleevib8d7ea02018-05-07 20:01:01947 InitSession(reads, writes);
[email protected]d11b6912013-06-27 23:07:32948
mmenkecbc2b712014-10-09 20:29:07949 ChunkedUploadDataStream upload_stream(0);
[email protected]d11b6912013-06-27 23:07:32950
951 HttpRequestInfo request;
952 request.method = "POST";
bnca2fbdc9b2016-11-22 21:14:26953 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:35954 request.traffic_annotation =
955 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]d11b6912013-06-27 23:07:32956 request.upload_data_stream = &upload_stream;
957
tfarina42834112016-09-22 13:38:20958 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
959 NetLogWithSource()),
960 IsOk());
[email protected]d11b6912013-06-27 23:07:32961
tfarina42834112016-09-22 13:38:20962 NetLogWithSource net_log;
Bence Békye8955cf22018-01-02 17:31:29963 auto http_stream = std::make_unique<SpdyHttpStream>(
Cammie Smith Barnes5191037b72021-03-01 22:06:53964 session_, kNoPushedStreamFound, net_log.source(),
Eric Orthac661912022-01-10 21:44:17965 /*dns_aliases=*/std::set<std::string>());
Ali Beyada0b1a1c2022-04-08 20:08:14966 http_stream->RegisterRequest(&request);
967 ASSERT_THAT(http_stream->InitializeStream(false, DEFAULT_PRIORITY, net_log,
968 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:26969 IsOk());
[email protected]d11b6912013-06-27 23:07:32970
971 HttpRequestHeaders headers;
972 HttpResponseInfo response;
973 // This will attempt to Write() the initial request and headers, which will
974 // complete asynchronously.
[email protected]41d64e82013-07-03 22:44:26975 TestCompletionCallback callback;
bnca2fbdc9b2016-11-22 21:14:26976 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
977 IsError(ERR_IO_PENDING));
bnc3d9035b32016-06-30 18:18:48978 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
[email protected]d11b6912013-06-27 23:07:32979
980 // Complete the initial request write and first chunk.
bnc78edcd52015-06-04 11:34:03981 base::RunLoop().RunUntilIdle();
maksim.sisov8d2df66d2016-06-20 07:07:11982 ASSERT_FALSE(callback.have_result());
[email protected]d11b6912013-06-27 23:07:32983
bncdf80d44fd2016-07-15 20:27:41984 EXPECT_EQ(static_cast<int64_t>(req.size()), http_stream->GetTotalSentBytes());
sclittlec8db2ff2015-09-02 22:02:38985 EXPECT_EQ(0, http_stream->GetTotalReceivedBytes());
986
bnc78edcd52015-06-04 11:34:03987 upload_stream.AppendData(kUploadData, kUploadDataSize, true);
988
[email protected]d11b6912013-06-27 23:07:32989 // Verify that the window size has decreased.
maksim.sisov167c3c02016-06-23 07:31:52990 ASSERT_TRUE(http_stream->stream() != nullptr);
bncbca843ba2016-07-14 13:05:48991 EXPECT_NE(static_cast<int>(kDefaultInitialWindowSize),
bnc638c4702015-04-09 18:01:18992 http_stream->stream()->send_window_size());
[email protected]d11b6912013-06-27 23:07:32993
994 // Read window update.
bnc78edcd52015-06-04 11:34:03995 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:32996
bncaa171332016-07-20 14:47:36997 ASSERT_TRUE(callback.have_result());
998 EXPECT_THAT(callback.WaitForResult(), IsOk());
999
bncdf80d44fd2016-07-15 20:27:411000 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk1.size()),
sclittlec8db2ff2015-09-02 22:02:381001 http_stream->GetTotalSentBytes());
1002 // The window update is not counted in the total received bytes.
1003 EXPECT_EQ(0, http_stream->GetTotalReceivedBytes());
1004
[email protected]d11b6912013-06-27 23:07:321005 // Verify the window update.
maksim.sisov167c3c02016-06-23 07:31:521006 ASSERT_TRUE(http_stream->stream() != nullptr);
bncbca843ba2016-07-14 13:05:481007 EXPECT_EQ(static_cast<int>(kDefaultInitialWindowSize),
bnc638c4702015-04-09 18:01:181008 http_stream->stream()->send_window_size());
[email protected]d11b6912013-06-27 23:07:321009
bnc78edcd52015-06-04 11:34:031010 // Read rest of data.
mmenkee24011922015-12-17 22:12:591011 sequenced_data_->Resume();
bnc78edcd52015-06-04 11:34:031012 base::RunLoop().RunUntilIdle();
1013
bncdf80d44fd2016-07-15 20:27:411014 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk1.size()),
sclittlec8db2ff2015-09-02 22:02:381015 http_stream->GetTotalSentBytes());
bncdf80d44fd2016-07-15 20:27:411016 EXPECT_EQ(static_cast<int64_t>(resp.size() + chunk1.size()),
sclittlec8db2ff2015-09-02 22:02:381017 http_stream->GetTotalReceivedBytes());
1018
bnc78edcd52015-06-04 11:34:031019 // Check response headers.
robpercival214763f2016-07-01 23:27:011020 ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
[email protected]d11b6912013-06-27 23:07:321021
bnc78edcd52015-06-04 11:34:031022 // Check |chunk1| response.
Victor Costan9c7302b2018-08-27 16:39:441023 scoped_refptr<IOBuffer> buf1 =
1024 base::MakeRefCounted<IOBuffer>(kUploadDataSize);
[email protected]d11b6912013-06-27 23:07:321025 ASSERT_EQ(kUploadDataSize,
1026 http_stream->ReadResponseBody(
1027 buf1.get(), kUploadDataSize, callback.callback()));
Bence Béky4e83f492018-05-13 23:14:251028 EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
[email protected]d11b6912013-06-27 23:07:321029
[email protected]d11b6912013-06-27 23:07:321030 ASSERT_TRUE(response.headers.get());
1031 ASSERT_EQ(200, response.headers->response_code());
[email protected]d11b6912013-06-27 23:07:321032}
1033
bncd16676a2016-07-20 16:23:011034TEST_F(SpdyHttpStreamTest, DataReadErrorSynchronous) {
Ryan Hamilton0239aac2018-05-19 00:03:131035 spdy::SpdySerializedFrame req(
1036 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
maksim.sisov167c3c02016-06-23 07:31:521037
Ryan Hamilton0239aac2018-05-19 00:03:131038 // Server receives spdy::ERROR_CODE_INTERNAL_ERROR on client's internal
1039 // failure. The failure is a reading error in this case caused by
maksim.sisov167c3c02016-06-23 07:31:521040 // UploadDataStream::Read().
Ryan Hamilton0239aac2018-05-19 00:03:131041 spdy::SpdySerializedFrame rst_frame(
1042 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_INTERNAL_ERROR));
maksim.sisov167c3c02016-06-23 07:31:521043
1044 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411045 CreateMockWrite(req, 0, SYNCHRONOUS), // Request
1046 CreateMockWrite(rst_frame, 1, SYNCHRONOUS) // Reset frame
maksim.sisov167c3c02016-06-23 07:31:521047 };
1048
Ryan Hamilton0239aac2018-05-19 00:03:131049 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
maksim.sisov167c3c02016-06-23 07:31:521050
1051 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411052 CreateMockRead(resp, 2), MockRead(SYNCHRONOUS, 0, 3),
maksim.sisov167c3c02016-06-23 07:31:521053 };
1054
Ryan Sleevib8d7ea02018-05-07 20:01:011055 InitSession(reads, writes);
maksim.sisov167c3c02016-06-23 07:31:521056
1057 ReadErrorUploadDataStream upload_data_stream(
1058 ReadErrorUploadDataStream::FailureMode::SYNC);
maksim.sisov819ba852016-08-17 08:22:521059 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
tfarina42834112016-09-22 13:38:201060 NetLogWithSource()),
robpercival214763f2016-07-01 23:27:011061 IsOk());
maksim.sisov167c3c02016-06-23 07:31:521062
1063 HttpRequestInfo request;
1064 request.method = "POST";
bnca2fbdc9b2016-11-22 21:14:261065 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:351066 request.traffic_annotation =
1067 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov167c3c02016-06-23 07:31:521068 request.upload_data_stream = &upload_data_stream;
1069
1070 TestCompletionCallback callback;
1071 HttpResponseInfo response;
1072 HttpRequestHeaders headers;
tfarina42834112016-09-22 13:38:201073 NetLogWithSource net_log;
Cammie Smith Barnes5191037b72021-03-01 22:06:531074 SpdyHttpStream http_stream(session_, kNoPushedStreamFound, net_log.source(),
1075 {} /* dns_aliases */);
Ali Beyada0b1a1c2022-04-08 20:08:141076 http_stream.RegisterRequest(&request);
1077 ASSERT_THAT(http_stream.InitializeStream(false, DEFAULT_PRIORITY, net_log,
1078 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:261079 IsOk());
maksim.sisov167c3c02016-06-23 07:31:521080
1081 int result = http_stream.SendRequest(headers, &response, callback.callback());
robpercival214763f2016-07-01 23:27:011082 EXPECT_THAT(callback.GetResult(result), IsError(ERR_FAILED));
maksim.sisov167c3c02016-06-23 07:31:521083
bnceb9aa7112017-01-05 01:03:461084 // Run posted SpdyHttpStream::ResetStreamInternal() task.
1085 base::RunLoop().RunUntilIdle();
1086
maksim.sisov167c3c02016-06-23 07:31:521087 // Because the server has not closed the connection yet, there shouldn't be
1088 // a stream but a session in the pool
bnc3d9035b32016-06-30 18:18:481089 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
maksim.sisov167c3c02016-06-23 07:31:521090}
1091
bncd16676a2016-07-20 16:23:011092TEST_F(SpdyHttpStreamTest, DataReadErrorAsynchronous) {
Ryan Hamilton0239aac2018-05-19 00:03:131093 spdy::SpdySerializedFrame req(
1094 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
maksim.sisov167c3c02016-06-23 07:31:521095
Ryan Hamilton0239aac2018-05-19 00:03:131096 // Server receives spdy::ERROR_CODE_INTERNAL_ERROR on client's internal
1097 // failure. The failure is a reading error in this case caused by
maksim.sisov167c3c02016-06-23 07:31:521098 // UploadDataStream::Read().
Ryan Hamilton0239aac2018-05-19 00:03:131099 spdy::SpdySerializedFrame rst_frame(
1100 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_INTERNAL_ERROR));
maksim.sisov167c3c02016-06-23 07:31:521101
1102 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411103 CreateMockWrite(req, 0), // Request
1104 CreateMockWrite(rst_frame, 1) // Reset frame
maksim.sisov167c3c02016-06-23 07:31:521105 };
1106
Ryan Hamilton0239aac2018-05-19 00:03:131107 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
maksim.sisov167c3c02016-06-23 07:31:521108
1109 MockRead reads[] = {
1110 MockRead(ASYNC, 0, 2),
1111 };
1112
Ryan Sleevib8d7ea02018-05-07 20:01:011113 InitSession(reads, writes);
maksim.sisov167c3c02016-06-23 07:31:521114
1115 ReadErrorUploadDataStream upload_data_stream(
1116 ReadErrorUploadDataStream::FailureMode::ASYNC);
maksim.sisov819ba852016-08-17 08:22:521117 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
tfarina42834112016-09-22 13:38:201118 NetLogWithSource()),
robpercival214763f2016-07-01 23:27:011119 IsOk());
maksim.sisov167c3c02016-06-23 07:31:521120
1121 HttpRequestInfo request;
1122 request.method = "POST";
bnca2fbdc9b2016-11-22 21:14:261123 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:351124 request.traffic_annotation =
1125 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov167c3c02016-06-23 07:31:521126 request.upload_data_stream = &upload_data_stream;
1127
1128 TestCompletionCallback callback;
1129 HttpResponseInfo response;
1130 HttpRequestHeaders headers;
tfarina42834112016-09-22 13:38:201131 NetLogWithSource net_log;
Cammie Smith Barnes5191037b72021-03-01 22:06:531132 SpdyHttpStream http_stream(session_, kNoPushedStreamFound, net_log.source(),
1133 {} /* dns_aliases */);
Ali Beyada0b1a1c2022-04-08 20:08:141134 http_stream.RegisterRequest(&request);
1135 ASSERT_THAT(http_stream.InitializeStream(false, DEFAULT_PRIORITY, net_log,
1136 CompletionOnceCallback()),
bnca2fbdc9b2016-11-22 21:14:261137 IsOk());
maksim.sisov167c3c02016-06-23 07:31:521138
1139 int result = http_stream.SendRequest(headers, &response, callback.callback());
robpercival214763f2016-07-01 23:27:011140 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
1141 EXPECT_THAT(callback.GetResult(result), IsError(ERR_FAILED));
maksim.sisov167c3c02016-06-23 07:31:521142
bnceb9aa7112017-01-05 01:03:461143 // Run posted SpdyHttpStream::ResetStreamInternal() task.
1144 base::RunLoop().RunUntilIdle();
1145
maksim.sisov167c3c02016-06-23 07:31:521146 // Because the server has closed the connection, there shouldn't be a session
1147 // in the pool anymore.
bnc3d9035b32016-06-30 18:18:481148 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
maksim.sisov167c3c02016-06-23 07:31:521149}
1150
bncaa171332016-07-20 14:47:361151// Regression test for https://crbug.com/622447.
bncd16676a2016-07-20 16:23:011152TEST_F(SpdyHttpStreamTest, RequestCallbackCancelsStream) {
Ryan Hamilton0239aac2018-05-19 00:03:131153 spdy::SpdySerializedFrame req(
1154 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
1155 spdy::SpdySerializedFrame chunk(
1156 spdy_util_.ConstructSpdyDataFrame(1, "", true));
1157 spdy::SpdySerializedFrame rst(
1158 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
bncaa171332016-07-20 14:47:361159 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(chunk, 1),
1160 CreateMockWrite(rst, 2)};
1161 MockRead reads[] = {MockRead(ASYNC, 0, 3)};
Ryan Sleevib8d7ea02018-05-07 20:01:011162 InitSession(reads, writes);
bncaa171332016-07-20 14:47:361163
1164 HttpRequestInfo request;
1165 request.method = "POST";
bnca2fbdc9b2016-11-22 21:14:261166 request.url = url_;
Ramin Halavati216426e2018-03-12 22:13:351167 request.traffic_annotation =
1168 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncaa171332016-07-20 14:47:361169 ChunkedUploadDataStream upload_stream(0);
1170 request.upload_data_stream = &upload_stream;
1171
1172 TestCompletionCallback upload_callback;
tfarina42834112016-09-22 13:38:201173 ASSERT_THAT(
1174 upload_stream.Init(upload_callback.callback(), NetLogWithSource()),
1175 IsOk());
bncaa171332016-07-20 14:47:361176 upload_stream.AppendData("", 0, true);
1177
tfarina42834112016-09-22 13:38:201178 NetLogWithSource net_log;
Cammie Smith Barnes5191037b72021-03-01 22:06:531179 SpdyHttpStream http_stream(session_, kNoPushedStreamFound, net_log.source(),
1180 {} /* dns_aliases */);
Ali Beyada0b1a1c2022-04-08 20:08:141181 http_stream.RegisterRequest(&request);
1182 ASSERT_THAT(http_stream.InitializeStream(false, DEFAULT_PRIORITY, net_log,
1183 CompletionOnceCallback()),
bncaa171332016-07-20 14:47:361184 IsOk());
1185
1186 CancelStreamCallback callback(&http_stream);
1187 HttpRequestHeaders headers;
1188 HttpResponseInfo response;
1189 // This will attempt to Write() the initial request and headers, which will
1190 // complete asynchronously.
bnca2fbdc9b2016-11-22 21:14:261191 EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
1192 IsError(ERR_IO_PENDING));
bncaa171332016-07-20 14:47:361193 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
1194
1195 // The callback cancels |http_stream|.
1196 EXPECT_THAT(callback.WaitForResult(), IsOk());
1197
bnceb9aa7112017-01-05 01:03:461198 // Finish async network reads/writes.
1199 base::RunLoop().RunUntilIdle();
1200
bncaa171332016-07-20 14:47:361201 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
1202}
1203
Bence Békya6765a072020-07-06 20:03:341204// Regression test for https://crbug.com/1082683.
1205// SendRequest() callback should be called as soon as sending is done,
1206// even when sending greased frame type is allowed.
Bence Békycb4be9e2020-07-09 11:18:141207TEST_F(SpdyHttpStreamTest, DownloadWithEmptyDataFrame) {
1208 session_deps_.http2_end_stream_with_data_frame = true;
Bence Békya6765a072020-07-06 20:03:341209
Bence Békycb4be9e2020-07-09 11:18:141210 // HEADERS frame without END_STREAM
Bence Béky4c325e52020-10-22 20:48:011211 spdy::Http2HeaderBlock request_headers;
Bence Békya6765a072020-07-06 20:03:341212 request_headers[spdy::kHttp2MethodHeader] = "GET";
1213 spdy_util_.AddUrlToHeaderBlock(kDefaultUrl, &request_headers);
1214 spdy::SpdySerializedFrame req = spdy_util_.ConstructSpdyHeaders(
1215 1, std::move(request_headers), LOWEST, /* fin = */ false);
1216
Bence Békycb4be9e2020-07-09 11:18:141217 // Empty DATA frame with END_STREAM
Bence Békya6765a072020-07-06 20:03:341218 spdy::SpdySerializedFrame empty_body(
Bence Békycb4be9e2020-07-09 11:18:141219 spdy_util_.ConstructSpdyDataFrame(1, "", /* fin = */ true));
Bence Békya6765a072020-07-06 20:03:341220
Bence Békycb4be9e2020-07-09 11:18:141221 MockWrite writes[] = {CreateMockWrite(req, 0),
1222 CreateMockWrite(empty_body, 1)};
Bence Békya6765a072020-07-06 20:03:341223
1224 // This test only concerns the request,
1225 // no need to construct a meaningful response.
1226 MockRead reads[] = {
Bence Békycb4be9e2020-07-09 11:18:141227 MockRead(ASYNC, ERR_IO_PENDING, 2), // Pause reads.
1228 MockRead(ASYNC, 0, 3) // Close connection.
Bence Békya6765a072020-07-06 20:03:341229 };
1230
1231 InitSession(reads, writes);
1232
1233 HttpRequestInfo request;
1234 request.method = "GET";
1235 request.url = url_;
1236 request.traffic_annotation =
1237 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1238 TestCompletionCallback callback;
1239 HttpResponseInfo response;
1240 HttpRequestHeaders headers;
1241 NetLogWithSource net_log;
1242 auto http_stream = std::make_unique<SpdyHttpStream>(
Cammie Smith Barnes5191037b72021-03-01 22:06:531243 session_, kNoPushedStreamFound, net_log.source(),
Eric Orthac661912022-01-10 21:44:171244 /*dns_aliases=*/std::set<std::string>());
Bence Békya6765a072020-07-06 20:03:341245
Ali Beyada0b1a1c2022-04-08 20:08:141246 http_stream->RegisterRequest(&request);
1247 int rv = http_stream->InitializeStream(true, DEFAULT_PRIORITY, net_log,
1248 CompletionOnceCallback());
Bence Békya6765a072020-07-06 20:03:341249 EXPECT_THAT(rv, IsOk());
1250
1251 rv = http_stream->SendRequest(headers, &response, callback.callback());
1252 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1253
1254 // The request callback should be called even though response has not been
1255 // received yet.
1256 rv = callback.WaitForResult();
1257 EXPECT_THAT(rv, IsOk());
1258
1259 sequenced_data_->Resume();
1260 base::RunLoop().RunUntilIdle();
1261}
1262
[email protected]955fc2e72010-02-08 20:37:301263// TODO(willchan): Write a longer test for SpdyStream that exercises all
[email protected]a677f2b2009-11-22 00:43:001264// methods.
1265
Tsuyoshi Horo4f516be2022-06-14 11:53:131266} // namespace net::test