blob: b4e560368f6d535c15b3cb44e596e648140a06d3 [file] [log] [blame]
[email protected]a1595312012-01-22 03:25:041// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]5af3c572010-07-20 14:16:272// Use of this source code is governed by a BSD-style license that can be
[email protected]aea80602009-09-18 00:55:083// found in the LICENSE file.
4
xunjieli179a6e72016-04-26 19:47:455#include <cmath>
dchengc7eeda422015-12-26 03:56:486#include <utility>
[email protected]a33cad2b62010-07-30 22:24:397#include <vector>
8
[email protected]49639fa2011-12-20 23:22:419#include "base/bind.h"
10#include "base/bind_helpers.h"
Bence Békydb3cf652017-10-10 15:22:1011#include "base/compiler_specific.h"
thestigd8df0332014-09-04 06:33:2912#include "base/files/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2313#include "base/files/scoped_temp_dir.h"
[email protected]fc9d88472013-08-14 02:31:1714#include "base/run_loop.h"
Avi Drissman4365a4782018-12-28 19:26:2415#include "base/stl_util.h"
Bence Békyd74f4382018-02-20 18:26:1916#include "base/strings/string_piece.h"
Devlin Cronine4bcb40e2018-06-05 18:02:4717#include "base/test/metrics/histogram_tester.h"
[email protected]999dd8c2013-11-12 06:45:5418#include "base/test/test_file_util.h"
gabf767595f2016-05-11 18:50:3519#include "base/threading/thread_task_runner_handle.h"
[email protected]018aabc2010-10-29 16:16:5920#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0721#include "net/base/chunked_upload_data_stream.h"
Bence Béky8ddc2492018-06-13 01:02:0422#include "net/base/completion_once_callback.h"
mmenkecbc2b712014-10-09 20:29:0723#include "net/base/elements_upload_data_stream.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3724#include "net/base/ip_endpoint.h"
tbansal28e68f82016-02-04 02:56:1525#include "net/base/proxy_delegate.h"
Lily Houghton582d4622018-01-22 22:43:4026#include "net/base/proxy_server.h"
[email protected]262eec82013-03-19 21:01:3627#include "net/base/request_priority.h"
tbansal28e68f82016-02-04 02:56:1528#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0629#include "net/base/upload_bytes_element_reader.h"
[email protected]b2d26cfd2012-12-11 10:36:0630#include "net/base/upload_file_element_reader.h"
Bence Béky1a5d8562018-01-05 17:29:2831#include "net/dns/mock_host_resolver.h"
aberentbba302d2015-12-03 10:20:1932#include "net/http/http_auth_scheme.h"
bnc3171a2432016-12-28 18:40:2633#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5634#include "net/http/http_network_session_peer.h"
[email protected]513963e2013-06-15 01:53:0435#include "net/http/http_network_transaction.h"
Matt Menke6e879bd2019-03-18 17:26:0436#include "net/http/http_proxy_connect_job.h"
Bence Béky3a0c48532018-03-02 13:38:5137#include "net/http/http_response_info.h"
[email protected]513963e2013-06-15 01:53:0438#include "net/http/http_server_properties.h"
[email protected]c41737d2014-05-14 07:47:1939#include "net/http/http_transaction_test_util.h"
mikecirone8b85c432016-09-08 19:11:0040#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1941#include "net/log/net_log_with_source.h"
mmenke16a7cbdd2015-04-24 23:00:5642#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4643#include "net/log/test_net_log_entry.h"
44#include "net/log/test_net_log_util.h"
[email protected]bb88e1d32013-05-03 23:11:0745#include "net/socket/next_proto.h"
Paul Jensena457017a2018-01-19 23:52:0446#include "net/socket/socket_tag.h"
Bence Béky94658bf2018-05-11 19:22:5847#include "net/spdy/buffered_spdy_framer.h"
48#include "net/spdy/spdy_http_stream.h"
49#include "net/spdy/spdy_http_utils.h"
50#include "net/spdy/spdy_session.h"
51#include "net/spdy/spdy_session_pool.h"
52#include "net/spdy/spdy_test_util_common.h"
[email protected]514aeaf2014-05-23 10:31:5153#include "net/ssl/ssl_connection_status_flags.h"
bncce36dca22015-04-21 22:11:2354#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0155#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4356#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:0157#include "net/test/test_with_scoped_task_environment.h"
Victor Vasiliev27cc7712019-01-24 11:50:1458#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
59#include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
rhalavati9ebaba7e2017-04-27 06:16:2960#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
[email protected]d2db0292011-01-26 20:23:4461#include "net/url_request/url_request_test_util.h"
Bence Béky0ca719f2018-01-31 13:41:1962#include "net/websockets/websocket_test_util.h"
[email protected]251029e2014-03-19 06:04:4063#include "testing/gmock/include/gmock/gmock.h"
[email protected]aea80602009-09-18 00:55:0864#include "testing/platform_test.h"
65
robpercival214763f2016-07-01 23:27:0166using net::test::IsError;
67using net::test::IsOk;
68
[email protected]aea80602009-09-18 00:55:0869//-----------------------------------------------------------------------------
70
[email protected]d1eda932009-11-04 01:03:1071namespace net {
[email protected]dae22c52010-07-30 02:16:3572
[email protected]cbdd73162013-03-18 23:27:3373namespace {
[email protected]251029e2014-03-19 06:04:4074
75using testing::Each;
76using testing::Eq;
77
xunjieli179a6e72016-04-26 19:47:4578const int32_t kBufferSize = SpdyHttpStream::kRequestBodyBufferSize;
79
[email protected]513963e2013-06-15 01:53:0480} // namespace
81
Bence Békyd2df6c1c82018-04-20 22:52:0182const char kPushedUrl[] = "https://www.example.org/foo.dat";
83
Bence Béky98447b12018-05-08 03:14:0184class SpdyNetworkTransactionTest : public TestWithScopedTaskEnvironment {
[email protected]34437af82009-11-06 02:28:4985 protected:
rdsmithebb50aa2015-11-12 03:44:3886 SpdyNetworkTransactionTest()
bncb26024382016-06-29 02:39:4587 : default_url_(kDefaultUrl),
bncd16676a2016-07-20 16:23:0188 host_port_pair_(HostPortPair::FromURL(default_url_)) {}
[email protected]2d6728692011-03-12 01:39:5589
bncd16676a2016-07-20 16:23:0190 ~SpdyNetworkTransactionTest() override {
Bence Békydb3cf652017-10-10 15:22:1091 // UploadDataStream may post a deletion task back to the message loop on
[email protected]fc9d88472013-08-14 02:31:1792 // destruction.
93 upload_data_stream_.reset();
94 base::RunLoop().RunUntilIdle();
95 }
96
dcheng67be2b1f2014-10-27 21:47:2997 void SetUp() override {
Bence Békydb3cf652017-10-10 15:22:1098 request_.method = "GET";
99 request_.url = GURL(kDefaultUrl);
Ramin Halavatib5e433e62018-02-07 07:41:10100 request_.traffic_annotation =
101 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]69e6b4a2012-10-18 08:03:01102 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]aea80602009-09-18 00:55:08103 }
104
[email protected]72552f02009-10-28 15:25:01105 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:08106 int rv;
Bence Béky4e83f492018-05-13 23:14:25107 std::string status_line;
108 std::string response_data;
[email protected]8b070372009-11-16 22:01:25109 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:08110 };
111
[email protected]3caf5542010-07-16 15:19:47112 // A helper class that handles all the initial npn/ssl setup.
113 class NormalSpdyTransactionHelper {
114 public:
rdsmith82957ad2015-09-16 19:42:03115 NormalSpdyTransactionHelper(
116 const HttpRequestInfo& request,
117 RequestPriority priority,
tfarina428341112016-09-22 13:38:20118 const NetLogWithSource& log,
danakjaee3e1ec2016-04-16 00:23:18119 std::unique_ptr<SpdySessionDependencies> session_deps)
[email protected]30c942b2010-07-21 16:59:59120 : request_(request),
[email protected]262eec82013-03-19 21:01:36121 priority_(priority),
tombergan5d22c182017-01-11 02:05:35122 session_deps_(session_deps.get() == nullptr
Jeremy Roman0579ed62017-08-29 15:56:19123 ? std::make_unique<SpdySessionDependencies>()
bncd16676a2016-07-20 16:23:01124 : std::move(session_deps)),
xunjieli925519532017-01-30 15:33:17125 log_(log) {
126 session_deps_->net_log = log.net_log();
127 session_ =
128 SpdySessionDependencies::SpdyCreateSession(session_deps_.get());
129 }
[email protected]61b4efc2012-04-27 18:12:50130
[email protected]19ec8a72010-08-23 03:38:23131 ~NormalSpdyTransactionHelper() {
132 // Any test which doesn't close the socket by sending it an EOF will
133 // have a valid session left open, which leaks the entire session pool.
134 // This is just fine - in fact, some of our tests intentionally do this
135 // so that we can check consistency of the SpdySessionPool as the test
136 // finishes. If we had put an EOF on the socket, the SpdySession would
137 // have closed and we wouldn't be able to check the consistency.
138
139 // Forcefully close existing sessions here.
140 session()->spdy_session_pool()->CloseAllSessions();
141 }
142
[email protected]3caf5542010-07-16 15:19:47143 void RunPreTestSetup() {
[email protected]3caf5542010-07-16 15:19:47144 // We're now ready to use SSL-npn SPDY.
bnc3f6a8552017-05-17 13:40:34145 trans_ =
Jeremy Roman0579ed62017-08-29 15:56:19146 std::make_unique<HttpNetworkTransaction>(priority_, session_.get());
[email protected]cb54b3b22010-06-03 16:28:55147 }
[email protected]aea80602009-09-18 00:55:08148
[email protected]3caf5542010-07-16 15:19:47149 // Start the transaction, read some data, finish.
150 void RunDefaultTest() {
[email protected]34b345f92013-02-22 03:27:26151 if (!StartDefaultTest())
152 return;
153 FinishDefaultTest();
154 }
155
156 bool StartDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51157 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
[email protected]aea80602009-09-18 00:55:08158
[email protected]3caf5542010-07-16 15:19:47159 // We expect an IO Pending or some sort of error.
160 EXPECT_LT(output_.rv, 0);
[email protected]34b345f92013-02-22 03:27:26161 return output_.rv == ERR_IO_PENDING;
162 }
[email protected]aea80602009-09-18 00:55:08163
[email protected]34b345f92013-02-22 03:27:26164 void FinishDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51165 output_.rv = callback_.WaitForResult();
bnceb9aa7112017-01-05 01:03:46166 // Finish async network reads/writes.
167 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:47168 if (output_.rv != OK) {
bnc301745a2015-03-10 03:22:16169 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
[email protected]3caf5542010-07-16 15:19:47170 return;
171 }
[email protected]ff57bb82009-11-12 06:52:14172
[email protected]3caf5542010-07-16 15:19:47173 // Verify responses.
174 const HttpResponseInfo* response = trans_->GetResponseInfo();
wezca1070932016-05-26 20:30:52175 ASSERT_TRUE(response);
176 ASSERT_TRUE(response->headers);
bnc80bb1d42016-10-26 18:11:34177 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
bnc927c4962016-07-21 14:45:59178 response->connection_info);
179 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
180 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:52181 EXPECT_TRUE(response->was_alpn_negotiated);
Tsuyoshi Horo01faed62019-02-20 22:11:37182 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
183 EXPECT_EQ(443, response->remote_endpoint.port());
[email protected]3caf5542010-07-16 15:19:47184 output_.status_line = response->headers->GetStatusLine();
185 output_.response_info = *response; // Make a copy so we can verify.
186 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
[email protected]3caf5542010-07-16 15:19:47187 }
188
bncfacdd852015-01-09 19:22:54189 void FinishDefaultTestWithoutVerification() {
190 output_.rv = callback_.WaitForResult();
bnceb9aa7112017-01-05 01:03:46191 // Finish async network reads/writes.
192 base::RunLoop().RunUntilIdle();
bncfacdd852015-01-09 19:22:54193 if (output_.rv != OK)
bnc301745a2015-03-10 03:22:16194 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
bncfacdd852015-01-09 19:22:54195 }
196
maksim.sisov8d2df66d2016-06-20 07:07:11197 void WaitForCallbackToComplete() { output_.rv = callback_.WaitForResult(); }
mmenke666a6fea2015-12-19 04:16:33198
[email protected]3caf5542010-07-16 15:19:47199 // Most tests will want to call this function. In particular, the MockReads
200 // should end with an empty read, and that read needs to be processed to
201 // ensure proper deletion of the spdy_session_pool.
202 void VerifyDataConsumed() {
rch08e3aa3e2015-05-16 14:27:52203 for (const SocketDataProvider* provider : data_vector_) {
204 EXPECT_TRUE(provider->AllReadDataConsumed());
205 EXPECT_TRUE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47206 }
207 }
208
209 // Occasionally a test will expect to error out before certain reads are
210 // processed. In that case we want to explicitly ensure that the reads were
211 // not processed.
212 void VerifyDataNotConsumed() {
rch08e3aa3e2015-05-16 14:27:52213 for (const SocketDataProvider* provider : data_vector_) {
214 EXPECT_FALSE(provider->AllReadDataConsumed());
215 EXPECT_FALSE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47216 }
217 }
218
rch08e3aa3e2015-05-16 14:27:52219 void RunToCompletion(SocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47220 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58221 AddData(data);
[email protected]3caf5542010-07-16 15:19:47222 RunDefaultTest();
223 VerifyDataConsumed();
224 }
[email protected]e6b06862010-07-20 16:32:58225
[email protected]514aeaf2014-05-23 10:31:51226 void RunToCompletionWithSSLData(
rch08e3aa3e2015-05-16 14:27:52227 SocketDataProvider* data,
danakjaee3e1ec2016-04-16 00:23:18228 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]514aeaf2014-05-23 10:31:51229 RunPreTestSetup();
dchengc7eeda422015-12-26 03:56:48230 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:51231 RunDefaultTest();
232 VerifyDataConsumed();
233 }
234
rch08e3aa3e2015-05-16 14:27:52235 void AddData(SocketDataProvider* data) {
Jeremy Roman0579ed62017-08-29 15:56:19236 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:49237 ssl_provider->ssl_info.cert =
bncce36dca22015-04-21 22:11:23238 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
dchengc7eeda422015-12-26 03:56:48239 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:51240 }
241
242 void AddDataWithSSLSocketDataProvider(
rch08e3aa3e2015-05-16 14:27:52243 SocketDataProvider* data,
danakjaee3e1ec2016-04-16 00:23:18244 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]3caf5542010-07-16 15:19:47245 data_vector_.push_back(data);
bnc3cf2a592016-08-11 14:48:36246 if (ssl_provider->next_proto == kProtoUnknown)
247 ssl_provider->next_proto = kProtoHTTP2;
rchebf12982015-04-10 01:15:00248
249 session_deps_->socket_factory->AddSSLSocketDataProvider(
250 ssl_provider.get());
olli.raulaae011c422015-12-10 07:38:51251 ssl_vector_.push_back(std::move(ssl_provider));
[email protected]d4f00222012-07-10 06:24:51252
[email protected]3b7828432010-08-18 18:33:27253 session_deps_->socket_factory->AddSocketDataProvider(data);
254 }
255
[email protected]3caf5542010-07-16 15:19:47256 HttpNetworkTransaction* trans() { return trans_.get(); }
257 void ResetTrans() { trans_.reset(); }
bnc4d782f492016-08-18 13:50:00258 const TransactionHelperResult& output() { return output_; }
mmenkee65e7af2015-10-13 17:16:42259 HttpNetworkSession* session() const { return session_.get(); }
bncd16676a2016-07-20 16:23:01260 SpdySessionDependencies* session_deps() { return session_deps_.get(); }
[email protected]3caf5542010-07-16 15:19:47261
262 private:
rch08e3aa3e2015-05-16 14:27:52263 typedef std::vector<SocketDataProvider*> DataVector;
danakjaee3e1ec2016-04-16 00:23:18264 typedef std::vector<std::unique_ptr<SSLSocketDataProvider>> SSLVector;
265 typedef std::vector<std::unique_ptr<SocketDataProvider>> AlternateVector;
Bence Békydb3cf652017-10-10 15:22:10266 const HttpRequestInfo request_;
267 const RequestPriority priority_;
danakjaee3e1ec2016-04-16 00:23:18268 std::unique_ptr<SpdySessionDependencies> session_deps_;
269 std::unique_ptr<HttpNetworkSession> session_;
[email protected]3caf5542010-07-16 15:19:47270 TransactionHelperResult output_;
[email protected]3caf5542010-07-16 15:19:47271 SSLVector ssl_vector_;
[email protected]514aeaf2014-05-23 10:31:51272 TestCompletionCallback callback_;
danakjaee3e1ec2016-04-16 00:23:18273 std::unique_ptr<HttpNetworkTransaction> trans_;
[email protected]3caf5542010-07-16 15:19:47274 DataVector data_vector_;
tfarina428341112016-09-22 13:38:20275 const NetLogWithSource log_;
[email protected]3caf5542010-07-16 15:19:47276 };
[email protected]aea80602009-09-18 00:55:08277
278 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
279 int expected_status);
280
281 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18282
Bence Békydb3cf652017-10-10 15:22:10283 HttpRequestInfo CreateGetPushRequest() const WARN_UNUSED_RESULT {
284 HttpRequestInfo request;
285 request.method = "GET";
Bence Békyd2df6c1c82018-04-20 22:52:01286 request.url = GURL(kPushedUrl);
Ramin Halavatib5e433e62018-02-07 07:41:10287 request.traffic_annotation =
288 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydb3cf652017-10-10 15:22:10289 return request;
[email protected]e3ebba0f2010-08-05 17:59:58290 }
291
Bence Békydb3cf652017-10-10 15:22:10292 void UsePostRequest() {
293 ASSERT_FALSE(upload_data_stream_);
294 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
295 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
296 kUploadData, kUploadDataSize));
297 upload_data_stream_ = std::make_unique<ElementsUploadDataStream>(
298 std::move(element_readers), 0);
299
300 request_.method = "POST";
301 request_.upload_data_stream = upload_data_stream_.get();
[email protected]d3cee19d2010-06-22 18:42:18302 }
303
Bence Békydb3cf652017-10-10 15:22:10304 void UseFilePostRequest() {
305 ASSERT_FALSE(upload_data_stream_);
306 base::FilePath file_path;
307 CHECK(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
308 CHECK_EQ(static_cast<int>(kUploadDataSize),
309 base::WriteFile(file_path, kUploadData, kUploadDataSize));
310
311 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
312 element_readers.push_back(std::make_unique<UploadFileElementReader>(
313 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
314 kUploadDataSize, base::Time()));
315 upload_data_stream_ = std::make_unique<ElementsUploadDataStream>(
316 std::move(element_readers), 0);
317
318 request_.method = "POST";
319 request_.upload_data_stream = upload_data_stream_.get();
Ramin Halavatib5e433e62018-02-07 07:41:10320 request_.traffic_annotation =
321 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3deb9a52010-11-11 00:24:40322 }
323
Bence Békydb3cf652017-10-10 15:22:10324 void UseUnreadableFilePostRequest() {
325 ASSERT_FALSE(upload_data_stream_);
[email protected]999dd8c2013-11-12 06:45:54326 base::FilePath file_path;
vabrb8582322016-09-09 08:05:37327 CHECK(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
[email protected]999dd8c2013-11-12 06:45:54328 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30329 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]92be8eb2014-08-07 22:57:11330 CHECK(base::MakeFileUnreadable(file_path));
[email protected]999dd8c2013-11-12 06:45:54331
danakjaee3e1ec2016-04-16 00:23:18332 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:19333 element_readers.push_back(std::make_unique<UploadFileElementReader>(
skyostil4891b25b2015-06-11 11:43:45334 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
ricea2deef682016-09-09 08:04:07335 kUploadDataSize, base::Time()));
Jeremy Roman0579ed62017-08-29 15:56:19336 upload_data_stream_ = std::make_unique<ElementsUploadDataStream>(
bnc3f6a8552017-05-17 13:40:34337 std::move(element_readers), 0);
[email protected]999dd8c2013-11-12 06:45:54338
Bence Békydb3cf652017-10-10 15:22:10339 request_.method = "POST";
340 request_.upload_data_stream = upload_data_stream_.get();
[email protected]999dd8c2013-11-12 06:45:54341 }
342
Bence Békydb3cf652017-10-10 15:22:10343 void UseComplexPostRequest() {
344 ASSERT_FALSE(upload_data_stream_);
345 const int kFileRangeOffset = 1;
346 const int kFileRangeLength = 3;
347 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
[email protected]69e6b4a2012-10-18 08:03:01348
Bence Békydb3cf652017-10-10 15:22:10349 base::FilePath file_path;
350 CHECK(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
351 CHECK_EQ(static_cast<int>(kUploadDataSize),
352 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01353
Bence Békydb3cf652017-10-10 15:22:10354 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
355 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
356 kUploadData, kFileRangeOffset));
357 element_readers.push_back(std::make_unique<UploadFileElementReader>(
358 base::ThreadTaskRunnerHandle::Get().get(), file_path, kFileRangeOffset,
359 kFileRangeLength, base::Time()));
360 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
361 kUploadData + kFileRangeOffset + kFileRangeLength,
362 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
363 upload_data_stream_ = std::make_unique<ElementsUploadDataStream>(
364 std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:27365
Bence Békydb3cf652017-10-10 15:22:10366 request_.method = "POST";
367 request_.upload_data_stream = upload_data_stream_.get();
[email protected]69e6b4a2012-10-18 08:03:01368 }
369
Bence Békydb3cf652017-10-10 15:22:10370 void UseChunkedPostRequest() {
371 ASSERT_FALSE(upload_chunked_data_stream_);
372 upload_chunked_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
373 request_.method = "POST";
374 request_.upload_data_stream = upload_chunked_data_stream_.get();
[email protected]0c9bf872011-03-04 17:53:22375 }
376
[email protected]19ec8a72010-08-23 03:38:23377 // Read the result of a particular transaction, knowing that we've got
378 // multiple transactions in the read pipeline; so as we read, we may have
379 // to skip over data destined for other transactions while we consume
380 // the data for |trans|.
Bence Béky4e83f492018-05-13 23:14:25381 int ReadResult(HttpNetworkTransaction* trans, std::string* result) {
[email protected]19ec8a72010-08-23 03:38:23382 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58383
[email protected]19ec8a72010-08-23 03:38:23384 int bytes_read = 0;
Victor Costan9c7302b2018-08-27 16:39:44385 scoped_refptr<IOBufferWithSize> buf =
386 base::MakeRefCounted<IOBufferWithSize>(kSize);
[email protected]49639fa2011-12-20 23:22:41387 TestCompletionCallback callback;
[email protected]19ec8a72010-08-23 03:38:23388 while (true) {
[email protected]90499482013-06-01 00:39:50389 int rv = trans->Read(buf.get(), kSize, callback.callback());
[email protected]19ec8a72010-08-23 03:38:23390 if (rv == ERR_IO_PENDING) {
[email protected]19ec8a72010-08-23 03:38:23391 rv = callback.WaitForResult();
392 } else if (rv <= 0) {
393 break;
394 }
395 result->append(buf->data(), rv);
396 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58397 }
[email protected]19ec8a72010-08-23 03:38:23398 return bytes_read;
399 }
[email protected]e3ebba0f2010-08-05 17:59:58400
[email protected]19ec8a72010-08-23 03:38:23401 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
402 // This lengthy block is reaching into the pool to dig out the active
403 // session. Once we have the session, we verify that the streams are
404 // all closed and not leaked at this point.
Bence Békydb3cf652017-10-10 15:22:10405 SpdySessionKey key(HostPortPair::FromURL(request_.url),
Paul Jensena457017a2018-01-19 23:52:04406 ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
Matt Menke2436b2f2018-12-11 18:07:11407 SpdySessionKey::IsProxySession::kFalse, SocketTag());
mmenkee65e7af2015-10-13 17:16:42408 HttpNetworkSession* session = helper.session();
[email protected]795cbf82013-07-22 09:37:27409 base::WeakPtr<SpdySession> spdy_session =
bnc9ead3ae2017-03-16 00:48:15410 session->spdy_session_pool()->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:31411 key, /* enable_ip_based_pooling = */ true,
412 /* is_websocket = */ false, log_);
wezca1070932016-05-26 20:30:52413 ASSERT_TRUE(spdy_session);
Bence Béky285e7d42017-12-04 20:22:11414 EXPECT_EQ(0u, num_active_streams(spdy_session));
415 EXPECT_EQ(0u, num_unclaimed_pushed_streams(spdy_session));
[email protected]19ec8a72010-08-23 03:38:23416 }
[email protected]e3ebba0f2010-08-05 17:59:58417
rch08e3aa3e2015-05-16 14:27:52418 void RunServerPushTest(SequencedSocketData* data,
[email protected]e3ebba0f2010-08-05 17:59:58419 HttpResponseInfo* response,
[email protected]a7a265ef2010-12-08 18:05:57420 HttpResponseInfo* push_response,
Bence Béky4e83f492018-05-13 23:14:25421 const std::string& expected) {
Bence Békydb3cf652017-10-10 15:22:10422 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
423 nullptr);
[email protected]e3ebba0f2010-08-05 17:59:58424 helper.RunPreTestSetup();
[email protected]d08358502010-12-03 22:04:03425 helper.AddData(data);
[email protected]e3ebba0f2010-08-05 17:59:58426
427 HttpNetworkTransaction* trans = helper.trans();
428
429 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:41430 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:10431 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:01432 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:58433 rv = callback.WaitForResult();
434
bnceb9aa7112017-01-05 01:03:46435 // Finish async network reads/writes.
436 base::RunLoop().RunUntilIdle();
437
[email protected]e3ebba0f2010-08-05 17:59:58438 // Request the pushed path.
bnc691fda62016-08-12 00:43:16439 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
Bence Békydb3cf652017-10-10 15:22:10440 HttpRequestInfo request = CreateGetPushRequest();
441 rv = trans2.Start(&request, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:01442 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:17443 base::RunLoop().RunUntilIdle();
[email protected]e3ebba0f2010-08-05 17:59:58444
[email protected]513963e2013-06-15 01:53:04445 // The data for the pushed path may be coming in more than 1 frame. Compile
[email protected]e3ebba0f2010-08-05 17:59:58446 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23447
448 // Read the server push body.
Bence Béky4e83f492018-05-13 23:14:25449 std::string result2;
bnc691fda62016-08-12 00:43:16450 ReadResult(&trans2, &result2);
[email protected]19ec8a72010-08-23 03:38:23451 // Read the response body.
Bence Béky4e83f492018-05-13 23:14:25452 std::string result;
rch0aecfd82015-05-19 17:22:32453 ReadResult(trans, &result);
[email protected]e3ebba0f2010-08-05 17:59:58454
455 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:17456 EXPECT_TRUE(data->AllReadDataConsumed());
457 EXPECT_TRUE(data->AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:58458
caseqe8340bc92016-04-20 00:02:57459 LoadTimingInfo load_timing_info;
460 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
461 EXPECT_TRUE(load_timing_info.push_start.is_null());
462 EXPECT_TRUE(load_timing_info.push_end.is_null());
463
464 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:16465 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
caseqe8340bc92016-04-20 00:02:57466 EXPECT_FALSE(load_timing_info2.push_start.is_null());
467 EXPECT_FALSE(load_timing_info2.push_end.is_null());
468
[email protected]e3ebba0f2010-08-05 17:59:58469 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23470 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
471 << result2
472 << "||||| Expected data: "
473 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58474
bnc42331402016-07-25 13:36:15475 // Verify the response HEADERS.
[email protected]e3ebba0f2010-08-05 17:59:58476 // Copy the response info, because trans goes away.
477 *response = *trans->GetResponseInfo();
bnc691fda62016-08-12 00:43:16478 *push_response = *trans2.GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23479
480 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58481 }
482
morlovichab1d1c1e2017-02-07 19:59:28483 void RunBrokenPushTest(SequencedSocketData* data, int expected_rv) {
Bence Békydb3cf652017-10-10 15:22:10484 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
485 nullptr);
morlovichab1d1c1e2017-02-07 19:59:28486 helper.RunPreTestSetup();
487 helper.AddData(data);
488
489 HttpNetworkTransaction* trans = helper.trans();
490
491 // Start the transaction with basic parameters.
492 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:10493 int rv = trans->Start(&request_, callback.callback(), log_);
morlovichab1d1c1e2017-02-07 19:59:28494 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
495 rv = callback.WaitForResult();
496 EXPECT_EQ(expected_rv, rv);
497
498 // Finish async network reads/writes.
499 base::RunLoop().RunUntilIdle();
500
501 // Verify that we consumed all test data.
502 EXPECT_TRUE(data->AllReadDataConsumed());
503 EXPECT_TRUE(data->AllWriteDataConsumed());
504
505 if (expected_rv == OK) {
506 // Expected main request to succeed, even if push failed.
507 HttpResponseInfo response = *trans->GetResponseInfo();
508 EXPECT_TRUE(response.headers);
509 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
510 }
511 }
512
[email protected]49639fa2011-12-20 23:22:41513 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
514 int result) {
515 helper->ResetTrans();
516 }
517
mmenkee65e7af2015-10-13 17:16:42518 static void StartTransactionCallback(HttpNetworkSession* session,
519 GURL url,
Bence Békyd3dde832017-09-19 19:02:31520 NetLogWithSource log,
mmenkee65e7af2015-10-13 17:16:42521 int result) {
krasin0bfeb6b2017-01-13 21:48:04522 HttpRequestInfo request;
bnc691fda62016-08-12 00:43:16523 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]49639fa2011-12-20 23:22:41524 TestCompletionCallback callback;
[email protected]49639fa2011-12-20 23:22:41525 request.method = "GET";
rchebf12982015-04-10 01:15:00526 request.url = url;
Ramin Halavatib5e433e62018-02-07 07:41:10527 request.traffic_annotation =
528 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békyd3dde832017-09-19 19:02:31529 int rv = trans.Start(&request, callback.callback(), log);
robpercival214763f2016-07-01 23:27:01530 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]49639fa2011-12-20 23:22:41531 callback.WaitForResult();
532 }
533
Bence Békydb3cf652017-10-10 15:22:10534 ChunkedUploadDataStream* upload_chunked_data_stream() {
mmenkecbc2b712014-10-09 20:29:07535 return upload_chunked_data_stream_.get();
536 }
537
Bence Béky285e7d42017-12-04 20:22:11538 size_t num_active_streams(base::WeakPtr<SpdySession> session) {
539 return session->active_streams_.size();
540 }
541
Bence Békyfd2c1fd2017-12-15 02:32:03542 static size_t num_unclaimed_pushed_streams(
543 base::WeakPtr<SpdySession> session) {
544 return session->pool_->push_promise_index()->CountStreamsForSession(
545 session.get());
Bence Béky285e7d42017-12-04 20:22:11546 }
547
Bence Békyfd2c1fd2017-12-15 02:32:03548 static bool has_unclaimed_pushed_stream_for_url(
549 base::WeakPtr<SpdySession> session,
550 const GURL& url) {
551 return session->pool_->push_promise_index()->FindStream(
552 url, session.get()) != kNoPushedStreamFound;
Bence Béky285e7d42017-12-04 20:22:11553 }
554
Ryan Hamilton0239aac2018-05-19 00:03:13555 static spdy::SpdyStreamId spdy_stream_hi_water_mark(
Yoav Weiss9693572f2018-01-04 09:37:34556 base::WeakPtr<SpdySession> session) {
557 return session->stream_hi_water_mark_;
558 }
559
bncb26024382016-06-29 02:39:45560 const GURL default_url_;
561 const HostPortPair host_port_pair_;
Bence Békydb3cf652017-10-10 15:22:10562 HttpRequestInfo request_;
[email protected]9ec54f82013-05-10 02:53:05563 SpdyTestUtil spdy_util_;
Bence Békyd3dde832017-09-19 19:02:31564 const NetLogWithSource log_;
[email protected]9ec54f82013-05-10 02:53:05565
[email protected]d3cee19d2010-06-22 18:42:18566 private:
danakjaee3e1ec2016-04-16 00:23:18567 std::unique_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
568 std::unique_ptr<UploadDataStream> upload_data_stream_;
[email protected]ea1a3f62012-11-16 20:34:23569 base::ScopedTempDir temp_dir_;
[email protected]aea80602009-09-18 00:55:08570};
571
[email protected]3caf5542010-07-16 15:19:47572// Verify HttpNetworkTransaction constructor.
bncd16676a2016-07-20 16:23:01573TEST_F(SpdyNetworkTransactionTest, Constructor) {
Jeremy Roman0579ed62017-08-29 15:56:19574 auto session_deps = std::make_unique<SpdySessionDependencies>();
danakjaee3e1ec2016-04-16 00:23:18575 std::unique_ptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:07576 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
bncd16676a2016-07-20 16:23:01577 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19578 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]aea80602009-09-18 00:55:08579}
580
bncd16676a2016-07-20 16:23:01581TEST_F(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38582 // Construct the request.
Ryan Hamilton0239aac2018-05-19 00:03:13583 spdy::SpdySerializedFrame req(
584 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:41585 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]72552f02009-10-28 15:25:01586
Ryan Hamilton0239aac2018-05-19 00:03:13587 spdy::SpdySerializedFrame resp(
588 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
589 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]72552f02009-10-28 15:25:01590 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41591 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:52592 MockRead(ASYNC, 0, 3) // EOF
[email protected]72552f02009-10-28 15:25:01593 };
594
Ryan Sleevib8d7ea02018-05-07 20:01:01595 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:10596 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:57597 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:47598 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:01599 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02600 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]72552f02009-10-28 15:25:01601 EXPECT_EQ("hello!", out.response_data);
602}
603
Bence Béky2fcf4fa2018-04-06 20:06:01604TEST_F(SpdyNetworkTransactionTest, SetPriority) {
605 for (bool set_priority_before_starting_transaction : {true, false}) {
606 SpdyTestUtil spdy_test_util;
Ryan Hamilton0239aac2018-05-19 00:03:13607 spdy::SpdySerializedFrame req(
Bence Béky2fcf4fa2018-04-06 20:06:01608 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
609 MockWrite writes[] = {CreateMockWrite(req, 0)};
610
Ryan Hamilton0239aac2018-05-19 00:03:13611 spdy::SpdySerializedFrame resp(
Bence Béky2fcf4fa2018-04-06 20:06:01612 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:13613 spdy::SpdySerializedFrame body(
614 spdy_test_util.ConstructSpdyDataFrame(1, true));
Bence Béky2fcf4fa2018-04-06 20:06:01615 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
616 MockRead(ASYNC, 0, 3)};
617
Ryan Sleevib8d7ea02018-05-07 20:01:01618 SequencedSocketData data(reads, writes);
Bence Béky2fcf4fa2018-04-06 20:06:01619 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_, nullptr);
620 helper.RunPreTestSetup();
621 helper.AddData(&data);
622
623 if (set_priority_before_starting_transaction) {
624 helper.trans()->SetPriority(LOWEST);
625 EXPECT_TRUE(helper.StartDefaultTest());
626 } else {
627 EXPECT_TRUE(helper.StartDefaultTest());
628 helper.trans()->SetPriority(LOWEST);
629 }
630
631 helper.FinishDefaultTest();
632 helper.VerifyDataConsumed();
633
634 TransactionHelperResult out = helper.output();
635 EXPECT_THAT(out.rv, IsOk());
636 EXPECT_EQ("HTTP/1.1 200", out.status_line);
637 EXPECT_EQ("hello!", out.response_data);
638 }
639}
640
Bence Béky7a4836c2018-05-08 03:52:48641// Test that changing the request priority of an existing stream triggers
Bence Béky73b85292018-06-14 04:56:43642// sending PRIORITY frames in case there are multiple open streams and their
Bence Béky7a4836c2018-05-08 03:52:48643// relative priorities change.
Bence Béky73b85292018-06-14 04:56:43644TEST_F(SpdyNetworkTransactionTest, SetPriorityOnExistingStream) {
Bence Béky7a4836c2018-05-08 03:52:48645 const char* kUrl2 = "https://www.example.org/bar";
646
Ryan Hamilton0239aac2018-05-19 00:03:13647 spdy::SpdySerializedFrame req1(
648 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
649 spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet(kUrl2, 3, MEDIUM));
650 spdy::SpdySerializedFrame priority1(
Bence Béky7a4836c2018-05-08 03:52:48651 spdy_util_.ConstructSpdyPriority(3, 0, MEDIUM, true));
Ryan Hamilton0239aac2018-05-19 00:03:13652 spdy::SpdySerializedFrame priority2(
Bence Béky7a4836c2018-05-08 03:52:48653 spdy_util_.ConstructSpdyPriority(1, 3, LOWEST, true));
654 MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 2),
655 CreateMockWrite(priority1, 4),
656 CreateMockWrite(priority2, 5)};
657
Ryan Hamilton0239aac2018-05-19 00:03:13658 spdy::SpdySerializedFrame resp1(
659 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
660 spdy::SpdySerializedFrame resp2(
661 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
662 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
663 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
Bence Béky7a4836c2018-05-08 03:52:48664 MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(resp2, 3),
665 CreateMockRead(body1, 6), CreateMockRead(body2, 7),
666 MockRead(ASYNC, 0, 8)};
667
668 SequencedSocketData data(reads, writes);
669 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_, nullptr);
670 helper.RunPreTestSetup();
671 helper.AddData(&data);
672 EXPECT_TRUE(helper.StartDefaultTest());
673
674 // Open HTTP/2 connection and create first stream.
675 base::RunLoop().RunUntilIdle();
676
677 HttpNetworkTransaction trans2(MEDIUM, helper.session());
678 HttpRequestInfo request2;
679 request2.url = GURL(kUrl2);
680 request2.method = "GET";
681 request2.traffic_annotation =
682 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
683 TestCompletionCallback callback2;
684 int rv = trans2.Start(&request2, callback2.callback(), log_);
685 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
686
687 // Create second stream.
688 base::RunLoop().RunUntilIdle();
689
690 // First request has HIGHEST priority, second request has MEDIUM priority.
691 // Changing the priority of the first request to LOWEST changes their order,
692 // and therefore triggers sending PRIORITY frames.
693 helper.trans()->SetPriority(LOWEST);
694
695 helper.FinishDefaultTest();
696 helper.VerifyDataConsumed();
697
698 TransactionHelperResult out = helper.output();
699 EXPECT_THAT(out.rv, IsOk());
700 EXPECT_EQ("HTTP/1.1 200", out.status_line);
701 EXPECT_EQ("hello!", out.response_data);
702
703 rv = callback2.WaitForResult();
704 ASSERT_THAT(rv, IsOk());
705 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
706 ASSERT_TRUE(response2);
707 ASSERT_TRUE(response2->headers);
708 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
709 response2->connection_info);
710 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
711}
712
Bence Béky73b85292018-06-14 04:56:43713// Create two requests: a lower priority one first, then a higher priority one.
714// Test that the second request gets sent out first.
715TEST_F(SpdyNetworkTransactionTest, RequestsOrderedByPriority) {
716 const char* kUrl2 = "https://www.example.org/foo";
717
718 // First send second request on stream 1, then first request on stream 3.
719 spdy::SpdySerializedFrame req2(
720 spdy_util_.ConstructSpdyGet(kUrl2, 1, HIGHEST));
721 spdy::SpdySerializedFrame req1(
722 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOW));
723 MockWrite writes[] = {CreateMockWrite(req2, 0), CreateMockWrite(req1, 1)};
724
725 spdy::SpdySerializedFrame resp2(
726 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
727 spdy::SpdySerializedFrame resp1(
728 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
729 spdy::SpdySerializedFrame body2(
730 spdy_util_.ConstructSpdyDataFrame(1, "stream 1", true));
731 spdy::SpdySerializedFrame body1(
732 spdy_util_.ConstructSpdyDataFrame(3, "stream 3", true));
733 MockRead reads[] = {CreateMockRead(resp2, 2), CreateMockRead(body2, 3),
734 CreateMockRead(resp1, 4), CreateMockRead(body1, 5),
735 MockRead(ASYNC, 0, 6)};
736
737 SequencedSocketData data(reads, writes);
738 NormalSpdyTransactionHelper helper(request_, LOW, log_, nullptr);
739 helper.RunPreTestSetup();
740 helper.AddData(&data);
741
742 // Create HTTP/2 connection. This is necessary because starting the first
743 // transaction does not create the connection yet, so the second request
744 // could not use the same connection, whereas running the message loop after
745 // starting the first transaction would call Socket::Write() with the first
746 // HEADERS frame, so the second transaction could not get ahead of it.
747 SpdySessionKey key(HostPortPair("www.example.org", 443),
Matt Menke2436b2f2018-12-11 18:07:11748 ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
749 SpdySessionKey::IsProxySession::kFalse, SocketTag());
Bence Béky73b85292018-06-14 04:56:43750 auto spdy_session = CreateSpdySession(helper.session(), key, log_);
751 EXPECT_TRUE(spdy_session);
752
753 // Start first transaction.
754 EXPECT_TRUE(helper.StartDefaultTest());
755
756 // Start second transaction.
757 HttpNetworkTransaction trans2(HIGHEST, helper.session());
758 HttpRequestInfo request2;
759 request2.url = GURL(kUrl2);
760 request2.method = "GET";
761 request2.traffic_annotation =
762 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
763 TestCompletionCallback callback2;
764 int rv = trans2.Start(&request2, callback2.callback(), log_);
765 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
766
767 // Complete first transaction and verify results.
768 helper.FinishDefaultTest();
769 helper.VerifyDataConsumed();
770
771 TransactionHelperResult out = helper.output();
772 EXPECT_THAT(out.rv, IsOk());
773 EXPECT_EQ("HTTP/1.1 200", out.status_line);
774 EXPECT_EQ("stream 3", out.response_data);
775
776 // Complete second transaction and verify results.
777 rv = callback2.WaitForResult();
778 ASSERT_THAT(rv, IsOk());
779 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
780 ASSERT_TRUE(response2);
781 ASSERT_TRUE(response2->headers);
782 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
783 response2->connection_info);
784 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
785 std::string response_data;
786 ReadTransaction(&trans2, &response_data);
787 EXPECT_EQ("stream 1", response_data);
788}
789
790// Test that already enqueued HEADERS frames are reordered if their relative
791// priority changes.
792TEST_F(SpdyNetworkTransactionTest, QueuedFramesReorderedOnPriorityChange) {
793 const char* kUrl2 = "https://www.example.org/foo";
794 const char* kUrl3 = "https://www.example.org/bar";
795
796 spdy::SpdySerializedFrame req1(
797 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY));
798 spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyGet(kUrl3, 3, MEDIUM));
799 spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet(kUrl2, 5, LOWEST));
800 MockWrite writes[] = {MockWrite(ASYNC, ERR_IO_PENDING, 0),
801 CreateMockWrite(req1, 1), CreateMockWrite(req3, 2),
802 CreateMockWrite(req2, 3)};
803
804 spdy::SpdySerializedFrame resp1(
805 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
806 spdy::SpdySerializedFrame resp3(
807 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
808 spdy::SpdySerializedFrame resp2(
809 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
810 spdy::SpdySerializedFrame body1(
811 spdy_util_.ConstructSpdyDataFrame(1, "stream 1", true));
812 spdy::SpdySerializedFrame body3(
813 spdy_util_.ConstructSpdyDataFrame(3, "stream 3", true));
814 spdy::SpdySerializedFrame body2(
815 spdy_util_.ConstructSpdyDataFrame(5, "stream 5", true));
816 MockRead reads[] = {CreateMockRead(resp1, 4), CreateMockRead(body1, 5),
817 CreateMockRead(resp3, 6), CreateMockRead(body3, 7),
818 CreateMockRead(resp2, 8), CreateMockRead(body2, 9),
819 MockRead(ASYNC, 0, 10)};
820
821 SequencedSocketData data(reads, writes);
822 // Priority of first request does not matter, because Socket::Write() will be
823 // called with its HEADERS frame before the other requests start.
824 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
825 helper.RunPreTestSetup();
826 helper.AddData(&data);
827 EXPECT_TRUE(helper.StartDefaultTest());
828
829 // Open HTTP/2 connection, create HEADERS frame for first request, and call
830 // Socket::Write() with that frame. After this, no other request can get
831 // ahead of the first one.
832 base::RunLoop().RunUntilIdle();
833
834 HttpNetworkTransaction trans2(HIGHEST, helper.session());
835 HttpRequestInfo request2;
836 request2.url = GURL(kUrl2);
837 request2.method = "GET";
838 request2.traffic_annotation =
839 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
840 TestCompletionCallback callback2;
841 int rv = trans2.Start(&request2, callback2.callback(), log_);
842 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
843
844 HttpNetworkTransaction trans3(MEDIUM, helper.session());
845 HttpRequestInfo request3;
846 request3.url = GURL(kUrl3);
847 request3.method = "GET";
848 request3.traffic_annotation =
849 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
850 TestCompletionCallback callback3;
851 rv = trans3.Start(&request3, callback3.callback(), log_);
852 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
853
854 // Create HEADERS frames for second and third request and enqueue them in
855 // SpdyWriteQueue with their original priorities. Writing of the first
856 // HEADERS frame to the socked still has not completed.
857 base::RunLoop().RunUntilIdle();
858
859 // Second request is of HIGHEST, third of MEDIUM priority. Changing second
860 // request to LOWEST changes their relative order. This should result in
861 // already enqueued frames being reordered within SpdyWriteQueue.
862 trans2.SetPriority(LOWEST);
863
864 // Complete async write of the first HEADERS frame.
865 data.Resume();
866
867 helper.FinishDefaultTest();
868 TransactionHelperResult out = helper.output();
869 EXPECT_THAT(out.rv, IsOk());
870 EXPECT_EQ("HTTP/1.1 200", out.status_line);
871 EXPECT_EQ("stream 1", out.response_data);
872
873 rv = callback2.WaitForResult();
874 ASSERT_THAT(rv, IsOk());
875 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
876 ASSERT_TRUE(response2);
877 ASSERT_TRUE(response2->headers);
878 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
879 response2->connection_info);
880 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
881 std::string response_data;
882 ReadTransaction(&trans2, &response_data);
883 EXPECT_EQ("stream 5", response_data);
884
885 rv = callback3.WaitForResult();
886 ASSERT_THAT(rv, IsOk());
887 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
888 ASSERT_TRUE(response3);
889 ASSERT_TRUE(response3->headers);
890 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
891 response3->connection_info);
892 EXPECT_EQ("HTTP/1.1 200", response3->headers->GetStatusLine());
893 ReadTransaction(&trans3, &response_data);
894 EXPECT_EQ("stream 3", response_data);
895
896 helper.VerifyDataConsumed();
897}
898
bncd16676a2016-07-20 16:23:01899TEST_F(SpdyNetworkTransactionTest, GetAtEachPriority) {
[email protected]3d08dd382013-10-19 00:13:11900 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
[email protected]31ae7ab2012-04-24 21:09:05901 p = RequestPriority(p + 1)) {
bncd16676a2016-07-20 16:23:01902 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:49903
[email protected]c9c6f5c2010-07-31 01:30:03904 // Construct the request.
Ryan Hamilton0239aac2018-05-19 00:03:13905 spdy::SpdySerializedFrame req(
906 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, p));
bncdf80d44fd2016-07-15 20:27:41907 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]c9c6f5c2010-07-31 01:30:03908
Ryan Hamilton0239aac2018-05-19 00:03:13909 spdy::SpdyPriority spdy_prio = 0;
bncdf80d44fd2016-07-15 20:27:41910 EXPECT_TRUE(GetSpdyPriority(req, &spdy_prio));
Ryan Hamilton0239aac2018-05-19 00:03:13911 // this repeats the RequestPriority-->spdy::SpdyPriority mapping from
912 // spdy::SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
[email protected]c9c6f5c2010-07-31 01:30:03913 // sure it's being done right.
bnc05808ff42016-01-08 23:48:25914 switch (p) {
915 case HIGHEST:
916 EXPECT_EQ(0, spdy_prio);
917 break;
918 case MEDIUM:
919 EXPECT_EQ(1, spdy_prio);
920 break;
921 case LOW:
922 EXPECT_EQ(2, spdy_prio);
923 break;
924 case LOWEST:
925 EXPECT_EQ(3, spdy_prio);
926 break;
927 case IDLE:
928 EXPECT_EQ(4, spdy_prio);
929 break;
rdsmith5eb6fbc2016-10-21 17:36:08930 case THROTTLED:
931 EXPECT_EQ(5, spdy_prio);
932 break;
bnc05808ff42016-01-08 23:48:25933 default:
934 FAIL();
[email protected]c9c6f5c2010-07-31 01:30:03935 }
936
Ryan Hamilton0239aac2018-05-19 00:03:13937 spdy::SpdySerializedFrame resp(
bnc42331402016-07-25 13:36:15938 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:13939 spdy::SpdySerializedFrame body(
940 spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]c9c6f5c2010-07-31 01:30:03941 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41942 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:52943 MockRead(ASYNC, 0, 3) // EOF
[email protected]c9c6f5c2010-07-31 01:30:03944 };
945
Ryan Sleevib8d7ea02018-05-07 20:01:01946 SequencedSocketData data(reads, writes);
[email protected]c9c6f5c2010-07-31 01:30:03947
Bence Békydb3cf652017-10-10 15:22:10948 NormalSpdyTransactionHelper helper(request_, p, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:57949 helper.RunToCompletion(&data);
[email protected]c9c6f5c2010-07-31 01:30:03950 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:01951 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02952 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]c9c6f5c2010-07-31 01:30:03953 EXPECT_EQ("hello!", out.response_data);
954 }
955}
956
[email protected]2bd93022010-07-17 00:58:44957// Start three gets simultaniously; making sure that multiplexed
958// streams work properly.
959
960// This can't use the TransactionHelper method, since it only
961// handles a single transaction, and finishes them as soon
962// as it launches them.
963
964// TODO(gavinp): create a working generalized TransactionHelper that
965// can allow multiple streams in flight.
966
bncd16676a2016-07-20 16:23:01967TEST_F(SpdyNetworkTransactionTest, ThreeGets) {
Ryan Hamilton0239aac2018-05-19 00:03:13968 spdy::SpdySerializedFrame req(
969 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
970 spdy::SpdySerializedFrame resp(
971 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
972 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
973 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2bd93022010-07-17 00:58:44974
Ryan Hamilton0239aac2018-05-19 00:03:13975 spdy::SpdySerializedFrame req2(
976 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
977 spdy::SpdySerializedFrame resp2(
978 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
979 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
980 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2bd93022010-07-17 00:58:44981
Ryan Hamilton0239aac2018-05-19 00:03:13982 spdy::SpdySerializedFrame req3(
983 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST));
984 spdy::SpdySerializedFrame resp3(
985 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
986 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
987 spdy::SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44988
[email protected]1b323172011-03-01 17:50:17989 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41990 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
991 CreateMockWrite(req3, 6),
[email protected]2bd93022010-07-17 00:58:44992 };
993 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41994 CreateMockRead(resp, 1), CreateMockRead(body, 2),
995 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
996 CreateMockRead(resp3, 7), CreateMockRead(body3, 8),
[email protected]2bd93022010-07-17 00:58:44997
bncdf80d44fd2016-07-15 20:27:41998 CreateMockRead(fbody, 9), CreateMockRead(fbody2, 10),
999 CreateMockRead(fbody3, 11),
[email protected]2bd93022010-07-17 00:58:441000
rch08e3aa3e2015-05-16 14:27:521001 MockRead(ASYNC, 0, 12), // EOF
[email protected]2bd93022010-07-17 00:58:441002 };
Ryan Sleevib8d7ea02018-05-07 20:01:011003 SequencedSocketData data(reads, writes);
1004 SequencedSocketData data_placeholder1;
1005 SequencedSocketData data_placeholder2;
[email protected]2bd93022010-07-17 00:58:441006
[email protected]2bd93022010-07-17 00:58:441007 TransactionHelperResult out;
Bence Békydb3cf652017-10-10 15:22:101008 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]bdebd1b2010-08-09 20:18:081009 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571010 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:491011 // We require placeholder data because three get requests are sent out at
1012 // the same time which results in three sockets being connected. The first
1013 // on will negotiate SPDY and will be used for all requests.
mmenkecc2298e2015-12-07 18:20:181014 helper.AddData(&data_placeholder1);
1015 helper.AddData(&data_placeholder2);
[email protected]49639fa2011-12-20 23:22:411016 TestCompletionCallback callback1;
1017 TestCompletionCallback callback2;
1018 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441019
krasin0bfeb6b2017-01-13 21:48:041020 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1021 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
1022 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
1023
Bence Békydb3cf652017-10-10 15:22:101024 out.rv = trans1.Start(&request_, callback1.callback(), log_);
robpercival214763f2016-07-01 23:27:011025 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
Bence Békydb3cf652017-10-10 15:22:101026 out.rv = trans2.Start(&request_, callback2.callback(), log_);
robpercival214763f2016-07-01 23:27:011027 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
Bence Békydb3cf652017-10-10 15:22:101028 out.rv = trans3.Start(&request_, callback3.callback(), log_);
robpercival214763f2016-07-01 23:27:011029 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]2bd93022010-07-17 00:58:441030
[email protected]bdebd1b2010-08-09 20:18:081031 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011032 ASSERT_THAT(out.rv, IsOk());
[email protected]bdebd1b2010-08-09 20:18:081033 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011034 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441035
bnc691fda62016-08-12 00:43:161036 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521037 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:081038 EXPECT_TRUE(response1->was_fetched_via_spdy);
1039 out.status_line = response1->headers->GetStatusLine();
1040 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:441041
bnc691fda62016-08-12 00:43:161042 trans2.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:441043
bnc691fda62016-08-12 00:43:161044 out.rv = ReadTransaction(&trans1, &out.response_data);
[email protected]bdebd1b2010-08-09 20:18:081045 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:011046 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441047
robpercival214763f2016-07-01 23:27:011048 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021049 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441050 EXPECT_EQ("hello!hello!", out.response_data);
1051}
1052
bncd16676a2016-07-20 16:23:011053TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
Ryan Hamilton0239aac2018-05-19 00:03:131054 spdy::SpdySerializedFrame req(
1055 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1056 spdy::SpdySerializedFrame resp(
1057 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1058 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1059 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1b323172011-03-01 17:50:171060
Ryan Hamilton0239aac2018-05-19 00:03:131061 spdy::SpdySerializedFrame req2(
1062 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
1063 spdy::SpdySerializedFrame resp2(
1064 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1065 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1066 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]1b323172011-03-01 17:50:171067
1068 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411069 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
[email protected]1b323172011-03-01 17:50:171070 };
1071 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411072 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1073 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
1074 CreateMockRead(fbody, 6), CreateMockRead(fbody2, 7),
rch08e3aa3e2015-05-16 14:27:521075 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:171076 };
Ryan Sleevib8d7ea02018-05-07 20:01:011077 SequencedSocketData data(reads, writes);
[email protected]1b323172011-03-01 17:50:171078
[email protected]d973e99a2012-02-17 21:02:361079 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:011080 SequencedSocketData data_placeholder;
[email protected]dd54bd82012-07-19 23:44:571081 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:171082
[email protected]1b323172011-03-01 17:50:171083 TransactionHelperResult out;
Bence Békydb3cf652017-10-10 15:22:101084 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]1b323172011-03-01 17:50:171085 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571086 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:491087 // We require placeholder data because two requests are sent out at
1088 // the same time which results in two sockets being connected. The first
1089 // on will negotiate SPDY and will be used for all requests.
[email protected]dd54bd82012-07-19 23:44:571090 helper.AddData(&data_placeholder);
bnc691fda62016-08-12 00:43:161091 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1092 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]1b323172011-03-01 17:50:171093
[email protected]49639fa2011-12-20 23:22:411094 TestCompletionCallback callback1;
1095 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:171096
Bence Békydb3cf652017-10-10 15:22:101097 out.rv = trans1.Start(&request_, callback1.callback(), log_);
robpercival214763f2016-07-01 23:27:011098 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
Bence Békydb3cf652017-10-10 15:22:101099 out.rv = trans2.Start(&request_, callback2.callback(), log_);
robpercival214763f2016-07-01 23:27:011100 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]1b323172011-03-01 17:50:171101
1102 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011103 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:171104 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011105 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:171106
bnc691fda62016-08-12 00:43:161107 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521108 EXPECT_TRUE(response1->headers);
[email protected]1b323172011-03-01 17:50:171109 EXPECT_TRUE(response1->was_fetched_via_spdy);
1110 out.status_line = response1->headers->GetStatusLine();
1111 out.response_info = *response1;
bnc691fda62016-08-12 00:43:161112 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011113 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021114 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:171115 EXPECT_EQ("hello!hello!", out.response_data);
1116
bnc691fda62016-08-12 00:43:161117 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:521118 EXPECT_TRUE(response2->headers);
[email protected]1b323172011-03-01 17:50:171119 EXPECT_TRUE(response2->was_fetched_via_spdy);
1120 out.status_line = response2->headers->GetStatusLine();
1121 out.response_info = *response2;
bnc691fda62016-08-12 00:43:161122 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011123 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021124 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:171125 EXPECT_EQ("hello!hello!", out.response_data);
1126
1127 helper.VerifyDataConsumed();
1128}
1129
bncd16676a2016-07-20 16:23:011130TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
Ryan Hamilton0239aac2018-05-19 00:03:131131 spdy::SpdySerializedFrame req(
1132 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1133 spdy::SpdySerializedFrame resp(
1134 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1135 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1136 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1b323172011-03-01 17:50:171137
Ryan Hamilton0239aac2018-05-19 00:03:131138 spdy::SpdySerializedFrame req2(
1139 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
1140 spdy::SpdySerializedFrame resp2(
1141 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1142 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1143 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]1b323172011-03-01 17:50:171144
1145 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411146 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
[email protected]1b323172011-03-01 17:50:171147 };
1148 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411149 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1150 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
1151 CreateMockRead(fbody, 6), CreateMockRead(fbody2, 7),
rch08e3aa3e2015-05-16 14:27:521152 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:171153 };
Ryan Sleevib8d7ea02018-05-07 20:01:011154 SequencedSocketData preconnect_data(reads, writes);
[email protected]1b323172011-03-01 17:50:171155
[email protected]d973e99a2012-02-17 21:02:361156 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
[email protected]1b323172011-03-01 17:50:171157
Ryan Sleevib8d7ea02018-05-07 20:01:011158 SequencedSocketData data_placeholder;
[email protected]dd54bd82012-07-19 23:44:571159 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:171160
[email protected]1b323172011-03-01 17:50:171161 TransactionHelperResult out;
Bence Békydb3cf652017-10-10 15:22:101162 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]1b323172011-03-01 17:50:171163 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571164 helper.AddData(&preconnect_data);
[email protected]1b323172011-03-01 17:50:171165 // We require placeholder data because 3 connections are attempted (first is
1166 // the preconnect, 2nd and 3rd are the never finished connections.
[email protected]dd54bd82012-07-19 23:44:571167 helper.AddData(&data_placeholder);
1168 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:171169
bnc691fda62016-08-12 00:43:161170 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1171 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]1b323172011-03-01 17:50:171172
[email protected]49639fa2011-12-20 23:22:411173 TestCompletionCallback callback1;
1174 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:171175
[email protected]1b323172011-03-01 17:50:171176 // Preconnect the first.
[email protected]1b323172011-03-01 17:50:171177 HttpStreamFactory* http_stream_factory =
1178 helper.session()->http_stream_factory();
[email protected]1b323172011-03-01 17:50:171179
Bence Békydb3cf652017-10-10 15:22:101180 http_stream_factory->PreconnectStreams(1, request_);
[email protected]1b323172011-03-01 17:50:171181
Bence Békydb3cf652017-10-10 15:22:101182 out.rv = trans1.Start(&request_, callback1.callback(), log_);
robpercival214763f2016-07-01 23:27:011183 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
Bence Békydb3cf652017-10-10 15:22:101184 out.rv = trans2.Start(&request_, callback2.callback(), log_);
robpercival214763f2016-07-01 23:27:011185 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]1b323172011-03-01 17:50:171186
1187 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011188 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:171189 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011190 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:171191
bnc691fda62016-08-12 00:43:161192 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521193 EXPECT_TRUE(response1->headers);
[email protected]1b323172011-03-01 17:50:171194 EXPECT_TRUE(response1->was_fetched_via_spdy);
1195 out.status_line = response1->headers->GetStatusLine();
1196 out.response_info = *response1;
bnc691fda62016-08-12 00:43:161197 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011198 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021199 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:171200 EXPECT_EQ("hello!hello!", out.response_data);
1201
bnc691fda62016-08-12 00:43:161202 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:521203 EXPECT_TRUE(response2->headers);
[email protected]1b323172011-03-01 17:50:171204 EXPECT_TRUE(response2->was_fetched_via_spdy);
1205 out.status_line = response2->headers->GetStatusLine();
1206 out.response_info = *response2;
bnc691fda62016-08-12 00:43:161207 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011208 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021209 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:171210 EXPECT_EQ("hello!hello!", out.response_data);
1211
1212 helper.VerifyDataConsumed();
1213}
1214
[email protected]2bd93022010-07-17 00:58:441215// Similar to ThreeGets above, however this test adds a SETTINGS
1216// frame. The SETTINGS frame is read during the IO loop waiting on
1217// the first transaction completion, and sets a maximum concurrent
1218// stream limit of 1. This means that our IO loop exists after the
1219// second transaction completes, so we can assert on read_index().
bncd16676a2016-07-20 16:23:011220TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:441221 // Construct the request.
rdsmithebb50aa2015-11-12 03:44:381222 // Each request fully completes before the next starts.
Ryan Hamilton0239aac2018-05-19 00:03:131223 spdy::SpdySerializedFrame req(
1224 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1225 spdy::SpdySerializedFrame resp(
1226 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1227 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1228 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381229 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441230
Ryan Hamilton0239aac2018-05-19 00:03:131231 spdy::SpdySerializedFrame req2(
1232 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
1233 spdy::SpdySerializedFrame resp2(
1234 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1235 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1236 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:381237 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:441238
Ryan Hamilton0239aac2018-05-19 00:03:131239 spdy::SpdySerializedFrame req3(
1240 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST));
1241 spdy::SpdySerializedFrame resp3(
1242 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
1243 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
1244 spdy::SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]2bd93022010-07-17 00:58:441245
Ryan Hamilton0239aac2018-05-19 00:03:131246 spdy::SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461247 const uint32_t max_concurrent_streams = 1;
Ryan Hamilton0239aac2018-05-19 00:03:131248 settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
1249 spdy::SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201250 spdy_util_.ConstructSpdySettings(settings));
Ryan Hamilton0239aac2018-05-19 00:03:131251 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441252
[email protected]2d6728692011-03-12 01:39:551253 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411254 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1255 CreateMockWrite(req2, 6), CreateMockWrite(req3, 10),
[email protected]2bd93022010-07-17 00:58:441256 };
[email protected]2d6728692011-03-12 01:39:551257
[email protected]2bd93022010-07-17 00:58:441258 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411259 CreateMockRead(settings_frame, 1),
1260 CreateMockRead(resp, 2),
1261 CreateMockRead(body, 3),
1262 CreateMockRead(fbody, 4),
1263 CreateMockRead(resp2, 7),
1264 CreateMockRead(body2, 8),
1265 CreateMockRead(fbody2, 9),
1266 CreateMockRead(resp3, 11),
1267 CreateMockRead(body3, 12),
1268 CreateMockRead(fbody3, 13),
[email protected]2bd93022010-07-17 00:58:441269
rch08e3aa3e2015-05-16 14:27:521270 MockRead(ASYNC, 0, 14), // EOF
[email protected]2bd93022010-07-17 00:58:441271 };
1272
Ryan Sleevib8d7ea02018-05-07 20:01:011273 SequencedSocketData data(reads, writes);
[email protected]2bd93022010-07-17 00:58:441274
[email protected]2bd93022010-07-17 00:58:441275 TransactionHelperResult out;
1276 {
Bence Békydb3cf652017-10-10 15:22:101277 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
1278 nullptr);
[email protected]2d6728692011-03-12 01:39:551279 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571280 helper.AddData(&data);
bnc691fda62016-08-12 00:43:161281 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1282 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
1283 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
[email protected]2bd93022010-07-17 00:58:441284
[email protected]49639fa2011-12-20 23:22:411285 TestCompletionCallback callback1;
1286 TestCompletionCallback callback2;
1287 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441288
Bence Békydb3cf652017-10-10 15:22:101289 out.rv = trans1.Start(&request_, callback1.callback(), log_);
[email protected]2bd93022010-07-17 00:58:441290 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]513963e2013-06-15 01:53:041291 // Run transaction 1 through quickly to force a read of our SETTINGS
1292 // frame.
[email protected]2bd93022010-07-17 00:58:441293 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011294 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441295
Bence Békydb3cf652017-10-10 15:22:101296 out.rv = trans2.Start(&request_, callback2.callback(), log_);
[email protected]2bd93022010-07-17 00:58:441297 ASSERT_EQ(out.rv, ERR_IO_PENDING);
Bence Békydb3cf652017-10-10 15:22:101298 out.rv = trans3.Start(&request_, callback3.callback(), log_);
[email protected]2bd93022010-07-17 00:58:441299 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1300 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011301 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441302
1303 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011304 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441305
bnc691fda62016-08-12 00:43:161306 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521307 ASSERT_TRUE(response1);
1308 EXPECT_TRUE(response1->headers);
[email protected]2bd93022010-07-17 00:58:441309 EXPECT_TRUE(response1->was_fetched_via_spdy);
1310 out.status_line = response1->headers->GetStatusLine();
1311 out.response_info = *response1;
bnc691fda62016-08-12 00:43:161312 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011313 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021314 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441315 EXPECT_EQ("hello!hello!", out.response_data);
1316
bnc691fda62016-08-12 00:43:161317 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:441318 out.status_line = response2->headers->GetStatusLine();
1319 out.response_info = *response2;
bnc691fda62016-08-12 00:43:161320 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011321 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021322 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441323 EXPECT_EQ("hello!hello!", out.response_data);
1324
bnc691fda62016-08-12 00:43:161325 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:441326 out.status_line = response3->headers->GetStatusLine();
1327 out.response_info = *response3;
bnc691fda62016-08-12 00:43:161328 out.rv = ReadTransaction(&trans3, &out.response_data);
robpercival214763f2016-07-01 23:27:011329 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021330 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441331 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:261332
1333 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441334 }
robpercival214763f2016-07-01 23:27:011335 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441336}
1337
1338// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1339// a fourth transaction. The third and fourth transactions have
1340// different data ("hello!" vs "hello!hello!") and because of the
1341// user specified priority, we expect to see them inverted in
1342// the response from the server.
bncd16676a2016-07-20 16:23:011343TEST_F(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:441344 // Construct the request.
Ryan Hamilton0239aac2018-05-19 00:03:131345 spdy::SpdySerializedFrame req(
1346 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1347 spdy::SpdySerializedFrame resp(
1348 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1349 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1350 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381351 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441352
Ryan Hamilton0239aac2018-05-19 00:03:131353 spdy::SpdySerializedFrame req2(
1354 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
1355 spdy::SpdySerializedFrame resp2(
1356 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1357 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1358 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:381359 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:441360
Ryan Hamilton0239aac2018-05-19 00:03:131361 spdy::SpdySerializedFrame req4(
1362 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, HIGHEST));
1363 spdy::SpdySerializedFrame resp4(
1364 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
1365 spdy::SpdySerializedFrame fbody4(spdy_util_.ConstructSpdyDataFrame(5, true));
rdsmithebb50aa2015-11-12 03:44:381366 spdy_util_.UpdateWithStreamDestruction(5);
[email protected]2bd93022010-07-17 00:58:441367
Ryan Hamilton0239aac2018-05-19 00:03:131368 spdy::SpdySerializedFrame req3(
1369 spdy_util_.ConstructSpdyGet(nullptr, 0, 7, LOWEST));
1370 spdy::SpdySerializedFrame resp3(
1371 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 7));
1372 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(7, false));
1373 spdy::SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(7, true));
[email protected]2bd93022010-07-17 00:58:441374
Ryan Hamilton0239aac2018-05-19 00:03:131375 spdy::SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461376 const uint32_t max_concurrent_streams = 1;
Ryan Hamilton0239aac2018-05-19 00:03:131377 settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
1378 spdy::SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201379 spdy_util_.ConstructSpdySettings(settings));
Ryan Hamilton0239aac2018-05-19 00:03:131380 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
rch08e3aa3e2015-05-16 14:27:521381 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411382 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
rch08e3aa3e2015-05-16 14:27:521383 // By making these synchronous, it guarantees that they are not *started*
1384 // before their sequence number, which in turn verifies that only a single
1385 // request is in-flight at a time.
bncdf80d44fd2016-07-15 20:27:411386 CreateMockWrite(req2, 6, SYNCHRONOUS),
1387 CreateMockWrite(req4, 10, SYNCHRONOUS),
1388 CreateMockWrite(req3, 13, SYNCHRONOUS),
[email protected]2bd93022010-07-17 00:58:441389 };
1390 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411391 CreateMockRead(settings_frame, 1),
1392 CreateMockRead(resp, 2),
1393 CreateMockRead(body, 3),
1394 CreateMockRead(fbody, 4),
1395 CreateMockRead(resp2, 7),
1396 CreateMockRead(body2, 8),
1397 CreateMockRead(fbody2, 9),
1398 CreateMockRead(resp4, 11),
1399 CreateMockRead(fbody4, 12),
1400 CreateMockRead(resp3, 14),
1401 CreateMockRead(body3, 15),
1402 CreateMockRead(fbody3, 16),
[email protected]2bd93022010-07-17 00:58:441403
rch08e3aa3e2015-05-16 14:27:521404 MockRead(ASYNC, 0, 17), // EOF
[email protected]2bd93022010-07-17 00:58:441405 };
Ryan Sleevib8d7ea02018-05-07 20:01:011406 SequencedSocketData data(reads, writes);
[email protected]2bd93022010-07-17 00:58:441407 TransactionHelperResult out;
Bence Békydb3cf652017-10-10 15:22:101408 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]bdebd1b2010-08-09 20:18:081409 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571410 helper.AddData(&data);
rch08e3aa3e2015-05-16 14:27:521411
bnc691fda62016-08-12 00:43:161412 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1413 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
1414 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
1415 HttpNetworkTransaction trans4(HIGHEST, helper.session());
[email protected]2bd93022010-07-17 00:58:441416
[email protected]49639fa2011-12-20 23:22:411417 TestCompletionCallback callback1;
1418 TestCompletionCallback callback2;
1419 TestCompletionCallback callback3;
1420 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:441421
Bence Békydb3cf652017-10-10 15:22:101422 out.rv = trans1.Start(&request_, callback1.callback(), log_);
robpercival214763f2016-07-01 23:27:011423 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]e0935cc2012-03-24 14:12:481424 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081425 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011426 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441427
bnceb9aa7112017-01-05 01:03:461428 // Finish async network reads and writes associated with |trans1|.
1429 base::RunLoop().RunUntilIdle();
1430
Bence Békydb3cf652017-10-10 15:22:101431 out.rv = trans2.Start(&request_, callback2.callback(), log_);
robpercival214763f2016-07-01 23:27:011432 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
Bence Békydb3cf652017-10-10 15:22:101433 out.rv = trans3.Start(&request_, callback3.callback(), log_);
robpercival214763f2016-07-01 23:27:011434 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
Bence Békydb3cf652017-10-10 15:22:101435 out.rv = trans4.Start(&request_, callback4.callback(), log_);
robpercival214763f2016-07-01 23:27:011436 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]2bd93022010-07-17 00:58:441437
[email protected]bdebd1b2010-08-09 20:18:081438 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011439 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441440
[email protected]bdebd1b2010-08-09 20:18:081441 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011442 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441443
bnc691fda62016-08-12 00:43:161444 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521445 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:081446 EXPECT_TRUE(response1->was_fetched_via_spdy);
1447 out.status_line = response1->headers->GetStatusLine();
1448 out.response_info = *response1;
bnc691fda62016-08-12 00:43:161449 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011450 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021451 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081452 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441453
bnc691fda62016-08-12 00:43:161454 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081455 out.status_line = response2->headers->GetStatusLine();
1456 out.response_info = *response2;
bnc691fda62016-08-12 00:43:161457 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011458 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021459 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081460 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441461
[email protected]bdebd1b2010-08-09 20:18:081462 // notice: response3 gets two hellos, response4 gets one
1463 // hello, so we know dequeuing priority was respected.
bnc691fda62016-08-12 00:43:161464 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081465 out.status_line = response3->headers->GetStatusLine();
1466 out.response_info = *response3;
bnc691fda62016-08-12 00:43:161467 out.rv = ReadTransaction(&trans3, &out.response_data);
robpercival214763f2016-07-01 23:27:011468 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021469 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081470 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441471
[email protected]bdebd1b2010-08-09 20:18:081472 out.rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:011473 EXPECT_THAT(out.rv, IsOk());
bnc691fda62016-08-12 00:43:161474 const HttpResponseInfo* response4 = trans4.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081475 out.status_line = response4->headers->GetStatusLine();
1476 out.response_info = *response4;
bnc691fda62016-08-12 00:43:161477 out.rv = ReadTransaction(&trans4, &out.response_data);
robpercival214763f2016-07-01 23:27:011478 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021479 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081480 EXPECT_EQ("hello!", out.response_data);
1481 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:011482 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441483}
1484
1485// Similar to ThreeGetsMaxConcurrrent above, however, this test
rch08e3aa3e2015-05-16 14:27:521486// deletes a session in the middle of the transaction to ensure
[email protected]2bd93022010-07-17 00:58:441487// that we properly remove pendingcreatestream objects from
1488// the spdy_session
bncd16676a2016-07-20 16:23:011489TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:441490 // Construct the request.
Ryan Hamilton0239aac2018-05-19 00:03:131491 spdy::SpdySerializedFrame req(
1492 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1493 spdy::SpdySerializedFrame resp(
1494 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1495 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1496 spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381497 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441498
Ryan Hamilton0239aac2018-05-19 00:03:131499 spdy::SpdySerializedFrame req2(
1500 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
1501 spdy::SpdySerializedFrame resp2(
1502 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
1503 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1504 spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441505
Ryan Hamilton0239aac2018-05-19 00:03:131506 spdy::SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461507 const uint32_t max_concurrent_streams = 1;
Ryan Hamilton0239aac2018-05-19 00:03:131508 settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
1509 spdy::SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201510 spdy_util_.ConstructSpdySettings(settings));
Ryan Hamilton0239aac2018-05-19 00:03:131511 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441512
[email protected]d4a77c12014-05-15 20:45:211513 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411514 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1515 CreateMockWrite(req2, 6),
[email protected]2bd93022010-07-17 00:58:441516 };
1517 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411518 CreateMockRead(settings_frame, 1), CreateMockRead(resp, 2),
1519 CreateMockRead(body, 3), CreateMockRead(fbody, 4),
1520 CreateMockRead(resp2, 7), CreateMockRead(body2, 8),
1521 CreateMockRead(fbody2, 9), MockRead(ASYNC, 0, 10), // EOF
[email protected]2bd93022010-07-17 00:58:441522 };
1523
Ryan Sleevib8d7ea02018-05-07 20:01:011524 SequencedSocketData data(reads, writes);
[email protected]2bd93022010-07-17 00:58:441525
[email protected]2bd93022010-07-17 00:58:441526 TransactionHelperResult out;
Bence Békydb3cf652017-10-10 15:22:101527 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]bdebd1b2010-08-09 20:18:081528 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571529 helper.AddData(&data);
Jeremy Roman0579ed62017-08-29 15:56:191530 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc3f6a8552017-05-17 13:40:341531 helper.session());
Jeremy Roman0579ed62017-08-29 15:56:191532 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc3f6a8552017-05-17 13:40:341533 helper.session());
Jeremy Roman0579ed62017-08-29 15:56:191534 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc3f6a8552017-05-17 13:40:341535 helper.session());
[email protected]2bd93022010-07-17 00:58:441536
[email protected]49639fa2011-12-20 23:22:411537 TestCompletionCallback callback1;
1538 TestCompletionCallback callback2;
1539 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441540
Bence Békydb3cf652017-10-10 15:22:101541 out.rv = trans1->Start(&request_, callback1.callback(), log_);
[email protected]bdebd1b2010-08-09 20:18:081542 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481543 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081544 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011545 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441546
Bence Békydb3cf652017-10-10 15:22:101547 out.rv = trans2->Start(&request_, callback2.callback(), log_);
[email protected]bdebd1b2010-08-09 20:18:081548 ASSERT_EQ(out.rv, ERR_IO_PENDING);
Bence Békydb3cf652017-10-10 15:22:101549 out.rv = trans3->Start(&request_, callback3.callback(), log_);
olli.raula7ca9cd1d2016-01-04 06:50:371550 trans3.reset();
[email protected]bdebd1b2010-08-09 20:18:081551 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1552 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011553 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441554
[email protected]bdebd1b2010-08-09 20:18:081555 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:521556 ASSERT_TRUE(response1);
1557 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:081558 EXPECT_TRUE(response1->was_fetched_via_spdy);
1559 out.status_line = response1->headers->GetStatusLine();
1560 out.response_info = *response1;
1561 out.rv = ReadTransaction(trans1.get(), &out.response_data);
robpercival214763f2016-07-01 23:27:011562 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021563 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081564 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441565
[email protected]bdebd1b2010-08-09 20:18:081566 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:521567 ASSERT_TRUE(response2);
[email protected]bdebd1b2010-08-09 20:18:081568 out.status_line = response2->headers->GetStatusLine();
1569 out.response_info = *response2;
1570 out.rv = ReadTransaction(trans2.get(), &out.response_data);
robpercival214763f2016-07-01 23:27:011571 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021572 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081573 EXPECT_EQ("hello!hello!", out.response_data);
1574 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:011575 EXPECT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261576}
[email protected]2bd93022010-07-17 00:58:441577
[email protected]448d4ca52012-03-04 04:12:231578namespace {
1579
Bence Béky8ddc2492018-06-13 01:02:041580// A helper class that will delete |transaction| on error when the callback is
1581// invoked.
[email protected]49639fa2011-12-20 23:22:411582class KillerCallback : public TestCompletionCallbackBase {
[email protected]044dcc52010-09-17 15:44:261583 public:
1584 explicit KillerCallback(HttpNetworkTransaction* transaction)
Bence Béky8ddc2492018-06-13 01:02:041585 : transaction_(transaction) {}
[email protected]044dcc52010-09-17 15:44:261586
Chris Watkins61914cb2017-12-01 19:59:001587 ~KillerCallback() override = default;
[email protected]49639fa2011-12-20 23:22:411588
Bence Béky8ddc2492018-06-13 01:02:041589 CompletionOnceCallback callback() {
1590 return base::BindOnce(&KillerCallback::OnComplete, base::Unretained(this));
1591 }
[email protected]49639fa2011-12-20 23:22:411592
[email protected]044dcc52010-09-17 15:44:261593 private:
[email protected]49639fa2011-12-20 23:22:411594 void OnComplete(int result) {
1595 if (result < 0)
1596 delete transaction_;
1597
1598 SetResult(result);
1599 }
1600
[email protected]044dcc52010-09-17 15:44:261601 HttpNetworkTransaction* transaction_;
1602};
1603
[email protected]448d4ca52012-03-04 04:12:231604} // namespace
1605
[email protected]044dcc52010-09-17 15:44:261606// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1607// closes the socket while we have a pending transaction waiting for
1608// a pending stream creation. http://crbug.com/52901
bncd16676a2016-07-20 16:23:011609TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
[email protected]044dcc52010-09-17 15:44:261610 // Construct the request.
Ryan Hamilton0239aac2018-05-19 00:03:131611 spdy::SpdySerializedFrame req(
1612 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1613 spdy::SpdySerializedFrame resp(
1614 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1615 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1616 spdy::SpdySerializedFrame fin_body(
1617 spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381618 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]044dcc52010-09-17 15:44:261619
Ryan Hamilton0239aac2018-05-19 00:03:131620 spdy::SpdySerializedFrame req2(
1621 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
1622 spdy::SpdySerializedFrame resp2(
1623 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]044dcc52010-09-17 15:44:261624
Ryan Hamilton0239aac2018-05-19 00:03:131625 spdy::SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461626 const uint32_t max_concurrent_streams = 1;
Ryan Hamilton0239aac2018-05-19 00:03:131627 settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
1628 spdy::SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201629 spdy_util_.ConstructSpdySettings(settings));
Ryan Hamilton0239aac2018-05-19 00:03:131630 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]044dcc52010-09-17 15:44:261631
[email protected]d4a77c12014-05-15 20:45:211632 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411633 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1634 CreateMockWrite(req2, 6),
[email protected]044dcc52010-09-17 15:44:261635 };
1636 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411637 CreateMockRead(settings_frame, 1),
1638 CreateMockRead(resp, 2),
1639 CreateMockRead(body, 3),
1640 CreateMockRead(fin_body, 4),
1641 CreateMockRead(resp2, 7),
rch08e3aa3e2015-05-16 14:27:521642 MockRead(ASYNC, ERR_CONNECTION_RESET, 8), // Abort!
[email protected]044dcc52010-09-17 15:44:261643 };
1644
Ryan Sleevib8d7ea02018-05-07 20:01:011645 SequencedSocketData data(reads, writes);
1646 SequencedSocketData data_placeholder;
[email protected]044dcc52010-09-17 15:44:261647
[email protected]044dcc52010-09-17 15:44:261648 TransactionHelperResult out;
Bence Békydb3cf652017-10-10 15:22:101649 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]044dcc52010-09-17 15:44:261650 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571651 helper.AddData(&data);
[email protected]044dcc52010-09-17 15:44:261652 // We require placeholder data because three get requests are sent out, so
1653 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571654 helper.AddData(&data_placeholder);
1655 helper.AddData(&data_placeholder);
mmenkee65e7af2015-10-13 17:16:421656 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1657 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]262eec82013-03-19 21:01:361658 HttpNetworkTransaction* trans3(
mmenkee65e7af2015-10-13 17:16:421659 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]044dcc52010-09-17 15:44:261660
[email protected]49639fa2011-12-20 23:22:411661 TestCompletionCallback callback1;
1662 TestCompletionCallback callback2;
[email protected]044dcc52010-09-17 15:44:261663 KillerCallback callback3(trans3);
1664
Bence Békydb3cf652017-10-10 15:22:101665 out.rv = trans1.Start(&request_, callback1.callback(), log_);
[email protected]044dcc52010-09-17 15:44:261666 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481667 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]044dcc52010-09-17 15:44:261668 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011669 ASSERT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261670
Bence Békydb3cf652017-10-10 15:22:101671 out.rv = trans2.Start(&request_, callback2.callback(), log_);
[email protected]044dcc52010-09-17 15:44:261672 ASSERT_EQ(out.rv, ERR_IO_PENDING);
Bence Békydb3cf652017-10-10 15:22:101673 out.rv = trans3->Start(&request_, callback3.callback(), log_);
[email protected]044dcc52010-09-17 15:44:261674 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1675 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011676 ASSERT_THAT(out.rv, IsError(ERR_ABORTED));
[email protected]044dcc52010-09-17 15:44:261677
[email protected]044dcc52010-09-17 15:44:261678 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521679 ASSERT_TRUE(response1);
1680 EXPECT_TRUE(response1->headers);
[email protected]044dcc52010-09-17 15:44:261681 EXPECT_TRUE(response1->was_fetched_via_spdy);
1682 out.status_line = response1->headers->GetStatusLine();
1683 out.response_info = *response1;
1684 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011685 EXPECT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261686
1687 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:521688 ASSERT_TRUE(response2);
[email protected]044dcc52010-09-17 15:44:261689 out.status_line = response2->headers->GetStatusLine();
1690 out.response_info = *response2;
1691 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011692 EXPECT_THAT(out.rv, IsError(ERR_CONNECTION_RESET));
[email protected]044dcc52010-09-17 15:44:261693
1694 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441695}
1696
[email protected]d8ef27b2010-08-06 17:34:391697// Test that a simple PUT request works.
bncd16676a2016-07-20 16:23:011698TEST_F(SpdyNetworkTransactionTest, Put) {
Bence Békydb3cf652017-10-10 15:22:101699 // Setup the request.
1700 request_.method = "PUT";
[email protected]d8ef27b2010-08-06 17:34:391701
Ryan Hamilton0239aac2018-05-19 00:03:131702 spdy::SpdyHeaderBlock put_headers(
bncb26024382016-06-29 02:39:451703 spdy_util_.ConstructPutHeaderBlock(kDefaultUrl, 0));
Ryan Hamilton0239aac2018-05-19 00:03:131704 spdy::SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151705 spdy_util_.ConstructSpdyHeaders(1, std::move(put_headers), LOWEST, true));
[email protected]d8ef27b2010-08-06 17:34:391706 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411707 CreateMockWrite(req, 0),
[email protected]d8ef27b2010-08-06 17:34:391708 };
1709
Ryan Hamilton0239aac2018-05-19 00:03:131710 spdy::SpdySerializedFrame resp(
1711 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1712 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391713 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411714 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521715 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391716 };
1717
Ryan Sleevib8d7ea02018-05-07 20:01:011718 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:101719 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:571720 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391721 TransactionHelperResult out = helper.output();
1722
robpercival214763f2016-07-01 23:27:011723 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021724 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391725}
1726
1727// Test that a simple HEAD request works.
bncd16676a2016-07-20 16:23:011728TEST_F(SpdyNetworkTransactionTest, Head) {
Bence Békydb3cf652017-10-10 15:22:101729 // Setup the request.
1730 request_.method = "HEAD";
[email protected]d8ef27b2010-08-06 17:34:391731
Ryan Hamilton0239aac2018-05-19 00:03:131732 spdy::SpdyHeaderBlock head_headers(
bncb26024382016-06-29 02:39:451733 spdy_util_.ConstructHeadHeaderBlock(kDefaultUrl, 0));
Ryan Hamilton0239aac2018-05-19 00:03:131734 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyHeaders(
bnc42331402016-07-25 13:36:151735 1, std::move(head_headers), LOWEST, true));
[email protected]d8ef27b2010-08-06 17:34:391736 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411737 CreateMockWrite(req, 0),
[email protected]d8ef27b2010-08-06 17:34:391738 };
1739
Ryan Hamilton0239aac2018-05-19 00:03:131740 spdy::SpdySerializedFrame resp(
1741 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1742 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391743 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411744 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521745 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391746 };
1747
Ryan Sleevib8d7ea02018-05-07 20:01:011748 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:101749 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:571750 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391751 TransactionHelperResult out = helper.output();
1752
robpercival214763f2016-07-01 23:27:011753 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021754 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391755}
1756
[email protected]72552f02009-10-28 15:25:011757// Test that a simple POST works.
bncd16676a2016-07-20 16:23:011758TEST_F(SpdyNetworkTransactionTest, Post) {
Ryan Hamilton0239aac2018-05-19 00:03:131759 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
tombergan5d22c182017-01-11 02:05:351760 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
Ryan Hamilton0239aac2018-05-19 00:03:131761 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141762 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411763 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141764 };
[email protected]72552f02009-10-28 15:25:011765
Ryan Hamilton0239aac2018-05-19 00:03:131766 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]ff57bb82009-11-12 06:52:141767 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411768 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521769 MockRead(ASYNC, 0, 4) // EOF
[email protected]aea80602009-09-18 00:55:081770 };
1771
Ryan Sleevib8d7ea02018-05-07 20:01:011772 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:101773 UsePostRequest();
1774 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:571775 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471776 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011777 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021778 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]aea80602009-09-18 00:55:081779 EXPECT_EQ("hello!", out.response_data);
1780}
1781
[email protected]69e6b4a2012-10-18 08:03:011782// Test that a POST with a file works.
bncd16676a2016-07-20 16:23:011783TEST_F(SpdyNetworkTransactionTest, FilePost) {
Ryan Hamilton0239aac2018-05-19 00:03:131784 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
tombergan5d22c182017-01-11 02:05:351785 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
Ryan Hamilton0239aac2018-05-19 00:03:131786 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011787 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411788 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011789 };
1790
Ryan Hamilton0239aac2018-05-19 00:03:131791 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]69e6b4a2012-10-18 08:03:011792 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411793 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521794 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011795 };
1796
Ryan Sleevib8d7ea02018-05-07 20:01:011797 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:101798 UseFilePostRequest();
1799 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]69e6b4a2012-10-18 08:03:011800 helper.RunToCompletion(&data);
1801 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011802 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021803 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011804 EXPECT_EQ("hello!", out.response_data);
1805}
1806
[email protected]999dd8c2013-11-12 06:45:541807// Test that a POST with a unreadable file fails.
bncd16676a2016-07-20 16:23:011808TEST_F(SpdyNetworkTransactionTest, UnreadableFilePost) {
[email protected]999dd8c2013-11-12 06:45:541809 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521810 MockWrite(ASYNC, 0, 0) // EOF
[email protected]999dd8c2013-11-12 06:45:541811 };
1812 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521813 MockRead(ASYNC, 0, 1) // EOF
[email protected]999dd8c2013-11-12 06:45:541814 };
1815
Ryan Sleevib8d7ea02018-05-07 20:01:011816 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:101817 UseUnreadableFilePostRequest();
1818 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]999dd8c2013-11-12 06:45:541819 helper.RunPreTestSetup();
1820 helper.AddData(&data);
1821 helper.RunDefaultTest();
1822
1823 base::RunLoop().RunUntilIdle();
1824 helper.VerifyDataNotConsumed();
robpercival214763f2016-07-01 23:27:011825 EXPECT_THAT(helper.output().rv, IsError(ERR_ACCESS_DENIED));
[email protected]999dd8c2013-11-12 06:45:541826}
1827
[email protected]69e6b4a2012-10-18 08:03:011828// Test that a complex POST works.
bncd16676a2016-07-20 16:23:011829TEST_F(SpdyNetworkTransactionTest, ComplexPost) {
Ryan Hamilton0239aac2018-05-19 00:03:131830 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
tombergan5d22c182017-01-11 02:05:351831 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
Ryan Hamilton0239aac2018-05-19 00:03:131832 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011833 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411834 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011835 };
1836
Ryan Hamilton0239aac2018-05-19 00:03:131837 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]69e6b4a2012-10-18 08:03:011838 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411839 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521840 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011841 };
1842
Ryan Sleevib8d7ea02018-05-07 20:01:011843 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:101844 UseComplexPostRequest();
1845 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]69e6b4a2012-10-18 08:03:011846 helper.RunToCompletion(&data);
1847 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011848 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021849 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011850 EXPECT_EQ("hello!", out.response_data);
1851}
1852
[email protected]0c9bf872011-03-04 17:53:221853// Test that a chunked POST works.
bncd16676a2016-07-20 16:23:011854TEST_F(SpdyNetworkTransactionTest, ChunkedPost) {
Ryan Hamilton0239aac2018-05-19 00:03:131855 spdy::SpdySerializedFrame req(
1856 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
1857 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]0c9bf872011-03-04 17:53:221858 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411859 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
[email protected]0c9bf872011-03-04 17:53:221860 };
1861
Ryan Hamilton0239aac2018-05-19 00:03:131862 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]0c9bf872011-03-04 17:53:221863 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411864 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521865 MockRead(ASYNC, 0, 4) // EOF
[email protected]0c9bf872011-03-04 17:53:221866 };
1867
Ryan Sleevib8d7ea02018-05-07 20:01:011868 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:101869 UseChunkedPostRequest();
1870 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]34b345f92013-02-22 03:27:261871
1872 // These chunks get merged into a single frame when being sent.
1873 const int kFirstChunkSize = kUploadDataSize/2;
mmenkecbc2b712014-10-09 20:29:071874 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1875 upload_chunked_data_stream()->AppendData(
[email protected]34b345f92013-02-22 03:27:261876 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1877
[email protected]dd54bd82012-07-19 23:44:571878 helper.RunToCompletion(&data);
[email protected]0c9bf872011-03-04 17:53:221879 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011880 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021881 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261882 EXPECT_EQ(kUploadData, out.response_data);
1883}
1884
1885// Test that a chunked POST works with chunks appended after transaction starts.
bncd16676a2016-07-20 16:23:011886TEST_F(SpdyNetworkTransactionTest, DelayedChunkedPost) {
Ryan Hamilton0239aac2018-05-19 00:03:131887 spdy::SpdySerializedFrame req(
1888 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
1889 spdy::SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false));
1890 spdy::SpdySerializedFrame chunk2(spdy_util_.ConstructSpdyDataFrame(1, false));
1891 spdy::SpdySerializedFrame chunk3(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]34b345f92013-02-22 03:27:261892 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411893 CreateMockWrite(req, 0), CreateMockWrite(chunk1, 1),
1894 CreateMockWrite(chunk2, 2), CreateMockWrite(chunk3, 3),
[email protected]34b345f92013-02-22 03:27:261895 };
1896
Ryan Hamilton0239aac2018-05-19 00:03:131897 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]34b345f92013-02-22 03:27:261898 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411899 CreateMockRead(resp, 4), CreateMockRead(chunk1, 5),
1900 CreateMockRead(chunk2, 6), CreateMockRead(chunk3, 7),
rch08e3aa3e2015-05-16 14:27:521901 MockRead(ASYNC, 0, 8) // EOF
[email protected]34b345f92013-02-22 03:27:261902 };
1903
Ryan Sleevib8d7ea02018-05-07 20:01:011904 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:101905 UseChunkedPostRequest();
1906 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]34b345f92013-02-22 03:27:261907
mmenkecbc2b712014-10-09 20:29:071908 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]34b345f92013-02-22 03:27:261909
1910 helper.RunPreTestSetup();
1911 helper.AddData(&data);
1912 ASSERT_TRUE(helper.StartDefaultTest());
1913
[email protected]fc9d88472013-08-14 02:31:171914 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071915 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]fc9d88472013-08-14 02:31:171916 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071917 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]34b345f92013-02-22 03:27:261918
1919 helper.FinishDefaultTest();
1920 helper.VerifyDataConsumed();
1921
Bence Béky4e83f492018-05-13 23:14:251922 std::string expected_response;
[email protected]34b345f92013-02-22 03:27:261923 expected_response += kUploadData;
1924 expected_response += kUploadData;
1925 expected_response += kUploadData;
1926
1927 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011928 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021929 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261930 EXPECT_EQ(expected_response, out.response_data);
[email protected]0c9bf872011-03-04 17:53:221931}
1932
[email protected]a33cad2b62010-07-30 22:24:391933// Test that a POST without any post data works.
bncd16676a2016-07-20 16:23:011934TEST_F(SpdyNetworkTransactionTest, NullPost) {
Bence Békydb3cf652017-10-10 15:22:101935 // Setup the request.
1936 request_.method = "POST";
[email protected]a33cad2b62010-07-30 22:24:391937 // Create an empty UploadData.
Bence Békydb3cf652017-10-10 15:22:101938 request_.upload_data_stream = nullptr;
[email protected]a33cad2b62010-07-30 22:24:391939
[email protected]329b68b2012-11-14 17:54:271940 // When request.upload_data_stream is NULL for post, content-length is
[email protected]a33cad2b62010-07-30 22:24:391941 // expected to be 0.
Ryan Hamilton0239aac2018-05-19 00:03:131942 spdy::SpdyHeaderBlock req_block(
bncb26024382016-06-29 02:39:451943 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
Ryan Hamilton0239aac2018-05-19 00:03:131944 spdy::SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151945 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block), LOWEST, true));
[email protected]d2c1a97b2014-03-03 19:25:091946
[email protected]a33cad2b62010-07-30 22:24:391947 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411948 CreateMockWrite(req, 0),
[email protected]a33cad2b62010-07-30 22:24:391949 };
1950
Ryan Hamilton0239aac2018-05-19 00:03:131951 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
1952 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]a33cad2b62010-07-30 22:24:391953 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411954 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521955 MockRead(ASYNC, 0, 3) // EOF
[email protected]a33cad2b62010-07-30 22:24:391956 };
1957
Ryan Sleevib8d7ea02018-05-07 20:01:011958 SequencedSocketData data(reads, writes);
[email protected]a33cad2b62010-07-30 22:24:391959
Bence Békydb3cf652017-10-10 15:22:101960 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:571961 helper.RunToCompletion(&data);
[email protected]a33cad2b62010-07-30 22:24:391962 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011963 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021964 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]a33cad2b62010-07-30 22:24:391965 EXPECT_EQ("hello!", out.response_data);
1966}
1967
[email protected]edd3b0a52009-11-24 18:56:361968// Test that a simple POST works.
bncd16676a2016-07-20 16:23:011969TEST_F(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]329b68b2012-11-14 17:54:271970 // Create an empty UploadDataStream.
danakjaee3e1ec2016-04-16 00:23:181971 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221972 ElementsUploadDataStream stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271973
Bence Békydb3cf652017-10-10 15:22:101974 // Setup the request.
1975 request_.method = "POST";
1976 request_.upload_data_stream = &stream;
[email protected]edd3b0a52009-11-24 18:56:361977
Avi Drissman13fc8932015-12-20 04:40:461978 const uint64_t kContentLength = 0;
[email protected]d2c1a97b2014-03-03 19:25:091979
Ryan Hamilton0239aac2018-05-19 00:03:131980 spdy::SpdyHeaderBlock req_block(
bncb26024382016-06-29 02:39:451981 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kContentLength));
Ryan Hamilton0239aac2018-05-19 00:03:131982 spdy::SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151983 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block), LOWEST, true));
[email protected]d2c1a97b2014-03-03 19:25:091984
[email protected]edd3b0a52009-11-24 18:56:361985 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411986 CreateMockWrite(req, 0),
[email protected]edd3b0a52009-11-24 18:56:361987 };
1988
Ryan Hamilton0239aac2018-05-19 00:03:131989 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
1990 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361991 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411992 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521993 MockRead(ASYNC, 0, 3) // EOF
[email protected]edd3b0a52009-11-24 18:56:361994 };
1995
Ryan Sleevib8d7ea02018-05-07 20:01:011996 SequencedSocketData data(reads, writes);
[email protected]bf2491a92009-11-29 16:39:481997
Bence Békydb3cf652017-10-10 15:22:101998 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:571999 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:472000 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:012001 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:022002 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]edd3b0a52009-11-24 18:56:362003 EXPECT_EQ("hello!", out.response_data);
2004}
2005
[email protected]35c3fc732014-02-15 00:16:072006// While we're doing a post, the server sends the reply before upload completes.
bncd16676a2016-07-20 16:23:012007TEST_F(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
Ryan Hamilton0239aac2018-05-19 00:03:132008 spdy::SpdySerializedFrame req(
2009 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
2010 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]35c3fc732014-02-15 00:16:072011 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412012 CreateMockWrite(req, 0), CreateMockWrite(body, 3),
[email protected]35c3fc732014-02-15 00:16:072013 };
Ryan Hamilton0239aac2018-05-19 00:03:132014 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]a5566f9702010-05-05 22:25:432015 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412016 CreateMockRead(resp, 1), CreateMockRead(body, 2),
2017 MockRead(ASYNC, 0, 4) // EOF
[email protected]a5566f9702010-05-05 22:25:432018 };
2019
[email protected]35c3fc732014-02-15 00:16:072020 // Write the request headers, and read the complete response
2021 // while still waiting for chunked request data.
Ryan Sleevib8d7ea02018-05-07 20:01:012022 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:102023 UseChunkedPostRequest();
2024 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]c92f4b4542012-07-26 23:53:212025 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:332026 helper.AddData(&data);
[email protected]c92f4b4542012-07-26 23:53:212027
[email protected]35c3fc732014-02-15 00:16:072028 ASSERT_TRUE(helper.StartDefaultTest());
[email protected]c92f4b4542012-07-26 23:53:212029
maksim.sisov8d2df66d2016-06-20 07:07:112030 base::RunLoop().RunUntilIdle();
mmenke666a6fea2015-12-19 04:16:332031
bnc42331402016-07-25 13:36:152032 // Process the request headers, response headers, and response body.
[email protected]35c3fc732014-02-15 00:16:072033 // The request body is still in flight.
[email protected]35c3fc732014-02-15 00:16:072034 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
bnc84e7fb52015-12-02 11:50:022035 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]35c3fc732014-02-15 00:16:072036
2037 // Finish sending the request body.
mmenkecbc2b712014-10-09 20:29:072038 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
maksim.sisov8d2df66d2016-06-20 07:07:112039 helper.WaitForCallbackToComplete();
robpercival214763f2016-07-01 23:27:012040 EXPECT_THAT(helper.output().rv, IsOk());
[email protected]35c3fc732014-02-15 00:16:072041
Bence Béky4e83f492018-05-13 23:14:252042 std::string response_body;
robpercival214763f2016-07-01 23:27:012043 EXPECT_THAT(ReadTransaction(helper.trans(), &response_body), IsOk());
[email protected]35c3fc732014-02-15 00:16:072044 EXPECT_EQ(kUploadData, response_body);
bnceb9aa7112017-01-05 01:03:462045
2046 // Finish async network reads/writes.
2047 base::RunLoop().RunUntilIdle();
[email protected]35c3fc732014-02-15 00:16:072048 helper.VerifyDataConsumed();
[email protected]a5566f9702010-05-05 22:25:432049}
2050
[email protected]f9a26d72010-08-03 18:07:132051// The client upon cancellation tries to send a RST_STREAM frame. The mock
2052// socket causes the TCP write to return zero. This test checks that the client
2053// tries to queue up the RST_STREAM frame again.
bncd16676a2016-07-20 16:23:012054TEST_F(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
Ryan Hamilton0239aac2018-05-19 00:03:132055 spdy::SpdySerializedFrame req(
2056 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2057 spdy::SpdySerializedFrame rst(
2058 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]f9a26d72010-08-03 18:07:132059 MockWrite writes[] = {
Raul Tambre94493c652019-03-11 17:18:352060 CreateMockWrite(req, 0, SYNCHRONOUS),
2061 MockWrite(SYNCHRONOUS, nullptr, 0, 2),
bncdf80d44fd2016-07-15 20:27:412062 CreateMockWrite(rst, 3, SYNCHRONOUS),
[email protected]f9a26d72010-08-03 18:07:132063 };
2064
Ryan Hamilton0239aac2018-05-19 00:03:132065 spdy::SpdySerializedFrame resp(
2066 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f9a26d72010-08-03 18:07:132067 MockRead reads[] = {
Raul Tambre94493c652019-03-11 17:18:352068 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, nullptr, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:132069 };
2070
Ryan Sleevib8d7ea02018-05-07 20:01:012071 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:102072 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]f9a26d72010-08-03 18:07:132073 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:332074 helper.AddData(&data);
bnc4d782f492016-08-18 13:50:002075 helper.StartDefaultTest();
2076 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
[email protected]f9a26d72010-08-03 18:07:132077
bnc4d782f492016-08-18 13:50:002078 helper.WaitForCallbackToComplete();
2079 EXPECT_THAT(helper.output().rv, IsOk());
[email protected]3b7828432010-08-18 18:33:272080
[email protected]f9a26d72010-08-03 18:07:132081 helper.ResetTrans();
mmenke666a6fea2015-12-19 04:16:332082 base::RunLoop().RunUntilIdle();
[email protected]3b7828432010-08-18 18:33:272083
[email protected]f9a26d72010-08-03 18:07:132084 helper.VerifyDataConsumed();
2085}
2086
[email protected]93300672009-10-24 13:22:512087// Test that the transaction doesn't crash when we don't have a reply.
bnc42331402016-07-25 13:36:152088TEST_F(SpdyNetworkTransactionTest, ResponseWithoutHeaders) {
Ryan Hamilton0239aac2018-05-19 00:03:132089 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:142090 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412091 CreateMockRead(body, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]93300672009-10-24 13:22:512092 };
2093
Ryan Hamilton0239aac2018-05-19 00:03:132094 spdy::SpdySerializedFrame req(
2095 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2096 spdy::SpdySerializedFrame rst(
2097 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
rch08e3aa3e2015-05-16 14:27:522098 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412099 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
rch08e3aa3e2015-05-16 14:27:522100 };
Ryan Sleevib8d7ea02018-05-07 20:01:012101 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:102102 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:572103 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:472104 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:012105 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]93300672009-10-24 13:22:512106}
2107
[email protected]d30022352010-06-24 19:17:582108// Test that the transaction doesn't crash when we get two replies on the same
2109// stream ID. See http://crbug.com/45639.
bncd16676a2016-07-20 16:23:012110TEST_F(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
Ryan Hamilton0239aac2018-05-19 00:03:132111 spdy::SpdySerializedFrame req(
2112 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2113 spdy::SpdySerializedFrame rst(
2114 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
[email protected]2aeef782013-06-21 18:30:562115 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412116 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
[email protected]2aeef782013-06-21 18:30:562117 };
[email protected]d30022352010-06-24 19:17:582118
Ryan Hamilton0239aac2018-05-19 00:03:132119 spdy::SpdySerializedFrame resp0(
2120 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2121 spdy::SpdySerializedFrame resp1(
2122 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2123 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d30022352010-06-24 19:17:582124 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412125 CreateMockRead(resp0, 1), CreateMockRead(resp1, 2),
2126 CreateMockRead(body, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]d30022352010-06-24 19:17:582127 };
2128
Ryan Sleevib8d7ea02018-05-07 20:01:012129 SequencedSocketData data(reads, writes);
[email protected]d30022352010-06-24 19:17:582130
Bence Békydb3cf652017-10-10 15:22:102131 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]3caf5542010-07-16 15:19:472132 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572133 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472134
2135 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:582136
[email protected]49639fa2011-12-20 23:22:412137 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:102138 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:012139 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d30022352010-06-24 19:17:582140 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012141 EXPECT_THAT(rv, IsOk());
[email protected]d30022352010-06-24 19:17:582142
2143 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522144 ASSERT_TRUE(response);
2145 EXPECT_TRUE(response->headers);
[email protected]d30022352010-06-24 19:17:582146 EXPECT_TRUE(response->was_fetched_via_spdy);
Bence Béky4e83f492018-05-13 23:14:252147 std::string response_data;
[email protected]3caf5542010-07-16 15:19:472148 rv = ReadTransaction(trans, &response_data);
robpercival214763f2016-07-01 23:27:012149 EXPECT_THAT(rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]3caf5542010-07-16 15:19:472150
2151 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:582152}
2153
bncd16676a2016-07-20 16:23:012154TEST_F(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252155 // Construct the request.
Ryan Hamilton0239aac2018-05-19 00:03:132156 spdy::SpdySerializedFrame req(
2157 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2158 spdy::SpdySerializedFrame rst(
2159 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252160 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412161 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
[email protected]b3503002012-03-27 04:57:252162 };
2163
2164 const char* const headers[] = {
[email protected]513963e2013-06-15 01:53:042165 "transfer-encoding", "chunked"
[email protected]b3503002012-03-27 04:57:252166 };
Ryan Hamilton0239aac2018-05-19 00:03:132167 spdy::SpdySerializedFrame resp(
2168 spdy_util_.ConstructSpdyGetReply(headers, 1, 1));
2169 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b3503002012-03-27 04:57:252170 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412171 CreateMockRead(resp, 1), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:522172 MockRead(ASYNC, 0, 4) // EOF
[email protected]b3503002012-03-27 04:57:252173 };
2174
Ryan Sleevib8d7ea02018-05-07 20:01:012175 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:102176 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:572177 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252178 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:012179 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252180
2181 helper.session()->spdy_session_pool()->CloseAllSessions();
2182 helper.VerifyDataConsumed();
2183}
2184
bncd16676a2016-07-20 16:23:012185TEST_F(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252186 // Construct the request.
Ryan Hamilton0239aac2018-05-19 00:03:132187 spdy::SpdySerializedFrame req(
2188 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2189 spdy::SpdySerializedFrame priority(
tombergan5d22c182017-01-11 02:05:352190 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
Ryan Hamilton0239aac2018-05-19 00:03:132191 spdy::SpdySerializedFrame rst(
2192 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252193 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352194 CreateMockWrite(req, 0), CreateMockWrite(priority, 3),
2195 CreateMockWrite(rst, 5),
[email protected]b3503002012-03-27 04:57:252196 };
2197
Ryan Hamilton0239aac2018-05-19 00:03:132198 spdy::SpdySerializedFrame resp(
2199 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]513963e2013-06-15 01:53:042200 const char* const headers[] = {
2201 "transfer-encoding", "chunked"
2202 };
Ryan Hamilton0239aac2018-05-19 00:03:132203 spdy::SpdySerializedFrame push(spdy_util_.ConstructSpdyPush(
Avi Drissman4365a4782018-12-28 19:26:242204 headers, base::size(headers) / 2, 2, 1, "https://www.example.org/1"));
Ryan Hamilton0239aac2018-05-19 00:03:132205 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b3503002012-03-27 04:57:252206 MockRead reads[] = {
tombergan5d22c182017-01-11 02:05:352207 CreateMockRead(resp, 1), CreateMockRead(push, 2), CreateMockRead(body, 4),
2208 MockRead(ASYNC, 0, 6) // EOF
[email protected]b3503002012-03-27 04:57:252209 };
2210
Ryan Sleevib8d7ea02018-05-07 20:01:012211 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:102212 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:572213 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252214 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:012215 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:022216 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b3503002012-03-27 04:57:252217 EXPECT_EQ("hello!", out.response_data);
2218
2219 helper.session()->spdy_session_pool()->CloseAllSessions();
2220 helper.VerifyDataConsumed();
2221}
2222
bncd16676a2016-07-20 16:23:012223TEST_F(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:382224 // Construct the request.
Ryan Hamilton0239aac2018-05-19 00:03:132225 spdy::SpdySerializedFrame req(
2226 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
[email protected]34437af82009-11-06 02:28:492227 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412228 CreateMockWrite(req),
[email protected]34437af82009-11-06 02:28:492229 };
2230
Ryan Hamilton0239aac2018-05-19 00:03:132231 spdy::SpdySerializedFrame resp(
2232 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]34437af82009-11-06 02:28:492233 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412234 CreateMockRead(resp),
2235 // This following read isn't used by the test, except during the
2236 // RunUntilIdle() call at the end since the SpdySession survives the
2237 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2238 // MockRead will do here.
2239 MockRead(ASYNC, 0, 0) // EOF
[email protected]34437af82009-11-06 02:28:492240 };
2241
Ryan Sleevib8d7ea02018-05-07 20:01:012242 StaticSocketDataProvider data(reads, writes);
[email protected]3caf5542010-07-16 15:19:472243
Bence Békydb3cf652017-10-10 15:22:102244 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]3caf5542010-07-16 15:19:472245 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:582246 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472247 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:492248
[email protected]49639fa2011-12-20 23:22:412249 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:102250 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:012251 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3caf5542010-07-16 15:19:472252 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:492253
[email protected]30c942b2010-07-21 16:59:592254 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:492255 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:172256 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472257 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:492258}
[email protected]72552f02009-10-28 15:25:012259
[email protected]6c6ea172010-07-27 20:04:032260// Verify that the client sends a Rst Frame upon cancelling the stream.
bncd16676a2016-07-20 16:23:012261TEST_F(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
Ryan Hamilton0239aac2018-05-19 00:03:132262 spdy::SpdySerializedFrame req(
2263 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2264 spdy::SpdySerializedFrame rst(
2265 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]6c6ea172010-07-27 20:04:032266 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412267 CreateMockWrite(req, 0, SYNCHRONOUS),
2268 CreateMockWrite(rst, 2, SYNCHRONOUS),
[email protected]6c6ea172010-07-27 20:04:032269 };
2270
Ryan Hamilton0239aac2018-05-19 00:03:132271 spdy::SpdySerializedFrame resp(
2272 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]6c6ea172010-07-27 20:04:032273 MockRead reads[] = {
Raul Tambre94493c652019-03-11 17:18:352274 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, nullptr, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:032275 };
2276
Ryan Sleevib8d7ea02018-05-07 20:01:012277 SequencedSocketData data(reads, writes);
[email protected]6c6ea172010-07-27 20:04:032278
Bence Békydb3cf652017-10-10 15:22:102279 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]6c6ea172010-07-27 20:04:032280 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:332281 helper.AddData(&data);
[email protected]6c6ea172010-07-27 20:04:032282 HttpNetworkTransaction* trans = helper.trans();
2283
[email protected]49639fa2011-12-20 23:22:412284 TestCompletionCallback callback;
[email protected]6c6ea172010-07-27 20:04:032285
Bence Békydb3cf652017-10-10 15:22:102286 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:012287 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]6c6ea172010-07-27 20:04:032288
[email protected]3b7828432010-08-18 18:33:272289 helper.ResetTrans();
mmenke666a6fea2015-12-19 04:16:332290 base::RunLoop().RunUntilIdle();
[email protected]3b7828432010-08-18 18:33:272291
[email protected]6c6ea172010-07-27 20:04:032292 helper.VerifyDataConsumed();
2293}
2294
[email protected]b278eb72010-07-09 20:17:002295// Verify that the client can correctly deal with the user callback attempting
2296// to start another transaction on a session that is closing down. See
2297// http://crbug.com/47455
bncd16676a2016-07-20 16:23:012298TEST_F(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
Ryan Hamilton0239aac2018-05-19 00:03:132299 spdy::SpdySerializedFrame req(
2300 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:412301 MockWrite writes[] = {CreateMockWrite(req)};
bnceb9aa7112017-01-05 01:03:462302 MockWrite writes2[] = {CreateMockWrite(req, 0),
2303 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]b278eb72010-07-09 20:17:002304
[email protected]cbdd73162013-03-18 23:27:332305 // The indicated length of this frame is longer than its actual length. When
2306 // the session receives an empty frame after this one, it shuts down the
[email protected]b278eb72010-07-09 20:17:002307 // session, and calls the read callback with the incomplete data.
Avi Drissman13fc8932015-12-20 04:40:462308 const uint8_t kGetBodyFrame2[] = {
2309 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
2310 0x07, 'h', 'e', 'l', 'l', 'o', '!',
[email protected]b278eb72010-07-09 20:17:002311 };
2312
Ryan Hamilton0239aac2018-05-19 00:03:132313 spdy::SpdySerializedFrame resp(
2314 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]b278eb72010-07-09 20:17:002315 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412316 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:092317 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2318 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
Avi Drissman4365a4782018-12-28 19:26:242319 base::size(kGetBodyFrame2), 3),
rch32320842015-05-16 15:57:092320 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
Raul Tambre94493c652019-03-11 17:18:352321 MockRead(ASYNC, nullptr, 0, 5), // EOF
[email protected]b278eb72010-07-09 20:17:002322 };
2323 MockRead reads2[] = {
Raul Tambre94493c652019-03-11 17:18:352324 CreateMockRead(resp, 1), MockRead(ASYNC, nullptr, 0, 2), // EOF
[email protected]b278eb72010-07-09 20:17:002325 };
2326
Ryan Sleevib8d7ea02018-05-07 20:01:012327 SequencedSocketData data(reads, writes);
2328 SequencedSocketData data2(reads2, writes2);
[email protected]3caf5542010-07-16 15:19:472329
Bence Békydb3cf652017-10-10 15:22:102330 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]e3ebba0f2010-08-05 17:59:582331 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572332 helper.AddData(&data);
2333 helper.AddData(&data2);
[email protected]3caf5542010-07-16 15:19:472334 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002335
2336 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412337 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:102338 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:012339 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b278eb72010-07-09 20:17:002340 rv = callback.WaitForResult();
2341
[email protected]b278eb72010-07-09 20:17:002342 const int kSize = 3000;
Victor Costan9c7302b2018-08-27 16:39:442343 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kSize);
[email protected]49639fa2011-12-20 23:22:412344 rv = trans->Read(
rchebf12982015-04-10 01:15:002345 buf.get(), kSize,
[email protected]513963e2013-06-15 01:53:042346 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
Bence Békyd3dde832017-09-19 19:02:312347 helper.session(), default_url_, log_));
robpercival214763f2016-07-01 23:27:012348 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3caf5542010-07-16 15:19:472349 // This forces an err_IO_pending, which sets the callback.
mmenkee24011922015-12-17 22:12:592350 data.Resume();
2351 data.RunUntilPaused();
2352
[email protected]3caf5542010-07-16 15:19:472353 // This finishes the read.
mmenkee24011922015-12-17 22:12:592354 data.Resume();
2355 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472356 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002357}
2358
Mostyn Bramley-Moore699c5312018-05-01 10:48:092359// Verify that the client can correctly deal with the user callback deleting
2360// the transaction. Failures will usually be flagged by thread and/or memory
2361// checking tools. See http://crbug.com/46925
bncd16676a2016-07-20 16:23:012362TEST_F(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
Ryan Hamilton0239aac2018-05-19 00:03:132363 spdy::SpdySerializedFrame req(
2364 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:412365 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]9be804c82010-06-24 17:59:462366
Ryan Hamilton0239aac2018-05-19 00:03:132367 spdy::SpdySerializedFrame resp(
2368 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2369 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462370 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412371 CreateMockRead(resp, 1),
Raul Tambre94493c652019-03-11 17:18:352372 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2373 CreateMockRead(body, 3), MockRead(ASYNC, nullptr, 0, 4), // EOF
[email protected]9be804c82010-06-24 17:59:462374 };
2375
Ryan Sleevib8d7ea02018-05-07 20:01:012376 SequencedSocketData data(reads, writes);
[email protected]3caf5542010-07-16 15:19:472377
Bence Békydb3cf652017-10-10 15:22:102378 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]3caf5542010-07-16 15:19:472379 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572380 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472381 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462382
2383 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412384 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:102385 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:012386 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9be804c82010-06-24 17:59:462387 rv = callback.WaitForResult();
2388
2389 // Setup a user callback which will delete the session, and clear out the
2390 // memory holding the stream object. Note that the callback deletes trans.
[email protected]9be804c82010-06-24 17:59:462391 const int kSize = 3000;
Victor Costan9c7302b2018-08-27 16:39:442392 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kSize);
[email protected]49639fa2011-12-20 23:22:412393 rv = trans->Read(
[email protected]90499482013-06-01 00:39:502394 buf.get(),
2395 kSize,
[email protected]513963e2013-06-15 01:53:042396 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
[email protected]49639fa2011-12-20 23:22:412397 base::Unretained(&helper)));
robpercival214763f2016-07-01 23:27:012398 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
mmenkee24011922015-12-17 22:12:592399 data.Resume();
[email protected]9be804c82010-06-24 17:59:462400
2401 // Finish running rest of tasks.
[email protected]fc9d88472013-08-14 02:31:172402 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472403 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462404}
2405
allada71b2efb2016-09-09 04:57:482406TEST_F(SpdyNetworkTransactionTest, TestRawHeaderSizeSuccessfullRequest) {
Ryan Hamilton0239aac2018-05-19 00:03:132407 spdy::SpdyHeaderBlock headers(
2408 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
allada71b2efb2016-09-09 04:57:482409 headers["user-agent"] = "";
2410 headers["accept-encoding"] = "gzip, deflate";
2411
Ryan Hamilton0239aac2018-05-19 00:03:132412 spdy::SpdySerializedFrame req(
allada71b2efb2016-09-09 04:57:482413 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
2414 MockWrite writes[] = {
2415 CreateMockWrite(req, 0),
2416 };
2417
Ryan Hamilton0239aac2018-05-19 00:03:132418 spdy::SpdySerializedFrame resp(
2419 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
allada71b2efb2016-09-09 04:57:482420
Ryan Hamilton0239aac2018-05-19 00:03:132421 spdy::SpdySerializedFrame response_body_frame(
Bence Békyd74f4382018-02-20 18:26:192422 spdy_util_.ConstructSpdyDataFrame(1, "should not include", true));
allada71b2efb2016-09-09 04:57:482423
2424 MockRead response_headers(CreateMockRead(resp, 1));
2425 MockRead reads[] = {
2426 response_headers, CreateMockRead(response_body_frame, 2),
Raul Tambre94493c652019-03-11 17:18:352427 MockRead(ASYNC, nullptr, 0, 3) // EOF
allada71b2efb2016-09-09 04:57:482428 };
Ryan Sleevib8d7ea02018-05-07 20:01:012429 SequencedSocketData data(reads, writes);
allada71b2efb2016-09-09 04:57:482430
2431 TestDelegate delegate;
2432 SpdyURLRequestContext spdy_url_request_context;
2433 TestNetworkDelegate network_delegate;
2434 spdy_url_request_context.set_network_delegate(&network_delegate);
2435 SSLSocketDataProvider ssl_data(ASYNC, OK);
2436 ssl_data.next_proto = kProtoHTTP2;
2437
2438 std::unique_ptr<URLRequest> request(spdy_url_request_context.CreateRequest(
rhalavati9ebaba7e2017-04-27 06:16:292439 GURL(kDefaultUrl), DEFAULT_PRIORITY, &delegate,
2440 TRAFFIC_ANNOTATION_FOR_TESTS));
allada71b2efb2016-09-09 04:57:482441 spdy_url_request_context.socket_factory().AddSSLSocketDataProvider(&ssl_data);
2442 spdy_url_request_context.socket_factory().AddSocketDataProvider(&data);
2443
2444 request->Start();
2445 base::RunLoop().Run();
2446
2447 EXPECT_LT(0, request->GetTotalSentBytes());
2448 EXPECT_LT(0, request->GetTotalReceivedBytes());
2449 EXPECT_EQ(network_delegate.total_network_bytes_sent(),
2450 request->GetTotalSentBytes());
2451 EXPECT_EQ(network_delegate.total_network_bytes_received(),
2452 request->GetTotalReceivedBytes());
2453 EXPECT_EQ(response_headers.data_len, request->raw_header_size());
2454 EXPECT_TRUE(data.AllReadDataConsumed());
2455 EXPECT_TRUE(data.AllWriteDataConsumed());
2456}
2457
2458TEST_F(SpdyNetworkTransactionTest,
2459 TestRawHeaderSizeSuccessfullPushHeadersFirst) {
Ryan Hamilton0239aac2018-05-19 00:03:132460 spdy::SpdyHeaderBlock headers(
2461 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
allada71b2efb2016-09-09 04:57:482462 headers["user-agent"] = "";
2463 headers["accept-encoding"] = "gzip, deflate";
2464
Ryan Hamilton0239aac2018-05-19 00:03:132465 spdy::SpdySerializedFrame req(
allada71b2efb2016-09-09 04:57:482466 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:132467 spdy::SpdySerializedFrame priority(
tombergan5d22c182017-01-11 02:05:352468 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
allada71b2efb2016-09-09 04:57:482469 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352470 CreateMockWrite(req, 0), CreateMockWrite(priority, 2),
allada71b2efb2016-09-09 04:57:482471 };
2472
Ryan Hamilton0239aac2018-05-19 00:03:132473 spdy::SpdySerializedFrame resp(
2474 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2475 spdy::SpdySerializedFrame response_body_frame(
Bence Békyd74f4382018-02-20 18:26:192476 spdy_util_.ConstructSpdyDataFrame(1, "should not include", true));
allada71b2efb2016-09-09 04:57:482477
Ryan Hamilton0239aac2018-05-19 00:03:132478 spdy::SpdyHeaderBlock push_headers;
bncc055fa32017-06-19 13:44:422479 push_headers[":method"] = "GET";
Bence Béky4e83f492018-05-13 23:14:252480 spdy_util_.AddUrlToHeaderBlock(std::string(kDefaultUrl) + "b.dat",
allada71b2efb2016-09-09 04:57:482481 &push_headers);
2482
Ryan Hamilton0239aac2018-05-19 00:03:132483 spdy::SpdySerializedFrame push_init_frame(
Bence Békyf1d78522018-01-11 01:16:502484 spdy_util_.ConstructSpdyPushPromise(1, 2, std::move(push_headers)));
allada71b2efb2016-09-09 04:57:482485
Ryan Hamilton0239aac2018-05-19 00:03:132486 spdy::SpdySerializedFrame push_headers_frame(
allada71b2efb2016-09-09 04:57:482487 spdy_util_.ConstructSpdyPushHeaders(2, nullptr, 0));
2488
Ryan Hamilton0239aac2018-05-19 00:03:132489 spdy::SpdySerializedFrame push_body_frame(
Bence Békyd74f4382018-02-20 18:26:192490 spdy_util_.ConstructSpdyDataFrame(2, "should not include either", false));
allada71b2efb2016-09-09 04:57:482491
2492 MockRead push_init_read(CreateMockRead(push_init_frame, 1));
tombergan5d22c182017-01-11 02:05:352493 MockRead response_headers(CreateMockRead(resp, 5));
allada71b2efb2016-09-09 04:57:482494 // raw_header_size() will contain the size of the push promise frame
2495 // initialization.
2496 int expected_response_headers_size =
2497 response_headers.data_len + push_init_read.data_len;
2498
2499 MockRead reads[] = {
2500 push_init_read,
tombergan5d22c182017-01-11 02:05:352501 CreateMockRead(push_headers_frame, 3),
2502 CreateMockRead(push_body_frame, 4),
allada71b2efb2016-09-09 04:57:482503 response_headers,
tombergan5d22c182017-01-11 02:05:352504 CreateMockRead(response_body_frame, 6),
2505 MockRead(ASYNC, 0, 7) // EOF
allada71b2efb2016-09-09 04:57:482506 };
2507
Ryan Sleevib8d7ea02018-05-07 20:01:012508 SequencedSocketData data(reads, writes);
allada71b2efb2016-09-09 04:57:482509
2510 TestDelegate delegate;
2511 SpdyURLRequestContext spdy_url_request_context;
2512 TestNetworkDelegate network_delegate;
2513 spdy_url_request_context.set_network_delegate(&network_delegate);
2514 SSLSocketDataProvider ssl_data(ASYNC, OK);
2515 ssl_data.next_proto = kProtoHTTP2;
2516
2517 std::unique_ptr<URLRequest> request(spdy_url_request_context.CreateRequest(
rhalavati9ebaba7e2017-04-27 06:16:292518 GURL(kDefaultUrl), DEFAULT_PRIORITY, &delegate,
2519 TRAFFIC_ANNOTATION_FOR_TESTS));
allada71b2efb2016-09-09 04:57:482520 spdy_url_request_context.socket_factory().AddSSLSocketDataProvider(&ssl_data);
2521 spdy_url_request_context.socket_factory().AddSocketDataProvider(&data);
2522
2523 request->Start();
2524 base::RunLoop().Run();
2525
2526 EXPECT_LT(0, request->GetTotalSentBytes());
2527 EXPECT_LT(0, request->GetTotalReceivedBytes());
2528 EXPECT_EQ(network_delegate.total_network_bytes_sent(),
2529 request->GetTotalSentBytes());
2530 EXPECT_EQ(network_delegate.total_network_bytes_received(),
2531 request->GetTotalReceivedBytes());
2532 EXPECT_EQ(expected_response_headers_size, request->raw_header_size());
2533 EXPECT_TRUE(data.AllReadDataConsumed());
2534 EXPECT_TRUE(data.AllWriteDataConsumed());
2535}
2536
bncf2ba58832017-06-07 00:22:282537TEST_F(SpdyNetworkTransactionTest, RedirectGetRequest) {
2538 SpdyURLRequestContext spdy_url_request_context;
[email protected]e3ebba0f2010-08-05 17:59:582539
bncf2ba58832017-06-07 00:22:282540 SSLSocketDataProvider ssl_provider0(ASYNC, OK);
2541 ssl_provider0.next_proto = kProtoHTTP2;
2542 spdy_url_request_context.socket_factory().AddSSLSocketDataProvider(
2543 &ssl_provider0);
[email protected]e3ebba0f2010-08-05 17:59:582544
Ryan Hamilton0239aac2018-05-19 00:03:132545 spdy::SpdyHeaderBlock headers0(
2546 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bncf2ba58832017-06-07 00:22:282547 headers0["user-agent"] = "";
2548 headers0["accept-encoding"] = "gzip, deflate";
bnc086b39e12016-06-24 13:05:262549
Ryan Hamilton0239aac2018-05-19 00:03:132550 spdy::SpdySerializedFrame req0(
bncf2ba58832017-06-07 00:22:282551 spdy_util_.ConstructSpdyHeaders(1, std::move(headers0), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:132552 spdy::SpdySerializedFrame rst(
2553 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
Shivani Sharmac18f9762017-10-23 16:43:232554 MockWrite writes0[] = {CreateMockWrite(req0, 0), CreateMockWrite(rst, 2)};
bnc086b39e12016-06-24 13:05:262555
bncf2ba58832017-06-07 00:22:282556 const char* const kExtraHeaders[] = {"location",
2557 "https://www.foo.com/index.php"};
Ryan Hamilton0239aac2018-05-19 00:03:132558 spdy::SpdySerializedFrame resp0(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:242559 "301", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Shivani Sharmac18f9762017-10-23 16:43:232560 MockRead reads0[] = {CreateMockRead(resp0, 1), MockRead(ASYNC, 0, 3)};
[email protected]e3ebba0f2010-08-05 17:59:582561
Ryan Sleevib8d7ea02018-05-07 20:01:012562 SequencedSocketData data0(reads0, writes0);
bncf2ba58832017-06-07 00:22:282563 spdy_url_request_context.socket_factory().AddSocketDataProvider(&data0);
[email protected]e3ebba0f2010-08-05 17:59:582564
bncf2ba58832017-06-07 00:22:282565 SSLSocketDataProvider ssl_provider1(ASYNC, OK);
2566 ssl_provider1.next_proto = kProtoHTTP2;
2567 spdy_url_request_context.socket_factory().AddSSLSocketDataProvider(
2568 &ssl_provider1);
[email protected]513963e2013-06-15 01:53:042569
bncf2ba58832017-06-07 00:22:282570 SpdyTestUtil spdy_util1;
Ryan Hamilton0239aac2018-05-19 00:03:132571 spdy::SpdyHeaderBlock headers1(
bncf2ba58832017-06-07 00:22:282572 spdy_util1.ConstructGetHeaderBlock("https://www.foo.com/index.php"));
2573 headers1["user-agent"] = "";
2574 headers1["accept-encoding"] = "gzip, deflate";
Ryan Hamilton0239aac2018-05-19 00:03:132575 spdy::SpdySerializedFrame req1(
bncf2ba58832017-06-07 00:22:282576 spdy_util1.ConstructSpdyHeaders(1, std::move(headers1), LOWEST, true));
2577 MockWrite writes1[] = {CreateMockWrite(req1, 0)};
[email protected]e3ebba0f2010-08-05 17:59:582578
Ryan Hamilton0239aac2018-05-19 00:03:132579 spdy::SpdySerializedFrame resp1(
2580 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
2581 spdy::SpdySerializedFrame body1(spdy_util1.ConstructSpdyDataFrame(1, true));
bncf2ba58832017-06-07 00:22:282582 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
2583 MockRead(ASYNC, 0, 3)};
2584
Ryan Sleevib8d7ea02018-05-07 20:01:012585 SequencedSocketData data1(reads1, writes1);
bncf2ba58832017-06-07 00:22:282586 spdy_url_request_context.socket_factory().AddSocketDataProvider(&data1);
2587
2588 TestDelegate delegate;
bncf2ba58832017-06-07 00:22:282589
2590 std::unique_ptr<URLRequest> request = spdy_url_request_context.CreateRequest(
2591 default_url_, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
2592 request->Start();
Wez0e717112018-06-18 23:09:222593 delegate.RunUntilRedirect();
bncf2ba58832017-06-07 00:22:282594
2595 EXPECT_EQ(1, delegate.received_redirect_count());
2596
Arthur Sonzognib8465ff72019-01-04 18:44:352597 request->FollowDeferredRedirect(base::nullopt /* removed_headers */,
2598 base::nullopt /* modified_headers */);
Wez0e717112018-06-18 23:09:222599 delegate.RunUntilComplete();
bncf2ba58832017-06-07 00:22:282600
2601 EXPECT_EQ(1, delegate.response_started_count());
2602 EXPECT_FALSE(delegate.received_data_before_response());
2603 EXPECT_THAT(delegate.request_status(), IsOk());
2604 EXPECT_EQ("hello!", delegate.data_received());
2605
Wez0e717112018-06-18 23:09:222606 // Pump the message loop to allow read data to be consumed.
2607 base::RunLoop().RunUntilIdle();
2608
bncf2ba58832017-06-07 00:22:282609 EXPECT_TRUE(data0.AllReadDataConsumed());
2610 EXPECT_TRUE(data0.AllWriteDataConsumed());
2611 EXPECT_TRUE(data1.AllReadDataConsumed());
2612 EXPECT_TRUE(data1.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582613}
2614
bncf2ba58832017-06-07 00:22:282615TEST_F(SpdyNetworkTransactionTest, RedirectServerPush) {
bncf2ba58832017-06-07 00:22:282616 const char redirected_url[] = "https://www.foo.com/index.php";
2617 SpdyURLRequestContext spdy_url_request_context;
[email protected]3a8d6852011-03-11 23:43:442618
bncf2ba58832017-06-07 00:22:282619 SSLSocketDataProvider ssl_provider0(ASYNC, OK);
2620 ssl_provider0.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:492621 ssl_provider0.ssl_info.cert =
bncf2ba58832017-06-07 00:22:282622 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
Ryan Sleevi4f832092017-11-21 23:25:492623 ASSERT_TRUE(ssl_provider0.ssl_info.cert);
bncf2ba58832017-06-07 00:22:282624 spdy_url_request_context.socket_factory().AddSSLSocketDataProvider(
2625 &ssl_provider0);
2626
Ryan Hamilton0239aac2018-05-19 00:03:132627 spdy::SpdyHeaderBlock headers0(
2628 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bncf2ba58832017-06-07 00:22:282629 headers0["user-agent"] = "";
2630 headers0["accept-encoding"] = "gzip, deflate";
Ryan Hamilton0239aac2018-05-19 00:03:132631 spdy::SpdySerializedFrame req0(
bncf2ba58832017-06-07 00:22:282632 spdy_util_.ConstructSpdyHeaders(1, std::move(headers0), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:132633 spdy::SpdySerializedFrame priority(
bncf2ba58832017-06-07 00:22:282634 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
Ryan Hamilton0239aac2018-05-19 00:03:132635 spdy::SpdySerializedFrame rst(
2636 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_CANCEL));
bncf2ba58832017-06-07 00:22:282637 MockWrite writes[] = {CreateMockWrite(req0, 0), CreateMockWrite(priority, 3),
2638 CreateMockWrite(rst, 5)};
[email protected]3a8d6852011-03-11 23:43:442639
Ryan Hamilton0239aac2018-05-19 00:03:132640 spdy::SpdySerializedFrame resp0(
2641 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2642 spdy::SpdySerializedFrame push(spdy_util_.ConstructSpdyPush(
Bence Békyd2df6c1c82018-04-20 22:52:012643 nullptr, 0, 2, 1, kPushedUrl, "301", redirected_url));
Ryan Hamilton0239aac2018-05-19 00:03:132644 spdy::SpdySerializedFrame body0(spdy_util_.ConstructSpdyDataFrame(1, true));
bncf2ba58832017-06-07 00:22:282645 MockRead reads[] = {CreateMockRead(resp0, 1), CreateMockRead(push, 2),
2646 CreateMockRead(body0, 4), MockRead(ASYNC, 0, 6)};
[email protected]e3ebba0f2010-08-05 17:59:582647
Ryan Sleevib8d7ea02018-05-07 20:01:012648 SequencedSocketData data0(reads, writes);
bncf2ba58832017-06-07 00:22:282649 spdy_url_request_context.socket_factory().AddSocketDataProvider(&data0);
[email protected]e3ebba0f2010-08-05 17:59:582650
bncf2ba58832017-06-07 00:22:282651 SSLSocketDataProvider ssl_provider1(ASYNC, OK);
2652 ssl_provider1.next_proto = kProtoHTTP2;
2653 spdy_url_request_context.socket_factory().AddSSLSocketDataProvider(
2654 &ssl_provider1);
[email protected]e3ebba0f2010-08-05 17:59:582655
bncf2ba58832017-06-07 00:22:282656 SpdyTestUtil spdy_util1;
Ryan Hamilton0239aac2018-05-19 00:03:132657 spdy::SpdyHeaderBlock headers1(
2658 spdy_util1.ConstructGetHeaderBlock(redirected_url));
bncf2ba58832017-06-07 00:22:282659 headers1["user-agent"] = "";
2660 headers1["accept-encoding"] = "gzip, deflate";
Ryan Hamilton0239aac2018-05-19 00:03:132661 spdy::SpdySerializedFrame req1(
bncf2ba58832017-06-07 00:22:282662 spdy_util1.ConstructSpdyHeaders(1, std::move(headers1), LOWEST, true));
2663 MockWrite writes1[] = {CreateMockWrite(req1, 0)};
[email protected]e3ebba0f2010-08-05 17:59:582664
Ryan Hamilton0239aac2018-05-19 00:03:132665 spdy::SpdySerializedFrame resp1(
2666 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
2667 spdy::SpdySerializedFrame body1(spdy_util1.ConstructSpdyDataFrame(1, true));
bncf2ba58832017-06-07 00:22:282668 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
2669 MockRead(ASYNC, 0, 3)};
[email protected]e3ebba0f2010-08-05 17:59:582670
Ryan Sleevib8d7ea02018-05-07 20:01:012671 SequencedSocketData data1(reads1, writes1);
bncf2ba58832017-06-07 00:22:282672 spdy_url_request_context.socket_factory().AddSocketDataProvider(&data1);
[email protected]e3ebba0f2010-08-05 17:59:582673
bncf2ba58832017-06-07 00:22:282674 TestDelegate delegate0;
2675 std::unique_ptr<URLRequest> request = spdy_url_request_context.CreateRequest(
2676 default_url_, DEFAULT_PRIORITY, &delegate0, TRAFFIC_ANNOTATION_FOR_TESTS);
2677
2678 request->Start();
Wez0e717112018-06-18 23:09:222679 delegate0.RunUntilComplete();
bncf2ba58832017-06-07 00:22:282680
2681 EXPECT_EQ(0, delegate0.received_redirect_count());
2682 EXPECT_EQ("hello!", delegate0.data_received());
2683
2684 TestDelegate delegate1;
2685 std::unique_ptr<URLRequest> request1 = spdy_url_request_context.CreateRequest(
Bence Békyd2df6c1c82018-04-20 22:52:012686 GURL(kPushedUrl), DEFAULT_PRIORITY, &delegate1,
2687 TRAFFIC_ANNOTATION_FOR_TESTS);
bncf2ba58832017-06-07 00:22:282688
bncf2ba58832017-06-07 00:22:282689 request1->Start();
Wez0e717112018-06-18 23:09:222690 delegate1.RunUntilRedirect();
bncf2ba58832017-06-07 00:22:282691 EXPECT_EQ(1, delegate1.received_redirect_count());
2692
Arthur Sonzognib8465ff72019-01-04 18:44:352693 request1->FollowDeferredRedirect(base::nullopt /* removed_headers */,
2694 base::nullopt /* modified_headers */);
Wez0e717112018-06-18 23:09:222695 delegate1.RunUntilComplete();
bncf2ba58832017-06-07 00:22:282696 EXPECT_EQ(1, delegate1.response_started_count());
2697 EXPECT_FALSE(delegate1.received_data_before_response());
2698 EXPECT_EQ(OK, delegate1.request_status());
2699 EXPECT_EQ("hello!", delegate1.data_received());
2700
Wez0e717112018-06-18 23:09:222701 // Pump the message loop to allow read data to be consumed.
2702 base::RunLoop().RunUntilIdle();
2703
bncf2ba58832017-06-07 00:22:282704 EXPECT_TRUE(data0.AllReadDataConsumed());
2705 EXPECT_TRUE(data0.AllWriteDataConsumed());
2706 EXPECT_TRUE(data1.AllReadDataConsumed());
2707 EXPECT_TRUE(data1.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582708}
2709
bncd16676a2016-07-20 16:23:012710TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
Ryan Hamilton0239aac2018-05-19 00:03:132711 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:482712 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:132713 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:352714 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]e3ebba0f2010-08-05 17:59:582715 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352716 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
[email protected]e3ebba0f2010-08-05 17:59:582717 };
2718
Ryan Hamilton0239aac2018-05-19 00:03:132719 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352720 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:132721 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:012722 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
Ryan Hamilton0239aac2018-05-19 00:03:132723 spdy::SpdySerializedFrame stream1_body(
2724 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8a0fc822013-06-27 20:52:432725 const char kPushedData[] = "pushed";
Ryan Hamilton0239aac2018-05-19 00:03:132726 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:192727 spdy_util_.ConstructSpdyDataFrame(2, kPushedData, true));
[email protected]e3ebba0f2010-08-05 17:59:582728 MockRead reads[] = {
tombergan5d22c182017-01-11 02:05:352729 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2730 CreateMockRead(stream1_body, 4), CreateMockRead(stream2_body, 5),
2731 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582732 };
2733
2734 HttpResponseInfo response;
2735 HttpResponseInfo response2;
Bence Béky4e83f492018-05-13 23:14:252736 std::string expected_push_result("pushed");
Ryan Sleevib8d7ea02018-05-07 20:01:012737 SequencedSocketData data(reads, writes);
[email protected]dd54bd82012-07-19 23:44:572738 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032739 &response,
2740 &response2,
2741 expected_push_result);
[email protected]e3ebba0f2010-08-05 17:59:582742
bnc42331402016-07-25 13:36:152743 // Verify the response headers.
wezca1070932016-05-26 20:30:522744 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022745 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582746
2747 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522748 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042749 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582750}
2751
Bence Béky02b906a2018-07-18 21:03:392752// When server push is disabled by
2753// HttpNetworkSession::initial_settings[SETTINGS_ENABLE_PUSH] = 0, verify that
2754// such a setting is sent out in the initial SETTINGS frame, and if the server
2755// creates a pushed stream despite of this, it is immediately reset.
2756TEST_F(SpdyNetworkTransactionTest, ServerPushDisabled) {
Bence Békyda83e052018-07-20 01:03:322757 base::HistogramTester histogram_tester;
2758
Bence Béky02b906a2018-07-18 21:03:392759 spdy::SpdySerializedFrame preface(
2760 const_cast<char*>(spdy::kHttp2ConnectionHeaderPrefix),
2761 spdy::kHttp2ConnectionHeaderPrefixSize,
2762 /* owns_buffer = */ false);
2763
2764 spdy::SettingsMap initial_settings;
2765 initial_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
2766 initial_settings[spdy::SETTINGS_ENABLE_PUSH] = 0;
2767 initial_settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] =
2768 kSpdyMaxConcurrentPushedStreams;
2769 spdy::SpdySerializedFrame initial_settings_frame(
2770 spdy_util_.ConstructSpdySettings(initial_settings));
2771
2772 spdy::SpdySerializedFrame req(
2773 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2774 spdy::SpdySerializedFrame rst(
2775 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
2776
2777 MockWrite writes[] = {CreateMockWrite(preface, 0),
2778 CreateMockWrite(initial_settings_frame, 1),
2779 CreateMockWrite(req, 2), CreateMockWrite(rst, 5)};
2780
2781 spdy::SpdySerializedFrame reply(
2782 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2783 spdy::SpdySerializedFrame push(
2784 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
2785 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
2786 MockRead reads[] = {CreateMockRead(reply, 3), CreateMockRead(push, 4),
2787 CreateMockRead(body, 6), MockRead(ASYNC, OK, 7)};
2788
2789 SequencedSocketData data(reads, writes);
2790
2791 auto session_deps = std::make_unique<SpdySessionDependencies>();
2792 session_deps->http2_settings[spdy::SETTINGS_ENABLE_PUSH] = 0;
2793 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
2794 std::move(session_deps));
2795
2796 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
2797 SpdySessionPoolPeer pool_peer(spdy_session_pool);
2798 pool_peer.SetEnableSendingInitialData(true);
2799
2800 helper.RunToCompletion(&data);
Bence Békyda83e052018-07-20 01:03:322801
2802 histogram_tester.ExpectBucketCount(
2803 "Net.SpdyPushedStreamFate",
2804 static_cast<int>(SpdyPushedStreamFate::kPushDisabled), 1);
2805 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
Bence Béky02b906a2018-07-18 21:03:392806}
2807
Bence Béky5b1e4ce72018-01-11 14:55:152808TEST_F(SpdyNetworkTransactionTest, ServerPushHeadMethod) {
Ryan Hamilton0239aac2018-05-19 00:03:132809 spdy::SpdySerializedFrame req(
2810 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2811 spdy::SpdySerializedFrame priority(
Bence Béky5b1e4ce72018-01-11 14:55:152812 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
2813 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(priority, 2)};
2814
Ryan Hamilton0239aac2018-05-19 00:03:132815 spdy::SpdyHeaderBlock push_promise_header_block;
2816 push_promise_header_block[spdy::kHttp2MethodHeader] = "HEAD";
Bence Békyd2df6c1c82018-04-20 22:52:012817 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, &push_promise_header_block);
Ryan Hamilton0239aac2018-05-19 00:03:132818 spdy::SpdySerializedFrame push_promise(spdy_util_.ConstructSpdyPushPromise(
Bence Béky5b1e4ce72018-01-11 14:55:152819 1, 2, std::move(push_promise_header_block)));
2820
Ryan Hamilton0239aac2018-05-19 00:03:132821 spdy::SpdyHeaderBlock push_response_headers;
2822 push_response_headers[spdy::kHttp2StatusHeader] = "200";
Bence Béky5b1e4ce72018-01-11 14:55:152823 push_response_headers["foo"] = "bar";
Ryan Hamilton0239aac2018-05-19 00:03:132824 spdy::SpdyHeadersIR headers_ir(2, std::move(push_response_headers));
2825 spdy::SpdySerializedFrame push_headers(spdy_util_.SerializeFrame(headers_ir));
Bence Béky5b1e4ce72018-01-11 14:55:152826
Ryan Hamilton0239aac2018-05-19 00:03:132827 spdy::SpdySerializedFrame resp(
2828 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2829 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Béky5b1e4ce72018-01-11 14:55:152830 MockRead reads[] = {
2831 CreateMockRead(push_promise, 1), CreateMockRead(push_headers, 3),
2832 CreateMockRead(resp, 4), CreateMockRead(body, 5),
2833 // Do not close the connection after first request is done.
2834 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
2835
Ryan Sleevib8d7ea02018-05-07 20:01:012836 SequencedSocketData data(reads, writes);
Bence Béky5b1e4ce72018-01-11 14:55:152837
2838 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2839 helper.RunPreTestSetup();
2840 helper.AddData(&data);
2841
2842 // Run first request. This reads PUSH_PROMISE.
2843 helper.RunDefaultTest();
2844
2845 // Request the pushed resource.
2846 HttpNetworkTransaction trans(DEFAULT_PRIORITY, helper.session());
2847 HttpRequestInfo request = CreateGetPushRequest();
2848 request.method = "HEAD";
Ramin Halavatib5e433e62018-02-07 07:41:102849 request.traffic_annotation =
2850 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky5b1e4ce72018-01-11 14:55:152851 TestCompletionCallback callback;
2852 int rv = trans.Start(&request, callback.callback(), log_);
2853 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2854 rv = callback.WaitForResult();
2855 EXPECT_THAT(rv, IsOk());
2856
2857 const HttpResponseInfo* response = trans.GetResponseInfo();
2858 ASSERT_TRUE(response);
2859 EXPECT_TRUE(response->was_fetched_via_spdy);
2860 EXPECT_TRUE(response->was_alpn_negotiated);
2861 ASSERT_TRUE(response->headers);
2862 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
2863 std::string value;
2864 EXPECT_TRUE(response->headers->GetNormalizedHeader("foo", &value));
2865 EXPECT_EQ("bar", value);
2866
2867 helper.VerifyDataConsumed();
2868}
2869
2870TEST_F(SpdyNetworkTransactionTest, ServerPushHeadDoesNotMatchGetRequest) {
Ryan Hamilton0239aac2018-05-19 00:03:132871 spdy::SpdySerializedFrame req1(
2872 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
2873 spdy::SpdySerializedFrame priority(
Bence Béky5b1e4ce72018-01-11 14:55:152874 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
2875 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:132876 spdy::SpdySerializedFrame req2(
2877 spdy_util_.ConstructSpdyGet(kPushedUrl, 3, LOWEST));
Bence Béky5b1e4ce72018-01-11 14:55:152878 MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(priority, 2),
2879 CreateMockWrite(req2, 6)};
2880
Ryan Hamilton0239aac2018-05-19 00:03:132881 spdy::SpdyHeaderBlock push_promise_header_block;
2882 push_promise_header_block[spdy::kHttp2MethodHeader] = "HEAD";
Bence Békyd2df6c1c82018-04-20 22:52:012883 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, &push_promise_header_block);
Ryan Hamilton0239aac2018-05-19 00:03:132884 spdy::SpdySerializedFrame push_promise(spdy_util_.ConstructSpdyPushPromise(
Bence Béky5b1e4ce72018-01-11 14:55:152885 1, 2, std::move(push_promise_header_block)));
2886
Ryan Hamilton0239aac2018-05-19 00:03:132887 spdy::SpdyHeaderBlock push_response_headers;
2888 push_response_headers[spdy::kHttp2StatusHeader] = "200";
Bence Béky5b1e4ce72018-01-11 14:55:152889 push_response_headers["foo"] = "bar";
Ryan Hamilton0239aac2018-05-19 00:03:132890 spdy::SpdyHeadersIR headers_ir(2, std::move(push_response_headers));
2891 spdy::SpdySerializedFrame push_headers(spdy_util_.SerializeFrame(headers_ir));
Bence Béky5b1e4ce72018-01-11 14:55:152892
Ryan Hamilton0239aac2018-05-19 00:03:132893 spdy::SpdySerializedFrame resp1(
2894 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2895 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
2896 spdy::SpdySerializedFrame resp2(
2897 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
2898 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
Bence Béky5b1e4ce72018-01-11 14:55:152899 MockRead reads[] = {CreateMockRead(push_promise, 1),
2900 CreateMockRead(push_headers, 3),
2901 CreateMockRead(resp1, 4),
2902 CreateMockRead(body1, 5),
2903 CreateMockRead(resp2, 7),
2904 CreateMockRead(body2, 8),
2905 MockRead(ASYNC, 0, 9)};
2906
Ryan Sleevib8d7ea02018-05-07 20:01:012907 SequencedSocketData data(reads, writes);
Bence Béky5b1e4ce72018-01-11 14:55:152908
2909 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
2910 helper.RunPreTestSetup();
2911 helper.AddData(&data);
2912
2913 // Run first request. This reads PUSH_PROMISE.
2914 helper.RunDefaultTest();
2915
2916 // Request the pushed resource.
2917 HttpNetworkTransaction trans(DEFAULT_PRIORITY, helper.session());
2918 HttpRequestInfo request = CreateGetPushRequest();
2919 TestCompletionCallback callback;
2920 int rv = trans.Start(&request, callback.callback(), log_);
2921 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2922 rv = callback.WaitForResult();
2923 EXPECT_THAT(rv, IsOk());
2924
2925 const HttpResponseInfo* response = trans.GetResponseInfo();
2926 ASSERT_TRUE(response);
2927 EXPECT_TRUE(response->was_fetched_via_spdy);
2928 EXPECT_TRUE(response->was_alpn_negotiated);
2929 ASSERT_TRUE(response->headers);
2930 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
2931 std::string value;
2932 EXPECT_FALSE(response->headers->GetNormalizedHeader("foo", &value));
2933 std::string result;
2934 ReadResult(&trans, &result);
2935 EXPECT_EQ("hello!", result);
2936
2937 // Read EOF.
2938 base::RunLoop().RunUntilIdle();
2939
2940 helper.VerifyDataConsumed();
2941}
2942
bncd16676a2016-07-20 16:23:012943TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
Ryan Hamilton0239aac2018-05-19 00:03:132944 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:482945 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:132946 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:352947 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
rch08e3aa3e2015-05-16 14:27:522948 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352949 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
rch08e3aa3e2015-05-16 14:27:522950 };
[email protected]82918cc2010-08-25 17:24:502951
Ryan Hamilton0239aac2018-05-19 00:03:132952 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352953 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:132954 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:012955 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
[email protected]8a0fc822013-06-27 20:52:432956 const char kPushedData[] = "pushed";
Ryan Hamilton0239aac2018-05-19 00:03:132957 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:192958 spdy_util_.ConstructSpdyDataFrame(2, kPushedData, true));
Ryan Hamilton0239aac2018-05-19 00:03:132959 spdy::SpdySerializedFrame stream1_body(
2960 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]82918cc2010-08-25 17:24:502961 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412962 CreateMockRead(stream1_reply, 1),
2963 CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:352964 CreateMockRead(stream2_body, 4),
2965 CreateMockRead(stream1_body, 5, SYNCHRONOUS),
2966 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]82918cc2010-08-25 17:24:502967 };
2968
2969 HttpResponseInfo response;
2970 HttpResponseInfo response2;
Bence Béky4e83f492018-05-13 23:14:252971 std::string expected_push_result("pushed");
Ryan Sleevib8d7ea02018-05-07 20:01:012972 SequencedSocketData data(reads, writes);
[email protected]dd54bd82012-07-19 23:44:572973 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032974 &response,
2975 &response2,
2976 expected_push_result);
[email protected]82918cc2010-08-25 17:24:502977
bnc42331402016-07-25 13:36:152978 // Verify the response headers.
wezca1070932016-05-26 20:30:522979 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022980 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]82918cc2010-08-25 17:24:502981
2982 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522983 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042984 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]82918cc2010-08-25 17:24:502985}
2986
tombergan5d22c182017-01-11 02:05:352987TEST_F(SpdyNetworkTransactionTest, ServerPushUpdatesPriority) {
Ryan Hamilton0239aac2018-05-19 00:03:132988 spdy::SpdySerializedFrame stream1_headers(
Bence Béky27ad0a12018-02-08 00:35:482989 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
Ryan Hamilton0239aac2018-05-19 00:03:132990 spdy::SpdySerializedFrame stream3_headers(
Bence Béky27ad0a12018-02-08 00:35:482991 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM));
Ryan Hamilton0239aac2018-05-19 00:03:132992 spdy::SpdySerializedFrame stream5_headers(
Bence Béky27ad0a12018-02-08 00:35:482993 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, MEDIUM));
tombergan5d22c182017-01-11 02:05:352994
2995 // Stream 1 pushes two streams that are initially prioritized below stream 5.
2996 // Stream 2 is later prioritized below stream 1 after it matches a request.
Ryan Hamilton0239aac2018-05-19 00:03:132997 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:352998 spdy_util_.ConstructSpdyPriority(2, 5, IDLE, true));
Ryan Hamilton0239aac2018-05-19 00:03:132999 spdy::SpdySerializedFrame stream4_priority(
tombergan5d22c182017-01-11 02:05:353000 spdy_util_.ConstructSpdyPriority(4, 2, IDLE, true));
Ryan Hamilton0239aac2018-05-19 00:03:133001 spdy::SpdySerializedFrame stream4_priority_update(
tombergan5d22c182017-01-11 02:05:353002 spdy_util_.ConstructSpdyPriority(4, 5, IDLE, true));
Ryan Hamilton0239aac2018-05-19 00:03:133003 spdy::SpdySerializedFrame stream2_priority_update(
tombergan5d22c182017-01-11 02:05:353004 spdy_util_.ConstructSpdyPriority(2, 1, HIGHEST, true));
3005
[email protected]e3ebba0f2010-08-05 17:59:583006 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:353007 CreateMockWrite(stream1_headers, 0),
3008 CreateMockWrite(stream3_headers, 1),
3009 CreateMockWrite(stream5_headers, 2),
3010 CreateMockWrite(stream2_priority, 7),
3011 CreateMockWrite(stream4_priority, 9),
3012 CreateMockWrite(stream4_priority_update, 11),
3013 CreateMockWrite(stream2_priority_update, 12),
[email protected]e3ebba0f2010-08-05 17:59:583014 };
3015
Ryan Hamilton0239aac2018-05-19 00:03:133016 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:353017 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133018 spdy::SpdySerializedFrame stream3_reply(
tombergan5d22c182017-01-11 02:05:353019 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:133020 spdy::SpdySerializedFrame stream5_reply(
tombergan5d22c182017-01-11 02:05:353021 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
3022
Ryan Hamilton0239aac2018-05-19 00:03:133023 spdy::SpdySerializedFrame stream2_push(
Bence Békyd2df6c1c82018-04-20 22:52:013024 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
Ryan Hamilton0239aac2018-05-19 00:03:133025 spdy::SpdySerializedFrame stream4_push(spdy_util_.ConstructSpdyPush(
Bence Béky3e01b532018-02-06 23:04:513026 nullptr, 0, 4, 1, "https://www.example.org/bar.dat"));
tombergan5d22c182017-01-11 02:05:353027
Ryan Hamilton0239aac2018-05-19 00:03:133028 spdy::SpdySerializedFrame stream1_body(
3029 spdy_util_.ConstructSpdyDataFrame(1, true));
3030 spdy::SpdySerializedFrame stream2_body(
3031 spdy_util_.ConstructSpdyDataFrame(2, true));
3032 spdy::SpdySerializedFrame stream3_body(
3033 spdy_util_.ConstructSpdyDataFrame(3, true));
3034 spdy::SpdySerializedFrame stream5_body(
3035 spdy_util_.ConstructSpdyDataFrame(5, true));
tombergan5d22c182017-01-11 02:05:353036
3037 MockRead reads[] = {
3038 CreateMockRead(stream1_reply, 3),
3039 CreateMockRead(stream3_reply, 4),
3040 CreateMockRead(stream5_reply, 5),
3041 CreateMockRead(stream2_push, 6),
3042 CreateMockRead(stream4_push, 8),
3043 MockRead(ASYNC, ERR_IO_PENDING, 10),
3044 CreateMockRead(stream1_body, 13),
3045 CreateMockRead(stream2_body, 14),
3046 CreateMockRead(stream3_body, 15),
3047 CreateMockRead(stream5_body, 16),
3048 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 17), // Force a pause
3049 };
3050
Ryan Sleevib8d7ea02018-05-07 20:01:013051 SequencedSocketData data(reads, writes);
3052 SequencedSocketData data_placeholder1;
3053 SequencedSocketData data_placeholder2;
3054 SequencedSocketData data_placeholder3;
tombergan5d22c182017-01-11 02:05:353055
Bence Békydb3cf652017-10-10 15:22:103056 NormalSpdyTransactionHelper helper(request_, LOWEST, log_, nullptr);
tombergan5d22c182017-01-11 02:05:353057 helper.RunPreTestSetup();
3058 helper.AddData(&data);
3059 helper.AddData(&data_placeholder1); // other requests reuse the same socket
3060 helper.AddData(&data_placeholder2);
3061 helper.AddData(&data_placeholder3);
3062 HttpNetworkTransaction trans1(HIGHEST, helper.session());
3063 HttpNetworkTransaction trans3(MEDIUM, helper.session());
3064 HttpNetworkTransaction trans5(MEDIUM, helper.session());
3065
3066 TestCompletionCallback callback1;
3067 TestCompletionCallback callback3;
3068 TestCompletionCallback callback5;
3069
3070 // Start the ordinary requests.
Bence Békydb3cf652017-10-10 15:22:103071 ASSERT_THAT(trans1.Start(&request_, callback1.callback(), log_),
tombergan5d22c182017-01-11 02:05:353072 IsError(ERR_IO_PENDING));
Bence Békydb3cf652017-10-10 15:22:103073 ASSERT_THAT(trans3.Start(&request_, callback3.callback(), log_),
tombergan5d22c182017-01-11 02:05:353074 IsError(ERR_IO_PENDING));
Bence Békydb3cf652017-10-10 15:22:103075 ASSERT_THAT(trans5.Start(&request_, callback5.callback(), log_),
tombergan5d22c182017-01-11 02:05:353076 IsError(ERR_IO_PENDING));
3077 data.RunUntilPaused();
3078
tombergan5d22c182017-01-11 02:05:353079 // Start a request that matches the push.
Bence Békydb3cf652017-10-10 15:22:103080 HttpRequestInfo push_req = CreateGetPushRequest();
krasin0bfeb6b2017-01-13 21:48:043081
3082 HttpNetworkTransaction trans2(HIGHEST, helper.session());
3083 TestCompletionCallback callback2;
Bence Békyd3dde832017-09-19 19:02:313084 ASSERT_THAT(trans2.Start(&push_req, callback2.callback(), log_),
tombergan5d22c182017-01-11 02:05:353085 IsError(ERR_IO_PENDING));
3086 data.Resume();
3087
3088 base::RunLoop().RunUntilIdle();
3089 ASSERT_THAT(callback1.WaitForResult(), IsOk());
3090 ASSERT_THAT(callback2.WaitForResult(), IsOk());
3091 ASSERT_THAT(callback3.WaitForResult(), IsOk());
3092 ASSERT_THAT(callback5.WaitForResult(), IsOk());
3093 helper.VerifyDataConsumed();
3094}
3095
3096TEST_F(SpdyNetworkTransactionTest, ServerPushServerAborted) {
Ryan Hamilton0239aac2018-05-19 00:03:133097 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:483098 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:133099 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:353100 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
3101 MockWrite writes[] = {
3102 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
3103 };
3104
Ryan Hamilton0239aac2018-05-19 00:03:133105 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:353106 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133107 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:013108 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
Ryan Hamilton0239aac2018-05-19 00:03:133109 spdy::SpdySerializedFrame stream2_rst(
3110 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_PROTOCOL_ERROR));
3111 spdy::SpdySerializedFrame stream1_body(
3112 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:583113 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413114 CreateMockRead(stream1_reply, 1),
bnceb9aa7112017-01-05 01:03:463115 CreateMockRead(stream2_syn, 2, SYNCHRONOUS),
tombergan5d22c182017-01-11 02:05:353116 CreateMockRead(stream2_rst, 4),
3117 CreateMockRead(stream1_body, 5, SYNCHRONOUS),
3118 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:583119 };
3120
Ryan Sleevib8d7ea02018-05-07 20:01:013121 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:103122 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]e3ebba0f2010-08-05 17:59:583123
3124 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573125 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:583126
3127 HttpNetworkTransaction* trans = helper.trans();
3128
3129 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:413130 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:103131 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:013132 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:583133 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:013134 EXPECT_THAT(rv, IsOk());
[email protected]19ec8a72010-08-23 03:38:233135
3136 // Verify that we consumed all test data.
tombergan5d22c182017-01-11 02:05:353137 base::RunLoop().RunUntilIdle();
rch08e3aa3e2015-05-16 14:27:523138 EXPECT_TRUE(data.AllReadDataConsumed());
3139 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]19ec8a72010-08-23 03:38:233140
bnc42331402016-07-25 13:36:153141 // Verify the response headers.
[email protected]19ec8a72010-08-23 03:38:233142 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523143 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:023144 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:233145}
3146
[email protected]8a0fc822013-06-27 20:52:433147// Verify that we don't leak streams and that we properly send a reset
3148// if the server pushes the same stream twice.
bncd16676a2016-07-20 16:23:013149TEST_F(SpdyNetworkTransactionTest, ServerPushDuplicate) {
Bence Békyeacd48f2018-05-14 11:34:333150 base::HistogramTester histogram_tester;
3151
Ryan Hamilton0239aac2018-05-19 00:03:133152 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:483153 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:133154 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:353155 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
Ryan Hamilton0239aac2018-05-19 00:03:133156 spdy::SpdySerializedFrame stream3_rst(
3157 spdy_util_.ConstructSpdyRstStream(4, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]fdc165a2010-09-03 03:51:293158 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:353159 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
3160 CreateMockWrite(stream3_rst, 5),
[email protected]fdc165a2010-09-03 03:51:293161 };
3162
Ryan Hamilton0239aac2018-05-19 00:03:133163 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:353164 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133165 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:013166 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
Ryan Hamilton0239aac2018-05-19 00:03:133167 spdy::SpdySerializedFrame stream3_syn(
Bence Békyd2df6c1c82018-04-20 22:52:013168 spdy_util_.ConstructSpdyPush(nullptr, 0, 4, 1, kPushedUrl));
tombergan5d22c182017-01-11 02:05:353169
[email protected]8a0fc822013-06-27 20:52:433170 const char kPushedData[] = "pushed";
Ryan Hamilton0239aac2018-05-19 00:03:133171 spdy::SpdySerializedFrame stream1_body(
3172 spdy_util_.ConstructSpdyDataFrame(1, true));
3173 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:193174 spdy_util_.ConstructSpdyDataFrame(2, kPushedData, true));
tombergan5d22c182017-01-11 02:05:353175
[email protected]fdc165a2010-09-03 03:51:293176 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413177 CreateMockRead(stream1_reply, 1),
3178 CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:353179 CreateMockRead(stream3_syn, 4),
3180 CreateMockRead(stream1_body, 6),
3181 CreateMockRead(stream2_body, 7),
3182 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), // Force a pause
[email protected]fdc165a2010-09-03 03:51:293183 };
3184
3185 HttpResponseInfo response;
3186 HttpResponseInfo response2;
Bence Béky4e83f492018-05-13 23:14:253187 std::string expected_push_result("pushed");
Ryan Sleevib8d7ea02018-05-07 20:01:013188 SequencedSocketData data(reads, writes);
[email protected]dd54bd82012-07-19 23:44:573189 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:033190 &response,
3191 &response2,
3192 expected_push_result);
[email protected]fdc165a2010-09-03 03:51:293193
bnc42331402016-07-25 13:36:153194 // Verify the response headers.
wezca1070932016-05-26 20:30:523195 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:023196 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]fdc165a2010-09-03 03:51:293197
3198 // Verify the pushed stream.
wezca1070932016-05-26 20:30:523199 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:043200 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
Bence Békyeacd48f2018-05-14 11:34:333201
3202 histogram_tester.ExpectBucketCount(
3203 "Net.SpdyPushedStreamFate",
3204 static_cast<int>(SpdyPushedStreamFate::kAcceptedNoVary), 1);
3205 histogram_tester.ExpectBucketCount(
3206 "Net.SpdyPushedStreamFate",
3207 static_cast<int>(SpdyPushedStreamFate::kDuplicateUrl), 1);
3208 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 2);
[email protected]fdc165a2010-09-03 03:51:293209}
3210
bncd16676a2016-07-20 16:23:013211TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
Ryan Hamilton0239aac2018-05-19 00:03:133212 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:483213 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:133214 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:353215 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]19ec8a72010-08-23 03:38:233216 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:353217 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
[email protected]19ec8a72010-08-23 03:38:233218 };
3219
Ryan Hamilton0239aac2018-05-19 00:03:133220 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:353221 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133222 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:013223 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
Bence Békyd74f4382018-02-20 18:26:193224 static const char kPushedData[] = "pushed payload for chunked test";
Ryan Hamilton0239aac2018-05-19 00:03:133225 spdy::SpdySerializedFrame stream2_body_base(
Bence Békyd74f4382018-02-20 18:26:193226 spdy_util_.ConstructSpdyDataFrame(2, kPushedData, true));
[email protected]8a0fc822013-06-27 20:52:433227 const size_t kChunkSize = strlen(kPushedData) / 4;
Ryan Hamilton0239aac2018-05-19 00:03:133228 spdy::SpdySerializedFrame stream2_body1(stream2_body_base.data(), kChunkSize,
3229 false);
3230 spdy::SpdySerializedFrame stream2_body2(stream2_body_base.data() + kChunkSize,
3231 kChunkSize, false);
3232 spdy::SpdySerializedFrame stream2_body3(
3233 stream2_body_base.data() + 2 * kChunkSize, kChunkSize, false);
3234 spdy::SpdySerializedFrame stream2_body4(
3235 stream2_body_base.data() + 3 * kChunkSize,
3236 stream2_body_base.size() - 3 * kChunkSize, false);
3237 spdy::SpdySerializedFrame stream1_body(
3238 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:233239 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413240 CreateMockRead(stream1_reply, 1),
3241 CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:353242 CreateMockRead(stream2_body1, 4),
3243 CreateMockRead(stream2_body2, 5),
3244 CreateMockRead(stream2_body3, 6),
3245 CreateMockRead(stream2_body4, 7),
3246 CreateMockRead(stream1_body, 8, SYNCHRONOUS),
3247 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9), // Force a pause
[email protected]19ec8a72010-08-23 03:38:233248 };
3249
3250 HttpResponseInfo response;
3251 HttpResponseInfo response2;
Bence Béky4e83f492018-05-13 23:14:253252 std::string expected_push_result(kPushedData);
Ryan Sleevib8d7ea02018-05-07 20:01:013253 SequencedSocketData data(reads, writes);
[email protected]8a0fc822013-06-27 20:52:433254 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:233255
bnc42331402016-07-25 13:36:153256 // Verify the response headers.
wezca1070932016-05-26 20:30:523257 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:023258 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:233259
3260 // Verify the pushed stream.
wezca1070932016-05-26 20:30:523261 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:043262 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:233263}
3264
bncd16676a2016-07-20 16:23:013265TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
Ryan Hamilton0239aac2018-05-19 00:03:133266 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:483267 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:133268 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:353269 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]19ec8a72010-08-23 03:38:233270 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:353271 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
[email protected]19ec8a72010-08-23 03:38:233272 };
3273
Ryan Hamilton0239aac2018-05-19 00:03:133274 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:353275 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133276 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:013277 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
Bence Békyd74f4382018-02-20 18:26:193278 static const char kPushedData[] = "pushed payload for chunked test";
Ryan Hamilton0239aac2018-05-19 00:03:133279 spdy::SpdySerializedFrame stream2_body_base(
Bence Békyd74f4382018-02-20 18:26:193280 spdy_util_.ConstructSpdyDataFrame(2, kPushedData, true));
[email protected]8a0fc822013-06-27 20:52:433281 const size_t kChunkSize = strlen(kPushedData) / 4;
Ryan Hamilton0239aac2018-05-19 00:03:133282 spdy::SpdySerializedFrame stream2_body1(stream2_body_base.data(), kChunkSize,
3283 false);
3284 spdy::SpdySerializedFrame stream2_body2(stream2_body_base.data() + kChunkSize,
3285 kChunkSize, false);
3286 spdy::SpdySerializedFrame stream2_body3(
3287 stream2_body_base.data() + 2 * kChunkSize, kChunkSize, false);
3288 spdy::SpdySerializedFrame stream2_body4(
3289 stream2_body_base.data() + 3 * kChunkSize,
3290 stream2_body_base.size() - 3 * kChunkSize, false);
3291 spdy::SpdySerializedFrame stream1_body(
3292 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:233293 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413294 CreateMockRead(stream1_reply, 1),
3295 CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:353296 CreateMockRead(stream2_body1, 4),
3297 CreateMockRead(stream2_body2, 5),
3298 CreateMockRead(stream2_body3, 6),
3299 CreateMockRead(stream2_body4, 7),
3300 CreateMockRead(stream1_body, 8, SYNCHRONOUS),
3301 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9) // Force a pause.
[email protected]19ec8a72010-08-23 03:38:233302 };
3303
3304 HttpResponseInfo response;
3305 HttpResponseInfo response2;
Ryan Sleevib8d7ea02018-05-07 20:01:013306 SequencedSocketData data(reads, writes);
[email protected]8a0fc822013-06-27 20:52:433307 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:233308
bnc42331402016-07-25 13:36:153309 // Verify the response headers.
wezca1070932016-05-26 20:30:523310 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:023311 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:233312
3313 // Verify the pushed stream.
wezca1070932016-05-26 20:30:523314 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:043315 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:233316}
3317
morlovichab1d1c1e2017-02-07 19:59:283318TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidUrl) {
Bence Békyeacd48f2018-05-14 11:34:333319 base::HistogramTester histogram_tester;
3320
morlovichab1d1c1e2017-02-07 19:59:283321 // Coverage on how a non-empty invalid GURL in a PUSH_PROMISE is handled.
Ryan Hamilton0239aac2018-05-19 00:03:133322 spdy::SpdyHeaderBlock headers(
3323 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
3324 spdy::SpdySerializedFrame req(
morlovichab1d1c1e2017-02-07 19:59:283325 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
3326
3327 // Can't use ConstructSpdyPush here since it wants to parse a URL and
3328 // split it into the appropriate :header pieces. So we have to hand-fill
3329 // those pieces in.
Ryan Hamilton0239aac2018-05-19 00:03:133330 spdy::SpdyHeaderBlock push_promise_header_block;
3331 push_promise_header_block[spdy::kHttp2AuthorityHeader] = "";
3332 push_promise_header_block[spdy::kHttp2SchemeHeader] = "";
3333 push_promise_header_block[spdy::kHttp2PathHeader] = "/index.html";
morlovichab1d1c1e2017-02-07 19:59:283334
Ryan Hamilton0239aac2018-05-19 00:03:133335 spdy::SpdySerializedFrame push_promise(spdy_util_.ConstructSpdyPushPromise(
Bence Békyf1d78522018-01-11 01:16:503336 1, 2, std::move(push_promise_header_block)));
morlovichab1d1c1e2017-02-07 19:59:283337
Ryan Hamilton0239aac2018-05-19 00:03:133338 spdy::SpdySerializedFrame stream2_rst(
3339 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
morlovichab1d1c1e2017-02-07 19:59:283340
3341 MockWrite writes[] = {CreateMockWrite(req, 0),
3342 CreateMockWrite(stream2_rst, 2)};
3343 MockRead reads[] = {
Bence Békyf1d78522018-01-11 01:16:503344 CreateMockRead(push_promise, 1), MockRead(ASYNC, 0, 3) /* EOF */
morlovichab1d1c1e2017-02-07 19:59:283345 };
Ryan Sleevib8d7ea02018-05-07 20:01:013346 SequencedSocketData data(reads, writes);
morlovichab1d1c1e2017-02-07 19:59:283347 RunBrokenPushTest(&data, ERR_CONNECTION_CLOSED);
Bence Békyeacd48f2018-05-14 11:34:333348
3349 histogram_tester.ExpectBucketCount(
3350 "Net.SpdyPushedStreamFate",
3351 static_cast<int>(SpdyPushedStreamFate::kInvalidUrl), 1);
3352 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
morlovichab1d1c1e2017-02-07 19:59:283353}
3354
bncd16676a2016-07-20 16:23:013355TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
Ryan Hamilton0239aac2018-05-19 00:03:133356 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:483357 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:133358 spdy::SpdySerializedFrame goaway(
3359 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_PROTOCOL_ERROR,
3360 "Framer error: 1 (INVALID_STREAM_ID)."));
[email protected]19ec8a72010-08-23 03:38:233361 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:413362 CreateMockWrite(stream1_syn, 0), CreateMockWrite(goaway, 3),
[email protected]19ec8a72010-08-23 03:38:233363 };
3364
Ryan Hamilton0239aac2018-05-19 00:03:133365 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:353366 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133367 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:013368 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 0, kPushedUrl));
[email protected]19ec8a72010-08-23 03:38:233369 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413370 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
[email protected]19ec8a72010-08-23 03:38:233371 };
Ryan Sleevib8d7ea02018-05-07 20:01:013372 SequencedSocketData data(reads, writes);
morlovichab1d1c1e2017-02-07 19:59:283373 RunBrokenPushTest(&data, OK);
[email protected]e3ebba0f2010-08-05 17:59:583374}
3375
bncd16676a2016-07-20 16:23:013376TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
Bence Békyeacd48f2018-05-14 11:34:333377 base::HistogramTester histogram_tester;
3378
Ryan Hamilton0239aac2018-05-19 00:03:133379 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:483380 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:133381 spdy::SpdySerializedFrame stream1_body(
3382 spdy_util_.ConstructSpdyDataFrame(1, true));
3383 spdy::SpdySerializedFrame stream2_rst(
3384 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_STREAM_CLOSED));
[email protected]e3ebba0f2010-08-05 17:59:583385 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:413386 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:583387 };
3388
Ryan Hamilton0239aac2018-05-19 00:03:133389 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:353390 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133391 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:013392 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 9, kPushedUrl));
[email protected]e3ebba0f2010-08-05 17:59:583393 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413394 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
3395 CreateMockRead(stream1_body, 4),
rch08e3aa3e2015-05-16 14:27:523396 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:583397 };
3398
Ryan Sleevib8d7ea02018-05-07 20:01:013399 SequencedSocketData data(reads, writes);
morlovichab1d1c1e2017-02-07 19:59:283400 RunBrokenPushTest(&data, OK);
Bence Békyeacd48f2018-05-14 11:34:333401
3402 histogram_tester.ExpectBucketCount(
3403 "Net.SpdyPushedStreamFate",
3404 static_cast<int>(SpdyPushedStreamFate::kInactiveAssociatedStream), 1);
3405 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
[email protected]e3ebba0f2010-08-05 17:59:583406}
3407
bncd16676a2016-07-20 16:23:013408TEST_F(SpdyNetworkTransactionTest, ServerPushNoURL) {
Bence Békyeacd48f2018-05-14 11:34:333409 base::HistogramTester histogram_tester;
3410
Ryan Hamilton0239aac2018-05-19 00:03:133411 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:483412 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:133413 spdy::SpdySerializedFrame stream1_body(
3414 spdy_util_.ConstructSpdyDataFrame(1, true));
3415 spdy::SpdySerializedFrame stream2_rst(
3416 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]e3ebba0f2010-08-05 17:59:583417 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:413418 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:583419 };
3420
Ryan Hamilton0239aac2018-05-19 00:03:133421 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:353422 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133423 spdy::SpdyHeaderBlock incomplete_headers;
3424 incomplete_headers[spdy::kHttp2StatusHeader] = "200 OK";
bnc086b39e12016-06-24 13:05:263425 incomplete_headers["hello"] = "bye";
Ryan Hamilton0239aac2018-05-19 00:03:133426 spdy::SpdySerializedFrame stream2_syn(
Bence Békyf1d78522018-01-11 01:16:503427 spdy_util_.ConstructSpdyPushPromise(1, 2, std::move(incomplete_headers)));
[email protected]e3ebba0f2010-08-05 17:59:583428 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413429 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
3430 CreateMockRead(stream1_body, 4),
rch08e3aa3e2015-05-16 14:27:523431 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:583432 };
3433
Ryan Sleevib8d7ea02018-05-07 20:01:013434 SequencedSocketData data(reads, writes);
morlovichab1d1c1e2017-02-07 19:59:283435 RunBrokenPushTest(&data, OK);
Bence Békyeacd48f2018-05-14 11:34:333436
3437 histogram_tester.ExpectBucketCount(
3438 "Net.SpdyPushedStreamFate",
3439 static_cast<int>(SpdyPushedStreamFate::kInvalidUrl), 1);
3440 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
[email protected]e3ebba0f2010-08-05 17:59:583441}
3442
bnc0cb98b22016-03-04 17:10:523443// PUSH_PROMISE on a server-initiated stream should trigger GOAWAY.
bncd16676a2016-07-20 16:23:013444TEST_F(SpdyNetworkTransactionTest, ServerPushOnPushedStream) {
Bence Békyeacd48f2018-05-14 11:34:333445 base::HistogramTester histogram_tester;
3446
Ryan Hamilton0239aac2018-05-19 00:03:133447 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:483448 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:133449 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:353450 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
Ryan Hamilton0239aac2018-05-19 00:03:133451 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
3452 2, spdy::ERROR_CODE_PROTOCOL_ERROR,
Bence Béky602c40c2017-07-26 05:22:563453 "Received pushed stream id 4 on invalid stream id 2 (must be odd)."));
bnc0cb98b22016-03-04 17:10:523454 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:353455 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
3456 CreateMockWrite(goaway, 5),
bnc0cb98b22016-03-04 17:10:523457 };
3458
Ryan Hamilton0239aac2018-05-19 00:03:133459 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:353460 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133461 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:013462 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
Ryan Hamilton0239aac2018-05-19 00:03:133463 spdy::SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
Bence Béky3e01b532018-02-06 23:04:513464 nullptr, 0, 4, 2, "https://www.example.org/bar.dat"));
bnc0cb98b22016-03-04 17:10:523465 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413466 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:353467 CreateMockRead(stream3_syn, 4),
bnc0cb98b22016-03-04 17:10:523468 };
3469
Ryan Sleevib8d7ea02018-05-07 20:01:013470 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:103471 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc0cb98b22016-03-04 17:10:523472 helper.RunToCompletion(&data);
Bence Békyeacd48f2018-05-14 11:34:333473
3474 histogram_tester.ExpectBucketCount(
3475 "Net.SpdyPushedStreamFate",
3476 static_cast<int>(SpdyPushedStreamFate::kAssociatedStreamIdParityError),
3477 1);
3478 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
bnc0cb98b22016-03-04 17:10:523479}
3480
3481// PUSH_PROMISE on a closed client-initiated stream should trigger RST_STREAM.
bncd16676a2016-07-20 16:23:013482TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedStream) {
Bence Békyeacd48f2018-05-14 11:34:333483 base::HistogramTester histogram_tester;
3484
Ryan Hamilton0239aac2018-05-19 00:03:133485 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:483486 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:133487 spdy::SpdySerializedFrame rst(
3488 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_STREAM_CLOSED));
bnc0cb98b22016-03-04 17:10:523489 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:413490 CreateMockWrite(stream1_syn, 0), CreateMockWrite(rst, 5),
bnc0cb98b22016-03-04 17:10:523491 };
3492
Ryan Hamilton0239aac2018-05-19 00:03:133493 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:153494 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133495 spdy::SpdySerializedFrame stream1_body(
3496 spdy_util_.ConstructSpdyDataFrame(1, true));
3497 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:013498 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
bnc0cb98b22016-03-04 17:10:523499 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413500 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_body, 2),
3501 CreateMockRead(stream2_syn, 3), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
bnc0cb98b22016-03-04 17:10:523502 };
3503
Ryan Sleevib8d7ea02018-05-07 20:01:013504 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:103505 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc0cb98b22016-03-04 17:10:523506 helper.RunPreTestSetup();
3507 helper.AddData(&data);
3508
3509 HttpNetworkTransaction* trans = helper.trans();
3510
3511 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:103512 int rv = trans->Start(&request_, callback.callback(), log_);
bnc0cb98b22016-03-04 17:10:523513 rv = callback.GetResult(rv);
robpercival214763f2016-07-01 23:27:013514 EXPECT_THAT(rv, IsOk());
bnceb9aa7112017-01-05 01:03:463515
3516 // Finish async network reads/writes.
3517 base::RunLoop().RunUntilIdle();
3518
bnc0cb98b22016-03-04 17:10:523519 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523520 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:523521 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
3522
3523 EXPECT_TRUE(data.AllReadDataConsumed());
3524 EXPECT_TRUE(data.AllWriteDataConsumed());
3525 VerifyStreamsClosed(helper);
Bence Békyeacd48f2018-05-14 11:34:333526
3527 histogram_tester.ExpectBucketCount(
3528 "Net.SpdyPushedStreamFate",
3529 static_cast<int>(SpdyPushedStreamFate::kInactiveAssociatedStream), 1);
3530 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
bnc0cb98b22016-03-04 17:10:523531}
3532
3533// PUSH_PROMISE on a server-initiated stream should trigger GOAWAY even if
3534// stream is closed.
bncd16676a2016-07-20 16:23:013535TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedPushedStream) {
Bence Békyeacd48f2018-05-14 11:34:333536 base::HistogramTester histogram_tester;
3537
Ryan Hamilton0239aac2018-05-19 00:03:133538 spdy::SpdySerializedFrame stream1_syn(
Bence Béky27ad0a12018-02-08 00:35:483539 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:133540 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:353541 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
Ryan Hamilton0239aac2018-05-19 00:03:133542 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
3543 2, spdy::ERROR_CODE_PROTOCOL_ERROR,
Bence Béky602c40c2017-07-26 05:22:563544 "Received pushed stream id 4 on invalid stream id 2 (must be odd)."));
Bence Béky7bf94362018-01-10 13:19:363545 MockWrite writes[] = {CreateMockWrite(stream1_syn, 0),
3546 CreateMockWrite(stream2_priority, 3),
3547 CreateMockWrite(goaway, 8)};
bnc0cb98b22016-03-04 17:10:523548
Ryan Hamilton0239aac2018-05-19 00:03:133549 spdy::SpdySerializedFrame stream2_syn(
Bence Békyd2df6c1c82018-04-20 22:52:013550 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
Ryan Hamilton0239aac2018-05-19 00:03:133551 spdy::SpdySerializedFrame stream1_reply(
Bence Béky7bf94362018-01-10 13:19:363552 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133553 spdy::SpdySerializedFrame stream1_body(
3554 spdy_util_.ConstructSpdyDataFrame(1, true));
bnc0cb98b22016-03-04 17:10:523555 const char kPushedData[] = "pushed";
Ryan Hamilton0239aac2018-05-19 00:03:133556 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:193557 spdy_util_.ConstructSpdyDataFrame(2, kPushedData, true));
Ryan Hamilton0239aac2018-05-19 00:03:133558 spdy::SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
Bence Béky3e01b532018-02-06 23:04:513559 nullptr, 0, 4, 2, "https://www.example.org/bar.dat"));
bnc0cb98b22016-03-04 17:10:523560
3561 MockRead reads[] = {
Bence Béky7bf94362018-01-10 13:19:363562 CreateMockRead(stream2_syn, 1), CreateMockRead(stream1_reply, 2),
tombergan5d22c182017-01-11 02:05:353563 CreateMockRead(stream1_body, 4), CreateMockRead(stream2_body, 5),
Bence Béky7bf94362018-01-10 13:19:363564 MockRead(ASYNC, ERR_IO_PENDING, 6), CreateMockRead(stream3_syn, 7)};
bnc0cb98b22016-03-04 17:10:523565
Ryan Sleevib8d7ea02018-05-07 20:01:013566 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:103567 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc0cb98b22016-03-04 17:10:523568 helper.RunPreTestSetup();
3569 helper.AddData(&data);
3570
3571 HttpNetworkTransaction* trans1 = helper.trans();
3572 TestCompletionCallback callback1;
Bence Békydb3cf652017-10-10 15:22:103573 int rv = trans1->Start(&request_, callback1.callback(), log_);
bnc0cb98b22016-03-04 17:10:523574 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:013575 EXPECT_THAT(rv, IsOk());
bnc0cb98b22016-03-04 17:10:523576 HttpResponseInfo response = *trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:523577 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:523578 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
3579
bnc691fda62016-08-12 00:43:163580 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
bnc0cb98b22016-03-04 17:10:523581 TestCompletionCallback callback2;
Bence Békydb3cf652017-10-10 15:22:103582 HttpRequestInfo request = CreateGetPushRequest();
3583 rv = trans2.Start(&request, callback2.callback(), log_);
bnc0cb98b22016-03-04 17:10:523584 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:013585 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:163586 response = *trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:523587 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:523588 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
Bence Béky4e83f492018-05-13 23:14:253589 std::string result;
bnc691fda62016-08-12 00:43:163590 ReadResult(&trans2, &result);
bnc0cb98b22016-03-04 17:10:523591 EXPECT_EQ(kPushedData, result);
3592
3593 data.Resume();
3594 base::RunLoop().RunUntilIdle();
3595
3596 EXPECT_TRUE(data.AllReadDataConsumed());
3597 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békyeacd48f2018-05-14 11:34:333598
3599 histogram_tester.ExpectBucketCount(
3600 "Net.SpdyPushedStreamFate",
3601 static_cast<int>(SpdyPushedStreamFate::kAssociatedStreamIdParityError),
3602 1);
3603 histogram_tester.ExpectBucketCount(
3604 "Net.SpdyPushedStreamFate",
3605 static_cast<int>(SpdyPushedStreamFate::kAcceptedNoVary), 1);
3606 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 2);
bnc0cb98b22016-03-04 17:10:523607}
3608
Bence Békye8955cf22018-01-02 17:31:293609TEST_F(SpdyNetworkTransactionTest, ServerCancelsPush) {
Ryan Hamilton0239aac2018-05-19 00:03:133610 spdy::SpdySerializedFrame req1(
3611 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3612 spdy::SpdySerializedFrame priority(
Bence Békye8955cf22018-01-02 17:31:293613 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
Bence Béky1a5d8562018-01-05 17:29:283614 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:133615 spdy::SpdySerializedFrame req2(
3616 spdy_util_.ConstructSpdyGet(kPushedUrl, 3, LOWEST));
Bence Béky1a5d8562018-01-05 17:29:283617 MockWrite writes1[] = {CreateMockWrite(req1, 0), CreateMockWrite(priority, 3),
3618 CreateMockWrite(req2, 6)};
Bence Békye8955cf22018-01-02 17:31:293619
Ryan Hamilton0239aac2018-05-19 00:03:133620 spdy::SpdySerializedFrame reply1(
3621 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3622 spdy::SpdySerializedFrame push(
Bence Békyd2df6c1c82018-04-20 22:52:013623 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
Ryan Hamilton0239aac2018-05-19 00:03:133624 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
3625 spdy::SpdySerializedFrame rst(
3626 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_INTERNAL_ERROR));
3627 spdy::SpdySerializedFrame reply2(
3628 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
3629 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
Bence Béky1a5d8562018-01-05 17:29:283630 MockRead reads1[] = {CreateMockRead(reply1, 1), CreateMockRead(push, 2),
3631 CreateMockRead(body1, 4), CreateMockRead(rst, 5),
3632 CreateMockRead(reply2, 7), CreateMockRead(body2, 8),
3633 MockRead(ASYNC, 0, 9)};
Bence Békye8955cf22018-01-02 17:31:293634
Ryan Sleevib8d7ea02018-05-07 20:01:013635 SequencedSocketData data(reads1, writes1);
Bence Békye8955cf22018-01-02 17:31:293636
3637 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
3638 helper.RunPreTestSetup();
3639 helper.AddData(&data);
3640
Bence Béky1a5d8562018-01-05 17:29:283641 // First request opens up connection.
Bence Békye8955cf22018-01-02 17:31:293642 HttpNetworkTransaction* trans1 = helper.trans();
3643 TestCompletionCallback callback1;
3644 int rv = trans1->Start(&request_, callback1.callback(), log_);
3645 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3646
3647 // Read until response body arrives. PUSH_PROMISE comes earlier.
3648 rv = callback1.WaitForResult();
3649 EXPECT_THAT(rv, IsOk());
Bence Béky1a5d8562018-01-05 17:29:283650 const HttpResponseInfo* response = trans1->GetResponseInfo();
3651 EXPECT_TRUE(response->headers);
3652 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
3653 std::string result1;
3654 ReadResult(trans1, &result1);
3655 EXPECT_EQ("hello!", result1);
3656
3657 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
3658 SpdySessionKey key(host_port_pair_, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:113659 PRIVACY_MODE_DISABLED,
3660 SpdySessionKey::IsProxySession::kFalse, SocketTag());
Bence Béky1a5d8562018-01-05 17:29:283661 base::WeakPtr<SpdySession> spdy_session =
3662 spdy_session_pool->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:313663 key, /* enable_ip_based_pooling = */ true,
3664 /* is_websocket = */ false, log_);
Bence Béky1a5d8562018-01-05 17:29:283665 EXPECT_EQ(1u, num_unclaimed_pushed_streams(spdy_session));
Bence Békye8955cf22018-01-02 17:31:293666
3667 // Create request matching pushed stream.
Bence Békye8955cf22018-01-02 17:31:293668 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
Bence Béky1a5d8562018-01-05 17:29:283669 HttpRequestInfo request2 = CreateGetPushRequest();
Bence Békye8955cf22018-01-02 17:31:293670 TestCompletionCallback callback2;
Bence Béky1a5d8562018-01-05 17:29:283671 rv = trans2.Start(&request2, callback2.callback(), log_);
Bence Békye8955cf22018-01-02 17:31:293672 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3673
Bence Béky1a5d8562018-01-05 17:29:283674 // Pushed stream is now claimed by second request.
3675 EXPECT_EQ(0u, num_unclaimed_pushed_streams(spdy_session));
3676
3677 // Second request receives RST_STREAM and is retried on the same connection.
Bence Békye8955cf22018-01-02 17:31:293678 rv = callback2.WaitForResult();
Bence Béky1a5d8562018-01-05 17:29:283679 EXPECT_THAT(rv, IsOk());
3680 response = trans2.GetResponseInfo();
3681 EXPECT_TRUE(response->headers);
3682 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
3683 std::string result2;
3684 ReadResult(&trans2, &result2);
3685 EXPECT_EQ("hello!", result2);
Bence Békye8955cf22018-01-02 17:31:293686
3687 // Read EOF.
3688 base::RunLoop().RunUntilIdle();
3689
Bence Béky1a5d8562018-01-05 17:29:283690 helper.VerifyDataConsumed();
3691}
3692
3693// Regression test for https://crbug.com/776415.
3694// A client-initiated request can only pool to an existing HTTP/2 connection if
3695// the IP address matches. However, a resource can be pushed by the server on a
3696// connection even if the IP address does not match. This test verifies that if
3697// the request binds to such a pushed stream, and after that the server resets
3698// the stream before SpdySession::GetPushedStream() is called, then the retry
3699// (using a client-initiated stream) does not pool to this connection.
3700TEST_F(SpdyNetworkTransactionTest, ServerCancelsCrossOriginPush) {
3701 const char* kUrl1 = "https://www.example.org";
3702 const char* kUrl2 = "https://mail.example.org";
3703
3704 auto resolver = std::make_unique<MockHostResolver>();
3705 resolver->rules()->ClearRules();
3706 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
3707 resolver->rules()->AddRule("mail.example.org", "127.0.0.2");
3708
3709 auto session_deps = std::make_unique<SpdySessionDependencies>();
3710 session_deps->host_resolver = std::move(resolver);
3711 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
3712 std::move(session_deps));
3713
Ryan Hamilton0239aac2018-05-19 00:03:133714 spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet(kUrl1, 1, LOWEST));
3715 spdy::SpdySerializedFrame priority(
Bence Béky1a5d8562018-01-05 17:29:283716 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
3717 MockWrite writes1[] = {CreateMockWrite(req1, 0),
3718 CreateMockWrite(priority, 3)};
3719
Ryan Hamilton0239aac2018-05-19 00:03:133720 spdy::SpdySerializedFrame reply1(
3721 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
3722 spdy::SpdySerializedFrame push(
Bence Béky1a5d8562018-01-05 17:29:283723 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kUrl2));
Ryan Hamilton0239aac2018-05-19 00:03:133724 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
3725 spdy::SpdySerializedFrame rst(
3726 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_INTERNAL_ERROR));
Bence Béky1a5d8562018-01-05 17:29:283727 MockRead reads1[] = {
3728 CreateMockRead(reply1, 1), CreateMockRead(push, 2),
3729 CreateMockRead(body1, 4), CreateMockRead(rst, 5),
3730 MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7)};
3731
Ryan Sleevib8d7ea02018-05-07 20:01:013732 SequencedSocketData data1(reads1, writes1);
Bence Béky1a5d8562018-01-05 17:29:283733
3734 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:133735 spdy::SpdySerializedFrame req2(spdy_util2.ConstructSpdyGet(kUrl2, 1, LOWEST));
Bence Béky1a5d8562018-01-05 17:29:283736 MockWrite writes2[] = {CreateMockWrite(req2, 0)};
3737
Ryan Hamilton0239aac2018-05-19 00:03:133738 spdy::SpdySerializedFrame reply2(
3739 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
3740 spdy::SpdySerializedFrame body2(spdy_util2.ConstructSpdyDataFrame(
Bence Békyd74f4382018-02-20 18:26:193741 1, "Response on the second connection.", true));
Bence Béky1a5d8562018-01-05 17:29:283742 MockRead reads2[] = {CreateMockRead(reply2, 1), CreateMockRead(body2, 2),
3743 MockRead(ASYNC, 0, 3)};
3744
Ryan Sleevib8d7ea02018-05-07 20:01:013745 SequencedSocketData data2(reads2, writes2);
Bence Béky1a5d8562018-01-05 17:29:283746
3747 helper.RunPreTestSetup();
3748 helper.AddData(&data1);
3749 helper.AddData(&data2);
3750
3751 // First request opens up connection to www.example.org.
3752 HttpNetworkTransaction* trans1 = helper.trans();
3753 HttpRequestInfo request1;
3754 request1.method = "GET";
3755 request1.url = GURL(kUrl1);
Ramin Halavatib5e433e62018-02-07 07:41:103756 request1.traffic_annotation =
3757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky1a5d8562018-01-05 17:29:283758 TestCompletionCallback callback1;
3759 int rv = trans1->Start(&request1, callback1.callback(), log_);
3760 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3761
3762 // Read until response body arrives. PUSH_PROMISE comes earlier.
3763 rv = callback1.WaitForResult();
3764 EXPECT_THAT(rv, IsOk());
3765 const HttpResponseInfo* response = trans1->GetResponseInfo();
3766 EXPECT_TRUE(response->headers);
3767 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
3768 std::string result1;
3769 ReadResult(trans1, &result1);
3770 EXPECT_EQ("hello!", result1);
3771
3772 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
3773 SpdySessionKey key1(HostPortPair::FromURL(GURL(kUrl1)), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:113774 PRIVACY_MODE_DISABLED,
3775 SpdySessionKey::IsProxySession::kFalse, SocketTag());
Bence Béky1a5d8562018-01-05 17:29:283776 base::WeakPtr<SpdySession> spdy_session1 =
3777 spdy_session_pool->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:313778 key1, /* enable_ip_based_pooling = */ true,
3779 /* is_websocket = */ false, log_);
Bence Béky1a5d8562018-01-05 17:29:283780 EXPECT_EQ(1u, num_unclaimed_pushed_streams(spdy_session1));
3781
3782 // While cross-origin push for kUrl2 is allowed on spdy_session1,
3783 // a client-initiated request would not pool to this connection,
3784 // because the IP address does not match.
3785 SpdySessionKey key2(HostPortPair::FromURL(GURL(kUrl2)), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:113786 PRIVACY_MODE_DISABLED,
3787 SpdySessionKey::IsProxySession::kFalse, SocketTag());
Bence Béky1a5d8562018-01-05 17:29:283788 EXPECT_FALSE(spdy_session_pool->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:313789 key2, /* enable_ip_based_pooling = */ true,
3790 /* is_websocket = */ false, log_));
Bence Béky1a5d8562018-01-05 17:29:283791
3792 // Create request matching pushed stream.
3793 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
3794 HttpRequestInfo request2;
3795 request2.method = "GET";
3796 request2.url = GURL(kUrl2);
Ramin Halavatib5e433e62018-02-07 07:41:103797 request2.traffic_annotation =
3798 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky1a5d8562018-01-05 17:29:283799 TestCompletionCallback callback2;
3800 rv = trans2.Start(&request2, callback2.callback(), log_);
3801 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3802
3803 // Pushed stream is now claimed by second request.
3804 EXPECT_EQ(0u, num_unclaimed_pushed_streams(spdy_session1));
3805
3806 // Second request receives RST_STREAM and is retried on a new connection.
3807 rv = callback2.WaitForResult();
3808 EXPECT_THAT(rv, IsOk());
3809 response = trans2.GetResponseInfo();
3810 EXPECT_TRUE(response->headers);
3811 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
3812 std::string result2;
3813 ReadResult(&trans2, &result2);
3814 EXPECT_EQ("Response on the second connection.", result2);
3815
3816 // Make sure that the first connection is still open. This is important in
3817 // order to test that the retry created its own connection (because the IP
3818 // address does not match), instead of using the connection of the cancelled
3819 // pushed stream.
3820 EXPECT_TRUE(spdy_session1);
3821
3822 // Read EOF.
3823 data1.Resume();
3824 base::RunLoop().RunUntilIdle();
3825
3826 helper.VerifyDataConsumed();
Bence Békye8955cf22018-01-02 17:31:293827}
3828
bncc055fa32017-06-19 13:44:423829// Regression test for https://crbug.com/727653.
3830TEST_F(SpdyNetworkTransactionTest, RejectServerPushWithNoMethod) {
Bence Békyeacd48f2018-05-14 11:34:333831 base::HistogramTester histogram_tester;
3832
Ryan Hamilton0239aac2018-05-19 00:03:133833 spdy::SpdySerializedFrame req(
3834 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3835 spdy::SpdySerializedFrame rst(
3836 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
bncc055fa32017-06-19 13:44:423837 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 3)};
3838
Ryan Hamilton0239aac2018-05-19 00:03:133839 spdy::SpdySerializedFrame reply(
3840 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncc055fa32017-06-19 13:44:423841
Ryan Hamilton0239aac2018-05-19 00:03:133842 spdy::SpdyHeaderBlock push_promise_header_block;
Bence Békyd2df6c1c82018-04-20 22:52:013843 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, &push_promise_header_block);
Ryan Hamilton0239aac2018-05-19 00:03:133844 spdy::SpdySerializedFrame push_promise(spdy_util_.ConstructSpdyPushPromise(
Bence Békyf1d78522018-01-11 01:16:503845 1, 2, std::move(push_promise_header_block)));
bncc055fa32017-06-19 13:44:423846
Ryan Hamilton0239aac2018-05-19 00:03:133847 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Békyf1d78522018-01-11 01:16:503848 MockRead reads[] = {CreateMockRead(reply, 1), CreateMockRead(push_promise, 2),
3849 CreateMockRead(body, 4),
3850 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5)};
bncc055fa32017-06-19 13:44:423851
Ryan Sleevib8d7ea02018-05-07 20:01:013852 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:103853 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bncc055fa32017-06-19 13:44:423854 helper.RunToCompletion(&data);
Bence Békyeacd48f2018-05-14 11:34:333855
3856 histogram_tester.ExpectBucketCount(
3857 "Net.SpdyPushedStreamFate",
3858 static_cast<int>(SpdyPushedStreamFate::kInvalidUrl), 1);
3859 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
bncc055fa32017-06-19 13:44:423860}
3861
3862// Regression test for https://crbug.com/727653.
3863TEST_F(SpdyNetworkTransactionTest, RejectServerPushWithInvalidMethod) {
Bence Békyeacd48f2018-05-14 11:34:333864 base::HistogramTester histogram_tester;
3865
Ryan Hamilton0239aac2018-05-19 00:03:133866 spdy::SpdySerializedFrame req(
3867 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
3868 spdy::SpdySerializedFrame rst(
3869 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
bncc055fa32017-06-19 13:44:423870 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 3)};
3871
Ryan Hamilton0239aac2018-05-19 00:03:133872 spdy::SpdySerializedFrame reply(
3873 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncc055fa32017-06-19 13:44:423874
Ryan Hamilton0239aac2018-05-19 00:03:133875 spdy::SpdyHeaderBlock push_promise_header_block;
bncc055fa32017-06-19 13:44:423876 push_promise_header_block[":method"] = "POST";
Bence Békyd2df6c1c82018-04-20 22:52:013877 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, &push_promise_header_block);
Ryan Hamilton0239aac2018-05-19 00:03:133878 spdy::SpdySerializedFrame push_promise(spdy_util_.ConstructSpdyPushPromise(
Bence Békyf1d78522018-01-11 01:16:503879 1, 2, std::move(push_promise_header_block)));
bncc055fa32017-06-19 13:44:423880
Ryan Hamilton0239aac2018-05-19 00:03:133881 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Békyf1d78522018-01-11 01:16:503882 MockRead reads[] = {CreateMockRead(reply, 1), CreateMockRead(push_promise, 2),
3883 CreateMockRead(body, 4),
3884 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5)};
bncc055fa32017-06-19 13:44:423885
Ryan Sleevib8d7ea02018-05-07 20:01:013886 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:103887 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bncc055fa32017-06-19 13:44:423888 helper.RunToCompletion(&data);
Bence Békyeacd48f2018-05-14 11:34:333889
3890 histogram_tester.ExpectBucketCount(
3891 "Net.SpdyPushedStreamFate",
3892 static_cast<int>(SpdyPushedStreamFate::kInvalidUrl), 1);
3893 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
bncc055fa32017-06-19 13:44:423894}
3895
bnc42331402016-07-25 13:36:153896// Verify that various response headers parse correctly through the HTTP layer.
3897TEST_F(SpdyNetworkTransactionTest, ResponseHeaders) {
3898 struct ResponseHeadersTests {
Bence Békye5438512017-11-22 23:07:423899 int extra_header_count;
3900 const char* extra_headers[4];
3901 size_t expected_header_count;
Bence Béky4e83f492018-05-13 23:14:253902 base::StringPiece expected_headers[8];
Bence Békye5438512017-11-22 23:07:423903 } test_cases[] = {
3904 // No extra headers.
3905 {0, {}, 2, {"status", "200", "hello", "bye"}},
3906 // Comma-separated header value.
3907 {1,
3908 {"cookie", "val1, val2"},
3909 3,
3910 {"status", "200", "hello", "bye", "cookie", "val1, val2"}},
3911 // Multiple headers are preserved: they are joined with \0 separator in
Ryan Hamilton0239aac2018-05-19 00:03:133912 // spdy::SpdyHeaderBlock.AppendValueOrAddHeader(), then split up in
Bence Békye5438512017-11-22 23:07:423913 // HpackEncoder, then joined with \0 separator when
Ryan Hamilton0239aac2018-05-19 00:03:133914 // spdy::HpackDecoderAdapter::ListenerAdapter::OnHeader() calls
3915 // spdy::SpdyHeaderBlock.AppendValueOrAddHeader(), then split up again in
Bence Békye5438512017-11-22 23:07:423916 // HttpResponseHeaders.
3917 {2,
3918 {"content-encoding", "val1", "content-encoding", "val2"},
3919 4,
3920 {"status", "200", "hello", "bye", "content-encoding", "val1",
3921 "content-encoding", "val2"}},
3922 // Cookie header is not split up by HttpResponseHeaders.
3923 {2,
3924 {"cookie", "val1", "cookie", "val2"},
3925 3,
3926 {"status", "200", "hello", "bye", "cookie", "val1; val2"}}};
bnc7ecc1122015-09-28 13:22:493927
Avi Drissman4365a4782018-12-28 19:26:243928 for (size_t i = 0; i < base::size(test_cases); ++i) {
bncd16676a2016-07-20 16:23:013929 SpdyTestUtil spdy_test_util;
Ryan Hamilton0239aac2018-05-19 00:03:133930 spdy::SpdySerializedFrame req(
Bence Béky27ad0a12018-02-08 00:35:483931 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:413932 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8b070372009-11-16 22:01:253933
Ryan Hamilton0239aac2018-05-19 00:03:133934 spdy::SpdySerializedFrame resp(spdy_test_util.ConstructSpdyGetReply(
Bence Békye5438512017-11-22 23:07:423935 test_cases[i].extra_headers, test_cases[i].extra_header_count, 1));
Ryan Hamilton0239aac2018-05-19 00:03:133936 spdy::SpdySerializedFrame body(
3937 spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]8b070372009-11-16 22:01:253938 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413939 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:523940 MockRead(ASYNC, 0, 3) // EOF
[email protected]8b070372009-11-16 22:01:253941 };
3942
Ryan Sleevib8d7ea02018-05-07 20:01:013943 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:103944 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
3945 nullptr);
[email protected]dd54bd82012-07-19 23:44:573946 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473947 TransactionHelperResult out = helper.output();
3948
robpercival214763f2016-07-01 23:27:013949 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023950 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8b070372009-11-16 22:01:253951 EXPECT_EQ("hello!", out.response_data);
3952
3953 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
wezca1070932016-05-26 20:30:523954 EXPECT_TRUE(headers);
olli.raula33c282f2016-01-21 12:12:493955 size_t iter = 0;
Bence Béky4e83f492018-05-13 23:14:253956 std::string name, value;
Bence Békye5438512017-11-22 23:07:423957 size_t expected_header_index = 0;
[email protected]8b070372009-11-16 22:01:253958 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
Bence Békye5438512017-11-22 23:07:423959 ASSERT_LT(expected_header_index, test_cases[i].expected_header_count)
3960 << i;
3961 EXPECT_EQ(name, test_cases[i].expected_headers[2 * expected_header_index])
3962 << i;
3963 EXPECT_EQ(value,
3964 test_cases[i].expected_headers[2 * expected_header_index + 1])
3965 << i;
3966 ++expected_header_index;
[email protected]8b070372009-11-16 22:01:253967 }
Bence Békye5438512017-11-22 23:07:423968 EXPECT_EQ(expected_header_index, test_cases[i].expected_header_count) << i;
[email protected]8b070372009-11-16 22:01:253969 }
3970}
3971
bnc42331402016-07-25 13:36:153972// Verify that various response headers parse vary fields correctly through the
3973// HTTP layer, and the response matches the request.
3974TEST_F(SpdyNetworkTransactionTest, ResponseHeadersVary) {
[email protected]3f662f12010-03-25 19:56:123975 // Modify the following data to change/add test cases:
bnc42331402016-07-25 13:36:153976 struct ResponseTests {
[email protected]3f662f12010-03-25 19:56:123977 bool vary_matches;
3978 int num_headers[2];
3979 const char* extra_headers[2][16];
3980 } test_cases[] = {
bnc7ecc1122015-09-28 13:22:493981 // Test the case of a multi-valued cookie. When the value is delimited
3982 // with NUL characters, it needs to be unfolded into multiple headers.
3983 {true,
bnca9b9e222016-07-11 20:10:403984 {1, 3},
tombergan5d22c182017-01-11 02:05:353985 {{"cookie", "val1,val2", nullptr},
Ryan Hamilton0239aac2018-05-19 00:03:133986 {spdy::kHttp2StatusHeader, "200", spdy::kHttp2PathHeader, "/index.php",
3987 "vary", "cookie", nullptr}}},
bnc7ecc1122015-09-28 13:22:493988 {// Multiple vary fields.
3989 true,
bnc7ecc1122015-09-28 13:22:493990 {2, 4},
tombergan5d22c182017-01-11 02:05:353991 {{"friend", "barney", "enemy", "snaggletooth", nullptr},
Ryan Hamilton0239aac2018-05-19 00:03:133992 {spdy::kHttp2StatusHeader, "200", spdy::kHttp2PathHeader, "/index.php",
3993 "vary", "friend", "vary", "enemy", nullptr}}},
bnca9b9e222016-07-11 20:10:403994 {// Test a '*' vary field.
Maks Orlovich722dc112017-11-10 00:29:303995 true,
bnca9b9e222016-07-11 20:10:403996 {1, 3},
tombergan5d22c182017-01-11 02:05:353997 {{"cookie", "val1,val2", nullptr},
Ryan Hamilton0239aac2018-05-19 00:03:133998 {spdy::kHttp2StatusHeader, "200", spdy::kHttp2PathHeader, "/index.php",
3999 "vary", "*", nullptr}}},
Maks Orlovich722dc112017-11-10 00:29:304000 {// Test w/o a vary field.
4001 false,
4002 {1, 2},
4003 {{"cookie", "val1,val2", nullptr},
Ryan Hamilton0239aac2018-05-19 00:03:134004 {spdy::kHttp2StatusHeader, "200", spdy::kHttp2PathHeader, "/index.php",
4005 nullptr}}},
Maks Orlovich722dc112017-11-10 00:29:304006
bnca9b9e222016-07-11 20:10:404007 {// Multiple comma-separated vary fields.
4008 true,
4009 {2, 3},
tombergan5d22c182017-01-11 02:05:354010 {{"friend", "barney", "enemy", "snaggletooth", nullptr},
Ryan Hamilton0239aac2018-05-19 00:03:134011 {spdy::kHttp2StatusHeader, "200", spdy::kHttp2PathHeader, "/index.php",
4012 "vary", "friend,enemy", nullptr}}}};
[email protected]3f662f12010-03-25 19:56:124013
Avi Drissman4365a4782018-12-28 19:26:244014 for (size_t i = 0; i < base::size(test_cases); ++i) {
bncd16676a2016-07-20 16:23:014015 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:494016
[email protected]3f662f12010-03-25 19:56:124017 // Construct the request.
Ryan Hamilton0239aac2018-05-19 00:03:134018 spdy::SpdySerializedFrame frame_req(spdy_test_util.ConstructSpdyGet(
Bence Béky27ad0a12018-02-08 00:35:484019 test_cases[i].extra_headers[0], test_cases[i].num_headers[0], 1,
4020 LOWEST));
[email protected]3f662f12010-03-25 19:56:124021
4022 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414023 CreateMockWrite(frame_req, 0),
[email protected]3f662f12010-03-25 19:56:124024 };
4025
4026 // Construct the reply.
Ryan Hamilton0239aac2018-05-19 00:03:134027 spdy::SpdyHeaderBlock reply_headers;
[email protected]745aa9c2014-06-27 02:21:294028 AppendToHeaderBlock(test_cases[i].extra_headers[1],
4029 test_cases[i].num_headers[1],
4030 &reply_headers);
bnc086b39e12016-06-24 13:05:264031 // Construct the expected header reply string before moving |reply_headers|.
Bence Béky4e83f492018-05-13 23:14:254032 std::string expected_reply =
bnc086b39e12016-06-24 13:05:264033 spdy_test_util.ConstructSpdyReplyString(reply_headers);
4034
Ryan Hamilton0239aac2018-05-19 00:03:134035 spdy::SpdySerializedFrame frame_reply(
bnc086b39e12016-06-24 13:05:264036 spdy_test_util.ConstructSpdyReply(1, std::move(reply_headers)));
[email protected]3f662f12010-03-25 19:56:124037
Ryan Hamilton0239aac2018-05-19 00:03:134038 spdy::SpdySerializedFrame body(
4039 spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]3f662f12010-03-25 19:56:124040 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414041 CreateMockRead(frame_reply, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:524042 MockRead(ASYNC, 0, 3) // EOF
[email protected]3f662f12010-03-25 19:56:124043 };
4044
[email protected]3f662f12010-03-25 19:56:124045 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:434046 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:124047
Bence Békydb3cf652017-10-10 15:22:104048 HttpRequestInfo request;
4049 request.method = "GET";
4050 request.url = GURL(kDefaultUrl);
Ramin Halavatib5e433e62018-02-07 07:41:104051 request.traffic_annotation =
4052 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c76ae22010-04-20 22:15:434053 for (int ct = 0; ct < header_count; ct++) {
4054 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
4055 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
4056 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:124057 }
4058
Ryan Sleevib8d7ea02018-05-07 20:01:014059 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:104060
Bence Békyd3dde832017-09-19 19:02:314061 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, log_,
4062 nullptr);
Bence Békydb3cf652017-10-10 15:22:104063
[email protected]dd54bd82012-07-19 23:44:574064 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:474065 TransactionHelperResult out = helper.output();
4066
[email protected]3f662f12010-03-25 19:56:124067 EXPECT_EQ(OK, out.rv) << i;
bnc84e7fb52015-12-02 11:50:024068 EXPECT_EQ("HTTP/1.1 200", out.status_line) << i;
[email protected]3f662f12010-03-25 19:56:124069 EXPECT_EQ("hello!", out.response_data) << i;
4070
4071 // Test the response information.
[email protected]3f662f12010-03-25 19:56:124072 EXPECT_EQ(out.response_info.vary_data.is_valid(),
4073 test_cases[i].vary_matches) << i;
4074
4075 // Check the headers.
4076 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
wezca1070932016-05-26 20:30:524077 ASSERT_TRUE(headers) << i;
olli.raula33c282f2016-01-21 12:12:494078 size_t iter = 0;
Bence Béky4e83f492018-05-13 23:14:254079 std::string name, value, lines;
[email protected]3f662f12010-03-25 19:56:124080 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
4081 lines.append(name);
4082 lines.append(": ");
4083 lines.append(value);
4084 lines.append("\n");
4085 }
4086
[email protected]9aa323192013-05-31 21:38:404087 EXPECT_EQ(expected_reply, lines) << i;
[email protected]3f662f12010-03-25 19:56:124088 }
4089}
4090
bnc42331402016-07-25 13:36:154091// Verify that we don't crash on invalid response headers.
4092TEST_F(SpdyNetworkTransactionTest, InvalidResponseHeaders) {
4093 struct InvalidResponseHeadersTests {
[email protected]e7f75092010-07-01 22:39:134094 int num_headers;
4095 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:484096 } test_cases[] = {
bnc42331402016-07-25 13:36:154097 // Response headers missing status header
bnc7ecc1122015-09-28 13:22:494098 {
bnca9b9e222016-07-11 20:10:404099 3,
Ryan Hamilton0239aac2018-05-19 00:03:134100 {spdy::kHttp2PathHeader, "/index.php", "cookie", "val1", "cookie",
4101 "val2", nullptr},
[email protected]e7f75092010-07-01 22:39:134102 },
bnc42331402016-07-25 13:36:154103 // Response headers missing version header
bnc7ecc1122015-09-28 13:22:494104 {
Ryan Hamilton0239aac2018-05-19 00:03:134105 1, {spdy::kHttp2PathHeader, "/index.php", "status", "200", nullptr},
[email protected]e7f75092010-07-01 22:39:134106 },
bnc42331402016-07-25 13:36:154107 // Response headers with no headers
bnc7ecc1122015-09-28 13:22:494108 {
tombergan5d22c182017-01-11 02:05:354109 0, {nullptr},
bnc7ecc1122015-09-28 13:22:494110 },
[email protected]dd11b932009-11-30 19:39:484111 };
4112
Avi Drissman4365a4782018-12-28 19:26:244113 for (size_t i = 0; i < base::size(test_cases); ++i) {
bncd16676a2016-07-20 16:23:014114 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:494115
Ryan Hamilton0239aac2018-05-19 00:03:134116 spdy::SpdySerializedFrame req(
Bence Béky27ad0a12018-02-08 00:35:484117 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:134118 spdy::SpdySerializedFrame rst(spdy_test_util.ConstructSpdyRstStream(
4119 1, spdy::ERROR_CODE_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:484120 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414121 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
[email protected]dd11b932009-11-30 19:39:484122 };
4123
[email protected]745aa9c2014-06-27 02:21:294124 // Construct the reply.
Ryan Hamilton0239aac2018-05-19 00:03:134125 spdy::SpdyHeaderBlock reply_headers;
[email protected]745aa9c2014-06-27 02:21:294126 AppendToHeaderBlock(
4127 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
Ryan Hamilton0239aac2018-05-19 00:03:134128 spdy::SpdySerializedFrame resp(
bnc086b39e12016-06-24 13:05:264129 spdy_test_util.ConstructSpdyReply(1, std::move(reply_headers)));
[email protected]dd11b932009-11-30 19:39:484130 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414131 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]dd11b932009-11-30 19:39:484132 };
4133
Ryan Sleevib8d7ea02018-05-07 20:01:014134 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:104135 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
4136 nullptr);
[email protected]dd54bd82012-07-19 23:44:574137 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:474138 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014139 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:484140 }
4141}
4142
bncd16676a2016-07-20 16:23:014143TEST_F(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
Ryan Hamilton0239aac2018-05-19 00:03:134144 spdy::SpdySerializedFrame req(
4145 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
4146 spdy::SpdySerializedFrame goaway(
4147 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_COMPRESSION_ERROR,
diannahu9904e272017-02-03 14:40:084148 "Framer error: 6 (DECOMPRESS_FAILURE)."));
bncdf80d44fd2016-07-15 20:27:414149 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]e3352df2014-03-19 05:55:424150
bnc38dcd392016-02-09 23:19:494151 // This is the length field that's too short.
Ryan Hamilton0239aac2018-05-19 00:03:134152 spdy::SpdySerializedFrame reply_wrong_length(
bnc42331402016-07-25 13:36:154153 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:134154 size_t right_size = reply_wrong_length.size() - spdy::kFrameHeaderSize;
bnc38dcd392016-02-09 23:19:494155 size_t wrong_size = right_size - 4;
Ryan Hamilton0239aac2018-05-19 00:03:134156 spdy::test::SetFrameLength(&reply_wrong_length, wrong_size);
bnc38dcd392016-02-09 23:19:494157
[email protected]e3352df2014-03-19 05:55:424158 MockRead reads[] = {
bnc42331402016-07-25 13:36:154159 MockRead(ASYNC, reply_wrong_length.data(), reply_wrong_length.size() - 4,
4160 1),
[email protected]e3352df2014-03-19 05:55:424161 };
4162
Ryan Sleevib8d7ea02018-05-07 20:01:014163 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:104164 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]e3352df2014-03-19 05:55:424165 helper.RunToCompletion(&data);
4166 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014167 EXPECT_THAT(out.rv, IsError(ERR_SPDY_COMPRESSION_ERROR));
[email protected]bdd1b222014-06-10 11:08:394168}
4169
bncd16676a2016-07-20 16:23:014170TEST_F(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
Ryan Hamilton0239aac2018-05-19 00:03:134171 spdy::SpdySerializedFrame req(
4172 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
4173 spdy::SpdySerializedFrame goaway(
4174 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_COMPRESSION_ERROR,
diannahu9904e272017-02-03 14:40:084175 "Framer error: 6 (DECOMPRESS_FAILURE)."));
bncdf80d44fd2016-07-15 20:27:414176 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:394177
4178 // Read HEADERS with corrupted payload.
Ryan Hamilton0239aac2018-05-19 00:03:134179 spdy::SpdySerializedFrame resp(
4180 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414181 memset(resp.data() + 12, 0xcf, resp.size() - 12);
4182 MockRead reads[] = {CreateMockRead(resp, 1)};
[email protected]bdd1b222014-06-10 11:08:394183
Ryan Sleevib8d7ea02018-05-07 20:01:014184 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:104185 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]bdd1b222014-06-10 11:08:394186 helper.RunToCompletion(&data);
4187 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014188 EXPECT_THAT(out.rv, IsError(ERR_SPDY_COMPRESSION_ERROR));
[email protected]bdd1b222014-06-10 11:08:394189}
4190
bncd16676a2016-07-20 16:23:014191TEST_F(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
Ryan Hamilton0239aac2018-05-19 00:03:134192 spdy::SpdySerializedFrame req(
4193 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
4194 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
4195 0, spdy::ERROR_CODE_FRAME_SIZE_ERROR,
dahollingsaf3796492016-05-25 19:21:354196 "Framer error: 15 (INVALID_CONTROL_FRAME_SIZE)."));
bncdf80d44fd2016-07-15 20:27:414197 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:394198
4199 // Read WINDOW_UPDATE with incorrectly-sized payload.
Ryan Hamilton0239aac2018-05-19 00:03:134200 spdy::SpdySerializedFrame bad_window_update(
[email protected]bdd1b222014-06-10 11:08:394201 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:134202 spdy::test::SetFrameLength(&bad_window_update, bad_window_update.size() - 1);
bncdf80d44fd2016-07-15 20:27:414203 MockRead reads[] = {CreateMockRead(bad_window_update, 1)};
[email protected]bdd1b222014-06-10 11:08:394204
Ryan Sleevib8d7ea02018-05-07 20:01:014205 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:104206 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]bdd1b222014-06-10 11:08:394207 helper.RunToCompletion(&data);
4208 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014209 EXPECT_THAT(out.rv, IsError(ERR_SPDY_FRAME_SIZE_ERROR));
[email protected]e3352df2014-03-19 05:55:424210}
4211
[email protected]bf2491a92009-11-29 16:39:484212// Test that we shutdown correctly on write errors.
bncd16676a2016-07-20 16:23:014213TEST_F(SpdyNetworkTransactionTest, WriteError) {
Ryan Hamilton0239aac2018-05-19 00:03:134214 spdy::SpdySerializedFrame req(
4215 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
[email protected]bf2491a92009-11-29 16:39:484216 MockWrite writes[] = {
[email protected]bdd1b222014-06-10 11:08:394217 // We'll write 10 bytes successfully
bncdf80d44fd2016-07-15 20:27:414218 MockWrite(ASYNC, req.data(), 10, 1),
[email protected]bdd1b222014-06-10 11:08:394219 // Followed by ERROR!
[email protected]bdd1b222014-06-10 11:08:394220 MockWrite(ASYNC, ERR_FAILED, 2),
mmenke666a6fea2015-12-19 04:16:334221 // Session drains and attempts to write a GOAWAY: Another ERROR!
4222 MockWrite(ASYNC, ERR_FAILED, 3),
[email protected]bf2491a92009-11-29 16:39:484223 };
4224
mmenke666a6fea2015-12-19 04:16:334225 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
[email protected]238002d2013-10-17 02:01:404226
Ryan Sleevib8d7ea02018-05-07 20:01:014227 SequencedSocketData data(reads, writes);
[email protected]238002d2013-10-17 02:01:404228
Bence Békydb3cf652017-10-10 15:22:104229 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]238002d2013-10-17 02:01:404230 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:334231 helper.AddData(&data);
[email protected]238002d2013-10-17 02:01:404232 EXPECT_TRUE(helper.StartDefaultTest());
[email protected]238002d2013-10-17 02:01:404233 helper.FinishDefaultTest();
rch37de576c2015-05-17 20:28:174234 EXPECT_TRUE(data.AllWriteDataConsumed());
mmenke666a6fea2015-12-19 04:16:334235 EXPECT_TRUE(data.AllReadDataConsumed());
[email protected]3caf5542010-07-16 15:19:474236 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014237 EXPECT_THAT(out.rv, IsError(ERR_FAILED));
[email protected]bf2491a92009-11-29 16:39:484238}
4239
4240// Test that partial writes work.
bncd16676a2016-07-20 16:23:014241TEST_F(SpdyNetworkTransactionTest, PartialWrite) {
bnc42331402016-07-25 13:36:154242 // Chop the HEADERS frame into 5 chunks.
Ryan Hamilton0239aac2018-05-19 00:03:134243 spdy::SpdySerializedFrame req(
4244 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
[email protected]bf2491a92009-11-29 16:39:484245 const int kChunks = 5;
bnc3f6a8552017-05-17 13:40:344246 std::unique_ptr<MockWrite[]> writes = ChopWriteFrame(req, kChunks);
rch08e3aa3e2015-05-16 14:27:524247 for (int i = 0; i < kChunks; ++i) {
4248 writes[i].sequence_number = i;
4249 }
[email protected]bf2491a92009-11-29 16:39:484250
Ryan Hamilton0239aac2018-05-19 00:03:134251 spdy::SpdySerializedFrame resp(
4252 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4253 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:484254 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414255 CreateMockRead(resp, kChunks), CreateMockRead(body, kChunks + 1),
rch08e3aa3e2015-05-16 14:27:524256 MockRead(ASYNC, 0, kChunks + 2) // EOF
[email protected]bf2491a92009-11-29 16:39:484257 };
4258
Ryan Sleevib8d7ea02018-05-07 20:01:014259 SequencedSocketData data(reads, base::make_span(writes.get(), kChunks));
Bence Békydb3cf652017-10-10 15:22:104260 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:574261 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:474262 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014263 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:024264 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bf2491a92009-11-29 16:39:484265 EXPECT_EQ("hello!", out.response_data);
4266}
4267
[email protected]9e743cd2010-03-16 07:03:534268// Test that the NetLog contains good data for a simple GET request.
bncd16676a2016-07-20 16:23:014269TEST_F(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:404270 static const char* const kExtraHeaders[] = {
4271 "user-agent", "Chrome",
4272 };
Ryan Hamilton0239aac2018-05-19 00:03:134273 spdy::SpdySerializedFrame req(
Bence Béky27ad0a12018-02-08 00:35:484274 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414275 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]dac358042009-12-18 02:07:484276
Ryan Hamilton0239aac2018-05-19 00:03:134277 spdy::SpdySerializedFrame resp(
4278 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4279 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]dac358042009-12-18 02:07:484280 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414281 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:524282 MockRead(ASYNC, 0, 3) // EOF
[email protected]dac358042009-12-18 02:07:484283 };
4284
vishal.b62985ca92015-04-17 08:45:514285 BoundTestNetLog log;
[email protected]dac358042009-12-18 02:07:484286
Ryan Sleevib8d7ea02018-05-07 20:01:014287 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:104288 request_.extra_headers.SetHeader("User-Agent", "Chrome");
4289 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log.bound(),
4290 nullptr);
[email protected]dd54bd82012-07-19 23:44:574291 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:474292 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014293 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:024294 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]dac358042009-12-18 02:07:484295 EXPECT_EQ("hello!", out.response_data);
4296
[email protected]9e743cd2010-03-16 07:03:534297 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:474298 // This test is intentionally non-specific about the exact ordering of the
4299 // log; instead we just check to make sure that certain events exist, and that
4300 // they are in the right order.
mmenke43758e62015-05-04 21:09:464301 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:404302 log.GetEntries(&entries);
4303
4304 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:484305 int pos = 0;
mikecirone8b85c432016-09-08 19:11:004306 pos = ExpectLogContainsSomewhere(
4307 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST,
4308 NetLogEventPhase::BEGIN);
4309 pos = ExpectLogContainsSomewhere(
4310 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST,
4311 NetLogEventPhase::END);
4312 pos = ExpectLogContainsSomewhere(
4313 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_READ_HEADERS,
4314 NetLogEventPhase::BEGIN);
4315 pos = ExpectLogContainsSomewhere(
4316 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_READ_HEADERS,
4317 NetLogEventPhase::END);
bnc301745a2015-03-10 03:22:164318 pos = ExpectLogContainsSomewhere(entries, pos + 1,
mikecirone8b85c432016-09-08 19:11:004319 NetLogEventType::HTTP_TRANSACTION_READ_BODY,
4320 NetLogEventPhase::BEGIN);
bnc301745a2015-03-10 03:22:164321 pos = ExpectLogContainsSomewhere(entries, pos + 1,
mikecirone8b85c432016-09-08 19:11:004322 NetLogEventType::HTTP_TRANSACTION_READ_BODY,
4323 NetLogEventPhase::END);
[email protected]3deb9a52010-11-11 00:24:404324
4325 // Check that we logged all the headers correctly
mikecirone8b85c432016-09-08 19:11:004326 pos = ExpectLogContainsSomewhere(entries, 0,
4327 NetLogEventType::HTTP2_SESSION_SEND_HEADERS,
4328 NetLogEventPhase::NONE);
[email protected]3deb9a52010-11-11 00:24:404329
Bence Béky66871e32018-12-06 21:11:244330 ASSERT_TRUE(entries[pos].params);
4331 auto* header_list = entries[pos].params->FindKey("headers");
4332 ASSERT_TRUE(header_list);
4333 ASSERT_TRUE(header_list->is_list());
4334 ASSERT_EQ(5u, header_list->GetList().size());
[email protected]f3da152d2012-06-02 01:00:574335
Bence Béky66871e32018-12-06 21:11:244336 ASSERT_TRUE(header_list->GetList()[0].is_string());
4337 EXPECT_EQ(":method: GET", header_list->GetList()[0].GetString());
4338
4339 ASSERT_TRUE(header_list->GetList()[1].is_string());
4340 EXPECT_EQ(":authority: www.example.org",
4341 header_list->GetList()[1].GetString());
4342
4343 ASSERT_TRUE(header_list->GetList()[2].is_string());
4344 EXPECT_EQ(":scheme: https", header_list->GetList()[2].GetString());
4345
4346 ASSERT_TRUE(header_list->GetList()[3].is_string());
4347 EXPECT_EQ(":path: /", header_list->GetList()[3].GetString());
4348
4349 ASSERT_TRUE(header_list->GetList()[4].is_string());
4350 EXPECT_EQ("user-agent: Chrome", header_list->GetList()[4].GetString());
[email protected]dac358042009-12-18 02:07:484351}
4352
[email protected]79d84222010-02-26 00:01:444353// Since we buffer the IO from the stream to the renderer, this test verifies
4354// that when we read out the maximum amount of data (e.g. we received 50 bytes
4355// on the network, but issued a Read for only 5 of those bytes) that the data
4356// flow still works correctly.
bncd16676a2016-07-20 16:23:014357TEST_F(SpdyNetworkTransactionTest, BufferFull) {
Ryan Hamilton0239aac2018-05-19 00:03:134358 spdy::SpdySerializedFrame req(
4359 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414360 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]79d84222010-02-26 00:01:444361
[email protected]20d005f2010-07-02 19:55:434362 // 2 data frames in a single read.
Ryan Hamilton0239aac2018-05-19 00:03:134363 spdy::SpdySerializedFrame data_frame_1(
Bence Békyd74f4382018-02-20 18:26:194364 spdy_util_.ConstructSpdyDataFrame(1, "goodby", /*fin=*/false));
Ryan Hamilton0239aac2018-05-19 00:03:134365 spdy::SpdySerializedFrame data_frame_2(
Bence Békyd74f4382018-02-20 18:26:194366 spdy_util_.ConstructSpdyDataFrame(1, "e worl", /*fin=*/false));
Ryan Hamilton0239aac2018-05-19 00:03:134367 spdy::SpdySerializedFrame combined_data_frames =
bncef26b602017-06-12 22:08:194368 CombineFrames({&data_frame_1, &data_frame_2});
4369
Ryan Hamilton0239aac2018-05-19 00:03:134370 spdy::SpdySerializedFrame last_frame(
Bence Békyd74f4382018-02-20 18:26:194371 spdy_util_.ConstructSpdyDataFrame(1, "d", /*fin=*/true));
[email protected]79d84222010-02-26 00:01:444372
Ryan Hamilton0239aac2018-05-19 00:03:134373 spdy::SpdySerializedFrame resp(
4374 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]79d84222010-02-26 00:01:444375 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414376 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:094377 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
bncef26b602017-06-12 22:08:194378 CreateMockRead(combined_data_frames, 3),
rch32320842015-05-16 15:57:094379 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
bncdf80d44fd2016-07-15 20:27:414380 CreateMockRead(last_frame, 5),
rch32320842015-05-16 15:57:094381 MockRead(ASYNC, 0, 6) // EOF
[email protected]79d84222010-02-26 00:01:444382 };
4383
Ryan Sleevib8d7ea02018-05-07 20:01:014384 SequencedSocketData data(reads, writes);
[email protected]79d84222010-02-26 00:01:444385
[email protected]49639fa2011-12-20 23:22:414386 TestCompletionCallback callback;
[email protected]79d84222010-02-26 00:01:444387
Bence Békydb3cf652017-10-10 15:22:104388 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]3caf5542010-07-16 15:19:474389 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574390 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474391 HttpNetworkTransaction* trans = helper.trans();
Bence Békydb3cf652017-10-10 15:22:104392 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:014393 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79d84222010-02-26 00:01:444394
[email protected]3caf5542010-07-16 15:19:474395 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:444396 out.rv = callback.WaitForResult();
4397 EXPECT_EQ(out.rv, OK);
4398
4399 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524400 EXPECT_TRUE(response->headers);
[email protected]79d84222010-02-26 00:01:444401 EXPECT_TRUE(response->was_fetched_via_spdy);
4402 out.status_line = response->headers->GetStatusLine();
4403 out.response_info = *response; // Make a copy so we can verify.
4404
4405 // Read Data
[email protected]49639fa2011-12-20 23:22:414406 TestCompletionCallback read_callback;
[email protected]79d84222010-02-26 00:01:444407
Bence Béky4e83f492018-05-13 23:14:254408 std::string content;
[email protected]79d84222010-02-26 00:01:444409 do {
4410 // Read small chunks at a time.
4411 const int kSmallReadSize = 3;
Victor Costan9c7302b2018-08-27 16:39:444412 scoped_refptr<IOBuffer> buf =
4413 base::MakeRefCounted<IOBuffer>(kSmallReadSize);
[email protected]90499482013-06-01 00:39:504414 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:164415 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:594416 data.Resume();
[email protected]79d84222010-02-26 00:01:444417 rv = read_callback.WaitForResult();
4418 }
4419 if (rv > 0) {
4420 content.append(buf->data(), rv);
4421 } else if (rv < 0) {
4422 NOTREACHED();
4423 }
4424 } while (rv > 0);
4425
4426 out.response_data.swap(content);
4427
[email protected]30c942b2010-07-21 16:59:594428 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:554429 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:174430 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:554431
[email protected]79d84222010-02-26 00:01:444432 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474433 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:444434
robpercival214763f2016-07-01 23:27:014435 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:024436 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]79d84222010-02-26 00:01:444437 EXPECT_EQ("goodbye world", out.response_data);
4438}
4439
[email protected]8918d282010-03-02 00:57:554440// Verify that basic buffering works; when multiple data frames arrive
4441// at the same time, ensure that we don't notify a read completion for
4442// each data frame individually.
bncd16676a2016-07-20 16:23:014443TEST_F(SpdyNetworkTransactionTest, Buffering) {
Ryan Hamilton0239aac2018-05-19 00:03:134444 spdy::SpdySerializedFrame req(
4445 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414446 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:554447
4448 // 4 data frames in a single read.
Ryan Hamilton0239aac2018-05-19 00:03:134449 spdy::SpdySerializedFrame data_frame(
Bence Békyd74f4382018-02-20 18:26:194450 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false));
Ryan Hamilton0239aac2018-05-19 00:03:134451 spdy::SpdySerializedFrame data_frame_fin(
Bence Békyd74f4382018-02-20 18:26:194452 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/true));
Ryan Hamilton0239aac2018-05-19 00:03:134453 spdy::SpdySerializedFrame combined_data_frames =
bncef26b602017-06-12 22:08:194454 CombineFrames({&data_frame, &data_frame, &data_frame, &data_frame_fin});
[email protected]8918d282010-03-02 00:57:554455
Ryan Hamilton0239aac2018-05-19 00:03:134456 spdy::SpdySerializedFrame resp(
4457 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8918d282010-03-02 00:57:554458 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414459 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:094460 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
bncef26b602017-06-12 22:08:194461 CreateMockRead(combined_data_frames, 3), MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:554462 };
4463
Ryan Sleevib8d7ea02018-05-07 20:01:014464 SequencedSocketData data(reads, writes);
[email protected]8918d282010-03-02 00:57:554465
Bence Békydb3cf652017-10-10 15:22:104466 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]3caf5542010-07-16 15:19:474467 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574468 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474469 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:554470
[email protected]49639fa2011-12-20 23:22:414471 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:104472 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:014473 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:554474
[email protected]3caf5542010-07-16 15:19:474475 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:554476 out.rv = callback.WaitForResult();
4477 EXPECT_EQ(out.rv, OK);
4478
4479 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524480 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:554481 EXPECT_TRUE(response->was_fetched_via_spdy);
4482 out.status_line = response->headers->GetStatusLine();
4483 out.response_info = *response; // Make a copy so we can verify.
4484
4485 // Read Data
[email protected]49639fa2011-12-20 23:22:414486 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:554487
Bence Béky4e83f492018-05-13 23:14:254488 std::string content;
[email protected]8918d282010-03-02 00:57:554489 int reads_completed = 0;
4490 do {
4491 // Read small chunks at a time.
4492 const int kSmallReadSize = 14;
Victor Costan9c7302b2018-08-27 16:39:444493 scoped_refptr<IOBuffer> buf =
4494 base::MakeRefCounted<IOBuffer>(kSmallReadSize);
[email protected]90499482013-06-01 00:39:504495 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:164496 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:594497 data.Resume();
[email protected]8918d282010-03-02 00:57:554498 rv = read_callback.WaitForResult();
4499 }
4500 if (rv > 0) {
4501 EXPECT_EQ(kSmallReadSize, rv);
4502 content.append(buf->data(), rv);
4503 } else if (rv < 0) {
4504 FAIL() << "Unexpected read error: " << rv;
4505 }
4506 reads_completed++;
4507 } while (rv > 0);
4508
4509 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
4510
4511 out.response_data.swap(content);
4512
[email protected]30c942b2010-07-21 16:59:594513 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:554514 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:174515 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:554516
4517 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474518 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:554519
robpercival214763f2016-07-01 23:27:014520 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:024521 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:554522 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4523}
4524
4525// Verify the case where we buffer data but read it after it has been buffered.
bncd16676a2016-07-20 16:23:014526TEST_F(SpdyNetworkTransactionTest, BufferedAll) {
Ryan Hamilton0239aac2018-05-19 00:03:134527 spdy::SpdySerializedFrame req(
4528 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414529 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:554530
[email protected]20d005f2010-07-02 19:55:434531 // 5 data frames in a single read.
Ryan Hamilton0239aac2018-05-19 00:03:134532 spdy::SpdySerializedFrame reply(
4533 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4534 spdy::SpdySerializedFrame data_frame(
Bence Békyd74f4382018-02-20 18:26:194535 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false));
Ryan Hamilton0239aac2018-05-19 00:03:134536 spdy::SpdySerializedFrame data_frame_fin(
Bence Békyd74f4382018-02-20 18:26:194537 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/true));
Ryan Hamilton0239aac2018-05-19 00:03:134538 spdy::SpdySerializedFrame combined_frames = CombineFrames(
bncef26b602017-06-12 22:08:194539 {&reply, &data_frame, &data_frame, &data_frame, &data_frame_fin});
[email protected]8918d282010-03-02 00:57:554540
4541 MockRead reads[] = {
bncef26b602017-06-12 22:08:194542 CreateMockRead(combined_frames, 1), MockRead(ASYNC, 0, 2) // EOF
[email protected]8918d282010-03-02 00:57:554543 };
4544
Ryan Sleevib8d7ea02018-05-07 20:01:014545 SequencedSocketData data(reads, writes);
[email protected]8918d282010-03-02 00:57:554546
Bence Békydb3cf652017-10-10 15:22:104547 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]3caf5542010-07-16 15:19:474548 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574549 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474550 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:554551
[email protected]49639fa2011-12-20 23:22:414552 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:104553 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:014554 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:554555
[email protected]3caf5542010-07-16 15:19:474556 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:554557 out.rv = callback.WaitForResult();
4558 EXPECT_EQ(out.rv, OK);
4559
4560 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524561 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:554562 EXPECT_TRUE(response->was_fetched_via_spdy);
4563 out.status_line = response->headers->GetStatusLine();
4564 out.response_info = *response; // Make a copy so we can verify.
4565
4566 // Read Data
[email protected]49639fa2011-12-20 23:22:414567 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:554568
Bence Béky4e83f492018-05-13 23:14:254569 std::string content;
[email protected]8918d282010-03-02 00:57:554570 int reads_completed = 0;
4571 do {
4572 // Read small chunks at a time.
4573 const int kSmallReadSize = 14;
Victor Costan9c7302b2018-08-27 16:39:444574 scoped_refptr<IOBuffer> buf =
4575 base::MakeRefCounted<IOBuffer>(kSmallReadSize);
[email protected]90499482013-06-01 00:39:504576 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:554577 if (rv > 0) {
4578 EXPECT_EQ(kSmallReadSize, rv);
4579 content.append(buf->data(), rv);
4580 } else if (rv < 0) {
4581 FAIL() << "Unexpected read error: " << rv;
4582 }
4583 reads_completed++;
4584 } while (rv > 0);
4585
4586 EXPECT_EQ(3, reads_completed);
4587
4588 out.response_data.swap(content);
4589
[email protected]30c942b2010-07-21 16:59:594590 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:554591 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:174592 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:554593
4594 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474595 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:554596
robpercival214763f2016-07-01 23:27:014597 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:024598 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:554599 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4600}
4601
4602// Verify the case where we buffer data and close the connection.
bncd16676a2016-07-20 16:23:014603TEST_F(SpdyNetworkTransactionTest, BufferedClosed) {
Ryan Hamilton0239aac2018-05-19 00:03:134604 spdy::SpdySerializedFrame req(
4605 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414606 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:554607
4608 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:434609 // NOTE: We don't FIN the stream.
Ryan Hamilton0239aac2018-05-19 00:03:134610 spdy::SpdySerializedFrame data_frame(
Bence Békyd74f4382018-02-20 18:26:194611 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false));
Ryan Hamilton0239aac2018-05-19 00:03:134612 spdy::SpdySerializedFrame combined_data_frames =
bncef26b602017-06-12 22:08:194613 CombineFrames({&data_frame, &data_frame, &data_frame, &data_frame});
Ryan Hamilton0239aac2018-05-19 00:03:134614 spdy::SpdySerializedFrame resp(
4615 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8918d282010-03-02 00:57:554616 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414617 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:094618 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
bncef26b602017-06-12 22:08:194619 CreateMockRead(combined_data_frames, 3), MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:554620 };
4621
Ryan Sleevib8d7ea02018-05-07 20:01:014622 SequencedSocketData data(reads, writes);
[email protected]8918d282010-03-02 00:57:554623
Bence Békydb3cf652017-10-10 15:22:104624 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]3caf5542010-07-16 15:19:474625 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574626 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474627 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:554628
[email protected]49639fa2011-12-20 23:22:414629 TestCompletionCallback callback;
[email protected]8918d282010-03-02 00:57:554630
Bence Békydb3cf652017-10-10 15:22:104631 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:014632 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:554633
[email protected]3caf5542010-07-16 15:19:474634 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:554635 out.rv = callback.WaitForResult();
4636 EXPECT_EQ(out.rv, OK);
4637
4638 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524639 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:554640 EXPECT_TRUE(response->was_fetched_via_spdy);
4641 out.status_line = response->headers->GetStatusLine();
4642 out.response_info = *response; // Make a copy so we can verify.
4643
4644 // Read Data
[email protected]49639fa2011-12-20 23:22:414645 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:554646
Bence Béky4e83f492018-05-13 23:14:254647 std::string content;
[email protected]8918d282010-03-02 00:57:554648 int reads_completed = 0;
4649 do {
4650 // Read small chunks at a time.
4651 const int kSmallReadSize = 14;
Victor Costan9c7302b2018-08-27 16:39:444652 scoped_refptr<IOBuffer> buf =
4653 base::MakeRefCounted<IOBuffer>(kSmallReadSize);
[email protected]90499482013-06-01 00:39:504654 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:164655 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:594656 data.Resume();
[email protected]8918d282010-03-02 00:57:554657 rv = read_callback.WaitForResult();
4658 }
4659 if (rv > 0) {
4660 content.append(buf->data(), rv);
4661 } else if (rv < 0) {
4662 // This test intentionally closes the connection, and will get an error.
robpercival214763f2016-07-01 23:27:014663 EXPECT_THAT(rv, IsError(ERR_CONNECTION_CLOSED));
[email protected]8918d282010-03-02 00:57:554664 break;
4665 }
4666 reads_completed++;
4667 } while (rv > 0);
4668
4669 EXPECT_EQ(0, reads_completed);
4670
4671 out.response_data.swap(content);
4672
[email protected]30c942b2010-07-21 16:59:594673 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:554674 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:174675 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:554676
4677 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474678 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:554679}
4680
[email protected]1ed7b3dc2010-03-04 05:41:454681// Verify the case where we buffer data and cancel the transaction.
bncd16676a2016-07-20 16:23:014682TEST_F(SpdyNetworkTransactionTest, BufferedCancelled) {
Ryan Hamilton0239aac2018-05-19 00:03:134683 spdy::SpdySerializedFrame req(
4684 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
4685 spdy::SpdySerializedFrame rst(
4686 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
bncdf80d44fd2016-07-15 20:27:414687 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 4)};
[email protected]1ed7b3dc2010-03-04 05:41:454688
[email protected]20d005f2010-07-02 19:55:434689 // NOTE: We don't FIN the stream.
Ryan Hamilton0239aac2018-05-19 00:03:134690 spdy::SpdySerializedFrame data_frame(
Bence Békyd74f4382018-02-20 18:26:194691 spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false));
[email protected]1ed7b3dc2010-03-04 05:41:454692
Ryan Hamilton0239aac2018-05-19 00:03:134693 spdy::SpdySerializedFrame resp(
4694 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:454695 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414696 CreateMockRead(resp, 1),
4697 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
4698 CreateMockRead(data_frame, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]1ed7b3dc2010-03-04 05:41:454699 };
4700
Ryan Sleevib8d7ea02018-05-07 20:01:014701 SequencedSocketData data(reads, writes);
[email protected]1ed7b3dc2010-03-04 05:41:454702
Bence Békydb3cf652017-10-10 15:22:104703 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]3caf5542010-07-16 15:19:474704 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574705 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474706 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:414707 TestCompletionCallback callback;
[email protected]1ed7b3dc2010-03-04 05:41:454708
Bence Békydb3cf652017-10-10 15:22:104709 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:014710 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1ed7b3dc2010-03-04 05:41:454711
[email protected]3caf5542010-07-16 15:19:474712 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:454713 out.rv = callback.WaitForResult();
4714 EXPECT_EQ(out.rv, OK);
4715
4716 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524717 EXPECT_TRUE(response->headers);
[email protected]1ed7b3dc2010-03-04 05:41:454718 EXPECT_TRUE(response->was_fetched_via_spdy);
4719 out.status_line = response->headers->GetStatusLine();
4720 out.response_info = *response; // Make a copy so we can verify.
4721
4722 // Read Data
[email protected]49639fa2011-12-20 23:22:414723 TestCompletionCallback read_callback;
[email protected]1ed7b3dc2010-03-04 05:41:454724
[email protected]88c7b4be2014-03-19 23:04:014725 const int kReadSize = 256;
Victor Costan9c7302b2018-08-27 16:39:444726 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kReadSize);
[email protected]88c7b4be2014-03-19 23:04:014727 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:164728 ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
[email protected]88c7b4be2014-03-19 23:04:014729
4730 // Complete the read now, which causes buffering to start.
mmenkee24011922015-12-17 22:12:594731 data.Resume();
4732 base::RunLoop().RunUntilIdle();
[email protected]88c7b4be2014-03-19 23:04:014733 // Destroy the transaction, causing the stream to get cancelled
4734 // and orphaning the buffered IO task.
4735 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:454736
4737 // Flush the MessageLoop; this will cause the buffered IO task
4738 // to run for the final time.
[email protected]fc9d88472013-08-14 02:31:174739 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:474740
4741 // Verify that we consumed all test data.
4742 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:454743}
4744
bncc4769d412017-04-19 19:57:544745// Request should fail upon receiving a GOAWAY frame
4746// with Last-Stream-ID lower than the stream id corresponding to the request
4747// and with error code other than NO_ERROR.
4748TEST_F(SpdyNetworkTransactionTest, FailOnGoAway) {
Ryan Hamilton0239aac2018-05-19 00:03:134749 spdy::SpdySerializedFrame req(
4750 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414751 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]69d717bd2010-04-21 18:43:214752
Ryan Hamilton0239aac2018-05-19 00:03:134753 spdy::SpdySerializedFrame go_away(
4754 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_INTERNAL_ERROR, ""));
[email protected]69d717bd2010-04-21 18:43:214755 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414756 CreateMockRead(go_away, 1),
[email protected]58cebf8f2010-07-31 19:20:164757 };
4758
Ryan Sleevib8d7ea02018-05-07 20:01:014759 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:104760 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:574761 helper.RunToCompletion(&data);
[email protected]58cebf8f2010-07-31 19:20:164762 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014763 EXPECT_THAT(out.rv, IsError(ERR_ABORTED));
[email protected]69d717bd2010-04-21 18:43:214764}
4765
bncc4769d412017-04-19 19:57:544766// Request should be retried on a new connection upon receiving a GOAWAY frame
4767// with Last-Stream-ID lower than the stream id corresponding to the request
4768// and with error code NO_ERROR.
4769TEST_F(SpdyNetworkTransactionTest, RetryOnGoAway) {
Bence Békydb3cf652017-10-10 15:22:104770 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bncc4769d412017-04-19 19:57:544771
4772 // First connection.
Ryan Hamilton0239aac2018-05-19 00:03:134773 spdy::SpdySerializedFrame req(
4774 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncc4769d412017-04-19 19:57:544775 MockWrite writes1[] = {CreateMockWrite(req, 0)};
Ryan Hamilton0239aac2018-05-19 00:03:134776 spdy::SpdySerializedFrame go_away(
4777 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_NO_ERROR, ""));
bncc4769d412017-04-19 19:57:544778 MockRead reads1[] = {CreateMockRead(go_away, 1)};
Ryan Sleevib8d7ea02018-05-07 20:01:014779 SequencedSocketData data1(reads1, writes1);
bncc4769d412017-04-19 19:57:544780 helper.AddData(&data1);
4781
4782 // Second connection.
4783 MockWrite writes2[] = {CreateMockWrite(req, 0)};
Ryan Hamilton0239aac2018-05-19 00:03:134784 spdy::SpdySerializedFrame resp(
4785 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4786 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bncc4769d412017-04-19 19:57:544787 MockRead reads2[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
4788 MockRead(ASYNC, 0, 3)};
Ryan Sleevib8d7ea02018-05-07 20:01:014789 SequencedSocketData data2(reads2, writes2);
bncc4769d412017-04-19 19:57:544790 helper.AddData(&data2);
4791
4792 helper.RunPreTestSetup();
4793 helper.RunDefaultTest();
4794
4795 TransactionHelperResult out = helper.output();
4796 EXPECT_THAT(out.rv, IsOk());
4797
4798 helper.VerifyDataConsumed();
4799}
4800
bnc1fc7b352017-01-12 17:51:024801// A server can gracefully shut down by sending a GOAWAY frame
4802// with maximum last-stream-id value.
4803// Transactions started before receiving such a GOAWAY frame should succeed,
4804// but SpdySession should be unavailable for new streams.
4805TEST_F(SpdyNetworkTransactionTest, GracefulGoaway) {
Ryan Hamilton0239aac2018-05-19 00:03:134806 spdy::SpdySerializedFrame req1(
4807 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnc1fc7b352017-01-12 17:51:024808 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:134809 spdy::SpdySerializedFrame req2(
bnc1fc7b352017-01-12 17:51:024810 spdy_util_.ConstructSpdyGet("https://www.example.org/foo", 3, LOWEST));
4811 MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 3)};
4812
Ryan Hamilton0239aac2018-05-19 00:03:134813 spdy::SpdySerializedFrame resp1(
4814 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4815 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
4816 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
4817 0x7fffffff, spdy::ERROR_CODE_NO_ERROR, "Graceful shutdown."));
4818 spdy::SpdySerializedFrame resp2(
4819 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
4820 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
bnc1fc7b352017-01-12 17:51:024821 MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
4822 CreateMockRead(goaway, 4), CreateMockRead(resp2, 5),
4823 CreateMockRead(body2, 6), MockRead(ASYNC, 0, 7)};
4824
4825 // Run first transaction.
Ryan Sleevib8d7ea02018-05-07 20:01:014826 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:104827 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc1fc7b352017-01-12 17:51:024828 helper.RunPreTestSetup();
4829 helper.AddData(&data);
4830 helper.RunDefaultTest();
4831
4832 // Verify first response.
4833 TransactionHelperResult out = helper.output();
4834 EXPECT_THAT(out.rv, IsOk());
4835 EXPECT_EQ("HTTP/1.1 200", out.status_line);
4836 EXPECT_EQ("hello!", out.response_data);
4837
4838 // GOAWAY frame has not yet been received, SpdySession should be available.
4839 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4840 SpdySessionKey key(host_port_pair_, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:114841 PRIVACY_MODE_DISABLED,
4842 SpdySessionKey::IsProxySession::kFalse, SocketTag());
bnc1fc7b352017-01-12 17:51:024843 base::WeakPtr<SpdySession> spdy_session =
bnc9ead3ae2017-03-16 00:48:154844 spdy_session_pool->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:314845 key, /* enable_ip_based_pooling = */ true,
4846 /* is_websocket = */ false, log_);
bnc1fc7b352017-01-12 17:51:024847 EXPECT_TRUE(spdy_session);
4848
4849 // Start second transaction.
4850 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
4851 TestCompletionCallback callback;
4852 HttpRequestInfo request2;
4853 request2.method = "GET";
4854 request2.url = GURL("https://www.example.org/foo");
Ramin Halavatib5e433e62018-02-07 07:41:104855 request2.traffic_annotation =
4856 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békyd3dde832017-09-19 19:02:314857 int rv = trans2.Start(&request2, callback.callback(), log_);
bnc1fc7b352017-01-12 17:51:024858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
4859 rv = callback.WaitForResult();
4860 EXPECT_THAT(rv, IsOk());
4861
4862 // Verify second response.
4863 const HttpResponseInfo* response = trans2.GetResponseInfo();
4864 ASSERT_TRUE(response);
4865 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2, response->connection_info);
4866 ASSERT_TRUE(response->headers);
4867 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
4868 EXPECT_TRUE(response->was_fetched_via_spdy);
4869 EXPECT_TRUE(response->was_alpn_negotiated);
Tsuyoshi Horo01faed62019-02-20 22:11:374870 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
4871 EXPECT_EQ(443, response->remote_endpoint.port());
Bence Béky4e83f492018-05-13 23:14:254872 std::string response_data;
bnc1fc7b352017-01-12 17:51:024873 rv = ReadTransaction(&trans2, &response_data);
4874 EXPECT_THAT(rv, IsOk());
4875 EXPECT_EQ("hello!", response_data);
4876
4877 // Graceful GOAWAY was received, SpdySession should be unavailable.
bnc9ead3ae2017-03-16 00:48:154878 spdy_session = spdy_session_pool->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:314879 key, /* enable_ip_based_pooling = */ true,
4880 /* is_websocket = */ false, log_);
bnc1fc7b352017-01-12 17:51:024881 EXPECT_FALSE(spdy_session);
4882
4883 helper.VerifyDataConsumed();
4884}
4885
bncd16676a2016-07-20 16:23:014886TEST_F(SpdyNetworkTransactionTest, CloseWithActiveStream) {
Ryan Hamilton0239aac2018-05-19 00:03:134887 spdy::SpdySerializedFrame req(
4888 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414889 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]f5ed21552010-05-04 18:39:544890
Ryan Hamilton0239aac2018-05-19 00:03:134891 spdy::SpdySerializedFrame resp(
4892 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f5ed21552010-05-04 18:39:544893 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414894 CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
[email protected]f5ed21552010-05-04 18:39:544895 };
4896
Ryan Sleevib8d7ea02018-05-07 20:01:014897 SequencedSocketData data(reads, writes);
bnc4d782f492016-08-18 13:50:004898
Bence Békydb3cf652017-10-10 15:22:104899 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]3caf5542010-07-16 15:19:474900 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574901 helper.AddData(&data);
bnc4d782f492016-08-18 13:50:004902 helper.StartDefaultTest();
4903 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
[email protected]f5ed21552010-05-04 18:39:544904
bnc4d782f492016-08-18 13:50:004905 helper.WaitForCallbackToComplete();
4906 EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED));
[email protected]3caf5542010-07-16 15:19:474907
bnc4d782f492016-08-18 13:50:004908 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:524909 EXPECT_TRUE(response->headers);
[email protected]f5ed21552010-05-04 18:39:544910 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]f5ed21552010-05-04 18:39:544911
4912 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474913 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:544914}
[email protected]58cebf8f2010-07-31 19:20:164915
Bence Békyc2d37952017-11-20 16:58:164916TEST_F(SpdyNetworkTransactionTest, GoAwayImmediately) {
Ryan Hamilton0239aac2018-05-19 00:03:134917 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1));
Bence Békyc2d37952017-11-20 16:58:164918 MockRead reads[] = {CreateMockRead(goaway, 0, SYNCHRONOUS)};
Ryan Sleevib8d7ea02018-05-07 20:01:014919 SequencedSocketData data(reads, base::span<MockWrite>());
Bence Békyc2d37952017-11-20 16:58:164920
4921 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
4922 helper.RunPreTestSetup();
4923 helper.AddData(&data);
4924 helper.StartDefaultTest();
4925 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
4926
4927 helper.WaitForCallbackToComplete();
4928 EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED));
4929
4930 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4931 EXPECT_FALSE(response->headers);
4932 EXPECT_TRUE(response->was_fetched_via_spdy);
4933
4934 // Verify that we consumed all test data.
4935 helper.VerifyDataConsumed();
4936}
4937
bncfacdd852015-01-09 19:22:544938// Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4939// protocol negotiation happens, instead this test forces protocols for both
4940// sockets.
bncd16676a2016-07-20 16:23:014941TEST_F(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
Bence Békydb3cf652017-10-10 15:22:104942 request_.method = "GET";
bncfacdd852015-01-09 19:22:544943 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
Bence Békydb3cf652017-10-10 15:22:104944 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bncfacdd852015-01-09 19:22:544945
4946 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
Ryan Hamilton0239aac2018-05-19 00:03:134947 spdy::SpdyHeaderBlock headers(
4948 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
4949 spdy::SpdySerializedFrame req(
bnc42331402016-07-25 13:36:154950 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414951 MockWrite writes0[] = {CreateMockWrite(req, 0)};
Ryan Hamilton0239aac2018-05-19 00:03:134952 spdy::SpdySerializedFrame rst(
4953 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
Bence Békycb3613122017-09-19 17:06:574954 MockRead reads0[] = {CreateMockRead(rst, 1)};
Ryan Sleevib8d7ea02018-05-07 20:01:014955 SequencedSocketData data0(reads0, writes0);
bncfacdd852015-01-09 19:22:544956
Jeremy Roman0579ed62017-08-29 15:56:194957 auto ssl_provider0 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
bncfacdd852015-01-09 19:22:544958 // Expect HTTP/2 protocols too in SSLConfig.
Bence Béky27a19b82018-01-30 14:58:364959 ssl_provider0->next_protos_expected_in_ssl_config =
4960 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
bncfacdd852015-01-09 19:22:544961 // Force SPDY.
bnc3cf2a592016-08-11 14:48:364962 ssl_provider0->next_proto = kProtoHTTP2;
dchengc7eeda422015-12-26 03:56:484963 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
bncfacdd852015-01-09 19:22:544964
4965 // Second socket: falling back to HTTP/1.1.
rch08e3aa3e2015-05-16 14:27:524966 MockWrite writes1[] = {MockWrite(ASYNC, 0,
4967 "GET / HTTP/1.1\r\n"
4968 "Host: www.example.org\r\n"
4969 "Connection: keep-alive\r\n\r\n")};
4970 MockRead reads1[] = {MockRead(ASYNC, 1,
4971 "HTTP/1.1 200 OK\r\n"
4972 "Content-Length: 5\r\n\r\n"
4973 "hello")};
Ryan Sleevib8d7ea02018-05-07 20:01:014974 SequencedSocketData data1(reads1, writes1);
bncfacdd852015-01-09 19:22:544975
Jeremy Roman0579ed62017-08-29 15:56:194976 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
bncfacdd852015-01-09 19:22:544977 // Expect only HTTP/1.1 protocol in SSLConfig.
Bence Béky27a19b82018-01-30 14:58:364978 ssl_provider1->next_protos_expected_in_ssl_config =
4979 NextProtoVector{kProtoHTTP11};
bncfacdd852015-01-09 19:22:544980 // Force HTTP/1.1.
bnc3cf2a592016-08-11 14:48:364981 ssl_provider1->next_proto = kProtoHTTP11;
dchengc7eeda422015-12-26 03:56:484982 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
bncfacdd852015-01-09 19:22:544983
bnc525e175a2016-06-20 12:36:404984 HttpServerProperties* http_server_properties =
bncfacdd852015-01-09 19:22:544985 helper.session()->spdy_session_pool()->http_server_properties();
bncb26024382016-06-29 02:39:454986 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair_));
bncfacdd852015-01-09 19:22:544987
4988 helper.RunPreTestSetup();
4989 helper.StartDefaultTest();
4990 helper.FinishDefaultTestWithoutVerification();
4991 helper.VerifyDataConsumed();
bncb26024382016-06-29 02:39:454992 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair_));
bncfacdd852015-01-09 19:22:544993
4994 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:524995 ASSERT_TRUE(response);
4996 ASSERT_TRUE(response->headers);
bncfacdd852015-01-09 19:22:544997 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4998 EXPECT_FALSE(response->was_fetched_via_spdy);
mmenke8210acc2016-07-11 16:34:524999 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
5000 response->connection_info);
bnc94c92842016-09-21 15:22:525001 EXPECT_TRUE(response->was_alpn_negotiated);
Bence Békydb3cf652017-10-10 15:22:105002 EXPECT_TRUE(request_.url.SchemeIs("https"));
Tsuyoshi Horo01faed62019-02-20 22:11:375003 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
5004 EXPECT_EQ(443, response->remote_endpoint.port());
Bence Béky4e83f492018-05-13 23:14:255005 std::string response_data;
robpercival214763f2016-07-01 23:27:015006 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
bncfacdd852015-01-09 19:22:545007 EXPECT_EQ("hello", response_data);
5008}
5009
5010// Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
5011// proxy. Note that no actual protocol negotiation happens, instead this test
5012// forces protocols for both sockets.
bncd16676a2016-07-20 16:23:015013TEST_F(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
Bence Békydb3cf652017-10-10 15:22:105014 request_.method = "GET";
Jeremy Roman0579ed62017-08-29 15:56:195015 auto session_deps = std::make_unique<SpdySessionDependencies>(
Ramin Halavatica8d5252018-03-12 05:33:495016 ProxyResolutionService::CreateFixedFromPacResult(
5017 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
bncfacdd852015-01-09 19:22:545018 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
Bence Békydb3cf652017-10-10 15:22:105019 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
Bence Békyd3dde832017-09-19 19:02:315020 std::move(session_deps));
bncfacdd852015-01-09 19:22:545021
5022 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
Ryan Hamilton0239aac2018-05-19 00:03:135023 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045024 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5025 HostPortPair("www.example.org", 443)));
bncdf80d44fd2016-07-15 20:27:415026 MockWrite writes0[] = {CreateMockWrite(req, 0)};
Ryan Hamilton0239aac2018-05-19 00:03:135027 spdy::SpdySerializedFrame rst(
5028 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
Bence Békycb3613122017-09-19 17:06:575029 MockRead reads0[] = {CreateMockRead(rst, 1)};
Ryan Sleevib8d7ea02018-05-07 20:01:015030 SequencedSocketData data0(reads0, writes0);
bncfacdd852015-01-09 19:22:545031
Jeremy Roman0579ed62017-08-29 15:56:195032 auto ssl_provider0 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
bncfacdd852015-01-09 19:22:545033 // Expect HTTP/2 protocols too in SSLConfig.
Bence Béky27a19b82018-01-30 14:58:365034 ssl_provider0->next_protos_expected_in_ssl_config =
5035 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
bncfacdd852015-01-09 19:22:545036 // Force SPDY.
bnc3cf2a592016-08-11 14:48:365037 ssl_provider0->next_proto = kProtoHTTP2;
dchengc7eeda422015-12-26 03:56:485038 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
bncfacdd852015-01-09 19:22:545039
5040 // Second socket: retry using HTTP/1.1.
5041 MockWrite writes1[] = {
rch08e3aa3e2015-05-16 14:27:525042 MockWrite(ASYNC, 0,
bncce36dca22015-04-21 22:11:235043 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175044 "Host: www.example.org:443\r\n"
bncfacdd852015-01-09 19:22:545045 "Proxy-Connection: keep-alive\r\n\r\n"),
rch08e3aa3e2015-05-16 14:27:525046 MockWrite(ASYNC, 2,
bncfacdd852015-01-09 19:22:545047 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:235048 "Host: www.example.org\r\n"
bncfacdd852015-01-09 19:22:545049 "Connection: keep-alive\r\n\r\n"),
5050 };
5051
5052 MockRead reads1[] = {
rch08e3aa3e2015-05-16 14:27:525053 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5054 MockRead(ASYNC, 3,
bncfacdd852015-01-09 19:22:545055 "HTTP/1.1 200 OK\r\n"
5056 "Content-Length: 5\r\n\r\n"
5057 "hello"),
5058 };
Ryan Sleevib8d7ea02018-05-07 20:01:015059 SequencedSocketData data1(reads1, writes1);
bncfacdd852015-01-09 19:22:545060
Jeremy Roman0579ed62017-08-29 15:56:195061 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
bncfacdd852015-01-09 19:22:545062 // Expect only HTTP/1.1 protocol in SSLConfig.
Bence Béky27a19b82018-01-30 14:58:365063 ssl_provider1->next_protos_expected_in_ssl_config =
5064 NextProtoVector{kProtoHTTP11};
bncfacdd852015-01-09 19:22:545065 // Force HTTP/1.1.
bnc3cf2a592016-08-11 14:48:365066 ssl_provider1->next_proto = kProtoHTTP11;
dchengc7eeda422015-12-26 03:56:485067 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
bncfacdd852015-01-09 19:22:545068
5069 // A third socket is needed for the tunnelled connection.
Jeremy Roman0579ed62017-08-29 15:56:195070 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
bncfacdd852015-01-09 19:22:545071 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
5072 ssl_provider2.get());
5073
bnc525e175a2016-06-20 12:36:405074 HttpServerProperties* http_server_properties =
bncfacdd852015-01-09 19:22:545075 helper.session()->spdy_session_pool()->http_server_properties();
5076 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
5077 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
5078
5079 helper.RunPreTestSetup();
5080 helper.StartDefaultTest();
5081 helper.FinishDefaultTestWithoutVerification();
5082 helper.VerifyDataConsumed();
5083 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
5084
5085 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:525086 ASSERT_TRUE(response);
5087 ASSERT_TRUE(response->headers);
bncfacdd852015-01-09 19:22:545088 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5089 EXPECT_FALSE(response->was_fetched_via_spdy);
mmenke8210acc2016-07-11 16:34:525090 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
5091 response->connection_info);
bnc94c92842016-09-21 15:22:525092 EXPECT_FALSE(response->was_alpn_negotiated);
Bence Békydb3cf652017-10-10 15:22:105093 EXPECT_TRUE(request_.url.SchemeIs("https"));
Tsuyoshi Horo01faed62019-02-20 22:11:375094 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
5095 EXPECT_EQ(70, response->remote_endpoint.port());
Bence Béky4e83f492018-05-13 23:14:255096 std::string response_data;
robpercival214763f2016-07-01 23:27:015097 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
bncfacdd852015-01-09 19:22:545098 EXPECT_EQ("hello", response_data);
5099}
5100
[email protected]b261d0e2010-08-02 19:13:245101// Test to make sure we can correctly connect through a proxy.
bncd16676a2016-07-20 16:23:015102TEST_F(SpdyNetworkTransactionTest, ProxyConnect) {
Jeremy Roman0579ed62017-08-29 15:56:195103 auto session_deps = std::make_unique<SpdySessionDependencies>(
Ramin Halavatica8d5252018-03-12 05:33:495104 ProxyResolutionService::CreateFixedFromPacResult(
5105 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
Bence Békydb3cf652017-10-10 15:22:105106 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
tfarina428341112016-09-22 13:38:205107 std::move(session_deps));
[email protected]b261d0e2010-08-02 19:13:245108 helper.RunPreTestSetup();
5109 HttpNetworkTransaction* trans = helper.trans();
5110
rchebf12982015-04-10 01:15:005111 const char kConnect443[] = {
bncce36dca22015-04-21 22:11:235112 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175113 "Host: www.example.org:443\r\n"
rchcb934f562015-04-07 16:25:125114 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:245115 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
Ryan Hamilton0239aac2018-05-19 00:03:135116 spdy::SpdySerializedFrame req(
5117 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5118 spdy::SpdySerializedFrame resp(
5119 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5120 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:245121
rchebf12982015-04-10 01:15:005122 MockWrite writes[] = {
Avi Drissman4365a4782018-12-28 19:26:245123 MockWrite(SYNCHRONOUS, kConnect443, base::size(kConnect443) - 1, 0),
bncdf80d44fd2016-07-15 20:27:415124 CreateMockWrite(req, 2),
[email protected]b261d0e2010-08-02 19:13:245125 };
rchebf12982015-04-10 01:15:005126 MockRead reads[] = {
Avi Drissman4365a4782018-12-28 19:26:245127 MockRead(SYNCHRONOUS, kHTTP200, base::size(kHTTP200) - 1, 1),
5128 CreateMockRead(resp, 3),
5129 CreateMockRead(body, 4),
Raul Tambre94493c652019-03-11 17:18:355130 MockRead(ASYNC, nullptr, 0, 5),
[email protected]b261d0e2010-08-02 19:13:245131 };
Ryan Sleevib8d7ea02018-05-07 20:01:015132 SequencedSocketData data(reads, writes);
[email protected]b261d0e2010-08-02 19:13:245133
Bence Béky53a5aef2018-03-29 21:54:125134 helper.AddData(&data);
[email protected]49639fa2011-12-20 23:22:415135 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:245136
Bence Békydb3cf652017-10-10 15:22:105137 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:015138 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b261d0e2010-08-02 19:13:245139
5140 rv = callback.WaitForResult();
5141 EXPECT_EQ(0, rv);
5142
bnc42331402016-07-25 13:36:155143 // Verify the response headers.
[email protected]b261d0e2010-08-02 19:13:245144 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525145 ASSERT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:025146 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:245147
Bence Béky4e83f492018-05-13 23:14:255148 std::string response_data;
robpercival214763f2016-07-01 23:27:015149 ASSERT_THAT(ReadTransaction(trans, &response_data), IsOk());
[email protected]b261d0e2010-08-02 19:13:245150 EXPECT_EQ("hello!", response_data);
5151 helper.VerifyDataConsumed();
5152}
5153
bncce36dca22015-04-21 22:11:235154// Test to make sure we can correctly connect through a proxy to
5155// www.example.org, if there already exists a direct spdy connection to
5156// www.example.org. See https://crbug.com/49874.
bncd16676a2016-07-20 16:23:015157TEST_F(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
[email protected]733b7a6d2010-08-25 01:38:435158 // Use a proxy service which returns a proxy fallback list from DIRECT to
5159 // myproxy:70. For this test there will be no fallback, so it is equivalent
5160 // to simply DIRECT. The reason for appending the second proxy is to verify
5161 // that the session pool key used does is just "DIRECT".
Jeremy Roman0579ed62017-08-29 15:56:195162 auto session_deps = std::make_unique<SpdySessionDependencies>(
Lily Houghton8c2f97d2018-01-22 05:06:595163 ProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495164 "DIRECT; PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
bncd16676a2016-07-20 16:23:015165 // When setting up the first transaction, we store the SpdySessionPool so that
5166 // we can use the same pool in the second transaction.
Bence Békydb3cf652017-10-10 15:22:105167 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
tfarina428341112016-09-22 13:38:205168 std::move(session_deps));
[email protected]733b7a6d2010-08-25 01:38:435169
[email protected]87bfa3f2010-09-30 14:54:565170 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:245171 helper.RunPreTestSetup();
5172
5173 // Construct and send a simple GET request.
Ryan Hamilton0239aac2018-05-19 00:03:135174 spdy::SpdySerializedFrame req(
5175 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
[email protected]b261d0e2010-08-02 19:13:245176 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415177 CreateMockWrite(req, 0),
[email protected]b261d0e2010-08-02 19:13:245178 };
5179
Ryan Hamilton0239aac2018-05-19 00:03:135180 spdy::SpdySerializedFrame resp(
5181 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5182 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:245183 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415184 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:525185 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3), // Force a pause
[email protected]b261d0e2010-08-02 19:13:245186 };
Ryan Sleevib8d7ea02018-05-07 20:01:015187 SequencedSocketData data(reads, writes);
[email protected]dd54bd82012-07-19 23:44:575188 helper.AddData(&data);
[email protected]b261d0e2010-08-02 19:13:245189 HttpNetworkTransaction* trans = helper.trans();
5190
[email protected]49639fa2011-12-20 23:22:415191 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:245192 TransactionHelperResult out;
Bence Békydb3cf652017-10-10 15:22:105193 out.rv = trans->Start(&request_, callback.callback(), log_);
[email protected]b261d0e2010-08-02 19:13:245194
5195 EXPECT_EQ(out.rv, ERR_IO_PENDING);
5196 out.rv = callback.WaitForResult();
5197 EXPECT_EQ(out.rv, OK);
5198
5199 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525200 EXPECT_TRUE(response->headers);
[email protected]b261d0e2010-08-02 19:13:245201 EXPECT_TRUE(response->was_fetched_via_spdy);
5202 out.rv = ReadTransaction(trans, &out.response_data);
robpercival214763f2016-07-01 23:27:015203 EXPECT_THAT(out.rv, IsOk());
[email protected]b261d0e2010-08-02 19:13:245204 out.status_line = response->headers->GetStatusLine();
bnc84e7fb52015-12-02 11:50:025205 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b261d0e2010-08-02 19:13:245206 EXPECT_EQ("hello!", out.response_data);
5207
5208 // Check that the SpdySession is still in the SpdySessionPool.
Matt Menke2436b2f2018-12-11 18:07:115209 SpdySessionKey session_pool_key_direct(
5210 host_port_pair_, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
5211 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]41d64e82013-07-03 22:44:265212 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
[email protected]e6d017652013-05-17 18:01:405213 SpdySessionKey session_pool_key_proxy(
bncb26024382016-06-29 02:39:455214 host_port_pair_,
[email protected]e6d017652013-05-17 18:01:405215 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
Matt Menke2436b2f2018-12-11 18:07:115216 PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
5217 SocketTag());
[email protected]41d64e82013-07-03 22:44:265218 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:245219
rdsmithebb50aa2015-11-12 03:44:385220 // New SpdyTestUtil instance for the session that will be used for the
5221 // proxy connection.
bncd16676a2016-07-20 16:23:015222 SpdyTestUtil spdy_util_2;
rdsmithebb50aa2015-11-12 03:44:385223
[email protected]b261d0e2010-08-02 19:13:245224 // Set up data for the proxy connection.
bncce36dca22015-04-21 22:11:235225 const char kConnect443[] = {
5226 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175227 "Host: www.example.org:443\r\n"
bncce36dca22015-04-21 22:11:235228 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:245229 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
Ryan Hamilton0239aac2018-05-19 00:03:135230 spdy::SpdySerializedFrame req2(
5231 spdy_util_2.ConstructSpdyGet(kPushedUrl, 1, LOWEST));
5232 spdy::SpdySerializedFrame resp2(
5233 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
5234 spdy::SpdySerializedFrame body2(spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:245235
rchebf12982015-04-10 01:15:005236 MockWrite writes2[] = {
Avi Drissman4365a4782018-12-28 19:26:245237 MockWrite(SYNCHRONOUS, kConnect443, base::size(kConnect443) - 1, 0),
bncdf80d44fd2016-07-15 20:27:415238 CreateMockWrite(req2, 2),
[email protected]b261d0e2010-08-02 19:13:245239 };
rchebf12982015-04-10 01:15:005240 MockRead reads2[] = {
Avi Drissman4365a4782018-12-28 19:26:245241 MockRead(SYNCHRONOUS, kHTTP200, base::size(kHTTP200) - 1, 1),
bncdf80d44fd2016-07-15 20:27:415242 CreateMockRead(resp2, 3), CreateMockRead(body2, 4),
rchebf12982015-04-10 01:15:005243 MockRead(ASYNC, 0, 5) // EOF
[email protected]b261d0e2010-08-02 19:13:245244 };
5245
Ryan Sleevib8d7ea02018-05-07 20:01:015246 SequencedSocketData data_proxy(reads2, writes2);
[email protected]b261d0e2010-08-02 19:13:245247
bncce36dca22015-04-21 22:11:235248 // Create another request to www.example.org, but this time through a proxy.
Bence Békydb3cf652017-10-10 15:22:105249 request_.method = "GET";
Bence Békyd2df6c1c82018-04-20 22:52:015250 request_.url = GURL(kPushedUrl);
Jeremy Roman0579ed62017-08-29 15:56:195251 auto session_deps_proxy = std::make_unique<SpdySessionDependencies>(
Ramin Halavatica8d5252018-03-12 05:33:495252 ProxyResolutionService::CreateFixedFromPacResult(
5253 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
Bence Békydb3cf652017-10-10 15:22:105254 NormalSpdyTransactionHelper helper_proxy(request_, DEFAULT_PRIORITY, log_,
5255 std::move(session_deps_proxy));
5256
[email protected]b261d0e2010-08-02 19:13:245257 helper_proxy.RunPreTestSetup();
Bence Béky53a5aef2018-03-29 21:54:125258 helper_proxy.AddData(&data_proxy);
[email protected]b261d0e2010-08-02 19:13:245259
5260 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
[email protected]49639fa2011-12-20 23:22:415261 TestCompletionCallback callback_proxy;
Bence Békydb3cf652017-10-10 15:22:105262 int rv = trans_proxy->Start(&request_, callback_proxy.callback(), log_);
robpercival214763f2016-07-01 23:27:015263 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b261d0e2010-08-02 19:13:245264 rv = callback_proxy.WaitForResult();
5265 EXPECT_EQ(0, rv);
5266
5267 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
wezca1070932016-05-26 20:30:525268 ASSERT_TRUE(response_proxy.headers);
bnc84e7fb52015-12-02 11:50:025269 EXPECT_EQ("HTTP/1.1 200", response_proxy.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:245270
Bence Béky4e83f492018-05-13 23:14:255271 std::string response_data;
robpercival214763f2016-07-01 23:27:015272 ASSERT_THAT(ReadTransaction(trans_proxy, &response_data), IsOk());
[email protected]b261d0e2010-08-02 19:13:245273 EXPECT_EQ("hello!", response_data);
5274
[email protected]b261d0e2010-08-02 19:13:245275 helper_proxy.VerifyDataConsumed();
5276}
5277
[email protected]58cebf8f2010-07-31 19:20:165278// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
5279// on a new connection, if the connection was previously known to be good.
5280// This can happen when a server reboots without saying goodbye, or when
5281// we're behind a NAT that masked the RST.
bncd16676a2016-07-20 16:23:015282TEST_F(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
Ryan Hamilton0239aac2018-05-19 00:03:135283 spdy::SpdySerializedFrame resp(
5284 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5285 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]58cebf8f2010-07-31 19:20:165286 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415287 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch32320842015-05-16 15:57:095288 MockRead(ASYNC, ERR_IO_PENDING, 3),
5289 MockRead(ASYNC, ERR_CONNECTION_RESET, 4),
[email protected]58cebf8f2010-07-31 19:20:165290 };
5291
5292 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:415293 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch32320842015-05-16 15:57:095294 MockRead(ASYNC, 0, 3) // EOF
[email protected]58cebf8f2010-07-31 19:20:165295 };
5296
Ryan Hamilton0239aac2018-05-19 00:03:135297 spdy::SpdySerializedFrame req(
5298 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:385299 // In all cases the connection will be reset before req3 can be
5300 // dispatched, destroying both streams.
5301 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:135302 spdy::SpdySerializedFrame req3(
5303 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
bncdf80d44fd2016-07-15 20:27:415304 MockWrite writes1[] = {CreateMockWrite(req, 0), CreateMockWrite(req3, 5)};
5305 MockWrite writes2[] = {CreateMockWrite(req, 0)};
rchacdcbdc2015-05-16 17:16:005306
[email protected]58cebf8f2010-07-31 19:20:165307 // This test has a couple of variants.
5308 enum {
5309 // Induce the RST while waiting for our transaction to send.
rchacdcbdc2015-05-16 17:16:005310 VARIANT_RST_DURING_SEND_COMPLETION = 0,
[email protected]58cebf8f2010-07-31 19:20:165311 // Induce the RST while waiting for our transaction to read.
5312 // In this case, the send completed - everything copied into the SNDBUF.
rchacdcbdc2015-05-16 17:16:005313 VARIANT_RST_DURING_READ_COMPLETION = 1
[email protected]58cebf8f2010-07-31 19:20:165314 };
5315
5316 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
5317 variant <= VARIANT_RST_DURING_READ_COMPLETION;
5318 ++variant) {
Ryan Sleevib8d7ea02018-05-07 20:01:015319 SequencedSocketData data1(reads,
5320 base::make_span(writes1).first(1 + variant));
[email protected]58cebf8f2010-07-31 19:20:165321
Ryan Sleevib8d7ea02018-05-07 20:01:015322 SequencedSocketData data2(reads2, writes2);
[email protected]58cebf8f2010-07-31 19:20:165323
Bence Békydb3cf652017-10-10 15:22:105324 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
5325 nullptr);
[email protected]dd54bd82012-07-19 23:44:575326 helper.AddData(&data1);
5327 helper.AddData(&data2);
[email protected]58cebf8f2010-07-31 19:20:165328 helper.RunPreTestSetup();
5329
5330 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:165331 HttpNetworkTransaction trans(DEFAULT_PRIORITY, helper.session());
[email protected]58cebf8f2010-07-31 19:20:165332
[email protected]49639fa2011-12-20 23:22:415333 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:105334 int rv = trans.Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:015335 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]58cebf8f2010-07-31 19:20:165336 // On the second transaction, we trigger the RST.
5337 if (i == 1) {
5338 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
5339 // Writes to the socket complete asynchronously on SPDY by running
5340 // through the message loop. Complete the write here.
[email protected]fc9d88472013-08-14 02:31:175341 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:165342 }
5343
5344 // Now schedule the ERR_CONNECTION_RESET.
mmenkee24011922015-12-17 22:12:595345 data1.Resume();
[email protected]58cebf8f2010-07-31 19:20:165346 }
5347 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015348 EXPECT_THAT(rv, IsOk());
[email protected]58cebf8f2010-07-31 19:20:165349
bnc691fda62016-08-12 00:43:165350 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525351 ASSERT_TRUE(response);
5352 EXPECT_TRUE(response->headers);
[email protected]58cebf8f2010-07-31 19:20:165353 EXPECT_TRUE(response->was_fetched_via_spdy);
Bence Béky4e83f492018-05-13 23:14:255354 std::string response_data;
bnc691fda62016-08-12 00:43:165355 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:015356 EXPECT_THAT(rv, IsOk());
bnc84e7fb52015-12-02 11:50:025357 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]58cebf8f2010-07-31 19:20:165358 EXPECT_EQ("hello!", response_data);
rchacdcbdc2015-05-16 17:16:005359 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:165360 }
5361
5362 helper.VerifyDataConsumed();
rchacdcbdc2015-05-16 17:16:005363 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:165364 }
5365}
[email protected]1f418ee2010-10-16 19:46:565366
[email protected]018aabc2010-10-29 16:16:595367// Tests that Basic authentication works over SPDY
bncd16676a2016-07-20 16:23:015368TEST_F(SpdyNetworkTransactionTest, SpdyBasicAuth) {
[email protected]018aabc2010-10-29 16:16:595369 // The first request will be a bare GET, the second request will be a
5370 // GET with an Authorization header.
Ryan Hamilton0239aac2018-05-19 00:03:135371 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:485372 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:385373 // Will be refused for lack of auth.
5374 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]018aabc2010-10-29 16:16:595375 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465376 "authorization", "Basic Zm9vOmJhcg=="
[email protected]018aabc2010-10-29 16:16:595377 };
Ryan Hamilton0239aac2018-05-19 00:03:135378 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:245379 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:485380 LOWEST));
[email protected]018aabc2010-10-29 16:16:595381 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415382 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]018aabc2010-10-29 16:16:595383 };
5384
5385 // The first response is a 401 authentication challenge, and the second
5386 // response will be a 200 response since the second request includes a valid
5387 // Authorization header.
5388 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:265389 "www-authenticate",
[email protected]018aabc2010-10-29 16:16:595390 "Basic realm=\"MyRealm\""
5391 };
Ryan Hamilton0239aac2018-05-19 00:03:135392 spdy::SpdySerializedFrame resp_authentication(
5393 spdy_util_.ConstructSpdyReplyError(
5394 "401", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:245395 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135396 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:415397 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:135398 spdy::SpdySerializedFrame resp_data(
tombergan5d22c182017-01-11 02:05:355399 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:135400 spdy::SpdySerializedFrame body_data(
5401 spdy_util_.ConstructSpdyDataFrame(3, true));
tombergan5d22c182017-01-11 02:05:355402
[email protected]018aabc2010-10-29 16:16:595403 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415404 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:465405 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:415406 CreateMockRead(resp_data, 4),
5407 CreateMockRead(body_data, 5),
rch08e3aa3e2015-05-16 14:27:525408 MockRead(ASYNC, 0, 6),
[email protected]018aabc2010-10-29 16:16:595409 };
5410
Ryan Sleevib8d7ea02018-05-07 20:01:015411 SequencedSocketData data(spdy_reads, spdy_writes);
Bence Békydb3cf652017-10-10 15:22:105412 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]018aabc2010-10-29 16:16:595413
5414 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575415 helper.AddData(&data);
bnc4d782f492016-08-18 13:50:005416 helper.StartDefaultTest();
5417 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
5418
5419 helper.WaitForCallbackToComplete();
5420 EXPECT_THAT(helper.output().rv, IsOk());
[email protected]018aabc2010-10-29 16:16:595421
5422 // Make sure the response has an auth challenge.
bnc4d782f492016-08-18 13:50:005423 HttpNetworkTransaction* trans = helper.trans();
[email protected]018aabc2010-10-29 16:16:595424 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525425 ASSERT_TRUE(response_start);
5426 ASSERT_TRUE(response_start->headers);
[email protected]018aabc2010-10-29 16:16:595427 EXPECT_EQ(401, response_start->headers->response_code());
5428 EXPECT_TRUE(response_start->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:585429 const base::Optional<AuthChallengeInfo>& auth_challenge =
5430 response_start->auth_challenge;
wezca1070932016-05-26 20:30:525431 ASSERT_TRUE(auth_challenge);
[email protected]79cb5c12011-09-12 13:12:045432 EXPECT_FALSE(auth_challenge->is_proxy);
aberentbba302d2015-12-03 10:20:195433 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:045434 EXPECT_EQ("MyRealm", auth_challenge->realm);
[email protected]018aabc2010-10-29 16:16:595435
5436 // Restart with a username/password.
[email protected]ad65a3e2013-12-25 18:18:015437 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
5438 base::ASCIIToUTF16("bar"));
[email protected]49639fa2011-12-20 23:22:415439 TestCompletionCallback callback_restart;
5440 const int rv_restart = trans->RestartWithAuth(
5441 credentials, callback_restart.callback());
robpercival214763f2016-07-01 23:27:015442 EXPECT_THAT(rv_restart, IsError(ERR_IO_PENDING));
[email protected]018aabc2010-10-29 16:16:595443 const int rv_restart_complete = callback_restart.WaitForResult();
robpercival214763f2016-07-01 23:27:015444 EXPECT_THAT(rv_restart_complete, IsOk());
[email protected]018aabc2010-10-29 16:16:595445 // TODO(cbentzel): This is actually the same response object as before, but
5446 // data has changed.
5447 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525448 ASSERT_TRUE(response_restart);
5449 ASSERT_TRUE(response_restart->headers);
[email protected]018aabc2010-10-29 16:16:595450 EXPECT_EQ(200, response_restart->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:585451 EXPECT_FALSE(response_restart->auth_challenge);
[email protected]018aabc2010-10-29 16:16:595452}
5453
Bence Békye7023f82018-05-14 01:53:035454struct PushHeaderTestParams {
Bence Béky49db0e22018-05-11 00:54:055455 std::vector<std::pair<base::StringPiece, base::StringPiece>>
5456 extra_request_headers;
5457 std::vector<std::pair<base::StringPiece, base::StringPiece>>
5458 extra_pushed_request_headers;
5459 std::vector<std::pair<base::StringPiece, base::StringPiece>>
5460 extra_pushed_response_headers;
5461 base::StringPiece pushed_status_code;
5462 bool push_accepted;
Bence Békyeacd48f2018-05-14 11:34:335463 SpdyPushedStreamFate expected_fate;
Bence Békye7023f82018-05-14 01:53:035464} push_header_test_cases[] = {
Bence Béky49db0e22018-05-11 00:54:055465 // Base case: no extra headers.
Bence Békyeacd48f2018-05-14 11:34:335466 {{}, {}, {}, "200", true, SpdyPushedStreamFate::kAcceptedNoVary},
Bence Béky49db0e22018-05-11 00:54:055467 // Cookie headers match.
5468 {{{"cookie", "value=foo"}},
5469 {{"cookie", "value=foo"}},
5470 {{"vary", "Cookie"}},
5471 "200",
Bence Békyeacd48f2018-05-14 11:34:335472 true,
5473 SpdyPushedStreamFate::kAcceptedMatchingVary},
Bence Béky49db0e22018-05-11 00:54:055474 // Cookie headers mismatch.
5475 {{{"cookie", "value=foo"}},
5476 {{"cookie", "value=bar"}},
5477 {{"vary", "Cookie"}},
5478 "200",
Bence Békyeacd48f2018-05-14 11:34:335479 false,
5480 SpdyPushedStreamFate::kVaryMismatch},
Bence Béky49db0e22018-05-11 00:54:055481 // Partial Content response, no Range headers.
Bence Békyeacd48f2018-05-14 11:34:335482 {{}, {}, {}, "206", false, SpdyPushedStreamFate::kClientRequestNotRange},
Bence Béky49db0e22018-05-11 00:54:055483 // Partial Content response, no Range headers in pushed request.
Bence Békyeacd48f2018-05-14 11:34:335484 {{{"range", "0-42"}},
5485 {},
5486 {},
5487 "206",
5488 false,
5489 SpdyPushedStreamFate::kPushedRequestNotRange},
Bence Béky49db0e22018-05-11 00:54:055490 // Partial Content response, no Range headers in client request.
Bence Békyeacd48f2018-05-14 11:34:335491 {{},
5492 {{"range", "0-42"}},
5493 {},
5494 "206",
5495 false,
5496 SpdyPushedStreamFate::kClientRequestNotRange},
Bence Béky49db0e22018-05-11 00:54:055497 // Partial Content response, mismatching Range headers.
Bence Békyeacd48f2018-05-14 11:34:335498 {{{"range", "0-42"}},
5499 {{"range", "10-42"}},
5500 {},
5501 "206",
5502 false,
5503 SpdyPushedStreamFate::kRangeMismatch},
Bence Béky49db0e22018-05-11 00:54:055504 // Partial Content response, matching Range headers.
Bence Békyeacd48f2018-05-14 11:34:335505 {{{"range", "0-42"}},
5506 {{"range", "0-42"}},
5507 {},
5508 "206",
5509 true,
5510 SpdyPushedStreamFate::kAcceptedNoVary},
5511};
[email protected]d08358502010-12-03 22:04:035512
Bence Békye7023f82018-05-14 01:53:035513class SpdyNetworkTransactionPushHeaderTest
Bence Béky49db0e22018-05-11 00:54:055514 : public SpdyNetworkTransactionTest,
Bence Békye7023f82018-05-14 01:53:035515 public ::testing::WithParamInterface<PushHeaderTestParams> {
Bence Béky49db0e22018-05-11 00:54:055516 protected:
5517 void RunTest(bool pushed_response_headers_received_before_request) {
Bence Békyeacd48f2018-05-14 11:34:335518 base::HistogramTester histogram_tester;
5519
Bence Békyc4caf072018-04-20 22:27:305520 int seq = 0;
5521 std::vector<MockWrite> writes;
5522 std::vector<MockRead> reads;
bnc38dcd392016-02-09 23:19:495523
Ryan Hamilton0239aac2018-05-19 00:03:135524 spdy::SpdySerializedFrame req1(
Bence Béky49db0e22018-05-11 00:54:055525 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
Bence Békyc4caf072018-04-20 22:27:305526 writes.push_back(CreateMockWrite(req1, seq++));
[email protected]513963e2013-06-15 01:53:045527
Ryan Hamilton0239aac2018-05-19 00:03:135528 spdy::SpdyHeaderBlock pushed_request_headers;
5529 pushed_request_headers[spdy::kHttp2MethodHeader] = "GET";
Bence Béky49db0e22018-05-11 00:54:055530 for (const auto& header : GetParam().extra_pushed_request_headers) {
Bence Békyc4caf072018-04-20 22:27:305531 pushed_request_headers.insert(header);
5532 }
Bence Béky49db0e22018-05-11 00:54:055533 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, &pushed_request_headers);
Ryan Hamilton0239aac2018-05-19 00:03:135534 spdy::SpdySerializedFrame pushed_request(
5535 spdy_util_.ConstructSpdyPushPromise(1, 2,
5536 std::move(pushed_request_headers)));
Bence Békyc4caf072018-04-20 22:27:305537 reads.push_back(CreateMockRead(pushed_request, seq++));
[email protected]d08358502010-12-03 22:04:035538
Ryan Hamilton0239aac2018-05-19 00:03:135539 spdy::SpdySerializedFrame priority(
Bence Béky49db0e22018-05-11 00:54:055540 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
Bence Békyc4caf072018-04-20 22:27:305541 writes.push_back(CreateMockWrite(priority, seq++));
bnc38dcd392016-02-09 23:19:495542
Bence Béky49db0e22018-05-11 00:54:055543 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, seq++));
5544
Ryan Hamilton0239aac2018-05-19 00:03:135545 spdy::SpdyHeaderBlock pushed_response_headers;
5546 pushed_response_headers[spdy::kHttp2StatusHeader] =
5547 GetParam().pushed_status_code;
Bence Béky49db0e22018-05-11 00:54:055548 for (const auto& header : GetParam().extra_pushed_response_headers) {
Bence Békyc4caf072018-04-20 22:27:305549 pushed_response_headers.insert(header);
5550 }
Ryan Hamilton0239aac2018-05-19 00:03:135551 spdy::SpdySerializedFrame pushed_response(
Bence Béky49db0e22018-05-11 00:54:055552 spdy_util_.ConstructSpdyReply(2, std::move(pushed_response_headers)));
Bence Békyc4caf072018-04-20 22:27:305553 reads.push_back(CreateMockRead(pushed_response, seq++));
bnc38dcd392016-02-09 23:19:495554
Ryan Hamilton0239aac2018-05-19 00:03:135555 spdy::SpdySerializedFrame resp1(
5556 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Bence Békyc4caf072018-04-20 22:27:305557 reads.push_back(CreateMockRead(resp1, seq++));
[email protected]d08358502010-12-03 22:04:035558
Ryan Hamilton0239aac2018-05-19 00:03:135559 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Békyc4caf072018-04-20 22:27:305560 reads.push_back(CreateMockRead(body1, seq++));
Bence Béky49db0e22018-05-11 00:54:055561 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]d08358502010-12-03 22:04:035562
Ryan Hamilton0239aac2018-05-19 00:03:135563 spdy::SpdySerializedFrame pushed_body(
Bence Béky49db0e22018-05-11 00:54:055564 spdy_util_.ConstructSpdyDataFrame(2, "This is pushed.", true));
Bence Békyc4caf072018-04-20 22:27:305565 reads.push_back(CreateMockRead(pushed_body, seq++));
[email protected]d08358502010-12-03 22:04:035566
Bence Békyc4caf072018-04-20 22:27:305567 // If push is not accepted, a new request is sent on the wire.
Ryan Hamilton0239aac2018-05-19 00:03:135568 spdy::SpdySerializedFrame rst;
5569 spdy::SpdySerializedFrame req2;
5570 spdy::SpdySerializedFrame resp2;
5571 spdy::SpdySerializedFrame body2;
Bence Béky49db0e22018-05-11 00:54:055572 if (!GetParam().push_accepted) {
Ryan Hamilton0239aac2018-05-19 00:03:135573 rst = spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_CANCEL);
Bence Béky49db0e22018-05-11 00:54:055574 writes.push_back(CreateMockWrite(rst, seq++));
5575
Ryan Hamilton0239aac2018-05-19 00:03:135576 spdy::SpdyHeaderBlock request_headers2(
Bence Béky49db0e22018-05-11 00:54:055577 spdy_util_.ConstructGetHeaderBlock(kPushedUrl));
5578 for (const auto& header : GetParam().extra_request_headers) {
Bence Békyc4caf072018-04-20 22:27:305579 request_headers2.insert(header);
5580 }
Bence Béky49db0e22018-05-11 00:54:055581 req2 = spdy_util_.ConstructSpdyHeaders(3, std::move(request_headers2),
5582 LOWEST, true);
Bence Békyc4caf072018-04-20 22:27:305583 writes.push_back(CreateMockWrite(req2, seq++));
[email protected]d08358502010-12-03 22:04:035584
Bence Béky49db0e22018-05-11 00:54:055585 resp2 = spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3);
Bence Békyc4caf072018-04-20 22:27:305586 reads.push_back(CreateMockRead(resp2, seq++));
Bence Béky04268b022018-04-19 01:17:415587
Bence Béky49db0e22018-05-11 00:54:055588 body2 = spdy_util_.ConstructSpdyDataFrame(3, "This is not pushed.", true);
Bence Békyc4caf072018-04-20 22:27:305589 reads.push_back(CreateMockRead(body2, seq++));
5590 }
Bence Béky04268b022018-04-19 01:17:415591
Bence Békyc4caf072018-04-20 22:27:305592 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, seq++));
Bence Béky04268b022018-04-19 01:17:415593
Bence Békyc4caf072018-04-20 22:27:305594 reads.push_back(MockRead(ASYNC, 0, seq++));
Bence Béky04268b022018-04-19 01:17:415595
Ryan Sleevib8d7ea02018-05-07 20:01:015596 SequencedSocketData data(reads, writes);
Bence Béky04268b022018-04-19 01:17:415597
Bence Békyc4caf072018-04-20 22:27:305598 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
5599 nullptr);
5600 helper.RunPreTestSetup();
5601 helper.AddData(&data);
Bence Béky04268b022018-04-19 01:17:415602
Bence Békyc4caf072018-04-20 22:27:305603 HttpNetworkTransaction* trans = helper.trans();
5604 TestCompletionCallback callback1;
5605 int rv = trans->Start(&request_, callback1.callback(), log_);
5606 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Béky49db0e22018-05-11 00:54:055607
5608 // Open connection.
5609 base::RunLoop().RunUntilIdle();
5610
5611 if (pushed_response_headers_received_before_request) {
5612 // Read pushed response headers.
5613 data.Resume();
5614 base::RunLoop().RunUntilIdle();
5615 }
5616
5617 HttpRequestInfo request2 = CreateGetPushRequest();
5618 for (const auto& header : GetParam().extra_request_headers) {
5619 request2.extra_headers.SetHeader(header.first, header.second);
5620 }
5621 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
5622 TestCompletionCallback callback2;
5623 rv = trans2.Start(&request2, callback2.callback(), log_);
5624 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5625 base::RunLoop().RunUntilIdle();
5626
5627 if (!pushed_response_headers_received_before_request) {
5628 // Read pushed response headers.
5629 data.Resume();
5630 base::RunLoop().RunUntilIdle();
5631 }
5632
Bence Békyc4caf072018-04-20 22:27:305633 rv = callback1.WaitForResult();
5634 EXPECT_THAT(rv, IsOk());
Bence Béky04268b022018-04-19 01:17:415635
Bence Békyc4caf072018-04-20 22:27:305636 const HttpResponseInfo* const response1 = trans->GetResponseInfo();
5637 EXPECT_TRUE(response1->headers);
5638 EXPECT_EQ("HTTP/1.1 200", response1->headers->GetStatusLine());
Bence Béky04268b022018-04-19 01:17:415639
Bence Béky4e83f492018-05-13 23:14:255640 std::string result1;
Bence Békyc4caf072018-04-20 22:27:305641 ReadResult(trans, &result1);
5642 EXPECT_EQ(result1, "hello!");
Bence Béky04268b022018-04-19 01:17:415643
Bence Békyc4caf072018-04-20 22:27:305644 rv = callback2.WaitForResult();
5645 EXPECT_THAT(rv, IsOk());
Bence Béky04268b022018-04-19 01:17:415646
Bence Béky4e83f492018-05-13 23:14:255647 std::string result2;
Bence Békyc4caf072018-04-20 22:27:305648 ReadResult(&trans2, &result2);
Bence Béky49db0e22018-05-11 00:54:055649 EXPECT_EQ(result2, GetParam().push_accepted ? "This is pushed."
5650 : "This is not pushed.");
Bence Béky04268b022018-04-19 01:17:415651
Bence Békyc4caf072018-04-20 22:27:305652 data.Resume();
5653 base::RunLoop().RunUntilIdle();
5654 helper.VerifyDataConsumed();
Bence Békyeacd48f2018-05-14 11:34:335655
5656 histogram_tester.ExpectBucketCount(
5657 "Net.SpdyPushedStreamFate", static_cast<int>(GetParam().expected_fate),
5658 1);
5659 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
Bence Békyc4caf072018-04-20 22:27:305660 }
Bence Béky49db0e22018-05-11 00:54:055661};
5662
Victor Costan2309ea02019-02-13 21:35:475663INSTANTIATE_TEST_SUITE_P(,
5664 SpdyNetworkTransactionPushHeaderTest,
5665 ::testing::ValuesIn(push_header_test_cases));
Bence Béky49db0e22018-05-11 00:54:055666
Bence Békye7023f82018-05-14 01:53:035667TEST_P(SpdyNetworkTransactionPushHeaderTest,
Bence Béky49db0e22018-05-11 00:54:055668 PushedResponseHeadersReceivedBeforeRequest) {
5669 RunTest(/* pushed_response_headers_received_before_request = */ true);
Bence Béky04268b022018-04-19 01:17:415670}
5671
Bence Békye7023f82018-05-14 01:53:035672TEST_P(SpdyNetworkTransactionPushHeaderTest,
Bence Béky49db0e22018-05-11 00:54:055673 PushedResponseHeadersReceivedAfterRequest) {
5674 RunTest(/* pushed_response_headers_received_before_request = */ false);
[email protected]d08358502010-12-03 22:04:035675}
5676
bnc42331402016-07-25 13:36:155677TEST_F(SpdyNetworkTransactionTest, ResponseHeadersTwice) {
Ryan Hamilton0239aac2018-05-19 00:03:135678 spdy::SpdySerializedFrame req(
5679 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5680 spdy::SpdySerializedFrame rst(
5681 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
[email protected]b771bb72013-06-24 09:55:415682 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415683 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
[email protected]745aa9c2014-06-27 02:21:295684 };
[email protected]d08358502010-12-03 22:04:035685
Ryan Hamilton0239aac2018-05-19 00:03:135686 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:355687 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]513963e2013-06-15 01:53:045688
Ryan Hamilton0239aac2018-05-19 00:03:135689 spdy::SpdyHeaderBlock late_headers;
bnc38dcd392016-02-09 23:19:495690 late_headers["hello"] = "bye";
Ryan Hamilton0239aac2018-05-19 00:03:135691 spdy::SpdySerializedFrame stream1_headers(
5692 spdy_util_.ConstructSpdyResponseHeaders(1, std::move(late_headers),
5693 false));
5694 spdy::SpdySerializedFrame stream1_body(
5695 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d08358502010-12-03 22:04:035696 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415697 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_headers, 2),
5698 CreateMockRead(stream1_body, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]d08358502010-12-03 22:04:035699 };
5700
Ryan Sleevib8d7ea02018-05-07 20:01:015701 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:105702 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:575703 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035704 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:015705 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d08358502010-12-03 22:04:035706}
5707
xunjieli294da722015-08-11 19:15:025708// Tests that receiving HEADERS, DATA, HEADERS, and DATA in that sequence will
5709// trigger a ERR_SPDY_PROTOCOL_ERROR because trailing HEADERS must not be
5710// followed by any DATA frames.
bncd16676a2016-07-20 16:23:015711TEST_F(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) {
Ryan Hamilton0239aac2018-05-19 00:03:135712 spdy::SpdySerializedFrame req(
5713 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
5714 spdy::SpdySerializedFrame rst(
5715 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
[email protected]b771bb72013-06-24 09:55:415716 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415717 CreateMockWrite(req, 0), CreateMockWrite(rst, 5),
[email protected]b771bb72013-06-24 09:55:415718 };
[email protected]d08358502010-12-03 22:04:035719
Ryan Hamilton0239aac2018-05-19 00:03:135720 spdy::SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:355721 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135722 spdy::SpdySerializedFrame stream1_body(
5723 spdy_util_.ConstructSpdyDataFrame(1, false));
bnc38dcd392016-02-09 23:19:495724
Ryan Hamilton0239aac2018-05-19 00:03:135725 spdy::SpdyHeaderBlock late_headers;
bnc38dcd392016-02-09 23:19:495726 late_headers["hello"] = "bye";
Ryan Hamilton0239aac2018-05-19 00:03:135727 spdy::SpdySerializedFrame stream1_headers(
5728 spdy_util_.ConstructSpdyResponseHeaders(1, std::move(late_headers),
5729 false));
5730 spdy::SpdySerializedFrame stream1_body2(
5731 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d08358502010-12-03 22:04:035732 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415733 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_body, 2),
5734 CreateMockRead(stream1_headers, 3), CreateMockRead(stream1_body2, 4),
rch08e3aa3e2015-05-16 14:27:525735 MockRead(ASYNC, 0, 6) // EOF
[email protected]d08358502010-12-03 22:04:035736 };
5737
Ryan Sleevib8d7ea02018-05-07 20:01:015738 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:105739 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]dd54bd82012-07-19 23:44:575740 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035741 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:015742 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d08358502010-12-03 22:04:035743}
5744
Bence Békye7023f82018-05-14 01:53:035745struct PushUrlTestParams {
5746 const char* url_to_fetch;
5747 const char* url_to_push;
Bence Békyb2f76672018-06-11 21:10:135748 bool client_cert_sent;
Bence Békyeacd48f2018-05-14 11:34:335749 SpdyPushedStreamFate expected_fate;
Bence Békye7023f82018-05-14 01:53:035750} push_url_test_cases[] = {
5751 // http scheme cannot be pushed (except by trusted proxy).
Bence Békyb2f76672018-06-11 21:10:135752 {"https://www.example.org/foo.html", "http://www.example.org/foo.js", false,
Bence Békyeacd48f2018-05-14 11:34:335753 SpdyPushedStreamFate::kNonHttpsPushedScheme},
Bence Békye7023f82018-05-14 01:53:035754 // ftp scheme cannot be pushed.
Bence Békyb2f76672018-06-11 21:10:135755 {"https://www.example.org/foo.html", "ftp://www.example.org/foo.js", false,
Bence Békyeacd48f2018-05-14 11:34:335756 SpdyPushedStreamFate::kInvalidUrl},
Bence Békye7023f82018-05-14 01:53:035757 // Cross subdomain, certificate not valid.
Bence Békyeacd48f2018-05-14 11:34:335758 {"https://www.example.org/foo.html", "https://blat.www.example.org/foo.js",
Bence Békyb2f76672018-06-11 21:10:135759 false, SpdyPushedStreamFate::kCertificateMismatch},
Bence Békye7023f82018-05-14 01:53:035760 // Cross domain, certificate not valid.
Bence Békyb2f76672018-06-11 21:10:135761 {"https://www.example.org/foo.html", "https://www.foo.com/foo.js", false,
5762 SpdyPushedStreamFate::kCertificateMismatch},
5763 // Cross domain, certificate valid, but cross-origin push is rejected on a
5764 // connection with client certificate.
5765 {"https://www.example.org/foo.html", "https://mail.example.org/foo.js",
5766 true, SpdyPushedStreamFate::kCertificateMismatch}};
Bence Békye7023f82018-05-14 01:53:035767
5768class SpdyNetworkTransactionPushUrlTest
5769 : public SpdyNetworkTransactionTest,
5770 public ::testing::WithParamInterface<PushUrlTestParams> {
5771 protected:
[email protected]a7a265ef2010-12-08 18:05:575772 // In this test we want to verify that we can't accidentally push content
5773 // which can't be pushed by this content server.
5774 // This test assumes that:
5775 // - if we're requesting http://www.foo.com/barbaz
5776 // - the browser has made a connection to "www.foo.com".
Bence Békye7023f82018-05-14 01:53:035777 void RunTest() {
Bence Békyeacd48f2018-05-14 11:34:335778 base::HistogramTester histogram_tester;
5779
bncd16676a2016-07-20 16:23:015780 SpdyTestUtil spdy_test_util;
Ryan Hamilton0239aac2018-05-19 00:03:135781 spdy::SpdySerializedFrame stream1_syn(
Bence Békye7023f82018-05-14 01:53:035782 spdy_test_util.ConstructSpdyGet(GetParam().url_to_fetch, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:135783 spdy::SpdySerializedFrame stream1_body(
bncdf80d44fd2016-07-15 20:27:415784 spdy_test_util.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:135785 spdy::SpdySerializedFrame push_rst(spdy_test_util.ConstructSpdyRstStream(
5786 2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]a7a265ef2010-12-08 18:05:575787 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415788 CreateMockWrite(stream1_syn, 0), CreateMockWrite(push_rst, 3),
[email protected]a7a265ef2010-12-08 18:05:575789 };
5790
Ryan Hamilton0239aac2018-05-19 00:03:135791 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:155792 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135793 spdy::SpdySerializedFrame stream2_syn(spdy_test_util.ConstructSpdyPush(
Bence Békye7023f82018-05-14 01:53:035794 nullptr, 0, 2, 1, GetParam().url_to_push));
[email protected]8a0fc822013-06-27 20:52:435795 const char kPushedData[] = "pushed";
Ryan Hamilton0239aac2018-05-19 00:03:135796 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:195797 spdy_test_util.ConstructSpdyDataFrame(2, kPushedData, true));
Ryan Hamilton0239aac2018-05-19 00:03:135798 spdy::SpdySerializedFrame rst(
5799 spdy_test_util.ConstructSpdyRstStream(2, spdy::ERROR_CODE_CANCEL));
[email protected]a7a265ef2010-12-08 18:05:575800
5801 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415802 CreateMockRead(stream1_reply, 1),
5803 CreateMockRead(stream2_syn, 2),
5804 CreateMockRead(stream1_body, 4),
5805 CreateMockRead(stream2_body, 5),
rch08e3aa3e2015-05-16 14:27:525806 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]a7a265ef2010-12-08 18:05:575807 };
5808
5809 HttpResponseInfo response;
Ryan Sleevib8d7ea02018-05-07 20:01:015810 SequencedSocketData data(reads, writes);
[email protected]a7a265ef2010-12-08 18:05:575811
Bence Békye7023f82018-05-14 01:53:035812 request_.url = GURL(GetParam().url_to_fetch);
[email protected]a7a265ef2010-12-08 18:05:575813
[email protected]7c6f7ba2012-04-03 04:09:295814 // Enable cross-origin push. Since we are not using a proxy, this should
5815 // not actually enable cross-origin SPDY push.
Jeremy Roman0579ed62017-08-29 15:56:195816 auto session_deps = std::make_unique<SpdySessionDependencies>();
5817 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:155818 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
5819 "https://123.45.67.89:443", net::ProxyServer::SCHEME_HTTP));
Eric Roman3d8546a2018-09-10 17:00:525820 session_deps->proxy_resolution_service->SetProxyDelegate(
5821 proxy_delegate.get());
Bence Békydb3cf652017-10-10 15:22:105822 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
Bence Békyd3dde832017-09-19 19:02:315823 std::move(session_deps));
Bence Békydb3cf652017-10-10 15:22:105824
[email protected]61b4efc2012-04-27 18:12:505825 helper.RunPreTestSetup();
Bence Békyb2f76672018-06-11 21:10:135826
5827 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
5828 ssl_provider->ssl_info.client_cert_sent = GetParam().client_cert_sent;
5829 ssl_provider->ssl_info.cert =
5830 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
5831 helper.AddDataWithSSLSocketDataProvider(&data, std::move(ssl_provider));
[email protected]7c6f7ba2012-04-03 04:09:295832
[email protected]a7a265ef2010-12-08 18:05:575833 HttpNetworkTransaction* trans = helper.trans();
5834
5835 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415836 TestCompletionCallback callback;
[email protected]a7a265ef2010-12-08 18:05:575837
Bence Békydb3cf652017-10-10 15:22:105838 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:015839 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a7a265ef2010-12-08 18:05:575840 rv = callback.WaitForResult();
5841
bnceb9aa7112017-01-05 01:03:465842 // Finish async network reads/writes.
5843 base::RunLoop().RunUntilIdle();
5844
[email protected]a7a265ef2010-12-08 18:05:575845 // Read the response body.
Bence Béky4e83f492018-05-13 23:14:255846 std::string result;
rch0aecfd82015-05-19 17:22:325847 ReadResult(trans, &result);
[email protected]a7a265ef2010-12-08 18:05:575848
5849 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:175850 EXPECT_TRUE(data.AllReadDataConsumed());
5851 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]a7a265ef2010-12-08 18:05:575852
bnc42331402016-07-25 13:36:155853 // Verify the response headers.
[email protected]a7a265ef2010-12-08 18:05:575854 // Copy the response info, because trans goes away.
5855 response = *trans->GetResponseInfo();
5856
5857 VerifyStreamsClosed(helper);
5858
bnc42331402016-07-25 13:36:155859 // Verify the response headers.
wezca1070932016-05-26 20:30:525860 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:025861 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
Bence Békyeacd48f2018-05-14 11:34:335862
5863 histogram_tester.ExpectBucketCount(
5864 "Net.SpdyPushedStreamFate", static_cast<int>(GetParam().expected_fate),
5865 1);
5866 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
[email protected]a7a265ef2010-12-08 18:05:575867 }
Bence Békye7023f82018-05-14 01:53:035868};
5869
Victor Costan2309ea02019-02-13 21:35:475870INSTANTIATE_TEST_SUITE_P(,
5871 SpdyNetworkTransactionPushUrlTest,
5872 ::testing::ValuesIn(push_url_test_cases));
Bence Békye7023f82018-05-14 01:53:035873
5874TEST_P(SpdyNetworkTransactionPushUrlTest, PushUrlTest) {
5875 RunTest();
[email protected]a7a265ef2010-12-08 18:05:575876}
5877
bnc3e79387f2016-03-15 14:49:205878// Verify that push works cross origin as long as the certificate is valid for
5879// the pushed authority.
bncd16676a2016-07-20 16:23:015880TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOrigin) {
bnc3e79387f2016-03-15 14:49:205881 // "spdy_pooling.pem" is valid for both www.example.org and mail.example.org.
5882 const char* url_to_fetch = "https://www.example.org";
5883 const char* url_to_push = "https://mail.example.org";
5884
Ryan Hamilton0239aac2018-05-19 00:03:135885 spdy::SpdySerializedFrame headers(
bnc3e79387f2016-03-15 14:49:205886 spdy_util_.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:135887 spdy::SpdySerializedFrame push_priority(
tombergan5d22c182017-01-11 02:05:355888 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
bnc3e79387f2016-03-15 14:49:205889 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:355890 CreateMockWrite(headers, 0), CreateMockWrite(push_priority, 3),
bnc3e79387f2016-03-15 14:49:205891 };
5892
Ryan Hamilton0239aac2018-05-19 00:03:135893 spdy::SpdySerializedFrame reply(
5894 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5895 spdy::SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:205896 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
Ryan Hamilton0239aac2018-05-19 00:03:135897 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc3e79387f2016-03-15 14:49:205898 const char kPushedData[] = "pushed";
Ryan Hamilton0239aac2018-05-19 00:03:135899 spdy::SpdySerializedFrame pushed_body(
Bence Békyd74f4382018-02-20 18:26:195900 spdy_util_.ConstructSpdyDataFrame(2, kPushedData, true));
bnc3e79387f2016-03-15 14:49:205901 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415902 CreateMockRead(reply, 1),
bnceb9aa7112017-01-05 01:03:465903 CreateMockRead(push, 2, SYNCHRONOUS),
tombergan5d22c182017-01-11 02:05:355904 CreateMockRead(body, 4),
5905 CreateMockRead(pushed_body, 5, SYNCHRONOUS),
5906 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
bnc3e79387f2016-03-15 14:49:205907 };
5908
Ryan Sleevib8d7ea02018-05-07 20:01:015909 SequencedSocketData data(reads, writes);
bnc3e79387f2016-03-15 14:49:205910
Bence Békydb3cf652017-10-10 15:22:105911 request_.url = GURL(url_to_fetch);
bnc3e79387f2016-03-15 14:49:205912
Bence Békydb3cf652017-10-10 15:22:105913 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc3e79387f2016-03-15 14:49:205914 helper.RunPreTestSetup();
5915 helper.AddData(&data);
5916
5917 HttpNetworkTransaction* trans0 = helper.trans();
5918 TestCompletionCallback callback0;
Bence Békydb3cf652017-10-10 15:22:105919 int rv = trans0->Start(&request_, callback0.callback(), log_);
bnc3e79387f2016-03-15 14:49:205920 rv = callback0.GetResult(rv);
robpercival214763f2016-07-01 23:27:015921 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205922
5923 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
bncb26024382016-06-29 02:39:455924 SpdySessionKey key(host_port_pair_, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:115925 PRIVACY_MODE_DISABLED,
5926 SpdySessionKey::IsProxySession::kFalse, SocketTag());
bnc3e79387f2016-03-15 14:49:205927 base::WeakPtr<SpdySession> spdy_session =
bnc9ead3ae2017-03-16 00:48:155928 spdy_session_pool->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:315929 key, /* enable_ip_based_pooling = */ true,
5930 /* is_websocket = */ false, log_);
bnc3e79387f2016-03-15 14:49:205931
Bence Béky285e7d42017-12-04 20:22:115932 EXPECT_EQ(1u, num_unclaimed_pushed_streams(spdy_session));
Bence Béky3b609012017-12-04 15:19:355933 EXPECT_TRUE(
Bence Béky285e7d42017-12-04 20:22:115934 has_unclaimed_pushed_stream_for_url(spdy_session, GURL(url_to_push)));
bnc3e79387f2016-03-15 14:49:205935
bnc691fda62016-08-12 00:43:165936 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:205937 HttpRequestInfo push_request;
5938 push_request.method = "GET";
5939 push_request.url = GURL(url_to_push);
Ramin Halavatib5e433e62018-02-07 07:41:105940 push_request.traffic_annotation =
5941 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc3e79387f2016-03-15 14:49:205942 TestCompletionCallback callback1;
Bence Békyd3dde832017-09-19 19:02:315943 rv = trans1.Start(&push_request, callback1.callback(), log_);
bnc3e79387f2016-03-15 14:49:205944 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:015945 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205946
Bence Béky285e7d42017-12-04 20:22:115947 EXPECT_EQ(0u, num_unclaimed_pushed_streams(spdy_session));
bnc3e79387f2016-03-15 14:49:205948
bnc3e79387f2016-03-15 14:49:205949 HttpResponseInfo response = *trans0->GetResponseInfo();
wezca1070932016-05-26 20:30:525950 EXPECT_TRUE(response.headers);
bnc3e79387f2016-03-15 14:49:205951 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
5952
Bence Béky4e83f492018-05-13 23:14:255953 std::string result0;
bnc3e79387f2016-03-15 14:49:205954 ReadResult(trans0, &result0);
5955 EXPECT_EQ("hello!", result0);
5956
bnc691fda62016-08-12 00:43:165957 HttpResponseInfo push_response = *trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:525958 EXPECT_TRUE(push_response.headers);
bnc3e79387f2016-03-15 14:49:205959 EXPECT_EQ("HTTP/1.1 200", push_response.headers->GetStatusLine());
5960
Bence Béky4e83f492018-05-13 23:14:255961 std::string result1;
bnc691fda62016-08-12 00:43:165962 ReadResult(&trans1, &result1);
bnc3e79387f2016-03-15 14:49:205963 EXPECT_EQ(kPushedData, result1);
tombergan5d22c182017-01-11 02:05:355964
5965 base::RunLoop().RunUntilIdle();
5966 helper.VerifyDataConsumed();
5967 VerifyStreamsClosed(helper);
bnc3e79387f2016-03-15 14:49:205968}
5969
Bence Békyb2f76672018-06-11 21:10:135970// Regression test for https://crbug.com/832859: Server push is accepted on a
5971// connection with client certificate, as long as SpdySessionKey matches.
5972TEST_F(SpdyNetworkTransactionTest, ServerPushWithClientCert) {
5973 spdy::SpdySerializedFrame req(
5974 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY));
5975 spdy::SpdySerializedFrame priority(
5976 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
5977 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(priority, 3)};
5978
5979 spdy::SpdySerializedFrame resp(
5980 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5981 spdy::SpdySerializedFrame push(
5982 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushedUrl));
5983 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
5984 spdy::SpdySerializedFrame body2(
5985 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
5986 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(push, 2),
5987 CreateMockRead(body1, 4), CreateMockRead(body2, 5),
5988 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
5989
5990 SequencedSocketData data(reads, writes);
5991
5992 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
5993 ssl_provider->ssl_info.client_cert_sent = true;
5994 ssl_provider->ssl_info.cert =
5995 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
5996
5997 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
5998 helper.RunPreTestSetup();
5999 helper.AddDataWithSSLSocketDataProvider(&data, std::move(ssl_provider));
6000
6001 EXPECT_TRUE(helper.StartDefaultTest());
6002 helper.FinishDefaultTest();
6003
6004 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
6005 HttpRequestInfo request = CreateGetPushRequest();
6006 TestCompletionCallback callback;
6007 int rv = trans2.Start(&request, callback.callback(), log_);
6008 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6009
6010 rv = callback.WaitForResult();
6011 EXPECT_THAT(rv, IsOk());
6012
6013 const HttpResponseInfo* const response = trans2.GetResponseInfo();
6014 EXPECT_TRUE(response->headers);
6015 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6016
6017 std::string result;
6018 ReadResult(&trans2, &result);
6019 EXPECT_EQ("pushed", result);
6020
6021 EXPECT_TRUE(data.AllReadDataConsumed());
6022 EXPECT_TRUE(data.AllWriteDataConsumed());
6023
6024 VerifyStreamsClosed(helper);
6025}
6026
bnc3e79387f2016-03-15 14:49:206027// Verify that push works cross origin, even if there is already a connection
6028// open to origin of pushed resource.
bncd16676a2016-07-20 16:23:016029TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOriginWithOpenSession) {
bnc3e79387f2016-03-15 14:49:206030 const char* url_to_fetch0 = "https://mail.example.org/foo";
6031 const char* url_to_fetch1 = "https://docs.example.org";
6032 const char* url_to_push = "https://mail.example.org/bar";
6033
bncd16676a2016-07-20 16:23:016034 SpdyTestUtil spdy_util_0;
bnc3e79387f2016-03-15 14:49:206035
Ryan Hamilton0239aac2018-05-19 00:03:136036 spdy::SpdySerializedFrame headers0(
bnc3e79387f2016-03-15 14:49:206037 spdy_util_0.ConstructSpdyGet(url_to_fetch0, 1, LOWEST));
6038 MockWrite writes0[] = {
bncdf80d44fd2016-07-15 20:27:416039 CreateMockWrite(headers0, 0),
bnc3e79387f2016-03-15 14:49:206040 };
6041
Ryan Hamilton0239aac2018-05-19 00:03:136042 spdy::SpdySerializedFrame reply0(
6043 spdy_util_0.ConstructSpdyGetReply(nullptr, 0, 1));
bnc3e79387f2016-03-15 14:49:206044 const char kData0[] = "first";
Ryan Hamilton0239aac2018-05-19 00:03:136045 spdy::SpdySerializedFrame body0(
Bence Békyd74f4382018-02-20 18:26:196046 spdy_util_0.ConstructSpdyDataFrame(1, kData0, true));
bncdf80d44fd2016-07-15 20:27:416047 MockRead reads0[] = {CreateMockRead(reply0, 1), CreateMockRead(body0, 2),
6048 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
bnc3e79387f2016-03-15 14:49:206049
Ryan Sleevib8d7ea02018-05-07 20:01:016050 SequencedSocketData data0(reads0, writes0);
bnc3e79387f2016-03-15 14:49:206051
bncd16676a2016-07-20 16:23:016052 SpdyTestUtil spdy_util_1;
bnc3e79387f2016-03-15 14:49:206053
Ryan Hamilton0239aac2018-05-19 00:03:136054 spdy::SpdySerializedFrame headers1(
bnc3e79387f2016-03-15 14:49:206055 spdy_util_1.ConstructSpdyGet(url_to_fetch1, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:136056 spdy::SpdySerializedFrame push_priority(
tombergan5d22c182017-01-11 02:05:356057 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
bnc3e79387f2016-03-15 14:49:206058 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:416059 CreateMockWrite(headers1, 0),
tombergan5d22c182017-01-11 02:05:356060 CreateMockWrite(push_priority, 3, SYNCHRONOUS),
bnc3e79387f2016-03-15 14:49:206061 };
6062
Ryan Hamilton0239aac2018-05-19 00:03:136063 spdy::SpdySerializedFrame reply1(
6064 spdy_util_1.ConstructSpdyGetReply(nullptr, 0, 1));
6065 spdy::SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:206066 spdy_util_1.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
6067 const char kData1[] = "second";
Ryan Hamilton0239aac2018-05-19 00:03:136068 spdy::SpdySerializedFrame body1(
Bence Békyd74f4382018-02-20 18:26:196069 spdy_util_1.ConstructSpdyDataFrame(1, kData1, true));
bnc3e79387f2016-03-15 14:49:206070 const char kPushedData[] = "pushed";
Ryan Hamilton0239aac2018-05-19 00:03:136071 spdy::SpdySerializedFrame pushed_body(
Bence Békyd74f4382018-02-20 18:26:196072 spdy_util_1.ConstructSpdyDataFrame(2, kPushedData, true));
bnc3e79387f2016-03-15 14:49:206073
6074 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:416075 CreateMockRead(reply1, 1),
bnceb9aa7112017-01-05 01:03:466076 CreateMockRead(push, 2, SYNCHRONOUS),
tombergan5d22c182017-01-11 02:05:356077 CreateMockRead(body1, 4),
6078 CreateMockRead(pushed_body, 5, SYNCHRONOUS),
6079 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
bnc3e79387f2016-03-15 14:49:206080 };
6081
Ryan Sleevib8d7ea02018-05-07 20:01:016082 SequencedSocketData data1(reads1, writes1);
bnc3e79387f2016-03-15 14:49:206083
6084 // Request |url_to_fetch0| to open connection to mail.example.org.
Bence Békydb3cf652017-10-10 15:22:106085 request_.url = GURL(url_to_fetch0);
bnc3e79387f2016-03-15 14:49:206086
Bence Békydb3cf652017-10-10 15:22:106087 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc3e79387f2016-03-15 14:49:206088 helper.RunPreTestSetup();
6089
6090 // "spdy_pooling.pem" is valid for www.example.org, but not for
6091 // docs.example.org.
Jeremy Roman0579ed62017-08-29 15:56:196092 auto ssl_provider0 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:496093 ssl_provider0->ssl_info.cert =
bnc3e79387f2016-03-15 14:49:206094 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
Ryan Sleevi4f832092017-11-21 23:25:496095 ASSERT_TRUE(ssl_provider0->ssl_info.cert);
bnc3e79387f2016-03-15 14:49:206096 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
6097
6098 // "wildcard.pem" is valid for both www.example.org and docs.example.org.
Jeremy Roman0579ed62017-08-29 15:56:196099 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:496100 ssl_provider1->ssl_info.cert =
bnc3e79387f2016-03-15 14:49:206101 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
Ryan Sleevi4f832092017-11-21 23:25:496102 ASSERT_TRUE(ssl_provider1->ssl_info.cert);
bnc3e79387f2016-03-15 14:49:206103 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
6104
6105 HttpNetworkTransaction* trans0 = helper.trans();
6106 TestCompletionCallback callback0;
Bence Békydb3cf652017-10-10 15:22:106107 int rv = trans0->Start(&request_, callback0.callback(), log_);
bnc3e79387f2016-03-15 14:49:206108 rv = callback0.GetResult(rv);
robpercival214763f2016-07-01 23:27:016109 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:206110
6111 // Request |url_to_fetch1|, during which docs.example.org pushes
6112 // |url_to_push|, which happens to be for www.example.org, to which there is
6113 // already an open connection.
bnc691fda62016-08-12 00:43:166114 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:206115 HttpRequestInfo request1;
6116 request1.method = "GET";
6117 request1.url = GURL(url_to_fetch1);
Ramin Halavatib5e433e62018-02-07 07:41:106118 request1.traffic_annotation =
6119 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc3e79387f2016-03-15 14:49:206120 TestCompletionCallback callback1;
Bence Békyd3dde832017-09-19 19:02:316121 rv = trans1.Start(&request1, callback1.callback(), log_);
bnc3e79387f2016-03-15 14:49:206122 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:016123 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:206124
6125 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
6126 HostPortPair host_port_pair0("mail.example.org", 443);
6127 SpdySessionKey key0(host_port_pair0, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:116128 PRIVACY_MODE_DISABLED,
6129 SpdySessionKey::IsProxySession::kFalse, SocketTag());
bnc3e79387f2016-03-15 14:49:206130 base::WeakPtr<SpdySession> spdy_session0 =
bnc9ead3ae2017-03-16 00:48:156131 spdy_session_pool->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:316132 key0, /* enable_ip_based_pooling = */ true,
6133 /* is_websocket = */ false, log_);
bnc3e79387f2016-03-15 14:49:206134
Bence Béky285e7d42017-12-04 20:22:116135 EXPECT_EQ(0u, num_unclaimed_pushed_streams(spdy_session0));
bnc3e79387f2016-03-15 14:49:206136
6137 HostPortPair host_port_pair1("docs.example.org", 443);
6138 SpdySessionKey key1(host_port_pair1, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:116139 PRIVACY_MODE_DISABLED,
6140 SpdySessionKey::IsProxySession::kFalse, SocketTag());
bnc3e79387f2016-03-15 14:49:206141 base::WeakPtr<SpdySession> spdy_session1 =
bnc9ead3ae2017-03-16 00:48:156142 spdy_session_pool->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:316143 key1, /* enable_ip_based_pooling = */ true,
6144 /* is_websocket = */ false, log_);
bnc3e79387f2016-03-15 14:49:206145
Bence Béky285e7d42017-12-04 20:22:116146 EXPECT_EQ(1u, num_unclaimed_pushed_streams(spdy_session1));
Bence Béky3b609012017-12-04 15:19:356147 EXPECT_TRUE(
Bence Béky285e7d42017-12-04 20:22:116148 has_unclaimed_pushed_stream_for_url(spdy_session1, GURL(url_to_push)));
bnc3e79387f2016-03-15 14:49:206149
6150 // Request |url_to_push|, which should be served from the pushed resource.
bnc691fda62016-08-12 00:43:166151 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:206152 HttpRequestInfo push_request;
6153 push_request.method = "GET";
6154 push_request.url = GURL(url_to_push);
Ramin Halavatib5e433e62018-02-07 07:41:106155 push_request.traffic_annotation =
6156 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc3e79387f2016-03-15 14:49:206157 TestCompletionCallback callback2;
Bence Békyd3dde832017-09-19 19:02:316158 rv = trans2.Start(&push_request, callback2.callback(), log_);
bnc3e79387f2016-03-15 14:49:206159 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:016160 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:206161
Bence Béky285e7d42017-12-04 20:22:116162 EXPECT_EQ(0u, num_unclaimed_pushed_streams(spdy_session0));
6163 EXPECT_EQ(0u, num_unclaimed_pushed_streams(spdy_session1));
bnc3e79387f2016-03-15 14:49:206164
bnc3e79387f2016-03-15 14:49:206165 HttpResponseInfo response0 = *trans0->GetResponseInfo();
wezca1070932016-05-26 20:30:526166 EXPECT_TRUE(response0.headers);
bnc3e79387f2016-03-15 14:49:206167 EXPECT_EQ("HTTP/1.1 200", response0.headers->GetStatusLine());
6168
Bence Béky4e83f492018-05-13 23:14:256169 std::string result0;
bnc3e79387f2016-03-15 14:49:206170 ReadResult(trans0, &result0);
6171 EXPECT_EQ(kData0, result0);
6172
bnc691fda62016-08-12 00:43:166173 HttpResponseInfo response1 = *trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:526174 EXPECT_TRUE(response1.headers);
bnc3e79387f2016-03-15 14:49:206175 EXPECT_EQ("HTTP/1.1 200", response1.headers->GetStatusLine());
6176
Bence Béky4e83f492018-05-13 23:14:256177 std::string result1;
bnc691fda62016-08-12 00:43:166178 ReadResult(&trans1, &result1);
bnc3e79387f2016-03-15 14:49:206179 EXPECT_EQ(kData1, result1);
6180
bnc691fda62016-08-12 00:43:166181 HttpResponseInfo push_response = *trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:526182 EXPECT_TRUE(push_response.headers);
bnc3e79387f2016-03-15 14:49:206183 EXPECT_EQ("HTTP/1.1 200", push_response.headers->GetStatusLine());
6184
Bence Béky4e83f492018-05-13 23:14:256185 std::string result2;
bnc691fda62016-08-12 00:43:166186 ReadResult(&trans2, &result2);
bnc3e79387f2016-03-15 14:49:206187 EXPECT_EQ(kPushedData, result2);
tombergan5d22c182017-01-11 02:05:356188
6189 base::RunLoop().RunUntilIdle();
6190 helper.VerifyDataConsumed();
6191 VerifyStreamsClosed(helper);
bnc3e79387f2016-03-15 14:49:206192}
6193
bncd16676a2016-07-20 16:23:016194TEST_F(SpdyNetworkTransactionTest, RetryAfterRefused) {
[email protected]721c0ce2011-10-13 02:41:006195 // Construct the request.
Ryan Hamilton0239aac2018-05-19 00:03:136196 spdy::SpdySerializedFrame req(
6197 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:386198 // Will be destroyed by the RST before stream 3 starts.
6199 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:136200 spdy::SpdySerializedFrame req2(
6201 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
[email protected]721c0ce2011-10-13 02:41:006202 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416203 CreateMockWrite(req, 0), CreateMockWrite(req2, 2),
[email protected]721c0ce2011-10-13 02:41:006204 };
6205
Ryan Hamilton0239aac2018-05-19 00:03:136206 spdy::SpdySerializedFrame refused(
6207 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_REFUSED_STREAM));
6208 spdy::SpdySerializedFrame resp(
6209 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
6210 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]721c0ce2011-10-13 02:41:006211 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416212 CreateMockRead(refused, 1), CreateMockRead(resp, 3),
6213 CreateMockRead(body, 4), MockRead(ASYNC, 0, 5) // EOF
[email protected]721c0ce2011-10-13 02:41:006214 };
6215
Ryan Sleevib8d7ea02018-05-07 20:01:016216 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:106217 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]721c0ce2011-10-13 02:41:006218
6219 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:576220 helper.AddData(&data);
[email protected]721c0ce2011-10-13 02:41:006221
6222 HttpNetworkTransaction* trans = helper.trans();
6223
6224 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:416225 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:106226 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:016227 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]721c0ce2011-10-13 02:41:006228 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016229 EXPECT_THAT(rv, IsOk());
[email protected]721c0ce2011-10-13 02:41:006230
bnceb9aa7112017-01-05 01:03:466231 // Finish async network reads.
6232 base::RunLoop().RunUntilIdle();
6233
[email protected]721c0ce2011-10-13 02:41:006234 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:526235 EXPECT_TRUE(data.AllReadDataConsumed());
6236 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]721c0ce2011-10-13 02:41:006237
bnc42331402016-07-25 13:36:156238 // Verify the response headers.
[email protected]721c0ce2011-10-13 02:41:006239 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526240 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:026241 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]721c0ce2011-10-13 02:41:006242}
6243
bnc42331402016-07-25 13:36:156244TEST_F(SpdyNetworkTransactionTest, OutOfOrderHeaders) {
[email protected]e1f58efa2012-05-15 18:23:406245 // This first request will start to establish the SpdySession.
6246 // Then we will start the second (MEDIUM priority) and then third
6247 // (HIGHEST priority) request in such a way that the third will actually
[email protected]c92f4b4542012-07-26 23:53:216248 // start before the second, causing the second to be numbered differently
[email protected]513963e2013-06-15 01:53:046249 // than the order they were created.
rdsmithebb50aa2015-11-12 03:44:386250 //
6251 // Note that the requests and responses created below are expectations
6252 // of what the above will produce on the wire, and hence are in the
6253 // initial->HIGHEST->LOWEST priority.
6254 //
6255 // Frames are created by SpdySession just before the write associated
6256 // with the frame is attempted, so stream dependencies will be based
6257 // on the streams alive at the point of the request write attempt. Thus
6258 // req1 is alive when req2 is attempted (during but not after the
6259 // |data.RunFor(2);| statement below) but not when req3 is attempted.
6260 // The call to spdy_util_.UpdateWithStreamDestruction() reflects this.
Ryan Hamilton0239aac2018-05-19 00:03:136261 spdy::SpdySerializedFrame req1(
6262 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
6263 spdy::SpdySerializedFrame req2(
6264 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, HIGHEST));
rdsmithebb50aa2015-11-12 03:44:386265 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:136266 spdy::SpdySerializedFrame req3(
6267 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, MEDIUM));
[email protected]e1f58efa2012-05-15 18:23:406268 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416269 MockWrite(ASYNC, ERR_IO_PENDING, 0), CreateMockWrite(req1, 1),
6270 CreateMockWrite(req2, 5), CreateMockWrite(req3, 6),
[email protected]e1f58efa2012-05-15 18:23:406271 };
6272
Ryan Hamilton0239aac2018-05-19 00:03:136273 spdy::SpdySerializedFrame resp1(
6274 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6275 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
6276 spdy::SpdySerializedFrame resp2(
6277 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
6278 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
6279 spdy::SpdySerializedFrame resp3(
6280 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
6281 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]e1f58efa2012-05-15 18:23:406282 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416283 CreateMockRead(resp1, 2), MockRead(ASYNC, ERR_IO_PENDING, 3),
6284 CreateMockRead(body1, 4), CreateMockRead(resp2, 7),
6285 CreateMockRead(body2, 8), CreateMockRead(resp3, 9),
6286 CreateMockRead(body3, 10), MockRead(ASYNC, 0, 11) // EOF
[email protected]e1f58efa2012-05-15 18:23:406287 };
6288
Ryan Sleevib8d7ea02018-05-07 20:01:016289 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:106290 NormalSpdyTransactionHelper helper(request_, LOWEST, log_, nullptr);
[email protected]e1f58efa2012-05-15 18:23:406291 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:336292 helper.AddData(&data);
[email protected]e1f58efa2012-05-15 18:23:406293
6294 // Start the first transaction to set up the SpdySession
6295 HttpNetworkTransaction* trans = helper.trans();
6296 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:106297 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:016298 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e1f58efa2012-05-15 18:23:406299
6300 // Run the message loop, but do not allow the write to complete.
6301 // This leaves the SpdySession with a write pending, which prevents
6302 // SpdySession from attempting subsequent writes until this write completes.
[email protected]fc9d88472013-08-14 02:31:176303 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:406304
6305 // Now, start both new transactions
[email protected]e1f58efa2012-05-15 18:23:406306 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:166307 HttpNetworkTransaction trans2(MEDIUM, helper.session());
Bence Békydb3cf652017-10-10 15:22:106308 rv = trans2.Start(&request_, callback2.callback(), log_);
robpercival214763f2016-07-01 23:27:016309 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:176310 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:406311
[email protected]e1f58efa2012-05-15 18:23:406312 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:166313 HttpNetworkTransaction trans3(HIGHEST, helper.session());
Bence Békydb3cf652017-10-10 15:22:106314 rv = trans3.Start(&request_, callback3.callback(), log_);
robpercival214763f2016-07-01 23:27:016315 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:176316 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:406317
bnc42331402016-07-25 13:36:156318 // We now have two HEADERS frames queued up which will be
[email protected]e1f58efa2012-05-15 18:23:406319 // dequeued only once the first write completes, which we
6320 // now allow to happen.
mmenke666a6fea2015-12-19 04:16:336321 ASSERT_TRUE(data.IsPaused());
6322 data.Resume();
robpercival214763f2016-07-01 23:27:016323 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e1f58efa2012-05-15 18:23:406324
6325 // And now we can allow everything else to run to completion.
mmenke666a6fea2015-12-19 04:16:336326 data.Resume();
6327 base::RunLoop().RunUntilIdle();
robpercival214763f2016-07-01 23:27:016328 EXPECT_THAT(callback2.WaitForResult(), IsOk());
6329 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]e1f58efa2012-05-15 18:23:406330
6331 helper.VerifyDataConsumed();
krasin0bfeb6b2017-01-13 21:48:046332
6333 // At this point the test is completed and we need to safely destroy
6334 // all allocated structures. Helper stores a transaction that has a
6335 // reference to a stack allocated request, which has a short lifetime,
6336 // and is accessed during the transaction destruction. We need to delete
6337 // the transaction while the request is still a valid object.
6338 helper.ResetTrans();
[email protected]e1f58efa2012-05-15 18:23:406339}
6340
[email protected]d11b6912013-06-27 23:07:326341// Test that sent data frames and received WINDOW_UPDATE frames change
6342// the send_window_size_ correctly.
6343
6344// WINDOW_UPDATE is different than most other frames in that it can arrive
6345// while the client is still sending the request body. In order to enforce
6346// this scenario, we feed a couple of dummy frames and give a delay of 0 to
6347// socket data provider, so that initial read that is done as soon as the
6348// stream is created, succeeds and schedules another read. This way reads
6349// and writes are interleaved; after doing a full frame write, SpdyStream
6350// will break out of DoLoop and will read and process a WINDOW_UPDATE.
bnc42331402016-07-25 13:36:156351// Once our WINDOW_UPDATE is read, we cannot send HEADERS right away
[email protected]d11b6912013-06-27 23:07:326352// since request has not been completely written, therefore we feed
6353// enough number of WINDOW_UPDATEs to finish the first read and cause a
6354// write, leading to a complete write of request body; after that we send
6355// a reply with a body, to cause a graceful shutdown.
6356
6357// TODO(agayev): develop a socket data provider where both, reads and
6358// writes are ordered so that writing tests like these are easy and rewrite
6359// all these tests using it. Right now we are working around the
6360// limitations as described above and it's not deterministic, tests may
6361// fail under specific circumstances.
bncd16676a2016-07-20 16:23:016362TEST_F(SpdyNetworkTransactionTest, WindowUpdateReceived) {
[email protected]d11b6912013-06-27 23:07:326363 static int kFrameCount = 2;
Bence Békyd74f4382018-02-20 18:26:196364 std::string content(kMaxSpdyFrameChunkSize, 'a');
Ryan Hamilton0239aac2018-05-19 00:03:136365 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
tombergan5d22c182017-01-11 02:05:356366 kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, nullptr,
6367 0));
Ryan Hamilton0239aac2018-05-19 00:03:136368 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:196369 spdy_util_.ConstructSpdyDataFrame(1, content, false));
Ryan Hamilton0239aac2018-05-19 00:03:136370 spdy::SpdySerializedFrame body_end(
Bence Békyd74f4382018-02-20 18:26:196371 spdy_util_.ConstructSpdyDataFrame(1, content, true));
[email protected]d11b6912013-06-27 23:07:326372
6373 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416374 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
6375 CreateMockWrite(body_end, 2),
[email protected]d11b6912013-06-27 23:07:326376 };
6377
Avi Drissman13fc8932015-12-20 04:40:466378 static const int32_t kDeltaWindowSize = 0xff;
[email protected]d11b6912013-06-27 23:07:326379 static const int kDeltaCount = 4;
Ryan Hamilton0239aac2018-05-19 00:03:136380 spdy::SpdySerializedFrame window_update(
[email protected]d11b6912013-06-27 23:07:326381 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
Ryan Hamilton0239aac2018-05-19 00:03:136382 spdy::SpdySerializedFrame window_update_dummy(
[email protected]d11b6912013-06-27 23:07:326383 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
Ryan Hamilton0239aac2018-05-19 00:03:136384 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]d11b6912013-06-27 23:07:326385 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416386 CreateMockRead(window_update_dummy, 3),
6387 CreateMockRead(window_update_dummy, 4),
6388 CreateMockRead(window_update_dummy, 5),
6389 CreateMockRead(window_update, 6), // Four updates, therefore window
6390 CreateMockRead(window_update, 7), // size should increase by
6391 CreateMockRead(window_update, 8), // kDeltaWindowSize * 4
6392 CreateMockRead(window_update, 9),
6393 CreateMockRead(resp, 10),
6394 MockRead(ASYNC, ERR_IO_PENDING, 11),
6395 CreateMockRead(body_end, 12),
mmenke666a6fea2015-12-19 04:16:336396 MockRead(ASYNC, 0, 13) // EOF
[email protected]d11b6912013-06-27 23:07:326397 };
6398
Ryan Sleevib8d7ea02018-05-07 20:01:016399 SequencedSocketData data(reads, writes);
[email protected]d11b6912013-06-27 23:07:326400
danakjaee3e1ec2016-04-16 00:23:186401 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:326402 for (int i = 0; i < kFrameCount; ++i) {
Jeremy Roman0579ed62017-08-29 15:56:196403 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Bence Békyd74f4382018-02-20 18:26:196404 content.data(), content.size()));
[email protected]d11b6912013-06-27 23:07:326405 }
olli.raula6df48b2a2015-11-26 07:40:226406 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326407
Bence Békydb3cf652017-10-10 15:22:106408 // Setup the request.
6409 request_.method = "POST";
6410 request_.upload_data_stream = &upload_data_stream;
[email protected]d11b6912013-06-27 23:07:326411
Bence Békydb3cf652017-10-10 15:22:106412 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
mmenke666a6fea2015-12-19 04:16:336413 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:326414 helper.RunPreTestSetup();
6415
6416 HttpNetworkTransaction* trans = helper.trans();
6417
6418 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:106419 int rv = trans->Start(&request_, callback.callback(), log_);
[email protected]d11b6912013-06-27 23:07:326420
robpercival214763f2016-07-01 23:27:016421 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:326422
mmenke666a6fea2015-12-19 04:16:336423 data.RunUntilPaused();
6424 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326425
6426 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:526427 ASSERT_TRUE(stream);
6428 ASSERT_TRUE(stream->stream());
bncbca843ba2016-07-14 13:05:486429 EXPECT_EQ(static_cast<int>(kDefaultInitialWindowSize) +
6430 kDeltaWindowSize * kDeltaCount -
6431 kMaxSpdyFrameChunkSize * kFrameCount,
6432 stream->stream()->send_window_size());
[email protected]d11b6912013-06-27 23:07:326433
mmenke666a6fea2015-12-19 04:16:336434 data.Resume();
6435 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326436
6437 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016438 EXPECT_THAT(rv, IsOk());
[email protected]d11b6912013-06-27 23:07:326439
6440 helper.VerifyDataConsumed();
6441}
6442
6443// Test that received data frames and sent WINDOW_UPDATE frames change
6444// the recv_window_size_ correctly.
bncd16676a2016-07-20 16:23:016445TEST_F(SpdyNetworkTransactionTest, WindowUpdateSent) {
bnc8f0f3b62015-04-08 04:37:236446 // Session level maximum window size that is more than twice the default
6447 // initial window size so that an initial window update is sent.
Avi Drissman13fc8932015-12-20 04:40:466448 const int32_t session_max_recv_window_size = 5 * 64 * 1024;
bncbca843ba2016-07-14 13:05:486449 ASSERT_LT(2 * kDefaultInitialWindowSize, session_max_recv_window_size);
bnc8f0f3b62015-04-08 04:37:236450 // Stream level maximum window size that is less than the session level
6451 // maximum window size so that we test for confusion between the two.
Avi Drissman13fc8932015-12-20 04:40:466452 const int32_t stream_max_recv_window_size = 4 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:236453 ASSERT_GT(session_max_recv_window_size, stream_max_recv_window_size);
6454 // Size of body to be sent. Has to be less than or equal to both window sizes
6455 // so that we do not run out of receiving window. Also has to be greater than
6456 // half of them so that it triggers both a session level and a stream level
6457 // window update frame.
Avi Drissman13fc8932015-12-20 04:40:466458 const int32_t kTargetSize = 3 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:236459 ASSERT_GE(session_max_recv_window_size, kTargetSize);
6460 ASSERT_GE(stream_max_recv_window_size, kTargetSize);
6461 ASSERT_LT(session_max_recv_window_size / 2, kTargetSize);
6462 ASSERT_LT(stream_max_recv_window_size / 2, kTargetSize);
6463 // Size of each DATA frame.
Avi Drissman13fc8932015-12-20 04:40:466464 const int32_t kChunkSize = 4096;
bnc8f0f3b62015-04-08 04:37:236465 // Size of window updates.
6466 ASSERT_EQ(0, session_max_recv_window_size / 2 % kChunkSize);
Avi Drissman13fc8932015-12-20 04:40:466467 const int32_t session_window_update_delta =
bnc8f0f3b62015-04-08 04:37:236468 session_max_recv_window_size / 2 + kChunkSize;
6469 ASSERT_EQ(0, stream_max_recv_window_size / 2 % kChunkSize);
Avi Drissman13fc8932015-12-20 04:40:466470 const int32_t stream_window_update_delta =
bnc8f0f3b62015-04-08 04:37:236471 stream_max_recv_window_size / 2 + kChunkSize;
[email protected]d11b6912013-06-27 23:07:326472
Ryan Hamilton0239aac2018-05-19 00:03:136473 spdy::SpdySerializedFrame preface(
6474 const_cast<char*>(spdy::kHttp2ConnectionHeaderPrefix),
6475 spdy::kHttp2ConnectionHeaderPrefixSize,
6476 /* owns_buffer = */ false);
bnc8abf64af2017-06-07 20:18:546477
Ryan Hamilton0239aac2018-05-19 00:03:136478 spdy::SettingsMap initial_settings;
6479 initial_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
6480 initial_settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] =
bnc3171a2432016-12-28 18:40:266481 kSpdyMaxConcurrentPushedStreams;
Ryan Hamilton0239aac2018-05-19 00:03:136482 initial_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] =
6483 stream_max_recv_window_size;
6484 spdy::SpdySerializedFrame initial_settings_frame(
bnc8f0f3b62015-04-08 04:37:236485 spdy_util_.ConstructSpdySettings(initial_settings));
bnc8abf64af2017-06-07 20:18:546486
Ryan Hamilton0239aac2018-05-19 00:03:136487 spdy::SpdySerializedFrame initial_window_update(
bnc8f0f3b62015-04-08 04:37:236488 spdy_util_.ConstructSpdyWindowUpdate(
Ryan Hamilton0239aac2018-05-19 00:03:136489 spdy::kSessionFlowControlStreamId,
bncbca843ba2016-07-14 13:05:486490 session_max_recv_window_size - kDefaultInitialWindowSize));
bnc8abf64af2017-06-07 20:18:546491
Ryan Hamilton0239aac2018-05-19 00:03:136492 spdy::SpdySerializedFrame combined_frames = CombineFrames(
bncef26b602017-06-12 22:08:196493 {&preface, &initial_settings_frame, &initial_window_update});
[email protected]d11b6912013-06-27 23:07:326494
6495 std::vector<MockWrite> writes;
bncef26b602017-06-12 22:08:196496 writes.push_back(CreateMockWrite(combined_frames));
bnc8abf64af2017-06-07 20:18:546497
Ryan Hamilton0239aac2018-05-19 00:03:136498 spdy::SpdySerializedFrame req(
6499 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416500 writes.push_back(CreateMockWrite(req, writes.size()));
[email protected]d11b6912013-06-27 23:07:326501
[email protected]251029e2014-03-19 06:04:406502 std::vector<MockRead> reads;
Ryan Hamilton0239aac2018-05-19 00:03:136503 spdy::SpdySerializedFrame resp(
6504 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:416505 reads.push_back(CreateMockRead(resp, writes.size() + reads.size()));
[email protected]d11b6912013-06-27 23:07:326506
Ryan Hamilton0239aac2018-05-19 00:03:136507 std::vector<spdy::SpdySerializedFrame> body_frames;
Bence Béky4e83f492018-05-13 23:14:256508 const std::string body_data(kChunkSize, 'x');
[email protected]251029e2014-03-19 06:04:406509 for (size_t remaining = kTargetSize; remaining != 0;) {
6510 size_t frame_size = std::min(remaining, body_data.size());
Bence Békyd74f4382018-02-20 18:26:196511 body_frames.push_back(spdy_util_.ConstructSpdyDataFrame(
6512 1, base::StringPiece(body_data.data(), frame_size), false));
rchacdcbdc2015-05-16 17:16:006513 reads.push_back(
bncdf80d44fd2016-07-15 20:27:416514 CreateMockRead(body_frames.back(), writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:406515 remaining -= frame_size;
6516 }
mmenkee24011922015-12-17 22:12:596517 // Yield.
rchacdcbdc2015-05-16 17:16:006518 reads.push_back(
mmenkee24011922015-12-17 22:12:596519 MockRead(SYNCHRONOUS, ERR_IO_PENDING, writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:406520
Ryan Hamilton0239aac2018-05-19 00:03:136521 spdy::SpdySerializedFrame session_window_update(
bnc8abf64af2017-06-07 20:18:546522 spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta));
rchacdcbdc2015-05-16 17:16:006523 writes.push_back(
bncdf80d44fd2016-07-15 20:27:416524 CreateMockWrite(session_window_update, writes.size() + reads.size()));
Ryan Hamilton0239aac2018-05-19 00:03:136525 spdy::SpdySerializedFrame stream_window_update(
bnc8abf64af2017-06-07 20:18:546526 spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta));
rchacdcbdc2015-05-16 17:16:006527 writes.push_back(
bncdf80d44fd2016-07-15 20:27:416528 CreateMockWrite(stream_window_update, writes.size() + reads.size()));
rchacdcbdc2015-05-16 17:16:006529
Ryan Sleevib8d7ea02018-05-07 20:01:016530 SequencedSocketData data(reads, writes);
[email protected]d11b6912013-06-27 23:07:326531
Jeremy Roman0579ed62017-08-29 15:56:196532 auto session_deps = std::make_unique<SpdySessionDependencies>();
bnc903e8c12016-12-09 20:50:056533 session_deps->session_max_recv_window_size = session_max_recv_window_size;
Ryan Hamilton0239aac2018-05-19 00:03:136534 session_deps->http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] =
bnc3171a2432016-12-28 18:40:266535 stream_max_recv_window_size;
bnc903e8c12016-12-09 20:50:056536
Bence Békydb3cf652017-10-10 15:22:106537 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
bnc903e8c12016-12-09 20:50:056538 std::move(session_deps));
[email protected]d11b6912013-06-27 23:07:326539 helper.AddData(&data);
6540 helper.RunPreTestSetup();
[email protected]d11b6912013-06-27 23:07:326541
bnc8f0f3b62015-04-08 04:37:236542 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
6543 SpdySessionPoolPeer pool_peer(spdy_session_pool);
6544 pool_peer.SetEnableSendingInitialData(true);
bnc8f0f3b62015-04-08 04:37:236545
6546 HttpNetworkTransaction* trans = helper.trans();
[email protected]d11b6912013-06-27 23:07:326547 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:106548 int rv = trans->Start(&request_, callback.callback(), log_);
[email protected]d11b6912013-06-27 23:07:326549
robpercival214763f2016-07-01 23:27:016550 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:326551 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016552 EXPECT_THAT(rv, IsOk());
[email protected]d11b6912013-06-27 23:07:326553
bnceb9aa7112017-01-05 01:03:466554 // Finish async network reads.
6555 base::RunLoop().RunUntilIdle();
6556
[email protected]d11b6912013-06-27 23:07:326557 SpdyHttpStream* stream =
6558 static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:526559 ASSERT_TRUE(stream);
6560 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:326561
[email protected]251029e2014-03-19 06:04:406562 // All data has been read, but not consumed. The window reflects this.
bnc8f0f3b62015-04-08 04:37:236563 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size - kTargetSize),
[email protected]251029e2014-03-19 06:04:406564 stream->stream()->recv_window_size());
[email protected]d11b6912013-06-27 23:07:326565
6566 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526567 ASSERT_TRUE(response);
6568 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026569 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d11b6912013-06-27 23:07:326570 EXPECT_TRUE(response->was_fetched_via_spdy);
6571
6572 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6573 // size increased to default.
Victor Costan9c7302b2018-08-27 16:39:446574 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTargetSize);
[email protected]251029e2014-03-19 06:04:406575 EXPECT_EQ(static_cast<int>(kTargetSize),
Bence Békybdbb0e72018-08-07 21:42:596576 trans->Read(buf.get(), kTargetSize, CompletionOnceCallback()));
bnc8f0f3b62015-04-08 04:37:236577 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size),
[email protected]251029e2014-03-19 06:04:406578 stream->stream()->recv_window_size());
Bence Béky4e83f492018-05-13 23:14:256579 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
[email protected]d11b6912013-06-27 23:07:326580
[email protected]251029e2014-03-19 06:04:406581 // Allow scheduled WINDOW_UPDATE frames to write.
[email protected]fc9d88472013-08-14 02:31:176582 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326583 helper.VerifyDataConsumed();
6584}
6585
6586// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
bncd16676a2016-07-20 16:23:016587TEST_F(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]d11b6912013-06-27 23:07:326588 // Number of full frames we hope to write (but will not, used to
6589 // set content-length header correctly)
6590 static int kFrameCount = 3;
6591
Bence Békyd74f4382018-02-20 18:26:196592 std::string content(kMaxSpdyFrameChunkSize, 'a');
Ryan Hamilton0239aac2018-05-19 00:03:136593 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
tombergan5d22c182017-01-11 02:05:356594 kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, nullptr,
6595 0));
Ryan Hamilton0239aac2018-05-19 00:03:136596 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:196597 spdy_util_.ConstructSpdyDataFrame(1, content, false));
Ryan Hamilton0239aac2018-05-19 00:03:136598 spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream(
6599 1, spdy::ERROR_CODE_FLOW_CONTROL_ERROR));
[email protected]d11b6912013-06-27 23:07:326600
6601 // We're not going to write a data frame with FIN, we'll receive a bad
6602 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6603 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416604 CreateMockWrite(req, 0), CreateMockWrite(body, 2),
6605 CreateMockWrite(rst, 3),
[email protected]d11b6912013-06-27 23:07:326606 };
6607
Avi Drissman13fc8932015-12-20 04:40:466608 static const int32_t kDeltaWindowSize = 0x7fffffff; // cause an overflow
Ryan Hamilton0239aac2018-05-19 00:03:136609 spdy::SpdySerializedFrame window_update(
[email protected]d11b6912013-06-27 23:07:326610 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6611 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416612 CreateMockRead(window_update, 1), MockRead(ASYNC, 0, 4) // EOF
[email protected]d11b6912013-06-27 23:07:326613 };
6614
Ryan Sleevib8d7ea02018-05-07 20:01:016615 SequencedSocketData data(reads, writes);
[email protected]d11b6912013-06-27 23:07:326616
danakjaee3e1ec2016-04-16 00:23:186617 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:326618 for (int i = 0; i < kFrameCount; ++i) {
Jeremy Roman0579ed62017-08-29 15:56:196619 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
Bence Békyd74f4382018-02-20 18:26:196620 content.data(), content.size()));
[email protected]d11b6912013-06-27 23:07:326621 }
olli.raula6df48b2a2015-11-26 07:40:226622 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326623
Bence Békydb3cf652017-10-10 15:22:106624 // Setup the request.
6625 request_.method = "POST";
6626 request_.upload_data_stream = &upload_data_stream;
[email protected]d11b6912013-06-27 23:07:326627
Bence Békydb3cf652017-10-10 15:22:106628 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
[email protected]d11b6912013-06-27 23:07:326629 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:336630 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:326631 HttpNetworkTransaction* trans = helper.trans();
6632
6633 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:106634 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:016635 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:326636
mmenke666a6fea2015-12-19 04:16:336637 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326638 ASSERT_TRUE(callback.have_result());
Bence Béky6b9c1352018-05-10 11:51:256639 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_SPDY_FLOW_CONTROL_ERROR));
[email protected]d11b6912013-06-27 23:07:326640 helper.VerifyDataConsumed();
6641}
6642
Bence Béky05dcb0382017-09-15 20:07:586643// Regression test for https://crbug.com/732019.
Ryan Hamilton0239aac2018-05-19 00:03:136644// RFC7540 Section 6.9.2: A spdy::SETTINGS_INITIAL_WINDOW_SIZE change that
6645// causes any stream flow control window to overflow MUST be treated as a
6646// connection error.
Bence Béky05dcb0382017-09-15 20:07:586647TEST_F(SpdyNetworkTransactionTest, InitialWindowSizeOverflow) {
Ryan Hamilton0239aac2018-05-19 00:03:136648 spdy::SpdySerializedFrame window_update(
Bence Béky05dcb0382017-09-15 20:07:586649 spdy_util_.ConstructSpdyWindowUpdate(1, 0x60000000));
Ryan Hamilton0239aac2018-05-19 00:03:136650 spdy::SettingsMap settings;
6651 settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = 0x60000000;
6652 spdy::SpdySerializedFrame settings_frame(
Bence Béky05dcb0382017-09-15 20:07:586653 spdy_util_.ConstructSpdySettings(settings));
6654 MockRead reads[] = {CreateMockRead(window_update, 1),
6655 CreateMockRead(settings_frame, 2)};
6656
Ryan Hamilton0239aac2018-05-19 00:03:136657 spdy::SpdySerializedFrame req(
6658 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
6659 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
6660 spdy::SpdySerializedFrame goaway(
6661 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_FLOW_CONTROL_ERROR,
6662 "New spdy::SETTINGS_INITIAL_WINDOW_SIZE "
6663 "value overflows flow control window of "
6664 "stream 1."));
Bence Béky05dcb0382017-09-15 20:07:586665 MockWrite writes[] = {CreateMockWrite(req, 0),
6666 CreateMockWrite(settings_ack, 3),
6667 CreateMockWrite(goaway, 4)};
6668
Ryan Sleevib8d7ea02018-05-07 20:01:016669 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:106670 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
Bence Béky05dcb0382017-09-15 20:07:586671 helper.RunToCompletion(&data);
6672 TransactionHelperResult out = helper.output();
6673 EXPECT_THAT(out.rv, IsError(ERR_SPDY_FLOW_CONTROL_ERROR));
6674}
6675
[email protected]d11b6912013-06-27 23:07:326676// Test that after hitting a send window size of 0, the write process
6677// stalls and upon receiving WINDOW_UPDATE frame write resumes.
6678
6679// This test constructs a POST request followed by enough data frames
6680// containing 'a' that would make the window size 0, followed by another
6681// data frame containing default content (which is "hello!") and this frame
rchacdcbdc2015-05-16 17:16:006682// also contains a FIN flag. SequencedSocketData is used to enforce all
6683// writes, save the last, go through before a read could happen. The last frame
6684// ("hello!") is not permitted to go through since by the time its turn
[email protected]d11b6912013-06-27 23:07:326685// arrives, window size is 0. At this point MessageLoop::Run() called via
6686// callback would block. Therefore we call MessageLoop::RunUntilIdle()
6687// which returns after performing all possible writes. We use DCHECKS to
6688// ensure that last data frame is still there and stream has stalled.
6689// After that, next read is artifically enforced, which causes a
6690// WINDOW_UPDATE to be read and I/O process resumes.
bncd16676a2016-07-20 16:23:016691TEST_F(SpdyNetworkTransactionTest, FlowControlStallResume) {
bncbca843ba2016-07-14 13:05:486692 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:456693 // Number of upload data buffers we need to send to zero out the window size
6694 // is the minimal number of upload buffers takes to be bigger than
6695 // |initial_window_size|.
6696 size_t num_upload_buffers =
6697 ceil(static_cast<double>(initial_window_size) / kBufferSize);
6698 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
6699 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
6700 // which has kBufferSize % kMaxSpdyChunkSize bytes.
6701 size_t num_frames_in_one_upload_buffer =
6702 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:326703
6704 // Construct content for a data frame of maximum size.
Bence Béky4e83f492018-05-13 23:14:256705 std::string content(kMaxSpdyFrameChunkSize, 'a');
[email protected]d11b6912013-06-27 23:07:326706
Ryan Hamilton0239aac2018-05-19 00:03:136707 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:456708 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:456709 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
tombergan5d22c182017-01-11 02:05:356710 LOWEST, nullptr, 0));
[email protected]d11b6912013-06-27 23:07:326711
6712 // Full frames.
Ryan Hamilton0239aac2018-05-19 00:03:136713 spdy::SpdySerializedFrame body1(
Bence Békyd74f4382018-02-20 18:26:196714 spdy_util_.ConstructSpdyDataFrame(1, content, false));
[email protected]d11b6912013-06-27 23:07:326715
xunjieli179a6e72016-04-26 19:47:456716 // Last frame in each upload data buffer.
Ryan Hamilton0239aac2018-05-19 00:03:136717 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
Bence Békyd74f4382018-02-20 18:26:196718 1,
6719 base::StringPiece(content.data(), kBufferSize % kMaxSpdyFrameChunkSize),
6720 false));
[email protected]d11b6912013-06-27 23:07:326721
xunjieli179a6e72016-04-26 19:47:456722 // The very last frame before the stalled frames.
Ryan Hamilton0239aac2018-05-19 00:03:136723 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
Bence Békyd74f4382018-02-20 18:26:196724 1,
6725 base::StringPiece(content.data(), initial_window_size % kBufferSize %
6726 kMaxSpdyFrameChunkSize),
6727 false));
xunjieli179a6e72016-04-26 19:47:456728
6729 // Data frames to be sent once WINDOW_UPDATE frame is received.
6730
6731 // If kBufferSize * num_upload_buffers > initial_window_size,
6732 // we need one additional frame to send the rest of 'a'.
Bence Béky4e83f492018-05-13 23:14:256733 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
6734 'a');
Ryan Hamilton0239aac2018-05-19 00:03:136735 spdy::SpdySerializedFrame body4(
Bence Békyd74f4382018-02-20 18:26:196736 spdy_util_.ConstructSpdyDataFrame(1, last_body, false));
xunjieli179a6e72016-04-26 19:47:456737
6738 // Also send a "hello!" after WINDOW_UPDATE.
Ryan Hamilton0239aac2018-05-19 00:03:136739 spdy::SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:326740
6741 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:326742 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:456743 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:416744 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:456745 for (size_t j = 0; j < num_upload_buffers; j++) {
6746 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
6747 if (k == num_frames_in_one_upload_buffer - 1 &&
6748 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
6749 if (j == num_upload_buffers - 1 &&
6750 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:416751 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:456752 } else {
bncdf80d44fd2016-07-15 20:27:416753 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:456754 }
6755 } else {
bncdf80d44fd2016-07-15 20:27:416756 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:456757 }
6758 }
6759 }
[email protected]d11b6912013-06-27 23:07:326760
xunjieli179a6e72016-04-26 19:47:456761 // Fill in mock reads.
6762 std::vector<MockRead> reads;
6763 // Force a pause.
6764 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
6765 // Construct read frame for window updates that gives enough space to upload
6766 // the rest of the data.
Ryan Hamilton0239aac2018-05-19 00:03:136767 spdy::SpdySerializedFrame session_window_update(
xunjieli179a6e72016-04-26 19:47:456768 spdy_util_.ConstructSpdyWindowUpdate(0,
6769 kUploadDataSize + last_body.size()));
Ryan Hamilton0239aac2018-05-19 00:03:136770 spdy::SpdySerializedFrame window_update(spdy_util_.ConstructSpdyWindowUpdate(
bncdf80d44fd2016-07-15 20:27:416771 1, kUploadDataSize + last_body.size()));
xunjieli179a6e72016-04-26 19:47:456772
bncdf80d44fd2016-07-15 20:27:416773 reads.push_back(CreateMockRead(session_window_update, i++));
6774 reads.push_back(CreateMockRead(window_update, i++));
xunjieli179a6e72016-04-26 19:47:456775
6776 // Stalled frames which can be sent after receiving window updates.
6777 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:416778 writes.push_back(CreateMockWrite(body4, i++));
6779 writes.push_back(CreateMockWrite(body5, i++));
xunjieli179a6e72016-04-26 19:47:456780
Ryan Hamilton0239aac2018-05-19 00:03:136781 spdy::SpdySerializedFrame reply(
6782 spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:416783 reads.push_back(CreateMockRead(reply, i++));
6784 reads.push_back(CreateMockRead(body2, i++));
6785 reads.push_back(CreateMockRead(body5, i++));
xunjieli179a6e72016-04-26 19:47:456786 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
[email protected]d11b6912013-06-27 23:07:326787
Ryan Sleevib8d7ea02018-05-07 20:01:016788 SequencedSocketData data(reads, writes);
[email protected]d11b6912013-06-27 23:07:326789
danakjaee3e1ec2016-04-16 00:23:186790 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Bence Béky4e83f492018-05-13 23:14:256791 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:326792 upload_data_string.append(kUploadData, kUploadDataSize);
Jeremy Roman0579ed62017-08-29 15:56:196793 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
bnc3f6a8552017-05-17 13:40:346794 upload_data_string.c_str(), upload_data_string.size()));
olli.raula6df48b2a2015-11-26 07:40:226795 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326796
Bence Békydb3cf652017-10-10 15:22:106797 request_.method = "POST";
6798 request_.upload_data_stream = &upload_data_stream;
6799 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6800
[email protected]d11b6912013-06-27 23:07:326801 helper.AddData(&data);
6802 helper.RunPreTestSetup();
6803
6804 HttpNetworkTransaction* trans = helper.trans();
6805
6806 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:106807 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:016808 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:326809
[email protected]fc9d88472013-08-14 02:31:176810 base::RunLoop().RunUntilIdle(); // Write as much as we can.
[email protected]d11b6912013-06-27 23:07:326811
6812 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:526813 ASSERT_TRUE(stream);
6814 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:326815 EXPECT_EQ(0, stream->stream()->send_window_size());
xunjieli179a6e72016-04-26 19:47:456816 if (initial_window_size % kBufferSize != 0) {
6817 // If it does not take whole number of full upload buffer to zero out
6818 // initial window size, then the upload data is not at EOF, because the
6819 // last read must be stalled.
6820 EXPECT_FALSE(upload_data_stream.IsEOF());
6821 } else {
6822 // All the body data should have been read.
6823 // TODO(satorux): This is because of the weirdness in reading the request
6824 // body in OnSendBodyComplete(). See crbug.com/113107.
6825 EXPECT_TRUE(upload_data_stream.IsEOF());
6826 }
[email protected]d11b6912013-06-27 23:07:326827 // But the body is not yet fully sent (kUploadData is not yet sent)
6828 // since we're send-stalled.
6829 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6830
mmenkee24011922015-12-17 22:12:596831 data.Resume(); // Read in WINDOW_UPDATE frame.
[email protected]d11b6912013-06-27 23:07:326832 rv = callback.WaitForResult();
bnceb9aa7112017-01-05 01:03:466833 EXPECT_THAT(rv, IsOk());
6834
6835 // Finish async network reads.
6836 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326837 helper.VerifyDataConsumed();
6838}
6839
6840// Test we correctly handle the case where the SETTINGS frame results in
6841// unstalling the send window.
bncd16676a2016-07-20 16:23:016842TEST_F(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
bncbca843ba2016-07-14 13:05:486843 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:456844 // Number of upload data buffers we need to send to zero out the window size
6845 // is the minimal number of upload buffers takes to be bigger than
6846 // |initial_window_size|.
6847 size_t num_upload_buffers =
6848 ceil(static_cast<double>(initial_window_size) / kBufferSize);
6849 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
6850 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
6851 // which has kBufferSize % kMaxSpdyChunkSize bytes.
6852 size_t num_frames_in_one_upload_buffer =
6853 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:326854
6855 // Construct content for a data frame of maximum size.
Bence Béky4e83f492018-05-13 23:14:256856 std::string content(kMaxSpdyFrameChunkSize, 'a');
[email protected]d11b6912013-06-27 23:07:326857
Ryan Hamilton0239aac2018-05-19 00:03:136858 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:456859 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:456860 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
tombergan5d22c182017-01-11 02:05:356861 LOWEST, nullptr, 0));
[email protected]d11b6912013-06-27 23:07:326862
6863 // Full frames.
Ryan Hamilton0239aac2018-05-19 00:03:136864 spdy::SpdySerializedFrame body1(
Bence Békyd74f4382018-02-20 18:26:196865 spdy_util_.ConstructSpdyDataFrame(1, content, false));
[email protected]d11b6912013-06-27 23:07:326866
xunjieli179a6e72016-04-26 19:47:456867 // Last frame in each upload data buffer.
Ryan Hamilton0239aac2018-05-19 00:03:136868 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
Bence Békyd74f4382018-02-20 18:26:196869 1,
6870 base::StringPiece(content.data(), kBufferSize % kMaxSpdyFrameChunkSize),
6871 false));
[email protected]d11b6912013-06-27 23:07:326872
xunjieli179a6e72016-04-26 19:47:456873 // The very last frame before the stalled frames.
Ryan Hamilton0239aac2018-05-19 00:03:136874 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
Bence Békyd74f4382018-02-20 18:26:196875 1,
6876 base::StringPiece(content.data(), initial_window_size % kBufferSize %
6877 kMaxSpdyFrameChunkSize),
6878 false));
xunjieli179a6e72016-04-26 19:47:456879
6880 // Data frames to be sent once WINDOW_UPDATE frame is received.
6881
6882 // If kBufferSize * num_upload_buffers > initial_window_size,
6883 // we need one additional frame to send the rest of 'a'.
Bence Béky4e83f492018-05-13 23:14:256884 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
6885 'a');
Ryan Hamilton0239aac2018-05-19 00:03:136886 spdy::SpdySerializedFrame body4(
Bence Békyd74f4382018-02-20 18:26:196887 spdy_util_.ConstructSpdyDataFrame(1, last_body, false));
xunjieli179a6e72016-04-26 19:47:456888
6889 // Also send a "hello!" after WINDOW_UPDATE.
Ryan Hamilton0239aac2018-05-19 00:03:136890 spdy::SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:326891
xunjieli179a6e72016-04-26 19:47:456892 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:326893 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:456894 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:416895 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:456896 for (size_t j = 0; j < num_upload_buffers; j++) {
6897 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
6898 if (k == num_frames_in_one_upload_buffer - 1 &&
6899 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
6900 if (j == num_upload_buffers - 1 &&
6901 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:416902 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:456903 } else {
bncdf80d44fd2016-07-15 20:27:416904 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:456905 }
6906 } else {
bncdf80d44fd2016-07-15 20:27:416907 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:456908 }
6909 }
6910 }
[email protected]d11b6912013-06-27 23:07:326911
xunjieli179a6e72016-04-26 19:47:456912 // Fill in mock reads.
6913 std::vector<MockRead> reads;
6914 // Force a pause.
mmenke666a6fea2015-12-19 04:16:336915 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
6916
[email protected]d11b6912013-06-27 23:07:326917 // Construct read frame for SETTINGS that gives enough space to upload the
6918 // rest of the data.
Ryan Hamilton0239aac2018-05-19 00:03:136919 spdy::SettingsMap settings;
6920 settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = initial_window_size * 2;
6921 spdy::SpdySerializedFrame settings_frame_large(
[email protected]d11b6912013-06-27 23:07:326922 spdy_util_.ConstructSpdySettings(settings));
6923
bncdf80d44fd2016-07-15 20:27:416924 reads.push_back(CreateMockRead(settings_frame_large, i++));
[email protected]d11b6912013-06-27 23:07:326925
Ryan Hamilton0239aac2018-05-19 00:03:136926 spdy::SpdySerializedFrame session_window_update(
xunjieli179a6e72016-04-26 19:47:456927 spdy_util_.ConstructSpdyWindowUpdate(0,
6928 last_body.size() + kUploadDataSize));
bncdf80d44fd2016-07-15 20:27:416929 reads.push_back(CreateMockRead(session_window_update, i++));
[email protected]d11b6912013-06-27 23:07:326930
Ryan Hamilton0239aac2018-05-19 00:03:136931 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
bncdf80d44fd2016-07-15 20:27:416932 writes.push_back(CreateMockWrite(settings_ack, i++));
[email protected]d4a77c12014-05-15 20:45:216933
xunjieli179a6e72016-04-26 19:47:456934 // Stalled frames which can be sent after |settings_ack|.
6935 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:416936 writes.push_back(CreateMockWrite(body4, i++));
6937 writes.push_back(CreateMockWrite(body5, i++));
[email protected]d11b6912013-06-27 23:07:326938
Ryan Hamilton0239aac2018-05-19 00:03:136939 spdy::SpdySerializedFrame reply(
6940 spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:416941 reads.push_back(CreateMockRead(reply, i++));
6942 reads.push_back(CreateMockRead(body2, i++));
6943 reads.push_back(CreateMockRead(body5, i++));
[email protected]d11b6912013-06-27 23:07:326944 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6945
6946 // Force all writes to happen before any read, last write will not
6947 // actually queue a frame, due to window size being 0.
Ryan Sleevib8d7ea02018-05-07 20:01:016948 SequencedSocketData data(reads, writes);
[email protected]d11b6912013-06-27 23:07:326949
danakjaee3e1ec2016-04-16 00:23:186950 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Bence Béky4e83f492018-05-13 23:14:256951 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:326952 upload_data_string.append(kUploadData, kUploadDataSize);
Jeremy Roman0579ed62017-08-29 15:56:196953 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
bnc3f6a8552017-05-17 13:40:346954 upload_data_string.c_str(), upload_data_string.size()));
olli.raula6df48b2a2015-11-26 07:40:226955 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326956
Bence Békydb3cf652017-10-10 15:22:106957 request_.method = "POST";
6958 request_.upload_data_stream = &upload_data_stream;
6959 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
6960
[email protected]d11b6912013-06-27 23:07:326961 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:336962 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:326963
6964 HttpNetworkTransaction* trans = helper.trans();
6965
6966 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:106967 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:016968 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:326969
mmenke666a6fea2015-12-19 04:16:336970 data.RunUntilPaused(); // Write as much as we can.
6971 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326972
6973 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:526974 ASSERT_TRUE(stream);
6975 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:326976 EXPECT_EQ(0, stream->stream()->send_window_size());
6977
xunjieli179a6e72016-04-26 19:47:456978 if (initial_window_size % kBufferSize != 0) {
6979 // If it does not take whole number of full upload buffer to zero out
6980 // initial window size, then the upload data is not at EOF, because the
6981 // last read must be stalled.
6982 EXPECT_FALSE(upload_data_stream.IsEOF());
6983 } else {
6984 // All the body data should have been read.
6985 // TODO(satorux): This is because of the weirdness in reading the request
6986 // body in OnSendBodyComplete(). See crbug.com/113107.
6987 EXPECT_TRUE(upload_data_stream.IsEOF());
6988 }
[email protected]d11b6912013-06-27 23:07:326989 // But the body is not yet fully sent (kUploadData is not yet sent)
6990 // since we're send-stalled.
6991 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6992
mmenke666a6fea2015-12-19 04:16:336993 // Read in SETTINGS frame to unstall.
6994 data.Resume();
6995 base::RunLoop().RunUntilIdle();
6996
[email protected]d11b6912013-06-27 23:07:326997 rv = callback.WaitForResult();
6998 helper.VerifyDataConsumed();
tombergan5d22c182017-01-11 02:05:356999 // If stream is nullptr, that means it was unstalled and closed.
7000 EXPECT_TRUE(stream->stream() == nullptr);
[email protected]d11b6912013-06-27 23:07:327001}
7002
7003// Test we correctly handle the case where the SETTINGS frame results in a
7004// negative send window size.
bncd16676a2016-07-20 16:23:017005TEST_F(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
bncbca843ba2016-07-14 13:05:487006 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:457007 // Number of upload data buffers we need to send to zero out the window size
7008 // is the minimal number of upload buffers takes to be bigger than
7009 // |initial_window_size|.
7010 size_t num_upload_buffers =
7011 ceil(static_cast<double>(initial_window_size) / kBufferSize);
7012 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
7013 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
7014 // which has kBufferSize % kMaxSpdyChunkSize bytes.
7015 size_t num_frames_in_one_upload_buffer =
7016 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:327017
7018 // Construct content for a data frame of maximum size.
Bence Béky4e83f492018-05-13 23:14:257019 std::string content(kMaxSpdyFrameChunkSize, 'a');
[email protected]d11b6912013-06-27 23:07:327020
Ryan Hamilton0239aac2018-05-19 00:03:137021 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:457022 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:457023 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
tombergan5d22c182017-01-11 02:05:357024 LOWEST, nullptr, 0));
[email protected]d11b6912013-06-27 23:07:327025
7026 // Full frames.
Ryan Hamilton0239aac2018-05-19 00:03:137027 spdy::SpdySerializedFrame body1(
Bence Békyd74f4382018-02-20 18:26:197028 spdy_util_.ConstructSpdyDataFrame(1, content, false));
[email protected]d11b6912013-06-27 23:07:327029
xunjieli179a6e72016-04-26 19:47:457030 // Last frame in each upload data buffer.
Ryan Hamilton0239aac2018-05-19 00:03:137031 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
Bence Békyd74f4382018-02-20 18:26:197032 1,
7033 base::StringPiece(content.data(), kBufferSize % kMaxSpdyFrameChunkSize),
7034 false));
[email protected]d11b6912013-06-27 23:07:327035
xunjieli179a6e72016-04-26 19:47:457036 // The very last frame before the stalled frames.
Ryan Hamilton0239aac2018-05-19 00:03:137037 spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
Bence Békyd74f4382018-02-20 18:26:197038 1,
7039 base::StringPiece(content.data(), initial_window_size % kBufferSize %
7040 kMaxSpdyFrameChunkSize),
7041 false));
xunjieli179a6e72016-04-26 19:47:457042
7043 // Data frames to be sent once WINDOW_UPDATE frame is received.
7044
7045 // If kBufferSize * num_upload_buffers > initial_window_size,
7046 // we need one additional frame to send the rest of 'a'.
Bence Béky4e83f492018-05-13 23:14:257047 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
7048 'a');
Ryan Hamilton0239aac2018-05-19 00:03:137049 spdy::SpdySerializedFrame body4(
Bence Békyd74f4382018-02-20 18:26:197050 spdy_util_.ConstructSpdyDataFrame(1, last_body, false));
xunjieli179a6e72016-04-26 19:47:457051
7052 // Also send a "hello!" after WINDOW_UPDATE.
Ryan Hamilton0239aac2018-05-19 00:03:137053 spdy::SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:327054
xunjieli179a6e72016-04-26 19:47:457055 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:327056 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:457057 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:417058 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:457059 for (size_t j = 0; j < num_upload_buffers; j++) {
7060 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
7061 if (k == num_frames_in_one_upload_buffer - 1 &&
7062 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
7063 if (j == num_upload_buffers - 1 &&
7064 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:417065 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:457066 } else {
bncdf80d44fd2016-07-15 20:27:417067 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:457068 }
7069 } else {
bncdf80d44fd2016-07-15 20:27:417070 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:457071 }
7072 }
7073 }
[email protected]d11b6912013-06-27 23:07:327074
xunjieli179a6e72016-04-26 19:47:457075 // Fill in mock reads.
7076 std::vector<MockRead> reads;
7077 // Force a pause.
mmenke666a6fea2015-12-19 04:16:337078 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
[email protected]d11b6912013-06-27 23:07:327079 // Construct read frame for SETTINGS that makes the send_window_size
7080 // negative.
Ryan Hamilton0239aac2018-05-19 00:03:137081 spdy::SettingsMap new_settings;
7082 new_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = initial_window_size / 2;
7083 spdy::SpdySerializedFrame settings_frame_small(
[email protected]d11b6912013-06-27 23:07:327084 spdy_util_.ConstructSpdySettings(new_settings));
7085 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
7086 // positive.
Ryan Hamilton0239aac2018-05-19 00:03:137087 spdy::SpdySerializedFrame session_window_update_init_size(
bnc2f54c832014-12-01 13:31:197088 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
Ryan Hamilton0239aac2018-05-19 00:03:137089 spdy::SpdySerializedFrame window_update_init_size(
bnc2f54c832014-12-01 13:31:197090 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
[email protected]d11b6912013-06-27 23:07:327091
bncdf80d44fd2016-07-15 20:27:417092 reads.push_back(CreateMockRead(settings_frame_small, i++));
7093 reads.push_back(CreateMockRead(session_window_update_init_size, i++));
7094 reads.push_back(CreateMockRead(window_update_init_size, i++));
[email protected]d11b6912013-06-27 23:07:327095
Ryan Hamilton0239aac2018-05-19 00:03:137096 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
bncdf80d44fd2016-07-15 20:27:417097 writes.push_back(CreateMockWrite(settings_ack, i++));
[email protected]d4a77c12014-05-15 20:45:217098
xunjieli179a6e72016-04-26 19:47:457099 // Stalled frames which can be sent after |settings_ack|.
7100 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:417101 writes.push_back(CreateMockWrite(body4, i++));
7102 writes.push_back(CreateMockWrite(body5, i++));
[email protected]d11b6912013-06-27 23:07:327103
Ryan Hamilton0239aac2018-05-19 00:03:137104 spdy::SpdySerializedFrame reply(
7105 spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:417106 reads.push_back(CreateMockRead(reply, i++));
7107 reads.push_back(CreateMockRead(body2, i++));
7108 reads.push_back(CreateMockRead(body5, i++));
[email protected]d11b6912013-06-27 23:07:327109 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
7110
7111 // Force all writes to happen before any read, last write will not
7112 // actually queue a frame, due to window size being 0.
Ryan Sleevib8d7ea02018-05-07 20:01:017113 SequencedSocketData data(reads, writes);
[email protected]d11b6912013-06-27 23:07:327114
danakjaee3e1ec2016-04-16 00:23:187115 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Bence Béky4e83f492018-05-13 23:14:257116 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:327117 upload_data_string.append(kUploadData, kUploadDataSize);
Jeremy Roman0579ed62017-08-29 15:56:197118 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
bnc3f6a8552017-05-17 13:40:347119 upload_data_string.c_str(), upload_data_string.size()));
olli.raula6df48b2a2015-11-26 07:40:227120 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:327121
Bence Békydb3cf652017-10-10 15:22:107122 request_.method = "POST";
7123 request_.upload_data_stream = &upload_data_stream;
7124 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
7125
[email protected]d11b6912013-06-27 23:07:327126 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:337127 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:327128
7129 HttpNetworkTransaction* trans = helper.trans();
7130
7131 TestCompletionCallback callback;
Bence Békydb3cf652017-10-10 15:22:107132 int rv = trans->Start(&request_, callback.callback(), log_);
robpercival214763f2016-07-01 23:27:017133 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:327134
mmenke666a6fea2015-12-19 04:16:337135 data.RunUntilPaused(); // Write as much as we can.
7136 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:327137
7138 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:527139 ASSERT_TRUE(stream);
7140 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:327141 EXPECT_EQ(0, stream->stream()->send_window_size());
7142
xunjieli179a6e72016-04-26 19:47:457143 if (initial_window_size % kBufferSize != 0) {
7144 // If it does not take whole number of full upload buffer to zero out
7145 // initial window size, then the upload data is not at EOF, because the
7146 // last read must be stalled.
7147 EXPECT_FALSE(upload_data_stream.IsEOF());
7148 } else {
7149 // All the body data should have been read.
7150 // TODO(satorux): This is because of the weirdness in reading the request
7151 // body in OnSendBodyComplete(). See crbug.com/113107.
7152 EXPECT_TRUE(upload_data_stream.IsEOF());
7153 }
[email protected]d11b6912013-06-27 23:07:327154
7155 // Read in WINDOW_UPDATE or SETTINGS frame.
mmenke666a6fea2015-12-19 04:16:337156 data.Resume();
7157 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:327158 rv = callback.WaitForResult();
7159 helper.VerifyDataConsumed();
7160}
7161
bncd16676a2016-07-20 16:23:017162TEST_F(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
Bence Békyeacd48f2018-05-14 11:34:337163 base::HistogramTester histogram_tester;
7164
Ryan Hamilton0239aac2018-05-19 00:03:137165 spdy::SpdyHeaderBlock push_headers;
bnc086b39e12016-06-24 13:05:267166 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat", &push_headers);
Ryan Hamilton0239aac2018-05-19 00:03:137167 spdy::SpdySerializedFrame push(
Bence Békyf1d78522018-01-11 01:16:507168 spdy_util_.ConstructSpdyPushPromise(1, 3, std::move(push_headers)));
bncdf80d44fd2016-07-15 20:27:417169 MockRead reads[] = {CreateMockRead(push, 1)};
baranovich212a1292014-09-02 21:45:317170
Ryan Hamilton0239aac2018-05-19 00:03:137171 spdy::SpdySerializedFrame req(
7172 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
7173 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
7174 0, spdy::ERROR_CODE_PROTOCOL_ERROR,
Bence Béky602c40c2017-07-26 05:22:567175 "Received invalid pushed stream id 3 (must be even) on stream id 1."));
baranovich212a1292014-09-02 21:45:317176 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:417177 CreateMockWrite(req, 0), CreateMockWrite(goaway, 2),
baranovich212a1292014-09-02 21:45:317178 };
7179
Ryan Sleevib8d7ea02018-05-07 20:01:017180 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:107181 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
baranovich212a1292014-09-02 21:45:317182 helper.RunToCompletion(&data);
7183 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:017184 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
Bence Békyeacd48f2018-05-14 11:34:337185
7186 histogram_tester.ExpectBucketCount(
7187 "Net.SpdyPushedStreamFate",
7188 static_cast<int>(SpdyPushedStreamFate::kPromisedStreamIdParityError), 1);
7189 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
baranovich212a1292014-09-02 21:45:317190}
7191
bncd16676a2016-07-20 16:23:017192TEST_F(SpdyNetworkTransactionTest,
baranovich212a1292014-09-02 21:45:317193 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
Bence Békyeacd48f2018-05-14 11:34:337194 base::HistogramTester histogram_tester;
7195
Ryan Hamilton0239aac2018-05-19 00:03:137196 spdy::SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
Bence Béky3e01b532018-02-06 23:04:517197 nullptr, 0, 4, 1, "https://www.example.org/a.dat"));
Ryan Hamilton0239aac2018-05-19 00:03:137198 spdy::SpdyHeaderBlock push_b_headers;
Bence Béky3e01b532018-02-06 23:04:517199 spdy_util_.AddUrlToHeaderBlock("https://www.example.org/b.dat",
bnc086b39e12016-06-24 13:05:267200 &push_b_headers);
Ryan Hamilton0239aac2018-05-19 00:03:137201 spdy::SpdySerializedFrame push_b(
Bence Békyf1d78522018-01-11 01:16:507202 spdy_util_.ConstructSpdyPushPromise(1, 2, std::move(push_b_headers)));
baranovich212a1292014-09-02 21:45:317203 MockRead reads[] = {
tombergan5d22c182017-01-11 02:05:357204 CreateMockRead(push_a, 1), CreateMockRead(push_b, 3),
baranovich212a1292014-09-02 21:45:317205 };
7206
Ryan Hamilton0239aac2018-05-19 00:03:137207 spdy::SpdySerializedFrame req(
7208 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
7209 spdy::SpdySerializedFrame priority_a(
tombergan5d22c182017-01-11 02:05:357210 spdy_util_.ConstructSpdyPriority(4, 1, IDLE, true));
Ryan Hamilton0239aac2018-05-19 00:03:137211 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
7212 4, spdy::ERROR_CODE_PROTOCOL_ERROR,
Bence Béky602c40c2017-07-26 05:22:567213 "Received pushed stream id 2 must be larger than last accepted id 4."));
baranovich212a1292014-09-02 21:45:317214 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:357215 CreateMockWrite(req, 0), CreateMockWrite(priority_a, 2),
7216 CreateMockWrite(goaway, 4),
baranovich212a1292014-09-02 21:45:317217 };
7218
Ryan Sleevib8d7ea02018-05-07 20:01:017219 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:107220 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
baranovich212a1292014-09-02 21:45:317221 helper.RunToCompletion(&data);
7222 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:017223 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
Bence Békyeacd48f2018-05-14 11:34:337224
7225 histogram_tester.ExpectBucketCount(
7226 "Net.SpdyPushedStreamFate",
7227 static_cast<int>(SpdyPushedStreamFate::kStreamIdOutOfOrder), 1);
7228 histogram_tester.ExpectTotalCount("Net.SpdyPushedStreamFate", 1);
baranovich212a1292014-09-02 21:45:317229}
7230
bnc76598ab2015-06-29 12:43:077231// Regression test for https://crbug.com/493348: request header exceeds 16 kB
7232// and thus sent in multiple frames when using HTTP/2.
bncd16676a2016-07-20 16:23:017233TEST_F(SpdyNetworkTransactionTest, LargeRequest) {
Bence Béky4e83f492018-05-13 23:14:257234 const std::string kKey("foo");
7235 const std::string kValue(1 << 15, 'z');
bnc76598ab2015-06-29 12:43:077236
Bence Békydb3cf652017-10-10 15:22:107237 request_.extra_headers.SetHeader(kKey, kValue);
bnc76598ab2015-06-29 12:43:077238
Ryan Hamilton0239aac2018-05-19 00:03:137239 spdy::SpdyHeaderBlock headers(
7240 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc086b39e12016-06-24 13:05:267241 headers[kKey] = kValue;
Ryan Hamilton0239aac2018-05-19 00:03:137242 spdy::SpdySerializedFrame req(
bnc42331402016-07-25 13:36:157243 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bnc76598ab2015-06-29 12:43:077244 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:417245 CreateMockWrite(req, 0),
bnc76598ab2015-06-29 12:43:077246 };
7247
Ryan Hamilton0239aac2018-05-19 00:03:137248 spdy::SpdySerializedFrame resp(
7249 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7250 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc76598ab2015-06-29 12:43:077251 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:417252 CreateMockRead(resp, 1), CreateMockRead(body, 2),
bnc76598ab2015-06-29 12:43:077253 MockRead(ASYNC, 0, 3) // EOF
7254 };
7255
Ryan Sleevib8d7ea02018-05-07 20:01:017256 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:107257 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc76598ab2015-06-29 12:43:077258 helper.RunToCompletion(&data);
7259 TransactionHelperResult out = helper.output();
7260
robpercival214763f2016-07-01 23:27:017261 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:027262 EXPECT_EQ("HTTP/1.1 200", out.status_line);
bnc76598ab2015-06-29 12:43:077263 EXPECT_EQ("hello!", out.response_data);
7264}
7265
bncd67383342016-01-08 21:58:437266// Regression test for https://crbug.com/535629: response header exceeds 16 kB.
bncd16676a2016-07-20 16:23:017267TEST_F(SpdyNetworkTransactionTest, LargeResponseHeader) {
Ryan Hamilton0239aac2018-05-19 00:03:137268 spdy::SpdyHeaderBlock headers(
7269 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
7270 spdy::SpdySerializedFrame req(
bnc42331402016-07-25 13:36:157271 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bncd67383342016-01-08 21:58:437272 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:417273 CreateMockWrite(req, 0),
bncd67383342016-01-08 21:58:437274 };
7275
7276 // HPACK decoder implementation limits string literal length to 16 kB.
7277 const char* response_headers[2];
Bence Béky4e83f492018-05-13 23:14:257278 const std::string kKey(16 * 1024, 'a');
bncd67383342016-01-08 21:58:437279 response_headers[0] = kKey.data();
Bence Béky4e83f492018-05-13 23:14:257280 const std::string kValue(16 * 1024, 'b');
bncd67383342016-01-08 21:58:437281 response_headers[1] = kValue.data();
7282
Ryan Hamilton0239aac2018-05-19 00:03:137283 spdy::SpdySerializedFrame resp(
bnc42331402016-07-25 13:36:157284 spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:137285 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bncd67383342016-01-08 21:58:437286 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:417287 CreateMockRead(resp, 1), CreateMockRead(body, 2),
bncd67383342016-01-08 21:58:437288 MockRead(ASYNC, 0, 3) // EOF
7289 };
7290
Bence Békydb3cf652017-10-10 15:22:107291 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bncd67383342016-01-08 21:58:437292
Ryan Sleevib8d7ea02018-05-07 20:01:017293 SequencedSocketData data(reads, writes);
bncd67383342016-01-08 21:58:437294 helper.RunToCompletion(&data);
7295 TransactionHelperResult out = helper.output();
7296
robpercival214763f2016-07-01 23:27:017297 EXPECT_THAT(out.rv, IsOk());
bncd67383342016-01-08 21:58:437298 EXPECT_EQ("HTTP/1.1 200", out.status_line);
7299 EXPECT_EQ("hello!", out.response_data);
7300 ASSERT_TRUE(out.response_info.headers->HasHeaderValue(kKey, kValue));
7301}
7302
bnc204a6d02016-08-01 14:34:277303// End of line delimiter is forbidden according to RFC 7230 Section 3.2.
7304TEST_F(SpdyNetworkTransactionTest, CRLFInHeaderValue) {
Ryan Hamilton0239aac2018-05-19 00:03:137305 spdy::SpdySerializedFrame req(
7306 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
7307 spdy::SpdySerializedFrame rst(
7308 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR));
bnc204a6d02016-08-01 14:34:277309 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 2)};
7310
7311 const char* response_headers[] = {"folded", "foo\r\nbar"};
Ryan Hamilton0239aac2018-05-19 00:03:137312 spdy::SpdySerializedFrame resp(
bnc204a6d02016-08-01 14:34:277313 spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1));
7314 MockRead reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3)};
7315
Ryan Sleevib8d7ea02018-05-07 20:01:017316 SequencedSocketData data(reads, writes);
bnc204a6d02016-08-01 14:34:277317
Bence Békydb3cf652017-10-10 15:22:107318 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc204a6d02016-08-01 14:34:277319 helper.RunToCompletion(&data);
7320 TransactionHelperResult out = helper.output();
7321
7322 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
7323}
7324
bncc22b581e82016-10-27 04:45:427325// Regression test for https://crbug.com/603182.
7326// No response headers received before RST_STREAM: error.
7327TEST_F(SpdyNetworkTransactionTest, RstStreamNoError) {
Ryan Hamilton0239aac2018-05-19 00:03:137328 spdy::SpdySerializedFrame req(
7329 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
bncc22b581e82016-10-27 04:45:427330 MockWrite writes[] = {CreateMockWrite(req, 0, ASYNC)};
7331
Ryan Hamilton0239aac2018-05-19 00:03:137332 spdy::SpdySerializedFrame rst(
7333 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR));
bncc22b581e82016-10-27 04:45:427334 MockRead reads[] = {CreateMockRead(rst, 1), MockRead(ASYNC, 0, 2)};
7335
Ryan Sleevib8d7ea02018-05-07 20:01:017336 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:107337 UseChunkedPostRequest();
7338 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bncc22b581e82016-10-27 04:45:427339 helper.RunToCompletion(&data);
7340 TransactionHelperResult out = helper.output();
7341 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
7342}
7343
7344// Regression test for https://crbug.com/603182.
7345// Response headers and data, then RST_STREAM received,
7346// before request body is sent: success.
7347TEST_F(SpdyNetworkTransactionTest, RstStreamNoErrorAfterResponse) {
Ryan Hamilton0239aac2018-05-19 00:03:137348 spdy::SpdySerializedFrame req(
7349 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
bncc22b581e82016-10-27 04:45:427350 MockWrite writes[] = {CreateMockWrite(req, 0, ASYNC)};
7351
Ryan Hamilton0239aac2018-05-19 00:03:137352 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
7353 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
7354 spdy::SpdySerializedFrame rst(
7355 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR));
bncc22b581e82016-10-27 04:45:427356 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
7357 CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
7358
Ryan Sleevib8d7ea02018-05-07 20:01:017359 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:107360 UseChunkedPostRequest();
7361 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bncc22b581e82016-10-27 04:45:427362 helper.RunToCompletion(&data);
7363 TransactionHelperResult out = helper.output();
7364 EXPECT_THAT(out.rv, IsOk());
7365 EXPECT_EQ("HTTP/1.1 200", out.status_line);
7366 EXPECT_EQ("hello!", out.response_data);
7367}
7368
bncc9f762a2016-12-06 20:38:237369TEST_F(SpdyNetworkTransactionTest, 100Continue) {
Ryan Hamilton0239aac2018-05-19 00:03:137370 spdy::SpdySerializedFrame req(
7371 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncc9f762a2016-12-06 20:38:237372 MockWrite writes[] = {CreateMockWrite(req, 0)};
7373
Ryan Hamilton0239aac2018-05-19 00:03:137374 spdy::SpdyHeaderBlock informational_headers;
7375 informational_headers[spdy::kHttp2StatusHeader] = "100";
7376 spdy::SpdySerializedFrame informational_response(
bncc9f762a2016-12-06 20:38:237377 spdy_util_.ConstructSpdyReply(1, std::move(informational_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:137378 spdy::SpdySerializedFrame resp(
7379 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7380 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bncc9f762a2016-12-06 20:38:237381 MockRead reads[] = {
7382 CreateMockRead(informational_response, 1), CreateMockRead(resp, 2),
7383 CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF
7384 };
7385
Ryan Sleevib8d7ea02018-05-07 20:01:017386 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:107387 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bncc9f762a2016-12-06 20:38:237388 helper.RunToCompletion(&data);
7389 TransactionHelperResult out = helper.output();
7390 EXPECT_THAT(out.rv, IsOk());
7391 EXPECT_EQ("HTTP/1.1 200", out.status_line);
7392 EXPECT_EQ("hello!", out.response_data);
7393}
7394
bnc1ff80872016-12-16 20:57:577395// "A server can send a complete response prior to the client sending an entire
7396// request if the response does not depend on any portion of the request that
7397// has not been sent and received." (RFC7540 Section 8.1)
7398// Regression test for https://crbug.com/606990. Server responds before POST
7399// data are sent and closes connection: this must result in
7400// ERR_CONNECTION_CLOSED (as opposed to ERR_SPDY_PROTOCOL_ERROR).
7401TEST_F(SpdyNetworkTransactionTest, ResponseBeforePostDataSent) {
Ryan Hamilton0239aac2018-05-19 00:03:137402 spdy::SpdySerializedFrame req(
7403 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
bnc1ff80872016-12-16 20:57:577404 MockWrite writes[] = {CreateMockWrite(req, 0)};
7405
Ryan Hamilton0239aac2018-05-19 00:03:137406 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
7407 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc1ff80872016-12-16 20:57:577408 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
7409 MockRead(ASYNC, 0, 3)};
7410
Ryan Sleevib8d7ea02018-05-07 20:01:017411 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:107412 UseChunkedPostRequest();
7413 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc1ff80872016-12-16 20:57:577414
7415 helper.RunPreTestSetup();
7416 helper.AddData(&data);
7417 helper.StartDefaultTest();
7418 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
7419 helper.WaitForCallbackToComplete();
7420 EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED));
7421}
7422
7423// Regression test for https://crbug.com/606990.
7424// Server responds before POST data are sent and resets stream with NO_ERROR.
7425TEST_F(SpdyNetworkTransactionTest, ResponseAndRstStreamBeforePostDataSent) {
Ryan Hamilton0239aac2018-05-19 00:03:137426 spdy::SpdySerializedFrame req(
7427 spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
bnc1ff80872016-12-16 20:57:577428 MockWrite writes[] = {CreateMockWrite(req, 0)};
7429
Ryan Hamilton0239aac2018-05-19 00:03:137430 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
7431 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
7432 spdy::SpdySerializedFrame rst(
7433 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR));
bnc1ff80872016-12-16 20:57:577434 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
7435 CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
7436
Ryan Sleevib8d7ea02018-05-07 20:01:017437 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:107438 UseChunkedPostRequest();
7439 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc1ff80872016-12-16 20:57:577440
7441 helper.RunToCompletion(&data);
7442
7443 TransactionHelperResult out = helper.output();
7444 EXPECT_THAT(out.rv, IsOk());
7445 EXPECT_EQ("HTTP/1.1 200", out.status_line);
7446 EXPECT_EQ("hello!", out.response_data);
7447}
7448
bnc96487ec2017-03-29 19:40:237449// Unsupported frames must be ignored. This is especially important for frame
7450// type 0xb, which used to be the BLOCKED frame in previous versions of SPDY,
7451// but is going to be used for the ORIGIN frame.
7452// TODO(bnc): Implement ORIGIN frame support. https://crbug.com/697333
7453TEST_F(SpdyNetworkTransactionTest, IgnoreUnsupportedOriginFrame) {
Ryan Hamilton0239aac2018-05-19 00:03:137454 spdy::SpdySerializedFrame req(
7455 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bnc96487ec2017-03-29 19:40:237456 MockWrite writes[] = {CreateMockWrite(req, 0)};
7457
7458 const char origin_frame_on_stream_zero[] = {
7459 0x00, 0x00, 0x05, // Length
7460 0x0b, // Type
7461 0x00, // Flags
7462 0x00, 0x00, 0x00, 0x00, // Stream ID
7463 0x00, 0x03, // Origin-Len
7464 'f', 'o', 'o' // ASCII-Origin
7465 };
7466
7467 const char origin_frame_on_stream_one[] = {
7468 0x00, 0x00, 0x05, // Length
7469 0x0b, // Type
7470 0x00, // Flags
7471 0x00, 0x00, 0x00, 0x01, // Stream ID
7472 0x00, 0x03, // Origin-Len
7473 'b', 'a', 'r' // ASCII-Origin
7474 };
7475
Ryan Hamilton0239aac2018-05-19 00:03:137476 spdy::SpdySerializedFrame resp(
7477 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7478 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc96487ec2017-03-29 19:40:237479 MockRead reads[] = {MockRead(ASYNC, origin_frame_on_stream_zero,
Avi Drissman4365a4782018-12-28 19:26:247480 base::size(origin_frame_on_stream_zero), 1),
bnc96487ec2017-03-29 19:40:237481 CreateMockRead(resp, 2),
7482 MockRead(ASYNC, origin_frame_on_stream_one,
Avi Drissman4365a4782018-12-28 19:26:247483 base::size(origin_frame_on_stream_one), 3),
bnc96487ec2017-03-29 19:40:237484 CreateMockRead(body, 4), MockRead(ASYNC, 0, 5)};
7485
Ryan Sleevib8d7ea02018-05-07 20:01:017486 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:107487 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
bnc96487ec2017-03-29 19:40:237488 helper.RunToCompletion(&data);
7489 TransactionHelperResult out = helper.output();
7490 EXPECT_THAT(out.rv, IsOk());
7491 EXPECT_EQ("HTTP/1.1 200", out.status_line);
7492 EXPECT_EQ("hello!", out.response_data);
7493}
7494
[email protected]514aeaf2014-05-23 10:31:517495class SpdyNetworkTransactionTLSUsageCheckTest
7496 : public SpdyNetworkTransactionTest {
7497 protected:
danakjaee3e1ec2016-04-16 00:23:187498 void RunTLSUsageCheckTest(
7499 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
Ryan Hamilton0239aac2018-05-19 00:03:137500 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
7501 0, spdy::ERROR_CODE_INADEQUATE_SECURITY, ""));
bncdf80d44fd2016-07-15 20:27:417502 MockWrite writes[] = {CreateMockWrite(goaway)};
[email protected]514aeaf2014-05-23 10:31:517503
Ryan Sleevib8d7ea02018-05-07 20:01:017504 StaticSocketDataProvider data(base::span<MockRead>(), writes);
Bence Békydb3cf652017-10-10 15:22:107505 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
Bence Békyd3dde832017-09-19 19:02:317506 nullptr);
dchengc7eeda422015-12-26 03:56:487507 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:517508 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:017509 EXPECT_THAT(out.rv, IsError(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
[email protected]514aeaf2014-05-23 10:31:517510 }
7511};
7512
bncd16676a2016-07-20 16:23:017513TEST_F(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
Jeremy Roman0579ed62017-08-29 15:56:197514 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
[email protected]514aeaf2014-05-23 10:31:517515 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
Ryan Sleevi4f832092017-11-21 23:25:497516 &ssl_provider->ssl_info.connection_status);
[email protected]514aeaf2014-05-23 10:31:517517
dchengc7eeda422015-12-26 03:56:487518 RunTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:517519}
7520
bncd16676a2016-07-20 16:23:017521TEST_F(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
Jeremy Roman0579ed62017-08-29 15:56:197522 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
[email protected]514aeaf2014-05-23 10:31:517523 // Set to TLS_RSA_WITH_NULL_MD5
Ryan Sleevi4f832092017-11-21 23:25:497524 SSLConnectionStatusSetCipherSuite(0x1,
7525 &ssl_provider->ssl_info.connection_status);
[email protected]514aeaf2014-05-23 10:31:517526
dchengc7eeda422015-12-26 03:56:487527 RunTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:517528}
7529
Bence Béky306378f2017-06-30 12:09:567530// Regression test for https://crbug.com/737143.
7531// This test sets up an old TLS version just like in TLSVersionTooOld,
Ryan Hamilton0239aac2018-05-19 00:03:137532// and makes sure that it results in an spdy::ERROR_CODE_INADEQUATE_SECURITY
Bence Béky306378f2017-06-30 12:09:567533// even for a non-secure request URL.
7534TEST_F(SpdyNetworkTransactionTest, InsecureUrlCreatesSecureSpdySession) {
Jeremy Roman0579ed62017-08-29 15:56:197535 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
Bence Béky306378f2017-06-30 12:09:567536 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
Ryan Sleevi4f832092017-11-21 23:25:497537 &ssl_provider->ssl_info.connection_status);
Bence Béky306378f2017-06-30 12:09:567538
Ryan Hamilton0239aac2018-05-19 00:03:137539 spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
7540 0, spdy::ERROR_CODE_INADEQUATE_SECURITY, ""));
Bence Béky306378f2017-06-30 12:09:567541 MockWrite writes[] = {CreateMockWrite(goaway)};
Ryan Sleevib8d7ea02018-05-07 20:01:017542 StaticSocketDataProvider data(base::span<MockRead>(), writes);
Bence Béky306378f2017-06-30 12:09:567543
Bence Békydb3cf652017-10-10 15:22:107544 request_.url = GURL("http://www.example.org/");
Bence Béky306378f2017-06-30 12:09:567545
7546 // Need secure proxy so that insecure URL can use HTTP/2.
Jeremy Roman0579ed62017-08-29 15:56:197547 auto session_deps = std::make_unique<SpdySessionDependencies>(
Ramin Halavatica8d5252018-03-12 05:33:497548 ProxyResolutionService::CreateFixedFromPacResult(
7549 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS));
Bence Békydb3cf652017-10-10 15:22:107550 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
Bence Békyd3dde832017-09-19 19:02:317551 std::move(session_deps));
Bence Béky306378f2017-06-30 12:09:567552
7553 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
7554 TransactionHelperResult out = helper.output();
7555 EXPECT_THAT(out.rv, IsError(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
Bence Békydb3cf652017-10-10 15:22:107556}
Bence Béky306378f2017-06-30 12:09:567557
Andrey Kosyakov83a6eee2017-08-14 19:20:047558TEST_F(SpdyNetworkTransactionTest, RequestHeadersCallback) {
Ryan Hamilton0239aac2018-05-19 00:03:137559 spdy::SpdySerializedFrame req(
Bence Béky27ad0a12018-02-08 00:35:487560 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY));
Andrey Kosyakov83a6eee2017-08-14 19:20:047561 MockWrite writes[] = {CreateMockWrite(req, 0)};
7562
Ryan Hamilton0239aac2018-05-19 00:03:137563 spdy::SpdySerializedFrame resp(
7564 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7565 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
Andrey Kosyakov83a6eee2017-08-14 19:20:047566 MockRead reads[] = {
7567 CreateMockRead(resp, 1), CreateMockRead(body, 2),
7568 MockRead(ASYNC, 0, 3) // EOF
7569 };
7570
7571 HttpRawRequestHeaders raw_headers;
7572
Ryan Sleevib8d7ea02018-05-07 20:01:017573 SequencedSocketData data(reads, writes);
Bence Békydb3cf652017-10-10 15:22:107574 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
Andrey Kosyakov83a6eee2017-08-14 19:20:047575 helper.RunPreTestSetup();
7576 helper.AddData(&data);
7577 helper.trans()->SetRequestHeadersCallback(base::Bind(
7578 &HttpRawRequestHeaders::Assign, base::Unretained(&raw_headers)));
7579 helper.StartDefaultTest();
7580 helper.FinishDefaultTestWithoutVerification();
7581 EXPECT_FALSE(raw_headers.headers().empty());
7582 std::string value;
7583 EXPECT_TRUE(raw_headers.FindHeaderForTest(":path", &value));
7584 EXPECT_EQ("/", value);
7585 EXPECT_TRUE(raw_headers.FindHeaderForTest(":method", &value));
7586 EXPECT_EQ("GET", value);
7587 EXPECT_TRUE(raw_headers.request_line().empty());
7588}
7589
Yoav Weiss9693572f2018-01-04 09:37:347590// A request that has adopted a push promise and later got reset by the server
7591// should be retried on a new stream.
7592// Regression test for https://crbug.com/798508.
7593TEST_F(SpdyNetworkTransactionTest, PushCanceledByServerAfterClaimed) {
7594 const char pushed_url[] = "https://www.example.org/a.dat";
7595 // Construct a request to the default URL on stream 1.
Ryan Hamilton0239aac2018-05-19 00:03:137596 spdy::SpdySerializedFrame req(
7597 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
7598 spdy::SpdySerializedFrame req2(
7599 spdy_util_.ConstructSpdyGet(pushed_url, 3, LOWEST));
Yoav Weiss9693572f2018-01-04 09:37:347600 // Construct a priority frame for stream 2.
Ryan Hamilton0239aac2018-05-19 00:03:137601 spdy::SpdySerializedFrame priority(
Yoav Weiss9693572f2018-01-04 09:37:347602 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
7603 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(priority, 3),
7604 CreateMockWrite(req2, 6)};
7605
7606 // Construct a Push Promise frame, with no response.
Ryan Hamilton0239aac2018-05-19 00:03:137607 spdy::SpdySerializedFrame push_promise(spdy_util_.ConstructSpdyPushPromise(
Bence Békyf1d78522018-01-11 01:16:507608 1, 2, spdy_util_.ConstructGetHeaderBlock(pushed_url)));
Yoav Weiss9693572f2018-01-04 09:37:347609 // Construct a RST frame, canceling stream 2.
Ryan Hamilton0239aac2018-05-19 00:03:137610 spdy::SpdySerializedFrame rst_server(
7611 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_CANCEL));
Yoav Weiss9693572f2018-01-04 09:37:347612 // Construct response headers and bodies.
Ryan Hamilton0239aac2018-05-19 00:03:137613 spdy::SpdySerializedFrame resp1(
7614 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7615 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
7616 spdy::SpdySerializedFrame resp2(
7617 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
7618 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
Yoav Weiss9693572f2018-01-04 09:37:347619 MockRead reads[] = {
7620 CreateMockRead(push_promise, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
7621 CreateMockRead(rst_server, 4), MockRead(ASYNC, ERR_IO_PENDING, 5),
7622 CreateMockRead(resp1, 7), CreateMockRead(body1, 8),
7623 CreateMockRead(resp2, 9), CreateMockRead(body2, 10),
7624 MockRead(ASYNC, 0, 11)};
7625
Ryan Sleevib8d7ea02018-05-07 20:01:017626 SequencedSocketData data(reads, writes);
Yoav Weiss9693572f2018-01-04 09:37:347627
7628 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
7629
7630 helper.RunPreTestSetup();
7631 helper.AddData(&data);
7632
7633 HttpNetworkTransaction* trans = helper.trans();
7634
7635 // First request to start the connection.
7636 TestCompletionCallback callback1;
7637 int rv = trans->Start(&request_, callback1.callback(), log_);
7638 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7639
7640 data.RunUntilPaused();
7641
7642 // Get a SpdySession.
7643 SpdySessionKey key(HostPortPair::FromURL(request_.url), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:117644 PRIVACY_MODE_DISABLED,
7645 SpdySessionKey::IsProxySession::kFalse, SocketTag());
Yoav Weiss9693572f2018-01-04 09:37:347646 HttpNetworkSession* session = helper.session();
7647 base::WeakPtr<SpdySession> spdy_session =
7648 session->spdy_session_pool()->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:317649 key, /* enable_ip_based_pooling = */ true,
7650 /* is_websocket = */ false, log_);
Yoav Weiss9693572f2018-01-04 09:37:347651
7652 // Verify that there is one unclaimed push stream.
7653 EXPECT_EQ(1u, num_unclaimed_pushed_streams(spdy_session));
7654
7655 // Claim the pushed stream.
7656 HttpNetworkTransaction transaction2(DEFAULT_PRIORITY, session);
7657 TestCompletionCallback callback2;
7658 HttpRequestInfo request2;
7659 request2.method = "GET";
7660 request2.url = GURL(pushed_url);
Ramin Halavatib5e433e62018-02-07 07:41:107661 request2.traffic_annotation =
7662 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Yoav Weiss9693572f2018-01-04 09:37:347663 transaction2.Start(&request2, callback2.callback(), log_);
7664 base::RunLoop().RunUntilIdle();
7665 EXPECT_EQ(3u, spdy_stream_hi_water_mark(spdy_session));
7666
7667 EXPECT_EQ(0u, num_unclaimed_pushed_streams(spdy_session));
7668
7669 // Continue reading and get the RST.
7670 data.Resume();
7671 base::RunLoop().RunUntilIdle();
7672
7673 // Make sure we got the RST and retried the request.
7674 EXPECT_EQ(2u, num_active_streams(spdy_session));
7675 EXPECT_EQ(0u, num_unclaimed_pushed_streams(spdy_session));
7676 EXPECT_EQ(5u, spdy_stream_hi_water_mark(spdy_session));
7677
7678 data.Resume();
7679
7680 // Test that transactions succeeded.
7681 rv = callback1.WaitForResult();
7682 ASSERT_THAT(rv, IsOk());
7683
7684 rv = callback2.WaitForResult();
7685 ASSERT_THAT(rv, IsOk());
7686
7687 // Read EOF.
7688 base::RunLoop().RunUntilIdle();
7689
7690 // Verify that all data was read and written.
7691 helper.VerifyDataConsumed();
7692}
7693
Bence Béky0ca719f2018-01-31 13:41:197694#if BUILDFLAG(ENABLE_WEBSOCKETS)
Bence Béky8bfacd42018-02-23 13:05:137695
7696TEST_F(SpdyNetworkTransactionTest, WebSocketOpensNewConnection) {
Bence Békyb09dddf12018-07-31 18:52:047697 base::HistogramTester histogram_tester;
Bence Béky0ca719f2018-01-31 13:41:197698 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
7699 helper.RunPreTestSetup();
7700
7701 // First request opens up an HTTP/2 connection.
Ryan Hamilton0239aac2018-05-19 00:03:137702 spdy::SpdySerializedFrame req(
Bence Béky8bfacd42018-02-23 13:05:137703 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY));
Bence Béky0ca719f2018-01-31 13:41:197704 MockWrite writes1[] = {CreateMockWrite(req, 0)};
7705
Ryan Hamilton0239aac2018-05-19 00:03:137706 spdy::SpdySerializedFrame resp(
7707 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7708 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
Bence Béky0ca719f2018-01-31 13:41:197709 MockRead reads1[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
7710 MockRead(ASYNC, ERR_IO_PENDING, 3),
7711 MockRead(ASYNC, 0, 4)};
7712
Ryan Sleevib8d7ea02018-05-07 20:01:017713 SequencedSocketData data1(reads1, writes1);
Bence Béky0ca719f2018-01-31 13:41:197714 helper.AddData(&data1);
7715
Bence Béky8bfacd42018-02-23 13:05:137716 // WebSocket request opens a new connection with HTTP/2 disabled.
Bence Béky0ca719f2018-01-31 13:41:197717 MockWrite writes2[] = {
7718 MockWrite("GET / HTTP/1.1\r\n"
7719 "Host: www.example.org\r\n"
7720 "Connection: Upgrade\r\n"
7721 "Upgrade: websocket\r\n"
7722 "Origin: http://www.example.org\r\n"
7723 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:157724 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7725 "Sec-WebSocket-Extensions: permessage-deflate; "
7726 "client_max_window_bits\r\n\r\n")};
Bence Béky0ca719f2018-01-31 13:41:197727
Bence Béky8d1c6052018-02-07 12:48:157728 MockRead reads2[] = {
7729 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
7730 "Upgrade: websocket\r\n"
7731 "Connection: Upgrade\r\n"
7732 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
7733
Ryan Sleevib8d7ea02018-05-07 20:01:017734 StaticSocketDataProvider data2(reads2, writes2);
Bence Béky0ca719f2018-01-31 13:41:197735
7736 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
7737 // Test that request has empty |alpn_protos|, that is, HTTP/2 is disabled.
7738 ssl_provider2->next_protos_expected_in_ssl_config = NextProtoVector{};
7739 // Force socket to use HTTP/1.1, the default protocol without ALPN.
7740 ssl_provider2->next_proto = kProtoHTTP11;
7741 ssl_provider2->ssl_info.cert =
7742 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
7743 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
7744
7745 TestCompletionCallback callback1;
7746 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
7747 int rv = trans1.Start(&request_, callback1.callback(), log_);
7748 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7749 rv = callback1.WaitForResult();
7750 ASSERT_THAT(rv, IsOk());
7751
7752 const HttpResponseInfo* response = trans1.GetResponseInfo();
7753 ASSERT_TRUE(response->headers);
7754 EXPECT_TRUE(response->was_fetched_via_spdy);
7755 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7756
7757 std::string response_data;
7758 rv = ReadTransaction(&trans1, &response_data);
7759 EXPECT_THAT(rv, IsOk());
7760 EXPECT_EQ("hello!", response_data);
7761
7762 SpdySessionKey key(HostPortPair::FromURL(request_.url), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:117763 PRIVACY_MODE_DISABLED,
7764 SpdySessionKey::IsProxySession::kFalse, SocketTag());
Bence Béky0ca719f2018-01-31 13:41:197765 base::WeakPtr<SpdySession> spdy_session =
7766 helper.session()->spdy_session_pool()->FindAvailableSession(
Bence Békyd885b2b2018-02-03 00:58:317767 key, /* enable_ip_based_pooling = */ true,
7768 /* is_websocket = */ false, log_);
Bence Béky0ca719f2018-01-31 13:41:197769 ASSERT_TRUE(spdy_session);
Bence Békyd885b2b2018-02-03 00:58:317770 EXPECT_FALSE(spdy_session->support_websocket());
Bence Béky0ca719f2018-01-31 13:41:197771
7772 HttpRequestInfo request2;
7773 request2.method = "GET";
7774 request2.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107775 request2.traffic_annotation =
7776 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky0ca719f2018-01-31 13:41:197777 EXPECT_TRUE(HostPortPair::FromURL(request_.url)
7778 .Equals(HostPortPair::FromURL(request2.url)));
7779 request2.extra_headers.SetHeader("Connection", "Upgrade");
7780 request2.extra_headers.SetHeader("Upgrade", "websocket");
7781 request2.extra_headers.SetHeader("Origin", "http://www.example.org");
7782 request2.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
Bence Béky8d1c6052018-02-07 12:48:157783
7784 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
Bence Béky0ca719f2018-01-31 13:41:197785
7786 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
Bence Béky0ca719f2018-01-31 13:41:197787 trans2.SetWebSocketHandshakeStreamCreateHelper(
7788 &websocket_stream_create_helper);
7789
7790 TestCompletionCallback callback2;
7791 rv = trans2.Start(&request2, callback2.callback(), log_);
7792 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7793 rv = callback2.WaitForResult();
7794 ASSERT_THAT(rv, IsOk());
7795
Bence Béky8bfacd42018-02-23 13:05:137796 // HTTP/2 connection is still open, but WebSocket request did not pool to it.
Bence Béky0ca719f2018-01-31 13:41:197797 ASSERT_TRUE(spdy_session);
7798
Bence Béky0ca719f2018-01-31 13:41:197799 data1.Resume();
Bence Békyb09dddf12018-07-31 18:52:047800 base::RunLoop().RunUntilIdle();
Bence Béky0ca719f2018-01-31 13:41:197801 helper.VerifyDataConsumed();
Bence Békyb09dddf12018-07-31 18:52:047802
7803 // Server did not advertise WebSocket support.
7804 histogram_tester.ExpectUniqueSample("Net.SpdySession.ServerSupportsWebSocket",
7805 /* support_websocket = false */ 0,
7806 /* expected_count = */ 1);
Bence Béky0ca719f2018-01-31 13:41:197807}
Bence Béky8bfacd42018-02-23 13:05:137808
7809TEST_F(SpdyNetworkTransactionTest, WebSocketOverHTTP2) {
Bence Békyb09dddf12018-07-31 18:52:047810 base::HistogramTester histogram_tester;
Bence Béky8bfacd42018-02-23 13:05:137811 auto session_deps = std::make_unique<SpdySessionDependencies>();
7812 session_deps->enable_websocket_over_http2 = true;
Bence Béky7a4836c2018-05-08 03:52:487813 NormalSpdyTransactionHelper helper(request_, HIGHEST, log_,
Bence Béky8bfacd42018-02-23 13:05:137814 std::move(session_deps));
7815 helper.RunPreTestSetup();
7816
Ryan Hamilton0239aac2018-05-19 00:03:137817 spdy::SpdySerializedFrame req(
7818 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST));
7819 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
Bence Béky8bfacd42018-02-23 13:05:137820
Ryan Hamilton0239aac2018-05-19 00:03:137821 spdy::SpdyHeaderBlock websocket_request_headers;
7822 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
7823 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "www.example.org";
7824 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
7825 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
7826 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
Bence Béky8bfacd42018-02-23 13:05:137827 websocket_request_headers["origin"] = "http://www.example.org";
7828 websocket_request_headers["sec-websocket-version"] = "13";
7829 websocket_request_headers["sec-websocket-extensions"] =
7830 "permessage-deflate; client_max_window_bits";
Ryan Hamilton0239aac2018-05-19 00:03:137831 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
Bence Béky7a4836c2018-05-08 03:52:487832 3, std::move(websocket_request_headers), MEDIUM, false));
7833
Bence Béky73b85292018-06-14 04:56:437834 spdy::SpdySerializedFrame priority1(
7835 spdy_util_.ConstructSpdyPriority(3, 0, MEDIUM, true));
7836 spdy::SpdySerializedFrame priority2(
7837 spdy_util_.ConstructSpdyPriority(1, 3, LOWEST, true));
7838
7839 MockWrite writes[] = {
7840 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 2),
7841 CreateMockWrite(websocket_request, 4), CreateMockWrite(priority1, 5),
7842 CreateMockWrite(priority2, 6)};
Bence Béky8bfacd42018-02-23 13:05:137843
Ryan Hamilton0239aac2018-05-19 00:03:137844 spdy::SettingsMap settings;
7845 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
7846 spdy::SpdySerializedFrame settings_frame(
Bence Béky8bfacd42018-02-23 13:05:137847 spdy_util_.ConstructSpdySettings(settings));
Ryan Hamilton0239aac2018-05-19 00:03:137848 spdy::SpdySerializedFrame resp1(
7849 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7850 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
7851 spdy::SpdySerializedFrame websocket_response(
Bence Béky8bfacd42018-02-23 13:05:137852 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Bence Béky73b85292018-06-14 04:56:437853 MockRead reads[] = {CreateMockRead(settings_frame, 1),
7854 CreateMockRead(resp1, 3), CreateMockRead(body1, 7),
7855 CreateMockRead(websocket_response, 8),
7856 MockRead(ASYNC, 0, 9)};
Bence Béky8bfacd42018-02-23 13:05:137857
Ryan Sleevib8d7ea02018-05-07 20:01:017858 SequencedSocketData data(reads, writes);
Bence Béky8bfacd42018-02-23 13:05:137859 helper.AddData(&data);
7860
7861 TestCompletionCallback callback1;
Bence Béky7a4836c2018-05-08 03:52:487862 int rv = helper.trans()->Start(&request_, callback1.callback(), log_);
Bence Béky8bfacd42018-02-23 13:05:137863 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Béky8bfacd42018-02-23 13:05:137864
Bence Béky7a4836c2018-05-08 03:52:487865 // Create HTTP/2 connection.
7866 base::RunLoop().RunUntilIdle();
Bence Béky8bfacd42018-02-23 13:05:137867
7868 SpdySessionKey key(HostPortPair::FromURL(request_.url), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:117869 PRIVACY_MODE_DISABLED,
7870 SpdySessionKey::IsProxySession::kFalse, SocketTag());
Bence Béky8bfacd42018-02-23 13:05:137871 base::WeakPtr<SpdySession> spdy_session =
7872 helper.session()->spdy_session_pool()->FindAvailableSession(
7873 key, /* enable_ip_based_pooling = */ true,
7874 /* is_websocket = */ true, log_);
7875 ASSERT_TRUE(spdy_session);
7876 EXPECT_TRUE(spdy_session->support_websocket());
7877
7878 HttpRequestInfo request2;
7879 request2.method = "GET";
7880 request2.url = GURL("wss://www.example.org/");
7881 request2.traffic_annotation =
7882 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7883 EXPECT_TRUE(HostPortPair::FromURL(request_.url)
7884 .Equals(HostPortPair::FromURL(request2.url)));
7885 request2.extra_headers.SetHeader("Origin", "http://www.example.org");
7886 request2.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7887 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
7888 request2.extra_headers.SetHeader("Connection", "Upgrade");
7889 request2.extra_headers.SetHeader("Upgrade", "websocket");
7890
7891 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7892
Bence Béky7a4836c2018-05-08 03:52:487893 HttpNetworkTransaction trans2(MEDIUM, helper.session());
Bence Béky8bfacd42018-02-23 13:05:137894 trans2.SetWebSocketHandshakeStreamCreateHelper(
7895 &websocket_stream_create_helper);
7896
7897 TestCompletionCallback callback2;
7898 rv = trans2.Start(&request2, callback2.callback(), log_);
7899 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Béky7a4836c2018-05-08 03:52:487900
7901 // Create WebSocket stream.
7902 base::RunLoop().RunUntilIdle();
Bence Béky73b85292018-06-14 04:56:437903 ASSERT_TRUE(spdy_session);
7904
7905 // First request has HIGHEST priority, WebSocket request has MEDIUM priority.
7906 // Changing the priority of the first request to LOWEST changes their order,
7907 // and therefore triggers sending PRIORITY frames.
7908 helper.trans()->SetPriority(LOWEST);
Bence Béky7a4836c2018-05-08 03:52:487909
7910 rv = callback1.WaitForResult();
7911 ASSERT_THAT(rv, IsOk());
7912
7913 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
7914 ASSERT_TRUE(response->headers);
7915 EXPECT_TRUE(response->was_fetched_via_spdy);
7916 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7917
7918 std::string response_data;
7919 rv = ReadTransaction(helper.trans(), &response_data);
7920 EXPECT_THAT(rv, IsOk());
7921 EXPECT_EQ("hello!", response_data);
7922
Bence Béky8bfacd42018-02-23 13:05:137923 rv = callback2.WaitForResult();
7924 ASSERT_THAT(rv, IsOk());
7925
Bence Béky8bfacd42018-02-23 13:05:137926 helper.VerifyDataConsumed();
Bence Békyb09dddf12018-07-31 18:52:047927
7928 // Server advertised WebSocket support.
7929 histogram_tester.ExpectUniqueSample("Net.SpdySession.ServerSupportsWebSocket",
7930 /* support_websocket = true */ 1,
7931 /* expected_count = */ 1);
Bence Béky8bfacd42018-02-23 13:05:137932}
7933
Bence Békyfbeb8832018-04-05 23:19:567934TEST_F(SpdyNetworkTransactionTest, WebSocketNegotiatesHttp2) {
7935 HttpRequestInfo request;
7936 request.method = "GET";
7937 request.url = GURL("wss://www.example.org/");
7938 request.traffic_annotation =
7939 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7940 EXPECT_TRUE(HostPortPair::FromURL(request_.url)
7941 .Equals(HostPortPair::FromURL(request.url)));
7942 request.extra_headers.SetHeader("Connection", "Upgrade");
7943 request.extra_headers.SetHeader("Upgrade", "websocket");
7944 request.extra_headers.SetHeader("Origin", "http://www.example.org");
7945 request.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7946
7947 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
7948 helper.RunPreTestSetup();
7949
Ryan Sleevib8d7ea02018-05-07 20:01:017950 StaticSocketDataProvider data;
Bence Békyfbeb8832018-04-05 23:19:567951
7952 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
7953 // Test that request has empty |alpn_protos|, that is, HTTP/2 is disabled.
7954 ssl_provider->next_protos_expected_in_ssl_config = NextProtoVector{};
Bence Békyb4a07f8f2018-05-17 14:31:557955 // Force socket to use HTTP/2, which should never happen (TLS implementation
7956 // should fail TLS handshake if server chooses HTTP/2 without client
7957 // advertising support).
Bence Békyfbeb8832018-04-05 23:19:567958 ssl_provider->next_proto = kProtoHTTP2;
7959 ssl_provider->ssl_info.cert =
7960 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
7961 helper.AddDataWithSSLSocketDataProvider(&data, std::move(ssl_provider));
7962
7963 HttpNetworkTransaction* trans = helper.trans();
7964 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7965 trans->SetWebSocketHandshakeStreamCreateHelper(
7966 &websocket_stream_create_helper);
7967
7968 TestCompletionCallback callback;
7969 int rv = trans->Start(&request, callback.callback(), log_);
7970 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
7971 rv = callback.WaitForResult();
7972 ASSERT_THAT(rv, IsError(ERR_NOT_IMPLEMENTED));
7973
7974 helper.VerifyDataConsumed();
7975}
7976
Bence Béky420bb2d2018-03-30 17:25:267977// Plaintext WebSocket over HTTP/2 is not implemented, see
7978// https://crbug.com/684681.
7979TEST_F(SpdyNetworkTransactionTest, PlaintextWebSocketOverHttp2Proxy) {
Ryan Hamilton0239aac2018-05-19 00:03:137980 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047981 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7982 HostPortPair("www.example.org", 80)));
Bence Béky420bb2d2018-03-30 17:25:267983 MockWrite writes[] = {CreateMockWrite(req, 0)};
7984
Ryan Hamilton0239aac2018-05-19 00:03:137985 spdy::SpdySerializedFrame resp(
7986 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Bence Béky420bb2d2018-03-30 17:25:267987 MockRead reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 2)};
7988
Ryan Sleevib8d7ea02018-05-07 20:01:017989 SequencedSocketData data(reads, writes);
Bence Béky420bb2d2018-03-30 17:25:267990
7991 request_.url = GURL("ws://www.example.org/");
7992 auto session_deps = std::make_unique<SpdySessionDependencies>(
7993 ProxyResolutionService::CreateFixed("https://proxy:70",
7994 TRAFFIC_ANNOTATION_FOR_TESTS));
7995 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
7996 std::move(session_deps));
7997 helper.RunPreTestSetup();
7998 helper.AddData(&data);
7999
8000 HttpNetworkTransaction* trans = helper.trans();
8001 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
8002 trans->SetWebSocketHandshakeStreamCreateHelper(
8003 &websocket_stream_create_helper);
8004
8005 EXPECT_TRUE(helper.StartDefaultTest());
8006 helper.WaitForCallbackToComplete();
8007 EXPECT_THAT(helper.output().rv, IsError(ERR_NOT_IMPLEMENTED));
8008
8009 helper.VerifyDataConsumed();
8010}
8011
Bence Béky6434d5e2018-04-03 13:43:118012// Regression test for https://crbug.com/819101. Open two identical plaintext
Xida Chen9bfe0b62018-04-24 19:52:218013// websocket requests over proxy. The HttpStreamFactory::Job for the second
Bence Béky6434d5e2018-04-03 13:43:118014// request should reuse the first connection.
8015TEST_F(SpdyNetworkTransactionTest, TwoWebSocketRequestsOverHttp2Proxy) {
Ryan Hamilton0239aac2018-05-19 00:03:138016 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:048017 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8018 HostPortPair("www.example.org", 80)));
Bence Béky6434d5e2018-04-03 13:43:118019 MockWrite writes[] = {CreateMockWrite(req, 0)};
8020
Ryan Hamilton0239aac2018-05-19 00:03:138021 spdy::SpdySerializedFrame resp(
8022 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Bence Béky6434d5e2018-04-03 13:43:118023 MockRead reads[] = {CreateMockRead(resp, 1),
8024 MockRead(ASYNC, ERR_IO_PENDING, 2),
8025 MockRead(ASYNC, 0, 3)};
8026
Ryan Sleevib8d7ea02018-05-07 20:01:018027 SequencedSocketData data(reads, writes);
Bence Béky6434d5e2018-04-03 13:43:118028
8029 request_.url = GURL("ws://www.example.org/");
8030 auto session_deps = std::make_unique<SpdySessionDependencies>(
8031 ProxyResolutionService::CreateFixed("https://proxy:70",
8032 TRAFFIC_ANNOTATION_FOR_TESTS));
8033 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8034 std::move(session_deps));
8035 helper.RunPreTestSetup();
8036 helper.AddData(&data);
8037
8038 HttpNetworkTransaction* trans1 = helper.trans();
8039 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
8040 trans1->SetWebSocketHandshakeStreamCreateHelper(
8041 &websocket_stream_create_helper);
8042
8043 EXPECT_TRUE(helper.StartDefaultTest());
8044 helper.WaitForCallbackToComplete();
8045 EXPECT_THAT(helper.output().rv, IsError(ERR_NOT_IMPLEMENTED));
8046
8047 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
8048 trans2.SetWebSocketHandshakeStreamCreateHelper(
8049 &websocket_stream_create_helper);
8050
8051 TestCompletionCallback callback2;
8052 int rv = trans2.Start(&request_, callback2.callback(), log_);
8053 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8054
8055 rv = callback2.WaitForResult();
8056 EXPECT_THAT(rv, IsError(ERR_NOT_IMPLEMENTED));
8057
8058 data.Resume();
8059 base::RunLoop().RunUntilIdle();
8060
8061 helper.VerifyDataConsumed();
8062}
8063
Bence Béky420bb2d2018-03-30 17:25:268064TEST_F(SpdyNetworkTransactionTest, SecureWebSocketOverHttp2Proxy) {
Ryan Hamilton0239aac2018-05-19 00:03:138065 spdy::SpdySerializedFrame connect_request(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:048066 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8067 HostPortPair("www.example.org", 443)));
Bence Béky420bb2d2018-03-30 17:25:268068 const char kWebSocketRequest[] =
8069 "GET / HTTP/1.1\r\n"
8070 "Host: www.example.org\r\n"
8071 "Connection: Upgrade\r\n"
8072 "Upgrade: websocket\r\n"
8073 "Origin: http://www.example.org\r\n"
8074 "Sec-WebSocket-Version: 13\r\n"
8075 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8076 "Sec-WebSocket-Extensions: permessage-deflate; "
8077 "client_max_window_bits\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:138078 spdy::SpdySerializedFrame websocket_request(
Bence Béky420bb2d2018-03-30 17:25:268079 spdy_util_.ConstructSpdyDataFrame(1, kWebSocketRequest, false));
8080 MockWrite writes[] = {CreateMockWrite(connect_request, 0),
8081 CreateMockWrite(websocket_request, 2)};
8082
Ryan Hamilton0239aac2018-05-19 00:03:138083 spdy::SpdySerializedFrame connect_response(
Bence Béky420bb2d2018-03-30 17:25:268084 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8085 const char kWebSocketResponse[] =
8086 "HTTP/1.1 101 Switching Protocols\r\n"
8087 "Upgrade: websocket\r\n"
8088 "Connection: Upgrade\r\n"
8089 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:138090 spdy::SpdySerializedFrame websocket_response(
Bence Béky420bb2d2018-03-30 17:25:268091 spdy_util_.ConstructSpdyDataFrame(1, kWebSocketResponse, false));
8092 MockRead reads[] = {CreateMockRead(connect_response, 1),
8093 CreateMockRead(websocket_response, 3),
8094 MockRead(ASYNC, 0, 4)};
8095
Ryan Sleevib8d7ea02018-05-07 20:01:018096 SequencedSocketData data(reads, writes);
Bence Béky420bb2d2018-03-30 17:25:268097
8098 request_.url = GURL("wss://www.example.org/");
8099 request_.extra_headers.SetHeader("Connection", "Upgrade");
8100 request_.extra_headers.SetHeader("Upgrade", "websocket");
8101 request_.extra_headers.SetHeader("Origin", "http://www.example.org");
8102 request_.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
8103 auto session_deps = std::make_unique<SpdySessionDependencies>(
8104 ProxyResolutionService::CreateFixed("https://proxy:70",
8105 TRAFFIC_ANNOTATION_FOR_TESTS));
8106 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8107 std::move(session_deps));
8108 helper.RunPreTestSetup();
8109 helper.AddData(&data);
8110
8111 // Add SSL data for the tunneled connection.
8112 SSLSocketDataProvider ssl_provider(ASYNC, OK);
8113 ssl_provider.ssl_info.cert =
8114 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
Bence Béky12943c62018-04-05 19:16:508115 // A WebSocket request should not advertise HTTP/2 support.
8116 ssl_provider.next_protos_expected_in_ssl_config = NextProtoVector{};
Bence Béky420bb2d2018-03-30 17:25:268117 // This test uses WebSocket over HTTP/1.1.
8118 ssl_provider.next_proto = kProtoHTTP11;
8119 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
8120 &ssl_provider);
8121
8122 HttpNetworkTransaction* trans = helper.trans();
8123 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
8124 trans->SetWebSocketHandshakeStreamCreateHelper(
8125 &websocket_stream_create_helper);
8126
8127 EXPECT_TRUE(helper.StartDefaultTest());
8128 helper.WaitForCallbackToComplete();
8129 EXPECT_THAT(helper.output().rv, IsOk());
8130 const HttpResponseInfo* response = trans->GetResponseInfo();
8131 ASSERT_TRUE(response);
8132 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
8133 response->connection_info);
8134 EXPECT_TRUE(response->was_alpn_negotiated);
8135 EXPECT_FALSE(response->was_fetched_via_spdy);
Tsuyoshi Horo01faed62019-02-20 22:11:378136 EXPECT_EQ(70, response->remote_endpoint.port());
Bence Béky420bb2d2018-03-30 17:25:268137 ASSERT_TRUE(response->headers);
8138 EXPECT_EQ("HTTP/1.1 101 Switching Protocols",
8139 response->headers->GetStatusLine());
8140
8141 base::RunLoop().RunUntilIdle();
8142 helper.VerifyDataConsumed();
8143}
8144
Bence Béky12943c62018-04-05 19:16:508145// Regression test for https://crbug.com/828865.
8146TEST_F(SpdyNetworkTransactionTest,
8147 SecureWebSocketOverHttp2ProxyNegotiatesHttp2) {
Ryan Hamilton0239aac2018-05-19 00:03:138148 spdy::SpdySerializedFrame connect_request(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:048149 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8150 HostPortPair("www.example.org", 443)));
Bence Béky12943c62018-04-05 19:16:508151 MockWrite writes[] = {CreateMockWrite(connect_request, 0)};
Ryan Hamilton0239aac2018-05-19 00:03:138152 spdy::SpdySerializedFrame connect_response(
Bence Béky12943c62018-04-05 19:16:508153 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8154 MockRead reads[] = {CreateMockRead(connect_response, 1),
8155 MockRead(ASYNC, 0, 2)};
Ryan Sleevib8d7ea02018-05-07 20:01:018156 SequencedSocketData data(reads, writes);
Bence Béky12943c62018-04-05 19:16:508157
8158 request_.url = GURL("wss://www.example.org/");
8159 request_.extra_headers.SetHeader("Connection", "Upgrade");
8160 request_.extra_headers.SetHeader("Upgrade", "websocket");
8161 request_.extra_headers.SetHeader("Origin", "http://www.example.org");
8162 request_.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
8163 auto session_deps = std::make_unique<SpdySessionDependencies>(
8164 ProxyResolutionService::CreateFixed("https://proxy:70",
8165 TRAFFIC_ANNOTATION_FOR_TESTS));
8166 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8167 std::move(session_deps));
8168 helper.RunPreTestSetup();
8169 helper.AddData(&data);
8170
8171 // Add SSL data for the tunneled connection.
8172 SSLSocketDataProvider ssl_provider(ASYNC, OK);
8173 ssl_provider.ssl_info.cert =
8174 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
8175 // A WebSocket request should not advertise HTTP/2 support.
8176 ssl_provider.next_protos_expected_in_ssl_config = NextProtoVector{};
8177 // The server should not negotiate HTTP/2 over the tunnelled connection,
8178 // but it must be handled gracefully if it does.
8179 ssl_provider.next_proto = kProtoHTTP2;
8180 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
8181 &ssl_provider);
8182
8183 HttpNetworkTransaction* trans = helper.trans();
8184 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
8185 trans->SetWebSocketHandshakeStreamCreateHelper(
8186 &websocket_stream_create_helper);
8187
8188 EXPECT_TRUE(helper.StartDefaultTest());
8189 helper.WaitForCallbackToComplete();
8190 EXPECT_THAT(helper.output().rv, IsError(ERR_NOT_IMPLEMENTED));
8191
8192 base::RunLoop().RunUntilIdle();
8193 helper.VerifyDataConsumed();
8194}
8195
Bence Béky0ca719f2018-01-31 13:41:198196#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
8197
Steven Valdez1c1859172019-04-10 15:33:288198TEST_F(SpdyNetworkTransactionTest, ZeroRTTDoesntConfirm) {
8199 spdy::SpdySerializedFrame req(
8200 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
8201 MockWrite writes[] = {CreateMockWrite(req, 0)};
8202
8203 spdy::SpdySerializedFrame resp(
8204 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8205 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8206 MockRead reads[] = {
8207 CreateMockRead(resp, 1), CreateMockRead(body, 2),
8208 MockRead(ASYNC, 0, 3) // EOF
8209 };
8210
8211 SequencedSocketData data(reads, writes);
8212 auto session_deps = std::make_unique<SpdySessionDependencies>();
8213 session_deps->enable_early_data = true;
8214 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8215 std::move(session_deps));
8216 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8217 // Configure |ssl_provider| to fail if ConfirmHandshake is called. The request
8218 // should still succeed.
8219 ssl_provider->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
8220 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
8221 TransactionHelperResult out = helper.output();
8222 EXPECT_THAT(out.rv, IsOk());
8223 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8224 EXPECT_EQ("hello!", out.response_data);
8225}
8226
8227// Run multiple concurrent streams that don't require handshake confirmation.
8228TEST_F(SpdyNetworkTransactionTest, ZeroRTTNoConfirmMultipleStreams) {
8229 spdy::SpdySerializedFrame req1(
8230 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
8231 spdy::SpdySerializedFrame req2(
8232 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST));
8233 MockWrite writes1[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 3)};
8234
8235 spdy::SpdySerializedFrame resp1(
8236 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8237 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
8238 spdy::SpdySerializedFrame resp2(
8239 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
8240 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
8241 MockRead reads1[] = {
8242 CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
8243 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
8244 MockRead(ASYNC, 0, 6) // EOF
8245 };
8246
8247 SequencedSocketData data1(reads1, writes1);
8248 SequencedSocketData data2({}, {});
8249 auto session_deps = std::make_unique<SpdySessionDependencies>();
8250 session_deps->enable_early_data = true;
8251 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8252 std::move(session_deps));
8253 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8254 ssl_provider1->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
8255 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8256 ssl_provider2->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
8257
8258 helper.RunPreTestSetup();
8259 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
8260 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
8261 EXPECT_TRUE(helper.StartDefaultTest());
8262
8263 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
8264 HttpRequestInfo request2;
8265 request2.method = "GET";
8266 request2.url = GURL(kDefaultUrl);
8267 request2.traffic_annotation =
8268 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8269 TestCompletionCallback callback2;
8270 int rv = trans2.Start(&request2, callback2.callback(), log_);
8271 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8272
8273 helper.FinishDefaultTest();
8274 EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk());
8275 helper.VerifyDataConsumed();
8276
8277 TransactionHelperResult out = helper.output();
8278 EXPECT_THAT(out.rv, IsOk());
8279 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8280 EXPECT_EQ("hello!", out.response_data);
8281}
8282
8283// Run multiple concurrent streams that require handshake confirmation.
8284TEST_F(SpdyNetworkTransactionTest, ZeroRTTConfirmMultipleStreams) {
8285 spdy::SpdyHeaderBlock req_block1(
8286 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
8287 spdy::SpdySerializedFrame req1(
8288 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block1), LOWEST, true));
8289 spdy::SpdyHeaderBlock req_block2(
8290 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
8291 spdy::SpdySerializedFrame req2(
8292 spdy_util_.ConstructSpdyHeaders(3, std::move(req_block2), LOWEST, true));
8293 MockWrite writes[] = {
8294 CreateMockWrite(req1, 0),
8295 CreateMockWrite(req2, 3),
8296 };
8297 spdy::SpdySerializedFrame resp1(
8298 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8299 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
8300 spdy::SpdySerializedFrame resp2(
8301 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
8302 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
8303 MockRead reads[] = {
8304 CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
8305 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
8306 MockRead(ASYNC, 0, 6) // EOF
8307 };
8308
8309 SequencedSocketData data1(reads, writes);
8310 SequencedSocketData data2({}, {});
8311 UsePostRequest();
8312 auto session_deps = std::make_unique<SpdySessionDependencies>();
8313 session_deps->enable_early_data = true;
8314 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8315 std::move(session_deps));
8316 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8317 ssl_provider1->confirm = MockConfirm(ASYNC, OK);
8318 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8319 ssl_provider2->confirm = MockConfirm(ASYNC, OK);
8320
8321 helper.RunPreTestSetup();
8322 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
8323 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
8324
8325 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
8326 HttpRequestInfo request1;
8327 request1.method = "POST";
8328 request1.url = GURL(kDefaultUrl);
8329 request1.traffic_annotation =
8330 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8331 TestCompletionCallback callback1;
8332 int rv = trans1.Start(&request1, callback1.callback(), log_);
8333 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8334
8335 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
8336 HttpRequestInfo request2;
8337 request2.method = "POST";
8338 request2.url = GURL(kDefaultUrl);
8339 request2.traffic_annotation =
8340 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8341 TestCompletionCallback callback2;
8342 rv = trans2.Start(&request2, callback2.callback(), log_);
8343 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8344
8345 EXPECT_THAT(callback1.GetResult(ERR_IO_PENDING), IsOk());
8346 EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk());
8347
8348 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
8349 ASSERT_TRUE(response1);
8350 ASSERT_TRUE(response1->headers);
8351 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
8352 response1->connection_info);
8353 EXPECT_EQ("HTTP/1.1 200", response1->headers->GetStatusLine());
8354 std::string response_data;
8355 ReadTransaction(&trans1, &response_data);
8356 EXPECT_EQ("hello!", response_data);
8357
8358 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
8359 ASSERT_TRUE(response2);
8360 ASSERT_TRUE(response2->headers);
8361 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
8362 response2->connection_info);
8363 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
8364 ReadTransaction(&trans2, &response_data);
8365 EXPECT_EQ("hello!", response_data);
8366
8367 helper.VerifyDataConsumed();
8368}
8369
8370// Run multiple concurrent streams, the first require a confirmation and the
8371// second not requiring confirmation.
8372TEST_F(SpdyNetworkTransactionTest, ZeroRTTConfirmNoConfirmStreams) {
8373 // This test orders the writes such that the GET (no confirmation) is written
8374 // before the POST (confirmation required).
8375 spdy::SpdyHeaderBlock req_block1(
8376 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
8377 spdy::SpdySerializedFrame req1(
8378 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block1), LOWEST, true));
8379 spdy::SpdyHeaderBlock req_block2(
8380 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
8381 spdy::SpdySerializedFrame req2(
8382 spdy_util_.ConstructSpdyHeaders(3, std::move(req_block2), LOWEST, true));
8383 MockWrite writes[] = {
8384 CreateMockWrite(req1, 0),
8385 CreateMockWrite(req2, 3),
8386 };
8387 spdy::SpdySerializedFrame resp1(
8388 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8389 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
8390 spdy::SpdySerializedFrame resp2(
8391 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
8392 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
8393 MockRead reads[] = {
8394 CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
8395 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
8396 MockRead(ASYNC, 0, 6) // EOF
8397 };
8398
8399 SequencedSocketData data1(reads, writes);
8400 SequencedSocketData data2({}, {});
8401 UsePostRequest();
8402 auto session_deps = std::make_unique<SpdySessionDependencies>();
8403 session_deps->enable_early_data = true;
8404 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8405 std::move(session_deps));
8406 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8407 ssl_provider1->confirm = MockConfirm(ASYNC, OK);
8408 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8409 ssl_provider2->confirm = MockConfirm(ASYNC, OK);
8410
8411 helper.RunPreTestSetup();
8412 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
8413 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
8414
8415 // TODO(https://crbug.com/949724): Explicitly verify the ordering of
8416 // ConfirmHandshake and the second stream.
8417
8418 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
8419 HttpRequestInfo request1;
8420 request1.method = "POST";
8421 request1.url = GURL(kDefaultUrl);
8422 request1.traffic_annotation =
8423 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8424 TestCompletionCallback callback1;
8425 int rv = trans1.Start(&request1, callback1.callback(), log_);
8426 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8427
8428 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
8429 HttpRequestInfo request2;
8430 request2.method = "GET";
8431 request2.url = GURL(kDefaultUrl);
8432 request2.traffic_annotation =
8433 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8434 TestCompletionCallback callback2;
8435 rv = trans2.Start(&request2, callback2.callback(), log_);
8436 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8437
8438 EXPECT_THAT(callback1.GetResult(ERR_IO_PENDING), IsOk());
8439 EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk());
8440
8441 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
8442 ASSERT_TRUE(response1);
8443 ASSERT_TRUE(response1->headers);
8444 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
8445 response1->connection_info);
8446 EXPECT_EQ("HTTP/1.1 200", response1->headers->GetStatusLine());
8447 std::string response_data;
8448 ReadTransaction(&trans1, &response_data);
8449 EXPECT_EQ("hello!", response_data);
8450
8451 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
8452 ASSERT_TRUE(response2);
8453 ASSERT_TRUE(response2->headers);
8454 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
8455 response2->connection_info);
8456 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
8457 ReadTransaction(&trans2, &response_data);
8458 EXPECT_EQ("hello!", response_data);
8459
8460 helper.VerifyDataConsumed();
8461}
8462
8463// Run multiple concurrent streams, the first not requiring confirmation and the
8464// second requiring confirmation.
8465TEST_F(SpdyNetworkTransactionTest, ZeroRTTNoConfirmConfirmStreams) {
8466 // This test orders the writes such that the GET (no confirmation) is written
8467 // before the POST (confirmation required).
8468 spdy::SpdyHeaderBlock req_block1(
8469 spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
8470 spdy::SpdySerializedFrame req1(
8471 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block1), LOWEST, true));
8472 spdy::SpdyHeaderBlock req_block2(
8473 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
8474 spdy::SpdySerializedFrame req2(
8475 spdy_util_.ConstructSpdyHeaders(3, std::move(req_block2), LOWEST, true));
8476 MockWrite writes[] = {
8477 CreateMockWrite(req1, 0),
8478 CreateMockWrite(req2, 3),
8479 };
8480 spdy::SpdySerializedFrame resp1(
8481 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8482 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
8483 spdy::SpdySerializedFrame resp2(
8484 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
8485 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
8486 MockRead reads[] = {
8487 CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
8488 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
8489 MockRead(ASYNC, 0, 6) // EOF
8490 };
8491
8492 SequencedSocketData data1(reads, writes);
8493 SequencedSocketData data2({}, {});
8494 UsePostRequest();
8495 auto session_deps = std::make_unique<SpdySessionDependencies>();
8496 session_deps->enable_early_data = true;
8497 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8498 std::move(session_deps));
8499 auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8500 ssl_provider1->confirm = MockConfirm(ASYNC, OK);
8501 auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8502 ssl_provider2->confirm = MockConfirm(ASYNC, OK);
8503
8504 helper.RunPreTestSetup();
8505 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
8506 helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2));
8507
8508 // TODO(https://crbug.com/949724): Explicitly verify the ordering of
8509 // ConfirmHandshake and the second stream.
8510
8511 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
8512 HttpRequestInfo request1;
8513 request1.method = "GET";
8514 request1.url = GURL(kDefaultUrl);
8515 request1.traffic_annotation =
8516 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8517 TestCompletionCallback callback1;
8518 int rv = trans1.Start(&request1, callback1.callback(), log_);
8519 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8520
8521 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
8522 HttpRequestInfo request2;
8523 request2.method = "POST";
8524 request2.url = GURL(kDefaultUrl);
8525 request2.traffic_annotation =
8526 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8527 TestCompletionCallback callback2;
8528 rv = trans2.Start(&request2, callback2.callback(), log_);
8529 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8530
8531 EXPECT_THAT(callback1.GetResult(ERR_IO_PENDING), IsOk());
8532 EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk());
8533
8534 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
8535 ASSERT_TRUE(response1);
8536 ASSERT_TRUE(response1->headers);
8537 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
8538 response1->connection_info);
8539 EXPECT_EQ("HTTP/1.1 200", response1->headers->GetStatusLine());
8540 std::string response_data;
8541 ReadTransaction(&trans1, &response_data);
8542 EXPECT_EQ("hello!", response_data);
8543
8544 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
8545 ASSERT_TRUE(response2);
8546 ASSERT_TRUE(response2->headers);
8547 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
8548 response2->connection_info);
8549 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
8550 ReadTransaction(&trans2, &response_data);
8551 EXPECT_EQ("hello!", response_data);
8552
8553 helper.VerifyDataConsumed();
8554}
8555
8556TEST_F(SpdyNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
8557 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8558 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8559 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8560 MockWrite writes[] = {
8561 CreateMockWrite(req, 0, SYNCHRONOUS),
8562 CreateMockWrite(body, 1), // POST upload frame
8563 };
8564
8565 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8566 MockRead reads[] = {
8567 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8568 MockRead(ASYNC, 0, 4) // EOF
8569 };
8570
8571 SequencedSocketData data(reads, writes);
8572 UsePostRequest();
8573 auto session_deps = std::make_unique<SpdySessionDependencies>();
8574 session_deps->enable_early_data = true;
8575 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8576 std::move(session_deps));
8577 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8578 ssl_provider->confirm = MockConfirm(SYNCHRONOUS, OK);
8579 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
8580 TransactionHelperResult out = helper.output();
8581 EXPECT_THAT(out.rv, IsOk());
8582 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8583 EXPECT_EQ("hello!", out.response_data);
8584}
8585
8586TEST_F(SpdyNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
8587 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8588 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8589 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8590 MockWrite writes[] = {
8591 CreateMockWrite(req, 0, ASYNC),
8592 CreateMockWrite(body, 1), // POST upload frame
8593 };
8594
8595 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8596 MockRead reads[] = {
8597 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8598 MockRead(ASYNC, 0, 4) // EOF
8599 };
8600
8601 SequencedSocketData data(reads, writes);
8602 UsePostRequest();
8603 auto session_deps = std::make_unique<SpdySessionDependencies>();
8604 session_deps->enable_early_data = true;
8605 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8606 std::move(session_deps));
8607 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8608 ssl_provider->confirm = MockConfirm(SYNCHRONOUS, OK);
8609 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
8610 TransactionHelperResult out = helper.output();
8611 EXPECT_THAT(out.rv, IsOk());
8612 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8613 EXPECT_EQ("hello!", out.response_data);
8614}
8615
8616TEST_F(SpdyNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
8617 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8618 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8619 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8620 MockWrite writes[] = {
8621 CreateMockWrite(req, 0, SYNCHRONOUS),
8622 CreateMockWrite(body, 1), // POST upload frame
8623 };
8624
8625 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8626 MockRead reads[] = {
8627 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8628 MockRead(ASYNC, 0, 4) // EOF
8629 };
8630
8631 SequencedSocketData data(reads, writes);
8632 UsePostRequest();
8633 auto session_deps = std::make_unique<SpdySessionDependencies>();
8634 session_deps->enable_early_data = true;
8635 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8636 std::move(session_deps));
8637 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8638 ssl_provider->confirm = MockConfirm(ASYNC, OK);
8639 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
8640 TransactionHelperResult out = helper.output();
8641 EXPECT_THAT(out.rv, IsOk());
8642 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8643 EXPECT_EQ("hello!", out.response_data);
8644}
8645
8646TEST_F(SpdyNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
8647 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8648 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8649 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8650 MockWrite writes[] = {
8651 CreateMockWrite(req, 0, ASYNC),
8652 CreateMockWrite(body, 1), // POST upload frame
8653 };
8654
8655 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8656 MockRead reads[] = {
8657 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8658 MockRead(ASYNC, 0, 4) // EOF
8659 };
8660
8661 SequencedSocketData data(reads, writes);
8662 UsePostRequest();
8663 auto session_deps = std::make_unique<SpdySessionDependencies>();
8664 session_deps->enable_early_data = true;
8665 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8666 std::move(session_deps));
8667 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8668 ssl_provider->confirm = MockConfirm(ASYNC, OK);
8669 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
8670 TransactionHelperResult out = helper.output();
8671 EXPECT_THAT(out.rv, IsOk());
8672 EXPECT_EQ("HTTP/1.1 200", out.status_line);
8673 EXPECT_EQ("hello!", out.response_data);
8674}
8675
8676TEST_F(SpdyNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
8677 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8678 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8679 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8680 MockWrite writes[] = {
8681 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
8682 };
8683
8684 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8685 MockRead reads[] = {
8686 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8687 MockRead(ASYNC, 0, 4) // EOF
8688 };
8689
8690 SequencedSocketData data(reads, writes);
8691 UsePostRequest();
8692 auto session_deps = std::make_unique<SpdySessionDependencies>();
8693 session_deps->enable_early_data = true;
8694 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8695 std::move(session_deps));
8696 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8697 ssl_provider->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
8698 helper.RunPreTestSetup();
8699 helper.AddDataWithSSLSocketDataProvider(&data, std::move(ssl_provider));
8700 helper.RunDefaultTest();
8701 TransactionHelperResult out = helper.output();
8702 EXPECT_THAT(out.rv, IsError(ERR_SSL_PROTOCOL_ERROR));
8703}
8704
8705TEST_F(SpdyNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
8706 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
8707 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
8708 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
8709 MockWrite writes[] = {
8710 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
8711 };
8712
8713 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
8714 MockRead reads[] = {
8715 CreateMockRead(resp, 2), CreateMockRead(body, 3),
8716 MockRead(ASYNC, 0, 4) // EOF
8717 };
8718
8719 SequencedSocketData data(reads, writes);
8720 UsePostRequest();
8721 auto session_deps = std::make_unique<SpdySessionDependencies>();
8722 session_deps->enable_early_data = true;
8723 NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
8724 std::move(session_deps));
8725 auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
8726 ssl_provider->confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
8727 helper.RunPreTestSetup();
8728 helper.AddDataWithSSLSocketDataProvider(&data, std::move(ssl_provider));
8729 helper.RunDefaultTest();
8730 TransactionHelperResult out = helper.output();
8731 EXPECT_THAT(out.rv, IsError(ERR_SSL_PROTOCOL_ERROR));
8732}
8733
[email protected]aea80602009-09-18 00:55:088734} // namespace net