blob: 9acaf3d9490668d207cd98fa72db604169ff316d [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>
danakjaee3e1ec2016-04-16 00:23:186#include <memory>
[email protected]d8ef27b2010-08-06 17:34:397#include <string>
dchengc7eeda422015-12-26 03:56:488#include <utility>
[email protected]a33cad2b62010-07-30 22:24:399#include <vector>
10
[email protected]49639fa2011-12-20 23:22:4111#include "base/bind.h"
12#include "base/bind_helpers.h"
thestigd8df0332014-09-04 06:33:2913#include "base/files/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2314#include "base/files/scoped_temp_dir.h"
danakjaee3e1ec2016-04-16 00:23:1815#include "base/memory/ptr_util.h"
[email protected]fc9d88472013-08-14 02:31:1716#include "base/run_loop.h"
[email protected]251029e2014-03-19 06:04:4017#include "base/strings/string_piece.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"
22#include "net/base/elements_upload_data_stream.h"
tbansal28e68f82016-02-04 02:56:1523#include "net/base/proxy_delegate.h"
[email protected]262eec82013-03-19 21:01:3624#include "net/base/request_priority.h"
tbansal28e68f82016-02-04 02:56:1525#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0626#include "net/base/upload_bytes_element_reader.h"
[email protected]b2d26cfd2012-12-11 10:36:0627#include "net/base/upload_file_element_reader.h"
aberentbba302d2015-12-03 10:20:1928#include "net/http/http_auth_scheme.h"
bnc3171a2432016-12-28 18:40:2629#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5630#include "net/http/http_network_session_peer.h"
[email protected]513963e2013-06-15 01:53:0431#include "net/http/http_network_transaction.h"
32#include "net/http/http_server_properties.h"
[email protected]c41737d2014-05-14 07:47:1933#include "net/http/http_transaction_test_util.h"
mikecirone8b85c432016-09-08 19:11:0034#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1935#include "net/log/net_log_with_source.h"
mmenke16a7cbdd2015-04-24 23:00:5636#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4637#include "net/log/test_net_log_entry.h"
38#include "net/log/test_net_log_util.h"
tbansal28e68f82016-02-04 02:56:1539#include "net/proxy/proxy_server.h"
[email protected]2d6728692011-03-12 01:39:5540#include "net/socket/client_socket_pool_base.h"
[email protected]bb88e1d32013-05-03 23:11:0741#include "net/socket/next_proto.h"
[email protected]f54c85792012-03-08 19:06:4142#include "net/spdy/buffered_spdy_framer.h"
[email protected]9be804c82010-06-24 17:59:4643#include "net/spdy/spdy_http_stream.h"
[email protected]9e1bdd32011-02-03 21:48:3444#include "net/spdy/spdy_http_utils.h"
[email protected]bdebd1b2010-08-09 20:18:0845#include "net/spdy/spdy_session.h"
[email protected]19ec8a72010-08-23 03:38:2346#include "net/spdy/spdy_session_pool.h"
[email protected]86aa87b2013-02-15 01:10:0347#include "net/spdy/spdy_test_util_common.h"
[email protected]a4bfdf72013-02-22 04:06:1648#include "net/spdy/spdy_test_utils.h"
[email protected]514aeaf2014-05-23 10:31:5149#include "net/ssl/ssl_connection_status_flags.h"
bncce36dca22015-04-21 22:11:2350#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0151#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4352#include "net/test/test_data_directory.h"
[email protected]d2db0292011-01-26 20:23:4453#include "net/url_request/url_request_test_util.h"
[email protected]251029e2014-03-19 06:04:4054#include "testing/gmock/include/gmock/gmock.h"
[email protected]aea80602009-09-18 00:55:0855#include "testing/platform_test.h"
56
robpercival214763f2016-07-01 23:27:0157using net::test::IsError;
58using net::test::IsOk;
59
[email protected]aea80602009-09-18 00:55:0860//-----------------------------------------------------------------------------
61
[email protected]d1eda932009-11-04 01:03:1062namespace net {
[email protected]dae22c52010-07-30 02:16:3563
[email protected]cbdd73162013-03-18 23:27:3364namespace {
[email protected]251029e2014-03-19 06:04:4065
66using testing::Each;
67using testing::Eq;
68
xunjieli179a6e72016-04-26 19:47:4569const int32_t kBufferSize = SpdyHttpStream::kRequestBodyBufferSize;
70
[email protected]513963e2013-06-15 01:53:0471} // namespace
72
bncd16676a2016-07-20 16:23:0173class SpdyNetworkTransactionTest : public ::testing::Test {
[email protected]34437af82009-11-06 02:28:4974 protected:
rdsmithebb50aa2015-11-12 03:44:3875 SpdyNetworkTransactionTest()
bncb26024382016-06-29 02:39:4576 : default_url_(kDefaultUrl),
bncd16676a2016-07-20 16:23:0177 host_port_pair_(HostPortPair::FromURL(default_url_)) {}
[email protected]2d6728692011-03-12 01:39:5578
bncd16676a2016-07-20 16:23:0179 ~SpdyNetworkTransactionTest() override {
mmenkecbc2b712014-10-09 20:29:0780 // UploadDataStream may post a deletion tasks back to the message loop on
[email protected]fc9d88472013-08-14 02:31:1781 // destruction.
82 upload_data_stream_.reset();
83 base::RunLoop().RunUntilIdle();
84 }
85
dcheng67be2b1f2014-10-27 21:47:2986 void SetUp() override {
bncce36dca22015-04-21 22:11:2387 get_request_initialized_ = false;
88 post_request_initialized_ = false;
89 chunked_post_request_initialized_ = false;
[email protected]69e6b4a2012-10-18 08:03:0190 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]aea80602009-09-18 00:55:0891 }
92
[email protected]72552f02009-10-28 15:25:0193 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:0894 int rv;
95 std::string status_line;
96 std::string response_data;
[email protected]8b070372009-11-16 22:01:2597 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:0898 };
99
[email protected]3caf5542010-07-16 15:19:47100 // A helper class that handles all the initial npn/ssl setup.
101 class NormalSpdyTransactionHelper {
102 public:
rdsmith82957ad2015-09-16 19:42:03103 NormalSpdyTransactionHelper(
104 const HttpRequestInfo& request,
105 RequestPriority priority,
tfarina428341112016-09-22 13:38:20106 const NetLogWithSource& log,
danakjaee3e1ec2016-04-16 00:23:18107 std::unique_ptr<SpdySessionDependencies> session_deps)
[email protected]30c942b2010-07-21 16:59:59108 : request_(request),
[email protected]262eec82013-03-19 21:01:36109 priority_(priority),
tombergan5d22c182017-01-11 02:05:35110 session_deps_(session_deps.get() == nullptr
bncd16676a2016-07-20 16:23:01111 ? base::MakeUnique<SpdySessionDependencies>()
112 : std::move(session_deps)),
xunjieli925519532017-01-30 15:33:17113 log_(log) {
114 session_deps_->net_log = log.net_log();
115 session_ =
116 SpdySessionDependencies::SpdyCreateSession(session_deps_.get());
117 }
[email protected]61b4efc2012-04-27 18:12:50118
[email protected]19ec8a72010-08-23 03:38:23119 ~NormalSpdyTransactionHelper() {
120 // Any test which doesn't close the socket by sending it an EOF will
121 // have a valid session left open, which leaks the entire session pool.
122 // This is just fine - in fact, some of our tests intentionally do this
123 // so that we can check consistency of the SpdySessionPool as the test
124 // finishes. If we had put an EOF on the socket, the SpdySession would
125 // have closed and we wouldn't be able to check the consistency.
126
127 // Forcefully close existing sessions here.
128 session()->spdy_session_pool()->CloseAllSessions();
129 }
130
[email protected]3caf5542010-07-16 15:19:47131 void RunPreTestSetup() {
[email protected]3caf5542010-07-16 15:19:47132 // We're now ready to use SSL-npn SPDY.
[email protected]90499482013-06-01 00:39:50133 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
[email protected]cb54b3b22010-06-03 16:28:55134 }
[email protected]aea80602009-09-18 00:55:08135
[email protected]3caf5542010-07-16 15:19:47136 // Start the transaction, read some data, finish.
137 void RunDefaultTest() {
[email protected]34b345f92013-02-22 03:27:26138 if (!StartDefaultTest())
139 return;
140 FinishDefaultTest();
141 }
142
143 bool StartDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51144 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
[email protected]aea80602009-09-18 00:55:08145
[email protected]3caf5542010-07-16 15:19:47146 // We expect an IO Pending or some sort of error.
147 EXPECT_LT(output_.rv, 0);
[email protected]34b345f92013-02-22 03:27:26148 return output_.rv == ERR_IO_PENDING;
149 }
[email protected]aea80602009-09-18 00:55:08150
[email protected]34b345f92013-02-22 03:27:26151 void FinishDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51152 output_.rv = callback_.WaitForResult();
bnceb9aa7112017-01-05 01:03:46153 // Finish async network reads/writes.
154 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:47155 if (output_.rv != OK) {
bnc301745a2015-03-10 03:22:16156 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
[email protected]3caf5542010-07-16 15:19:47157 return;
158 }
[email protected]ff57bb82009-11-12 06:52:14159
[email protected]3caf5542010-07-16 15:19:47160 // Verify responses.
161 const HttpResponseInfo* response = trans_->GetResponseInfo();
wezca1070932016-05-26 20:30:52162 ASSERT_TRUE(response);
163 ASSERT_TRUE(response->headers);
bnc80bb1d42016-10-26 18:11:34164 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2,
bnc927c4962016-07-21 14:45:59165 response->connection_info);
166 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
167 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:52168 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]80a09a82012-11-16 17:40:06169 EXPECT_EQ("127.0.0.1", response->socket_address.host());
bncb26024382016-06-29 02:39:45170 EXPECT_EQ(443, response->socket_address.port());
[email protected]3caf5542010-07-16 15:19:47171 output_.status_line = response->headers->GetStatusLine();
172 output_.response_info = *response; // Make a copy so we can verify.
173 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
[email protected]3caf5542010-07-16 15:19:47174 }
175
bncfacdd852015-01-09 19:22:54176 void FinishDefaultTestWithoutVerification() {
177 output_.rv = callback_.WaitForResult();
bnceb9aa7112017-01-05 01:03:46178 // Finish async network reads/writes.
179 base::RunLoop().RunUntilIdle();
bncfacdd852015-01-09 19:22:54180 if (output_.rv != OK)
bnc301745a2015-03-10 03:22:16181 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
bncfacdd852015-01-09 19:22:54182 }
183
maksim.sisov8d2df66d2016-06-20 07:07:11184 void WaitForCallbackToComplete() { output_.rv = callback_.WaitForResult(); }
mmenke666a6fea2015-12-19 04:16:33185
[email protected]3caf5542010-07-16 15:19:47186 // Most tests will want to call this function. In particular, the MockReads
187 // should end with an empty read, and that read needs to be processed to
188 // ensure proper deletion of the spdy_session_pool.
189 void VerifyDataConsumed() {
rch08e3aa3e2015-05-16 14:27:52190 for (const SocketDataProvider* provider : data_vector_) {
191 EXPECT_TRUE(provider->AllReadDataConsumed());
192 EXPECT_TRUE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47193 }
194 }
195
196 // Occasionally a test will expect to error out before certain reads are
197 // processed. In that case we want to explicitly ensure that the reads were
198 // not processed.
199 void VerifyDataNotConsumed() {
rch08e3aa3e2015-05-16 14:27:52200 for (const SocketDataProvider* provider : data_vector_) {
201 EXPECT_FALSE(provider->AllReadDataConsumed());
202 EXPECT_FALSE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47203 }
204 }
205
rch08e3aa3e2015-05-16 14:27:52206 void RunToCompletion(SocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47207 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58208 AddData(data);
[email protected]3caf5542010-07-16 15:19:47209 RunDefaultTest();
210 VerifyDataConsumed();
211 }
[email protected]e6b06862010-07-20 16:32:58212
[email protected]514aeaf2014-05-23 10:31:51213 void RunToCompletionWithSSLData(
rch08e3aa3e2015-05-16 14:27:52214 SocketDataProvider* data,
danakjaee3e1ec2016-04-16 00:23:18215 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]514aeaf2014-05-23 10:31:51216 RunPreTestSetup();
dchengc7eeda422015-12-26 03:56:48217 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:51218 RunDefaultTest();
219 VerifyDataConsumed();
220 }
221
rch08e3aa3e2015-05-16 14:27:52222 void AddData(SocketDataProvider* data) {
danakjaee3e1ec2016-04-16 00:23:18223 std::unique_ptr<SSLSocketDataProvider> ssl_provider(
[email protected]514aeaf2014-05-23 10:31:51224 new SSLSocketDataProvider(ASYNC, OK));
bncce36dca22015-04-21 22:11:23225 ssl_provider->cert =
226 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
dchengc7eeda422015-12-26 03:56:48227 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:51228 }
229
230 void AddDataWithSSLSocketDataProvider(
rch08e3aa3e2015-05-16 14:27:52231 SocketDataProvider* data,
danakjaee3e1ec2016-04-16 00:23:18232 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]3caf5542010-07-16 15:19:47233 data_vector_.push_back(data);
bnc3cf2a592016-08-11 14:48:36234 if (ssl_provider->next_proto == kProtoUnknown)
235 ssl_provider->next_proto = kProtoHTTP2;
rchebf12982015-04-10 01:15:00236
237 session_deps_->socket_factory->AddSSLSocketDataProvider(
238 ssl_provider.get());
olli.raulaae011c422015-12-10 07:38:51239 ssl_vector_.push_back(std::move(ssl_provider));
[email protected]d4f00222012-07-10 06:24:51240
[email protected]3b7828432010-08-18 18:33:27241 session_deps_->socket_factory->AddSocketDataProvider(data);
[email protected]3b7828432010-08-18 18:33:27242 }
243
[email protected]3caf5542010-07-16 15:19:47244 HttpNetworkTransaction* trans() { return trans_.get(); }
245 void ResetTrans() { trans_.reset(); }
bnc4d782f492016-08-18 13:50:00246 const TransactionHelperResult& output() { return output_; }
[email protected]19ec8a72010-08-23 03:38:23247 const HttpRequestInfo& request() const { return request_; }
mmenkee65e7af2015-10-13 17:16:42248 HttpNetworkSession* session() const { return session_.get(); }
bncd16676a2016-07-20 16:23:01249 SpdySessionDependencies* session_deps() { return session_deps_.get(); }
[email protected]3caf5542010-07-16 15:19:47250
251 private:
rch08e3aa3e2015-05-16 14:27:52252 typedef std::vector<SocketDataProvider*> DataVector;
danakjaee3e1ec2016-04-16 00:23:18253 typedef std::vector<std::unique_ptr<SSLSocketDataProvider>> SSLVector;
254 typedef std::vector<std::unique_ptr<SocketDataProvider>> AlternateVector;
[email protected]3caf5542010-07-16 15:19:47255 HttpRequestInfo request_;
[email protected]262eec82013-03-19 21:01:36256 RequestPriority priority_;
danakjaee3e1ec2016-04-16 00:23:18257 std::unique_ptr<SpdySessionDependencies> session_deps_;
258 std::unique_ptr<HttpNetworkSession> session_;
[email protected]3caf5542010-07-16 15:19:47259 TransactionHelperResult output_;
[email protected]3caf5542010-07-16 15:19:47260 SSLVector ssl_vector_;
[email protected]514aeaf2014-05-23 10:31:51261 TestCompletionCallback callback_;
danakjaee3e1ec2016-04-16 00:23:18262 std::unique_ptr<HttpNetworkTransaction> trans_;
[email protected]3caf5542010-07-16 15:19:47263 DataVector data_vector_;
tfarina428341112016-09-22 13:38:20264 const NetLogWithSource log_;
[email protected]3caf5542010-07-16 15:19:47265 };
[email protected]aea80602009-09-18 00:55:08266
267 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
268 int expected_status);
269
270 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18271
[email protected]e3ebba0f2010-08-05 17:59:58272 const HttpRequestInfo& CreateGetPushRequest() {
bncce36dca22015-04-21 22:11:23273 get_push_request_.method = "GET";
274 get_push_request_.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
275 get_push_request_.load_flags = 0;
276 return get_push_request_;
[email protected]e3ebba0f2010-08-05 17:59:58277 }
278
[email protected]d3cee19d2010-06-22 18:42:18279 const HttpRequestInfo& CreateGetRequest() {
bncce36dca22015-04-21 22:11:23280 if (!get_request_initialized_) {
281 get_request_.method = "GET";
bncb26024382016-06-29 02:39:45282 get_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23283 get_request_.load_flags = 0;
284 get_request_initialized_ = true;
[email protected]d3cee19d2010-06-22 18:42:18285 }
bncce36dca22015-04-21 22:11:23286 return get_request_;
[email protected]d3cee19d2010-06-22 18:42:18287 }
288
[email protected]3deb9a52010-11-11 00:24:40289 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
bncce36dca22015-04-21 22:11:23290 if (!get_request_initialized_) {
291 get_request_.method = "GET";
bncb26024382016-06-29 02:39:45292 get_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23293 get_request_.load_flags = 0;
294 get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
295 get_request_initialized_ = true;
[email protected]3deb9a52010-11-11 00:24:40296 }
bncce36dca22015-04-21 22:11:23297 return get_request_;
[email protected]3deb9a52010-11-11 00:24:40298 }
299
[email protected]310240592010-08-05 21:04:19300 const HttpRequestInfo& CreatePostRequest() {
bncce36dca22015-04-21 22:11:23301 if (!post_request_initialized_) {
danakjaee3e1ec2016-04-16 00:23:18302 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
ricea2deef682016-09-09 08:04:07303 element_readers.push_back(base::MakeUnique<UploadBytesElementReader>(
304 kUploadData, kUploadDataSize));
[email protected]96c77a72013-09-24 09:49:20305 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22306 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27307
bncce36dca22015-04-21 22:11:23308 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45309 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23310 post_request_.upload_data_stream = upload_data_stream_.get();
311 post_request_initialized_ = true;
[email protected]310240592010-08-05 21:04:19312 }
bncce36dca22015-04-21 22:11:23313 return post_request_;
[email protected]310240592010-08-05 21:04:19314 }
315
[email protected]69e6b4a2012-10-18 08:03:01316 const HttpRequestInfo& CreateFilePostRequest() {
bncce36dca22015-04-21 22:11:23317 if (!post_request_initialized_) {
[email protected]6cdfd7f2013-02-08 20:40:15318 base::FilePath file_path;
vabrb8582322016-09-09 08:05:37319 CHECK(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01320 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30321 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01322
danakjaee3e1ec2016-04-16 00:23:18323 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
ricea2deef682016-09-09 08:04:07324 element_readers.push_back(base::MakeUnique<UploadFileElementReader>(
skyostil4891b25b2015-06-11 11:43:45325 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
ricea2deef682016-09-09 08:04:07326 kUploadDataSize, base::Time()));
[email protected]96c77a72013-09-24 09:49:20327 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22328 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27329
bncce36dca22015-04-21 22:11:23330 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45331 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23332 post_request_.upload_data_stream = upload_data_stream_.get();
333 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01334 }
bncce36dca22015-04-21 22:11:23335 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01336 }
337
[email protected]999dd8c2013-11-12 06:45:54338 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
bncce36dca22015-04-21 22:11:23339 if (post_request_initialized_)
340 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54341
342 base::FilePath file_path;
vabrb8582322016-09-09 08:05:37343 CHECK(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
[email protected]999dd8c2013-11-12 06:45:54344 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30345 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]92be8eb2014-08-07 22:57:11346 CHECK(base::MakeFileUnreadable(file_path));
[email protected]999dd8c2013-11-12 06:45:54347
danakjaee3e1ec2016-04-16 00:23:18348 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
ricea2deef682016-09-09 08:04:07349 element_readers.push_back(base::MakeUnique<UploadFileElementReader>(
skyostil4891b25b2015-06-11 11:43:45350 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
ricea2deef682016-09-09 08:04:07351 kUploadDataSize, base::Time()));
[email protected]999dd8c2013-11-12 06:45:54352 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22353 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]999dd8c2013-11-12 06:45:54354
bncce36dca22015-04-21 22:11:23355 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45356 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23357 post_request_.upload_data_stream = upload_data_stream_.get();
358 post_request_initialized_ = true;
359 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54360 }
361
[email protected]69e6b4a2012-10-18 08:03:01362 const HttpRequestInfo& CreateComplexPostRequest() {
bncce36dca22015-04-21 22:11:23363 if (!post_request_initialized_) {
[email protected]69e6b4a2012-10-18 08:03:01364 const int kFileRangeOffset = 1;
365 const int kFileRangeLength = 3;
366 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
367
[email protected]6cdfd7f2013-02-08 20:40:15368 base::FilePath file_path;
vabrb8582322016-09-09 08:05:37369 CHECK(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01370 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30371 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01372
danakjaee3e1ec2016-04-16 00:23:18373 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
ricea2deef682016-09-09 08:04:07374 element_readers.push_back(base::MakeUnique<UploadBytesElementReader>(
375 kUploadData, kFileRangeOffset));
376 element_readers.push_back(base::MakeUnique<UploadFileElementReader>(
skyostil4891b25b2015-06-11 11:43:45377 base::ThreadTaskRunnerHandle::Get().get(), file_path,
ricea2deef682016-09-09 08:04:07378 kFileRangeOffset, kFileRangeLength, base::Time()));
379 element_readers.push_back(base::MakeUnique<UploadBytesElementReader>(
[email protected]69e6b4a2012-10-18 08:03:01380 kUploadData + kFileRangeOffset + kFileRangeLength,
ricea2deef682016-09-09 08:04:07381 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
[email protected]96c77a72013-09-24 09:49:20382 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22383 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27384
bncce36dca22015-04-21 22:11:23385 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45386 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23387 post_request_.upload_data_stream = upload_data_stream_.get();
388 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01389 }
bncce36dca22015-04-21 22:11:23390 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01391 }
392
[email protected]0c9bf872011-03-04 17:53:22393 const HttpRequestInfo& CreateChunkedPostRequest() {
bncce36dca22015-04-21 22:11:23394 if (!chunked_post_request_initialized_) {
mmenkecbc2b712014-10-09 20:29:07395 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
bncce36dca22015-04-21 22:11:23396 chunked_post_request_.method = "POST";
bncb26024382016-06-29 02:39:45397 chunked_post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23398 chunked_post_request_.upload_data_stream =
mmenkecbc2b712014-10-09 20:29:07399 upload_chunked_data_stream_.get();
bncce36dca22015-04-21 22:11:23400 chunked_post_request_initialized_ = true;
[email protected]0c9bf872011-03-04 17:53:22401 }
bncce36dca22015-04-21 22:11:23402 return chunked_post_request_;
[email protected]0c9bf872011-03-04 17:53:22403 }
404
[email protected]19ec8a72010-08-23 03:38:23405 // Read the result of a particular transaction, knowing that we've got
406 // multiple transactions in the read pipeline; so as we read, we may have
407 // to skip over data destined for other transactions while we consume
408 // the data for |trans|.
409 int ReadResult(HttpNetworkTransaction* trans,
[email protected]19ec8a72010-08-23 03:38:23410 std::string* result) {
411 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58412
[email protected]19ec8a72010-08-23 03:38:23413 int bytes_read = 0;
bnc301745a2015-03-10 03:22:16414 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(kSize));
[email protected]49639fa2011-12-20 23:22:41415 TestCompletionCallback callback;
[email protected]19ec8a72010-08-23 03:38:23416 while (true) {
[email protected]90499482013-06-01 00:39:50417 int rv = trans->Read(buf.get(), kSize, callback.callback());
[email protected]19ec8a72010-08-23 03:38:23418 if (rv == ERR_IO_PENDING) {
[email protected]19ec8a72010-08-23 03:38:23419 rv = callback.WaitForResult();
420 } else if (rv <= 0) {
421 break;
422 }
423 result->append(buf->data(), rv);
424 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58425 }
[email protected]19ec8a72010-08-23 03:38:23426 return bytes_read;
427 }
[email protected]e3ebba0f2010-08-05 17:59:58428
[email protected]19ec8a72010-08-23 03:38:23429 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
430 // This lengthy block is reaching into the pool to dig out the active
431 // session. Once we have the session, we verify that the streams are
432 // all closed and not leaked at this point.
433 const GURL& url = helper.request().url;
bncb26024382016-06-29 02:39:45434 SpdySessionKey key(HostPortPair::FromURL(url), ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:53435 PRIVACY_MODE_DISABLED);
tfarina428341112016-09-22 13:38:20436 NetLogWithSource log;
mmenkee65e7af2015-10-13 17:16:42437 HttpNetworkSession* session = helper.session();
[email protected]795cbf82013-07-22 09:37:27438 base::WeakPtr<SpdySession> spdy_session =
bnc3e79387f2016-03-15 14:49:20439 session->spdy_session_pool()->FindAvailableSession(key, url, log);
wezca1070932016-05-26 20:30:52440 ASSERT_TRUE(spdy_session);
[email protected]19ec8a72010-08-23 03:38:23441 EXPECT_EQ(0u, spdy_session->num_active_streams());
442 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
443 }
[email protected]e3ebba0f2010-08-05 17:59:58444
rch08e3aa3e2015-05-16 14:27:52445 void RunServerPushTest(SequencedSocketData* data,
[email protected]e3ebba0f2010-08-05 17:59:58446 HttpResponseInfo* response,
[email protected]a7a265ef2010-12-08 18:05:57447 HttpResponseInfo* push_response,
[email protected]8a0fc822013-06-27 20:52:43448 const std::string& expected) {
[email protected]262eec82013-03-19 21:01:36449 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:35450 NetLogWithSource(), nullptr);
[email protected]e3ebba0f2010-08-05 17:59:58451 helper.RunPreTestSetup();
[email protected]d08358502010-12-03 22:04:03452 helper.AddData(data);
[email protected]e3ebba0f2010-08-05 17:59:58453
454 HttpNetworkTransaction* trans = helper.trans();
455
456 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:41457 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:20458 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
459 NetLogWithSource());
robpercival214763f2016-07-01 23:27:01460 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:58461 rv = callback.WaitForResult();
462
bnceb9aa7112017-01-05 01:03:46463 // Finish async network reads/writes.
464 base::RunLoop().RunUntilIdle();
465
[email protected]e3ebba0f2010-08-05 17:59:58466 // Request the pushed path.
bnc691fda62016-08-12 00:43:16467 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
468 rv = trans2.Start(&CreateGetPushRequest(), callback.callback(),
tfarina428341112016-09-22 13:38:20469 NetLogWithSource());
robpercival214763f2016-07-01 23:27:01470 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:17471 base::RunLoop().RunUntilIdle();
[email protected]e3ebba0f2010-08-05 17:59:58472
[email protected]513963e2013-06-15 01:53:04473 // The data for the pushed path may be coming in more than 1 frame. Compile
[email protected]e3ebba0f2010-08-05 17:59:58474 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23475
476 // Read the server push body.
477 std::string result2;
bnc691fda62016-08-12 00:43:16478 ReadResult(&trans2, &result2);
[email protected]19ec8a72010-08-23 03:38:23479 // Read the response body.
[email protected]e3ebba0f2010-08-05 17:59:58480 std::string result;
rch0aecfd82015-05-19 17:22:32481 ReadResult(trans, &result);
[email protected]e3ebba0f2010-08-05 17:59:58482
483 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:17484 EXPECT_TRUE(data->AllReadDataConsumed());
485 EXPECT_TRUE(data->AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:58486
caseqe8340bc92016-04-20 00:02:57487 LoadTimingInfo load_timing_info;
488 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
489 EXPECT_TRUE(load_timing_info.push_start.is_null());
490 EXPECT_TRUE(load_timing_info.push_end.is_null());
491
492 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:16493 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
caseqe8340bc92016-04-20 00:02:57494 EXPECT_FALSE(load_timing_info2.push_start.is_null());
495 EXPECT_FALSE(load_timing_info2.push_end.is_null());
496
[email protected]e3ebba0f2010-08-05 17:59:58497 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23498 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
499 << result2
500 << "||||| Expected data: "
501 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58502
bnc42331402016-07-25 13:36:15503 // Verify the response HEADERS.
[email protected]e3ebba0f2010-08-05 17:59:58504 // Copy the response info, because trans goes away.
505 *response = *trans->GetResponseInfo();
bnc691fda62016-08-12 00:43:16506 *push_response = *trans2.GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23507
508 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58509 }
510
[email protected]49639fa2011-12-20 23:22:41511 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
512 int result) {
513 helper->ResetTrans();
514 }
515
mmenkee65e7af2015-10-13 17:16:42516 static void StartTransactionCallback(HttpNetworkSession* session,
517 GURL url,
518 int result) {
krasin0bfeb6b2017-01-13 21:48:04519 HttpRequestInfo request;
bnc691fda62016-08-12 00:43:16520 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]49639fa2011-12-20 23:22:41521 TestCompletionCallback callback;
[email protected]49639fa2011-12-20 23:22:41522 request.method = "GET";
rchebf12982015-04-10 01:15:00523 request.url = url;
[email protected]49639fa2011-12-20 23:22:41524 request.load_flags = 0;
tfarina428341112016-09-22 13:38:20525 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:01526 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]49639fa2011-12-20 23:22:41527 callback.WaitForResult();
528 }
529
mmenkecbc2b712014-10-09 20:29:07530 ChunkedUploadDataStream* upload_chunked_data_stream() const {
531 return upload_chunked_data_stream_.get();
532 }
533
rchebf12982015-04-10 01:15:00534 std::string GetDefaultUrlWithPath(const char* path) {
bncb26024382016-06-29 02:39:45535 return std::string(kDefaultUrl) + path;
rchebf12982015-04-10 01:15:00536 }
537
bncb26024382016-06-29 02:39:45538 const GURL default_url_;
539 const HostPortPair host_port_pair_;
[email protected]9ec54f82013-05-10 02:53:05540 SpdyTestUtil spdy_util_;
541
[email protected]d3cee19d2010-06-22 18:42:18542 private:
danakjaee3e1ec2016-04-16 00:23:18543 std::unique_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
544 std::unique_ptr<UploadDataStream> upload_data_stream_;
bncce36dca22015-04-21 22:11:23545 bool get_request_initialized_;
546 bool post_request_initialized_;
547 bool chunked_post_request_initialized_;
548 HttpRequestInfo get_request_;
549 HttpRequestInfo post_request_;
550 HttpRequestInfo chunked_post_request_;
551 HttpRequestInfo get_push_request_;
[email protected]ea1a3f62012-11-16 20:34:23552 base::ScopedTempDir temp_dir_;
[email protected]aea80602009-09-18 00:55:08553};
554
[email protected]3caf5542010-07-16 15:19:47555// Verify HttpNetworkTransaction constructor.
bncd16676a2016-07-20 16:23:01556TEST_F(SpdyNetworkTransactionTest, Constructor) {
557 auto session_deps = base::MakeUnique<SpdySessionDependencies>();
danakjaee3e1ec2016-04-16 00:23:18558 std::unique_ptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:07559 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
bncd16676a2016-07-20 16:23:01560 auto trans =
561 base::MakeUnique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]aea80602009-09-18 00:55:08562}
563
bncd16676a2016-07-20 16:23:01564TEST_F(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38565 // Construct the request.
bncdf80d44fd2016-07-15 20:27:41566 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49567 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:41568 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]72552f02009-10-28 15:25:01569
tombergan5d22c182017-01-11 02:05:35570 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41571 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]72552f02009-10-28 15:25:01572 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41573 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:52574 MockRead(ASYNC, 0, 3) // EOF
[email protected]72552f02009-10-28 15:25:01575 };
576
rch08e3aa3e2015-05-16 14:27:52577 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:36578 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:35579 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:57580 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:47581 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:01582 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02583 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]72552f02009-10-28 15:25:01584 EXPECT_EQ("hello!", out.response_data);
585}
586
bncd16676a2016-07-20 16:23:01587TEST_F(SpdyNetworkTransactionTest, GetAtEachPriority) {
[email protected]3d08dd382013-10-19 00:13:11588 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
[email protected]31ae7ab2012-04-24 21:09:05589 p = RequestPriority(p + 1)) {
bncd16676a2016-07-20 16:23:01590 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:49591
[email protected]c9c6f5c2010-07-31 01:30:03592 // Construct the request.
bncdf80d44fd2016-07-15 20:27:41593 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49594 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, p, true));
bncdf80d44fd2016-07-15 20:27:41595 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]c9c6f5c2010-07-31 01:30:03596
[email protected]86aa87b2013-02-15 01:10:03597 SpdyPriority spdy_prio = 0;
bncdf80d44fd2016-07-15 20:27:41598 EXPECT_TRUE(GetSpdyPriority(req, &spdy_prio));
[email protected]c9c6f5c2010-07-31 01:30:03599 // this repeats the RequestPriority-->SpdyPriority mapping from
600 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
601 // sure it's being done right.
bnc05808ff42016-01-08 23:48:25602 switch (p) {
603 case HIGHEST:
604 EXPECT_EQ(0, spdy_prio);
605 break;
606 case MEDIUM:
607 EXPECT_EQ(1, spdy_prio);
608 break;
609 case LOW:
610 EXPECT_EQ(2, spdy_prio);
611 break;
612 case LOWEST:
613 EXPECT_EQ(3, spdy_prio);
614 break;
615 case IDLE:
616 EXPECT_EQ(4, spdy_prio);
617 break;
rdsmith5eb6fbc2016-10-21 17:36:08618 case THROTTLED:
619 EXPECT_EQ(5, spdy_prio);
620 break;
bnc05808ff42016-01-08 23:48:25621 default:
622 FAIL();
[email protected]c9c6f5c2010-07-31 01:30:03623 }
624
bncdf80d44fd2016-07-15 20:27:41625 SpdySerializedFrame resp(
bnc42331402016-07-25 13:36:15626 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41627 SpdySerializedFrame body(spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]c9c6f5c2010-07-31 01:30:03628 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41629 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:52630 MockRead(ASYNC, 0, 3) // EOF
[email protected]c9c6f5c2010-07-31 01:30:03631 };
632
rch08e3aa3e2015-05-16 14:27:52633 SequencedSocketData data(reads, arraysize(reads), writes,
634 arraysize(writes));
[email protected]c9c6f5c2010-07-31 01:30:03635 HttpRequestInfo http_req = CreateGetRequest();
[email protected]c9c6f5c2010-07-31 01:30:03636
tombergan5d22c182017-01-11 02:05:35637 NormalSpdyTransactionHelper helper(http_req, p, NetLogWithSource(),
638 nullptr);
[email protected]dd54bd82012-07-19 23:44:57639 helper.RunToCompletion(&data);
[email protected]c9c6f5c2010-07-31 01:30:03640 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:01641 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02642 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]c9c6f5c2010-07-31 01:30:03643 EXPECT_EQ("hello!", out.response_data);
644 }
645}
646
[email protected]2bd93022010-07-17 00:58:44647// Start three gets simultaniously; making sure that multiplexed
648// streams work properly.
649
650// This can't use the TransactionHelper method, since it only
651// handles a single transaction, and finishes them as soon
652// as it launches them.
653
654// TODO(gavinp): create a working generalized TransactionHelper that
655// can allow multiple streams in flight.
656
bncd16676a2016-07-20 16:23:01657TEST_F(SpdyNetworkTransactionTest, ThreeGets) {
bncdf80d44fd2016-07-15 20:27:41658 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49659 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:35660 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41661 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
662 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2bd93022010-07-17 00:58:44663
bncdf80d44fd2016-07-15 20:27:41664 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49665 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
tombergan5d22c182017-01-11 02:05:35666 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
bncdf80d44fd2016-07-15 20:27:41667 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
668 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2bd93022010-07-17 00:58:44669
bncdf80d44fd2016-07-15 20:27:41670 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:49671 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
tombergan5d22c182017-01-11 02:05:35672 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
bncdf80d44fd2016-07-15 20:27:41673 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
674 SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44675
[email protected]1b323172011-03-01 17:50:17676 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41677 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
678 CreateMockWrite(req3, 6),
[email protected]2bd93022010-07-17 00:58:44679 };
680 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41681 CreateMockRead(resp, 1), CreateMockRead(body, 2),
682 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
683 CreateMockRead(resp3, 7), CreateMockRead(body3, 8),
[email protected]2bd93022010-07-17 00:58:44684
bncdf80d44fd2016-07-15 20:27:41685 CreateMockRead(fbody, 9), CreateMockRead(fbody2, 10),
686 CreateMockRead(fbody3, 11),
[email protected]2bd93022010-07-17 00:58:44687
rch08e3aa3e2015-05-16 14:27:52688 MockRead(ASYNC, 0, 12), // EOF
[email protected]2bd93022010-07-17 00:58:44689 };
rch08e3aa3e2015-05-16 14:27:52690 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tombergan5d22c182017-01-11 02:05:35691 SequencedSocketData data_placeholder1(nullptr, 0, nullptr, 0);
692 SequencedSocketData data_placeholder2(nullptr, 0, nullptr, 0);
[email protected]2bd93022010-07-17 00:58:44693
tfarina428341112016-09-22 13:38:20694 NetLogWithSource log;
[email protected]2bd93022010-07-17 00:58:44695 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36696 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:35697 NetLogWithSource(), nullptr);
[email protected]bdebd1b2010-08-09 20:18:08698 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57699 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49700 // We require placeholder data because three get requests are sent out at
701 // the same time which results in three sockets being connected. The first
702 // on will negotiate SPDY and will be used for all requests.
mmenkecc2298e2015-12-07 18:20:18703 helper.AddData(&data_placeholder1);
704 helper.AddData(&data_placeholder2);
[email protected]49639fa2011-12-20 23:22:41705 TestCompletionCallback callback1;
706 TestCompletionCallback callback2;
707 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44708
[email protected]bdebd1b2010-08-09 20:18:08709 HttpRequestInfo httpreq1 = CreateGetRequest();
710 HttpRequestInfo httpreq2 = CreateGetRequest();
711 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:44712
krasin0bfeb6b2017-01-13 21:48:04713 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
714 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
715 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
716
bnc691fda62016-08-12 00:43:16717 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:01718 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16719 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:01720 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16721 out.rv = trans3.Start(&httpreq3, callback3.callback(), log);
robpercival214763f2016-07-01 23:27:01722 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]2bd93022010-07-17 00:58:44723
[email protected]bdebd1b2010-08-09 20:18:08724 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01725 ASSERT_THAT(out.rv, IsOk());
[email protected]bdebd1b2010-08-09 20:18:08726 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:01727 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44728
bnc691fda62016-08-12 00:43:16729 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52730 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:08731 EXPECT_TRUE(response1->was_fetched_via_spdy);
732 out.status_line = response1->headers->GetStatusLine();
733 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:44734
bnc691fda62016-08-12 00:43:16735 trans2.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:44736
bnc691fda62016-08-12 00:43:16737 out.rv = ReadTransaction(&trans1, &out.response_data);
[email protected]bdebd1b2010-08-09 20:18:08738 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:01739 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44740
robpercival214763f2016-07-01 23:27:01741 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02742 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:44743 EXPECT_EQ("hello!hello!", out.response_data);
744}
745
bncd16676a2016-07-20 16:23:01746TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
bncdf80d44fd2016-07-15 20:27:41747 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49748 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:35749 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41750 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
751 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1b323172011-03-01 17:50:17752
bncdf80d44fd2016-07-15 20:27:41753 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49754 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
tombergan5d22c182017-01-11 02:05:35755 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
bncdf80d44fd2016-07-15 20:27:41756 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
757 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]1b323172011-03-01 17:50:17758
759 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41760 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
[email protected]1b323172011-03-01 17:50:17761 };
762 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41763 CreateMockRead(resp, 1), CreateMockRead(body, 2),
764 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
765 CreateMockRead(fbody, 6), CreateMockRead(fbody2, 7),
rch08e3aa3e2015-05-16 14:27:52766 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:17767 };
rch08e3aa3e2015-05-16 14:27:52768 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1b323172011-03-01 17:50:17769
[email protected]d973e99a2012-02-17 21:02:36770 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
tombergan5d22c182017-01-11 02:05:35771 SequencedSocketData data_placeholder(nullptr, 0, nullptr, 0);
[email protected]dd54bd82012-07-19 23:44:57772 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17773
tfarina428341112016-09-22 13:38:20774 NetLogWithSource log;
[email protected]1b323172011-03-01 17:50:17775 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36776 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:35777 NetLogWithSource(), nullptr);
[email protected]1b323172011-03-01 17:50:17778 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57779 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49780 // We require placeholder data because two requests are sent out at
781 // the same time which results in two sockets being connected. The first
782 // on will negotiate SPDY and will be used for all requests.
[email protected]dd54bd82012-07-19 23:44:57783 helper.AddData(&data_placeholder);
bnc691fda62016-08-12 00:43:16784 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
785 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]1b323172011-03-01 17:50:17786
[email protected]49639fa2011-12-20 23:22:41787 TestCompletionCallback callback1;
788 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:17789
790 HttpRequestInfo httpreq1 = CreateGetRequest();
791 HttpRequestInfo httpreq2 = CreateGetRequest();
792
bnc691fda62016-08-12 00:43:16793 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:01794 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16795 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:01796 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]1b323172011-03-01 17:50:17797
798 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01799 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17800 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:01801 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17802
bnc691fda62016-08-12 00:43:16803 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52804 EXPECT_TRUE(response1->headers);
[email protected]1b323172011-03-01 17:50:17805 EXPECT_TRUE(response1->was_fetched_via_spdy);
806 out.status_line = response1->headers->GetStatusLine();
807 out.response_info = *response1;
bnc691fda62016-08-12 00:43:16808 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:01809 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02810 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17811 EXPECT_EQ("hello!hello!", out.response_data);
812
bnc691fda62016-08-12 00:43:16813 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:52814 EXPECT_TRUE(response2->headers);
[email protected]1b323172011-03-01 17:50:17815 EXPECT_TRUE(response2->was_fetched_via_spdy);
816 out.status_line = response2->headers->GetStatusLine();
817 out.response_info = *response2;
bnc691fda62016-08-12 00:43:16818 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:01819 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02820 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17821 EXPECT_EQ("hello!hello!", out.response_data);
822
823 helper.VerifyDataConsumed();
824}
825
bncd16676a2016-07-20 16:23:01826TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
bncdf80d44fd2016-07-15 20:27:41827 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49828 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:35829 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41830 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
831 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1b323172011-03-01 17:50:17832
bncdf80d44fd2016-07-15 20:27:41833 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49834 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
tombergan5d22c182017-01-11 02:05:35835 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
bncdf80d44fd2016-07-15 20:27:41836 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
837 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]1b323172011-03-01 17:50:17838
839 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41840 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
[email protected]1b323172011-03-01 17:50:17841 };
842 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41843 CreateMockRead(resp, 1), CreateMockRead(body, 2),
844 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
845 CreateMockRead(fbody, 6), CreateMockRead(fbody2, 7),
rch08e3aa3e2015-05-16 14:27:52846 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:17847 };
rch08e3aa3e2015-05-16 14:27:52848 SequencedSocketData preconnect_data(reads, arraysize(reads), writes,
849 arraysize(writes));
[email protected]1b323172011-03-01 17:50:17850
[email protected]d973e99a2012-02-17 21:02:36851 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
[email protected]1b323172011-03-01 17:50:17852
tombergan5d22c182017-01-11 02:05:35853 SequencedSocketData data_placeholder(nullptr, 0, nullptr, 0);
[email protected]dd54bd82012-07-19 23:44:57854 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17855
tfarina428341112016-09-22 13:38:20856 NetLogWithSource log;
[email protected]1b323172011-03-01 17:50:17857 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36858 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:35859 NetLogWithSource(), nullptr);
[email protected]1b323172011-03-01 17:50:17860 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57861 helper.AddData(&preconnect_data);
[email protected]1b323172011-03-01 17:50:17862 // We require placeholder data because 3 connections are attempted (first is
863 // the preconnect, 2nd and 3rd are the never finished connections.
[email protected]dd54bd82012-07-19 23:44:57864 helper.AddData(&data_placeholder);
865 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:17866
bnc691fda62016-08-12 00:43:16867 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
868 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]1b323172011-03-01 17:50:17869
[email protected]49639fa2011-12-20 23:22:41870 TestCompletionCallback callback1;
871 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:17872
873 HttpRequestInfo httpreq = CreateGetRequest();
874
875 // Preconnect the first.
[email protected]1b323172011-03-01 17:50:17876 HttpStreamFactory* http_stream_factory =
877 helper.session()->http_stream_factory();
[email protected]1b323172011-03-01 17:50:17878
nharper8cdb0fb2016-04-22 21:34:59879 http_stream_factory->PreconnectStreams(1, httpreq);
[email protected]1b323172011-03-01 17:50:17880
bnc691fda62016-08-12 00:43:16881 out.rv = trans1.Start(&httpreq, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:01882 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16883 out.rv = trans2.Start(&httpreq, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:01884 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]1b323172011-03-01 17:50:17885
886 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01887 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17888 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:01889 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17890
bnc691fda62016-08-12 00:43:16891 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52892 EXPECT_TRUE(response1->headers);
[email protected]1b323172011-03-01 17:50:17893 EXPECT_TRUE(response1->was_fetched_via_spdy);
894 out.status_line = response1->headers->GetStatusLine();
895 out.response_info = *response1;
bnc691fda62016-08-12 00:43:16896 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:01897 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02898 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17899 EXPECT_EQ("hello!hello!", out.response_data);
900
bnc691fda62016-08-12 00:43:16901 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:52902 EXPECT_TRUE(response2->headers);
[email protected]1b323172011-03-01 17:50:17903 EXPECT_TRUE(response2->was_fetched_via_spdy);
904 out.status_line = response2->headers->GetStatusLine();
905 out.response_info = *response2;
bnc691fda62016-08-12 00:43:16906 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:01907 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02908 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17909 EXPECT_EQ("hello!hello!", out.response_data);
910
911 helper.VerifyDataConsumed();
912}
913
[email protected]2bd93022010-07-17 00:58:44914// Similar to ThreeGets above, however this test adds a SETTINGS
915// frame. The SETTINGS frame is read during the IO loop waiting on
916// the first transaction completion, and sets a maximum concurrent
917// stream limit of 1. This means that our IO loop exists after the
918// second transaction completes, so we can assert on read_index().
bncd16676a2016-07-20 16:23:01919TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:44920 // Construct the request.
rdsmithebb50aa2015-11-12 03:44:38921 // Each request fully completes before the next starts.
bncdf80d44fd2016-07-15 20:27:41922 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49923 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:35924 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41925 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
926 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:38927 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:44928
bncdf80d44fd2016-07-15 20:27:41929 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49930 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
tombergan5d22c182017-01-11 02:05:35931 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
bncdf80d44fd2016-07-15 20:27:41932 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
933 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:38934 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:44935
bncdf80d44fd2016-07-15 20:27:41936 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:49937 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
tombergan5d22c182017-01-11 02:05:35938 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
bncdf80d44fd2016-07-15 20:27:41939 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
940 SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44941
[email protected]18b28ab2012-04-18 02:14:42942 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:46943 const uint32_t max_concurrent_streams = 1;
diannahu0e5f4982016-12-22 15:50:29944 settings[SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
bncdf80d44fd2016-07-15 20:27:41945 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:20946 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:41947 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:44948
[email protected]2d6728692011-03-12 01:39:55949 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41950 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
951 CreateMockWrite(req2, 6), CreateMockWrite(req3, 10),
[email protected]2bd93022010-07-17 00:58:44952 };
[email protected]2d6728692011-03-12 01:39:55953
[email protected]2bd93022010-07-17 00:58:44954 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41955 CreateMockRead(settings_frame, 1),
956 CreateMockRead(resp, 2),
957 CreateMockRead(body, 3),
958 CreateMockRead(fbody, 4),
959 CreateMockRead(resp2, 7),
960 CreateMockRead(body2, 8),
961 CreateMockRead(fbody2, 9),
962 CreateMockRead(resp3, 11),
963 CreateMockRead(body3, 12),
964 CreateMockRead(fbody3, 13),
[email protected]2bd93022010-07-17 00:58:44965
rch08e3aa3e2015-05-16 14:27:52966 MockRead(ASYNC, 0, 14), // EOF
[email protected]2bd93022010-07-17 00:58:44967 };
968
rch08e3aa3e2015-05-16 14:27:52969 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:44970
tfarina428341112016-09-22 13:38:20971 NetLogWithSource log;
[email protected]2bd93022010-07-17 00:58:44972 TransactionHelperResult out;
973 {
[email protected]262eec82013-03-19 21:01:36974 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:35975 NetLogWithSource(), nullptr);
[email protected]2d6728692011-03-12 01:39:55976 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57977 helper.AddData(&data);
bnc691fda62016-08-12 00:43:16978 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
979 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
980 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
[email protected]2bd93022010-07-17 00:58:44981
[email protected]49639fa2011-12-20 23:22:41982 TestCompletionCallback callback1;
983 TestCompletionCallback callback2;
984 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44985
986 HttpRequestInfo httpreq1 = CreateGetRequest();
987 HttpRequestInfo httpreq2 = CreateGetRequest();
988 HttpRequestInfo httpreq3 = CreateGetRequest();
989
bnc691fda62016-08-12 00:43:16990 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]2bd93022010-07-17 00:58:44991 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]513963e2013-06-15 01:53:04992 // Run transaction 1 through quickly to force a read of our SETTINGS
993 // frame.
[email protected]2bd93022010-07-17 00:58:44994 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01995 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44996
bnc691fda62016-08-12 00:43:16997 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]2bd93022010-07-17 00:58:44998 ASSERT_EQ(out.rv, ERR_IO_PENDING);
bnc691fda62016-08-12 00:43:16999 out.rv = trans3.Start(&httpreq3, callback3.callback(), log);
[email protected]2bd93022010-07-17 00:58:441000 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1001 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011002 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441003
1004 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011005 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441006
bnc691fda62016-08-12 00:43:161007 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521008 ASSERT_TRUE(response1);
1009 EXPECT_TRUE(response1->headers);
[email protected]2bd93022010-07-17 00:58:441010 EXPECT_TRUE(response1->was_fetched_via_spdy);
1011 out.status_line = response1->headers->GetStatusLine();
1012 out.response_info = *response1;
bnc691fda62016-08-12 00:43:161013 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011014 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021015 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441016 EXPECT_EQ("hello!hello!", out.response_data);
1017
bnc691fda62016-08-12 00:43:161018 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:441019 out.status_line = response2->headers->GetStatusLine();
1020 out.response_info = *response2;
bnc691fda62016-08-12 00:43:161021 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011022 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021023 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441024 EXPECT_EQ("hello!hello!", out.response_data);
1025
bnc691fda62016-08-12 00:43:161026 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:441027 out.status_line = response3->headers->GetStatusLine();
1028 out.response_info = *response3;
bnc691fda62016-08-12 00:43:161029 out.rv = ReadTransaction(&trans3, &out.response_data);
robpercival214763f2016-07-01 23:27:011030 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021031 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441032 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:261033
1034 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441035 }
robpercival214763f2016-07-01 23:27:011036 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441037}
1038
1039// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1040// a fourth transaction. The third and fourth transactions have
1041// different data ("hello!" vs "hello!hello!") and because of the
1042// user specified priority, we expect to see them inverted in
1043// the response from the server.
bncd16676a2016-07-20 16:23:011044TEST_F(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:441045 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411046 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491047 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:351048 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411049 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1050 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381051 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441052
bncdf80d44fd2016-07-15 20:27:411053 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:491054 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
tombergan5d22c182017-01-11 02:05:351055 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
bncdf80d44fd2016-07-15 20:27:411056 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1057 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:381058 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:441059
bncdf80d44fd2016-07-15 20:27:411060 SpdySerializedFrame req4(
bnc38dcd392016-02-09 23:19:491061 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, HIGHEST, true));
tombergan5d22c182017-01-11 02:05:351062 SpdySerializedFrame resp4(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
bncdf80d44fd2016-07-15 20:27:411063 SpdySerializedFrame fbody4(spdy_util_.ConstructSpdyDataFrame(5, true));
rdsmithebb50aa2015-11-12 03:44:381064 spdy_util_.UpdateWithStreamDestruction(5);
[email protected]2bd93022010-07-17 00:58:441065
bncdf80d44fd2016-07-15 20:27:411066 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:491067 spdy_util_.ConstructSpdyGet(nullptr, 0, 7, LOWEST, true));
tombergan5d22c182017-01-11 02:05:351068 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 7));
bncdf80d44fd2016-07-15 20:27:411069 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(7, false));
1070 SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(7, true));
[email protected]2bd93022010-07-17 00:58:441071
[email protected]18b28ab2012-04-18 02:14:421072 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461073 const uint32_t max_concurrent_streams = 1;
diannahu0e5f4982016-12-22 15:50:291074 settings[SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
bncdf80d44fd2016-07-15 20:27:411075 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201076 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:411077 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
rch08e3aa3e2015-05-16 14:27:521078 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411079 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
rch08e3aa3e2015-05-16 14:27:521080 // By making these synchronous, it guarantees that they are not *started*
1081 // before their sequence number, which in turn verifies that only a single
1082 // request is in-flight at a time.
bncdf80d44fd2016-07-15 20:27:411083 CreateMockWrite(req2, 6, SYNCHRONOUS),
1084 CreateMockWrite(req4, 10, SYNCHRONOUS),
1085 CreateMockWrite(req3, 13, SYNCHRONOUS),
[email protected]2bd93022010-07-17 00:58:441086 };
1087 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411088 CreateMockRead(settings_frame, 1),
1089 CreateMockRead(resp, 2),
1090 CreateMockRead(body, 3),
1091 CreateMockRead(fbody, 4),
1092 CreateMockRead(resp2, 7),
1093 CreateMockRead(body2, 8),
1094 CreateMockRead(fbody2, 9),
1095 CreateMockRead(resp4, 11),
1096 CreateMockRead(fbody4, 12),
1097 CreateMockRead(resp3, 14),
1098 CreateMockRead(body3, 15),
1099 CreateMockRead(fbody3, 16),
[email protected]2bd93022010-07-17 00:58:441100
rch08e3aa3e2015-05-16 14:27:521101 MockRead(ASYNC, 0, 17), // EOF
[email protected]2bd93022010-07-17 00:58:441102 };
rch08e3aa3e2015-05-16 14:27:521103 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tfarina428341112016-09-22 13:38:201104 NetLogWithSource log;
[email protected]2bd93022010-07-17 00:58:441105 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361106 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351107 NetLogWithSource(), nullptr);
[email protected]bdebd1b2010-08-09 20:18:081108 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571109 helper.AddData(&data);
rch08e3aa3e2015-05-16 14:27:521110
bnc691fda62016-08-12 00:43:161111 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1112 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
1113 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
1114 HttpNetworkTransaction trans4(HIGHEST, helper.session());
[email protected]2bd93022010-07-17 00:58:441115
[email protected]49639fa2011-12-20 23:22:411116 TestCompletionCallback callback1;
1117 TestCompletionCallback callback2;
1118 TestCompletionCallback callback3;
1119 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:441120
[email protected]bdebd1b2010-08-09 20:18:081121 HttpRequestInfo httpreq1 = CreateGetRequest();
1122 HttpRequestInfo httpreq2 = CreateGetRequest();
1123 HttpRequestInfo httpreq3 = CreateGetRequest();
1124 HttpRequestInfo httpreq4 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441125
bnc691fda62016-08-12 00:43:161126 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:011127 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]e0935cc2012-03-24 14:12:481128 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081129 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011130 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441131
bnceb9aa7112017-01-05 01:03:461132 // Finish async network reads and writes associated with |trans1|.
1133 base::RunLoop().RunUntilIdle();
1134
bnc691fda62016-08-12 00:43:161135 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:011136 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:161137 out.rv = trans3.Start(&httpreq3, callback3.callback(), log);
robpercival214763f2016-07-01 23:27:011138 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:161139 out.rv = trans4.Start(&httpreq4, callback4.callback(), log);
robpercival214763f2016-07-01 23:27:011140 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]2bd93022010-07-17 00:58:441141
[email protected]bdebd1b2010-08-09 20:18:081142 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011143 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441144
[email protected]bdebd1b2010-08-09 20:18:081145 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011146 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441147
bnc691fda62016-08-12 00:43:161148 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521149 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:081150 EXPECT_TRUE(response1->was_fetched_via_spdy);
1151 out.status_line = response1->headers->GetStatusLine();
1152 out.response_info = *response1;
bnc691fda62016-08-12 00:43:161153 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011154 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021155 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081156 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441157
bnc691fda62016-08-12 00:43:161158 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081159 out.status_line = response2->headers->GetStatusLine();
1160 out.response_info = *response2;
bnc691fda62016-08-12 00:43:161161 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011162 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021163 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081164 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441165
[email protected]bdebd1b2010-08-09 20:18:081166 // notice: response3 gets two hellos, response4 gets one
1167 // hello, so we know dequeuing priority was respected.
bnc691fda62016-08-12 00:43:161168 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081169 out.status_line = response3->headers->GetStatusLine();
1170 out.response_info = *response3;
bnc691fda62016-08-12 00:43:161171 out.rv = ReadTransaction(&trans3, &out.response_data);
robpercival214763f2016-07-01 23:27:011172 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021173 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081174 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441175
[email protected]bdebd1b2010-08-09 20:18:081176 out.rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:011177 EXPECT_THAT(out.rv, IsOk());
bnc691fda62016-08-12 00:43:161178 const HttpResponseInfo* response4 = trans4.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081179 out.status_line = response4->headers->GetStatusLine();
1180 out.response_info = *response4;
bnc691fda62016-08-12 00:43:161181 out.rv = ReadTransaction(&trans4, &out.response_data);
robpercival214763f2016-07-01 23:27:011182 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021183 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081184 EXPECT_EQ("hello!", out.response_data);
1185 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:011186 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441187}
1188
1189// Similar to ThreeGetsMaxConcurrrent above, however, this test
rch08e3aa3e2015-05-16 14:27:521190// deletes a session in the middle of the transaction to ensure
[email protected]2bd93022010-07-17 00:58:441191// that we properly remove pendingcreatestream objects from
1192// the spdy_session
bncd16676a2016-07-20 16:23:011193TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:441194 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411195 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491196 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:351197 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411198 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1199 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381200 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441201
bncdf80d44fd2016-07-15 20:27:411202 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:491203 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
tombergan5d22c182017-01-11 02:05:351204 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
bncdf80d44fd2016-07-15 20:27:411205 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1206 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441207
[email protected]18b28ab2012-04-18 02:14:421208 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461209 const uint32_t max_concurrent_streams = 1;
diannahu0e5f4982016-12-22 15:50:291210 settings[SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
bncdf80d44fd2016-07-15 20:27:411211 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201212 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:411213 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441214
[email protected]d4a77c12014-05-15 20:45:211215 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411216 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1217 CreateMockWrite(req2, 6),
[email protected]2bd93022010-07-17 00:58:441218 };
1219 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411220 CreateMockRead(settings_frame, 1), CreateMockRead(resp, 2),
1221 CreateMockRead(body, 3), CreateMockRead(fbody, 4),
1222 CreateMockRead(resp2, 7), CreateMockRead(body2, 8),
1223 CreateMockRead(fbody2, 9), MockRead(ASYNC, 0, 10), // EOF
[email protected]2bd93022010-07-17 00:58:441224 };
1225
rch08e3aa3e2015-05-16 14:27:521226 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441227
tfarina428341112016-09-22 13:38:201228 NetLogWithSource log;
[email protected]2bd93022010-07-17 00:58:441229 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361230 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351231 NetLogWithSource(), nullptr);
[email protected]bdebd1b2010-08-09 20:18:081232 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571233 helper.AddData(&data);
danakjaee3e1ec2016-04-16 00:23:181234 std::unique_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421235 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
danakjaee3e1ec2016-04-16 00:23:181236 std::unique_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421237 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
danakjaee3e1ec2016-04-16 00:23:181238 std::unique_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:421239 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]2bd93022010-07-17 00:58:441240
[email protected]49639fa2011-12-20 23:22:411241 TestCompletionCallback callback1;
1242 TestCompletionCallback callback2;
1243 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441244
[email protected]bdebd1b2010-08-09 20:18:081245 HttpRequestInfo httpreq1 = CreateGetRequest();
1246 HttpRequestInfo httpreq2 = CreateGetRequest();
1247 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441248
[email protected]49639fa2011-12-20 23:22:411249 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081250 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481251 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081252 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011253 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441254
[email protected]49639fa2011-12-20 23:22:411255 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081256 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411257 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
olli.raula7ca9cd1d2016-01-04 06:50:371258 trans3.reset();
[email protected]bdebd1b2010-08-09 20:18:081259 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1260 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011261 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441262
[email protected]bdebd1b2010-08-09 20:18:081263 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:521264 ASSERT_TRUE(response1);
1265 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:081266 EXPECT_TRUE(response1->was_fetched_via_spdy);
1267 out.status_line = response1->headers->GetStatusLine();
1268 out.response_info = *response1;
1269 out.rv = ReadTransaction(trans1.get(), &out.response_data);
robpercival214763f2016-07-01 23:27:011270 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021271 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081272 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441273
[email protected]bdebd1b2010-08-09 20:18:081274 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:521275 ASSERT_TRUE(response2);
[email protected]bdebd1b2010-08-09 20:18:081276 out.status_line = response2->headers->GetStatusLine();
1277 out.response_info = *response2;
1278 out.rv = ReadTransaction(trans2.get(), &out.response_data);
robpercival214763f2016-07-01 23:27:011279 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021280 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081281 EXPECT_EQ("hello!hello!", out.response_data);
1282 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:011283 EXPECT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261284}
[email protected]2bd93022010-07-17 00:58:441285
[email protected]448d4ca52012-03-04 04:12:231286namespace {
1287
[email protected]044dcc52010-09-17 15:44:261288// The KillerCallback will delete the transaction on error as part of the
1289// callback.
[email protected]49639fa2011-12-20 23:22:411290class KillerCallback : public TestCompletionCallbackBase {
[email protected]044dcc52010-09-17 15:44:261291 public:
1292 explicit KillerCallback(HttpNetworkTransaction* transaction)
[email protected]49639fa2011-12-20 23:22:411293 : transaction_(transaction),
[email protected]aa249b52013-04-30 01:04:321294 callback_(base::Bind(&KillerCallback::OnComplete,
1295 base::Unretained(this))) {
[email protected]044dcc52010-09-17 15:44:261296 }
1297
dchengb03027d2014-10-21 12:00:201298 ~KillerCallback() override {}
[email protected]49639fa2011-12-20 23:22:411299
1300 const CompletionCallback& callback() const { return callback_; }
1301
[email protected]044dcc52010-09-17 15:44:261302 private:
[email protected]49639fa2011-12-20 23:22:411303 void OnComplete(int result) {
1304 if (result < 0)
1305 delete transaction_;
1306
1307 SetResult(result);
1308 }
1309
[email protected]044dcc52010-09-17 15:44:261310 HttpNetworkTransaction* transaction_;
[email protected]49639fa2011-12-20 23:22:411311 CompletionCallback callback_;
[email protected]044dcc52010-09-17 15:44:261312};
1313
[email protected]448d4ca52012-03-04 04:12:231314} // namespace
1315
[email protected]044dcc52010-09-17 15:44:261316// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1317// closes the socket while we have a pending transaction waiting for
1318// a pending stream creation. http://crbug.com/52901
bncd16676a2016-07-20 16:23:011319TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
[email protected]044dcc52010-09-17 15:44:261320 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411321 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491322 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:351323 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411324 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1325 SpdySerializedFrame fin_body(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381326 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]044dcc52010-09-17 15:44:261327
bncdf80d44fd2016-07-15 20:27:411328 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:491329 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
tombergan5d22c182017-01-11 02:05:351330 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]044dcc52010-09-17 15:44:261331
[email protected]18b28ab2012-04-18 02:14:421332 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461333 const uint32_t max_concurrent_streams = 1;
diannahu0e5f4982016-12-22 15:50:291334 settings[SETTINGS_MAX_CONCURRENT_STREAMS] = max_concurrent_streams;
bncdf80d44fd2016-07-15 20:27:411335 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201336 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:411337 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]044dcc52010-09-17 15:44:261338
[email protected]d4a77c12014-05-15 20:45:211339 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411340 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1341 CreateMockWrite(req2, 6),
[email protected]044dcc52010-09-17 15:44:261342 };
1343 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411344 CreateMockRead(settings_frame, 1),
1345 CreateMockRead(resp, 2),
1346 CreateMockRead(body, 3),
1347 CreateMockRead(fin_body, 4),
1348 CreateMockRead(resp2, 7),
rch08e3aa3e2015-05-16 14:27:521349 MockRead(ASYNC, ERR_CONNECTION_RESET, 8), // Abort!
[email protected]044dcc52010-09-17 15:44:261350 };
1351
rch08e3aa3e2015-05-16 14:27:521352 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tombergan5d22c182017-01-11 02:05:351353 SequencedSocketData data_placeholder(nullptr, 0, nullptr, 0);
[email protected]044dcc52010-09-17 15:44:261354
tfarina428341112016-09-22 13:38:201355 NetLogWithSource log;
[email protected]044dcc52010-09-17 15:44:261356 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361357 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351358 NetLogWithSource(), nullptr);
[email protected]044dcc52010-09-17 15:44:261359 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571360 helper.AddData(&data);
[email protected]044dcc52010-09-17 15:44:261361 // We require placeholder data because three get requests are sent out, so
1362 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571363 helper.AddData(&data_placeholder);
1364 helper.AddData(&data_placeholder);
mmenkee65e7af2015-10-13 17:16:421365 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1366 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]262eec82013-03-19 21:01:361367 HttpNetworkTransaction* trans3(
mmenkee65e7af2015-10-13 17:16:421368 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]044dcc52010-09-17 15:44:261369
[email protected]49639fa2011-12-20 23:22:411370 TestCompletionCallback callback1;
1371 TestCompletionCallback callback2;
[email protected]044dcc52010-09-17 15:44:261372 KillerCallback callback3(trans3);
1373
1374 HttpRequestInfo httpreq1 = CreateGetRequest();
1375 HttpRequestInfo httpreq2 = CreateGetRequest();
1376 HttpRequestInfo httpreq3 = CreateGetRequest();
1377
[email protected]49639fa2011-12-20 23:22:411378 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]044dcc52010-09-17 15:44:261379 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481380 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]044dcc52010-09-17 15:44:261381 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011382 ASSERT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261383
[email protected]49639fa2011-12-20 23:22:411384 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]044dcc52010-09-17 15:44:261385 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411386 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]044dcc52010-09-17 15:44:261387 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1388 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011389 ASSERT_THAT(out.rv, IsError(ERR_ABORTED));
[email protected]044dcc52010-09-17 15:44:261390
[email protected]044dcc52010-09-17 15:44:261391 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521392 ASSERT_TRUE(response1);
1393 EXPECT_TRUE(response1->headers);
[email protected]044dcc52010-09-17 15:44:261394 EXPECT_TRUE(response1->was_fetched_via_spdy);
1395 out.status_line = response1->headers->GetStatusLine();
1396 out.response_info = *response1;
1397 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011398 EXPECT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261399
1400 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:521401 ASSERT_TRUE(response2);
[email protected]044dcc52010-09-17 15:44:261402 out.status_line = response2->headers->GetStatusLine();
1403 out.response_info = *response2;
1404 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011405 EXPECT_THAT(out.rv, IsError(ERR_CONNECTION_RESET));
[email protected]044dcc52010-09-17 15:44:261406
1407 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441408}
1409
[email protected]d8ef27b2010-08-06 17:34:391410// Test that a simple PUT request works.
bncd16676a2016-07-20 16:23:011411TEST_F(SpdyNetworkTransactionTest, Put) {
[email protected]d8ef27b2010-08-06 17:34:391412 // Setup the request
1413 HttpRequestInfo request;
1414 request.method = "PUT";
bncb26024382016-06-29 02:39:451415 request.url = default_url_;
[email protected]d8ef27b2010-08-06 17:34:391416
bnc086b39e12016-06-24 13:05:261417 SpdyHeaderBlock put_headers(
bncb26024382016-06-29 02:39:451418 spdy_util_.ConstructPutHeaderBlock(kDefaultUrl, 0));
bncdf80d44fd2016-07-15 20:27:411419 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151420 spdy_util_.ConstructSpdyHeaders(1, std::move(put_headers), LOWEST, true));
[email protected]d8ef27b2010-08-06 17:34:391421 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411422 CreateMockWrite(req, 0),
[email protected]d8ef27b2010-08-06 17:34:391423 };
1424
tombergan5d22c182017-01-11 02:05:351425 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411426 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391427 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411428 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521429 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391430 };
1431
rch08e3aa3e2015-05-16 14:27:521432 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tfarina428341112016-09-22 13:38:201433 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351434 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:571435 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391436 TransactionHelperResult out = helper.output();
1437
robpercival214763f2016-07-01 23:27:011438 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021439 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391440}
1441
1442// Test that a simple HEAD request works.
bncd16676a2016-07-20 16:23:011443TEST_F(SpdyNetworkTransactionTest, Head) {
[email protected]d8ef27b2010-08-06 17:34:391444 // Setup the request
1445 HttpRequestInfo request;
1446 request.method = "HEAD";
bncb26024382016-06-29 02:39:451447 request.url = default_url_;
[email protected]d8ef27b2010-08-06 17:34:391448
bnc086b39e12016-06-24 13:05:261449 SpdyHeaderBlock head_headers(
bncb26024382016-06-29 02:39:451450 spdy_util_.ConstructHeadHeaderBlock(kDefaultUrl, 0));
bnc42331402016-07-25 13:36:151451 SpdySerializedFrame req(spdy_util_.ConstructSpdyHeaders(
1452 1, std::move(head_headers), LOWEST, true));
[email protected]d8ef27b2010-08-06 17:34:391453 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411454 CreateMockWrite(req, 0),
[email protected]d8ef27b2010-08-06 17:34:391455 };
1456
tombergan5d22c182017-01-11 02:05:351457 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411458 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391459 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411460 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521461 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391462 };
1463
rch08e3aa3e2015-05-16 14:27:521464 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tfarina428341112016-09-22 13:38:201465 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351466 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:571467 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391468 TransactionHelperResult out = helper.output();
1469
robpercival214763f2016-07-01 23:27:011470 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021471 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391472}
1473
[email protected]72552f02009-10-28 15:25:011474// Test that a simple POST works.
bncd16676a2016-07-20 16:23:011475TEST_F(SpdyNetworkTransactionTest, Post) {
bncdf80d44fd2016-07-15 20:27:411476 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
tombergan5d22c182017-01-11 02:05:351477 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411478 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141479 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411480 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141481 };
[email protected]72552f02009-10-28 15:25:011482
tombergan5d22c182017-01-11 02:05:351483 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]ff57bb82009-11-12 06:52:141484 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411485 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521486 MockRead(ASYNC, 0, 4) // EOF
[email protected]aea80602009-09-18 00:55:081487 };
1488
rch08e3aa3e2015-05-16 14:27:521489 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361490 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351491 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:571492 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471493 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011494 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021495 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]aea80602009-09-18 00:55:081496 EXPECT_EQ("hello!", out.response_data);
1497}
1498
[email protected]69e6b4a2012-10-18 08:03:011499// Test that a POST with a file works.
bncd16676a2016-07-20 16:23:011500TEST_F(SpdyNetworkTransactionTest, FilePost) {
bncdf80d44fd2016-07-15 20:27:411501 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
tombergan5d22c182017-01-11 02:05:351502 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411503 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011504 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411505 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011506 };
1507
tombergan5d22c182017-01-11 02:05:351508 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]69e6b4a2012-10-18 08:03:011509 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411510 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521511 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011512 };
1513
rch08e3aa3e2015-05-16 14:27:521514 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361515 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351516 NetLogWithSource(), nullptr);
[email protected]69e6b4a2012-10-18 08:03:011517 helper.RunToCompletion(&data);
1518 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011519 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021520 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011521 EXPECT_EQ("hello!", out.response_data);
1522}
1523
[email protected]999dd8c2013-11-12 06:45:541524// Test that a POST with a unreadable file fails.
bncd16676a2016-07-20 16:23:011525TEST_F(SpdyNetworkTransactionTest, UnreadableFilePost) {
[email protected]999dd8c2013-11-12 06:45:541526 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521527 MockWrite(ASYNC, 0, 0) // EOF
[email protected]999dd8c2013-11-12 06:45:541528 };
1529 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521530 MockRead(ASYNC, 0, 1) // EOF
[email protected]999dd8c2013-11-12 06:45:541531 };
1532
rch08e3aa3e2015-05-16 14:27:521533 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]999dd8c2013-11-12 06:45:541534 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
tfarina428341112016-09-22 13:38:201535 DEFAULT_PRIORITY, NetLogWithSource(),
tombergan5d22c182017-01-11 02:05:351536 nullptr);
[email protected]999dd8c2013-11-12 06:45:541537 helper.RunPreTestSetup();
1538 helper.AddData(&data);
1539 helper.RunDefaultTest();
1540
1541 base::RunLoop().RunUntilIdle();
1542 helper.VerifyDataNotConsumed();
robpercival214763f2016-07-01 23:27:011543 EXPECT_THAT(helper.output().rv, IsError(ERR_ACCESS_DENIED));
[email protected]999dd8c2013-11-12 06:45:541544}
1545
[email protected]69e6b4a2012-10-18 08:03:011546// Test that a complex POST works.
bncd16676a2016-07-20 16:23:011547TEST_F(SpdyNetworkTransactionTest, ComplexPost) {
bncdf80d44fd2016-07-15 20:27:411548 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
tombergan5d22c182017-01-11 02:05:351549 kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411550 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011551 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411552 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011553 };
1554
tombergan5d22c182017-01-11 02:05:351555 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]69e6b4a2012-10-18 08:03:011556 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411557 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521558 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011559 };
1560
rch08e3aa3e2015-05-16 14:27:521561 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tombergan5d22c182017-01-11 02:05:351562 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
1563 DEFAULT_PRIORITY, NetLogWithSource(),
1564 nullptr);
[email protected]69e6b4a2012-10-18 08:03:011565 helper.RunToCompletion(&data);
1566 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011567 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021568 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011569 EXPECT_EQ("hello!", out.response_data);
1570}
1571
[email protected]0c9bf872011-03-04 17:53:221572// Test that a chunked POST works.
bncd16676a2016-07-20 16:23:011573TEST_F(SpdyNetworkTransactionTest, ChunkedPost) {
tombergan5d22c182017-01-11 02:05:351574 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411575 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]0c9bf872011-03-04 17:53:221576 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411577 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
[email protected]0c9bf872011-03-04 17:53:221578 };
1579
tombergan5d22c182017-01-11 02:05:351580 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]0c9bf872011-03-04 17:53:221581 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411582 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521583 MockRead(ASYNC, 0, 4) // EOF
[email protected]0c9bf872011-03-04 17:53:221584 };
1585
rch08e3aa3e2015-05-16 14:27:521586 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tombergan5d22c182017-01-11 02:05:351587 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1588 DEFAULT_PRIORITY, NetLogWithSource(),
1589 nullptr);
[email protected]34b345f92013-02-22 03:27:261590
1591 // These chunks get merged into a single frame when being sent.
1592 const int kFirstChunkSize = kUploadDataSize/2;
mmenkecbc2b712014-10-09 20:29:071593 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1594 upload_chunked_data_stream()->AppendData(
[email protected]34b345f92013-02-22 03:27:261595 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1596
[email protected]dd54bd82012-07-19 23:44:571597 helper.RunToCompletion(&data);
[email protected]0c9bf872011-03-04 17:53:221598 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011599 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021600 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261601 EXPECT_EQ(kUploadData, out.response_data);
1602}
1603
1604// Test that a chunked POST works with chunks appended after transaction starts.
bncd16676a2016-07-20 16:23:011605TEST_F(SpdyNetworkTransactionTest, DelayedChunkedPost) {
tombergan5d22c182017-01-11 02:05:351606 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411607 SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false));
1608 SpdySerializedFrame chunk2(spdy_util_.ConstructSpdyDataFrame(1, false));
1609 SpdySerializedFrame chunk3(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]34b345f92013-02-22 03:27:261610 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411611 CreateMockWrite(req, 0), CreateMockWrite(chunk1, 1),
1612 CreateMockWrite(chunk2, 2), CreateMockWrite(chunk3, 3),
[email protected]34b345f92013-02-22 03:27:261613 };
1614
tombergan5d22c182017-01-11 02:05:351615 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]34b345f92013-02-22 03:27:261616 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411617 CreateMockRead(resp, 4), CreateMockRead(chunk1, 5),
1618 CreateMockRead(chunk2, 6), CreateMockRead(chunk3, 7),
rch08e3aa3e2015-05-16 14:27:521619 MockRead(ASYNC, 0, 8) // EOF
[email protected]34b345f92013-02-22 03:27:261620 };
1621
rch08e3aa3e2015-05-16 14:27:521622 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tombergan5d22c182017-01-11 02:05:351623 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1624 DEFAULT_PRIORITY, NetLogWithSource(),
1625 nullptr);
[email protected]34b345f92013-02-22 03:27:261626
mmenkecbc2b712014-10-09 20:29:071627 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]34b345f92013-02-22 03:27:261628
1629 helper.RunPreTestSetup();
1630 helper.AddData(&data);
1631 ASSERT_TRUE(helper.StartDefaultTest());
1632
[email protected]fc9d88472013-08-14 02:31:171633 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071634 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]fc9d88472013-08-14 02:31:171635 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071636 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]34b345f92013-02-22 03:27:261637
1638 helper.FinishDefaultTest();
1639 helper.VerifyDataConsumed();
1640
1641 std::string expected_response;
1642 expected_response += kUploadData;
1643 expected_response += kUploadData;
1644 expected_response += kUploadData;
1645
1646 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011647 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021648 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261649 EXPECT_EQ(expected_response, out.response_data);
[email protected]0c9bf872011-03-04 17:53:221650}
1651
[email protected]a33cad2b62010-07-30 22:24:391652// Test that a POST without any post data works.
bncd16676a2016-07-20 16:23:011653TEST_F(SpdyNetworkTransactionTest, NullPost) {
[email protected]a33cad2b62010-07-30 22:24:391654 // Setup the request
1655 HttpRequestInfo request;
1656 request.method = "POST";
bncb26024382016-06-29 02:39:451657 request.url = default_url_;
[email protected]a33cad2b62010-07-30 22:24:391658 // Create an empty UploadData.
tombergan5d22c182017-01-11 02:05:351659 request.upload_data_stream = nullptr;
[email protected]a33cad2b62010-07-30 22:24:391660
[email protected]329b68b2012-11-14 17:54:271661 // When request.upload_data_stream is NULL for post, content-length is
[email protected]a33cad2b62010-07-30 22:24:391662 // expected to be 0.
bnc086b39e12016-06-24 13:05:261663 SpdyHeaderBlock req_block(
bncb26024382016-06-29 02:39:451664 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
bncdf80d44fd2016-07-15 20:27:411665 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151666 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block), LOWEST, true));
[email protected]d2c1a97b2014-03-03 19:25:091667
[email protected]a33cad2b62010-07-30 22:24:391668 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411669 CreateMockWrite(req, 0),
[email protected]a33cad2b62010-07-30 22:24:391670 };
1671
tombergan5d22c182017-01-11 02:05:351672 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411673 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]a33cad2b62010-07-30 22:24:391674 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411675 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521676 MockRead(ASYNC, 0, 3) // EOF
[email protected]a33cad2b62010-07-30 22:24:391677 };
1678
rch08e3aa3e2015-05-16 14:27:521679 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]a33cad2b62010-07-30 22:24:391680
tfarina428341112016-09-22 13:38:201681 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351682 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:571683 helper.RunToCompletion(&data);
[email protected]a33cad2b62010-07-30 22:24:391684 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011685 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021686 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]a33cad2b62010-07-30 22:24:391687 EXPECT_EQ("hello!", out.response_data);
1688}
1689
[email protected]edd3b0a52009-11-24 18:56:361690// Test that a simple POST works.
bncd16676a2016-07-20 16:23:011691TEST_F(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]329b68b2012-11-14 17:54:271692 // Create an empty UploadDataStream.
danakjaee3e1ec2016-04-16 00:23:181693 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221694 ElementsUploadDataStream stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271695
[email protected]edd3b0a52009-11-24 18:56:361696 // Setup the request
1697 HttpRequestInfo request;
1698 request.method = "POST";
bncb26024382016-06-29 02:39:451699 request.url = default_url_;
[email protected]329b68b2012-11-14 17:54:271700 request.upload_data_stream = &stream;
[email protected]edd3b0a52009-11-24 18:56:361701
Avi Drissman13fc8932015-12-20 04:40:461702 const uint64_t kContentLength = 0;
[email protected]d2c1a97b2014-03-03 19:25:091703
bnc086b39e12016-06-24 13:05:261704 SpdyHeaderBlock req_block(
bncb26024382016-06-29 02:39:451705 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kContentLength));
bncdf80d44fd2016-07-15 20:27:411706 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151707 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block), LOWEST, true));
[email protected]d2c1a97b2014-03-03 19:25:091708
[email protected]edd3b0a52009-11-24 18:56:361709 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411710 CreateMockWrite(req, 0),
[email protected]edd3b0a52009-11-24 18:56:361711 };
1712
tombergan5d22c182017-01-11 02:05:351713 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411714 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361715 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411716 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521717 MockRead(ASYNC, 0, 3) // EOF
[email protected]edd3b0a52009-11-24 18:56:361718 };
1719
rch08e3aa3e2015-05-16 14:27:521720 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bf2491a92009-11-29 16:39:481721
tfarina428341112016-09-22 13:38:201722 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351723 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:571724 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471725 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011726 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021727 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]edd3b0a52009-11-24 18:56:361728 EXPECT_EQ("hello!", out.response_data);
1729}
1730
[email protected]35c3fc732014-02-15 00:16:071731// While we're doing a post, the server sends the reply before upload completes.
bncd16676a2016-07-20 16:23:011732TEST_F(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
tombergan5d22c182017-01-11 02:05:351733 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:411734 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]35c3fc732014-02-15 00:16:071735 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411736 CreateMockWrite(req, 0), CreateMockWrite(body, 3),
[email protected]35c3fc732014-02-15 00:16:071737 };
tombergan5d22c182017-01-11 02:05:351738 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]a5566f9702010-05-05 22:25:431739 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411740 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1741 MockRead(ASYNC, 0, 4) // EOF
[email protected]a5566f9702010-05-05 22:25:431742 };
1743
[email protected]35c3fc732014-02-15 00:16:071744 // Write the request headers, and read the complete response
1745 // while still waiting for chunked request data.
mmenke666a6fea2015-12-19 04:16:331746 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tombergan5d22c182017-01-11 02:05:351747 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1748 DEFAULT_PRIORITY, NetLogWithSource(),
1749 nullptr);
[email protected]c92f4b4542012-07-26 23:53:211750 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:331751 helper.AddData(&data);
[email protected]c92f4b4542012-07-26 23:53:211752
[email protected]35c3fc732014-02-15 00:16:071753 ASSERT_TRUE(helper.StartDefaultTest());
[email protected]c92f4b4542012-07-26 23:53:211754
maksim.sisov8d2df66d2016-06-20 07:07:111755 base::RunLoop().RunUntilIdle();
mmenke666a6fea2015-12-19 04:16:331756
bnc42331402016-07-25 13:36:151757 // Process the request headers, response headers, and response body.
[email protected]35c3fc732014-02-15 00:16:071758 // The request body is still in flight.
[email protected]35c3fc732014-02-15 00:16:071759 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
bnc84e7fb52015-12-02 11:50:021760 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]35c3fc732014-02-15 00:16:071761
1762 // Finish sending the request body.
mmenkecbc2b712014-10-09 20:29:071763 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
maksim.sisov8d2df66d2016-06-20 07:07:111764 helper.WaitForCallbackToComplete();
robpercival214763f2016-07-01 23:27:011765 EXPECT_THAT(helper.output().rv, IsOk());
[email protected]35c3fc732014-02-15 00:16:071766
1767 std::string response_body;
robpercival214763f2016-07-01 23:27:011768 EXPECT_THAT(ReadTransaction(helper.trans(), &response_body), IsOk());
[email protected]35c3fc732014-02-15 00:16:071769 EXPECT_EQ(kUploadData, response_body);
bnceb9aa7112017-01-05 01:03:461770
1771 // Finish async network reads/writes.
1772 base::RunLoop().RunUntilIdle();
[email protected]35c3fc732014-02-15 00:16:071773 helper.VerifyDataConsumed();
[email protected]a5566f9702010-05-05 22:25:431774}
1775
[email protected]f9a26d72010-08-03 18:07:131776// The client upon cancellation tries to send a RST_STREAM frame. The mock
1777// socket causes the TCP write to return zero. This test checks that the client
1778// tries to queue up the RST_STREAM frame again.
bncd16676a2016-07-20 16:23:011779TEST_F(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
bncdf80d44fd2016-07-15 20:27:411780 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491781 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411782 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201783 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]f9a26d72010-08-03 18:07:131784 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411785 CreateMockWrite(req, 0, SYNCHRONOUS), MockWrite(SYNCHRONOUS, 0, 0, 2),
1786 CreateMockWrite(rst, 3, SYNCHRONOUS),
[email protected]f9a26d72010-08-03 18:07:131787 };
1788
tombergan5d22c182017-01-11 02:05:351789 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f9a26d72010-08-03 18:07:131790 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411791 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:131792 };
1793
mmenke666a6fea2015-12-19 04:16:331794 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361795 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351796 NetLogWithSource(), nullptr);
[email protected]f9a26d72010-08-03 18:07:131797 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:331798 helper.AddData(&data);
bnc4d782f492016-08-18 13:50:001799 helper.StartDefaultTest();
1800 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
[email protected]f9a26d72010-08-03 18:07:131801
bnc4d782f492016-08-18 13:50:001802 helper.WaitForCallbackToComplete();
1803 EXPECT_THAT(helper.output().rv, IsOk());
[email protected]3b7828432010-08-18 18:33:271804
[email protected]f9a26d72010-08-03 18:07:131805 helper.ResetTrans();
mmenke666a6fea2015-12-19 04:16:331806 base::RunLoop().RunUntilIdle();
[email protected]3b7828432010-08-18 18:33:271807
[email protected]f9a26d72010-08-03 18:07:131808 helper.VerifyDataConsumed();
1809}
1810
[email protected]93300672009-10-24 13:22:511811// Test that the transaction doesn't crash when we don't have a reply.
bnc42331402016-07-25 13:36:151812TEST_F(SpdyNetworkTransactionTest, ResponseWithoutHeaders) {
bncdf80d44fd2016-07-15 20:27:411813 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141814 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411815 CreateMockRead(body, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]93300672009-10-24 13:22:511816 };
1817
bncdf80d44fd2016-07-15 20:27:411818 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491819 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411820 SpdySerializedFrame rst(
rch08e3aa3e2015-05-16 14:27:521821 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
1822 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411823 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
rch08e3aa3e2015-05-16 14:27:521824 };
1825 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361826 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351827 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:571828 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471829 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011830 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]93300672009-10-24 13:22:511831}
1832
[email protected]d30022352010-06-24 19:17:581833// Test that the transaction doesn't crash when we get two replies on the same
1834// stream ID. See http://crbug.com/45639.
bncd16676a2016-07-20 16:23:011835TEST_F(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
bncdf80d44fd2016-07-15 20:27:411836 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491837 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411838 SpdySerializedFrame rst(
[email protected]00b29472014-01-16 18:10:241839 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]2aeef782013-06-21 18:30:561840 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411841 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
[email protected]2aeef782013-06-21 18:30:561842 };
[email protected]d30022352010-06-24 19:17:581843
bnc42331402016-07-25 13:36:151844 SpdySerializedFrame resp0(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1845 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411846 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d30022352010-06-24 19:17:581847 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411848 CreateMockRead(resp0, 1), CreateMockRead(resp1, 2),
1849 CreateMockRead(body, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]d30022352010-06-24 19:17:581850 };
1851
rch08e3aa3e2015-05-16 14:27:521852 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d30022352010-06-24 19:17:581853
[email protected]262eec82013-03-19 21:01:361854 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351855 NetLogWithSource(), nullptr);
[email protected]3caf5542010-07-16 15:19:471856 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571857 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:471858
1859 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:581860
[email protected]49639fa2011-12-20 23:22:411861 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:201862 int rv =
1863 trans->Start(&helper.request(), callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011864 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d30022352010-06-24 19:17:581865 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011866 EXPECT_THAT(rv, IsOk());
[email protected]d30022352010-06-24 19:17:581867
1868 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:521869 ASSERT_TRUE(response);
1870 EXPECT_TRUE(response->headers);
[email protected]d30022352010-06-24 19:17:581871 EXPECT_TRUE(response->was_fetched_via_spdy);
1872 std::string response_data;
[email protected]3caf5542010-07-16 15:19:471873 rv = ReadTransaction(trans, &response_data);
robpercival214763f2016-07-01 23:27:011874 EXPECT_THAT(rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]3caf5542010-07-16 15:19:471875
1876 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:581877}
1878
bncd16676a2016-07-20 16:23:011879TEST_F(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:251880 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411881 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491882 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411883 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201884 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:251885 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411886 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
[email protected]b3503002012-03-27 04:57:251887 };
1888
1889 const char* const headers[] = {
[email protected]513963e2013-06-15 01:53:041890 "transfer-encoding", "chunked"
[email protected]b3503002012-03-27 04:57:251891 };
bnc42331402016-07-25 13:36:151892 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(headers, 1, 1));
bncdf80d44fd2016-07-15 20:27:411893 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b3503002012-03-27 04:57:251894 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411895 CreateMockRead(resp, 1), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521896 MockRead(ASYNC, 0, 4) // EOF
[email protected]b3503002012-03-27 04:57:251897 };
1898
rch08e3aa3e2015-05-16 14:27:521899 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361900 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351901 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:571902 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:251903 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011904 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:251905
1906 helper.session()->spdy_session_pool()->CloseAllSessions();
1907 helper.VerifyDataConsumed();
1908}
1909
bncd16676a2016-07-20 16:23:011910TEST_F(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:251911 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411912 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491913 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:351914 SpdySerializedFrame priority(
1915 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
bncdf80d44fd2016-07-15 20:27:411916 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201917 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:251918 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:351919 CreateMockWrite(req, 0), CreateMockWrite(priority, 3),
1920 CreateMockWrite(rst, 5),
[email protected]b3503002012-03-27 04:57:251921 };
1922
tombergan5d22c182017-01-11 02:05:351923 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]513963e2013-06-15 01:53:041924 const char* const headers[] = {
1925 "transfer-encoding", "chunked"
1926 };
bncdf80d44fd2016-07-15 20:27:411927 SpdySerializedFrame push(
rchebf12982015-04-10 01:15:001928 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2, 2, 1,
1929 GetDefaultUrlWithPath("/1").c_str()));
bncdf80d44fd2016-07-15 20:27:411930 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b3503002012-03-27 04:57:251931 MockRead reads[] = {
tombergan5d22c182017-01-11 02:05:351932 CreateMockRead(resp, 1), CreateMockRead(push, 2), CreateMockRead(body, 4),
1933 MockRead(ASYNC, 0, 6) // EOF
[email protected]b3503002012-03-27 04:57:251934 };
1935
rch08e3aa3e2015-05-16 14:27:521936 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361937 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351938 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:571939 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:251940 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011941 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021942 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b3503002012-03-27 04:57:251943 EXPECT_EQ("hello!", out.response_data);
1944
1945 helper.session()->spdy_session_pool()->CloseAllSessions();
1946 helper.VerifyDataConsumed();
1947}
1948
bncd16676a2016-07-20 16:23:011949TEST_F(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:381950 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411951 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491952 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]34437af82009-11-06 02:28:491953 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411954 CreateMockWrite(req),
[email protected]34437af82009-11-06 02:28:491955 };
1956
tombergan5d22c182017-01-11 02:05:351957 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]34437af82009-11-06 02:28:491958 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411959 CreateMockRead(resp),
1960 // This following read isn't used by the test, except during the
1961 // RunUntilIdle() call at the end since the SpdySession survives the
1962 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
1963 // MockRead will do here.
1964 MockRead(ASYNC, 0, 0) // EOF
[email protected]34437af82009-11-06 02:28:491965 };
1966
[email protected]31a2bfe2010-02-09 08:03:391967 StaticSocketDataProvider data(reads, arraysize(reads),
1968 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:471969
[email protected]262eec82013-03-19 21:01:361970 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:351971 NetLogWithSource(), nullptr);
[email protected]3caf5542010-07-16 15:19:471972 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:581973 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:471974 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:491975
[email protected]49639fa2011-12-20 23:22:411976 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:201977 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
1978 NetLogWithSource());
robpercival214763f2016-07-01 23:27:011979 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3caf5542010-07-16 15:19:471980 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:491981
[email protected]30c942b2010-07-21 16:59:591982 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:491983 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:171984 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:471985 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:491986}
[email protected]72552f02009-10-28 15:25:011987
[email protected]6c6ea172010-07-27 20:04:031988// Verify that the client sends a Rst Frame upon cancelling the stream.
bncd16676a2016-07-20 16:23:011989TEST_F(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
bncdf80d44fd2016-07-15 20:27:411990 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491991 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411992 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201993 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]6c6ea172010-07-27 20:04:031994 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411995 CreateMockWrite(req, 0, SYNCHRONOUS),
1996 CreateMockWrite(rst, 2, SYNCHRONOUS),
[email protected]6c6ea172010-07-27 20:04:031997 };
1998
tombergan5d22c182017-01-11 02:05:351999 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]6c6ea172010-07-27 20:04:032000 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412001 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:032002 };
2003
mmenke666a6fea2015-12-19 04:16:332004 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]6c6ea172010-07-27 20:04:032005
[email protected]262eec82013-03-19 21:01:362006 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:352007 NetLogWithSource(), nullptr);
[email protected]6c6ea172010-07-27 20:04:032008 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:332009 helper.AddData(&data);
[email protected]6c6ea172010-07-27 20:04:032010 HttpNetworkTransaction* trans = helper.trans();
2011
[email protected]49639fa2011-12-20 23:22:412012 TestCompletionCallback callback;
[email protected]6c6ea172010-07-27 20:04:032013
tfarina428341112016-09-22 13:38:202014 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
2015 NetLogWithSource());
robpercival214763f2016-07-01 23:27:012016 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]6c6ea172010-07-27 20:04:032017
[email protected]3b7828432010-08-18 18:33:272018 helper.ResetTrans();
mmenke666a6fea2015-12-19 04:16:332019 base::RunLoop().RunUntilIdle();
[email protected]3b7828432010-08-18 18:33:272020
[email protected]6c6ea172010-07-27 20:04:032021 helper.VerifyDataConsumed();
2022}
2023
[email protected]b278eb72010-07-09 20:17:002024// Verify that the client can correctly deal with the user callback attempting
2025// to start another transaction on a session that is closing down. See
2026// http://crbug.com/47455
bncd16676a2016-07-20 16:23:012027TEST_F(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
bncdf80d44fd2016-07-15 20:27:412028 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:492029 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412030 MockWrite writes[] = {CreateMockWrite(req)};
bnceb9aa7112017-01-05 01:03:462031 MockWrite writes2[] = {CreateMockWrite(req, 0),
2032 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]b278eb72010-07-09 20:17:002033
[email protected]cbdd73162013-03-18 23:27:332034 // The indicated length of this frame is longer than its actual length. When
2035 // the session receives an empty frame after this one, it shuts down the
[email protected]b278eb72010-07-09 20:17:002036 // session, and calls the read callback with the incomplete data.
Avi Drissman13fc8932015-12-20 04:40:462037 const uint8_t kGetBodyFrame2[] = {
2038 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
2039 0x07, 'h', 'e', 'l', 'l', 'o', '!',
[email protected]b278eb72010-07-09 20:17:002040 };
2041
tombergan5d22c182017-01-11 02:05:352042 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]b278eb72010-07-09 20:17:002043 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412044 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:092045 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2046 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2047 arraysize(kGetBodyFrame2), 3),
2048 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
2049 MockRead(ASYNC, 0, 0, 5), // EOF
[email protected]b278eb72010-07-09 20:17:002050 };
2051 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:412052 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 0, 2), // EOF
[email protected]b278eb72010-07-09 20:17:002053 };
2054
rch32320842015-05-16 15:57:092055 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
rch08e3aa3e2015-05-16 14:27:522056 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2057 arraysize(writes2));
[email protected]3caf5542010-07-16 15:19:472058
[email protected]262eec82013-03-19 21:01:362059 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:352060 NetLogWithSource(), nullptr);
[email protected]e3ebba0f2010-08-05 17:59:582061 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572062 helper.AddData(&data);
2063 helper.AddData(&data2);
[email protected]3caf5542010-07-16 15:19:472064 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002065
2066 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412067 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:202068 int rv =
2069 trans->Start(&helper.request(), callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012070 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b278eb72010-07-09 20:17:002071 rv = callback.WaitForResult();
2072
[email protected]b278eb72010-07-09 20:17:002073 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162074 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412075 rv = trans->Read(
rchebf12982015-04-10 01:15:002076 buf.get(), kSize,
[email protected]513963e2013-06-15 01:53:042077 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
bncb26024382016-06-29 02:39:452078 helper.session(), default_url_));
robpercival214763f2016-07-01 23:27:012079 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3caf5542010-07-16 15:19:472080 // This forces an err_IO_pending, which sets the callback.
mmenkee24011922015-12-17 22:12:592081 data.Resume();
2082 data.RunUntilPaused();
2083
[email protected]3caf5542010-07-16 15:19:472084 // This finishes the read.
mmenkee24011922015-12-17 22:12:592085 data.Resume();
2086 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472087 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002088}
2089
[email protected]9be804c82010-06-24 17:59:462090// Verify that the client can correctly deal with the user callback deleting the
2091// transaction. Failures will usually be valgrind errors. See
2092// http://crbug.com/46925
bncd16676a2016-07-20 16:23:012093TEST_F(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
bncdf80d44fd2016-07-15 20:27:412094 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:492095 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412096 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]9be804c82010-06-24 17:59:462097
tombergan5d22c182017-01-11 02:05:352098 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412099 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462100 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412101 CreateMockRead(resp, 1),
2102 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2103 CreateMockRead(body, 3), MockRead(ASYNC, 0, 0, 4), // EOF
[email protected]9be804c82010-06-24 17:59:462104 };
2105
rch32320842015-05-16 15:57:092106 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472107
[email protected]262eec82013-03-19 21:01:362108 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:352109 NetLogWithSource(), nullptr);
[email protected]3caf5542010-07-16 15:19:472110 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572111 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472112 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462113
2114 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412115 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:202116 int rv =
2117 trans->Start(&helper.request(), callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9be804c82010-06-24 17:59:462119 rv = callback.WaitForResult();
2120
2121 // Setup a user callback which will delete the session, and clear out the
2122 // memory holding the stream object. Note that the callback deletes trans.
[email protected]9be804c82010-06-24 17:59:462123 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162124 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412125 rv = trans->Read(
[email protected]90499482013-06-01 00:39:502126 buf.get(),
2127 kSize,
[email protected]513963e2013-06-15 01:53:042128 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
[email protected]49639fa2011-12-20 23:22:412129 base::Unretained(&helper)));
robpercival214763f2016-07-01 23:27:012130 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
mmenkee24011922015-12-17 22:12:592131 data.Resume();
[email protected]9be804c82010-06-24 17:59:462132
2133 // Finish running rest of tasks.
[email protected]fc9d88472013-08-14 02:31:172134 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472135 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462136}
2137
allada71b2efb2016-09-09 04:57:482138TEST_F(SpdyNetworkTransactionTest, TestRawHeaderSizeSuccessfullRequest) {
2139 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2140 headers["user-agent"] = "";
2141 headers["accept-encoding"] = "gzip, deflate";
2142
2143 SpdySerializedFrame req(
2144 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
2145 MockWrite writes[] = {
2146 CreateMockWrite(req, 0),
2147 };
2148
2149 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2150
2151 SpdySerializedFrame response_body_frame(
2152 spdy_util_.ConstructSpdyDataFrame(1, "should not include", 18, true));
2153
2154 MockRead response_headers(CreateMockRead(resp, 1));
2155 MockRead reads[] = {
2156 response_headers, CreateMockRead(response_body_frame, 2),
2157 MockRead(ASYNC, 0, 0, 3) // EOF
2158 };
2159 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2160
2161 TestDelegate delegate;
2162 SpdyURLRequestContext spdy_url_request_context;
2163 TestNetworkDelegate network_delegate;
2164 spdy_url_request_context.set_network_delegate(&network_delegate);
2165 SSLSocketDataProvider ssl_data(ASYNC, OK);
2166 ssl_data.next_proto = kProtoHTTP2;
2167
2168 std::unique_ptr<URLRequest> request(spdy_url_request_context.CreateRequest(
2169 GURL(kDefaultUrl), DEFAULT_PRIORITY, &delegate));
2170 spdy_url_request_context.socket_factory().AddSSLSocketDataProvider(&ssl_data);
2171 spdy_url_request_context.socket_factory().AddSocketDataProvider(&data);
2172
2173 request->Start();
2174 base::RunLoop().Run();
2175
2176 EXPECT_LT(0, request->GetTotalSentBytes());
2177 EXPECT_LT(0, request->GetTotalReceivedBytes());
2178 EXPECT_EQ(network_delegate.total_network_bytes_sent(),
2179 request->GetTotalSentBytes());
2180 EXPECT_EQ(network_delegate.total_network_bytes_received(),
2181 request->GetTotalReceivedBytes());
2182 EXPECT_EQ(response_headers.data_len, request->raw_header_size());
2183 EXPECT_TRUE(data.AllReadDataConsumed());
2184 EXPECT_TRUE(data.AllWriteDataConsumed());
2185}
2186
2187TEST_F(SpdyNetworkTransactionTest,
2188 TestRawHeaderSizeSuccessfullPushHeadersFirst) {
2189 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2190 headers["user-agent"] = "";
2191 headers["accept-encoding"] = "gzip, deflate";
2192
2193 SpdySerializedFrame req(
2194 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
tombergan5d22c182017-01-11 02:05:352195 SpdySerializedFrame priority(
2196 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
allada71b2efb2016-09-09 04:57:482197 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352198 CreateMockWrite(req, 0), CreateMockWrite(priority, 2),
allada71b2efb2016-09-09 04:57:482199 };
2200
2201 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2202 SpdySerializedFrame response_body_frame(
2203 spdy_util_.ConstructSpdyDataFrame(1, "should not include", 18, true));
2204
2205 SpdyHeaderBlock push_headers;
2206 spdy_util_.AddUrlToHeaderBlock(std::string(kDefaultUrl) + "b.dat",
2207 &push_headers);
2208
2209 SpdySerializedFrame push_init_frame(
2210 spdy_util_.ConstructInitialSpdyPushFrame(std::move(push_headers), 2, 1));
2211
2212 SpdySerializedFrame push_headers_frame(
2213 spdy_util_.ConstructSpdyPushHeaders(2, nullptr, 0));
2214
2215 SpdySerializedFrame push_body_frame(spdy_util_.ConstructSpdyDataFrame(
2216 2, "should not include either", 25, false));
2217
2218 MockRead push_init_read(CreateMockRead(push_init_frame, 1));
tombergan5d22c182017-01-11 02:05:352219 MockRead response_headers(CreateMockRead(resp, 5));
allada71b2efb2016-09-09 04:57:482220 // raw_header_size() will contain the size of the push promise frame
2221 // initialization.
2222 int expected_response_headers_size =
2223 response_headers.data_len + push_init_read.data_len;
2224
2225 MockRead reads[] = {
2226 push_init_read,
tombergan5d22c182017-01-11 02:05:352227 CreateMockRead(push_headers_frame, 3),
2228 CreateMockRead(push_body_frame, 4),
allada71b2efb2016-09-09 04:57:482229 response_headers,
tombergan5d22c182017-01-11 02:05:352230 CreateMockRead(response_body_frame, 6),
2231 MockRead(ASYNC, 0, 7) // EOF
allada71b2efb2016-09-09 04:57:482232 };
2233
2234 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2235
2236 TestDelegate delegate;
2237 SpdyURLRequestContext spdy_url_request_context;
2238 TestNetworkDelegate network_delegate;
2239 spdy_url_request_context.set_network_delegate(&network_delegate);
2240 SSLSocketDataProvider ssl_data(ASYNC, OK);
2241 ssl_data.next_proto = kProtoHTTP2;
2242
2243 std::unique_ptr<URLRequest> request(spdy_url_request_context.CreateRequest(
2244 GURL(kDefaultUrl), DEFAULT_PRIORITY, &delegate));
2245 spdy_url_request_context.socket_factory().AddSSLSocketDataProvider(&ssl_data);
2246 spdy_url_request_context.socket_factory().AddSocketDataProvider(&data);
2247
2248 request->Start();
2249 base::RunLoop().Run();
2250
2251 EXPECT_LT(0, request->GetTotalSentBytes());
2252 EXPECT_LT(0, request->GetTotalReceivedBytes());
2253 EXPECT_EQ(network_delegate.total_network_bytes_sent(),
2254 request->GetTotalSentBytes());
2255 EXPECT_EQ(network_delegate.total_network_bytes_received(),
2256 request->GetTotalReceivedBytes());
2257 EXPECT_EQ(expected_response_headers_size, request->raw_header_size());
2258 EXPECT_TRUE(data.AllReadDataConsumed());
2259 EXPECT_TRUE(data.AllWriteDataConsumed());
2260}
2261
bncce36dca22015-04-21 22:11:232262// Send a spdy request to www.example.org that gets redirected to www.foo.com.
bncd16676a2016-07-20 16:23:012263TEST_F(SpdyNetworkTransactionTest, DISABLED_RedirectGetRequest) {
bncb26024382016-06-29 02:39:452264 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc086b39e12016-06-24 13:05:262265 headers["user-agent"] = "";
2266 headers["accept-encoding"] = "gzip, deflate";
[email protected]e3ebba0f2010-08-05 17:59:582267
bncce36dca22015-04-21 22:11:232268 // Setup writes/reads to www.example.org
bncdf80d44fd2016-07-15 20:27:412269 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:152270 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
2271 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReplyRedirect(1));
[email protected]e3ebba0f2010-08-05 17:59:582272 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412273 CreateMockWrite(req, 1),
[email protected]e3ebba0f2010-08-05 17:59:582274 };
2275 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412276 CreateMockRead(resp, 2), MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582277 };
bnc086b39e12016-06-24 13:05:262278 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]e3ebba0f2010-08-05 17:59:582279
2280 // Setup writes/reads to www.foo.com
bnc086b39e12016-06-24 13:05:262281 SpdyHeaderBlock headers2(
2282 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2283 headers2["user-agent"] = "";
2284 headers2["accept-encoding"] = "gzip, deflate";
bncdf80d44fd2016-07-15 20:27:412285 SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:152286 spdy_util_.ConstructSpdyHeaders(1, std::move(headers2), LOWEST, true));
bnc086b39e12016-06-24 13:05:262287 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:412288 CreateMockWrite(req2, 1),
bnc086b39e12016-06-24 13:05:262289 };
2290
tombergan5d22c182017-01-11 02:05:352291 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412292 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582293 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:412294 CreateMockRead(resp2, 2), CreateMockRead(body2, 3),
2295 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582296 };
bnc086b39e12016-06-24 13:05:262297
rch08e3aa3e2015-05-16 14:27:522298 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2299 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582300
2301 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582302 TestDelegate d;
2303 {
bnca9b9e222016-07-11 20:10:402304 SpdyURLRequestContext spdy_url_request_context;
danakjaee3e1ec2016-04-16 00:23:182305 std::unique_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
bncb26024382016-06-29 02:39:452306 default_url_, DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092307 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572308 AddSocketDataProvider(&data);
[email protected]ef2bf422012-05-11 03:27:092309 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572310 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582311
2312 d.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192313 r->Start();
[email protected]fc9d88472013-08-14 02:31:172314 base::RunLoop().Run();
[email protected]513963e2013-06-15 01:53:042315
[email protected]e3ebba0f2010-08-05 17:59:582316 EXPECT_EQ(1, d.received_redirect_count());
2317
[email protected]f7022f32014-08-21 16:32:192318 r->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172319 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582320 EXPECT_EQ(1, d.response_started_count());
2321 EXPECT_FALSE(d.received_data_before_response());
maksim.sisov4887d11c2016-09-17 21:02:052322 EXPECT_EQ(OK, d.request_status());
[email protected]e3ebba0f2010-08-05 17:59:582323 std::string contents("hello!");
2324 EXPECT_EQ(contents, d.data_received());
2325 }
rch37de576c2015-05-17 20:28:172326 EXPECT_TRUE(data.AllReadDataConsumed());
2327 EXPECT_TRUE(data.AllWriteDataConsumed());
2328 EXPECT_TRUE(data2.AllReadDataConsumed());
2329 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582330}
2331
bncce36dca22015-04-21 22:11:232332// Send a spdy request to www.example.org. Get a pushed stream that redirects to
[email protected]e3ebba0f2010-08-05 17:59:582333// www.foo.com.
bncd16676a2016-07-20 16:23:012334TEST_F(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
bncb26024382016-06-29 02:39:452335 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc086b39e12016-06-24 13:05:262336 headers["user-agent"] = "";
2337 headers["accept-encoding"] = "gzip, deflate";
[email protected]3a8d6852011-03-11 23:43:442338
bncce36dca22015-04-21 22:11:232339 // Setup writes/reads to www.example.org
bncdf80d44fd2016-07-15 20:27:412340 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:152341 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
tombergan5d22c182017-01-11 02:05:352342 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412343 SpdySerializedFrame rep(spdy_util_.ConstructSpdyPush(
tombergan5d22c182017-01-11 02:05:352344 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
rchebf12982015-04-10 01:15:002345 "301 Moved Permanently", "http://www.foo.com/index.php"));
bncdf80d44fd2016-07-15 20:27:412346 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
2347 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:202348 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]3a8d6852011-03-11 23:43:442349 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412350 CreateMockWrite(req, 1), CreateMockWrite(rst, 6),
[email protected]3a8d6852011-03-11 23:43:442351 };
2352 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412353 CreateMockRead(resp, 2), CreateMockRead(rep, 3), CreateMockRead(body, 4),
2354 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2355 MockRead(ASYNC, 0, 0, 7) // EOF
[email protected]3a8d6852011-03-11 23:43:442356 };
2357
2358 // Setup writes/reads to www.foo.com
bnc086b39e12016-06-24 13:05:262359 SpdyHeaderBlock headers2(
[email protected]513963e2013-06-15 01:53:042360 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
bnc086b39e12016-06-24 13:05:262361 headers2["user-agent"] = "";
2362 headers2["accept-encoding"] = "gzip, deflate";
bncdf80d44fd2016-07-15 20:27:412363 SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:152364 spdy_util_.ConstructSpdyHeaders(1, std::move(headers2), LOWEST, true));
tombergan5d22c182017-01-11 02:05:352365 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412366 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582367 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:412368 CreateMockWrite(req2, 1),
[email protected]e3ebba0f2010-08-05 17:59:582369 };
2370 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:412371 CreateMockRead(resp2, 2), CreateMockRead(body2, 3),
2372 MockRead(ASYNC, 0, 0, 5) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582373 };
rch08e3aa3e2015-05-16 14:27:522374 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2375 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2376 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582377
[email protected]e3ebba0f2010-08-05 17:59:582378 TestDelegate d;
2379 TestDelegate d2;
bnca9b9e222016-07-11 20:10:402380 SpdyURLRequestContext spdy_url_request_context;
[email protected]e3ebba0f2010-08-05 17:59:582381 {
danakjaee3e1ec2016-04-16 00:23:182382 std::unique_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
bncb26024382016-06-29 02:39:452383 default_url_, DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092384 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572385 AddSocketDataProvider(&data);
[email protected]e3ebba0f2010-08-05 17:59:582386
[email protected]f7022f32014-08-21 16:32:192387 r->Start();
[email protected]fc9d88472013-08-14 02:31:172388 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582389
2390 EXPECT_EQ(0, d.received_redirect_count());
2391 std::string contents("hello!");
2392 EXPECT_EQ(contents, d.data_received());
2393
danakjaee3e1ec2016-04-16 00:23:182394 std::unique_ptr<URLRequest> r2(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002395 GURL(GetDefaultUrlWithPath("/foo.dat")), DEFAULT_PRIORITY, &d2));
[email protected]ef2bf422012-05-11 03:27:092396 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572397 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582398
2399 d2.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192400 r2->Start();
[email protected]fc9d88472013-08-14 02:31:172401 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582402 EXPECT_EQ(1, d2.received_redirect_count());
2403
[email protected]f7022f32014-08-21 16:32:192404 r2->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172405 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582406 EXPECT_EQ(1, d2.response_started_count());
2407 EXPECT_FALSE(d2.received_data_before_response());
maksim.sisov4887d11c2016-09-17 21:02:052408 EXPECT_EQ(OK, d2.request_status());
[email protected]e3ebba0f2010-08-05 17:59:582409 std::string contents2("hello!");
2410 EXPECT_EQ(contents2, d2.data_received());
2411 }
rch08e3aa3e2015-05-16 14:27:522412 EXPECT_TRUE(data.AllReadDataConsumed());
2413 EXPECT_TRUE(data.AllWriteDataConsumed());
2414 EXPECT_TRUE(data2.AllReadDataConsumed());
2415 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582416}
2417
bncd16676a2016-07-20 16:23:012418TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
bncdf80d44fd2016-07-15 20:27:412419 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492420 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:352421 SpdySerializedFrame stream2_priority(
2422 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]e3ebba0f2010-08-05 17:59:582423 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352424 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
[email protected]e3ebba0f2010-08-05 17:59:582425 };
2426
bncdf80d44fd2016-07-15 20:27:412427 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352428 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412429 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
tombergan5d22c182017-01-11 02:05:352430 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2431 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8a0fc822013-06-27 20:52:432432 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412433 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2434 2, kPushedData, strlen(kPushedData), true));
[email protected]e3ebba0f2010-08-05 17:59:582435 MockRead reads[] = {
tombergan5d22c182017-01-11 02:05:352436 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2437 CreateMockRead(stream1_body, 4), CreateMockRead(stream2_body, 5),
2438 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582439 };
2440
2441 HttpResponseInfo response;
2442 HttpResponseInfo response2;
[email protected]19ec8a72010-08-23 03:38:232443 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522444 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572445 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032446 &response,
2447 &response2,
2448 expected_push_result);
[email protected]e3ebba0f2010-08-05 17:59:582449
bnc42331402016-07-25 13:36:152450 // Verify the response headers.
wezca1070932016-05-26 20:30:522451 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022452 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582453
2454 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522455 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042456 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582457}
2458
bnc42331402016-07-25 13:36:152459TEST_F(SpdyNetworkTransactionTest, ServerPushBeforeHeaders) {
bncdf80d44fd2016-07-15 20:27:412460 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492461 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:352462 SpdySerializedFrame stream2_priority(
2463 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]a5b8eb29d2012-03-06 06:19:462464 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352465 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 2),
[email protected]a5b8eb29d2012-03-06 06:19:462466 };
2467
bncdf80d44fd2016-07-15 20:27:412468 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc38dcd392016-02-09 23:19:492469 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:412470 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352471 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412472 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8a0fc822013-06-27 20:52:432473 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412474 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2475 2, kPushedData, strlen(kPushedData), true));
[email protected]a5b8eb29d2012-03-06 06:19:462476 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412477 CreateMockRead(stream2_syn, 1),
tombergan5d22c182017-01-11 02:05:352478 CreateMockRead(stream1_reply, 3),
2479 CreateMockRead(stream1_body, 4, SYNCHRONOUS),
2480 CreateMockRead(stream2_body, 5),
2481 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]a5b8eb29d2012-03-06 06:19:462482 };
2483
2484 HttpResponseInfo response;
2485 HttpResponseInfo response2;
2486 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522487 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572488 RunServerPushTest(&data,
[email protected]a5b8eb29d2012-03-06 06:19:462489 &response,
2490 &response2,
2491 expected_push_result);
2492
bnc42331402016-07-25 13:36:152493 // Verify the response headers.
wezca1070932016-05-26 20:30:522494 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022495 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]a5b8eb29d2012-03-06 06:19:462496
2497 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522498 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042499 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]a5b8eb29d2012-03-06 06:19:462500}
2501
bncd16676a2016-07-20 16:23:012502TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
bncdf80d44fd2016-07-15 20:27:412503 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492504 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:352505 SpdySerializedFrame stream2_priority(
2506 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
rch08e3aa3e2015-05-16 14:27:522507 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352508 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
rch08e3aa3e2015-05-16 14:27:522509 };
[email protected]82918cc2010-08-25 17:24:502510
bncdf80d44fd2016-07-15 20:27:412511 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352512 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412513 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
tombergan5d22c182017-01-11 02:05:352514 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432515 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412516 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2517 2, kPushedData, strlen(kPushedData), true));
2518 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]82918cc2010-08-25 17:24:502519 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412520 CreateMockRead(stream1_reply, 1),
2521 CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:352522 CreateMockRead(stream2_body, 4),
2523 CreateMockRead(stream1_body, 5, SYNCHRONOUS),
2524 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]82918cc2010-08-25 17:24:502525 };
2526
2527 HttpResponseInfo response;
2528 HttpResponseInfo response2;
2529 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522530 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572531 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032532 &response,
2533 &response2,
2534 expected_push_result);
[email protected]82918cc2010-08-25 17:24:502535
bnc42331402016-07-25 13:36:152536 // Verify the response headers.
wezca1070932016-05-26 20:30:522537 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022538 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]82918cc2010-08-25 17:24:502539
2540 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522541 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042542 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]82918cc2010-08-25 17:24:502543}
2544
tombergan5d22c182017-01-11 02:05:352545TEST_F(SpdyNetworkTransactionTest, ServerPushUpdatesPriority) {
2546 SpdySerializedFrame stream1_headers(
2547 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST, true));
2548 SpdySerializedFrame stream3_headers(
2549 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM, true));
2550 SpdySerializedFrame stream5_headers(
2551 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, MEDIUM, true));
2552
2553 // Stream 1 pushes two streams that are initially prioritized below stream 5.
2554 // Stream 2 is later prioritized below stream 1 after it matches a request.
2555 SpdySerializedFrame stream2_priority(
2556 spdy_util_.ConstructSpdyPriority(2, 5, IDLE, true));
2557 SpdySerializedFrame stream4_priority(
2558 spdy_util_.ConstructSpdyPriority(4, 2, IDLE, true));
2559 SpdySerializedFrame stream4_priority_update(
2560 spdy_util_.ConstructSpdyPriority(4, 5, IDLE, true));
2561 SpdySerializedFrame stream2_priority_update(
2562 spdy_util_.ConstructSpdyPriority(2, 1, HIGHEST, true));
2563
[email protected]e3ebba0f2010-08-05 17:59:582564 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352565 CreateMockWrite(stream1_headers, 0),
2566 CreateMockWrite(stream3_headers, 1),
2567 CreateMockWrite(stream5_headers, 2),
2568 CreateMockWrite(stream2_priority, 7),
2569 CreateMockWrite(stream4_priority, 9),
2570 CreateMockWrite(stream4_priority_update, 11),
2571 CreateMockWrite(stream2_priority_update, 12),
[email protected]e3ebba0f2010-08-05 17:59:582572 };
2573
bncdf80d44fd2016-07-15 20:27:412574 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352575 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2576 SpdySerializedFrame stream3_reply(
2577 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
2578 SpdySerializedFrame stream5_reply(
2579 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
2580
2581 SpdySerializedFrame stream2_push(spdy_util_.ConstructSpdyPush(
2582 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2583 SpdySerializedFrame stream4_push(spdy_util_.ConstructSpdyPush(
2584 nullptr, 0, 4, 1, GetDefaultUrlWithPath("/bar.dat").c_str()));
2585
2586 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2587 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(2, true));
2588 SpdySerializedFrame stream3_body(spdy_util_.ConstructSpdyDataFrame(3, true));
2589 SpdySerializedFrame stream5_body(spdy_util_.ConstructSpdyDataFrame(5, true));
2590
2591 MockRead reads[] = {
2592 CreateMockRead(stream1_reply, 3),
2593 CreateMockRead(stream3_reply, 4),
2594 CreateMockRead(stream5_reply, 5),
2595 CreateMockRead(stream2_push, 6),
2596 CreateMockRead(stream4_push, 8),
2597 MockRead(ASYNC, ERR_IO_PENDING, 10),
2598 CreateMockRead(stream1_body, 13),
2599 CreateMockRead(stream2_body, 14),
2600 CreateMockRead(stream3_body, 15),
2601 CreateMockRead(stream5_body, 16),
2602 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 17), // Force a pause
2603 };
2604
2605 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2606 SequencedSocketData data_placeholder1(nullptr, 0, nullptr, 0);
2607 SequencedSocketData data_placeholder2(nullptr, 0, nullptr, 0);
2608 SequencedSocketData data_placeholder3(nullptr, 0, nullptr, 0);
2609
2610 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
2611 NetLogWithSource(), nullptr);
2612 helper.RunPreTestSetup();
2613 helper.AddData(&data);
2614 helper.AddData(&data_placeholder1); // other requests reuse the same socket
2615 helper.AddData(&data_placeholder2);
2616 helper.AddData(&data_placeholder3);
2617 HttpNetworkTransaction trans1(HIGHEST, helper.session());
2618 HttpNetworkTransaction trans3(MEDIUM, helper.session());
2619 HttpNetworkTransaction trans5(MEDIUM, helper.session());
2620
2621 TestCompletionCallback callback1;
2622 TestCompletionCallback callback3;
2623 TestCompletionCallback callback5;
2624
2625 // Start the ordinary requests.
2626 NetLogWithSource log;
2627 ASSERT_THAT(trans1.Start(&CreateGetRequest(), callback1.callback(), log),
2628 IsError(ERR_IO_PENDING));
2629 ASSERT_THAT(trans3.Start(&CreateGetRequest(), callback3.callback(), log),
2630 IsError(ERR_IO_PENDING));
2631 ASSERT_THAT(trans5.Start(&CreateGetRequest(), callback5.callback(), log),
2632 IsError(ERR_IO_PENDING));
2633 data.RunUntilPaused();
2634
tombergan5d22c182017-01-11 02:05:352635 // Start a request that matches the push.
2636 HttpRequestInfo push_req = CreateGetRequest();
2637 push_req.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
krasin0bfeb6b2017-01-13 21:48:042638
2639 HttpNetworkTransaction trans2(HIGHEST, helper.session());
2640 TestCompletionCallback callback2;
tombergan5d22c182017-01-11 02:05:352641 ASSERT_THAT(trans2.Start(&push_req, callback2.callback(), log),
2642 IsError(ERR_IO_PENDING));
2643 data.Resume();
2644
2645 base::RunLoop().RunUntilIdle();
2646 ASSERT_THAT(callback1.WaitForResult(), IsOk());
2647 ASSERT_THAT(callback2.WaitForResult(), IsOk());
2648 ASSERT_THAT(callback3.WaitForResult(), IsOk());
2649 ASSERT_THAT(callback5.WaitForResult(), IsOk());
2650 helper.VerifyDataConsumed();
2651}
2652
2653TEST_F(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2654 SpdySerializedFrame stream1_syn(
2655 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
2656 SpdySerializedFrame stream2_priority(
2657 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
2658 MockWrite writes[] = {
2659 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
2660 };
2661
2662 SpdySerializedFrame stream1_reply(
2663 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412664 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
tombergan5d22c182017-01-11 02:05:352665 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:412666 SpdySerializedFrame stream2_rst(
[email protected]c10b20852013-05-15 21:29:202667 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
tombergan5d22c182017-01-11 02:05:352668 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582669 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412670 CreateMockRead(stream1_reply, 1),
bnceb9aa7112017-01-05 01:03:462671 CreateMockRead(stream2_syn, 2, SYNCHRONOUS),
tombergan5d22c182017-01-11 02:05:352672 CreateMockRead(stream2_rst, 4),
2673 CreateMockRead(stream1_body, 5, SYNCHRONOUS),
2674 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582675 };
2676
rch08e3aa3e2015-05-16 14:27:522677 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362678 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:352679 NetLogWithSource(), nullptr);
[email protected]e3ebba0f2010-08-05 17:59:582680
2681 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572682 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582683
2684 HttpNetworkTransaction* trans = helper.trans();
2685
2686 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412687 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:202688 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
2689 NetLogWithSource());
robpercival214763f2016-07-01 23:27:012690 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:582691 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012692 EXPECT_THAT(rv, IsOk());
[email protected]19ec8a72010-08-23 03:38:232693
2694 // Verify that we consumed all test data.
tombergan5d22c182017-01-11 02:05:352695 base::RunLoop().RunUntilIdle();
rch08e3aa3e2015-05-16 14:27:522696 EXPECT_TRUE(data.AllReadDataConsumed());
2697 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]19ec8a72010-08-23 03:38:232698
bnc42331402016-07-25 13:36:152699 // Verify the response headers.
[email protected]19ec8a72010-08-23 03:38:232700 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522701 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022702 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232703}
2704
[email protected]8a0fc822013-06-27 20:52:432705// Verify that we don't leak streams and that we properly send a reset
2706// if the server pushes the same stream twice.
bncd16676a2016-07-20 16:23:012707TEST_F(SpdyNetworkTransactionTest, ServerPushDuplicate) {
bncdf80d44fd2016-07-15 20:27:412708 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492709 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:352710 SpdySerializedFrame stream2_priority(
2711 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
bncdf80d44fd2016-07-15 20:27:412712 SpdySerializedFrame stream3_rst(
[email protected]c10b20852013-05-15 21:29:202713 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
[email protected]fdc165a2010-09-03 03:51:292714 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352715 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
2716 CreateMockWrite(stream3_rst, 5),
[email protected]fdc165a2010-09-03 03:51:292717 };
2718
bncdf80d44fd2016-07-15 20:27:412719 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352720 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412721 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
tombergan5d22c182017-01-11 02:05:352722 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2723 SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
2724 nullptr, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2725
[email protected]8a0fc822013-06-27 20:52:432726 const char kPushedData[] = "pushed";
tombergan5d22c182017-01-11 02:05:352727 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:412728 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2729 2, kPushedData, strlen(kPushedData), true));
tombergan5d22c182017-01-11 02:05:352730
[email protected]fdc165a2010-09-03 03:51:292731 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412732 CreateMockRead(stream1_reply, 1),
2733 CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:352734 CreateMockRead(stream3_syn, 4),
2735 CreateMockRead(stream1_body, 6),
2736 CreateMockRead(stream2_body, 7),
2737 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), // Force a pause
[email protected]fdc165a2010-09-03 03:51:292738 };
2739
2740 HttpResponseInfo response;
2741 HttpResponseInfo response2;
2742 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522743 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572744 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032745 &response,
2746 &response2,
2747 expected_push_result);
[email protected]fdc165a2010-09-03 03:51:292748
bnc42331402016-07-25 13:36:152749 // Verify the response headers.
wezca1070932016-05-26 20:30:522750 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022751 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]fdc165a2010-09-03 03:51:292752
2753 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522754 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042755 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]fdc165a2010-09-03 03:51:292756}
2757
bncd16676a2016-07-20 16:23:012758TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
bncdf80d44fd2016-07-15 20:27:412759 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492760 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:352761 SpdySerializedFrame stream2_priority(
2762 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]19ec8a72010-08-23 03:38:232763 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352764 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
[email protected]19ec8a72010-08-23 03:38:232765 };
2766
bncdf80d44fd2016-07-15 20:27:412767 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352768 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412769 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
tombergan5d22c182017-01-11 02:05:352770 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432771 static const char kPushedData[] = "pushed my darling hello my baby";
bncdf80d44fd2016-07-15 20:27:412772 SpdySerializedFrame stream2_body_base(spdy_util_.ConstructSpdyDataFrame(
2773 2, kPushedData, strlen(kPushedData), true));
[email protected]8a0fc822013-06-27 20:52:432774 const size_t kChunkSize = strlen(kPushedData) / 4;
bncdf80d44fd2016-07-15 20:27:412775 SpdySerializedFrame stream2_body1(stream2_body_base.data(), kChunkSize,
2776 false);
2777 SpdySerializedFrame stream2_body2(stream2_body_base.data() + kChunkSize,
2778 kChunkSize, false);
2779 SpdySerializedFrame stream2_body3(stream2_body_base.data() + 2 * kChunkSize,
2780 kChunkSize, false);
2781 SpdySerializedFrame stream2_body4(stream2_body_base.data() + 3 * kChunkSize,
2782 stream2_body_base.size() - 3 * kChunkSize,
2783 false);
tombergan5d22c182017-01-11 02:05:352784 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232785 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412786 CreateMockRead(stream1_reply, 1),
2787 CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:352788 CreateMockRead(stream2_body1, 4),
2789 CreateMockRead(stream2_body2, 5),
2790 CreateMockRead(stream2_body3, 6),
2791 CreateMockRead(stream2_body4, 7),
2792 CreateMockRead(stream1_body, 8, SYNCHRONOUS),
2793 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9), // Force a pause
[email protected]19ec8a72010-08-23 03:38:232794 };
2795
2796 HttpResponseInfo response;
2797 HttpResponseInfo response2;
2798 std::string expected_push_result("pushed my darling hello my baby");
rch08e3aa3e2015-05-16 14:27:522799 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432800 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232801
bnc42331402016-07-25 13:36:152802 // Verify the response headers.
wezca1070932016-05-26 20:30:522803 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022804 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232805
2806 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522807 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042808 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232809}
2810
bncd16676a2016-07-20 16:23:012811TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
bncdf80d44fd2016-07-15 20:27:412812 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492813 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:352814 SpdySerializedFrame stream2_priority(
2815 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]19ec8a72010-08-23 03:38:232816 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:352817 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
[email protected]19ec8a72010-08-23 03:38:232818 };
2819
bncdf80d44fd2016-07-15 20:27:412820 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352821 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412822 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
tombergan5d22c182017-01-11 02:05:352823 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432824 static const char kPushedData[] = "pushed my darling hello my baby";
bncdf80d44fd2016-07-15 20:27:412825 SpdySerializedFrame stream2_body_base(spdy_util_.ConstructSpdyDataFrame(
2826 2, kPushedData, strlen(kPushedData), true));
[email protected]8a0fc822013-06-27 20:52:432827 const size_t kChunkSize = strlen(kPushedData) / 4;
bncdf80d44fd2016-07-15 20:27:412828 SpdySerializedFrame stream2_body1(stream2_body_base.data(), kChunkSize,
2829 false);
2830 SpdySerializedFrame stream2_body2(stream2_body_base.data() + kChunkSize,
2831 kChunkSize, false);
2832 SpdySerializedFrame stream2_body3(stream2_body_base.data() + 2 * kChunkSize,
2833 kChunkSize, false);
2834 SpdySerializedFrame stream2_body4(stream2_body_base.data() + 3 * kChunkSize,
2835 stream2_body_base.size() - 3 * kChunkSize,
2836 false);
tombergan5d22c182017-01-11 02:05:352837 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232838 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412839 CreateMockRead(stream1_reply, 1),
2840 CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:352841 CreateMockRead(stream2_body1, 4),
2842 CreateMockRead(stream2_body2, 5),
2843 CreateMockRead(stream2_body3, 6),
2844 CreateMockRead(stream2_body4, 7),
2845 CreateMockRead(stream1_body, 8, SYNCHRONOUS),
2846 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9) // Force a pause.
[email protected]19ec8a72010-08-23 03:38:232847 };
2848
2849 HttpResponseInfo response;
2850 HttpResponseInfo response2;
rch08e3aa3e2015-05-16 14:27:522851 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432852 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232853
bnc42331402016-07-25 13:36:152854 // Verify the response headers.
wezca1070932016-05-26 20:30:522855 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022856 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232857
2858 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522859 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042860 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232861}
2862
bncd16676a2016-07-20 16:23:012863TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
bncdf80d44fd2016-07-15 20:27:412864 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492865 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412866 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
2867 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_STREAM_ID)."));
[email protected]19ec8a72010-08-23 03:38:232868 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412869 CreateMockWrite(stream1_syn, 0), CreateMockWrite(goaway, 3),
[email protected]19ec8a72010-08-23 03:38:232870 };
2871
bncdf80d44fd2016-07-15 20:27:412872 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352873 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412874 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
tombergan5d22c182017-01-11 02:05:352875 nullptr, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]19ec8a72010-08-23 03:38:232876 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412877 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
[email protected]19ec8a72010-08-23 03:38:232878 };
2879
rch08e3aa3e2015-05-16 14:27:522880 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362881 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:352882 NetLogWithSource(), nullptr);
[email protected]19ec8a72010-08-23 03:38:232883
2884 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572885 helper.AddData(&data);
[email protected]19ec8a72010-08-23 03:38:232886
2887 HttpNetworkTransaction* trans = helper.trans();
2888
2889 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412890 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:202891 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
2892 NetLogWithSource());
robpercival214763f2016-07-01 23:27:012893 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]19ec8a72010-08-23 03:38:232894 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012895 EXPECT_THAT(rv, IsOk());
[email protected]e3ebba0f2010-08-05 17:59:582896
bnceb9aa7112017-01-05 01:03:462897 // Finish async network reads/writes.
2898 base::RunLoop().RunUntilIdle();
2899
[email protected]e3ebba0f2010-08-05 17:59:582900 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522901 EXPECT_TRUE(data.AllReadDataConsumed());
2902 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582903
bnc42331402016-07-25 13:36:152904 // Verify the response headers.
[email protected]e3ebba0f2010-08-05 17:59:582905 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522906 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022907 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582908}
2909
bncd16676a2016-07-20 16:23:012910TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
bncdf80d44fd2016-07-15 20:27:412911 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492912 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412913 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2914 SpdySerializedFrame stream2_rst(
bnc5221fd12017-01-11 22:06:072915 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_STREAM_CLOSED));
[email protected]e3ebba0f2010-08-05 17:59:582916 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412917 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582918 };
2919
bncdf80d44fd2016-07-15 20:27:412920 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352921 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412922 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
tombergan5d22c182017-01-11 02:05:352923 nullptr, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]e3ebba0f2010-08-05 17:59:582924 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412925 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2926 CreateMockRead(stream1_body, 4),
rch08e3aa3e2015-05-16 14:27:522927 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582928 };
2929
rch08e3aa3e2015-05-16 14:27:522930 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362931 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:352932 NetLogWithSource(), nullptr);
[email protected]e3ebba0f2010-08-05 17:59:582933
2934 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572935 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582936
2937 HttpNetworkTransaction* trans = helper.trans();
2938
2939 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412940 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:202941 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
2942 NetLogWithSource());
robpercival214763f2016-07-01 23:27:012943 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:582944 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012945 EXPECT_THAT(rv, IsOk());
[email protected]e3ebba0f2010-08-05 17:59:582946
bnceb9aa7112017-01-05 01:03:462947 // Finish async network reads/writes.
2948 base::RunLoop().RunUntilIdle();
2949
[email protected]e3ebba0f2010-08-05 17:59:582950 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522951 EXPECT_TRUE(data.AllReadDataConsumed());
2952 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582953
bnc42331402016-07-25 13:36:152954 // Verify the response headers.
[email protected]e3ebba0f2010-08-05 17:59:582955 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522956 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022957 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582958}
2959
bncd16676a2016-07-20 16:23:012960TEST_F(SpdyNetworkTransactionTest, ServerPushNoURL) {
bncdf80d44fd2016-07-15 20:27:412961 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492962 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412963 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2964 SpdySerializedFrame stream2_rst(
[email protected]c10b20852013-05-15 21:29:202965 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582966 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412967 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582968 };
2969
bncdf80d44fd2016-07-15 20:27:412970 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:352971 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc086b39e12016-06-24 13:05:262972 SpdyHeaderBlock incomplete_headers;
2973 incomplete_headers[spdy_util_.GetStatusKey()] = "200 OK";
bnc086b39e12016-06-24 13:05:262974 incomplete_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:412975 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
2976 std::move(incomplete_headers), 2, 1));
[email protected]e3ebba0f2010-08-05 17:59:582977 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412978 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2979 CreateMockRead(stream1_body, 4),
rch08e3aa3e2015-05-16 14:27:522980 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582981 };
2982
rch08e3aa3e2015-05-16 14:27:522983 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362984 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:352985 NetLogWithSource(), nullptr);
[email protected]e3ebba0f2010-08-05 17:59:582986
2987 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572988 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582989
2990 HttpNetworkTransaction* trans = helper.trans();
2991
2992 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412993 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:202994 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
2995 NetLogWithSource());
robpercival214763f2016-07-01 23:27:012996 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:582997 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012998 EXPECT_THAT(rv, IsOk());
rch08e3aa3e2015-05-16 14:27:522999
bnceb9aa7112017-01-05 01:03:463000 // Finish async network reads/writes.
3001 base::RunLoop().RunUntilIdle();
3002
[email protected]e3ebba0f2010-08-05 17:59:583003 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:523004 EXPECT_TRUE(data.AllReadDataConsumed());
3005 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:583006
bnc42331402016-07-25 13:36:153007 // Verify the response headers.
[email protected]e3ebba0f2010-08-05 17:59:583008 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523009 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:023010 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:583011}
3012
bnc0cb98b22016-03-04 17:10:523013// PUSH_PROMISE on a server-initiated stream should trigger GOAWAY.
bncd16676a2016-07-20 16:23:013014TEST_F(SpdyNetworkTransactionTest, ServerPushOnPushedStream) {
bncdf80d44fd2016-07-15 20:27:413015 SpdySerializedFrame stream1_syn(
bnc0cb98b22016-03-04 17:10:523016 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:353017 SpdySerializedFrame stream2_priority(
3018 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
bncdf80d44fd2016-07-15 20:27:413019 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bnc0cb98b22016-03-04 17:10:523020 2, GOAWAY_PROTOCOL_ERROR, "Push on even stream id."));
3021 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:353022 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
3023 CreateMockWrite(goaway, 5),
bnc0cb98b22016-03-04 17:10:523024 };
3025
bncdf80d44fd2016-07-15 20:27:413026 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:353027 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:413028 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:523029 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:413030 SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:523031 nullptr, 0, 4, 2, GetDefaultUrlWithPath("/bar.dat").c_str()));
3032 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413033 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:353034 CreateMockRead(stream3_syn, 4),
bnc0cb98b22016-03-04 17:10:523035 };
3036
3037 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3038 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tfarina428341112016-09-22 13:38:203039 NetLogWithSource(), nullptr);
bnc0cb98b22016-03-04 17:10:523040 helper.RunToCompletion(&data);
3041}
3042
3043// PUSH_PROMISE on a closed client-initiated stream should trigger RST_STREAM.
bncd16676a2016-07-20 16:23:013044TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedStream) {
bncdf80d44fd2016-07-15 20:27:413045 SpdySerializedFrame stream1_syn(
bnc0cb98b22016-03-04 17:10:523046 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413047 SpdySerializedFrame rst(
bnc5221fd12017-01-11 22:06:073048 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_STREAM_CLOSED));
bnc0cb98b22016-03-04 17:10:523049 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:413050 CreateMockWrite(stream1_syn, 0), CreateMockWrite(rst, 5),
bnc0cb98b22016-03-04 17:10:523051 };
3052
bncdf80d44fd2016-07-15 20:27:413053 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:153054 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:413055 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
3056 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:523057 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
3058 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413059 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_body, 2),
3060 CreateMockRead(stream2_syn, 3), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
bnc0cb98b22016-03-04 17:10:523061 };
3062
3063 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3064 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tfarina428341112016-09-22 13:38:203065 NetLogWithSource(), nullptr);
bnc0cb98b22016-03-04 17:10:523066 helper.RunPreTestSetup();
3067 helper.AddData(&data);
3068
3069 HttpNetworkTransaction* trans = helper.trans();
3070
3071 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:203072 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
3073 NetLogWithSource());
bnc0cb98b22016-03-04 17:10:523074 rv = callback.GetResult(rv);
robpercival214763f2016-07-01 23:27:013075 EXPECT_THAT(rv, IsOk());
bnceb9aa7112017-01-05 01:03:463076
3077 // Finish async network reads/writes.
3078 base::RunLoop().RunUntilIdle();
3079
bnc0cb98b22016-03-04 17:10:523080 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523081 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:523082 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
3083
3084 EXPECT_TRUE(data.AllReadDataConsumed());
3085 EXPECT_TRUE(data.AllWriteDataConsumed());
3086 VerifyStreamsClosed(helper);
3087}
3088
3089// PUSH_PROMISE on a server-initiated stream should trigger GOAWAY even if
3090// stream is closed.
bncd16676a2016-07-20 16:23:013091TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedPushedStream) {
bncdf80d44fd2016-07-15 20:27:413092 SpdySerializedFrame stream1_syn(
bnc0cb98b22016-03-04 17:10:523093 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:353094 SpdySerializedFrame stream2_priority(
3095 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
bncdf80d44fd2016-07-15 20:27:413096 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bnc0cb98b22016-03-04 17:10:523097 2, GOAWAY_PROTOCOL_ERROR, "Push on even stream id."));
3098 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:353099 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
3100 CreateMockWrite(goaway, 8),
bnc0cb98b22016-03-04 17:10:523101 };
3102
bncdf80d44fd2016-07-15 20:27:413103 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:153104 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:413105 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:523106 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:413107 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc0cb98b22016-03-04 17:10:523108 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:413109 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
3110 2, kPushedData, strlen(kPushedData), true));
3111 SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:523112 nullptr, 0, 4, 2, GetDefaultUrlWithPath("/bar.dat").c_str()));
3113
3114 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413115 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:353116 CreateMockRead(stream1_body, 4), CreateMockRead(stream2_body, 5),
3117 MockRead(ASYNC, ERR_IO_PENDING, 6), CreateMockRead(stream3_syn, 7),
bnc0cb98b22016-03-04 17:10:523118 };
3119
3120 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3121 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tfarina428341112016-09-22 13:38:203122 NetLogWithSource(), nullptr);
bnc0cb98b22016-03-04 17:10:523123 helper.RunPreTestSetup();
3124 helper.AddData(&data);
3125
3126 HttpNetworkTransaction* trans1 = helper.trans();
3127 TestCompletionCallback callback1;
tfarina428341112016-09-22 13:38:203128 int rv = trans1->Start(&CreateGetRequest(), callback1.callback(),
3129 NetLogWithSource());
bnc0cb98b22016-03-04 17:10:523130 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:013131 EXPECT_THAT(rv, IsOk());
bnc0cb98b22016-03-04 17:10:523132 HttpResponseInfo response = *trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:523133 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:523134 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
3135
bnc691fda62016-08-12 00:43:163136 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
bnc0cb98b22016-03-04 17:10:523137 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:163138 rv = trans2.Start(&CreateGetPushRequest(), callback2.callback(),
tfarina428341112016-09-22 13:38:203139 NetLogWithSource());
bnc0cb98b22016-03-04 17:10:523140 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:013141 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:163142 response = *trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:523143 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:523144 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
3145 std::string result;
bnc691fda62016-08-12 00:43:163146 ReadResult(&trans2, &result);
bnc0cb98b22016-03-04 17:10:523147 EXPECT_EQ(kPushedData, result);
3148
3149 data.Resume();
3150 base::RunLoop().RunUntilIdle();
3151
3152 EXPECT_TRUE(data.AllReadDataConsumed());
3153 EXPECT_TRUE(data.AllWriteDataConsumed());
3154}
3155
bnc42331402016-07-25 13:36:153156// Verify that various response headers parse correctly through the HTTP layer.
3157TEST_F(SpdyNetworkTransactionTest, ResponseHeaders) {
3158 struct ResponseHeadersTests {
[email protected]e7f75092010-07-01 22:39:133159 int num_headers;
3160 const char* extra_headers[5];
[email protected]513963e2013-06-15 01:53:043161 SpdyHeaderBlock expected_headers;
tombergan5d22c182017-01-11 02:05:353162 } test_cases[] = {// This uses a multi-valued cookie header.
3163 {
3164 2,
3165 {"cookie", "val1", "cookie",
3166 "val2", // will get appended separated by nullptr
3167 nullptr},
3168 },
3169 // This is the minimalist set of headers.
3170 {
3171 0, {nullptr},
3172 },
3173 // Headers with a comma separated list.
3174 {
3175 1, {"cookie", "val1,val2", nullptr},
3176 }};
[email protected]8b070372009-11-16 22:01:253177
[email protected]513963e2013-06-15 01:53:043178 test_cases[0].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043179 test_cases[1].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043180 test_cases[2].expected_headers["status"] = "200";
[email protected]601e03f12014-04-06 16:26:393181
bnc7ecc1122015-09-28 13:22:493182 test_cases[0].expected_headers["hello"] = "bye";
3183 test_cases[1].expected_headers["hello"] = "bye";
3184 test_cases[2].expected_headers["hello"] = "bye";
3185
bnc2d247912016-04-21 23:34:373186 test_cases[0].expected_headers["cookie"] = base::StringPiece("val1\0val2", 9);
bnc7ecc1122015-09-28 13:22:493187 test_cases[2].expected_headers["cookie"] = "val1,val2";
3188
viettrungluue4a8b882014-10-16 06:17:383189 for (size_t i = 0; i < arraysize(test_cases); ++i) {
bncd16676a2016-07-20 16:23:013190 SpdyTestUtil spdy_test_util;
bncdf80d44fd2016-07-15 20:27:413191 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493192 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413193 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8b070372009-11-16 22:01:253194
bnc42331402016-07-25 13:36:153195 SpdySerializedFrame resp(spdy_test_util.ConstructSpdyGetReply(
bncdf80d44fd2016-07-15 20:27:413196 test_cases[i].extra_headers, test_cases[i].num_headers, 1));
3197 SpdySerializedFrame body(spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]8b070372009-11-16 22:01:253198 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413199 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:523200 MockRead(ASYNC, 0, 3) // EOF
[email protected]8b070372009-11-16 22:01:253201 };
3202
rch08e3aa3e2015-05-16 14:27:523203 SequencedSocketData data(reads, arraysize(reads), writes,
3204 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363205 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353206 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:573207 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473208 TransactionHelperResult out = helper.output();
3209
robpercival214763f2016-07-01 23:27:013210 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023211 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8b070372009-11-16 22:01:253212 EXPECT_EQ("hello!", out.response_data);
3213
3214 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
wezca1070932016-05-26 20:30:523215 EXPECT_TRUE(headers);
olli.raula33c282f2016-01-21 12:12:493216 size_t iter = 0;
[email protected]513963e2013-06-15 01:53:043217 std::string name, value;
3218 SpdyHeaderBlock header_block;
[email protected]8b070372009-11-16 22:01:253219 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
diannahub0186222016-10-20 00:27:223220 auto value_it = header_block.find(name);
3221 if (value_it == header_block.end() || value_it->second.empty()) {
3222 header_block[name] = value;
[email protected]513963e2013-06-15 01:53:043223 } else {
diannahub0186222016-10-20 00:27:223224 std::string joint_value = value_it->second.as_string();
bnc7ecc1122015-09-28 13:22:493225 joint_value.append(1, '\0');
3226 joint_value.append(value);
diannahub0186222016-10-20 00:27:223227 header_block[name] = joint_value;
[email protected]513963e2013-06-15 01:53:043228 }
[email protected]8b070372009-11-16 22:01:253229 }
[email protected]513963e2013-06-15 01:53:043230 EXPECT_EQ(test_cases[i].expected_headers, header_block);
[email protected]8b070372009-11-16 22:01:253231 }
3232}
3233
bnc42331402016-07-25 13:36:153234// Verify that various response headers parse vary fields correctly through the
3235// HTTP layer, and the response matches the request.
3236TEST_F(SpdyNetworkTransactionTest, ResponseHeadersVary) {
[email protected]3f662f12010-03-25 19:56:123237 // Modify the following data to change/add test cases:
bnc42331402016-07-25 13:36:153238 struct ResponseTests {
[email protected]3f662f12010-03-25 19:56:123239 bool vary_matches;
3240 int num_headers[2];
3241 const char* extra_headers[2][16];
3242 } test_cases[] = {
bnc7ecc1122015-09-28 13:22:493243 // Test the case of a multi-valued cookie. When the value is delimited
3244 // with NUL characters, it needs to be unfolded into multiple headers.
3245 {true,
bnca9b9e222016-07-11 20:10:403246 {1, 3},
tombergan5d22c182017-01-11 02:05:353247 {{"cookie", "val1,val2", nullptr},
bnc7ecc1122015-09-28 13:22:493248 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
tombergan5d22c182017-01-11 02:05:353249 "/index.php", "vary", "cookie", nullptr}}},
bnc7ecc1122015-09-28 13:22:493250 {// Multiple vary fields.
3251 true,
bnc7ecc1122015-09-28 13:22:493252 {2, 4},
tombergan5d22c182017-01-11 02:05:353253 {{"friend", "barney", "enemy", "snaggletooth", nullptr},
bnc7ecc1122015-09-28 13:22:493254 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
tombergan5d22c182017-01-11 02:05:353255 "/index.php", "vary", "friend", "vary", "enemy", nullptr}}},
bnca9b9e222016-07-11 20:10:403256 {// Test a '*' vary field.
3257 false,
3258 {1, 3},
tombergan5d22c182017-01-11 02:05:353259 {{"cookie", "val1,val2", nullptr},
bnca9b9e222016-07-11 20:10:403260 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
tombergan5d22c182017-01-11 02:05:353261 "/index.php", "vary", "*", nullptr}}},
bnca9b9e222016-07-11 20:10:403262 {// Multiple comma-separated vary fields.
3263 true,
3264 {2, 3},
tombergan5d22c182017-01-11 02:05:353265 {{"friend", "barney", "enemy", "snaggletooth", nullptr},
bnca9b9e222016-07-11 20:10:403266 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
tombergan5d22c182017-01-11 02:05:353267 "/index.php", "vary", "friend,enemy", nullptr}}}};
[email protected]3f662f12010-03-25 19:56:123268
viettrungluue4a8b882014-10-16 06:17:383269 for (size_t i = 0; i < arraysize(test_cases); ++i) {
bncd16676a2016-07-20 16:23:013270 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:493271
[email protected]3f662f12010-03-25 19:56:123272 // Construct the request.
bncdf80d44fd2016-07-15 20:27:413273 SpdySerializedFrame frame_req(spdy_test_util.ConstructSpdyGet(
3274 test_cases[i].extra_headers[0], test_cases[i].num_headers[0], 1, LOWEST,
3275 true));
[email protected]3f662f12010-03-25 19:56:123276
3277 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:413278 CreateMockWrite(frame_req, 0),
[email protected]3f662f12010-03-25 19:56:123279 };
3280
3281 // Construct the reply.
[email protected]745aa9c2014-06-27 02:21:293282 SpdyHeaderBlock reply_headers;
3283 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3284 test_cases[i].num_headers[1],
3285 &reply_headers);
bnc086b39e12016-06-24 13:05:263286 // Construct the expected header reply string before moving |reply_headers|.
3287 std::string expected_reply =
3288 spdy_test_util.ConstructSpdyReplyString(reply_headers);
3289
bncdf80d44fd2016-07-15 20:27:413290 SpdySerializedFrame frame_reply(
bnc086b39e12016-06-24 13:05:263291 spdy_test_util.ConstructSpdyReply(1, std::move(reply_headers)));
[email protected]3f662f12010-03-25 19:56:123292
bncdf80d44fd2016-07-15 20:27:413293 SpdySerializedFrame body(spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]3f662f12010-03-25 19:56:123294 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413295 CreateMockRead(frame_reply, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:523296 MockRead(ASYNC, 0, 3) // EOF
[email protected]3f662f12010-03-25 19:56:123297 };
3298
[email protected]3f662f12010-03-25 19:56:123299 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:433300 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:123301
[email protected]d3cee19d2010-06-22 18:42:183302 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:433303 for (int ct = 0; ct < header_count; ct++) {
3304 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3305 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3306 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:123307 }
3308
rch08e3aa3e2015-05-16 14:27:523309 SequencedSocketData data(reads, arraysize(reads), writes,
3310 arraysize(writes));
tfarina428341112016-09-22 13:38:203311 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353312 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:573313 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473314 TransactionHelperResult out = helper.output();
3315
[email protected]3f662f12010-03-25 19:56:123316 EXPECT_EQ(OK, out.rv) << i;
bnc84e7fb52015-12-02 11:50:023317 EXPECT_EQ("HTTP/1.1 200", out.status_line) << i;
[email protected]3f662f12010-03-25 19:56:123318 EXPECT_EQ("hello!", out.response_data) << i;
3319
3320 // Test the response information.
[email protected]3f662f12010-03-25 19:56:123321 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3322 test_cases[i].vary_matches) << i;
3323
3324 // Check the headers.
3325 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
wezca1070932016-05-26 20:30:523326 ASSERT_TRUE(headers) << i;
olli.raula33c282f2016-01-21 12:12:493327 size_t iter = 0;
[email protected]3f662f12010-03-25 19:56:123328 std::string name, value, lines;
3329 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3330 lines.append(name);
3331 lines.append(": ");
3332 lines.append(value);
3333 lines.append("\n");
3334 }
3335
[email protected]9aa323192013-05-31 21:38:403336 EXPECT_EQ(expected_reply, lines) << i;
[email protected]3f662f12010-03-25 19:56:123337 }
3338}
3339
bnc42331402016-07-25 13:36:153340// Verify that we don't crash on invalid response headers.
3341TEST_F(SpdyNetworkTransactionTest, InvalidResponseHeaders) {
3342 struct InvalidResponseHeadersTests {
[email protected]e7f75092010-07-01 22:39:133343 int num_headers;
3344 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:483345 } test_cases[] = {
bnc42331402016-07-25 13:36:153346 // Response headers missing status header
bnc7ecc1122015-09-28 13:22:493347 {
bnca9b9e222016-07-11 20:10:403348 3,
3349 {spdy_util_.GetPathKey(), "/index.php", "cookie", "val1", "cookie",
tombergan5d22c182017-01-11 02:05:353350 "val2", nullptr},
[email protected]e7f75092010-07-01 22:39:133351 },
bnc42331402016-07-25 13:36:153352 // Response headers missing version header
bnc7ecc1122015-09-28 13:22:493353 {
tombergan5d22c182017-01-11 02:05:353354 1, {spdy_util_.GetPathKey(), "/index.php", "status", "200", nullptr},
[email protected]e7f75092010-07-01 22:39:133355 },
bnc42331402016-07-25 13:36:153356 // Response headers with no headers
bnc7ecc1122015-09-28 13:22:493357 {
tombergan5d22c182017-01-11 02:05:353358 0, {nullptr},
bnc7ecc1122015-09-28 13:22:493359 },
[email protected]dd11b932009-11-30 19:39:483360 };
3361
viettrungluue4a8b882014-10-16 06:17:383362 for (size_t i = 0; i < arraysize(test_cases); ++i) {
bncd16676a2016-07-20 16:23:013363 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:493364
bncdf80d44fd2016-07-15 20:27:413365 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493366 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413367 SpdySerializedFrame rst(
bnc38dcd392016-02-09 23:19:493368 spdy_test_util.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:483369 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:413370 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
[email protected]dd11b932009-11-30 19:39:483371 };
3372
[email protected]745aa9c2014-06-27 02:21:293373 // Construct the reply.
3374 SpdyHeaderBlock reply_headers;
3375 AppendToHeaderBlock(
3376 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
bncdf80d44fd2016-07-15 20:27:413377 SpdySerializedFrame resp(
bnc086b39e12016-06-24 13:05:263378 spdy_test_util.ConstructSpdyReply(1, std::move(reply_headers)));
[email protected]dd11b932009-11-30 19:39:483379 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413380 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]dd11b932009-11-30 19:39:483381 };
3382
rch08e3aa3e2015-05-16 14:27:523383 SequencedSocketData data(reads, arraysize(reads), writes,
3384 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363385 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353386 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:573387 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473388 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013389 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:483390 }
3391}
3392
bncd16676a2016-07-20 16:23:013393TEST_F(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
bncdf80d44fd2016-07-15 20:27:413394 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493395 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413396 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bncf5012992016-04-19 16:36:263397 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 6 (DECOMPRESS_FAILURE)."));
bncdf80d44fd2016-07-15 20:27:413398 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]e3352df2014-03-19 05:55:423399
bnc38dcd392016-02-09 23:19:493400 // This is the length field that's too short.
bnc42331402016-07-25 13:36:153401 SpdySerializedFrame reply_wrong_length(
3402 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
diannahu46ab1812016-12-26 21:27:073403 size_t right_size = reply_wrong_length.size() - kFrameHeaderSize;
bnc38dcd392016-02-09 23:19:493404 size_t wrong_size = right_size - 4;
bnc9921fa1d2016-12-01 18:51:153405 test::SetFrameLength(&reply_wrong_length, wrong_size);
bnc38dcd392016-02-09 23:19:493406
[email protected]e3352df2014-03-19 05:55:423407 MockRead reads[] = {
bnc42331402016-07-25 13:36:153408 MockRead(ASYNC, reply_wrong_length.data(), reply_wrong_length.size() - 4,
3409 1),
[email protected]e3352df2014-03-19 05:55:423410 };
3411
rch08e3aa3e2015-05-16 14:27:523412 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]e3352df2014-03-19 05:55:423413 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353414 NetLogWithSource(), nullptr);
[email protected]e3352df2014-03-19 05:55:423415 helper.RunToCompletion(&data);
3416 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013417 EXPECT_THAT(out.rv, IsError(ERR_SPDY_COMPRESSION_ERROR));
[email protected]bdd1b222014-06-10 11:08:393418}
3419
bncd16676a2016-07-20 16:23:013420TEST_F(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
bncdf80d44fd2016-07-15 20:27:413421 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493422 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413423 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bncf5012992016-04-19 16:36:263424 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 6 (DECOMPRESS_FAILURE)."));
bncdf80d44fd2016-07-15 20:27:413425 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393426
3427 // Read HEADERS with corrupted payload.
tombergan5d22c182017-01-11 02:05:353428 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:413429 memset(resp.data() + 12, 0xcf, resp.size() - 12);
3430 MockRead reads[] = {CreateMockRead(resp, 1)};
[email protected]bdd1b222014-06-10 11:08:393431
rch08e3aa3e2015-05-16 14:27:523432 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:013433 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353434 NetLogWithSource(), nullptr);
[email protected]bdd1b222014-06-10 11:08:393435 helper.RunToCompletion(&data);
3436 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013437 EXPECT_THAT(out.rv, IsError(ERR_SPDY_COMPRESSION_ERROR));
[email protected]bdd1b222014-06-10 11:08:393438}
3439
bncd16676a2016-07-20 16:23:013440TEST_F(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
bncdf80d44fd2016-07-15 20:27:413441 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493442 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413443 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bnc20df67c2016-04-07 01:36:183444 0, GOAWAY_FRAME_SIZE_ERROR,
dahollingsaf3796492016-05-25 19:21:353445 "Framer error: 15 (INVALID_CONTROL_FRAME_SIZE)."));
bncdf80d44fd2016-07-15 20:27:413446 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393447
3448 // Read WINDOW_UPDATE with incorrectly-sized payload.
bncdf80d44fd2016-07-15 20:27:413449 SpdySerializedFrame bad_window_update(
[email protected]bdd1b222014-06-10 11:08:393450 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
bnc9921fa1d2016-12-01 18:51:153451 test::SetFrameLength(&bad_window_update, bad_window_update.size() - 1);
bncdf80d44fd2016-07-15 20:27:413452 MockRead reads[] = {CreateMockRead(bad_window_update, 1)};
[email protected]bdd1b222014-06-10 11:08:393453
rch08e3aa3e2015-05-16 14:27:523454 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:013455 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353456 NetLogWithSource(), nullptr);
[email protected]bdd1b222014-06-10 11:08:393457 helper.RunToCompletion(&data);
3458 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013459 EXPECT_THAT(out.rv, IsError(ERR_SPDY_FRAME_SIZE_ERROR));
[email protected]e3352df2014-03-19 05:55:423460}
3461
[email protected]bf2491a92009-11-29 16:39:483462// Test that we shutdown correctly on write errors.
bncd16676a2016-07-20 16:23:013463TEST_F(SpdyNetworkTransactionTest, WriteError) {
bncdf80d44fd2016-07-15 20:27:413464 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493465 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483466 MockWrite writes[] = {
[email protected]bdd1b222014-06-10 11:08:393467 // We'll write 10 bytes successfully
bncdf80d44fd2016-07-15 20:27:413468 MockWrite(ASYNC, req.data(), 10, 1),
[email protected]bdd1b222014-06-10 11:08:393469 // Followed by ERROR!
[email protected]bdd1b222014-06-10 11:08:393470 MockWrite(ASYNC, ERR_FAILED, 2),
mmenke666a6fea2015-12-19 04:16:333471 // Session drains and attempts to write a GOAWAY: Another ERROR!
3472 MockWrite(ASYNC, ERR_FAILED, 3),
[email protected]bf2491a92009-11-29 16:39:483473 };
3474
mmenke666a6fea2015-12-19 04:16:333475 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
[email protected]238002d2013-10-17 02:01:403476
mmenke666a6fea2015-12-19 04:16:333477 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]238002d2013-10-17 02:01:403478
[email protected]262eec82013-03-19 21:01:363479 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353480 NetLogWithSource(), nullptr);
[email protected]238002d2013-10-17 02:01:403481 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:333482 helper.AddData(&data);
[email protected]238002d2013-10-17 02:01:403483 EXPECT_TRUE(helper.StartDefaultTest());
[email protected]238002d2013-10-17 02:01:403484 helper.FinishDefaultTest();
rch37de576c2015-05-17 20:28:173485 EXPECT_TRUE(data.AllWriteDataConsumed());
mmenke666a6fea2015-12-19 04:16:333486 EXPECT_TRUE(data.AllReadDataConsumed());
[email protected]3caf5542010-07-16 15:19:473487 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013488 EXPECT_THAT(out.rv, IsError(ERR_FAILED));
[email protected]bf2491a92009-11-29 16:39:483489}
3490
3491// Test that partial writes work.
bncd16676a2016-07-20 16:23:013492TEST_F(SpdyNetworkTransactionTest, PartialWrite) {
bnc42331402016-07-25 13:36:153493 // Chop the HEADERS frame into 5 chunks.
bncdf80d44fd2016-07-15 20:27:413494 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493495 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483496 const int kChunks = 5;
bncdf80d44fd2016-07-15 20:27:413497 std::unique_ptr<MockWrite[]> writes(ChopWriteFrame(req, kChunks));
rch08e3aa3e2015-05-16 14:27:523498 for (int i = 0; i < kChunks; ++i) {
3499 writes[i].sequence_number = i;
3500 }
[email protected]bf2491a92009-11-29 16:39:483501
tombergan5d22c182017-01-11 02:05:353502 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:413503 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:483504 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413505 CreateMockRead(resp, kChunks), CreateMockRead(body, kChunks + 1),
rch08e3aa3e2015-05-16 14:27:523506 MockRead(ASYNC, 0, kChunks + 2) // EOF
[email protected]bf2491a92009-11-29 16:39:483507 };
3508
rch08e3aa3e2015-05-16 14:27:523509 SequencedSocketData data(reads, arraysize(reads), writes.get(), kChunks);
[email protected]262eec82013-03-19 21:01:363510 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353511 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:573512 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473513 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013514 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023515 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bf2491a92009-11-29 16:39:483516 EXPECT_EQ("hello!", out.response_data);
3517}
3518
[email protected]9e743cd2010-03-16 07:03:533519// Test that the NetLog contains good data for a simple GET request.
bncd16676a2016-07-20 16:23:013520TEST_F(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:403521 static const char* const kExtraHeaders[] = {
3522 "user-agent", "Chrome",
3523 };
bncdf80d44fd2016-07-15 20:27:413524 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493525 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413526 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]dac358042009-12-18 02:07:483527
tombergan5d22c182017-01-11 02:05:353528 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:413529 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]dac358042009-12-18 02:07:483530 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413531 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:523532 MockRead(ASYNC, 0, 3) // EOF
[email protected]dac358042009-12-18 02:07:483533 };
3534
vishal.b62985ca92015-04-17 08:45:513535 BoundTestNetLog log;
[email protected]dac358042009-12-18 02:07:483536
rch08e3aa3e2015-05-16 14:27:523537 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3deb9a52010-11-11 00:24:403538 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
tombergan5d22c182017-01-11 02:05:353539 DEFAULT_PRIORITY, log.bound(), nullptr);
[email protected]dd54bd82012-07-19 23:44:573540 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473541 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013542 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023543 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]dac358042009-12-18 02:07:483544 EXPECT_EQ("hello!", out.response_data);
3545
[email protected]9e743cd2010-03-16 07:03:533546 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:473547 // This test is intentionally non-specific about the exact ordering of the
3548 // log; instead we just check to make sure that certain events exist, and that
3549 // they are in the right order.
mmenke43758e62015-05-04 21:09:463550 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403551 log.GetEntries(&entries);
3552
3553 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:483554 int pos = 0;
mikecirone8b85c432016-09-08 19:11:003555 pos = ExpectLogContainsSomewhere(
3556 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST,
3557 NetLogEventPhase::BEGIN);
3558 pos = ExpectLogContainsSomewhere(
3559 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST,
3560 NetLogEventPhase::END);
3561 pos = ExpectLogContainsSomewhere(
3562 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_READ_HEADERS,
3563 NetLogEventPhase::BEGIN);
3564 pos = ExpectLogContainsSomewhere(
3565 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_READ_HEADERS,
3566 NetLogEventPhase::END);
bnc301745a2015-03-10 03:22:163567 pos = ExpectLogContainsSomewhere(entries, pos + 1,
mikecirone8b85c432016-09-08 19:11:003568 NetLogEventType::HTTP_TRANSACTION_READ_BODY,
3569 NetLogEventPhase::BEGIN);
bnc301745a2015-03-10 03:22:163570 pos = ExpectLogContainsSomewhere(entries, pos + 1,
mikecirone8b85c432016-09-08 19:11:003571 NetLogEventType::HTTP_TRANSACTION_READ_BODY,
3572 NetLogEventPhase::END);
[email protected]3deb9a52010-11-11 00:24:403573
3574 // Check that we logged all the headers correctly
mikecirone8b85c432016-09-08 19:11:003575 pos = ExpectLogContainsSomewhere(entries, 0,
3576 NetLogEventType::HTTP2_SESSION_SEND_HEADERS,
3577 NetLogEventPhase::NONE);
[email protected]3deb9a52010-11-11 00:24:403578
[email protected]ea5ef4c2013-06-13 22:50:273579 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:573580 ASSERT_TRUE(entries[pos].params.get());
3581 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3582
3583 std::vector<std::string> expected;
bncce36dca22015-04-21 22:11:233584 expected.push_back(std::string(spdy_util_.GetHostKey()) +
3585 ": www.example.org");
[email protected]513963e2013-06-15 01:53:043586 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
rchebf12982015-04-10 01:15:003587 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": " +
bncb26024382016-06-29 02:39:453588 default_url_.scheme());
[email protected]513963e2013-06-15 01:53:043589 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
[email protected]f3da152d2012-06-02 01:00:573590 expected.push_back("user-agent: Chrome");
[email protected]f3da152d2012-06-02 01:00:573591 EXPECT_EQ(expected.size(), header_list->GetSize());
3592 for (std::vector<std::string>::const_iterator it = expected.begin();
3593 it != expected.end();
3594 ++it) {
3595 base::StringValue header(*it);
3596 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3597 "Header not found: " << *it;
[email protected]3deb9a52010-11-11 00:24:403598 }
[email protected]dac358042009-12-18 02:07:483599}
3600
[email protected]79d84222010-02-26 00:01:443601// Since we buffer the IO from the stream to the renderer, this test verifies
3602// that when we read out the maximum amount of data (e.g. we received 50 bytes
3603// on the network, but issued a Read for only 5 of those bytes) that the data
3604// flow still works correctly.
bncd16676a2016-07-20 16:23:013605TEST_F(SpdyNetworkTransactionTest, BufferFull) {
bncdf80d44fd2016-07-15 20:27:413606 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493607 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413608 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]79d84222010-02-26 00:01:443609
[email protected]20d005f2010-07-02 19:55:433610 // 2 data frames in a single read.
bncdf80d44fd2016-07-15 20:27:413611 SpdySerializedFrame data_frame_1(
3612 spdy_util_.ConstructSpdyDataFrame(1, "goodby", 6, /*fin=*/false));
3613 SpdySerializedFrame data_frame_2(
3614 spdy_util_.ConstructSpdyDataFrame(1, "e worl", 6, /*fin=*/false));
bncb03b1092016-04-06 11:19:553615 const SpdySerializedFrame* data_frames[2] = {
bncdf80d44fd2016-07-15 20:27:413616 &data_frame_1, &data_frame_2,
[email protected]79d84222010-02-26 00:01:443617 };
[email protected]20d005f2010-07-02 19:55:433618 char combined_data_frames[100];
3619 int combined_data_frames_len =
3620 CombineFrames(data_frames, arraysize(data_frames),
3621 combined_data_frames, arraysize(combined_data_frames));
bncdf80d44fd2016-07-15 20:27:413622 SpdySerializedFrame last_frame(
3623 spdy_util_.ConstructSpdyDataFrame(1, "d", 1, /*fin=*/true));
[email protected]79d84222010-02-26 00:01:443624
tombergan5d22c182017-01-11 02:05:353625 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]79d84222010-02-26 00:01:443626 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413627 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:093628 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3629 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3630 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
bncdf80d44fd2016-07-15 20:27:413631 CreateMockRead(last_frame, 5),
rch32320842015-05-16 15:57:093632 MockRead(ASYNC, 0, 6) // EOF
[email protected]79d84222010-02-26 00:01:443633 };
3634
rch32320842015-05-16 15:57:093635 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]79d84222010-02-26 00:01:443636
[email protected]49639fa2011-12-20 23:22:413637 TestCompletionCallback callback;
[email protected]79d84222010-02-26 00:01:443638
[email protected]262eec82013-03-19 21:01:363639 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353640 NetLogWithSource(), nullptr);
[email protected]3caf5542010-07-16 15:19:473641 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573642 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473643 HttpNetworkTransaction* trans = helper.trans();
tfarina428341112016-09-22 13:38:203644 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
3645 NetLogWithSource());
robpercival214763f2016-07-01 23:27:013646 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79d84222010-02-26 00:01:443647
[email protected]3caf5542010-07-16 15:19:473648 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:443649 out.rv = callback.WaitForResult();
3650 EXPECT_EQ(out.rv, OK);
3651
3652 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523653 EXPECT_TRUE(response->headers);
[email protected]79d84222010-02-26 00:01:443654 EXPECT_TRUE(response->was_fetched_via_spdy);
3655 out.status_line = response->headers->GetStatusLine();
3656 out.response_info = *response; // Make a copy so we can verify.
3657
3658 // Read Data
[email protected]49639fa2011-12-20 23:22:413659 TestCompletionCallback read_callback;
[email protected]79d84222010-02-26 00:01:443660
3661 std::string content;
3662 do {
3663 // Read small chunks at a time.
3664 const int kSmallReadSize = 3;
bnc301745a2015-03-10 03:22:163665 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503666 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163667 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593668 data.Resume();
[email protected]79d84222010-02-26 00:01:443669 rv = read_callback.WaitForResult();
3670 }
3671 if (rv > 0) {
3672 content.append(buf->data(), rv);
3673 } else if (rv < 0) {
3674 NOTREACHED();
3675 }
3676 } while (rv > 0);
3677
3678 out.response_data.swap(content);
3679
[email protected]30c942b2010-07-21 16:59:593680 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553681 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173682 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553683
[email protected]79d84222010-02-26 00:01:443684 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473685 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:443686
robpercival214763f2016-07-01 23:27:013687 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023688 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]79d84222010-02-26 00:01:443689 EXPECT_EQ("goodbye world", out.response_data);
3690}
3691
[email protected]8918d282010-03-02 00:57:553692// Verify that basic buffering works; when multiple data frames arrive
3693// at the same time, ensure that we don't notify a read completion for
3694// each data frame individually.
bncd16676a2016-07-20 16:23:013695TEST_F(SpdyNetworkTransactionTest, Buffering) {
bncdf80d44fd2016-07-15 20:27:413696 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493697 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413698 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:553699
3700 // 4 data frames in a single read.
bncdf80d44fd2016-07-15 20:27:413701 SpdySerializedFrame data_frame(
3702 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
3703 SpdySerializedFrame data_frame_fin(
3704 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/true));
3705 const SpdySerializedFrame* data_frames[4] = {&data_frame, &data_frame,
3706 &data_frame, &data_frame_fin};
[email protected]20d005f2010-07-02 19:55:433707 char combined_data_frames[100];
3708 int combined_data_frames_len =
3709 CombineFrames(data_frames, arraysize(data_frames),
3710 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:553711
tombergan5d22c182017-01-11 02:05:353712 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8918d282010-03-02 00:57:553713 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413714 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:093715 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3716 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3717 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553718 };
3719
rch32320842015-05-16 15:57:093720 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553721
[email protected]262eec82013-03-19 21:01:363722 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353723 NetLogWithSource(), nullptr);
[email protected]3caf5542010-07-16 15:19:473724 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573725 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473726 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553727
[email protected]49639fa2011-12-20 23:22:413728 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:203729 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
3730 NetLogWithSource());
robpercival214763f2016-07-01 23:27:013731 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:553732
[email protected]3caf5542010-07-16 15:19:473733 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553734 out.rv = callback.WaitForResult();
3735 EXPECT_EQ(out.rv, OK);
3736
3737 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523738 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:553739 EXPECT_TRUE(response->was_fetched_via_spdy);
3740 out.status_line = response->headers->GetStatusLine();
3741 out.response_info = *response; // Make a copy so we can verify.
3742
3743 // Read Data
[email protected]49639fa2011-12-20 23:22:413744 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553745
3746 std::string content;
3747 int reads_completed = 0;
3748 do {
3749 // Read small chunks at a time.
3750 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163751 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503752 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163753 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593754 data.Resume();
[email protected]8918d282010-03-02 00:57:553755 rv = read_callback.WaitForResult();
3756 }
3757 if (rv > 0) {
3758 EXPECT_EQ(kSmallReadSize, rv);
3759 content.append(buf->data(), rv);
3760 } else if (rv < 0) {
3761 FAIL() << "Unexpected read error: " << rv;
3762 }
3763 reads_completed++;
3764 } while (rv > 0);
3765
3766 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3767
3768 out.response_data.swap(content);
3769
[email protected]30c942b2010-07-21 16:59:593770 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553771 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173772 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553773
3774 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473775 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553776
robpercival214763f2016-07-01 23:27:013777 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023778 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:553779 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3780}
3781
3782// Verify the case where we buffer data but read it after it has been buffered.
bncd16676a2016-07-20 16:23:013783TEST_F(SpdyNetworkTransactionTest, BufferedAll) {
bncdf80d44fd2016-07-15 20:27:413784 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493785 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413786 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:553787
[email protected]20d005f2010-07-02 19:55:433788 // 5 data frames in a single read.
tombergan5d22c182017-01-11 02:05:353789 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:413790 SpdySerializedFrame data_frame(
3791 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
3792 SpdySerializedFrame data_frame_fin(
3793 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/true));
3794 const SpdySerializedFrame* frames[5] = {&reply, &data_frame, &data_frame,
3795 &data_frame, &data_frame_fin};
[email protected]20d005f2010-07-02 19:55:433796 char combined_frames[200];
3797 int combined_frames_len =
3798 CombineFrames(frames, arraysize(frames),
3799 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:553800
3801 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523802 MockRead(ASYNC, combined_frames, combined_frames_len, 1),
3803 MockRead(ASYNC, 0, 2) // EOF
[email protected]8918d282010-03-02 00:57:553804 };
3805
rch08e3aa3e2015-05-16 14:27:523806 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553807
[email protected]262eec82013-03-19 21:01:363808 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353809 NetLogWithSource(), nullptr);
[email protected]3caf5542010-07-16 15:19:473810 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573811 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473812 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553813
[email protected]49639fa2011-12-20 23:22:413814 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:203815 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
3816 NetLogWithSource());
robpercival214763f2016-07-01 23:27:013817 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:553818
[email protected]3caf5542010-07-16 15:19:473819 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553820 out.rv = callback.WaitForResult();
3821 EXPECT_EQ(out.rv, OK);
3822
3823 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523824 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:553825 EXPECT_TRUE(response->was_fetched_via_spdy);
3826 out.status_line = response->headers->GetStatusLine();
3827 out.response_info = *response; // Make a copy so we can verify.
3828
3829 // Read Data
[email protected]49639fa2011-12-20 23:22:413830 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553831
3832 std::string content;
3833 int reads_completed = 0;
3834 do {
3835 // Read small chunks at a time.
3836 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163837 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503838 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:553839 if (rv > 0) {
3840 EXPECT_EQ(kSmallReadSize, rv);
3841 content.append(buf->data(), rv);
3842 } else if (rv < 0) {
3843 FAIL() << "Unexpected read error: " << rv;
3844 }
3845 reads_completed++;
3846 } while (rv > 0);
3847
3848 EXPECT_EQ(3, reads_completed);
3849
3850 out.response_data.swap(content);
3851
[email protected]30c942b2010-07-21 16:59:593852 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553853 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173854 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553855
3856 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473857 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553858
robpercival214763f2016-07-01 23:27:013859 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023860 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:553861 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3862}
3863
3864// Verify the case where we buffer data and close the connection.
bncd16676a2016-07-20 16:23:013865TEST_F(SpdyNetworkTransactionTest, BufferedClosed) {
bncdf80d44fd2016-07-15 20:27:413866 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493867 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413868 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:553869
3870 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:433871 // NOTE: We don't FIN the stream.
bncdf80d44fd2016-07-15 20:27:413872 SpdySerializedFrame data_frame(
3873 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
3874 const SpdySerializedFrame* data_frames[4] = {&data_frame, &data_frame,
3875 &data_frame, &data_frame};
[email protected]20d005f2010-07-02 19:55:433876 char combined_data_frames[100];
3877 int combined_data_frames_len =
3878 CombineFrames(data_frames, arraysize(data_frames),
3879 combined_data_frames, arraysize(combined_data_frames));
tombergan5d22c182017-01-11 02:05:353880 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8918d282010-03-02 00:57:553881 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413882 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:093883 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3884 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3885 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553886 };
3887
rch32320842015-05-16 15:57:093888 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553889
[email protected]262eec82013-03-19 21:01:363890 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353891 NetLogWithSource(), nullptr);
[email protected]3caf5542010-07-16 15:19:473892 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573893 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473894 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553895
[email protected]49639fa2011-12-20 23:22:413896 TestCompletionCallback callback;
[email protected]8918d282010-03-02 00:57:553897
tfarina428341112016-09-22 13:38:203898 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
3899 NetLogWithSource());
robpercival214763f2016-07-01 23:27:013900 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:553901
[email protected]3caf5542010-07-16 15:19:473902 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553903 out.rv = callback.WaitForResult();
3904 EXPECT_EQ(out.rv, OK);
3905
3906 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523907 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:553908 EXPECT_TRUE(response->was_fetched_via_spdy);
3909 out.status_line = response->headers->GetStatusLine();
3910 out.response_info = *response; // Make a copy so we can verify.
3911
3912 // Read Data
[email protected]49639fa2011-12-20 23:22:413913 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553914
3915 std::string content;
3916 int reads_completed = 0;
3917 do {
3918 // Read small chunks at a time.
3919 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163920 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503921 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163922 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593923 data.Resume();
[email protected]8918d282010-03-02 00:57:553924 rv = read_callback.WaitForResult();
3925 }
3926 if (rv > 0) {
3927 content.append(buf->data(), rv);
3928 } else if (rv < 0) {
3929 // This test intentionally closes the connection, and will get an error.
robpercival214763f2016-07-01 23:27:013930 EXPECT_THAT(rv, IsError(ERR_CONNECTION_CLOSED));
[email protected]8918d282010-03-02 00:57:553931 break;
3932 }
3933 reads_completed++;
3934 } while (rv > 0);
3935
3936 EXPECT_EQ(0, reads_completed);
3937
3938 out.response_data.swap(content);
3939
[email protected]30c942b2010-07-21 16:59:593940 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553941 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173942 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553943
3944 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473945 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553946}
3947
[email protected]1ed7b3dc2010-03-04 05:41:453948// Verify the case where we buffer data and cancel the transaction.
bncd16676a2016-07-20 16:23:013949TEST_F(SpdyNetworkTransactionTest, BufferedCancelled) {
bncdf80d44fd2016-07-15 20:27:413950 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493951 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413952 SpdySerializedFrame rst(
[email protected]975da41a2014-06-05 03:36:243953 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
bncdf80d44fd2016-07-15 20:27:413954 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 4)};
[email protected]1ed7b3dc2010-03-04 05:41:453955
[email protected]20d005f2010-07-02 19:55:433956 // NOTE: We don't FIN the stream.
bncdf80d44fd2016-07-15 20:27:413957 SpdySerializedFrame data_frame(
3958 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
[email protected]1ed7b3dc2010-03-04 05:41:453959
tombergan5d22c182017-01-11 02:05:353960 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:453961 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413962 CreateMockRead(resp, 1),
3963 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3964 CreateMockRead(data_frame, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]1ed7b3dc2010-03-04 05:41:453965 };
3966
rch32320842015-05-16 15:57:093967 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1ed7b3dc2010-03-04 05:41:453968
[email protected]262eec82013-03-19 21:01:363969 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:353970 NetLogWithSource(), nullptr);
[email protected]3caf5542010-07-16 15:19:473971 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573972 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473973 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413974 TestCompletionCallback callback;
[email protected]1ed7b3dc2010-03-04 05:41:453975
tfarina428341112016-09-22 13:38:203976 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
3977 NetLogWithSource());
robpercival214763f2016-07-01 23:27:013978 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1ed7b3dc2010-03-04 05:41:453979
[email protected]3caf5542010-07-16 15:19:473980 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:453981 out.rv = callback.WaitForResult();
3982 EXPECT_EQ(out.rv, OK);
3983
3984 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523985 EXPECT_TRUE(response->headers);
[email protected]1ed7b3dc2010-03-04 05:41:453986 EXPECT_TRUE(response->was_fetched_via_spdy);
3987 out.status_line = response->headers->GetStatusLine();
3988 out.response_info = *response; // Make a copy so we can verify.
3989
3990 // Read Data
[email protected]49639fa2011-12-20 23:22:413991 TestCompletionCallback read_callback;
[email protected]1ed7b3dc2010-03-04 05:41:453992
[email protected]88c7b4be2014-03-19 23:04:013993 const int kReadSize = 256;
bnc301745a2015-03-10 03:22:163994 scoped_refptr<IOBuffer> buf(new IOBuffer(kReadSize));
[email protected]88c7b4be2014-03-19 23:04:013995 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163996 ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
[email protected]88c7b4be2014-03-19 23:04:013997
3998 // Complete the read now, which causes buffering to start.
mmenkee24011922015-12-17 22:12:593999 data.Resume();
4000 base::RunLoop().RunUntilIdle();
[email protected]88c7b4be2014-03-19 23:04:014001 // Destroy the transaction, causing the stream to get cancelled
4002 // and orphaning the buffered IO task.
4003 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:454004
4005 // Flush the MessageLoop; this will cause the buffered IO task
4006 // to run for the final time.
[email protected]fc9d88472013-08-14 02:31:174007 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:474008
4009 // Verify that we consumed all test data.
4010 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:454011}
4012
bncd16676a2016-07-20 16:23:014013TEST_F(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
bncdf80d44fd2016-07-15 20:27:414014 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494015 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414016 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]69d717bd2010-04-21 18:43:214017
bncdf80d44fd2016-07-15 20:27:414018 SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:214019 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414020 CreateMockRead(go_away, 1),
[email protected]58cebf8f2010-07-31 19:20:164021 };
4022
rch08e3aa3e2015-05-16 14:27:524023 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364024 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:354025 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:574026 helper.AddData(&data);
4027 helper.RunToCompletion(&data);
[email protected]58cebf8f2010-07-31 19:20:164028 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014029 EXPECT_THAT(out.rv, IsError(ERR_ABORTED));
[email protected]69d717bd2010-04-21 18:43:214030}
4031
bnc1fc7b352017-01-12 17:51:024032// A server can gracefully shut down by sending a GOAWAY frame
4033// with maximum last-stream-id value.
4034// Transactions started before receiving such a GOAWAY frame should succeed,
4035// but SpdySession should be unavailable for new streams.
4036TEST_F(SpdyNetworkTransactionTest, GracefulGoaway) {
4037 SpdySerializedFrame req1(
4038 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
4039 spdy_util_.UpdateWithStreamDestruction(1);
4040 SpdySerializedFrame req2(
4041 spdy_util_.ConstructSpdyGet("https://www.example.org/foo", 3, LOWEST));
4042 MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 3)};
4043
4044 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
4045 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
4046 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
4047 0x7fffffff, GOAWAY_NO_ERROR, "Graceful shutdown."));
4048 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
4049 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
4050 MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
4051 CreateMockRead(goaway, 4), CreateMockRead(resp2, 5),
4052 CreateMockRead(body2, 6), MockRead(ASYNC, 0, 7)};
4053
4054 // Run first transaction.
4055 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4056 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4057 NetLogWithSource(), nullptr);
4058 helper.RunPreTestSetup();
4059 helper.AddData(&data);
4060 helper.RunDefaultTest();
4061
4062 // Verify first response.
4063 TransactionHelperResult out = helper.output();
4064 EXPECT_THAT(out.rv, IsOk());
4065 EXPECT_EQ("HTTP/1.1 200", out.status_line);
4066 EXPECT_EQ("hello!", out.response_data);
4067
4068 // GOAWAY frame has not yet been received, SpdySession should be available.
4069 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4070 SpdySessionKey key(host_port_pair_, ProxyServer::Direct(),
4071 PRIVACY_MODE_DISABLED);
4072 NetLogWithSource log;
4073 base::WeakPtr<SpdySession> spdy_session =
4074 spdy_session_pool->FindAvailableSession(key, GURL(), log);
4075 EXPECT_TRUE(spdy_session);
4076
4077 // Start second transaction.
4078 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
4079 TestCompletionCallback callback;
4080 HttpRequestInfo request2;
4081 request2.method = "GET";
4082 request2.url = GURL("https://www.example.org/foo");
4083 int rv = trans2.Start(&request2, callback.callback(), log);
4084 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
4085 rv = callback.WaitForResult();
4086 EXPECT_THAT(rv, IsOk());
4087
4088 // Verify second response.
4089 const HttpResponseInfo* response = trans2.GetResponseInfo();
4090 ASSERT_TRUE(response);
4091 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2, response->connection_info);
4092 ASSERT_TRUE(response->headers);
4093 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
4094 EXPECT_TRUE(response->was_fetched_via_spdy);
4095 EXPECT_TRUE(response->was_alpn_negotiated);
4096 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4097 EXPECT_EQ(443, response->socket_address.port());
4098 std::string response_data;
4099 rv = ReadTransaction(&trans2, &response_data);
4100 EXPECT_THAT(rv, IsOk());
4101 EXPECT_EQ("hello!", response_data);
4102
4103 // Graceful GOAWAY was received, SpdySession should be unavailable.
4104 spdy_session = spdy_session_pool->FindAvailableSession(key, GURL(), log);
4105 EXPECT_FALSE(spdy_session);
4106
4107 helper.VerifyDataConsumed();
4108}
4109
bncd16676a2016-07-20 16:23:014110TEST_F(SpdyNetworkTransactionTest, CloseWithActiveStream) {
bncdf80d44fd2016-07-15 20:27:414111 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494112 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414113 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]f5ed21552010-05-04 18:39:544114
tombergan5d22c182017-01-11 02:05:354115 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f5ed21552010-05-04 18:39:544116 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414117 CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
[email protected]f5ed21552010-05-04 18:39:544118 };
4119
rch08e3aa3e2015-05-16 14:27:524120 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bnc4d782f492016-08-18 13:50:004121
4122 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:354123 NetLogWithSource(), nullptr);
[email protected]3caf5542010-07-16 15:19:474124 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574125 helper.AddData(&data);
bnc4d782f492016-08-18 13:50:004126 helper.StartDefaultTest();
4127 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
[email protected]f5ed21552010-05-04 18:39:544128
bnc4d782f492016-08-18 13:50:004129 helper.WaitForCallbackToComplete();
4130 EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED));
[email protected]3caf5542010-07-16 15:19:474131
bnc4d782f492016-08-18 13:50:004132 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:524133 EXPECT_TRUE(response->headers);
[email protected]f5ed21552010-05-04 18:39:544134 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]f5ed21552010-05-04 18:39:544135
4136 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474137 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:544138}
[email protected]58cebf8f2010-07-31 19:20:164139
bncfacdd852015-01-09 19:22:544140// Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4141// protocol negotiation happens, instead this test forces protocols for both
4142// sockets.
bncd16676a2016-07-20 16:23:014143TEST_F(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
bncfacdd852015-01-09 19:22:544144 HttpRequestInfo request;
4145 request.method = "GET";
bncb26024382016-06-29 02:39:454146 request.url = default_url_;
bncfacdd852015-01-09 19:22:544147 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
tfarina428341112016-09-22 13:38:204148 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
4149 NetLogWithSource(), nullptr);
bncfacdd852015-01-09 19:22:544150
4151 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
bncb26024382016-06-29 02:39:454152 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bncdf80d44fd2016-07-15 20:27:414153 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:154154 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414155 MockWrite writes0[] = {CreateMockWrite(req, 0)};
4156 SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway(
bncfacdd852015-01-09 19:22:544157 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
bncdf80d44fd2016-07-15 20:27:414158 MockRead reads0[] = {CreateMockRead(go_away, 1)};
rch08e3aa3e2015-05-16 14:27:524159 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4160 arraysize(writes0));
bncfacdd852015-01-09 19:22:544161
danakjaee3e1ec2016-04-16 00:23:184162 std::unique_ptr<SSLSocketDataProvider> ssl_provider0(
bncfacdd852015-01-09 19:22:544163 new SSLSocketDataProvider(ASYNC, OK));
4164 // Expect HTTP/2 protocols too in SSLConfig.
bnc06d22432015-06-29 12:39:434165 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
bnc3f0118e2016-02-02 15:42:224166 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
bncfacdd852015-01-09 19:22:544167 // Force SPDY.
bnc3cf2a592016-08-11 14:48:364168 ssl_provider0->next_proto = kProtoHTTP2;
dchengc7eeda422015-12-26 03:56:484169 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
bncfacdd852015-01-09 19:22:544170
4171 // Second socket: falling back to HTTP/1.1.
rch08e3aa3e2015-05-16 14:27:524172 MockWrite writes1[] = {MockWrite(ASYNC, 0,
4173 "GET / HTTP/1.1\r\n"
4174 "Host: www.example.org\r\n"
4175 "Connection: keep-alive\r\n\r\n")};
4176 MockRead reads1[] = {MockRead(ASYNC, 1,
4177 "HTTP/1.1 200 OK\r\n"
4178 "Content-Length: 5\r\n\r\n"
4179 "hello")};
4180 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4181 arraysize(writes1));
bncfacdd852015-01-09 19:22:544182
danakjaee3e1ec2016-04-16 00:23:184183 std::unique_ptr<SSLSocketDataProvider> ssl_provider1(
bncfacdd852015-01-09 19:22:544184 new SSLSocketDataProvider(ASYNC, OK));
4185 // Expect only HTTP/1.1 protocol in SSLConfig.
4186 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4187 // Force HTTP/1.1.
bnc3cf2a592016-08-11 14:48:364188 ssl_provider1->next_proto = kProtoHTTP11;
dchengc7eeda422015-12-26 03:56:484189 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
bncfacdd852015-01-09 19:22:544190
bnc525e175a2016-06-20 12:36:404191 HttpServerProperties* http_server_properties =
bncfacdd852015-01-09 19:22:544192 helper.session()->spdy_session_pool()->http_server_properties();
bncb26024382016-06-29 02:39:454193 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair_));
bncfacdd852015-01-09 19:22:544194
4195 helper.RunPreTestSetup();
4196 helper.StartDefaultTest();
4197 helper.FinishDefaultTestWithoutVerification();
4198 helper.VerifyDataConsumed();
bncb26024382016-06-29 02:39:454199 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair_));
bncfacdd852015-01-09 19:22:544200
4201 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:524202 ASSERT_TRUE(response);
4203 ASSERT_TRUE(response->headers);
bncfacdd852015-01-09 19:22:544204 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4205 EXPECT_FALSE(response->was_fetched_via_spdy);
mmenke8210acc2016-07-11 16:34:524206 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
4207 response->connection_info);
bnc94c92842016-09-21 15:22:524208 EXPECT_TRUE(response->was_alpn_negotiated);
bncfacdd852015-01-09 19:22:544209 EXPECT_TRUE(request.url.SchemeIs("https"));
4210 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4211 EXPECT_EQ(443, response->socket_address.port());
4212 std::string response_data;
robpercival214763f2016-07-01 23:27:014213 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
bncfacdd852015-01-09 19:22:544214 EXPECT_EQ("hello", response_data);
4215}
4216
4217// Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4218// proxy. Note that no actual protocol negotiation happens, instead this test
4219// forces protocols for both sockets.
bncd16676a2016-07-20 16:23:014220TEST_F(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
bncfacdd852015-01-09 19:22:544221 HttpRequestInfo request;
4222 request.method = "GET";
bncb26024382016-06-29 02:39:454223 request.url = default_url_;
bncd16676a2016-07-20 16:23:014224 auto session_deps = base::MakeUnique<SpdySessionDependencies>(
4225 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
bncfacdd852015-01-09 19:22:544226 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
tfarina428341112016-09-22 13:38:204227 NormalSpdyTransactionHelper helper(
4228 request, DEFAULT_PRIORITY, NetLogWithSource(), std::move(session_deps));
bncfacdd852015-01-09 19:22:544229
4230 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
bncdf80d44fd2016-07-15 20:27:414231 SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234232 nullptr, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
bncdf80d44fd2016-07-15 20:27:414233 MockWrite writes0[] = {CreateMockWrite(req, 0)};
4234 SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway(
bncfacdd852015-01-09 19:22:544235 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
bncdf80d44fd2016-07-15 20:27:414236 MockRead reads0[] = {CreateMockRead(go_away, 1)};
rch08e3aa3e2015-05-16 14:27:524237 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4238 arraysize(writes0));
bncfacdd852015-01-09 19:22:544239
danakjaee3e1ec2016-04-16 00:23:184240 std::unique_ptr<SSLSocketDataProvider> ssl_provider0(
bncfacdd852015-01-09 19:22:544241 new SSLSocketDataProvider(ASYNC, OK));
4242 // Expect HTTP/2 protocols too in SSLConfig.
bnc06d22432015-06-29 12:39:434243 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
bnc3f0118e2016-02-02 15:42:224244 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
bncfacdd852015-01-09 19:22:544245 // Force SPDY.
bnc3cf2a592016-08-11 14:48:364246 ssl_provider0->next_proto = kProtoHTTP2;
dchengc7eeda422015-12-26 03:56:484247 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
bncfacdd852015-01-09 19:22:544248
4249 // Second socket: retry using HTTP/1.1.
4250 MockWrite writes1[] = {
rch08e3aa3e2015-05-16 14:27:524251 MockWrite(ASYNC, 0,
bncce36dca22015-04-21 22:11:234252 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174253 "Host: www.example.org:443\r\n"
bncfacdd852015-01-09 19:22:544254 "Proxy-Connection: keep-alive\r\n\r\n"),
rch08e3aa3e2015-05-16 14:27:524255 MockWrite(ASYNC, 2,
bncfacdd852015-01-09 19:22:544256 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:234257 "Host: www.example.org\r\n"
bncfacdd852015-01-09 19:22:544258 "Connection: keep-alive\r\n\r\n"),
4259 };
4260
4261 MockRead reads1[] = {
rch08e3aa3e2015-05-16 14:27:524262 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4263 MockRead(ASYNC, 3,
bncfacdd852015-01-09 19:22:544264 "HTTP/1.1 200 OK\r\n"
4265 "Content-Length: 5\r\n\r\n"
4266 "hello"),
4267 };
rch08e3aa3e2015-05-16 14:27:524268 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4269 arraysize(writes1));
bncfacdd852015-01-09 19:22:544270
danakjaee3e1ec2016-04-16 00:23:184271 std::unique_ptr<SSLSocketDataProvider> ssl_provider1(
bncfacdd852015-01-09 19:22:544272 new SSLSocketDataProvider(ASYNC, OK));
4273 // Expect only HTTP/1.1 protocol in SSLConfig.
4274 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4275 // Force HTTP/1.1.
bnc3cf2a592016-08-11 14:48:364276 ssl_provider1->next_proto = kProtoHTTP11;
dchengc7eeda422015-12-26 03:56:484277 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
bncfacdd852015-01-09 19:22:544278
4279 // A third socket is needed for the tunnelled connection.
danakjaee3e1ec2016-04-16 00:23:184280 std::unique_ptr<SSLSocketDataProvider> ssl_provider2(
bncfacdd852015-01-09 19:22:544281 new SSLSocketDataProvider(ASYNC, OK));
4282 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4283 ssl_provider2.get());
4284
bnc525e175a2016-06-20 12:36:404285 HttpServerProperties* http_server_properties =
bncfacdd852015-01-09 19:22:544286 helper.session()->spdy_session_pool()->http_server_properties();
4287 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
4288 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4289
4290 helper.RunPreTestSetup();
4291 helper.StartDefaultTest();
4292 helper.FinishDefaultTestWithoutVerification();
4293 helper.VerifyDataConsumed();
4294 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4295
4296 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:524297 ASSERT_TRUE(response);
4298 ASSERT_TRUE(response->headers);
bncfacdd852015-01-09 19:22:544299 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4300 EXPECT_FALSE(response->was_fetched_via_spdy);
mmenke8210acc2016-07-11 16:34:524301 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
4302 response->connection_info);
bnc94c92842016-09-21 15:22:524303 EXPECT_FALSE(response->was_alpn_negotiated);
bncfacdd852015-01-09 19:22:544304 EXPECT_TRUE(request.url.SchemeIs("https"));
4305 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4306 EXPECT_EQ(70, response->socket_address.port());
4307 std::string response_data;
robpercival214763f2016-07-01 23:27:014308 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
bncfacdd852015-01-09 19:22:544309 EXPECT_EQ("hello", response_data);
4310}
4311
[email protected]b261d0e2010-08-02 19:13:244312// Test to make sure we can correctly connect through a proxy.
bncd16676a2016-07-20 16:23:014313TEST_F(SpdyNetworkTransactionTest, ProxyConnect) {
4314 auto session_deps = base::MakeUnique<SpdySessionDependencies>(
4315 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
[email protected]262eec82013-03-19 21:01:364316 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tfarina428341112016-09-22 13:38:204317 NetLogWithSource(),
4318 std::move(session_deps));
[email protected]b261d0e2010-08-02 19:13:244319 helper.RunPreTestSetup();
4320 HttpNetworkTransaction* trans = helper.trans();
4321
rchebf12982015-04-10 01:15:004322 const char kConnect443[] = {
bncce36dca22015-04-21 22:11:234323 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174324 "Host: www.example.org:443\r\n"
rchcb934f562015-04-07 16:25:124325 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244326 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
bncdf80d44fd2016-07-15 20:27:414327 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494328 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:354329 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414330 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244331
rchebf12982015-04-10 01:15:004332 MockWrite writes[] = {
4333 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
bncdf80d44fd2016-07-15 20:27:414334 CreateMockWrite(req, 2),
[email protected]b261d0e2010-08-02 19:13:244335 };
rchebf12982015-04-10 01:15:004336 MockRead reads[] = {
4337 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
bncdf80d44fd2016-07-15 20:27:414338 CreateMockRead(resp, 3), CreateMockRead(body, 4),
rchebf12982015-04-10 01:15:004339 MockRead(ASYNC, 0, 0, 5),
[email protected]b261d0e2010-08-02 19:13:244340 };
danakjaee3e1ec2016-04-16 00:23:184341 std::unique_ptr<SequencedSocketData> data(new SequencedSocketData(
rchebf12982015-04-10 01:15:004342 reads, arraysize(reads), writes, arraysize(writes)));
[email protected]b261d0e2010-08-02 19:13:244343
4344 helper.AddData(data.get());
[email protected]49639fa2011-12-20 23:22:414345 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244346
tfarina428341112016-09-22 13:38:204347 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
4348 NetLogWithSource());
robpercival214763f2016-07-01 23:27:014349 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b261d0e2010-08-02 19:13:244350
4351 rv = callback.WaitForResult();
4352 EXPECT_EQ(0, rv);
4353
bnc42331402016-07-25 13:36:154354 // Verify the response headers.
[email protected]b261d0e2010-08-02 19:13:244355 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524356 ASSERT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024357 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:244358
4359 std::string response_data;
robpercival214763f2016-07-01 23:27:014360 ASSERT_THAT(ReadTransaction(trans, &response_data), IsOk());
[email protected]b261d0e2010-08-02 19:13:244361 EXPECT_EQ("hello!", response_data);
4362 helper.VerifyDataConsumed();
4363}
4364
bncce36dca22015-04-21 22:11:234365// Test to make sure we can correctly connect through a proxy to
4366// www.example.org, if there already exists a direct spdy connection to
4367// www.example.org. See https://crbug.com/49874.
bncd16676a2016-07-20 16:23:014368TEST_F(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
[email protected]733b7a6d2010-08-25 01:38:434369 // Use a proxy service which returns a proxy fallback list from DIRECT to
4370 // myproxy:70. For this test there will be no fallback, so it is equivalent
4371 // to simply DIRECT. The reason for appending the second proxy is to verify
4372 // that the session pool key used does is just "DIRECT".
bncd16676a2016-07-20 16:23:014373 auto session_deps = base::MakeUnique<SpdySessionDependencies>(
rdsmith82957ad2015-09-16 19:42:034374 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70"));
bncd16676a2016-07-20 16:23:014375 // When setting up the first transaction, we store the SpdySessionPool so that
4376 // we can use the same pool in the second transaction.
4377 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tfarina428341112016-09-22 13:38:204378 NetLogWithSource(),
4379 std::move(session_deps));
[email protected]733b7a6d2010-08-25 01:38:434380
[email protected]87bfa3f2010-09-30 14:54:564381 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:244382 helper.RunPreTestSetup();
4383
4384 // Construct and send a simple GET request.
bncdf80d44fd2016-07-15 20:27:414385 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494386 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]b261d0e2010-08-02 19:13:244387 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414388 CreateMockWrite(req, 0),
[email protected]b261d0e2010-08-02 19:13:244389 };
4390
tombergan5d22c182017-01-11 02:05:354391 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414392 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244393 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414394 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:524395 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3), // Force a pause
[email protected]b261d0e2010-08-02 19:13:244396 };
rch08e3aa3e2015-05-16 14:27:524397 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574398 helper.AddData(&data);
[email protected]b261d0e2010-08-02 19:13:244399 HttpNetworkTransaction* trans = helper.trans();
4400
[email protected]49639fa2011-12-20 23:22:414401 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244402 TransactionHelperResult out;
tfarina428341112016-09-22 13:38:204403 out.rv = trans->Start(&CreateGetRequest(), callback.callback(),
4404 NetLogWithSource());
[email protected]b261d0e2010-08-02 19:13:244405
4406 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4407 out.rv = callback.WaitForResult();
4408 EXPECT_EQ(out.rv, OK);
4409
4410 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524411 EXPECT_TRUE(response->headers);
[email protected]b261d0e2010-08-02 19:13:244412 EXPECT_TRUE(response->was_fetched_via_spdy);
4413 out.rv = ReadTransaction(trans, &out.response_data);
robpercival214763f2016-07-01 23:27:014414 EXPECT_THAT(out.rv, IsOk());
[email protected]b261d0e2010-08-02 19:13:244415 out.status_line = response->headers->GetStatusLine();
bnc84e7fb52015-12-02 11:50:024416 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b261d0e2010-08-02 19:13:244417 EXPECT_EQ("hello!", out.response_data);
4418
4419 // Check that the SpdySession is still in the SpdySessionPool.
bncb26024382016-06-29 02:39:454420 SpdySessionKey session_pool_key_direct(host_port_pair_, ProxyServer::Direct(),
4421 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264422 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
[email protected]e6d017652013-05-17 18:01:404423 SpdySessionKey session_pool_key_proxy(
bncb26024382016-06-29 02:39:454424 host_port_pair_,
[email protected]e6d017652013-05-17 18:01:404425 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
[email protected]314b03992014-04-01 01:28:534426 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264427 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:244428
rdsmithebb50aa2015-11-12 03:44:384429 // New SpdyTestUtil instance for the session that will be used for the
4430 // proxy connection.
bncd16676a2016-07-20 16:23:014431 SpdyTestUtil spdy_util_2;
rdsmithebb50aa2015-11-12 03:44:384432
[email protected]b261d0e2010-08-02 19:13:244433 // Set up data for the proxy connection.
bncce36dca22015-04-21 22:11:234434 const char kConnect443[] = {
4435 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174436 "Host: www.example.org:443\r\n"
bncce36dca22015-04-21 22:11:234437 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244438 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
bncdf80d44fd2016-07-15 20:27:414439 SpdySerializedFrame req2(spdy_util_2.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:494440 GetDefaultUrlWithPath("/foo.dat").c_str(), 1, LOWEST));
tombergan5d22c182017-01-11 02:05:354441 SpdySerializedFrame resp2(spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414442 SpdySerializedFrame body2(spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244443
rchebf12982015-04-10 01:15:004444 MockWrite writes2[] = {
4445 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
bncdf80d44fd2016-07-15 20:27:414446 CreateMockWrite(req2, 2),
[email protected]b261d0e2010-08-02 19:13:244447 };
rchebf12982015-04-10 01:15:004448 MockRead reads2[] = {
4449 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
bncdf80d44fd2016-07-15 20:27:414450 CreateMockRead(resp2, 3), CreateMockRead(body2, 4),
rchebf12982015-04-10 01:15:004451 MockRead(ASYNC, 0, 5) // EOF
[email protected]b261d0e2010-08-02 19:13:244452 };
4453
danakjaee3e1ec2016-04-16 00:23:184454 std::unique_ptr<SequencedSocketData> data_proxy(new SequencedSocketData(
rchebf12982015-04-10 01:15:004455 reads2, arraysize(reads2), writes2, arraysize(writes2)));
[email protected]b261d0e2010-08-02 19:13:244456
bncce36dca22015-04-21 22:11:234457 // Create another request to www.example.org, but this time through a proxy.
[email protected]b261d0e2010-08-02 19:13:244458 HttpRequestInfo request_proxy;
4459 request_proxy.method = "GET";
rchebf12982015-04-10 01:15:004460 request_proxy.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
[email protected]b261d0e2010-08-02 19:13:244461 request_proxy.load_flags = 0;
bncd16676a2016-07-20 16:23:014462 auto session_deps_proxy = base::MakeUnique<SpdySessionDependencies>(
bnc301745a2015-03-10 03:22:164463 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
bncd16676a2016-07-20 16:23:014464 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
tfarina428341112016-09-22 13:38:204465 NetLogWithSource(),
bncd16676a2016-07-20 16:23:014466 std::move(session_deps_proxy));
[email protected]b261d0e2010-08-02 19:13:244467 helper_proxy.RunPreTestSetup();
4468 helper_proxy.AddData(data_proxy.get());
4469
4470 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
[email protected]49639fa2011-12-20 23:22:414471 TestCompletionCallback callback_proxy;
tfarina428341112016-09-22 13:38:204472 int rv = trans_proxy->Start(&request_proxy, callback_proxy.callback(),
4473 NetLogWithSource());
robpercival214763f2016-07-01 23:27:014474 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b261d0e2010-08-02 19:13:244475 rv = callback_proxy.WaitForResult();
4476 EXPECT_EQ(0, rv);
4477
4478 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
wezca1070932016-05-26 20:30:524479 ASSERT_TRUE(response_proxy.headers);
bnc84e7fb52015-12-02 11:50:024480 EXPECT_EQ("HTTP/1.1 200", response_proxy.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:244481
4482 std::string response_data;
robpercival214763f2016-07-01 23:27:014483 ASSERT_THAT(ReadTransaction(trans_proxy, &response_data), IsOk());
[email protected]b261d0e2010-08-02 19:13:244484 EXPECT_EQ("hello!", response_data);
4485
[email protected]b261d0e2010-08-02 19:13:244486 helper_proxy.VerifyDataConsumed();
4487}
4488
[email protected]58cebf8f2010-07-31 19:20:164489// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4490// on a new connection, if the connection was previously known to be good.
4491// This can happen when a server reboots without saying goodbye, or when
4492// we're behind a NAT that masked the RST.
bncd16676a2016-07-20 16:23:014493TEST_F(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
tombergan5d22c182017-01-11 02:05:354494 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414495 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]58cebf8f2010-07-31 19:20:164496 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414497 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch32320842015-05-16 15:57:094498 MockRead(ASYNC, ERR_IO_PENDING, 3),
4499 MockRead(ASYNC, ERR_CONNECTION_RESET, 4),
[email protected]58cebf8f2010-07-31 19:20:164500 };
4501
4502 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:414503 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch32320842015-05-16 15:57:094504 MockRead(ASYNC, 0, 3) // EOF
[email protected]58cebf8f2010-07-31 19:20:164505 };
4506
bncdf80d44fd2016-07-15 20:27:414507 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494508 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:384509 // In all cases the connection will be reset before req3 can be
4510 // dispatched, destroying both streams.
4511 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:414512 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:494513 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414514 MockWrite writes1[] = {CreateMockWrite(req, 0), CreateMockWrite(req3, 5)};
4515 MockWrite writes2[] = {CreateMockWrite(req, 0)};
rchacdcbdc2015-05-16 17:16:004516
[email protected]58cebf8f2010-07-31 19:20:164517 // This test has a couple of variants.
4518 enum {
4519 // Induce the RST while waiting for our transaction to send.
rchacdcbdc2015-05-16 17:16:004520 VARIANT_RST_DURING_SEND_COMPLETION = 0,
[email protected]58cebf8f2010-07-31 19:20:164521 // Induce the RST while waiting for our transaction to read.
4522 // In this case, the send completed - everything copied into the SNDBUF.
rchacdcbdc2015-05-16 17:16:004523 VARIANT_RST_DURING_READ_COMPLETION = 1
[email protected]58cebf8f2010-07-31 19:20:164524 };
4525
4526 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4527 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4528 ++variant) {
rchacdcbdc2015-05-16 17:16:004529 SequencedSocketData data1(reads, arraysize(reads), writes1, 1 + variant);
[email protected]58cebf8f2010-07-31 19:20:164530
rchacdcbdc2015-05-16 17:16:004531 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
4532 arraysize(writes2));
[email protected]58cebf8f2010-07-31 19:20:164533
[email protected]262eec82013-03-19 21:01:364534 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:354535 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:574536 helper.AddData(&data1);
4537 helper.AddData(&data2);
[email protected]58cebf8f2010-07-31 19:20:164538 helper.RunPreTestSetup();
4539
4540 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:164541 HttpNetworkTransaction trans(DEFAULT_PRIORITY, helper.session());
[email protected]58cebf8f2010-07-31 19:20:164542
[email protected]49639fa2011-12-20 23:22:414543 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:204544 int rv = trans.Start(&helper.request(), callback.callback(),
4545 NetLogWithSource());
robpercival214763f2016-07-01 23:27:014546 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]58cebf8f2010-07-31 19:20:164547 // On the second transaction, we trigger the RST.
4548 if (i == 1) {
4549 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4550 // Writes to the socket complete asynchronously on SPDY by running
4551 // through the message loop. Complete the write here.
[email protected]fc9d88472013-08-14 02:31:174552 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164553 }
4554
4555 // Now schedule the ERR_CONNECTION_RESET.
mmenkee24011922015-12-17 22:12:594556 data1.Resume();
[email protected]58cebf8f2010-07-31 19:20:164557 }
4558 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014559 EXPECT_THAT(rv, IsOk());
[email protected]58cebf8f2010-07-31 19:20:164560
bnc691fda62016-08-12 00:43:164561 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:524562 ASSERT_TRUE(response);
4563 EXPECT_TRUE(response->headers);
[email protected]58cebf8f2010-07-31 19:20:164564 EXPECT_TRUE(response->was_fetched_via_spdy);
4565 std::string response_data;
bnc691fda62016-08-12 00:43:164566 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014567 EXPECT_THAT(rv, IsOk());
bnc84e7fb52015-12-02 11:50:024568 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]58cebf8f2010-07-31 19:20:164569 EXPECT_EQ("hello!", response_data);
rchacdcbdc2015-05-16 17:16:004570 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164571 }
4572
4573 helper.VerifyDataConsumed();
rchacdcbdc2015-05-16 17:16:004574 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164575 }
4576}
[email protected]1f418ee2010-10-16 19:46:564577
[email protected]018aabc2010-10-29 16:16:594578// Tests that Basic authentication works over SPDY
bncd16676a2016-07-20 16:23:014579TEST_F(SpdyNetworkTransactionTest, SpdyBasicAuth) {
[email protected]018aabc2010-10-29 16:16:594580 // The first request will be a bare GET, the second request will be a
4581 // GET with an Authorization header.
bncdf80d44fd2016-07-15 20:27:414582 SpdySerializedFrame req_get(
bnc38dcd392016-02-09 23:19:494583 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:384584 // Will be refused for lack of auth.
4585 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]018aabc2010-10-29 16:16:594586 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464587 "authorization", "Basic Zm9vOmJhcg=="
[email protected]018aabc2010-10-29 16:16:594588 };
bncdf80d44fd2016-07-15 20:27:414589 SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
4590 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders) / 2, 3,
4591 LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594592 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:414593 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]018aabc2010-10-29 16:16:594594 };
4595
4596 // The first response is a 401 authentication challenge, and the second
4597 // response will be a 200 response since the second request includes a valid
4598 // Authorization header.
4599 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:264600 "www-authenticate",
[email protected]018aabc2010-10-29 16:16:594601 "Basic realm=\"MyRealm\""
4602 };
bnc42331402016-07-25 13:36:154603 SpdySerializedFrame resp_authentication(spdy_util_.ConstructSpdyReplyError(
bncc9f762a2016-12-06 20:38:234604 "401", kExtraAuthenticationHeaders,
bncdf80d44fd2016-07-15 20:27:414605 arraysize(kExtraAuthenticationHeaders) / 2, 1));
4606 SpdySerializedFrame body_authentication(
4607 spdy_util_.ConstructSpdyDataFrame(1, true));
tombergan5d22c182017-01-11 02:05:354608 SpdySerializedFrame resp_data(
4609 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
bncdf80d44fd2016-07-15 20:27:414610 SpdySerializedFrame body_data(spdy_util_.ConstructSpdyDataFrame(3, true));
tombergan5d22c182017-01-11 02:05:354611
[email protected]018aabc2010-10-29 16:16:594612 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414613 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:464614 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:414615 CreateMockRead(resp_data, 4),
4616 CreateMockRead(body_data, 5),
rch08e3aa3e2015-05-16 14:27:524617 MockRead(ASYNC, 0, 6),
[email protected]018aabc2010-10-29 16:16:594618 };
4619
rch08e3aa3e2015-05-16 14:27:524620 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4621 arraysize(spdy_writes));
[email protected]018aabc2010-10-29 16:16:594622 HttpRequestInfo request(CreateGetRequest());
tfarina428341112016-09-22 13:38:204623 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:354624 NetLogWithSource(), nullptr);
[email protected]018aabc2010-10-29 16:16:594625
4626 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574627 helper.AddData(&data);
bnc4d782f492016-08-18 13:50:004628 helper.StartDefaultTest();
4629 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
4630
4631 helper.WaitForCallbackToComplete();
4632 EXPECT_THAT(helper.output().rv, IsOk());
[email protected]018aabc2010-10-29 16:16:594633
4634 // Make sure the response has an auth challenge.
bnc4d782f492016-08-18 13:50:004635 HttpNetworkTransaction* trans = helper.trans();
[email protected]018aabc2010-10-29 16:16:594636 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524637 ASSERT_TRUE(response_start);
4638 ASSERT_TRUE(response_start->headers);
[email protected]018aabc2010-10-29 16:16:594639 EXPECT_EQ(401, response_start->headers->response_code());
4640 EXPECT_TRUE(response_start->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044641 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
wezca1070932016-05-26 20:30:524642 ASSERT_TRUE(auth_challenge);
[email protected]79cb5c12011-09-12 13:12:044643 EXPECT_FALSE(auth_challenge->is_proxy);
aberentbba302d2015-12-03 10:20:194644 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:044645 EXPECT_EQ("MyRealm", auth_challenge->realm);
[email protected]018aabc2010-10-29 16:16:594646
4647 // Restart with a username/password.
[email protected]ad65a3e2013-12-25 18:18:014648 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
4649 base::ASCIIToUTF16("bar"));
[email protected]49639fa2011-12-20 23:22:414650 TestCompletionCallback callback_restart;
4651 const int rv_restart = trans->RestartWithAuth(
4652 credentials, callback_restart.callback());
robpercival214763f2016-07-01 23:27:014653 EXPECT_THAT(rv_restart, IsError(ERR_IO_PENDING));
[email protected]018aabc2010-10-29 16:16:594654 const int rv_restart_complete = callback_restart.WaitForResult();
robpercival214763f2016-07-01 23:27:014655 EXPECT_THAT(rv_restart_complete, IsOk());
[email protected]018aabc2010-10-29 16:16:594656 // TODO(cbentzel): This is actually the same response object as before, but
4657 // data has changed.
4658 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524659 ASSERT_TRUE(response_restart);
4660 ASSERT_TRUE(response_restart->headers);
[email protected]018aabc2010-10-29 16:16:594661 EXPECT_EQ(200, response_restart->headers->response_code());
tombergan5d22c182017-01-11 02:05:354662 EXPECT_TRUE(response_restart->auth_challenge.get() == nullptr);
[email protected]018aabc2010-10-29 16:16:594663}
4664
bncd16676a2016-07-20 16:23:014665TEST_F(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
bncdf80d44fd2016-07-15 20:27:414666 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494667 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:354668 SpdySerializedFrame stream2_priority(
4669 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]d08358502010-12-03 22:04:034670 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:354671 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_priority, 3),
[email protected]d08358502010-12-03 22:04:034672 };
4673
bncdf80d44fd2016-07-15 20:27:414674 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154675 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc38dcd392016-02-09 23:19:494676
bnc086b39e12016-06-24 13:05:264677 SpdyHeaderBlock initial_headers;
rchebf12982015-04-10 01:15:004678 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
bnc086b39e12016-06-24 13:05:264679 &initial_headers);
bncdf80d44fd2016-07-15 20:27:414680 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4681 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:044682
bnc38dcd392016-02-09 23:19:494683 SpdyHeaderBlock late_headers;
4684 late_headers[spdy_util_.GetStatusKey()] = "200";
bnc38dcd392016-02-09 23:19:494685 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414686 SpdySerializedFrame stream2_headers(spdy_util_.ConstructSpdyResponseHeaders(
4687 2, std::move(late_headers), false));
[email protected]d08358502010-12-03 22:04:034688
bncdf80d44fd2016-07-15 20:27:414689 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc38dcd392016-02-09 23:19:494690
[email protected]8a0fc822013-06-27 20:52:434691 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414692 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
4693 2, kPushedData, strlen(kPushedData), true));
bnc38dcd392016-02-09 23:19:494694
[email protected]d08358502010-12-03 22:04:034695 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414696 CreateMockRead(stream1_reply, 1),
4697 CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:354698 CreateMockRead(stream2_headers, 4),
4699 CreateMockRead(stream1_body, 5, SYNCHRONOUS),
4700 CreateMockRead(stream2_body, 6),
4701 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7), // Force a pause
[email protected]d08358502010-12-03 22:04:034702 };
4703
4704 HttpResponseInfo response;
4705 HttpResponseInfo response2;
4706 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:524707 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574708 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:034709 &response,
4710 &response2,
4711 expected_push_result);
4712
bnc42331402016-07-25 13:36:154713 // Verify the response headers.
wezca1070932016-05-26 20:30:524714 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024715 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034716
4717 // Verify the pushed stream.
wezca1070932016-05-26 20:30:524718 EXPECT_TRUE(response2.headers);
bnc84e7fb52015-12-02 11:50:024719 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034720}
4721
bncd16676a2016-07-20 16:23:014722TEST_F(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
[email protected]d08358502010-12-03 22:04:034723 // We push a stream and attempt to claim it before the headers come down.
bncdf80d44fd2016-07-15 20:27:414724 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494725 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:354726 SpdySerializedFrame stream2_priority(
4727 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]d08358502010-12-03 22:04:034728 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414729 CreateMockWrite(stream1_syn, 0, SYNCHRONOUS),
tombergan5d22c182017-01-11 02:05:354730 CreateMockWrite(stream2_priority, 3),
[email protected]d08358502010-12-03 22:04:034731 };
4732
bncdf80d44fd2016-07-15 20:27:414733 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154734 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc086b39e12016-06-24 13:05:264735 SpdyHeaderBlock initial_headers;
rchebf12982015-04-10 01:15:004736 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
bnc086b39e12016-06-24 13:05:264737 &initial_headers);
bncdf80d44fd2016-07-15 20:27:414738 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4739 std::move(initial_headers), 2, 1));
4740 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc38dcd392016-02-09 23:19:494741 SpdyHeaderBlock late_headers;
4742 late_headers[spdy_util_.GetStatusKey()] = "200";
bnc38dcd392016-02-09 23:19:494743 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414744 SpdySerializedFrame stream2_headers(spdy_util_.ConstructSpdyResponseHeaders(
4745 2, std::move(late_headers), false));
[email protected]8a0fc822013-06-27 20:52:434746 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414747 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
4748 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:034749 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414750 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
tombergan5d22c182017-01-11 02:05:354751 CreateMockRead(stream1_body, 4), MockRead(ASYNC, ERR_IO_PENDING, 5),
4752 CreateMockRead(stream2_headers, 6), CreateMockRead(stream2_body, 7),
4753 MockRead(ASYNC, ERR_IO_PENDING, 8), MockRead(ASYNC, 0, 9), // EOF
[email protected]d08358502010-12-03 22:04:034754 };
4755
4756 HttpResponseInfo response;
4757 HttpResponseInfo response2;
4758 std::string expected_push_result("pushed");
mmenke666a6fea2015-12-19 04:16:334759 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:034760
[email protected]262eec82013-03-19 21:01:364761 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:354762 NetLogWithSource(), nullptr);
mmenke666a6fea2015-12-19 04:16:334763 helper.AddData(&data);
[email protected]d08358502010-12-03 22:04:034764 helper.RunPreTestSetup();
4765
4766 HttpNetworkTransaction* trans = helper.trans();
4767
[email protected]d08358502010-12-03 22:04:034768 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:414769 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:204770 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
4771 NetLogWithSource());
robpercival214763f2016-07-01 23:27:014772 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bnc42331402016-07-25 13:36:154773 // Run until we've received the primary HEADERS, the pushed HEADERS,
mmenke666a6fea2015-12-19 04:16:334774 // and the body of the primary stream, but before we've received the HEADERS
4775 // for the pushed stream.
4776 data.RunUntilPaused();
robpercival214763f2016-07-01 23:27:014777 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d08358502010-12-03 22:04:034778
4779 // Request the pushed path. At this point, we've received the push, but the
4780 // headers are not yet complete.
bnc691fda62016-08-12 00:43:164781 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
tfarina428341112016-09-22 13:38:204782 rv = trans2.Start(&CreateGetPushRequest(), callback.callback(),
4783 NetLogWithSource());
robpercival214763f2016-07-01 23:27:014784 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
mmenke666a6fea2015-12-19 04:16:334785 data.Resume();
4786 data.RunUntilPaused();
[email protected]fc9d88472013-08-14 02:31:174787 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:034788
4789 // Read the server push body.
4790 std::string result2;
bnc691fda62016-08-12 00:43:164791 ReadResult(&trans2, &result2);
[email protected]d08358502010-12-03 22:04:034792 // Read the response body.
4793 std::string result;
rch0aecfd82015-05-19 17:22:324794 ReadResult(trans, &result);
[email protected]d08358502010-12-03 22:04:034795
[email protected]d08358502010-12-03 22:04:034796 // Verify that the received push data is same as the expected push data.
4797 EXPECT_EQ(result2.compare(expected_push_result), 0)
4798 << "Received data: "
4799 << result2
4800 << "||||| Expected data: "
4801 << expected_push_result;
4802
bnc42331402016-07-25 13:36:154803 // Verify the response headers.
[email protected]d08358502010-12-03 22:04:034804 // Copy the response info, because trans goes away.
4805 response = *trans->GetResponseInfo();
bnc691fda62016-08-12 00:43:164806 response2 = *trans2.GetResponseInfo();
[email protected]d08358502010-12-03 22:04:034807
4808 VerifyStreamsClosed(helper);
4809
bnc42331402016-07-25 13:36:154810 // Verify the response headers.
wezca1070932016-05-26 20:30:524811 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024812 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034813
4814 // Verify the pushed stream.
wezca1070932016-05-26 20:30:524815 EXPECT_TRUE(response2.headers);
bnc84e7fb52015-12-02 11:50:024816 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d55b30a2012-07-21 00:35:394817
4818 // Read the final EOF (which will close the session)
mmenke666a6fea2015-12-19 04:16:334819 data.Resume();
4820 base::RunLoop().RunUntilIdle();
[email protected]d55b30a2012-07-21 00:35:394821
4822 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:174823 EXPECT_TRUE(data.AllReadDataConsumed());
4824 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:034825}
4826
bnc42331402016-07-25 13:36:154827TEST_F(SpdyNetworkTransactionTest, ResponseHeadersTwice) {
bncdf80d44fd2016-07-15 20:27:414828 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494829 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414830 SpdySerializedFrame rst(
[email protected]b771bb72013-06-24 09:55:414831 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
4832 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414833 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
[email protected]745aa9c2014-06-27 02:21:294834 };
[email protected]d08358502010-12-03 22:04:034835
bncdf80d44fd2016-07-15 20:27:414836 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:354837 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]513963e2013-06-15 01:53:044838
bnc38dcd392016-02-09 23:19:494839 SpdyHeaderBlock late_headers;
4840 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414841 SpdySerializedFrame stream1_headers(spdy_util_.ConstructSpdyResponseHeaders(
4842 1, std::move(late_headers), false));
4843 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d08358502010-12-03 22:04:034844 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414845 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_headers, 2),
4846 CreateMockRead(stream1_body, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]d08358502010-12-03 22:04:034847 };
4848
rch08e3aa3e2015-05-16 14:27:524849 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364850 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:354851 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:574852 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:034853 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014854 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d08358502010-12-03 22:04:034855}
4856
xunjieli294da722015-08-11 19:15:024857// Tests that receiving HEADERS, DATA, HEADERS, and DATA in that sequence will
4858// trigger a ERR_SPDY_PROTOCOL_ERROR because trailing HEADERS must not be
4859// followed by any DATA frames.
bncd16676a2016-07-20 16:23:014860TEST_F(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) {
bncdf80d44fd2016-07-15 20:27:414861 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494862 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414863 SpdySerializedFrame rst(
[email protected]b771bb72013-06-24 09:55:414864 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
4865 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414866 CreateMockWrite(req, 0), CreateMockWrite(rst, 5),
[email protected]b771bb72013-06-24 09:55:414867 };
[email protected]d08358502010-12-03 22:04:034868
bncdf80d44fd2016-07-15 20:27:414869 SpdySerializedFrame stream1_reply(
tombergan5d22c182017-01-11 02:05:354870 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414871 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, false));
bnc38dcd392016-02-09 23:19:494872
4873 SpdyHeaderBlock late_headers;
4874 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414875 SpdySerializedFrame stream1_headers(spdy_util_.ConstructSpdyResponseHeaders(
4876 1, std::move(late_headers), false));
4877 SpdySerializedFrame stream1_body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d08358502010-12-03 22:04:034878 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414879 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_body, 2),
4880 CreateMockRead(stream1_headers, 3), CreateMockRead(stream1_body2, 4),
rch08e3aa3e2015-05-16 14:27:524881 MockRead(ASYNC, 0, 6) // EOF
[email protected]d08358502010-12-03 22:04:034882 };
4883
rch32320842015-05-16 15:57:094884 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364885 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:354886 NetLogWithSource(), nullptr);
[email protected]dd54bd82012-07-19 23:44:574887 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:034888 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014889 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d08358502010-12-03 22:04:034890}
4891
bncd16676a2016-07-20 16:23:014892TEST_F(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
[email protected]a7a265ef2010-12-08 18:05:574893 // In this test we want to verify that we can't accidentally push content
4894 // which can't be pushed by this content server.
4895 // This test assumes that:
4896 // - if we're requesting http://www.foo.com/barbaz
4897 // - the browser has made a connection to "www.foo.com".
4898
4899 // A list of the URL to fetch, followed by the URL being pushed.
4900 static const char* const kTestCases[] = {
bncce36dca22015-04-21 22:11:234901 "https://www.example.org/foo.html",
bncce36dca22015-04-21 22:11:234902 "http://www.example.org/foo.js", // Bad protocol
[email protected]a7a265ef2010-12-08 18:05:574903
bncce36dca22015-04-21 22:11:234904 "https://www.example.org/foo.html",
4905 "ftp://www.example.org/foo.js", // Invalid Protocol
[email protected]a7a265ef2010-12-08 18:05:574906
bncce36dca22015-04-21 22:11:234907 "https://www.example.org/foo.html",
4908 "https://blat.www.example.org/foo.js", // Cross subdomain
[email protected]a7a265ef2010-12-08 18:05:574909
bncce36dca22015-04-21 22:11:234910 "https://www.example.org/foo.html",
rchebf12982015-04-10 01:15:004911 "https://www.foo.com/foo.js", // Cross domain
[email protected]a7a265ef2010-12-08 18:05:574912 };
4913
[email protected]b3f899332010-12-08 18:20:444914 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
[email protected]a7a265ef2010-12-08 18:05:574915 const char* url_to_fetch = kTestCases[index];
4916 const char* url_to_push = kTestCases[index + 1];
4917
bncd16676a2016-07-20 16:23:014918 SpdyTestUtil spdy_test_util;
bncdf80d44fd2016-07-15 20:27:414919 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494920 spdy_test_util.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414921 SpdySerializedFrame stream1_body(
4922 spdy_test_util.ConstructSpdyDataFrame(1, true));
4923 SpdySerializedFrame push_rst(
bnc38dcd392016-02-09 23:19:494924 spdy_test_util.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]a7a265ef2010-12-08 18:05:574925 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414926 CreateMockWrite(stream1_syn, 0), CreateMockWrite(push_rst, 3),
[email protected]a7a265ef2010-12-08 18:05:574927 };
4928
bncdf80d44fd2016-07-15 20:27:414929 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154930 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414931 SpdySerializedFrame stream2_syn(
bnc38dcd392016-02-09 23:19:494932 spdy_test_util.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
[email protected]8a0fc822013-06-27 20:52:434933 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414934 SpdySerializedFrame stream2_body(spdy_test_util.ConstructSpdyDataFrame(
4935 2, kPushedData, strlen(kPushedData), true));
4936 SpdySerializedFrame rst(
bnc38dcd392016-02-09 23:19:494937 spdy_test_util.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]a7a265ef2010-12-08 18:05:574938
4939 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414940 CreateMockRead(stream1_reply, 1),
4941 CreateMockRead(stream2_syn, 2),
4942 CreateMockRead(stream1_body, 4),
4943 CreateMockRead(stream2_body, 5),
rch08e3aa3e2015-05-16 14:27:524944 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]a7a265ef2010-12-08 18:05:574945 };
4946
4947 HttpResponseInfo response;
rch08e3aa3e2015-05-16 14:27:524948 SequencedSocketData data(reads, arraysize(reads), writes,
4949 arraysize(writes));
[email protected]a7a265ef2010-12-08 18:05:574950
4951 HttpRequestInfo request;
4952 request.method = "GET";
4953 request.url = GURL(url_to_fetch);
4954 request.load_flags = 0;
[email protected]a7a265ef2010-12-08 18:05:574955
[email protected]7c6f7ba2012-04-03 04:09:294956 // Enable cross-origin push. Since we are not using a proxy, this should
4957 // not actually enable cross-origin SPDY push.
bncd16676a2016-07-20 16:23:014958 auto session_deps = base::MakeUnique<SpdySessionDependencies>();
danakjaee3e1ec2016-04-16 00:23:184959 std::unique_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
tbansal28e68f82016-02-04 02:56:154960 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
4961 "https://123.45.67.89:443", net::ProxyServer::SCHEME_HTTP));
inlinechan894515af2016-12-09 02:40:104962 session_deps->proxy_delegate = std::move(proxy_delegate);
tfarina428341112016-09-22 13:38:204963 NormalSpdyTransactionHelper helper(
4964 request, DEFAULT_PRIORITY, NetLogWithSource(), std::move(session_deps));
[email protected]61b4efc2012-04-27 18:12:504965 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574966 helper.AddData(&data);
[email protected]7c6f7ba2012-04-03 04:09:294967
[email protected]a7a265ef2010-12-08 18:05:574968 HttpNetworkTransaction* trans = helper.trans();
4969
4970 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:414971 TestCompletionCallback callback;
[email protected]a7a265ef2010-12-08 18:05:574972
tfarina428341112016-09-22 13:38:204973 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014974 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a7a265ef2010-12-08 18:05:574975 rv = callback.WaitForResult();
4976
bnceb9aa7112017-01-05 01:03:464977 // Finish async network reads/writes.
4978 base::RunLoop().RunUntilIdle();
4979
[email protected]a7a265ef2010-12-08 18:05:574980 // Read the response body.
4981 std::string result;
rch0aecfd82015-05-19 17:22:324982 ReadResult(trans, &result);
[email protected]a7a265ef2010-12-08 18:05:574983
4984 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:174985 EXPECT_TRUE(data.AllReadDataConsumed());
4986 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]a7a265ef2010-12-08 18:05:574987
bnc42331402016-07-25 13:36:154988 // Verify the response headers.
[email protected]a7a265ef2010-12-08 18:05:574989 // Copy the response info, because trans goes away.
4990 response = *trans->GetResponseInfo();
4991
4992 VerifyStreamsClosed(helper);
4993
bnc42331402016-07-25 13:36:154994 // Verify the response headers.
wezca1070932016-05-26 20:30:524995 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024996 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]a7a265ef2010-12-08 18:05:574997 }
4998}
4999
bnc3e79387f2016-03-15 14:49:205000// Verify that push works cross origin as long as the certificate is valid for
5001// the pushed authority.
bncd16676a2016-07-20 16:23:015002TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOrigin) {
bnc3e79387f2016-03-15 14:49:205003 // "spdy_pooling.pem" is valid for both www.example.org and mail.example.org.
5004 const char* url_to_fetch = "https://www.example.org";
5005 const char* url_to_push = "https://mail.example.org";
5006
bncdf80d44fd2016-07-15 20:27:415007 SpdySerializedFrame headers(
bnc3e79387f2016-03-15 14:49:205008 spdy_util_.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
tombergan5d22c182017-01-11 02:05:355009 SpdySerializedFrame push_priority(
5010 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
bnc3e79387f2016-03-15 14:49:205011 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:355012 CreateMockWrite(headers, 0), CreateMockWrite(push_priority, 3),
bnc3e79387f2016-03-15 14:49:205013 };
5014
bnc42331402016-07-25 13:36:155015 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:415016 SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:205017 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
bncdf80d44fd2016-07-15 20:27:415018 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc3e79387f2016-03-15 14:49:205019 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:415020 SpdySerializedFrame pushed_body(spdy_util_.ConstructSpdyDataFrame(
5021 2, kPushedData, strlen(kPushedData), true));
bnc3e79387f2016-03-15 14:49:205022 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415023 CreateMockRead(reply, 1),
bnceb9aa7112017-01-05 01:03:465024 CreateMockRead(push, 2, SYNCHRONOUS),
tombergan5d22c182017-01-11 02:05:355025 CreateMockRead(body, 4),
5026 CreateMockRead(pushed_body, 5, SYNCHRONOUS),
5027 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
bnc3e79387f2016-03-15 14:49:205028 };
5029
5030 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
5031
5032 HttpRequestInfo request;
5033 request.method = "GET";
5034 request.url = GURL(url_to_fetch);
5035 request.load_flags = 0;
5036
tfarina428341112016-09-22 13:38:205037 NetLogWithSource log;
bncd16676a2016-07-20 16:23:015038 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, log, nullptr);
bnc3e79387f2016-03-15 14:49:205039 helper.RunPreTestSetup();
5040 helper.AddData(&data);
5041
5042 HttpNetworkTransaction* trans0 = helper.trans();
5043 TestCompletionCallback callback0;
5044 int rv = trans0->Start(&request, callback0.callback(), log);
5045 rv = callback0.GetResult(rv);
robpercival214763f2016-07-01 23:27:015046 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205047
5048 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
bncb26024382016-06-29 02:39:455049 SpdySessionKey key(host_port_pair_, ProxyServer::Direct(),
bnc3e79387f2016-03-15 14:49:205050 PRIVACY_MODE_DISABLED);
5051 base::WeakPtr<SpdySession> spdy_session =
5052 spdy_session_pool->FindAvailableSession(key, GURL(), log);
5053
5054 EXPECT_FALSE(spdy_session->unclaimed_pushed_streams_.empty());
5055 EXPECT_EQ(1u, spdy_session->unclaimed_pushed_streams_.size());
5056 EXPECT_EQ(1u,
5057 spdy_session->unclaimed_pushed_streams_.count(GURL(url_to_push)));
5058
bnc691fda62016-08-12 00:43:165059 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:205060 HttpRequestInfo push_request;
5061 push_request.method = "GET";
5062 push_request.url = GURL(url_to_push);
5063 push_request.load_flags = 0;
5064 TestCompletionCallback callback1;
bnc691fda62016-08-12 00:43:165065 rv = trans1.Start(&push_request, callback1.callback(), log);
bnc3e79387f2016-03-15 14:49:205066 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:015067 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205068
5069 EXPECT_TRUE(spdy_session->unclaimed_pushed_streams_.empty());
5070 EXPECT_EQ(0u, spdy_session->unclaimed_pushed_streams_.size());
5071
bnc3e79387f2016-03-15 14:49:205072 HttpResponseInfo response = *trans0->GetResponseInfo();
wezca1070932016-05-26 20:30:525073 EXPECT_TRUE(response.headers);
bnc3e79387f2016-03-15 14:49:205074 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
5075
5076 std::string result0;
5077 ReadResult(trans0, &result0);
5078 EXPECT_EQ("hello!", result0);
5079
bnc691fda62016-08-12 00:43:165080 HttpResponseInfo push_response = *trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:525081 EXPECT_TRUE(push_response.headers);
bnc3e79387f2016-03-15 14:49:205082 EXPECT_EQ("HTTP/1.1 200", push_response.headers->GetStatusLine());
5083
5084 std::string result1;
bnc691fda62016-08-12 00:43:165085 ReadResult(&trans1, &result1);
bnc3e79387f2016-03-15 14:49:205086 EXPECT_EQ(kPushedData, result1);
tombergan5d22c182017-01-11 02:05:355087
5088 base::RunLoop().RunUntilIdle();
5089 helper.VerifyDataConsumed();
5090 VerifyStreamsClosed(helper);
bnc3e79387f2016-03-15 14:49:205091}
5092
5093// Verify that push works cross origin, even if there is already a connection
5094// open to origin of pushed resource.
bncd16676a2016-07-20 16:23:015095TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOriginWithOpenSession) {
bnc3e79387f2016-03-15 14:49:205096 const char* url_to_fetch0 = "https://mail.example.org/foo";
5097 const char* url_to_fetch1 = "https://docs.example.org";
5098 const char* url_to_push = "https://mail.example.org/bar";
5099
bncd16676a2016-07-20 16:23:015100 SpdyTestUtil spdy_util_0;
bnc3e79387f2016-03-15 14:49:205101
bncdf80d44fd2016-07-15 20:27:415102 SpdySerializedFrame headers0(
bnc3e79387f2016-03-15 14:49:205103 spdy_util_0.ConstructSpdyGet(url_to_fetch0, 1, LOWEST));
5104 MockWrite writes0[] = {
bncdf80d44fd2016-07-15 20:27:415105 CreateMockWrite(headers0, 0),
bnc3e79387f2016-03-15 14:49:205106 };
5107
bnc42331402016-07-25 13:36:155108 SpdySerializedFrame reply0(spdy_util_0.ConstructSpdyGetReply(nullptr, 0, 1));
bnc3e79387f2016-03-15 14:49:205109 const char kData0[] = "first";
bncdf80d44fd2016-07-15 20:27:415110 SpdySerializedFrame body0(
5111 spdy_util_0.ConstructSpdyDataFrame(1, kData0, strlen(kData0), true));
5112 MockRead reads0[] = {CreateMockRead(reply0, 1), CreateMockRead(body0, 2),
5113 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
bnc3e79387f2016-03-15 14:49:205114
5115 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
5116 arraysize(writes0));
5117
bncd16676a2016-07-20 16:23:015118 SpdyTestUtil spdy_util_1;
bnc3e79387f2016-03-15 14:49:205119
bncdf80d44fd2016-07-15 20:27:415120 SpdySerializedFrame headers1(
bnc3e79387f2016-03-15 14:49:205121 spdy_util_1.ConstructSpdyGet(url_to_fetch1, 1, LOWEST));
tombergan5d22c182017-01-11 02:05:355122 SpdySerializedFrame push_priority(
5123 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
bnc3e79387f2016-03-15 14:49:205124 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:415125 CreateMockWrite(headers1, 0),
tombergan5d22c182017-01-11 02:05:355126 CreateMockWrite(push_priority, 3, SYNCHRONOUS),
bnc3e79387f2016-03-15 14:49:205127 };
5128
bnc42331402016-07-25 13:36:155129 SpdySerializedFrame reply1(spdy_util_1.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:415130 SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:205131 spdy_util_1.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
5132 const char kData1[] = "second";
bncdf80d44fd2016-07-15 20:27:415133 SpdySerializedFrame body1(
5134 spdy_util_1.ConstructSpdyDataFrame(1, kData1, strlen(kData1), true));
bnc3e79387f2016-03-15 14:49:205135 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:415136 SpdySerializedFrame pushed_body(spdy_util_1.ConstructSpdyDataFrame(
5137 2, kPushedData, strlen(kPushedData), true));
bnc3e79387f2016-03-15 14:49:205138
5139 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:415140 CreateMockRead(reply1, 1),
bnceb9aa7112017-01-05 01:03:465141 CreateMockRead(push, 2, SYNCHRONOUS),
tombergan5d22c182017-01-11 02:05:355142 CreateMockRead(body1, 4),
5143 CreateMockRead(pushed_body, 5, SYNCHRONOUS),
5144 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
bnc3e79387f2016-03-15 14:49:205145 };
5146
5147 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
5148 arraysize(writes1));
5149
5150 // Request |url_to_fetch0| to open connection to mail.example.org.
5151 HttpRequestInfo request0;
5152 request0.method = "GET";
5153 request0.url = GURL(url_to_fetch0);
5154 request0.load_flags = 0;
5155
tfarina428341112016-09-22 13:38:205156 NetLogWithSource log;
bncd16676a2016-07-20 16:23:015157 NormalSpdyTransactionHelper helper(request0, DEFAULT_PRIORITY, log, nullptr);
bnc3e79387f2016-03-15 14:49:205158 helper.RunPreTestSetup();
5159
5160 // "spdy_pooling.pem" is valid for www.example.org, but not for
5161 // docs.example.org.
danakjaee3e1ec2016-04-16 00:23:185162 std::unique_ptr<SSLSocketDataProvider> ssl_provider0(
bnc3e79387f2016-03-15 14:49:205163 new SSLSocketDataProvider(ASYNC, OK));
5164 ssl_provider0->cert =
5165 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
5166 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
5167
5168 // "wildcard.pem" is valid for both www.example.org and docs.example.org.
danakjaee3e1ec2016-04-16 00:23:185169 std::unique_ptr<SSLSocketDataProvider> ssl_provider1(
bnc3e79387f2016-03-15 14:49:205170 new SSLSocketDataProvider(ASYNC, OK));
5171 ssl_provider1->cert =
5172 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
5173 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
5174
5175 HttpNetworkTransaction* trans0 = helper.trans();
5176 TestCompletionCallback callback0;
5177 int rv = trans0->Start(&request0, callback0.callback(), log);
5178 rv = callback0.GetResult(rv);
robpercival214763f2016-07-01 23:27:015179 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205180
5181 // Request |url_to_fetch1|, during which docs.example.org pushes
5182 // |url_to_push|, which happens to be for www.example.org, to which there is
5183 // already an open connection.
bnc691fda62016-08-12 00:43:165184 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:205185 HttpRequestInfo request1;
5186 request1.method = "GET";
5187 request1.url = GURL(url_to_fetch1);
5188 request1.load_flags = 0;
5189 TestCompletionCallback callback1;
bnc691fda62016-08-12 00:43:165190 rv = trans1.Start(&request1, callback1.callback(), log);
bnc3e79387f2016-03-15 14:49:205191 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:015192 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205193
5194 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5195 HostPortPair host_port_pair0("mail.example.org", 443);
5196 SpdySessionKey key0(host_port_pair0, ProxyServer::Direct(),
5197 PRIVACY_MODE_DISABLED);
5198 base::WeakPtr<SpdySession> spdy_session0 =
5199 spdy_session_pool->FindAvailableSession(key0, GURL(), log);
5200
5201 EXPECT_TRUE(spdy_session0->unclaimed_pushed_streams_.empty());
5202 EXPECT_EQ(0u, spdy_session0->unclaimed_pushed_streams_.size());
5203
5204 HostPortPair host_port_pair1("docs.example.org", 443);
5205 SpdySessionKey key1(host_port_pair1, ProxyServer::Direct(),
5206 PRIVACY_MODE_DISABLED);
5207 base::WeakPtr<SpdySession> spdy_session1 =
5208 spdy_session_pool->FindAvailableSession(key1, GURL(), log);
5209
5210 EXPECT_FALSE(spdy_session1->unclaimed_pushed_streams_.empty());
5211 EXPECT_EQ(1u, spdy_session1->unclaimed_pushed_streams_.size());
5212 EXPECT_EQ(1u,
5213 spdy_session1->unclaimed_pushed_streams_.count(GURL(url_to_push)));
5214
5215 // Request |url_to_push|, which should be served from the pushed resource.
bnc691fda62016-08-12 00:43:165216 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:205217 HttpRequestInfo push_request;
5218 push_request.method = "GET";
5219 push_request.url = GURL(url_to_push);
5220 push_request.load_flags = 0;
5221 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:165222 rv = trans2.Start(&push_request, callback2.callback(), log);
bnc3e79387f2016-03-15 14:49:205223 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:015224 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205225
5226 EXPECT_TRUE(spdy_session0->unclaimed_pushed_streams_.empty());
5227 EXPECT_EQ(0u, spdy_session0->unclaimed_pushed_streams_.size());
5228
5229 EXPECT_TRUE(spdy_session1->unclaimed_pushed_streams_.empty());
5230 EXPECT_EQ(0u, spdy_session1->unclaimed_pushed_streams_.size());
5231
bnc3e79387f2016-03-15 14:49:205232 HttpResponseInfo response0 = *trans0->GetResponseInfo();
wezca1070932016-05-26 20:30:525233 EXPECT_TRUE(response0.headers);
bnc3e79387f2016-03-15 14:49:205234 EXPECT_EQ("HTTP/1.1 200", response0.headers->GetStatusLine());
5235
5236 std::string result0;
5237 ReadResult(trans0, &result0);
5238 EXPECT_EQ(kData0, result0);
5239
bnc691fda62016-08-12 00:43:165240 HttpResponseInfo response1 = *trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:525241 EXPECT_TRUE(response1.headers);
bnc3e79387f2016-03-15 14:49:205242 EXPECT_EQ("HTTP/1.1 200", response1.headers->GetStatusLine());
5243
5244 std::string result1;
bnc691fda62016-08-12 00:43:165245 ReadResult(&trans1, &result1);
bnc3e79387f2016-03-15 14:49:205246 EXPECT_EQ(kData1, result1);
5247
bnc691fda62016-08-12 00:43:165248 HttpResponseInfo push_response = *trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:525249 EXPECT_TRUE(push_response.headers);
bnc3e79387f2016-03-15 14:49:205250 EXPECT_EQ("HTTP/1.1 200", push_response.headers->GetStatusLine());
5251
5252 std::string result2;
bnc691fda62016-08-12 00:43:165253 ReadResult(&trans2, &result2);
bnc3e79387f2016-03-15 14:49:205254 EXPECT_EQ(kPushedData, result2);
tombergan5d22c182017-01-11 02:05:355255
5256 base::RunLoop().RunUntilIdle();
5257 helper.VerifyDataConsumed();
5258 VerifyStreamsClosed(helper);
bnc3e79387f2016-03-15 14:49:205259}
5260
bncd16676a2016-07-20 16:23:015261TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidCrossOrigin) {
bnc3e79387f2016-03-15 14:49:205262 // "spdy_pooling.pem" is valid for www.example.org,
5263 // but not for invalid.example.org.
5264 const char* url_to_fetch = "https://www.example.org";
5265 const char* url_to_push = "https://invalid.example.org";
5266
bncdf80d44fd2016-07-15 20:27:415267 SpdySerializedFrame headers(
bnc3e79387f2016-03-15 14:49:205268 spdy_util_.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415269 SpdySerializedFrame rst(
bnc3e79387f2016-03-15 14:49:205270 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5271 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415272 CreateMockWrite(headers, 0), CreateMockWrite(rst, 3),
bnc3e79387f2016-03-15 14:49:205273 };
5274
bnc42331402016-07-25 13:36:155275 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:415276 SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:205277 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
bncdf80d44fd2016-07-15 20:27:415278 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc3e79387f2016-03-15 14:49:205279 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:415280 SpdySerializedFrame pushed_body(spdy_util_.ConstructSpdyDataFrame(
5281 2, kPushedData, strlen(kPushedData), true));
bnc3e79387f2016-03-15 14:49:205282 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415283 CreateMockRead(reply, 1),
tombergan5d22c182017-01-11 02:05:355284 CreateMockRead(push, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:415285 CreateMockRead(body, 4),
tombergan5d22c182017-01-11 02:05:355286 CreateMockRead(pushed_body, 5, SYNCHRONOUS),
bnc3e79387f2016-03-15 14:49:205287 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
5288 };
5289
5290 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
5291
5292 HttpRequestInfo request;
5293 request.method = "GET";
5294 request.url = GURL(url_to_fetch);
5295 request.load_flags = 0;
5296
tfarina428341112016-09-22 13:38:205297 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5298 NetLogWithSource(), nullptr);
bnc3e79387f2016-03-15 14:49:205299 helper.RunToCompletion(&data);
5300 TransactionHelperResult out = helper.output();
5301 EXPECT_EQ("HTTP/1.1 200", out.status_line);
5302 EXPECT_EQ("hello!", out.response_data);
5303}
5304
bncd16676a2016-07-20 16:23:015305TEST_F(SpdyNetworkTransactionTest, RetryAfterRefused) {
[email protected]721c0ce2011-10-13 02:41:005306 // Construct the request.
bncdf80d44fd2016-07-15 20:27:415307 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:495308 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:385309 // Will be destroyed by the RST before stream 3 starts.
5310 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:415311 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:495312 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
[email protected]721c0ce2011-10-13 02:41:005313 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415314 CreateMockWrite(req, 0), CreateMockWrite(req2, 2),
[email protected]721c0ce2011-10-13 02:41:005315 };
5316
bncdf80d44fd2016-07-15 20:27:415317 SpdySerializedFrame refused(
[email protected]c10b20852013-05-15 21:29:205318 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
tombergan5d22c182017-01-11 02:05:355319 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
bncdf80d44fd2016-07-15 20:27:415320 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]721c0ce2011-10-13 02:41:005321 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415322 CreateMockRead(refused, 1), CreateMockRead(resp, 3),
5323 CreateMockRead(body, 4), MockRead(ASYNC, 0, 5) // EOF
[email protected]721c0ce2011-10-13 02:41:005324 };
5325
rch08e3aa3e2015-05-16 14:27:525326 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365327 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:355328 NetLogWithSource(), nullptr);
[email protected]721c0ce2011-10-13 02:41:005329
5330 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575331 helper.AddData(&data);
[email protected]721c0ce2011-10-13 02:41:005332
5333 HttpNetworkTransaction* trans = helper.trans();
5334
5335 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415336 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:205337 int rv = trans->Start(&CreateGetRequest(), callback.callback(),
5338 NetLogWithSource());
robpercival214763f2016-07-01 23:27:015339 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]721c0ce2011-10-13 02:41:005340 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015341 EXPECT_THAT(rv, IsOk());
[email protected]721c0ce2011-10-13 02:41:005342
bnceb9aa7112017-01-05 01:03:465343 // Finish async network reads.
5344 base::RunLoop().RunUntilIdle();
5345
[email protected]721c0ce2011-10-13 02:41:005346 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:525347 EXPECT_TRUE(data.AllReadDataConsumed());
5348 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]721c0ce2011-10-13 02:41:005349
bnc42331402016-07-25 13:36:155350 // Verify the response headers.
[email protected]721c0ce2011-10-13 02:41:005351 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525352 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:025353 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]721c0ce2011-10-13 02:41:005354}
5355
bnc42331402016-07-25 13:36:155356TEST_F(SpdyNetworkTransactionTest, OutOfOrderHeaders) {
[email protected]e1f58efa2012-05-15 18:23:405357 // This first request will start to establish the SpdySession.
5358 // Then we will start the second (MEDIUM priority) and then third
5359 // (HIGHEST priority) request in such a way that the third will actually
[email protected]c92f4b4542012-07-26 23:53:215360 // start before the second, causing the second to be numbered differently
[email protected]513963e2013-06-15 01:53:045361 // than the order they were created.
rdsmithebb50aa2015-11-12 03:44:385362 //
5363 // Note that the requests and responses created below are expectations
5364 // of what the above will produce on the wire, and hence are in the
5365 // initial->HIGHEST->LOWEST priority.
5366 //
5367 // Frames are created by SpdySession just before the write associated
5368 // with the frame is attempted, so stream dependencies will be based
5369 // on the streams alive at the point of the request write attempt. Thus
5370 // req1 is alive when req2 is attempted (during but not after the
5371 // |data.RunFor(2);| statement below) but not when req3 is attempted.
5372 // The call to spdy_util_.UpdateWithStreamDestruction() reflects this.
bncdf80d44fd2016-07-15 20:27:415373 SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:495374 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:415375 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:495376 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, HIGHEST, true));
rdsmithebb50aa2015-11-12 03:44:385377 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:415378 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:495379 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, MEDIUM, true));
[email protected]e1f58efa2012-05-15 18:23:405380 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415381 MockWrite(ASYNC, ERR_IO_PENDING, 0), CreateMockWrite(req1, 1),
5382 CreateMockWrite(req2, 5), CreateMockWrite(req3, 6),
[email protected]e1f58efa2012-05-15 18:23:405383 };
5384
tombergan5d22c182017-01-11 02:05:355385 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:415386 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
tombergan5d22c182017-01-11 02:05:355387 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
bncdf80d44fd2016-07-15 20:27:415388 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
tombergan5d22c182017-01-11 02:05:355389 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5));
bncdf80d44fd2016-07-15 20:27:415390 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]e1f58efa2012-05-15 18:23:405391 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415392 CreateMockRead(resp1, 2), MockRead(ASYNC, ERR_IO_PENDING, 3),
5393 CreateMockRead(body1, 4), CreateMockRead(resp2, 7),
5394 CreateMockRead(body2, 8), CreateMockRead(resp3, 9),
5395 CreateMockRead(body3, 10), MockRead(ASYNC, 0, 11) // EOF
[email protected]e1f58efa2012-05-15 18:23:405396 };
5397
mmenke666a6fea2015-12-19 04:16:335398 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tfarina428341112016-09-22 13:38:205399 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
tombergan5d22c182017-01-11 02:05:355400 NetLogWithSource(), nullptr);
[email protected]e1f58efa2012-05-15 18:23:405401 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:335402 helper.AddData(&data);
[email protected]e1f58efa2012-05-15 18:23:405403
5404 // Start the first transaction to set up the SpdySession
5405 HttpNetworkTransaction* trans = helper.trans();
5406 TestCompletionCallback callback;
5407 HttpRequestInfo info1 = CreateGetRequest();
tfarina428341112016-09-22 13:38:205408 int rv = trans->Start(&info1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015409 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e1f58efa2012-05-15 18:23:405410
5411 // Run the message loop, but do not allow the write to complete.
5412 // This leaves the SpdySession with a write pending, which prevents
5413 // SpdySession from attempting subsequent writes until this write completes.
[email protected]fc9d88472013-08-14 02:31:175414 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405415
5416 // Now, start both new transactions
5417 HttpRequestInfo info2 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405418 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:165419 HttpNetworkTransaction trans2(MEDIUM, helper.session());
tfarina428341112016-09-22 13:38:205420 rv = trans2.Start(&info2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015421 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:175422 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405423
5424 HttpRequestInfo info3 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405425 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:165426 HttpNetworkTransaction trans3(HIGHEST, helper.session());
tfarina428341112016-09-22 13:38:205427 rv = trans3.Start(&info3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015428 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:175429 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405430
bnc42331402016-07-25 13:36:155431 // We now have two HEADERS frames queued up which will be
[email protected]e1f58efa2012-05-15 18:23:405432 // dequeued only once the first write completes, which we
5433 // now allow to happen.
mmenke666a6fea2015-12-19 04:16:335434 ASSERT_TRUE(data.IsPaused());
5435 data.Resume();
robpercival214763f2016-07-01 23:27:015436 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e1f58efa2012-05-15 18:23:405437
5438 // And now we can allow everything else to run to completion.
mmenke666a6fea2015-12-19 04:16:335439 data.Resume();
5440 base::RunLoop().RunUntilIdle();
robpercival214763f2016-07-01 23:27:015441 EXPECT_THAT(callback2.WaitForResult(), IsOk());
5442 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]e1f58efa2012-05-15 18:23:405443
5444 helper.VerifyDataConsumed();
krasin0bfeb6b2017-01-13 21:48:045445
5446 // At this point the test is completed and we need to safely destroy
5447 // all allocated structures. Helper stores a transaction that has a
5448 // reference to a stack allocated request, which has a short lifetime,
5449 // and is accessed during the transaction destruction. We need to delete
5450 // the transaction while the request is still a valid object.
5451 helper.ResetTrans();
[email protected]e1f58efa2012-05-15 18:23:405452}
5453
[email protected]d11b6912013-06-27 23:07:325454// Test that sent data frames and received WINDOW_UPDATE frames change
5455// the send_window_size_ correctly.
5456
5457// WINDOW_UPDATE is different than most other frames in that it can arrive
5458// while the client is still sending the request body. In order to enforce
5459// this scenario, we feed a couple of dummy frames and give a delay of 0 to
5460// socket data provider, so that initial read that is done as soon as the
5461// stream is created, succeeds and schedules another read. This way reads
5462// and writes are interleaved; after doing a full frame write, SpdyStream
5463// will break out of DoLoop and will read and process a WINDOW_UPDATE.
bnc42331402016-07-25 13:36:155464// Once our WINDOW_UPDATE is read, we cannot send HEADERS right away
[email protected]d11b6912013-06-27 23:07:325465// since request has not been completely written, therefore we feed
5466// enough number of WINDOW_UPDATEs to finish the first read and cause a
5467// write, leading to a complete write of request body; after that we send
5468// a reply with a body, to cause a graceful shutdown.
5469
5470// TODO(agayev): develop a socket data provider where both, reads and
5471// writes are ordered so that writing tests like these are easy and rewrite
5472// all these tests using it. Right now we are working around the
5473// limitations as described above and it's not deterministic, tests may
5474// fail under specific circumstances.
bncd16676a2016-07-20 16:23:015475TEST_F(SpdyNetworkTransactionTest, WindowUpdateReceived) {
[email protected]d11b6912013-06-27 23:07:325476 static int kFrameCount = 2;
danakjaee3e1ec2016-04-16 00:23:185477 std::unique_ptr<std::string> content(
[email protected]d11b6912013-06-27 23:07:325478 new std::string(kMaxSpdyFrameChunkSize, 'a'));
bncdf80d44fd2016-07-15 20:27:415479 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
tombergan5d22c182017-01-11 02:05:355480 kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, nullptr,
5481 0));
bncdf80d44fd2016-07-15 20:27:415482 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555483 1, content->c_str(), content->size(), false));
bncdf80d44fd2016-07-15 20:27:415484 SpdySerializedFrame body_end(spdy_util_.ConstructSpdyDataFrame(
5485 1, content->c_str(), content->size(), true));
[email protected]d11b6912013-06-27 23:07:325486
5487 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415488 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
5489 CreateMockWrite(body_end, 2),
[email protected]d11b6912013-06-27 23:07:325490 };
5491
Avi Drissman13fc8932015-12-20 04:40:465492 static const int32_t kDeltaWindowSize = 0xff;
[email protected]d11b6912013-06-27 23:07:325493 static const int kDeltaCount = 4;
bncdf80d44fd2016-07-15 20:27:415494 SpdySerializedFrame window_update(
[email protected]d11b6912013-06-27 23:07:325495 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
bncdf80d44fd2016-07-15 20:27:415496 SpdySerializedFrame window_update_dummy(
[email protected]d11b6912013-06-27 23:07:325497 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
tombergan5d22c182017-01-11 02:05:355498 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
[email protected]d11b6912013-06-27 23:07:325499 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415500 CreateMockRead(window_update_dummy, 3),
5501 CreateMockRead(window_update_dummy, 4),
5502 CreateMockRead(window_update_dummy, 5),
5503 CreateMockRead(window_update, 6), // Four updates, therefore window
5504 CreateMockRead(window_update, 7), // size should increase by
5505 CreateMockRead(window_update, 8), // kDeltaWindowSize * 4
5506 CreateMockRead(window_update, 9),
5507 CreateMockRead(resp, 10),
5508 MockRead(ASYNC, ERR_IO_PENDING, 11),
5509 CreateMockRead(body_end, 12),
mmenke666a6fea2015-12-19 04:16:335510 MockRead(ASYNC, 0, 13) // EOF
[email protected]d11b6912013-06-27 23:07:325511 };
5512
mmenke666a6fea2015-12-19 04:16:335513 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d11b6912013-06-27 23:07:325514
danakjaee3e1ec2016-04-16 00:23:185515 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:325516 for (int i = 0; i < kFrameCount; ++i) {
danakjaee3e1ec2016-04-16 00:23:185517 element_readers.push_back(base::WrapUnique(
olli.raula6df48b2a2015-11-26 07:40:225518 new UploadBytesElementReader(content->c_str(), content->size())));
[email protected]d11b6912013-06-27 23:07:325519 }
olli.raula6df48b2a2015-11-26 07:40:225520 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325521
5522 // Setup the request
5523 HttpRequestInfo request;
5524 request.method = "POST";
bncb26024382016-06-29 02:39:455525 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325526 request.upload_data_stream = &upload_data_stream;
5527
tfarina428341112016-09-22 13:38:205528 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:355529 NetLogWithSource(), nullptr);
mmenke666a6fea2015-12-19 04:16:335530 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:325531 helper.RunPreTestSetup();
5532
5533 HttpNetworkTransaction* trans = helper.trans();
5534
5535 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:205536 int rv =
5537 trans->Start(&helper.request(), callback.callback(), NetLogWithSource());
[email protected]d11b6912013-06-27 23:07:325538
robpercival214763f2016-07-01 23:27:015539 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325540
mmenke666a6fea2015-12-19 04:16:335541 data.RunUntilPaused();
5542 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325543
5544 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525545 ASSERT_TRUE(stream);
5546 ASSERT_TRUE(stream->stream());
bncbca843ba2016-07-14 13:05:485547 EXPECT_EQ(static_cast<int>(kDefaultInitialWindowSize) +
5548 kDeltaWindowSize * kDeltaCount -
5549 kMaxSpdyFrameChunkSize * kFrameCount,
5550 stream->stream()->send_window_size());
[email protected]d11b6912013-06-27 23:07:325551
mmenke666a6fea2015-12-19 04:16:335552 data.Resume();
5553 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325554
5555 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015556 EXPECT_THAT(rv, IsOk());
[email protected]d11b6912013-06-27 23:07:325557
5558 helper.VerifyDataConsumed();
5559}
5560
5561// Test that received data frames and sent WINDOW_UPDATE frames change
5562// the recv_window_size_ correctly.
bncd16676a2016-07-20 16:23:015563TEST_F(SpdyNetworkTransactionTest, WindowUpdateSent) {
bnc8f0f3b62015-04-08 04:37:235564 // Session level maximum window size that is more than twice the default
5565 // initial window size so that an initial window update is sent.
Avi Drissman13fc8932015-12-20 04:40:465566 const int32_t session_max_recv_window_size = 5 * 64 * 1024;
bncbca843ba2016-07-14 13:05:485567 ASSERT_LT(2 * kDefaultInitialWindowSize, session_max_recv_window_size);
bnc8f0f3b62015-04-08 04:37:235568 // Stream level maximum window size that is less than the session level
5569 // maximum window size so that we test for confusion between the two.
Avi Drissman13fc8932015-12-20 04:40:465570 const int32_t stream_max_recv_window_size = 4 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:235571 ASSERT_GT(session_max_recv_window_size, stream_max_recv_window_size);
5572 // Size of body to be sent. Has to be less than or equal to both window sizes
5573 // so that we do not run out of receiving window. Also has to be greater than
5574 // half of them so that it triggers both a session level and a stream level
5575 // window update frame.
Avi Drissman13fc8932015-12-20 04:40:465576 const int32_t kTargetSize = 3 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:235577 ASSERT_GE(session_max_recv_window_size, kTargetSize);
5578 ASSERT_GE(stream_max_recv_window_size, kTargetSize);
5579 ASSERT_LT(session_max_recv_window_size / 2, kTargetSize);
5580 ASSERT_LT(stream_max_recv_window_size / 2, kTargetSize);
5581 // Size of each DATA frame.
Avi Drissman13fc8932015-12-20 04:40:465582 const int32_t kChunkSize = 4096;
bnc8f0f3b62015-04-08 04:37:235583 // Size of window updates.
5584 ASSERT_EQ(0, session_max_recv_window_size / 2 % kChunkSize);
Avi Drissman13fc8932015-12-20 04:40:465585 const int32_t session_window_update_delta =
bnc8f0f3b62015-04-08 04:37:235586 session_max_recv_window_size / 2 + kChunkSize;
5587 ASSERT_EQ(0, stream_max_recv_window_size / 2 % kChunkSize);
Avi Drissman13fc8932015-12-20 04:40:465588 const int32_t stream_window_update_delta =
bnc8f0f3b62015-04-08 04:37:235589 stream_max_recv_window_size / 2 + kChunkSize;
[email protected]d11b6912013-06-27 23:07:325590
bnc8f0f3b62015-04-08 04:37:235591 SettingsMap initial_settings;
bnc3171a2432016-12-28 18:40:265592 initial_settings[SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
bnc8f0f3b62015-04-08 04:37:235593 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
bnc3171a2432016-12-28 18:40:265594 kSpdyMaxConcurrentPushedStreams;
diannahu0e5f4982016-12-22 15:50:295595 initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] = stream_max_recv_window_size;
bncdf80d44fd2016-07-15 20:27:415596 SpdySerializedFrame initial_settings_frame(
bnc8f0f3b62015-04-08 04:37:235597 spdy_util_.ConstructSpdySettings(initial_settings));
bncdf80d44fd2016-07-15 20:27:415598 SpdySerializedFrame initial_window_update(
bnc8f0f3b62015-04-08 04:37:235599 spdy_util_.ConstructSpdyWindowUpdate(
5600 kSessionFlowControlStreamId,
bncbca843ba2016-07-14 13:05:485601 session_max_recv_window_size - kDefaultInitialWindowSize));
bncdf80d44fd2016-07-15 20:27:415602 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:495603 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:415604 SpdySerializedFrame session_window_update(
bnc8f0f3b62015-04-08 04:37:235605 spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta));
bncdf80d44fd2016-07-15 20:27:415606 SpdySerializedFrame stream_window_update(
bnc8f0f3b62015-04-08 04:37:235607 spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta));
[email protected]d11b6912013-06-27 23:07:325608
5609 std::vector<MockWrite> writes;
bnca9b9e222016-07-11 20:10:405610 writes.push_back(MockWrite(ASYNC, kHttp2ConnectionHeaderPrefix,
5611 kHttp2ConnectionHeaderPrefixSize, 0));
bncdf80d44fd2016-07-15 20:27:415612 writes.push_back(CreateMockWrite(initial_settings_frame, writes.size()));
5613 writes.push_back(CreateMockWrite(initial_window_update, writes.size()));
5614 writes.push_back(CreateMockWrite(req, writes.size()));
[email protected]d11b6912013-06-27 23:07:325615
[email protected]251029e2014-03-19 06:04:405616 std::vector<MockRead> reads;
tombergan5d22c182017-01-11 02:05:355617 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:415618 reads.push_back(CreateMockRead(resp, writes.size() + reads.size()));
[email protected]d11b6912013-06-27 23:07:325619
bncdf80d44fd2016-07-15 20:27:415620 std::vector<SpdySerializedFrame> body_frames;
bnc8f0f3b62015-04-08 04:37:235621 const std::string body_data(kChunkSize, 'x');
[email protected]251029e2014-03-19 06:04:405622 for (size_t remaining = kTargetSize; remaining != 0;) {
5623 size_t frame_size = std::min(remaining, body_data.size());
bncdf80d44fd2016-07-15 20:27:415624 body_frames.push_back(spdy_util_.ConstructSpdyDataFrame(1, body_data.data(),
5625 frame_size, false));
rchacdcbdc2015-05-16 17:16:005626 reads.push_back(
bncdf80d44fd2016-07-15 20:27:415627 CreateMockRead(body_frames.back(), writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:405628 remaining -= frame_size;
5629 }
mmenkee24011922015-12-17 22:12:595630 // Yield.
rchacdcbdc2015-05-16 17:16:005631 reads.push_back(
mmenkee24011922015-12-17 22:12:595632 MockRead(SYNCHRONOUS, ERR_IO_PENDING, writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:405633
rchacdcbdc2015-05-16 17:16:005634 writes.push_back(
bncdf80d44fd2016-07-15 20:27:415635 CreateMockWrite(session_window_update, writes.size() + reads.size()));
rchacdcbdc2015-05-16 17:16:005636 writes.push_back(
bncdf80d44fd2016-07-15 20:27:415637 CreateMockWrite(stream_window_update, writes.size() + reads.size()));
rchacdcbdc2015-05-16 17:16:005638
davidben5f8b6bc2015-11-25 03:19:545639 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
5640 writes.size());
[email protected]d11b6912013-06-27 23:07:325641
bnc903e8c12016-12-09 20:50:055642 auto session_deps = base::MakeUnique<SpdySessionDependencies>();
5643 session_deps->session_max_recv_window_size = session_max_recv_window_size;
bnc3171a2432016-12-28 18:40:265644 session_deps->http2_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
5645 stream_max_recv_window_size;
bnc903e8c12016-12-09 20:50:055646
[email protected]d11b6912013-06-27 23:07:325647 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bnc903e8c12016-12-09 20:50:055648 NetLogWithSource(),
5649 std::move(session_deps));
[email protected]d11b6912013-06-27 23:07:325650 helper.AddData(&data);
5651 helper.RunPreTestSetup();
[email protected]d11b6912013-06-27 23:07:325652
bnc8f0f3b62015-04-08 04:37:235653 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5654 SpdySessionPoolPeer pool_peer(spdy_session_pool);
5655 pool_peer.SetEnableSendingInitialData(true);
bnc8f0f3b62015-04-08 04:37:235656
5657 HttpNetworkTransaction* trans = helper.trans();
[email protected]d11b6912013-06-27 23:07:325658 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:205659 int rv =
5660 trans->Start(&helper.request(), callback.callback(), NetLogWithSource());
[email protected]d11b6912013-06-27 23:07:325661
robpercival214763f2016-07-01 23:27:015662 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325663 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015664 EXPECT_THAT(rv, IsOk());
[email protected]d11b6912013-06-27 23:07:325665
bnceb9aa7112017-01-05 01:03:465666 // Finish async network reads.
5667 base::RunLoop().RunUntilIdle();
5668
[email protected]d11b6912013-06-27 23:07:325669 SpdyHttpStream* stream =
5670 static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525671 ASSERT_TRUE(stream);
5672 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:325673
[email protected]251029e2014-03-19 06:04:405674 // All data has been read, but not consumed. The window reflects this.
bnc8f0f3b62015-04-08 04:37:235675 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size - kTargetSize),
[email protected]251029e2014-03-19 06:04:405676 stream->stream()->recv_window_size());
[email protected]d11b6912013-06-27 23:07:325677
5678 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525679 ASSERT_TRUE(response);
5680 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025681 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d11b6912013-06-27 23:07:325682 EXPECT_TRUE(response->was_fetched_via_spdy);
5683
5684 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5685 // size increased to default.
bnc301745a2015-03-10 03:22:165686 scoped_refptr<IOBuffer> buf(new IOBuffer(kTargetSize));
[email protected]251029e2014-03-19 06:04:405687 EXPECT_EQ(static_cast<int>(kTargetSize),
5688 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
bnc8f0f3b62015-04-08 04:37:235689 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size),
[email protected]251029e2014-03-19 06:04:405690 stream->stream()->recv_window_size());
5691 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
[email protected]d11b6912013-06-27 23:07:325692
[email protected]251029e2014-03-19 06:04:405693 // Allow scheduled WINDOW_UPDATE frames to write.
[email protected]fc9d88472013-08-14 02:31:175694 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325695 helper.VerifyDataConsumed();
5696}
5697
5698// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
bncd16676a2016-07-20 16:23:015699TEST_F(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]d11b6912013-06-27 23:07:325700 // Number of full frames we hope to write (but will not, used to
5701 // set content-length header correctly)
5702 static int kFrameCount = 3;
5703
danakjaee3e1ec2016-04-16 00:23:185704 std::unique_ptr<std::string> content(
[email protected]d11b6912013-06-27 23:07:325705 new std::string(kMaxSpdyFrameChunkSize, 'a'));
bncdf80d44fd2016-07-15 20:27:415706 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
tombergan5d22c182017-01-11 02:05:355707 kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, nullptr,
5708 0));
bncdf80d44fd2016-07-15 20:27:415709 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555710 1, content->c_str(), content->size(), false));
bncdf80d44fd2016-07-15 20:27:415711 SpdySerializedFrame rst(
[email protected]d11b6912013-06-27 23:07:325712 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
5713
5714 // We're not going to write a data frame with FIN, we'll receive a bad
5715 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
5716 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415717 CreateMockWrite(req, 0), CreateMockWrite(body, 2),
5718 CreateMockWrite(rst, 3),
[email protected]d11b6912013-06-27 23:07:325719 };
5720
Avi Drissman13fc8932015-12-20 04:40:465721 static const int32_t kDeltaWindowSize = 0x7fffffff; // cause an overflow
bncdf80d44fd2016-07-15 20:27:415722 SpdySerializedFrame window_update(
[email protected]d11b6912013-06-27 23:07:325723 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5724 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415725 CreateMockRead(window_update, 1), MockRead(ASYNC, 0, 4) // EOF
[email protected]d11b6912013-06-27 23:07:325726 };
5727
mmenke666a6fea2015-12-19 04:16:335728 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d11b6912013-06-27 23:07:325729
danakjaee3e1ec2016-04-16 00:23:185730 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:325731 for (int i = 0; i < kFrameCount; ++i) {
danakjaee3e1ec2016-04-16 00:23:185732 element_readers.push_back(base::WrapUnique(
olli.raula6df48b2a2015-11-26 07:40:225733 new UploadBytesElementReader(content->c_str(), content->size())));
[email protected]d11b6912013-06-27 23:07:325734 }
olli.raula6df48b2a2015-11-26 07:40:225735 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325736
5737 // Setup the request
5738 HttpRequestInfo request;
5739 request.method = "POST";
bncb26024382016-06-29 02:39:455740 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325741 request.upload_data_stream = &upload_data_stream;
5742
tfarina428341112016-09-22 13:38:205743 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:355744 NetLogWithSource(), nullptr);
[email protected]d11b6912013-06-27 23:07:325745 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:335746 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:325747 HttpNetworkTransaction* trans = helper.trans();
5748
5749 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:205750 int rv =
5751 trans->Start(&helper.request(), callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015752 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325753
mmenke666a6fea2015-12-19 04:16:335754 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325755 ASSERT_TRUE(callback.have_result());
robpercival214763f2016-07-01 23:27:015756 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d11b6912013-06-27 23:07:325757 helper.VerifyDataConsumed();
5758}
5759
5760// Test that after hitting a send window size of 0, the write process
5761// stalls and upon receiving WINDOW_UPDATE frame write resumes.
5762
5763// This test constructs a POST request followed by enough data frames
5764// containing 'a' that would make the window size 0, followed by another
5765// data frame containing default content (which is "hello!") and this frame
rchacdcbdc2015-05-16 17:16:005766// also contains a FIN flag. SequencedSocketData is used to enforce all
5767// writes, save the last, go through before a read could happen. The last frame
5768// ("hello!") is not permitted to go through since by the time its turn
[email protected]d11b6912013-06-27 23:07:325769// arrives, window size is 0. At this point MessageLoop::Run() called via
5770// callback would block. Therefore we call MessageLoop::RunUntilIdle()
5771// which returns after performing all possible writes. We use DCHECKS to
5772// ensure that last data frame is still there and stream has stalled.
5773// After that, next read is artifically enforced, which causes a
5774// WINDOW_UPDATE to be read and I/O process resumes.
bncd16676a2016-07-20 16:23:015775TEST_F(SpdyNetworkTransactionTest, FlowControlStallResume) {
bncbca843ba2016-07-14 13:05:485776 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:455777 // Number of upload data buffers we need to send to zero out the window size
5778 // is the minimal number of upload buffers takes to be bigger than
5779 // |initial_window_size|.
5780 size_t num_upload_buffers =
5781 ceil(static_cast<double>(initial_window_size) / kBufferSize);
5782 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
5783 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
5784 // which has kBufferSize % kMaxSpdyChunkSize bytes.
5785 size_t num_frames_in_one_upload_buffer =
5786 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:325787
5788 // Construct content for a data frame of maximum size.
5789 std::string content(kMaxSpdyFrameChunkSize, 'a');
5790
bncdf80d44fd2016-07-15 20:27:415791 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455792 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:455793 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
tombergan5d22c182017-01-11 02:05:355794 LOWEST, nullptr, 0));
[email protected]d11b6912013-06-27 23:07:325795
5796 // Full frames.
bncdf80d44fd2016-07-15 20:27:415797 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555798 1, content.c_str(), content.size(), false));
[email protected]d11b6912013-06-27 23:07:325799
xunjieli179a6e72016-04-26 19:47:455800 // Last frame in each upload data buffer.
bncdf80d44fd2016-07-15 20:27:415801 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455802 1, content.c_str(), kBufferSize % kMaxSpdyFrameChunkSize, false));
[email protected]d11b6912013-06-27 23:07:325803
xunjieli179a6e72016-04-26 19:47:455804 // The very last frame before the stalled frames.
bncdf80d44fd2016-07-15 20:27:415805 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455806 1, content.c_str(),
5807 initial_window_size % kBufferSize % kMaxSpdyFrameChunkSize, false));
5808
5809 // Data frames to be sent once WINDOW_UPDATE frame is received.
5810
5811 // If kBufferSize * num_upload_buffers > initial_window_size,
5812 // we need one additional frame to send the rest of 'a'.
5813 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
5814 'a');
bncdf80d44fd2016-07-15 20:27:415815 SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455816 1, last_body.c_str(), last_body.size(), false));
5817
5818 // Also send a "hello!" after WINDOW_UPDATE.
bncdf80d44fd2016-07-15 20:27:415819 SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:325820
5821 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:325822 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:455823 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:415824 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:455825 for (size_t j = 0; j < num_upload_buffers; j++) {
5826 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
5827 if (k == num_frames_in_one_upload_buffer - 1 &&
5828 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
5829 if (j == num_upload_buffers - 1 &&
5830 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:415831 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:455832 } else {
bncdf80d44fd2016-07-15 20:27:415833 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:455834 }
5835 } else {
bncdf80d44fd2016-07-15 20:27:415836 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:455837 }
5838 }
5839 }
[email protected]d11b6912013-06-27 23:07:325840
xunjieli179a6e72016-04-26 19:47:455841 // Fill in mock reads.
5842 std::vector<MockRead> reads;
5843 // Force a pause.
5844 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
5845 // Construct read frame for window updates that gives enough space to upload
5846 // the rest of the data.
bncdf80d44fd2016-07-15 20:27:415847 SpdySerializedFrame session_window_update(
xunjieli179a6e72016-04-26 19:47:455848 spdy_util_.ConstructSpdyWindowUpdate(0,
5849 kUploadDataSize + last_body.size()));
bncdf80d44fd2016-07-15 20:27:415850 SpdySerializedFrame window_update(spdy_util_.ConstructSpdyWindowUpdate(
5851 1, kUploadDataSize + last_body.size()));
xunjieli179a6e72016-04-26 19:47:455852
bncdf80d44fd2016-07-15 20:27:415853 reads.push_back(CreateMockRead(session_window_update, i++));
5854 reads.push_back(CreateMockRead(window_update, i++));
xunjieli179a6e72016-04-26 19:47:455855
5856 // Stalled frames which can be sent after receiving window updates.
5857 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:415858 writes.push_back(CreateMockWrite(body4, i++));
5859 writes.push_back(CreateMockWrite(body5, i++));
xunjieli179a6e72016-04-26 19:47:455860
tombergan5d22c182017-01-11 02:05:355861 SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:415862 reads.push_back(CreateMockRead(reply, i++));
5863 reads.push_back(CreateMockRead(body2, i++));
5864 reads.push_back(CreateMockRead(body5, i++));
xunjieli179a6e72016-04-26 19:47:455865 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
[email protected]d11b6912013-06-27 23:07:325866
xunjieli179a6e72016-04-26 19:47:455867 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
5868 writes.size());
[email protected]d11b6912013-06-27 23:07:325869
danakjaee3e1ec2016-04-16 00:23:185870 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
xunjieli179a6e72016-04-26 19:47:455871 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:325872 upload_data_string.append(kUploadData, kUploadDataSize);
danakjaee3e1ec2016-04-16 00:23:185873 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader(
olli.raula6df48b2a2015-11-26 07:40:225874 upload_data_string.c_str(), upload_data_string.size())));
5875 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325876
5877 HttpRequestInfo request;
5878 request.method = "POST";
bncb26024382016-06-29 02:39:455879 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325880 request.upload_data_stream = &upload_data_stream;
tfarina428341112016-09-22 13:38:205881 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:355882 NetLogWithSource(), nullptr);
[email protected]d11b6912013-06-27 23:07:325883 helper.AddData(&data);
5884 helper.RunPreTestSetup();
5885
5886 HttpNetworkTransaction* trans = helper.trans();
5887
5888 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:205889 int rv =
5890 trans->Start(&helper.request(), callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015891 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325892
[email protected]fc9d88472013-08-14 02:31:175893 base::RunLoop().RunUntilIdle(); // Write as much as we can.
[email protected]d11b6912013-06-27 23:07:325894
5895 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525896 ASSERT_TRUE(stream);
5897 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:325898 EXPECT_EQ(0, stream->stream()->send_window_size());
xunjieli179a6e72016-04-26 19:47:455899 if (initial_window_size % kBufferSize != 0) {
5900 // If it does not take whole number of full upload buffer to zero out
5901 // initial window size, then the upload data is not at EOF, because the
5902 // last read must be stalled.
5903 EXPECT_FALSE(upload_data_stream.IsEOF());
5904 } else {
5905 // All the body data should have been read.
5906 // TODO(satorux): This is because of the weirdness in reading the request
5907 // body in OnSendBodyComplete(). See crbug.com/113107.
5908 EXPECT_TRUE(upload_data_stream.IsEOF());
5909 }
[email protected]d11b6912013-06-27 23:07:325910 // But the body is not yet fully sent (kUploadData is not yet sent)
5911 // since we're send-stalled.
5912 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
5913
mmenkee24011922015-12-17 22:12:595914 data.Resume(); // Read in WINDOW_UPDATE frame.
[email protected]d11b6912013-06-27 23:07:325915 rv = callback.WaitForResult();
bnceb9aa7112017-01-05 01:03:465916 EXPECT_THAT(rv, IsOk());
5917
5918 // Finish async network reads.
5919 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325920 helper.VerifyDataConsumed();
5921}
5922
5923// Test we correctly handle the case where the SETTINGS frame results in
5924// unstalling the send window.
bncd16676a2016-07-20 16:23:015925TEST_F(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
bncbca843ba2016-07-14 13:05:485926 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:455927 // Number of upload data buffers we need to send to zero out the window size
5928 // is the minimal number of upload buffers takes to be bigger than
5929 // |initial_window_size|.
5930 size_t num_upload_buffers =
5931 ceil(static_cast<double>(initial_window_size) / kBufferSize);
5932 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
5933 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
5934 // which has kBufferSize % kMaxSpdyChunkSize bytes.
5935 size_t num_frames_in_one_upload_buffer =
5936 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:325937
5938 // Construct content for a data frame of maximum size.
5939 std::string content(kMaxSpdyFrameChunkSize, 'a');
5940
bncdf80d44fd2016-07-15 20:27:415941 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455942 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:455943 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
tombergan5d22c182017-01-11 02:05:355944 LOWEST, nullptr, 0));
[email protected]d11b6912013-06-27 23:07:325945
5946 // Full frames.
bncdf80d44fd2016-07-15 20:27:415947 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555948 1, content.c_str(), content.size(), false));
[email protected]d11b6912013-06-27 23:07:325949
xunjieli179a6e72016-04-26 19:47:455950 // Last frame in each upload data buffer.
bncdf80d44fd2016-07-15 20:27:415951 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455952 1, content.c_str(), kBufferSize % kMaxSpdyFrameChunkSize, false));
[email protected]d11b6912013-06-27 23:07:325953
xunjieli179a6e72016-04-26 19:47:455954 // The very last frame before the stalled frames.
bncdf80d44fd2016-07-15 20:27:415955 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455956 1, content.c_str(),
5957 initial_window_size % kBufferSize % kMaxSpdyFrameChunkSize, false));
5958
5959 // Data frames to be sent once WINDOW_UPDATE frame is received.
5960
5961 // If kBufferSize * num_upload_buffers > initial_window_size,
5962 // we need one additional frame to send the rest of 'a'.
5963 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
5964 'a');
bncdf80d44fd2016-07-15 20:27:415965 SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455966 1, last_body.c_str(), last_body.size(), false));
5967
5968 // Also send a "hello!" after WINDOW_UPDATE.
bncdf80d44fd2016-07-15 20:27:415969 SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:325970
xunjieli179a6e72016-04-26 19:47:455971 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:325972 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:455973 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:415974 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:455975 for (size_t j = 0; j < num_upload_buffers; j++) {
5976 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
5977 if (k == num_frames_in_one_upload_buffer - 1 &&
5978 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
5979 if (j == num_upload_buffers - 1 &&
5980 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:415981 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:455982 } else {
bncdf80d44fd2016-07-15 20:27:415983 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:455984 }
5985 } else {
bncdf80d44fd2016-07-15 20:27:415986 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:455987 }
5988 }
5989 }
[email protected]d11b6912013-06-27 23:07:325990
xunjieli179a6e72016-04-26 19:47:455991 // Fill in mock reads.
5992 std::vector<MockRead> reads;
5993 // Force a pause.
mmenke666a6fea2015-12-19 04:16:335994 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
5995
[email protected]d11b6912013-06-27 23:07:325996 // Construct read frame for SETTINGS that gives enough space to upload the
5997 // rest of the data.
5998 SettingsMap settings;
diannahu0e5f4982016-12-22 15:50:295999 settings[SETTINGS_INITIAL_WINDOW_SIZE] = initial_window_size * 2;
bncdf80d44fd2016-07-15 20:27:416000 SpdySerializedFrame settings_frame_large(
[email protected]d11b6912013-06-27 23:07:326001 spdy_util_.ConstructSpdySettings(settings));
6002
bncdf80d44fd2016-07-15 20:27:416003 reads.push_back(CreateMockRead(settings_frame_large, i++));
[email protected]d11b6912013-06-27 23:07:326004
bncdf80d44fd2016-07-15 20:27:416005 SpdySerializedFrame session_window_update(
xunjieli179a6e72016-04-26 19:47:456006 spdy_util_.ConstructSpdyWindowUpdate(0,
6007 last_body.size() + kUploadDataSize));
bncdf80d44fd2016-07-15 20:27:416008 reads.push_back(CreateMockRead(session_window_update, i++));
[email protected]d11b6912013-06-27 23:07:326009
bncdf80d44fd2016-07-15 20:27:416010 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
6011 writes.push_back(CreateMockWrite(settings_ack, i++));
[email protected]d4a77c12014-05-15 20:45:216012
xunjieli179a6e72016-04-26 19:47:456013 // Stalled frames which can be sent after |settings_ack|.
6014 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:416015 writes.push_back(CreateMockWrite(body4, i++));
6016 writes.push_back(CreateMockWrite(body5, i++));
[email protected]d11b6912013-06-27 23:07:326017
tombergan5d22c182017-01-11 02:05:356018 SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:416019 reads.push_back(CreateMockRead(reply, i++));
6020 reads.push_back(CreateMockRead(body2, i++));
6021 reads.push_back(CreateMockRead(body5, i++));
[email protected]d11b6912013-06-27 23:07:326022 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6023
6024 // Force all writes to happen before any read, last write will not
6025 // actually queue a frame, due to window size being 0.
mmenke666a6fea2015-12-19 04:16:336026 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
6027 writes.size());
[email protected]d11b6912013-06-27 23:07:326028
danakjaee3e1ec2016-04-16 00:23:186029 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
xunjieli179a6e72016-04-26 19:47:456030 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:326031 upload_data_string.append(kUploadData, kUploadDataSize);
danakjaee3e1ec2016-04-16 00:23:186032 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader(
olli.raula6df48b2a2015-11-26 07:40:226033 upload_data_string.c_str(), upload_data_string.size())));
6034 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326035
6036 HttpRequestInfo request;
6037 request.method = "POST";
bncb26024382016-06-29 02:39:456038 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:326039 request.upload_data_stream = &upload_data_stream;
tfarina428341112016-09-22 13:38:206040 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:356041 NetLogWithSource(), nullptr);
[email protected]d11b6912013-06-27 23:07:326042 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:336043 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:326044
6045 HttpNetworkTransaction* trans = helper.trans();
6046
6047 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:206048 int rv =
6049 trans->Start(&helper.request(), callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016050 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:326051
mmenke666a6fea2015-12-19 04:16:336052 data.RunUntilPaused(); // Write as much as we can.
6053 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326054
6055 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:526056 ASSERT_TRUE(stream);
6057 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:326058 EXPECT_EQ(0, stream->stream()->send_window_size());
6059
xunjieli179a6e72016-04-26 19:47:456060 if (initial_window_size % kBufferSize != 0) {
6061 // If it does not take whole number of full upload buffer to zero out
6062 // initial window size, then the upload data is not at EOF, because the
6063 // last read must be stalled.
6064 EXPECT_FALSE(upload_data_stream.IsEOF());
6065 } else {
6066 // All the body data should have been read.
6067 // TODO(satorux): This is because of the weirdness in reading the request
6068 // body in OnSendBodyComplete(). See crbug.com/113107.
6069 EXPECT_TRUE(upload_data_stream.IsEOF());
6070 }
[email protected]d11b6912013-06-27 23:07:326071 // But the body is not yet fully sent (kUploadData is not yet sent)
6072 // since we're send-stalled.
6073 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6074
mmenke666a6fea2015-12-19 04:16:336075 // Read in SETTINGS frame to unstall.
6076 data.Resume();
6077 base::RunLoop().RunUntilIdle();
6078
[email protected]d11b6912013-06-27 23:07:326079 rv = callback.WaitForResult();
6080 helper.VerifyDataConsumed();
tombergan5d22c182017-01-11 02:05:356081 // If stream is nullptr, that means it was unstalled and closed.
6082 EXPECT_TRUE(stream->stream() == nullptr);
[email protected]d11b6912013-06-27 23:07:326083}
6084
6085// Test we correctly handle the case where the SETTINGS frame results in a
6086// negative send window size.
bncd16676a2016-07-20 16:23:016087TEST_F(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
bncbca843ba2016-07-14 13:05:486088 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:456089 // Number of upload data buffers we need to send to zero out the window size
6090 // is the minimal number of upload buffers takes to be bigger than
6091 // |initial_window_size|.
6092 size_t num_upload_buffers =
6093 ceil(static_cast<double>(initial_window_size) / kBufferSize);
6094 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
6095 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
6096 // which has kBufferSize % kMaxSpdyChunkSize bytes.
6097 size_t num_frames_in_one_upload_buffer =
6098 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:326099
6100 // Construct content for a data frame of maximum size.
6101 std::string content(kMaxSpdyFrameChunkSize, 'a');
6102
bncdf80d44fd2016-07-15 20:27:416103 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:456104 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:456105 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
tombergan5d22c182017-01-11 02:05:356106 LOWEST, nullptr, 0));
[email protected]d11b6912013-06-27 23:07:326107
6108 // Full frames.
bncdf80d44fd2016-07-15 20:27:416109 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:556110 1, content.c_str(), content.size(), false));
[email protected]d11b6912013-06-27 23:07:326111
xunjieli179a6e72016-04-26 19:47:456112 // Last frame in each upload data buffer.
bncdf80d44fd2016-07-15 20:27:416113 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:456114 1, content.c_str(), kBufferSize % kMaxSpdyFrameChunkSize, false));
[email protected]d11b6912013-06-27 23:07:326115
xunjieli179a6e72016-04-26 19:47:456116 // The very last frame before the stalled frames.
bncdf80d44fd2016-07-15 20:27:416117 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:456118 1, content.c_str(),
6119 initial_window_size % kBufferSize % kMaxSpdyFrameChunkSize, false));
6120
6121 // Data frames to be sent once WINDOW_UPDATE frame is received.
6122
6123 // If kBufferSize * num_upload_buffers > initial_window_size,
6124 // we need one additional frame to send the rest of 'a'.
6125 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
6126 'a');
bncdf80d44fd2016-07-15 20:27:416127 SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:456128 1, last_body.c_str(), last_body.size(), false));
6129
6130 // Also send a "hello!" after WINDOW_UPDATE.
bncdf80d44fd2016-07-15 20:27:416131 SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:326132
xunjieli179a6e72016-04-26 19:47:456133 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:326134 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:456135 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:416136 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:456137 for (size_t j = 0; j < num_upload_buffers; j++) {
6138 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
6139 if (k == num_frames_in_one_upload_buffer - 1 &&
6140 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
6141 if (j == num_upload_buffers - 1 &&
6142 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:416143 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:456144 } else {
bncdf80d44fd2016-07-15 20:27:416145 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:456146 }
6147 } else {
bncdf80d44fd2016-07-15 20:27:416148 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:456149 }
6150 }
6151 }
[email protected]d11b6912013-06-27 23:07:326152
xunjieli179a6e72016-04-26 19:47:456153 // Fill in mock reads.
6154 std::vector<MockRead> reads;
6155 // Force a pause.
mmenke666a6fea2015-12-19 04:16:336156 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
[email protected]d11b6912013-06-27 23:07:326157 // Construct read frame for SETTINGS that makes the send_window_size
6158 // negative.
6159 SettingsMap new_settings;
diannahu0e5f4982016-12-22 15:50:296160 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] = initial_window_size / 2;
bncdf80d44fd2016-07-15 20:27:416161 SpdySerializedFrame settings_frame_small(
[email protected]d11b6912013-06-27 23:07:326162 spdy_util_.ConstructSpdySettings(new_settings));
6163 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6164 // positive.
bncdf80d44fd2016-07-15 20:27:416165 SpdySerializedFrame session_window_update_init_size(
bnc2f54c832014-12-01 13:31:196166 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
bncdf80d44fd2016-07-15 20:27:416167 SpdySerializedFrame window_update_init_size(
bnc2f54c832014-12-01 13:31:196168 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
[email protected]d11b6912013-06-27 23:07:326169
bncdf80d44fd2016-07-15 20:27:416170 reads.push_back(CreateMockRead(settings_frame_small, i++));
6171 reads.push_back(CreateMockRead(session_window_update_init_size, i++));
6172 reads.push_back(CreateMockRead(window_update_init_size, i++));
[email protected]d11b6912013-06-27 23:07:326173
bncdf80d44fd2016-07-15 20:27:416174 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
6175 writes.push_back(CreateMockWrite(settings_ack, i++));
[email protected]d4a77c12014-05-15 20:45:216176
xunjieli179a6e72016-04-26 19:47:456177 // Stalled frames which can be sent after |settings_ack|.
6178 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:416179 writes.push_back(CreateMockWrite(body4, i++));
6180 writes.push_back(CreateMockWrite(body5, i++));
[email protected]d11b6912013-06-27 23:07:326181
tombergan5d22c182017-01-11 02:05:356182 SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
bncdf80d44fd2016-07-15 20:27:416183 reads.push_back(CreateMockRead(reply, i++));
6184 reads.push_back(CreateMockRead(body2, i++));
6185 reads.push_back(CreateMockRead(body5, i++));
[email protected]d11b6912013-06-27 23:07:326186 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6187
6188 // Force all writes to happen before any read, last write will not
6189 // actually queue a frame, due to window size being 0.
mmenke666a6fea2015-12-19 04:16:336190 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
6191 writes.size());
[email protected]d11b6912013-06-27 23:07:326192
danakjaee3e1ec2016-04-16 00:23:186193 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
xunjieli179a6e72016-04-26 19:47:456194 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:326195 upload_data_string.append(kUploadData, kUploadDataSize);
danakjaee3e1ec2016-04-16 00:23:186196 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader(
olli.raula6df48b2a2015-11-26 07:40:226197 upload_data_string.c_str(), upload_data_string.size())));
6198 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326199
6200 HttpRequestInfo request;
6201 request.method = "POST";
bncb26024382016-06-29 02:39:456202 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:326203 request.upload_data_stream = &upload_data_stream;
tfarina428341112016-09-22 13:38:206204 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:356205 NetLogWithSource(), nullptr);
[email protected]d11b6912013-06-27 23:07:326206 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:336207 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:326208
6209 HttpNetworkTransaction* trans = helper.trans();
6210
6211 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:206212 int rv =
6213 trans->Start(&helper.request(), callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016214 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:326215
mmenke666a6fea2015-12-19 04:16:336216 data.RunUntilPaused(); // Write as much as we can.
6217 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326218
6219 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:526220 ASSERT_TRUE(stream);
6221 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:326222 EXPECT_EQ(0, stream->stream()->send_window_size());
6223
xunjieli179a6e72016-04-26 19:47:456224 if (initial_window_size % kBufferSize != 0) {
6225 // If it does not take whole number of full upload buffer to zero out
6226 // initial window size, then the upload data is not at EOF, because the
6227 // last read must be stalled.
6228 EXPECT_FALSE(upload_data_stream.IsEOF());
6229 } else {
6230 // All the body data should have been read.
6231 // TODO(satorux): This is because of the weirdness in reading the request
6232 // body in OnSendBodyComplete(). See crbug.com/113107.
6233 EXPECT_TRUE(upload_data_stream.IsEOF());
6234 }
[email protected]d11b6912013-06-27 23:07:326235
6236 // Read in WINDOW_UPDATE or SETTINGS frame.
mmenke666a6fea2015-12-19 04:16:336237 data.Resume();
6238 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326239 rv = callback.WaitForResult();
6240 helper.VerifyDataConsumed();
6241}
6242
bncd16676a2016-07-20 16:23:016243TEST_F(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
bnc086b39e12016-06-24 13:05:266244 SpdyHeaderBlock push_headers;
6245 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat", &push_headers);
bncdf80d44fd2016-07-15 20:27:416246 SpdySerializedFrame push(
dchengc7eeda422015-12-26 03:56:486247 spdy_util_.ConstructInitialSpdyPushFrame(std::move(push_headers), 3, 1));
bncdf80d44fd2016-07-15 20:27:416248 MockRead reads[] = {CreateMockRead(push, 1)};
baranovich212a1292014-09-02 21:45:316249
bncdf80d44fd2016-07-15 20:27:416250 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:496251 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:416252 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
baranovich212a1292014-09-02 21:45:316253 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6254 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416255 CreateMockWrite(req, 0), CreateMockWrite(goaway, 2),
baranovich212a1292014-09-02 21:45:316256 };
6257
rch08e3aa3e2015-05-16 14:27:526258 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:016259 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:356260 NetLogWithSource(), nullptr);
baranovich212a1292014-09-02 21:45:316261 helper.RunToCompletion(&data);
6262 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:016263 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
baranovich212a1292014-09-02 21:45:316264}
6265
bncd16676a2016-07-20 16:23:016266TEST_F(SpdyNetworkTransactionTest,
baranovich212a1292014-09-02 21:45:316267 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
bncdf80d44fd2016-07-15 20:27:416268 SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
tombergan5d22c182017-01-11 02:05:356269 nullptr, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
bnc086b39e12016-06-24 13:05:266270 SpdyHeaderBlock push_b_headers;
rchebf12982015-04-10 01:15:006271 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/b.dat"),
bnc086b39e12016-06-24 13:05:266272 &push_b_headers);
bncdf80d44fd2016-07-15 20:27:416273 SpdySerializedFrame push_b(spdy_util_.ConstructInitialSpdyPushFrame(
6274 std::move(push_b_headers), 2, 1));
baranovich212a1292014-09-02 21:45:316275 MockRead reads[] = {
tombergan5d22c182017-01-11 02:05:356276 CreateMockRead(push_a, 1), CreateMockRead(push_b, 3),
baranovich212a1292014-09-02 21:45:316277 };
6278
bncdf80d44fd2016-07-15 20:27:416279 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:496280 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
tombergan5d22c182017-01-11 02:05:356281 SpdySerializedFrame priority_a(
6282 spdy_util_.ConstructSpdyPriority(4, 1, IDLE, true));
bncdf80d44fd2016-07-15 20:27:416283 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bncb03b1092016-04-06 11:19:556284 4, GOAWAY_PROTOCOL_ERROR,
baranovich212a1292014-09-02 21:45:316285 "New push stream id must be greater than the last accepted."));
6286 MockWrite writes[] = {
tombergan5d22c182017-01-11 02:05:356287 CreateMockWrite(req, 0), CreateMockWrite(priority_a, 2),
6288 CreateMockWrite(goaway, 4),
baranovich212a1292014-09-02 21:45:316289 };
6290
rch08e3aa3e2015-05-16 14:27:526291 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:016292 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:356293 NetLogWithSource(), nullptr);
baranovich212a1292014-09-02 21:45:316294 helper.RunToCompletion(&data);
6295 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:016296 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
baranovich212a1292014-09-02 21:45:316297}
6298
bnc76598ab2015-06-29 12:43:076299// Regression test for https://crbug.com/493348: request header exceeds 16 kB
6300// and thus sent in multiple frames when using HTTP/2.
bncd16676a2016-07-20 16:23:016301TEST_F(SpdyNetworkTransactionTest, LargeRequest) {
bnc76598ab2015-06-29 12:43:076302 const std::string kKey("foo");
6303 const std::string kValue(1 << 15, 'z');
6304
6305 HttpRequestInfo request;
6306 request.method = "GET";
bncb26024382016-06-29 02:39:456307 request.url = default_url_;
bnc76598ab2015-06-29 12:43:076308 request.extra_headers.SetHeader(kKey, kValue);
6309
bncb26024382016-06-29 02:39:456310 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc086b39e12016-06-24 13:05:266311 headers[kKey] = kValue;
bncdf80d44fd2016-07-15 20:27:416312 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:156313 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bnc76598ab2015-06-29 12:43:076314 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416315 CreateMockWrite(req, 0),
bnc76598ab2015-06-29 12:43:076316 };
6317
bnc42331402016-07-25 13:36:156318 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:416319 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc76598ab2015-06-29 12:43:076320 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416321 CreateMockRead(resp, 1), CreateMockRead(body, 2),
bnc76598ab2015-06-29 12:43:076322 MockRead(ASYNC, 0, 3) // EOF
6323 };
6324
6325 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
tfarina428341112016-09-22 13:38:206326 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6327 NetLogWithSource(), nullptr);
bnc76598ab2015-06-29 12:43:076328 helper.RunToCompletion(&data);
6329 TransactionHelperResult out = helper.output();
6330
robpercival214763f2016-07-01 23:27:016331 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:026332 EXPECT_EQ("HTTP/1.1 200", out.status_line);
bnc76598ab2015-06-29 12:43:076333 EXPECT_EQ("hello!", out.response_data);
6334}
6335
bncd67383342016-01-08 21:58:436336// Regression test for https://crbug.com/535629: response header exceeds 16 kB.
bncd16676a2016-07-20 16:23:016337TEST_F(SpdyNetworkTransactionTest, LargeResponseHeader) {
bncb26024382016-06-29 02:39:456338 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bncdf80d44fd2016-07-15 20:27:416339 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:156340 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bncd67383342016-01-08 21:58:436341 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416342 CreateMockWrite(req, 0),
bncd67383342016-01-08 21:58:436343 };
6344
6345 // HPACK decoder implementation limits string literal length to 16 kB.
6346 const char* response_headers[2];
6347 const std::string kKey(16 * 1024, 'a');
6348 response_headers[0] = kKey.data();
6349 const std::string kValue(16 * 1024, 'b');
6350 response_headers[1] = kValue.data();
6351
bncdf80d44fd2016-07-15 20:27:416352 SpdySerializedFrame resp(
bnc42331402016-07-25 13:36:156353 spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1));
bncdf80d44fd2016-07-15 20:27:416354 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bncd67383342016-01-08 21:58:436355 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416356 CreateMockRead(resp, 1), CreateMockRead(body, 2),
bncd67383342016-01-08 21:58:436357 MockRead(ASYNC, 0, 3) // EOF
6358 };
6359
6360 HttpRequestInfo request;
6361 request.method = "GET";
bncb26024382016-06-29 02:39:456362 request.url = default_url_;
tfarina428341112016-09-22 13:38:206363 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6364 NetLogWithSource(), nullptr);
bncd67383342016-01-08 21:58:436365
6366 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6367 helper.RunToCompletion(&data);
6368 TransactionHelperResult out = helper.output();
6369
robpercival214763f2016-07-01 23:27:016370 EXPECT_THAT(out.rv, IsOk());
bncd67383342016-01-08 21:58:436371 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6372 EXPECT_EQ("hello!", out.response_data);
6373 ASSERT_TRUE(out.response_info.headers->HasHeaderValue(kKey, kValue));
6374}
6375
bnc204a6d02016-08-01 14:34:276376// End of line delimiter is forbidden according to RFC 7230 Section 3.2.
6377TEST_F(SpdyNetworkTransactionTest, CRLFInHeaderValue) {
6378 SpdySerializedFrame req(
6379 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
6380 SpdySerializedFrame rst(
6381 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
6382 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 2)};
6383
6384 const char* response_headers[] = {"folded", "foo\r\nbar"};
6385 SpdySerializedFrame resp(
6386 spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1));
6387 MockRead reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3)};
6388
6389 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6390
6391 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
tfarina428341112016-09-22 13:38:206392 NetLogWithSource(), nullptr);
bnc204a6d02016-08-01 14:34:276393 helper.RunToCompletion(&data);
6394 TransactionHelperResult out = helper.output();
6395
6396 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
6397}
6398
bncc22b581e82016-10-27 04:45:426399// Regression test for https://crbug.com/603182.
6400// No response headers received before RST_STREAM: error.
6401TEST_F(SpdyNetworkTransactionTest, RstStreamNoError) {
6402 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
6403 MockWrite writes[] = {CreateMockWrite(req, 0, ASYNC)};
6404
6405 SpdySerializedFrame rst(
6406 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_NO_ERROR));
6407 MockRead reads[] = {CreateMockRead(rst, 1), MockRead(ASYNC, 0, 2)};
6408
6409 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6410 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
6411 DEFAULT_PRIORITY, NetLogWithSource(),
6412 nullptr);
6413 helper.RunToCompletion(&data);
6414 TransactionHelperResult out = helper.output();
6415 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
6416}
6417
6418// Regression test for https://crbug.com/603182.
6419// Response headers and data, then RST_STREAM received,
6420// before request body is sent: success.
6421TEST_F(SpdyNetworkTransactionTest, RstStreamNoErrorAfterResponse) {
6422 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
6423 MockWrite writes[] = {CreateMockWrite(req, 0, ASYNC)};
6424
6425 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
6426 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6427 SpdySerializedFrame rst(
6428 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_NO_ERROR));
6429 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
6430 CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
6431
6432 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6433 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
6434 DEFAULT_PRIORITY, NetLogWithSource(),
6435 nullptr);
6436 helper.RunToCompletion(&data);
6437 TransactionHelperResult out = helper.output();
6438 EXPECT_THAT(out.rv, IsOk());
6439 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6440 EXPECT_EQ("hello!", out.response_data);
6441}
6442
bncc9f762a2016-12-06 20:38:236443TEST_F(SpdyNetworkTransactionTest, 100Continue) {
6444 SpdySerializedFrame req(
6445 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
6446 MockWrite writes[] = {CreateMockWrite(req, 0)};
6447
6448 SpdyHeaderBlock informational_headers;
6449 informational_headers[spdy_util_.GetStatusKey()] = "100";
6450 SpdySerializedFrame informational_response(
6451 spdy_util_.ConstructSpdyReply(1, std::move(informational_headers)));
6452 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6453 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6454 MockRead reads[] = {
6455 CreateMockRead(informational_response, 1), CreateMockRead(resp, 2),
6456 CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF
6457 };
6458
6459 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6460 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6461 NetLogWithSource(), nullptr);
6462 helper.RunToCompletion(&data);
6463 TransactionHelperResult out = helper.output();
6464 EXPECT_THAT(out.rv, IsOk());
6465 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6466 EXPECT_EQ("hello!", out.response_data);
6467}
6468
bnc1ff80872016-12-16 20:57:576469// "A server can send a complete response prior to the client sending an entire
6470// request if the response does not depend on any portion of the request that
6471// has not been sent and received." (RFC7540 Section 8.1)
6472// Regression test for https://crbug.com/606990. Server responds before POST
6473// data are sent and closes connection: this must result in
6474// ERR_CONNECTION_CLOSED (as opposed to ERR_SPDY_PROTOCOL_ERROR).
6475TEST_F(SpdyNetworkTransactionTest, ResponseBeforePostDataSent) {
6476 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
6477 MockWrite writes[] = {CreateMockWrite(req, 0)};
6478
6479 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
6480 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6481 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
6482 MockRead(ASYNC, 0, 3)};
6483
6484 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6485 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
6486 DEFAULT_PRIORITY, NetLogWithSource(),
6487 nullptr);
6488
6489 helper.RunPreTestSetup();
6490 helper.AddData(&data);
6491 helper.StartDefaultTest();
6492 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
6493 helper.WaitForCallbackToComplete();
6494 EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED));
6495}
6496
6497// Regression test for https://crbug.com/606990.
6498// Server responds before POST data are sent and resets stream with NO_ERROR.
6499TEST_F(SpdyNetworkTransactionTest, ResponseAndRstStreamBeforePostDataSent) {
6500 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
6501 MockWrite writes[] = {CreateMockWrite(req, 0)};
6502
6503 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
6504 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6505 SpdySerializedFrame rst(
6506 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_NO_ERROR));
6507 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2),
6508 CreateMockRead(rst, 3), MockRead(ASYNC, 0, 4)};
6509
6510 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6511 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
6512 DEFAULT_PRIORITY, NetLogWithSource(),
6513 nullptr);
6514
6515 helper.RunToCompletion(&data);
6516
6517 TransactionHelperResult out = helper.output();
6518 EXPECT_THAT(out.rv, IsOk());
6519 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6520 EXPECT_EQ("hello!", out.response_data);
6521}
6522
[email protected]514aeaf2014-05-23 10:31:516523class SpdyNetworkTransactionTLSUsageCheckTest
6524 : public SpdyNetworkTransactionTest {
6525 protected:
danakjaee3e1ec2016-04-16 00:23:186526 void RunTLSUsageCheckTest(
6527 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
bncdf80d44fd2016-07-15 20:27:416528 SpdySerializedFrame goaway(
[email protected]bdd1b222014-06-10 11:08:396529 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
bncdf80d44fd2016-07-15 20:27:416530 MockWrite writes[] = {CreateMockWrite(goaway)};
[email protected]514aeaf2014-05-23 10:31:516531
tombergan5d22c182017-01-11 02:05:356532 StaticSocketDataProvider data(nullptr, 0, writes, arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516533 HttpRequestInfo request;
6534 request.method = "GET";
bncb26024382016-06-29 02:39:456535 request.url = default_url_;
tfarina428341112016-09-22 13:38:206536 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
tombergan5d22c182017-01-11 02:05:356537 NetLogWithSource(), nullptr);
dchengc7eeda422015-12-26 03:56:486538 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516539 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:016540 EXPECT_THAT(out.rv, IsError(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
[email protected]514aeaf2014-05-23 10:31:516541 }
6542};
6543
bncd16676a2016-07-20 16:23:016544TEST_F(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
danakjaee3e1ec2016-04-16 00:23:186545 std::unique_ptr<SSLSocketDataProvider> ssl_provider(
[email protected]514aeaf2014-05-23 10:31:516546 new SSLSocketDataProvider(ASYNC, OK));
6547 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6548 &ssl_provider->connection_status);
6549
dchengc7eeda422015-12-26 03:56:486550 RunTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516551}
6552
bncd16676a2016-07-20 16:23:016553TEST_F(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
danakjaee3e1ec2016-04-16 00:23:186554 std::unique_ptr<SSLSocketDataProvider> ssl_provider(
[email protected]514aeaf2014-05-23 10:31:516555 new SSLSocketDataProvider(ASYNC, OK));
6556 // Set to TLS_RSA_WITH_NULL_MD5
6557 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6558
dchengc7eeda422015-12-26 03:56:486559 RunTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516560}
6561
[email protected]aea80602009-09-18 00:55:086562} // namespace net