blob: 473e7c5b74f7594218b6b7e2427baf0290b601be [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"
[email protected]87bfa3f2010-09-30 14:54:5629#include "net/http/http_network_session_peer.h"
[email protected]513963e2013-06-15 01:53:0430#include "net/http/http_network_transaction.h"
31#include "net/http/http_server_properties.h"
[email protected]c41737d2014-05-14 07:47:1932#include "net/http/http_transaction_test_util.h"
mmenke16a7cbdd2015-04-24 23:00:5633#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4634#include "net/log/test_net_log_entry.h"
35#include "net/log/test_net_log_util.h"
tbansal28e68f82016-02-04 02:56:1536#include "net/proxy/proxy_server.h"
[email protected]2d6728692011-03-12 01:39:5537#include "net/socket/client_socket_pool_base.h"
[email protected]bb88e1d32013-05-03 23:11:0738#include "net/socket/next_proto.h"
[email protected]f54c85792012-03-08 19:06:4139#include "net/spdy/buffered_spdy_framer.h"
[email protected]9be804c82010-06-24 17:59:4640#include "net/spdy/spdy_http_stream.h"
[email protected]9e1bdd32011-02-03 21:48:3441#include "net/spdy/spdy_http_utils.h"
[email protected]bdebd1b2010-08-09 20:18:0842#include "net/spdy/spdy_session.h"
[email protected]19ec8a72010-08-23 03:38:2343#include "net/spdy/spdy_session_pool.h"
[email protected]86aa87b2013-02-15 01:10:0344#include "net/spdy/spdy_test_util_common.h"
[email protected]a4bfdf72013-02-22 04:06:1645#include "net/spdy/spdy_test_utils.h"
[email protected]514aeaf2014-05-23 10:31:5146#include "net/ssl/ssl_connection_status_flags.h"
bncce36dca22015-04-21 22:11:2347#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0148#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4349#include "net/test/test_data_directory.h"
[email protected]d2db0292011-01-26 20:23:4450#include "net/url_request/url_request_test_util.h"
[email protected]251029e2014-03-19 06:04:4051#include "testing/gmock/include/gmock/gmock.h"
[email protected]aea80602009-09-18 00:55:0852#include "testing/platform_test.h"
53
robpercival214763f2016-07-01 23:27:0154using net::test::IsError;
55using net::test::IsOk;
56
[email protected]aea80602009-09-18 00:55:0857//-----------------------------------------------------------------------------
58
[email protected]d1eda932009-11-04 01:03:1059namespace net {
[email protected]dae22c52010-07-30 02:16:3560
[email protected]cbdd73162013-03-18 23:27:3361namespace {
[email protected]251029e2014-03-19 06:04:4062
63using testing::Each;
64using testing::Eq;
65
xunjieli179a6e72016-04-26 19:47:4566const int32_t kBufferSize = SpdyHttpStream::kRequestBodyBufferSize;
67
[email protected]513963e2013-06-15 01:53:0468} // namespace
69
bncd16676a2016-07-20 16:23:0170class SpdyNetworkTransactionTest : public ::testing::Test {
[email protected]34437af82009-11-06 02:28:4971 protected:
rdsmithebb50aa2015-11-12 03:44:3872 SpdyNetworkTransactionTest()
bncb26024382016-06-29 02:39:4573 : default_url_(kDefaultUrl),
bncd16676a2016-07-20 16:23:0174 host_port_pair_(HostPortPair::FromURL(default_url_)) {}
[email protected]2d6728692011-03-12 01:39:5575
bncd16676a2016-07-20 16:23:0176 ~SpdyNetworkTransactionTest() override {
mmenkecbc2b712014-10-09 20:29:0777 // UploadDataStream may post a deletion tasks back to the message loop on
[email protected]fc9d88472013-08-14 02:31:1778 // destruction.
79 upload_data_stream_.reset();
80 base::RunLoop().RunUntilIdle();
81 }
82
dcheng67be2b1f2014-10-27 21:47:2983 void SetUp() override {
bncce36dca22015-04-21 22:11:2384 get_request_initialized_ = false;
85 post_request_initialized_ = false;
86 chunked_post_request_initialized_ = false;
[email protected]69e6b4a2012-10-18 08:03:0187 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]aea80602009-09-18 00:55:0888 }
89
[email protected]72552f02009-10-28 15:25:0190 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:0891 int rv;
92 std::string status_line;
93 std::string response_data;
[email protected]8b070372009-11-16 22:01:2594 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:0895 };
96
[email protected]3caf5542010-07-16 15:19:4797 // A helper class that handles all the initial npn/ssl setup.
98 class NormalSpdyTransactionHelper {
99 public:
rdsmith82957ad2015-09-16 19:42:03100 NormalSpdyTransactionHelper(
101 const HttpRequestInfo& request,
102 RequestPriority priority,
103 const BoundNetLog& log,
danakjaee3e1ec2016-04-16 00:23:18104 std::unique_ptr<SpdySessionDependencies> session_deps)
[email protected]30c942b2010-07-21 16:59:59105 : request_(request),
[email protected]262eec82013-03-19 21:01:36106 priority_(priority),
bncd16676a2016-07-20 16:23:01107 session_deps_(session_deps.get() == NULL
108 ? base::MakeUnique<SpdySessionDependencies>()
109 : std::move(session_deps)),
rchebf12982015-04-10 01:15:00110 session_(
111 SpdySessionDependencies::SpdyCreateSession(session_deps_.get())),
bnc927c4962016-07-21 14:45:59112 log_(log) {}
[email protected]61b4efc2012-04-27 18:12:50113
[email protected]19ec8a72010-08-23 03:38:23114 ~NormalSpdyTransactionHelper() {
115 // Any test which doesn't close the socket by sending it an EOF will
116 // have a valid session left open, which leaks the entire session pool.
117 // This is just fine - in fact, some of our tests intentionally do this
118 // so that we can check consistency of the SpdySessionPool as the test
119 // finishes. If we had put an EOF on the socket, the SpdySession would
120 // have closed and we wouldn't be able to check the consistency.
121
122 // Forcefully close existing sessions here.
123 session()->spdy_session_pool()->CloseAllSessions();
124 }
125
[email protected]3caf5542010-07-16 15:19:47126 void RunPreTestSetup() {
[email protected]3caf5542010-07-16 15:19:47127 // We're now ready to use SSL-npn SPDY.
[email protected]90499482013-06-01 00:39:50128 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
[email protected]cb54b3b22010-06-03 16:28:55129 }
[email protected]aea80602009-09-18 00:55:08130
[email protected]3caf5542010-07-16 15:19:47131 // Start the transaction, read some data, finish.
132 void RunDefaultTest() {
[email protected]34b345f92013-02-22 03:27:26133 if (!StartDefaultTest())
134 return;
135 FinishDefaultTest();
136 }
137
138 bool StartDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51139 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
[email protected]aea80602009-09-18 00:55:08140
[email protected]3caf5542010-07-16 15:19:47141 // We expect an IO Pending or some sort of error.
142 EXPECT_LT(output_.rv, 0);
[email protected]34b345f92013-02-22 03:27:26143 return output_.rv == ERR_IO_PENDING;
144 }
[email protected]aea80602009-09-18 00:55:08145
[email protected]34b345f92013-02-22 03:27:26146 void FinishDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51147 output_.rv = callback_.WaitForResult();
[email protected]3caf5542010-07-16 15:19:47148 if (output_.rv != OK) {
bnc301745a2015-03-10 03:22:16149 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
[email protected]3caf5542010-07-16 15:19:47150 return;
151 }
[email protected]ff57bb82009-11-12 06:52:14152
[email protected]3caf5542010-07-16 15:19:47153 // Verify responses.
154 const HttpResponseInfo* response = trans_->GetResponseInfo();
wezca1070932016-05-26 20:30:52155 ASSERT_TRUE(response);
156 ASSERT_TRUE(response->headers);
bnc927c4962016-07-21 14:45:59157 EXPECT_EQ(HttpResponseInfo::ConnectionInfoFromNextProto(kProtoHTTP2),
158 response->connection_info);
159 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
160 EXPECT_TRUE(response->was_fetched_via_spdy);
161 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]80a09a82012-11-16 17:40:06162 EXPECT_EQ("127.0.0.1", response->socket_address.host());
bncb26024382016-06-29 02:39:45163 EXPECT_EQ(443, response->socket_address.port());
[email protected]3caf5542010-07-16 15:19:47164 output_.status_line = response->headers->GetStatusLine();
165 output_.response_info = *response; // Make a copy so we can verify.
166 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
[email protected]3caf5542010-07-16 15:19:47167 }
168
bncfacdd852015-01-09 19:22:54169 void FinishDefaultTestWithoutVerification() {
170 output_.rv = callback_.WaitForResult();
171 if (output_.rv != OK)
bnc301745a2015-03-10 03:22:16172 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
bncfacdd852015-01-09 19:22:54173 }
174
maksim.sisov8d2df66d2016-06-20 07:07:11175 void WaitForCallbackToComplete() { output_.rv = callback_.WaitForResult(); }
mmenke666a6fea2015-12-19 04:16:33176
[email protected]3caf5542010-07-16 15:19:47177 // Most tests will want to call this function. In particular, the MockReads
178 // should end with an empty read, and that read needs to be processed to
179 // ensure proper deletion of the spdy_session_pool.
180 void VerifyDataConsumed() {
rch08e3aa3e2015-05-16 14:27:52181 for (const SocketDataProvider* provider : data_vector_) {
182 EXPECT_TRUE(provider->AllReadDataConsumed());
183 EXPECT_TRUE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47184 }
185 }
186
187 // Occasionally a test will expect to error out before certain reads are
188 // processed. In that case we want to explicitly ensure that the reads were
189 // not processed.
190 void VerifyDataNotConsumed() {
rch08e3aa3e2015-05-16 14:27:52191 for (const SocketDataProvider* provider : data_vector_) {
192 EXPECT_FALSE(provider->AllReadDataConsumed());
193 EXPECT_FALSE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47194 }
195 }
196
rch08e3aa3e2015-05-16 14:27:52197 void RunToCompletion(SocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47198 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58199 AddData(data);
[email protected]3caf5542010-07-16 15:19:47200 RunDefaultTest();
201 VerifyDataConsumed();
202 }
[email protected]e6b06862010-07-20 16:32:58203
[email protected]514aeaf2014-05-23 10:31:51204 void RunToCompletionWithSSLData(
rch08e3aa3e2015-05-16 14:27:52205 SocketDataProvider* data,
danakjaee3e1ec2016-04-16 00:23:18206 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]514aeaf2014-05-23 10:31:51207 RunPreTestSetup();
dchengc7eeda422015-12-26 03:56:48208 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:51209 RunDefaultTest();
210 VerifyDataConsumed();
211 }
212
rch08e3aa3e2015-05-16 14:27:52213 void AddData(SocketDataProvider* data) {
danakjaee3e1ec2016-04-16 00:23:18214 std::unique_ptr<SSLSocketDataProvider> ssl_provider(
[email protected]514aeaf2014-05-23 10:31:51215 new SSLSocketDataProvider(ASYNC, OK));
bncce36dca22015-04-21 22:11:23216 ssl_provider->cert =
217 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
dchengc7eeda422015-12-26 03:56:48218 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:51219 }
220
221 void AddDataWithSSLSocketDataProvider(
rch08e3aa3e2015-05-16 14:27:52222 SocketDataProvider* data,
danakjaee3e1ec2016-04-16 00:23:18223 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]3caf5542010-07-16 15:19:47224 data_vector_.push_back(data);
bnc3cf2a592016-08-11 14:48:36225 if (ssl_provider->next_proto == kProtoUnknown)
226 ssl_provider->next_proto = kProtoHTTP2;
rchebf12982015-04-10 01:15:00227
228 session_deps_->socket_factory->AddSSLSocketDataProvider(
229 ssl_provider.get());
olli.raulaae011c422015-12-10 07:38:51230 ssl_vector_.push_back(std::move(ssl_provider));
[email protected]d4f00222012-07-10 06:24:51231
[email protected]3b7828432010-08-18 18:33:27232 session_deps_->socket_factory->AddSocketDataProvider(data);
[email protected]3b7828432010-08-18 18:33:27233 }
234
[email protected]3caf5542010-07-16 15:19:47235 HttpNetworkTransaction* trans() { return trans_.get(); }
236 void ResetTrans() { trans_.reset(); }
237 TransactionHelperResult& output() { return output_; }
[email protected]19ec8a72010-08-23 03:38:23238 const HttpRequestInfo& request() const { return request_; }
mmenkee65e7af2015-10-13 17:16:42239 HttpNetworkSession* session() const { return session_.get(); }
bncd16676a2016-07-20 16:23:01240 SpdySessionDependencies* session_deps() { return session_deps_.get(); }
[email protected]3caf5542010-07-16 15:19:47241
242 private:
rch08e3aa3e2015-05-16 14:27:52243 typedef std::vector<SocketDataProvider*> DataVector;
danakjaee3e1ec2016-04-16 00:23:18244 typedef std::vector<std::unique_ptr<SSLSocketDataProvider>> SSLVector;
245 typedef std::vector<std::unique_ptr<SocketDataProvider>> AlternateVector;
[email protected]3caf5542010-07-16 15:19:47246 HttpRequestInfo request_;
[email protected]262eec82013-03-19 21:01:36247 RequestPriority priority_;
danakjaee3e1ec2016-04-16 00:23:18248 std::unique_ptr<SpdySessionDependencies> session_deps_;
249 std::unique_ptr<HttpNetworkSession> session_;
[email protected]3caf5542010-07-16 15:19:47250 TransactionHelperResult output_;
danakjaee3e1ec2016-04-16 00:23:18251 std::unique_ptr<SocketDataProvider> first_transaction_;
[email protected]3caf5542010-07-16 15:19:47252 SSLVector ssl_vector_;
[email protected]514aeaf2014-05-23 10:31:51253 TestCompletionCallback callback_;
danakjaee3e1ec2016-04-16 00:23:18254 std::unique_ptr<HttpNetworkTransaction> trans_;
255 std::unique_ptr<HttpNetworkTransaction> trans_http_;
[email protected]3caf5542010-07-16 15:19:47256 DataVector data_vector_;
[email protected]2d6728692011-03-12 01:39:55257 AlternateVector alternate_vector_;
bnc29b1f072015-01-14 20:37:49258 const BoundNetLog log_;
[email protected]3caf5542010-07-16 15:19:47259 };
[email protected]aea80602009-09-18 00:55:08260
261 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
262 int expected_status);
263
264 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18265
[email protected]e3ebba0f2010-08-05 17:59:58266 const HttpRequestInfo& CreateGetPushRequest() {
bncce36dca22015-04-21 22:11:23267 get_push_request_.method = "GET";
268 get_push_request_.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
269 get_push_request_.load_flags = 0;
270 return get_push_request_;
[email protected]e3ebba0f2010-08-05 17:59:58271 }
272
[email protected]d3cee19d2010-06-22 18:42:18273 const HttpRequestInfo& CreateGetRequest() {
bncce36dca22015-04-21 22:11:23274 if (!get_request_initialized_) {
275 get_request_.method = "GET";
bncb26024382016-06-29 02:39:45276 get_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23277 get_request_.load_flags = 0;
278 get_request_initialized_ = true;
[email protected]d3cee19d2010-06-22 18:42:18279 }
bncce36dca22015-04-21 22:11:23280 return get_request_;
[email protected]d3cee19d2010-06-22 18:42:18281 }
282
[email protected]3deb9a52010-11-11 00:24:40283 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
bncce36dca22015-04-21 22:11:23284 if (!get_request_initialized_) {
285 get_request_.method = "GET";
bncb26024382016-06-29 02:39:45286 get_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23287 get_request_.load_flags = 0;
288 get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
289 get_request_initialized_ = true;
[email protected]3deb9a52010-11-11 00:24:40290 }
bncce36dca22015-04-21 22:11:23291 return get_request_;
[email protected]3deb9a52010-11-11 00:24:40292 }
293
[email protected]310240592010-08-05 21:04:19294 const HttpRequestInfo& CreatePostRequest() {
bncce36dca22015-04-21 22:11:23295 if (!post_request_initialized_) {
danakjaee3e1ec2016-04-16 00:23:18296 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
297 element_readers.push_back(base::WrapUnique(
olli.raula6df48b2a2015-11-26 07:40:22298 new UploadBytesElementReader(kUploadData, kUploadDataSize)));
[email protected]96c77a72013-09-24 09:49:20299 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22300 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27301
bncce36dca22015-04-21 22:11:23302 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45303 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23304 post_request_.upload_data_stream = upload_data_stream_.get();
305 post_request_initialized_ = true;
[email protected]310240592010-08-05 21:04:19306 }
bncce36dca22015-04-21 22:11:23307 return post_request_;
[email protected]310240592010-08-05 21:04:19308 }
309
[email protected]69e6b4a2012-10-18 08:03:01310 const HttpRequestInfo& CreateFilePostRequest() {
bncce36dca22015-04-21 22:11:23311 if (!post_request_initialized_) {
[email protected]6cdfd7f2013-02-08 20:40:15312 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52313 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01314 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30315 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01316
danakjaee3e1ec2016-04-16 00:23:18317 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
318 element_readers.push_back(base::WrapUnique(new UploadFileElementReader(
skyostil4891b25b2015-06-11 11:43:45319 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
olli.raula6df48b2a2015-11-26 07:40:22320 kUploadDataSize, base::Time())));
[email protected]96c77a72013-09-24 09:49:20321 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22322 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27323
bncce36dca22015-04-21 22:11:23324 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45325 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23326 post_request_.upload_data_stream = upload_data_stream_.get();
327 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01328 }
bncce36dca22015-04-21 22:11:23329 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01330 }
331
[email protected]999dd8c2013-11-12 06:45:54332 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
bncce36dca22015-04-21 22:11:23333 if (post_request_initialized_)
334 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54335
336 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52337 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]999dd8c2013-11-12 06:45:54338 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30339 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]92be8eb2014-08-07 22:57:11340 CHECK(base::MakeFileUnreadable(file_path));
[email protected]999dd8c2013-11-12 06:45:54341
danakjaee3e1ec2016-04-16 00:23:18342 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
343 element_readers.push_back(base::WrapUnique(new UploadFileElementReader(
skyostil4891b25b2015-06-11 11:43:45344 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
olli.raula6df48b2a2015-11-26 07:40:22345 kUploadDataSize, base::Time())));
[email protected]999dd8c2013-11-12 06:45:54346 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22347 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]999dd8c2013-11-12 06:45:54348
bncce36dca22015-04-21 22:11:23349 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45350 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23351 post_request_.upload_data_stream = upload_data_stream_.get();
352 post_request_initialized_ = true;
353 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54354 }
355
[email protected]69e6b4a2012-10-18 08:03:01356 const HttpRequestInfo& CreateComplexPostRequest() {
bncce36dca22015-04-21 22:11:23357 if (!post_request_initialized_) {
[email protected]69e6b4a2012-10-18 08:03:01358 const int kFileRangeOffset = 1;
359 const int kFileRangeLength = 3;
360 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
361
[email protected]6cdfd7f2013-02-08 20:40:15362 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52363 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01364 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30365 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01366
danakjaee3e1ec2016-04-16 00:23:18367 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
368 element_readers.push_back(base::WrapUnique(
olli.raula6df48b2a2015-11-26 07:40:22369 new UploadBytesElementReader(kUploadData, kFileRangeOffset)));
danakjaee3e1ec2016-04-16 00:23:18370 element_readers.push_back(base::WrapUnique(new UploadFileElementReader(
skyostil4891b25b2015-06-11 11:43:45371 base::ThreadTaskRunnerHandle::Get().get(), file_path,
olli.raula6df48b2a2015-11-26 07:40:22372 kFileRangeOffset, kFileRangeLength, base::Time())));
danakjaee3e1ec2016-04-16 00:23:18373 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader(
[email protected]69e6b4a2012-10-18 08:03:01374 kUploadData + kFileRangeOffset + kFileRangeLength,
olli.raula6df48b2a2015-11-26 07:40:22375 kUploadDataSize - (kFileRangeOffset + kFileRangeLength))));
[email protected]96c77a72013-09-24 09:49:20376 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22377 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27378
bncce36dca22015-04-21 22:11:23379 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45380 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23381 post_request_.upload_data_stream = upload_data_stream_.get();
382 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01383 }
bncce36dca22015-04-21 22:11:23384 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01385 }
386
[email protected]0c9bf872011-03-04 17:53:22387 const HttpRequestInfo& CreateChunkedPostRequest() {
bncce36dca22015-04-21 22:11:23388 if (!chunked_post_request_initialized_) {
mmenkecbc2b712014-10-09 20:29:07389 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
bncce36dca22015-04-21 22:11:23390 chunked_post_request_.method = "POST";
bncb26024382016-06-29 02:39:45391 chunked_post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23392 chunked_post_request_.upload_data_stream =
mmenkecbc2b712014-10-09 20:29:07393 upload_chunked_data_stream_.get();
bncce36dca22015-04-21 22:11:23394 chunked_post_request_initialized_ = true;
[email protected]0c9bf872011-03-04 17:53:22395 }
bncce36dca22015-04-21 22:11:23396 return chunked_post_request_;
[email protected]0c9bf872011-03-04 17:53:22397 }
398
[email protected]19ec8a72010-08-23 03:38:23399 // Read the result of a particular transaction, knowing that we've got
400 // multiple transactions in the read pipeline; so as we read, we may have
401 // to skip over data destined for other transactions while we consume
402 // the data for |trans|.
403 int ReadResult(HttpNetworkTransaction* trans,
[email protected]19ec8a72010-08-23 03:38:23404 std::string* result) {
405 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58406
[email protected]19ec8a72010-08-23 03:38:23407 int bytes_read = 0;
bnc301745a2015-03-10 03:22:16408 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(kSize));
[email protected]49639fa2011-12-20 23:22:41409 TestCompletionCallback callback;
[email protected]19ec8a72010-08-23 03:38:23410 while (true) {
[email protected]90499482013-06-01 00:39:50411 int rv = trans->Read(buf.get(), kSize, callback.callback());
[email protected]19ec8a72010-08-23 03:38:23412 if (rv == ERR_IO_PENDING) {
[email protected]19ec8a72010-08-23 03:38:23413 rv = callback.WaitForResult();
414 } else if (rv <= 0) {
415 break;
416 }
417 result->append(buf->data(), rv);
418 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58419 }
[email protected]19ec8a72010-08-23 03:38:23420 return bytes_read;
421 }
[email protected]e3ebba0f2010-08-05 17:59:58422
[email protected]19ec8a72010-08-23 03:38:23423 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
424 // This lengthy block is reaching into the pool to dig out the active
425 // session. Once we have the session, we verify that the streams are
426 // all closed and not leaked at this point.
427 const GURL& url = helper.request().url;
bncb26024382016-06-29 02:39:45428 SpdySessionKey key(HostPortPair::FromURL(url), ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:53429 PRIVACY_MODE_DISABLED);
[email protected]19ec8a72010-08-23 03:38:23430 BoundNetLog log;
mmenkee65e7af2015-10-13 17:16:42431 HttpNetworkSession* session = helper.session();
[email protected]795cbf82013-07-22 09:37:27432 base::WeakPtr<SpdySession> spdy_session =
bnc3e79387f2016-03-15 14:49:20433 session->spdy_session_pool()->FindAvailableSession(key, url, log);
wezca1070932016-05-26 20:30:52434 ASSERT_TRUE(spdy_session);
[email protected]19ec8a72010-08-23 03:38:23435 EXPECT_EQ(0u, spdy_session->num_active_streams());
436 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
437 }
[email protected]e3ebba0f2010-08-05 17:59:58438
rch08e3aa3e2015-05-16 14:27:52439 void RunServerPushTest(SequencedSocketData* data,
[email protected]e3ebba0f2010-08-05 17:59:58440 HttpResponseInfo* response,
[email protected]a7a265ef2010-12-08 18:05:57441 HttpResponseInfo* push_response,
[email protected]8a0fc822013-06-27 20:52:43442 const std::string& expected) {
[email protected]262eec82013-03-19 21:01:36443 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01444 BoundNetLog(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:58445 helper.RunPreTestSetup();
[email protected]d08358502010-12-03 22:04:03446 helper.AddData(data);
[email protected]e3ebba0f2010-08-05 17:59:58447
448 HttpNetworkTransaction* trans = helper.trans();
449
450 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:41451 TestCompletionCallback callback;
452 int rv = trans->Start(
453 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:01454 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:58455 rv = callback.WaitForResult();
456
457 // Request the pushed path.
bnc691fda62016-08-12 00:43:16458 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
459 rv = trans2.Start(&CreateGetPushRequest(), callback.callback(),
460 BoundNetLog());
robpercival214763f2016-07-01 23:27:01461 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:17462 base::RunLoop().RunUntilIdle();
[email protected]e3ebba0f2010-08-05 17:59:58463
[email protected]513963e2013-06-15 01:53:04464 // The data for the pushed path may be coming in more than 1 frame. Compile
[email protected]e3ebba0f2010-08-05 17:59:58465 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23466
467 // Read the server push body.
468 std::string result2;
bnc691fda62016-08-12 00:43:16469 ReadResult(&trans2, &result2);
[email protected]19ec8a72010-08-23 03:38:23470 // Read the response body.
[email protected]e3ebba0f2010-08-05 17:59:58471 std::string result;
rch0aecfd82015-05-19 17:22:32472 ReadResult(trans, &result);
[email protected]e3ebba0f2010-08-05 17:59:58473
474 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:17475 EXPECT_TRUE(data->AllReadDataConsumed());
476 EXPECT_TRUE(data->AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:58477
caseqe8340bc92016-04-20 00:02:57478 LoadTimingInfo load_timing_info;
479 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
480 EXPECT_TRUE(load_timing_info.push_start.is_null());
481 EXPECT_TRUE(load_timing_info.push_end.is_null());
482
483 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:16484 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
caseqe8340bc92016-04-20 00:02:57485 EXPECT_FALSE(load_timing_info2.push_start.is_null());
486 EXPECT_FALSE(load_timing_info2.push_end.is_null());
487
[email protected]e3ebba0f2010-08-05 17:59:58488 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23489 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
490 << result2
491 << "||||| Expected data: "
492 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58493
bnc42331402016-07-25 13:36:15494 // Verify the response HEADERS.
[email protected]e3ebba0f2010-08-05 17:59:58495 // Copy the response info, because trans goes away.
496 *response = *trans->GetResponseInfo();
bnc691fda62016-08-12 00:43:16497 *push_response = *trans2.GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23498
499 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58500 }
501
[email protected]49639fa2011-12-20 23:22:41502 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
503 int result) {
504 helper->ResetTrans();
505 }
506
mmenkee65e7af2015-10-13 17:16:42507 static void StartTransactionCallback(HttpNetworkSession* session,
508 GURL url,
509 int result) {
bnc691fda62016-08-12 00:43:16510 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]49639fa2011-12-20 23:22:41511 TestCompletionCallback callback;
512 HttpRequestInfo request;
513 request.method = "GET";
rchebf12982015-04-10 01:15:00514 request.url = url;
[email protected]49639fa2011-12-20 23:22:41515 request.load_flags = 0;
bnc691fda62016-08-12 00:43:16516 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:01517 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]49639fa2011-12-20 23:22:41518 callback.WaitForResult();
519 }
520
mmenkecbc2b712014-10-09 20:29:07521 ChunkedUploadDataStream* upload_chunked_data_stream() const {
522 return upload_chunked_data_stream_.get();
523 }
524
rchebf12982015-04-10 01:15:00525 std::string GetDefaultUrlWithPath(const char* path) {
bncb26024382016-06-29 02:39:45526 return std::string(kDefaultUrl) + path;
rchebf12982015-04-10 01:15:00527 }
528
bncb26024382016-06-29 02:39:45529 const GURL default_url_;
530 const HostPortPair host_port_pair_;
[email protected]9ec54f82013-05-10 02:53:05531 SpdyTestUtil spdy_util_;
532
[email protected]d3cee19d2010-06-22 18:42:18533 private:
danakjaee3e1ec2016-04-16 00:23:18534 std::unique_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
535 std::unique_ptr<UploadDataStream> upload_data_stream_;
bncce36dca22015-04-21 22:11:23536 bool get_request_initialized_;
537 bool post_request_initialized_;
538 bool chunked_post_request_initialized_;
539 HttpRequestInfo get_request_;
540 HttpRequestInfo post_request_;
541 HttpRequestInfo chunked_post_request_;
542 HttpRequestInfo get_push_request_;
[email protected]ea1a3f62012-11-16 20:34:23543 base::ScopedTempDir temp_dir_;
[email protected]aea80602009-09-18 00:55:08544};
545
[email protected]3caf5542010-07-16 15:19:47546// Verify HttpNetworkTransaction constructor.
bncd16676a2016-07-20 16:23:01547TEST_F(SpdyNetworkTransactionTest, Constructor) {
548 auto session_deps = base::MakeUnique<SpdySessionDependencies>();
danakjaee3e1ec2016-04-16 00:23:18549 std::unique_ptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:07550 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
bncd16676a2016-07-20 16:23:01551 auto trans =
552 base::MakeUnique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]aea80602009-09-18 00:55:08553}
554
bncd16676a2016-07-20 16:23:01555TEST_F(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38556 // Construct the request.
bncdf80d44fd2016-07-15 20:27:41557 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49558 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:41559 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]72552f02009-10-28 15:25:01560
bnc42331402016-07-25 13:36:15561 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:41562 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]72552f02009-10-28 15:25:01563 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41564 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:52565 MockRead(ASYNC, 0, 3) // EOF
[email protected]72552f02009-10-28 15:25:01566 };
567
rch08e3aa3e2015-05-16 14:27:52568 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:36569 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01570 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:57571 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:47572 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:01573 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02574 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]72552f02009-10-28 15:25:01575 EXPECT_EQ("hello!", out.response_data);
576}
577
bncd16676a2016-07-20 16:23:01578TEST_F(SpdyNetworkTransactionTest, GetAtEachPriority) {
[email protected]3d08dd382013-10-19 00:13:11579 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
[email protected]31ae7ab2012-04-24 21:09:05580 p = RequestPriority(p + 1)) {
bncd16676a2016-07-20 16:23:01581 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:49582
[email protected]c9c6f5c2010-07-31 01:30:03583 // Construct the request.
bncdf80d44fd2016-07-15 20:27:41584 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49585 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, p, true));
bncdf80d44fd2016-07-15 20:27:41586 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]c9c6f5c2010-07-31 01:30:03587
[email protected]86aa87b2013-02-15 01:10:03588 SpdyPriority spdy_prio = 0;
bncdf80d44fd2016-07-15 20:27:41589 EXPECT_TRUE(GetSpdyPriority(req, &spdy_prio));
[email protected]c9c6f5c2010-07-31 01:30:03590 // this repeats the RequestPriority-->SpdyPriority mapping from
591 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
592 // sure it's being done right.
bnc05808ff42016-01-08 23:48:25593 switch (p) {
594 case HIGHEST:
595 EXPECT_EQ(0, spdy_prio);
596 break;
597 case MEDIUM:
598 EXPECT_EQ(1, spdy_prio);
599 break;
600 case LOW:
601 EXPECT_EQ(2, spdy_prio);
602 break;
603 case LOWEST:
604 EXPECT_EQ(3, spdy_prio);
605 break;
606 case IDLE:
607 EXPECT_EQ(4, spdy_prio);
608 break;
609 default:
610 FAIL();
[email protected]c9c6f5c2010-07-31 01:30:03611 }
612
bncdf80d44fd2016-07-15 20:27:41613 SpdySerializedFrame resp(
bnc42331402016-07-25 13:36:15614 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41615 SpdySerializedFrame body(spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]c9c6f5c2010-07-31 01:30:03616 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41617 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:52618 MockRead(ASYNC, 0, 3) // EOF
[email protected]c9c6f5c2010-07-31 01:30:03619 };
620
rch08e3aa3e2015-05-16 14:27:52621 SequencedSocketData data(reads, arraysize(reads), writes,
622 arraysize(writes));
[email protected]c9c6f5c2010-07-31 01:30:03623 HttpRequestInfo http_req = CreateGetRequest();
[email protected]c9c6f5c2010-07-31 01:30:03624
bncd16676a2016-07-20 16:23:01625 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:57626 helper.RunToCompletion(&data);
[email protected]c9c6f5c2010-07-31 01:30:03627 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:01628 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02629 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]c9c6f5c2010-07-31 01:30:03630 EXPECT_EQ("hello!", out.response_data);
631 }
632}
633
[email protected]2bd93022010-07-17 00:58:44634// Start three gets simultaniously; making sure that multiplexed
635// streams work properly.
636
637// This can't use the TransactionHelper method, since it only
638// handles a single transaction, and finishes them as soon
639// as it launches them.
640
641// TODO(gavinp): create a working generalized TransactionHelper that
642// can allow multiple streams in flight.
643
bncd16676a2016-07-20 16:23:01644TEST_F(SpdyNetworkTransactionTest, ThreeGets) {
bncdf80d44fd2016-07-15 20:27:41645 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49646 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:15647 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:41648 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
649 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2bd93022010-07-17 00:58:44650
bncdf80d44fd2016-07-15 20:27:41651 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49652 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:15653 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:41654 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
655 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2bd93022010-07-17 00:58:44656
bncdf80d44fd2016-07-15 20:27:41657 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:49658 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
bnc42331402016-07-25 13:36:15659 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
bncdf80d44fd2016-07-15 20:27:41660 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
661 SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44662
[email protected]1b323172011-03-01 17:50:17663 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41664 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
665 CreateMockWrite(req3, 6),
[email protected]2bd93022010-07-17 00:58:44666 };
667 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41668 CreateMockRead(resp, 1), CreateMockRead(body, 2),
669 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
670 CreateMockRead(resp3, 7), CreateMockRead(body3, 8),
[email protected]2bd93022010-07-17 00:58:44671
bncdf80d44fd2016-07-15 20:27:41672 CreateMockRead(fbody, 9), CreateMockRead(fbody2, 10),
673 CreateMockRead(fbody3, 11),
[email protected]2bd93022010-07-17 00:58:44674
rch08e3aa3e2015-05-16 14:27:52675 MockRead(ASYNC, 0, 12), // EOF
[email protected]2bd93022010-07-17 00:58:44676 };
rch08e3aa3e2015-05-16 14:27:52677 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
mmenkecc2298e2015-12-07 18:20:18678 SequencedSocketData data_placeholder1(NULL, 0, NULL, 0);
679 SequencedSocketData data_placeholder2(NULL, 0, NULL, 0);
[email protected]2bd93022010-07-17 00:58:44680
681 BoundNetLog log;
682 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36683 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01684 BoundNetLog(), NULL);
[email protected]bdebd1b2010-08-09 20:18:08685 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57686 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49687 // We require placeholder data because three get requests are sent out at
688 // the same time which results in three sockets being connected. The first
689 // on will negotiate SPDY and will be used for all requests.
mmenkecc2298e2015-12-07 18:20:18690 helper.AddData(&data_placeholder1);
691 helper.AddData(&data_placeholder2);
bnc691fda62016-08-12 00:43:16692 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
693 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
694 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
[email protected]2bd93022010-07-17 00:58:44695
[email protected]49639fa2011-12-20 23:22:41696 TestCompletionCallback callback1;
697 TestCompletionCallback callback2;
698 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44699
[email protected]bdebd1b2010-08-09 20:18:08700 HttpRequestInfo httpreq1 = CreateGetRequest();
701 HttpRequestInfo httpreq2 = CreateGetRequest();
702 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:44703
bnc691fda62016-08-12 00:43:16704 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:01705 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16706 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:01707 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16708 out.rv = trans3.Start(&httpreq3, callback3.callback(), log);
robpercival214763f2016-07-01 23:27:01709 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]2bd93022010-07-17 00:58:44710
[email protected]bdebd1b2010-08-09 20:18:08711 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01712 ASSERT_THAT(out.rv, IsOk());
[email protected]bdebd1b2010-08-09 20:18:08713 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:01714 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44715
bnc691fda62016-08-12 00:43:16716 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52717 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:08718 EXPECT_TRUE(response1->was_fetched_via_spdy);
719 out.status_line = response1->headers->GetStatusLine();
720 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:44721
bnc691fda62016-08-12 00:43:16722 trans2.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:44723
bnc691fda62016-08-12 00:43:16724 out.rv = ReadTransaction(&trans1, &out.response_data);
[email protected]bdebd1b2010-08-09 20:18:08725 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:01726 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44727
robpercival214763f2016-07-01 23:27:01728 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02729 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:44730 EXPECT_EQ("hello!hello!", out.response_data);
731}
732
bncd16676a2016-07-20 16:23:01733TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
bncdf80d44fd2016-07-15 20:27:41734 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49735 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:15736 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:41737 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
738 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1b323172011-03-01 17:50:17739
bncdf80d44fd2016-07-15 20:27:41740 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49741 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:15742 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:41743 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
744 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]1b323172011-03-01 17:50:17745
746 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41747 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
[email protected]1b323172011-03-01 17:50:17748 };
749 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41750 CreateMockRead(resp, 1), CreateMockRead(body, 2),
751 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
752 CreateMockRead(fbody, 6), CreateMockRead(fbody2, 7),
rch08e3aa3e2015-05-16 14:27:52753 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:17754 };
rch08e3aa3e2015-05-16 14:27:52755 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1b323172011-03-01 17:50:17756
[email protected]d973e99a2012-02-17 21:02:36757 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
rch08e3aa3e2015-05-16 14:27:52758 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:57759 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17760
761 BoundNetLog log;
762 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36763 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01764 BoundNetLog(), NULL);
[email protected]1b323172011-03-01 17:50:17765 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57766 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49767 // We require placeholder data because two requests are sent out at
768 // the same time which results in two sockets being connected. The first
769 // on will negotiate SPDY and will be used for all requests.
[email protected]dd54bd82012-07-19 23:44:57770 helper.AddData(&data_placeholder);
bnc691fda62016-08-12 00:43:16771 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
772 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]1b323172011-03-01 17:50:17773
[email protected]49639fa2011-12-20 23:22:41774 TestCompletionCallback callback1;
775 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:17776
777 HttpRequestInfo httpreq1 = CreateGetRequest();
778 HttpRequestInfo httpreq2 = CreateGetRequest();
779
bnc691fda62016-08-12 00:43:16780 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:01781 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16782 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:01783 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]1b323172011-03-01 17:50:17784
785 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01786 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17787 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:01788 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17789
bnc691fda62016-08-12 00:43:16790 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52791 EXPECT_TRUE(response1->headers);
[email protected]1b323172011-03-01 17:50:17792 EXPECT_TRUE(response1->was_fetched_via_spdy);
793 out.status_line = response1->headers->GetStatusLine();
794 out.response_info = *response1;
bnc691fda62016-08-12 00:43:16795 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:01796 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02797 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17798 EXPECT_EQ("hello!hello!", out.response_data);
799
bnc691fda62016-08-12 00:43:16800 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:52801 EXPECT_TRUE(response2->headers);
[email protected]1b323172011-03-01 17:50:17802 EXPECT_TRUE(response2->was_fetched_via_spdy);
803 out.status_line = response2->headers->GetStatusLine();
804 out.response_info = *response2;
bnc691fda62016-08-12 00:43:16805 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:01806 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02807 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17808 EXPECT_EQ("hello!hello!", out.response_data);
809
810 helper.VerifyDataConsumed();
811}
812
bncd16676a2016-07-20 16:23:01813TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
bncdf80d44fd2016-07-15 20:27:41814 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49815 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:15816 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:41817 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
818 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1b323172011-03-01 17:50:17819
bncdf80d44fd2016-07-15 20:27:41820 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49821 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:15822 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:41823 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
824 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]1b323172011-03-01 17:50:17825
826 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41827 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
[email protected]1b323172011-03-01 17:50:17828 };
829 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41830 CreateMockRead(resp, 1), CreateMockRead(body, 2),
831 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
832 CreateMockRead(fbody, 6), CreateMockRead(fbody2, 7),
rch08e3aa3e2015-05-16 14:27:52833 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:17834 };
rch08e3aa3e2015-05-16 14:27:52835 SequencedSocketData preconnect_data(reads, arraysize(reads), writes,
836 arraysize(writes));
[email protected]1b323172011-03-01 17:50:17837
[email protected]d973e99a2012-02-17 21:02:36838 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
[email protected]1b323172011-03-01 17:50:17839
rch08e3aa3e2015-05-16 14:27:52840 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:57841 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17842
843 BoundNetLog log;
844 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36845 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01846 BoundNetLog(), NULL);
[email protected]1b323172011-03-01 17:50:17847 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57848 helper.AddData(&preconnect_data);
[email protected]1b323172011-03-01 17:50:17849 // We require placeholder data because 3 connections are attempted (first is
850 // the preconnect, 2nd and 3rd are the never finished connections.
[email protected]dd54bd82012-07-19 23:44:57851 helper.AddData(&data_placeholder);
852 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:17853
bnc691fda62016-08-12 00:43:16854 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
855 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]1b323172011-03-01 17:50:17856
[email protected]49639fa2011-12-20 23:22:41857 TestCompletionCallback callback1;
858 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:17859
860 HttpRequestInfo httpreq = CreateGetRequest();
861
862 // Preconnect the first.
[email protected]1b323172011-03-01 17:50:17863 HttpStreamFactory* http_stream_factory =
864 helper.session()->http_stream_factory();
[email protected]1b323172011-03-01 17:50:17865
nharper8cdb0fb2016-04-22 21:34:59866 http_stream_factory->PreconnectStreams(1, httpreq);
[email protected]1b323172011-03-01 17:50:17867
bnc691fda62016-08-12 00:43:16868 out.rv = trans1.Start(&httpreq, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:01869 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16870 out.rv = trans2.Start(&httpreq, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:01871 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]1b323172011-03-01 17:50:17872
873 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01874 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17875 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:01876 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17877
bnc691fda62016-08-12 00:43:16878 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52879 EXPECT_TRUE(response1->headers);
[email protected]1b323172011-03-01 17:50:17880 EXPECT_TRUE(response1->was_fetched_via_spdy);
881 out.status_line = response1->headers->GetStatusLine();
882 out.response_info = *response1;
bnc691fda62016-08-12 00:43:16883 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:01884 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02885 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17886 EXPECT_EQ("hello!hello!", out.response_data);
887
bnc691fda62016-08-12 00:43:16888 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:52889 EXPECT_TRUE(response2->headers);
[email protected]1b323172011-03-01 17:50:17890 EXPECT_TRUE(response2->was_fetched_via_spdy);
891 out.status_line = response2->headers->GetStatusLine();
892 out.response_info = *response2;
bnc691fda62016-08-12 00:43:16893 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:01894 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02895 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17896 EXPECT_EQ("hello!hello!", out.response_data);
897
898 helper.VerifyDataConsumed();
899}
900
[email protected]2bd93022010-07-17 00:58:44901// Similar to ThreeGets above, however this test adds a SETTINGS
902// frame. The SETTINGS frame is read during the IO loop waiting on
903// the first transaction completion, and sets a maximum concurrent
904// stream limit of 1. This means that our IO loop exists after the
905// second transaction completes, so we can assert on read_index().
bncd16676a2016-07-20 16:23:01906TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:44907 // Construct the request.
rdsmithebb50aa2015-11-12 03:44:38908 // Each request fully completes before the next starts.
bncdf80d44fd2016-07-15 20:27:41909 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49910 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:15911 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:41912 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
913 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:38914 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:44915
bncdf80d44fd2016-07-15 20:27:41916 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49917 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:15918 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:41919 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
920 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:38921 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:44922
bncdf80d44fd2016-07-15 20:27:41923 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:49924 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
bnc42331402016-07-25 13:36:15925 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
bncdf80d44fd2016-07-15 20:27:41926 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
927 SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44928
[email protected]18b28ab2012-04-18 02:14:42929 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:46930 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:42931 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
932 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
bncdf80d44fd2016-07-15 20:27:41933 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:20934 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:41935 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:44936
[email protected]2d6728692011-03-12 01:39:55937 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41938 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
939 CreateMockWrite(req2, 6), CreateMockWrite(req3, 10),
[email protected]2bd93022010-07-17 00:58:44940 };
[email protected]2d6728692011-03-12 01:39:55941
[email protected]2bd93022010-07-17 00:58:44942 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41943 CreateMockRead(settings_frame, 1),
944 CreateMockRead(resp, 2),
945 CreateMockRead(body, 3),
946 CreateMockRead(fbody, 4),
947 CreateMockRead(resp2, 7),
948 CreateMockRead(body2, 8),
949 CreateMockRead(fbody2, 9),
950 CreateMockRead(resp3, 11),
951 CreateMockRead(body3, 12),
952 CreateMockRead(fbody3, 13),
[email protected]2bd93022010-07-17 00:58:44953
rch08e3aa3e2015-05-16 14:27:52954 MockRead(ASYNC, 0, 14), // EOF
[email protected]2bd93022010-07-17 00:58:44955 };
956
rch08e3aa3e2015-05-16 14:27:52957 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:44958
959 BoundNetLog log;
960 TransactionHelperResult out;
961 {
[email protected]262eec82013-03-19 21:01:36962 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01963 BoundNetLog(), NULL);
[email protected]2d6728692011-03-12 01:39:55964 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57965 helper.AddData(&data);
bnc691fda62016-08-12 00:43:16966 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
967 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
968 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
[email protected]2bd93022010-07-17 00:58:44969
[email protected]49639fa2011-12-20 23:22:41970 TestCompletionCallback callback1;
971 TestCompletionCallback callback2;
972 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44973
974 HttpRequestInfo httpreq1 = CreateGetRequest();
975 HttpRequestInfo httpreq2 = CreateGetRequest();
976 HttpRequestInfo httpreq3 = CreateGetRequest();
977
bnc691fda62016-08-12 00:43:16978 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]2bd93022010-07-17 00:58:44979 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]513963e2013-06-15 01:53:04980 // Run transaction 1 through quickly to force a read of our SETTINGS
981 // frame.
[email protected]2bd93022010-07-17 00:58:44982 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01983 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44984
bnc691fda62016-08-12 00:43:16985 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]2bd93022010-07-17 00:58:44986 ASSERT_EQ(out.rv, ERR_IO_PENDING);
bnc691fda62016-08-12 00:43:16987 out.rv = trans3.Start(&httpreq3, callback3.callback(), log);
[email protected]2bd93022010-07-17 00:58:44988 ASSERT_EQ(out.rv, ERR_IO_PENDING);
989 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:01990 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44991
992 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:01993 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44994
bnc691fda62016-08-12 00:43:16995 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52996 ASSERT_TRUE(response1);
997 EXPECT_TRUE(response1->headers);
[email protected]2bd93022010-07-17 00:58:44998 EXPECT_TRUE(response1->was_fetched_via_spdy);
999 out.status_line = response1->headers->GetStatusLine();
1000 out.response_info = *response1;
bnc691fda62016-08-12 00:43:161001 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011002 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021003 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441004 EXPECT_EQ("hello!hello!", out.response_data);
1005
bnc691fda62016-08-12 00:43:161006 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:441007 out.status_line = response2->headers->GetStatusLine();
1008 out.response_info = *response2;
bnc691fda62016-08-12 00:43:161009 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011010 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021011 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441012 EXPECT_EQ("hello!hello!", out.response_data);
1013
bnc691fda62016-08-12 00:43:161014 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:441015 out.status_line = response3->headers->GetStatusLine();
1016 out.response_info = *response3;
bnc691fda62016-08-12 00:43:161017 out.rv = ReadTransaction(&trans3, &out.response_data);
robpercival214763f2016-07-01 23:27:011018 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021019 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441020 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:261021
1022 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441023 }
robpercival214763f2016-07-01 23:27:011024 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441025}
1026
1027// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1028// a fourth transaction. The third and fourth transactions have
1029// different data ("hello!" vs "hello!hello!") and because of the
1030// user specified priority, we expect to see them inverted in
1031// the response from the server.
bncd16676a2016-07-20 16:23:011032TEST_F(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:441033 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411034 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491035 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:151036 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411037 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1038 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381039 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441040
bncdf80d44fd2016-07-15 20:27:411041 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:491042 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:151043 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:411044 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1045 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:381046 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:441047
bncdf80d44fd2016-07-15 20:27:411048 SpdySerializedFrame req4(
bnc38dcd392016-02-09 23:19:491049 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, HIGHEST, true));
bnc42331402016-07-25 13:36:151050 SpdySerializedFrame resp4(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
bncdf80d44fd2016-07-15 20:27:411051 SpdySerializedFrame fbody4(spdy_util_.ConstructSpdyDataFrame(5, true));
rdsmithebb50aa2015-11-12 03:44:381052 spdy_util_.UpdateWithStreamDestruction(5);
[email protected]2bd93022010-07-17 00:58:441053
bncdf80d44fd2016-07-15 20:27:411054 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:491055 spdy_util_.ConstructSpdyGet(nullptr, 0, 7, LOWEST, true));
bnc42331402016-07-25 13:36:151056 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 7));
bncdf80d44fd2016-07-15 20:27:411057 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(7, false));
1058 SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(7, true));
[email protected]2bd93022010-07-17 00:58:441059
[email protected]18b28ab2012-04-18 02:14:421060 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461061 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421062 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1063 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
bncdf80d44fd2016-07-15 20:27:411064 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201065 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:411066 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
rch08e3aa3e2015-05-16 14:27:521067 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411068 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
rch08e3aa3e2015-05-16 14:27:521069 // By making these synchronous, it guarantees that they are not *started*
1070 // before their sequence number, which in turn verifies that only a single
1071 // request is in-flight at a time.
bncdf80d44fd2016-07-15 20:27:411072 CreateMockWrite(req2, 6, SYNCHRONOUS),
1073 CreateMockWrite(req4, 10, SYNCHRONOUS),
1074 CreateMockWrite(req3, 13, SYNCHRONOUS),
[email protected]2bd93022010-07-17 00:58:441075 };
1076 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411077 CreateMockRead(settings_frame, 1),
1078 CreateMockRead(resp, 2),
1079 CreateMockRead(body, 3),
1080 CreateMockRead(fbody, 4),
1081 CreateMockRead(resp2, 7),
1082 CreateMockRead(body2, 8),
1083 CreateMockRead(fbody2, 9),
1084 CreateMockRead(resp4, 11),
1085 CreateMockRead(fbody4, 12),
1086 CreateMockRead(resp3, 14),
1087 CreateMockRead(body3, 15),
1088 CreateMockRead(fbody3, 16),
[email protected]2bd93022010-07-17 00:58:441089
rch08e3aa3e2015-05-16 14:27:521090 MockRead(ASYNC, 0, 17), // EOF
[email protected]2bd93022010-07-17 00:58:441091 };
rch08e3aa3e2015-05-16 14:27:521092 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441093 BoundNetLog log;
1094 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361095 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011096 BoundNetLog(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081097 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571098 helper.AddData(&data);
rch08e3aa3e2015-05-16 14:27:521099
bnc691fda62016-08-12 00:43:161100 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1101 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
1102 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
1103 HttpNetworkTransaction trans4(HIGHEST, helper.session());
[email protected]2bd93022010-07-17 00:58:441104
[email protected]49639fa2011-12-20 23:22:411105 TestCompletionCallback callback1;
1106 TestCompletionCallback callback2;
1107 TestCompletionCallback callback3;
1108 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:441109
[email protected]bdebd1b2010-08-09 20:18:081110 HttpRequestInfo httpreq1 = CreateGetRequest();
1111 HttpRequestInfo httpreq2 = CreateGetRequest();
1112 HttpRequestInfo httpreq3 = CreateGetRequest();
1113 HttpRequestInfo httpreq4 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441114
bnc691fda62016-08-12 00:43:161115 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:011116 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]e0935cc2012-03-24 14:12:481117 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081118 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011119 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441120
bnc691fda62016-08-12 00:43:161121 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:011122 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:161123 out.rv = trans3.Start(&httpreq3, callback3.callback(), log);
robpercival214763f2016-07-01 23:27:011124 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:161125 out.rv = trans4.Start(&httpreq4, callback4.callback(), log);
robpercival214763f2016-07-01 23:27:011126 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]2bd93022010-07-17 00:58:441127
[email protected]bdebd1b2010-08-09 20:18:081128 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011129 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441130
[email protected]bdebd1b2010-08-09 20:18:081131 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011132 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441133
bnc691fda62016-08-12 00:43:161134 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521135 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:081136 EXPECT_TRUE(response1->was_fetched_via_spdy);
1137 out.status_line = response1->headers->GetStatusLine();
1138 out.response_info = *response1;
bnc691fda62016-08-12 00:43:161139 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011140 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021141 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081142 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441143
bnc691fda62016-08-12 00:43:161144 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081145 out.status_line = response2->headers->GetStatusLine();
1146 out.response_info = *response2;
bnc691fda62016-08-12 00:43:161147 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011148 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021149 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081150 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441151
[email protected]bdebd1b2010-08-09 20:18:081152 // notice: response3 gets two hellos, response4 gets one
1153 // hello, so we know dequeuing priority was respected.
bnc691fda62016-08-12 00:43:161154 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081155 out.status_line = response3->headers->GetStatusLine();
1156 out.response_info = *response3;
bnc691fda62016-08-12 00:43:161157 out.rv = ReadTransaction(&trans3, &out.response_data);
robpercival214763f2016-07-01 23:27:011158 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021159 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081160 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441161
[email protected]bdebd1b2010-08-09 20:18:081162 out.rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:011163 EXPECT_THAT(out.rv, IsOk());
bnc691fda62016-08-12 00:43:161164 const HttpResponseInfo* response4 = trans4.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081165 out.status_line = response4->headers->GetStatusLine();
1166 out.response_info = *response4;
bnc691fda62016-08-12 00:43:161167 out.rv = ReadTransaction(&trans4, &out.response_data);
robpercival214763f2016-07-01 23:27:011168 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021169 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081170 EXPECT_EQ("hello!", out.response_data);
1171 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:011172 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441173}
1174
1175// Similar to ThreeGetsMaxConcurrrent above, however, this test
rch08e3aa3e2015-05-16 14:27:521176// deletes a session in the middle of the transaction to ensure
[email protected]2bd93022010-07-17 00:58:441177// that we properly remove pendingcreatestream objects from
1178// the spdy_session
bncd16676a2016-07-20 16:23:011179TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:441180 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411181 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491182 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:151183 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411184 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1185 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381186 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441187
bncdf80d44fd2016-07-15 20:27:411188 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:491189 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:151190 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:411191 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1192 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441193
[email protected]18b28ab2012-04-18 02:14:421194 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461195 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421196 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1197 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
bncdf80d44fd2016-07-15 20:27:411198 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201199 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:411200 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441201
[email protected]d4a77c12014-05-15 20:45:211202 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411203 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1204 CreateMockWrite(req2, 6),
[email protected]2bd93022010-07-17 00:58:441205 };
1206 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411207 CreateMockRead(settings_frame, 1), CreateMockRead(resp, 2),
1208 CreateMockRead(body, 3), CreateMockRead(fbody, 4),
1209 CreateMockRead(resp2, 7), CreateMockRead(body2, 8),
1210 CreateMockRead(fbody2, 9), MockRead(ASYNC, 0, 10), // EOF
[email protected]2bd93022010-07-17 00:58:441211 };
1212
rch08e3aa3e2015-05-16 14:27:521213 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441214
1215 BoundNetLog log;
1216 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361217 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011218 BoundNetLog(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081219 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571220 helper.AddData(&data);
danakjaee3e1ec2016-04-16 00:23:181221 std::unique_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421222 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
danakjaee3e1ec2016-04-16 00:23:181223 std::unique_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421224 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
danakjaee3e1ec2016-04-16 00:23:181225 std::unique_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:421226 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]2bd93022010-07-17 00:58:441227
[email protected]49639fa2011-12-20 23:22:411228 TestCompletionCallback callback1;
1229 TestCompletionCallback callback2;
1230 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441231
[email protected]bdebd1b2010-08-09 20:18:081232 HttpRequestInfo httpreq1 = CreateGetRequest();
1233 HttpRequestInfo httpreq2 = CreateGetRequest();
1234 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441235
[email protected]49639fa2011-12-20 23:22:411236 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081237 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481238 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081239 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011240 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441241
[email protected]49639fa2011-12-20 23:22:411242 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081243 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411244 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
olli.raula7ca9cd1d2016-01-04 06:50:371245 trans3.reset();
[email protected]bdebd1b2010-08-09 20:18:081246 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1247 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011248 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441249
[email protected]bdebd1b2010-08-09 20:18:081250 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:521251 ASSERT_TRUE(response1);
1252 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:081253 EXPECT_TRUE(response1->was_fetched_via_spdy);
1254 out.status_line = response1->headers->GetStatusLine();
1255 out.response_info = *response1;
1256 out.rv = ReadTransaction(trans1.get(), &out.response_data);
robpercival214763f2016-07-01 23:27:011257 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021258 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081259 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441260
[email protected]bdebd1b2010-08-09 20:18:081261 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:521262 ASSERT_TRUE(response2);
[email protected]bdebd1b2010-08-09 20:18:081263 out.status_line = response2->headers->GetStatusLine();
1264 out.response_info = *response2;
1265 out.rv = ReadTransaction(trans2.get(), &out.response_data);
robpercival214763f2016-07-01 23:27:011266 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021267 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081268 EXPECT_EQ("hello!hello!", out.response_data);
1269 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:011270 EXPECT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261271}
[email protected]2bd93022010-07-17 00:58:441272
[email protected]448d4ca52012-03-04 04:12:231273namespace {
1274
[email protected]044dcc52010-09-17 15:44:261275// The KillerCallback will delete the transaction on error as part of the
1276// callback.
[email protected]49639fa2011-12-20 23:22:411277class KillerCallback : public TestCompletionCallbackBase {
[email protected]044dcc52010-09-17 15:44:261278 public:
1279 explicit KillerCallback(HttpNetworkTransaction* transaction)
[email protected]49639fa2011-12-20 23:22:411280 : transaction_(transaction),
[email protected]aa249b52013-04-30 01:04:321281 callback_(base::Bind(&KillerCallback::OnComplete,
1282 base::Unretained(this))) {
[email protected]044dcc52010-09-17 15:44:261283 }
1284
dchengb03027d2014-10-21 12:00:201285 ~KillerCallback() override {}
[email protected]49639fa2011-12-20 23:22:411286
1287 const CompletionCallback& callback() const { return callback_; }
1288
[email protected]044dcc52010-09-17 15:44:261289 private:
[email protected]49639fa2011-12-20 23:22:411290 void OnComplete(int result) {
1291 if (result < 0)
1292 delete transaction_;
1293
1294 SetResult(result);
1295 }
1296
[email protected]044dcc52010-09-17 15:44:261297 HttpNetworkTransaction* transaction_;
[email protected]49639fa2011-12-20 23:22:411298 CompletionCallback callback_;
[email protected]044dcc52010-09-17 15:44:261299};
1300
[email protected]448d4ca52012-03-04 04:12:231301} // namespace
1302
[email protected]044dcc52010-09-17 15:44:261303// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1304// closes the socket while we have a pending transaction waiting for
1305// a pending stream creation. http://crbug.com/52901
bncd16676a2016-07-20 16:23:011306TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
[email protected]044dcc52010-09-17 15:44:261307 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411308 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491309 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:151310 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411311 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1312 SpdySerializedFrame fin_body(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381313 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]044dcc52010-09-17 15:44:261314
bncdf80d44fd2016-07-15 20:27:411315 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:491316 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:151317 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
[email protected]044dcc52010-09-17 15:44:261318
[email protected]18b28ab2012-04-18 02:14:421319 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461320 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421321 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1322 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
bncdf80d44fd2016-07-15 20:27:411323 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201324 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:411325 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]044dcc52010-09-17 15:44:261326
[email protected]d4a77c12014-05-15 20:45:211327 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411328 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1329 CreateMockWrite(req2, 6),
[email protected]044dcc52010-09-17 15:44:261330 };
1331 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411332 CreateMockRead(settings_frame, 1),
1333 CreateMockRead(resp, 2),
1334 CreateMockRead(body, 3),
1335 CreateMockRead(fin_body, 4),
1336 CreateMockRead(resp2, 7),
rch08e3aa3e2015-05-16 14:27:521337 MockRead(ASYNC, ERR_CONNECTION_RESET, 8), // Abort!
[email protected]044dcc52010-09-17 15:44:261338 };
1339
rch08e3aa3e2015-05-16 14:27:521340 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1341 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]044dcc52010-09-17 15:44:261342
1343 BoundNetLog log;
1344 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361345 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011346 BoundNetLog(), NULL);
[email protected]044dcc52010-09-17 15:44:261347 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571348 helper.AddData(&data);
[email protected]044dcc52010-09-17 15:44:261349 // We require placeholder data because three get requests are sent out, so
1350 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571351 helper.AddData(&data_placeholder);
1352 helper.AddData(&data_placeholder);
mmenkee65e7af2015-10-13 17:16:421353 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1354 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]262eec82013-03-19 21:01:361355 HttpNetworkTransaction* trans3(
mmenkee65e7af2015-10-13 17:16:421356 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]044dcc52010-09-17 15:44:261357
[email protected]49639fa2011-12-20 23:22:411358 TestCompletionCallback callback1;
1359 TestCompletionCallback callback2;
[email protected]044dcc52010-09-17 15:44:261360 KillerCallback callback3(trans3);
1361
1362 HttpRequestInfo httpreq1 = CreateGetRequest();
1363 HttpRequestInfo httpreq2 = CreateGetRequest();
1364 HttpRequestInfo httpreq3 = CreateGetRequest();
1365
[email protected]49639fa2011-12-20 23:22:411366 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]044dcc52010-09-17 15:44:261367 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481368 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]044dcc52010-09-17 15:44:261369 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011370 ASSERT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261371
[email protected]49639fa2011-12-20 23:22:411372 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]044dcc52010-09-17 15:44:261373 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411374 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]044dcc52010-09-17 15:44:261375 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1376 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011377 ASSERT_THAT(out.rv, IsError(ERR_ABORTED));
[email protected]044dcc52010-09-17 15:44:261378
[email protected]044dcc52010-09-17 15:44:261379 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521380 ASSERT_TRUE(response1);
1381 EXPECT_TRUE(response1->headers);
[email protected]044dcc52010-09-17 15:44:261382 EXPECT_TRUE(response1->was_fetched_via_spdy);
1383 out.status_line = response1->headers->GetStatusLine();
1384 out.response_info = *response1;
1385 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011386 EXPECT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261387
1388 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:521389 ASSERT_TRUE(response2);
[email protected]044dcc52010-09-17 15:44:261390 out.status_line = response2->headers->GetStatusLine();
1391 out.response_info = *response2;
1392 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011393 EXPECT_THAT(out.rv, IsError(ERR_CONNECTION_RESET));
[email protected]044dcc52010-09-17 15:44:261394
1395 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441396}
1397
[email protected]d8ef27b2010-08-06 17:34:391398// Test that a simple PUT request works.
bncd16676a2016-07-20 16:23:011399TEST_F(SpdyNetworkTransactionTest, Put) {
[email protected]d8ef27b2010-08-06 17:34:391400 // Setup the request
1401 HttpRequestInfo request;
1402 request.method = "PUT";
bncb26024382016-06-29 02:39:451403 request.url = default_url_;
[email protected]d8ef27b2010-08-06 17:34:391404
bnc086b39e12016-06-24 13:05:261405 SpdyHeaderBlock put_headers(
bncb26024382016-06-29 02:39:451406 spdy_util_.ConstructPutHeaderBlock(kDefaultUrl, 0));
bncdf80d44fd2016-07-15 20:27:411407 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151408 spdy_util_.ConstructSpdyHeaders(1, std::move(put_headers), LOWEST, true));
[email protected]d8ef27b2010-08-06 17:34:391409 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411410 CreateMockWrite(req, 0),
[email protected]d8ef27b2010-08-06 17:34:391411 };
1412
bnc42331402016-07-25 13:36:151413 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411414 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391415 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411416 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521417 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391418 };
1419
rch08e3aa3e2015-05-16 14:27:521420 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:011421 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
1422 NULL);
[email protected]dd54bd82012-07-19 23:44:571423 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391424 TransactionHelperResult out = helper.output();
1425
robpercival214763f2016-07-01 23:27:011426 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021427 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391428}
1429
1430// Test that a simple HEAD request works.
bncd16676a2016-07-20 16:23:011431TEST_F(SpdyNetworkTransactionTest, Head) {
[email protected]d8ef27b2010-08-06 17:34:391432 // Setup the request
1433 HttpRequestInfo request;
1434 request.method = "HEAD";
bncb26024382016-06-29 02:39:451435 request.url = default_url_;
[email protected]d8ef27b2010-08-06 17:34:391436
bnc086b39e12016-06-24 13:05:261437 SpdyHeaderBlock head_headers(
bncb26024382016-06-29 02:39:451438 spdy_util_.ConstructHeadHeaderBlock(kDefaultUrl, 0));
bnc42331402016-07-25 13:36:151439 SpdySerializedFrame req(spdy_util_.ConstructSpdyHeaders(
1440 1, std::move(head_headers), LOWEST, true));
[email protected]d8ef27b2010-08-06 17:34:391441 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411442 CreateMockWrite(req, 0),
[email protected]d8ef27b2010-08-06 17:34:391443 };
1444
bnc42331402016-07-25 13:36:151445 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411446 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391447 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411448 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521449 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391450 };
1451
rch08e3aa3e2015-05-16 14:27:521452 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:011453 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
1454 NULL);
[email protected]dd54bd82012-07-19 23:44:571455 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391456 TransactionHelperResult out = helper.output();
1457
robpercival214763f2016-07-01 23:27:011458 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021459 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391460}
1461
[email protected]72552f02009-10-28 15:25:011462// Test that a simple POST works.
bncd16676a2016-07-20 16:23:011463TEST_F(SpdyNetworkTransactionTest, Post) {
bncdf80d44fd2016-07-15 20:27:411464 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:451465 kDefaultUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
bncdf80d44fd2016-07-15 20:27:411466 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141467 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411468 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141469 };
[email protected]72552f02009-10-28 15:25:011470
bnc42331402016-07-25 13:36:151471 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]ff57bb82009-11-12 06:52:141472 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411473 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521474 MockRead(ASYNC, 0, 4) // EOF
[email protected]aea80602009-09-18 00:55:081475 };
1476
rch08e3aa3e2015-05-16 14:27:521477 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361478 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011479 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:571480 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471481 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011482 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021483 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]aea80602009-09-18 00:55:081484 EXPECT_EQ("hello!", out.response_data);
1485}
1486
[email protected]69e6b4a2012-10-18 08:03:011487// Test that a POST with a file works.
bncd16676a2016-07-20 16:23:011488TEST_F(SpdyNetworkTransactionTest, FilePost) {
bncdf80d44fd2016-07-15 20:27:411489 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:451490 kDefaultUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
bncdf80d44fd2016-07-15 20:27:411491 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011492 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411493 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011494 };
1495
bnc42331402016-07-25 13:36:151496 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011497 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411498 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521499 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011500 };
1501
rch08e3aa3e2015-05-16 14:27:521502 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361503 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011504 BoundNetLog(), NULL);
[email protected]69e6b4a2012-10-18 08:03:011505 helper.RunToCompletion(&data);
1506 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011507 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021508 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011509 EXPECT_EQ("hello!", out.response_data);
1510}
1511
[email protected]999dd8c2013-11-12 06:45:541512// Test that a POST with a unreadable file fails.
bncd16676a2016-07-20 16:23:011513TEST_F(SpdyNetworkTransactionTest, UnreadableFilePost) {
[email protected]999dd8c2013-11-12 06:45:541514 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521515 MockWrite(ASYNC, 0, 0) // EOF
[email protected]999dd8c2013-11-12 06:45:541516 };
1517 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521518 MockRead(ASYNC, 0, 1) // EOF
[email protected]999dd8c2013-11-12 06:45:541519 };
1520
rch08e3aa3e2015-05-16 14:27:521521 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]999dd8c2013-11-12 06:45:541522 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
bncd16676a2016-07-20 16:23:011523 DEFAULT_PRIORITY, BoundNetLog(), NULL);
[email protected]999dd8c2013-11-12 06:45:541524 helper.RunPreTestSetup();
1525 helper.AddData(&data);
1526 helper.RunDefaultTest();
1527
1528 base::RunLoop().RunUntilIdle();
1529 helper.VerifyDataNotConsumed();
robpercival214763f2016-07-01 23:27:011530 EXPECT_THAT(helper.output().rv, IsError(ERR_ACCESS_DENIED));
[email protected]999dd8c2013-11-12 06:45:541531}
1532
[email protected]69e6b4a2012-10-18 08:03:011533// Test that a complex POST works.
bncd16676a2016-07-20 16:23:011534TEST_F(SpdyNetworkTransactionTest, ComplexPost) {
bncdf80d44fd2016-07-15 20:27:411535 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:451536 kDefaultUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
bncdf80d44fd2016-07-15 20:27:411537 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011538 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411539 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011540 };
1541
bnc42331402016-07-25 13:36:151542 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011543 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411544 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521545 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011546 };
1547
rch08e3aa3e2015-05-16 14:27:521548 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]69e6b4a2012-10-18 08:03:011549 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
bncd16676a2016-07-20 16:23:011550 DEFAULT_PRIORITY, BoundNetLog(), NULL);
[email protected]69e6b4a2012-10-18 08:03:011551 helper.RunToCompletion(&data);
1552 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011553 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021554 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011555 EXPECT_EQ("hello!", out.response_data);
1556}
1557
[email protected]0c9bf872011-03-04 17:53:221558// Test that a chunked POST works.
bncd16676a2016-07-20 16:23:011559TEST_F(SpdyNetworkTransactionTest, ChunkedPost) {
bncdf80d44fd2016-07-15 20:27:411560 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1561 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]0c9bf872011-03-04 17:53:221562 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411563 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
[email protected]0c9bf872011-03-04 17:53:221564 };
1565
bnc42331402016-07-25 13:36:151566 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]0c9bf872011-03-04 17:53:221567 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411568 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521569 MockRead(ASYNC, 0, 4) // EOF
[email protected]0c9bf872011-03-04 17:53:221570 };
1571
rch08e3aa3e2015-05-16 14:27:521572 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]0c9bf872011-03-04 17:53:221573 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
bncd16676a2016-07-20 16:23:011574 DEFAULT_PRIORITY, BoundNetLog(), NULL);
[email protected]34b345f92013-02-22 03:27:261575
1576 // These chunks get merged into a single frame when being sent.
1577 const int kFirstChunkSize = kUploadDataSize/2;
mmenkecbc2b712014-10-09 20:29:071578 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1579 upload_chunked_data_stream()->AppendData(
[email protected]34b345f92013-02-22 03:27:261580 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1581
[email protected]dd54bd82012-07-19 23:44:571582 helper.RunToCompletion(&data);
[email protected]0c9bf872011-03-04 17:53:221583 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011584 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021585 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261586 EXPECT_EQ(kUploadData, out.response_data);
1587}
1588
1589// Test that a chunked POST works with chunks appended after transaction starts.
bncd16676a2016-07-20 16:23:011590TEST_F(SpdyNetworkTransactionTest, DelayedChunkedPost) {
bncdf80d44fd2016-07-15 20:27:411591 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1592 SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false));
1593 SpdySerializedFrame chunk2(spdy_util_.ConstructSpdyDataFrame(1, false));
1594 SpdySerializedFrame chunk3(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]34b345f92013-02-22 03:27:261595 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411596 CreateMockWrite(req, 0), CreateMockWrite(chunk1, 1),
1597 CreateMockWrite(chunk2, 2), CreateMockWrite(chunk3, 3),
[email protected]34b345f92013-02-22 03:27:261598 };
1599
bnc42331402016-07-25 13:36:151600 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]34b345f92013-02-22 03:27:261601 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411602 CreateMockRead(resp, 4), CreateMockRead(chunk1, 5),
1603 CreateMockRead(chunk2, 6), CreateMockRead(chunk3, 7),
rch08e3aa3e2015-05-16 14:27:521604 MockRead(ASYNC, 0, 8) // EOF
[email protected]34b345f92013-02-22 03:27:261605 };
1606
rch08e3aa3e2015-05-16 14:27:521607 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]34b345f92013-02-22 03:27:261608 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
bncd16676a2016-07-20 16:23:011609 DEFAULT_PRIORITY, BoundNetLog(), NULL);
[email protected]34b345f92013-02-22 03:27:261610
mmenkecbc2b712014-10-09 20:29:071611 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]34b345f92013-02-22 03:27:261612
1613 helper.RunPreTestSetup();
1614 helper.AddData(&data);
1615 ASSERT_TRUE(helper.StartDefaultTest());
1616
[email protected]fc9d88472013-08-14 02:31:171617 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071618 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]fc9d88472013-08-14 02:31:171619 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071620 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]34b345f92013-02-22 03:27:261621
1622 helper.FinishDefaultTest();
1623 helper.VerifyDataConsumed();
1624
1625 std::string expected_response;
1626 expected_response += kUploadData;
1627 expected_response += kUploadData;
1628 expected_response += kUploadData;
1629
1630 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011631 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021632 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261633 EXPECT_EQ(expected_response, out.response_data);
[email protected]0c9bf872011-03-04 17:53:221634}
1635
[email protected]a33cad2b62010-07-30 22:24:391636// Test that a POST without any post data works.
bncd16676a2016-07-20 16:23:011637TEST_F(SpdyNetworkTransactionTest, NullPost) {
[email protected]a33cad2b62010-07-30 22:24:391638 // Setup the request
1639 HttpRequestInfo request;
1640 request.method = "POST";
bncb26024382016-06-29 02:39:451641 request.url = default_url_;
[email protected]a33cad2b62010-07-30 22:24:391642 // Create an empty UploadData.
[email protected]329b68b2012-11-14 17:54:271643 request.upload_data_stream = NULL;
[email protected]a33cad2b62010-07-30 22:24:391644
[email protected]329b68b2012-11-14 17:54:271645 // When request.upload_data_stream is NULL for post, content-length is
[email protected]a33cad2b62010-07-30 22:24:391646 // expected to be 0.
bnc086b39e12016-06-24 13:05:261647 SpdyHeaderBlock req_block(
bncb26024382016-06-29 02:39:451648 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
bncdf80d44fd2016-07-15 20:27:411649 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151650 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block), LOWEST, true));
[email protected]d2c1a97b2014-03-03 19:25:091651
[email protected]a33cad2b62010-07-30 22:24:391652 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411653 CreateMockWrite(req, 0),
[email protected]a33cad2b62010-07-30 22:24:391654 };
1655
bnc42331402016-07-25 13:36:151656 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
bncdf80d44fd2016-07-15 20:27:411657 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]a33cad2b62010-07-30 22:24:391658 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411659 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521660 MockRead(ASYNC, 0, 3) // EOF
[email protected]a33cad2b62010-07-30 22:24:391661 };
1662
rch08e3aa3e2015-05-16 14:27:521663 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]a33cad2b62010-07-30 22:24:391664
bncd16676a2016-07-20 16:23:011665 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
1666 NULL);
[email protected]dd54bd82012-07-19 23:44:571667 helper.RunToCompletion(&data);
[email protected]a33cad2b62010-07-30 22:24:391668 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011669 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021670 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]a33cad2b62010-07-30 22:24:391671 EXPECT_EQ("hello!", out.response_data);
1672}
1673
[email protected]edd3b0a52009-11-24 18:56:361674// Test that a simple POST works.
bncd16676a2016-07-20 16:23:011675TEST_F(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]329b68b2012-11-14 17:54:271676 // Create an empty UploadDataStream.
danakjaee3e1ec2016-04-16 00:23:181677 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221678 ElementsUploadDataStream stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271679
[email protected]edd3b0a52009-11-24 18:56:361680 // Setup the request
1681 HttpRequestInfo request;
1682 request.method = "POST";
bncb26024382016-06-29 02:39:451683 request.url = default_url_;
[email protected]329b68b2012-11-14 17:54:271684 request.upload_data_stream = &stream;
[email protected]edd3b0a52009-11-24 18:56:361685
Avi Drissman13fc8932015-12-20 04:40:461686 const uint64_t kContentLength = 0;
[email protected]d2c1a97b2014-03-03 19:25:091687
bnc086b39e12016-06-24 13:05:261688 SpdyHeaderBlock req_block(
bncb26024382016-06-29 02:39:451689 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kContentLength));
bncdf80d44fd2016-07-15 20:27:411690 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151691 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block), LOWEST, true));
[email protected]d2c1a97b2014-03-03 19:25:091692
[email protected]edd3b0a52009-11-24 18:56:361693 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411694 CreateMockWrite(req, 0),
[email protected]edd3b0a52009-11-24 18:56:361695 };
1696
bnc42331402016-07-25 13:36:151697 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
bncdf80d44fd2016-07-15 20:27:411698 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361699 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411700 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521701 MockRead(ASYNC, 0, 3) // EOF
[email protected]edd3b0a52009-11-24 18:56:361702 };
1703
rch08e3aa3e2015-05-16 14:27:521704 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bf2491a92009-11-29 16:39:481705
bncd16676a2016-07-20 16:23:011706 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
1707 NULL);
[email protected]dd54bd82012-07-19 23:44:571708 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471709 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011710 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021711 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]edd3b0a52009-11-24 18:56:361712 EXPECT_EQ("hello!", out.response_data);
1713}
1714
[email protected]35c3fc732014-02-15 00:16:071715// While we're doing a post, the server sends the reply before upload completes.
bncd16676a2016-07-20 16:23:011716TEST_F(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
bncdf80d44fd2016-07-15 20:27:411717 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1718 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]35c3fc732014-02-15 00:16:071719 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411720 CreateMockWrite(req, 0), CreateMockWrite(body, 3),
[email protected]35c3fc732014-02-15 00:16:071721 };
bnc42331402016-07-25 13:36:151722 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]a5566f9702010-05-05 22:25:431723 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411724 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1725 MockRead(ASYNC, 0, 4) // EOF
[email protected]a5566f9702010-05-05 22:25:431726 };
1727
[email protected]35c3fc732014-02-15 00:16:071728 // Write the request headers, and read the complete response
1729 // while still waiting for chunked request data.
mmenke666a6fea2015-12-19 04:16:331730 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]35c3fc732014-02-15 00:16:071731 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
bncd16676a2016-07-20 16:23:011732 DEFAULT_PRIORITY, BoundNetLog(), NULL);
[email protected]c92f4b4542012-07-26 23:53:211733 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:331734 helper.AddData(&data);
[email protected]c92f4b4542012-07-26 23:53:211735
[email protected]35c3fc732014-02-15 00:16:071736 ASSERT_TRUE(helper.StartDefaultTest());
[email protected]c92f4b4542012-07-26 23:53:211737
maksim.sisov8d2df66d2016-06-20 07:07:111738 base::RunLoop().RunUntilIdle();
mmenke666a6fea2015-12-19 04:16:331739
bnc42331402016-07-25 13:36:151740 // Process the request headers, response headers, and response body.
[email protected]35c3fc732014-02-15 00:16:071741 // The request body is still in flight.
[email protected]35c3fc732014-02-15 00:16:071742 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
bnc84e7fb52015-12-02 11:50:021743 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]35c3fc732014-02-15 00:16:071744
1745 // Finish sending the request body.
mmenkecbc2b712014-10-09 20:29:071746 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
maksim.sisov8d2df66d2016-06-20 07:07:111747 helper.WaitForCallbackToComplete();
robpercival214763f2016-07-01 23:27:011748 EXPECT_THAT(helper.output().rv, IsOk());
[email protected]35c3fc732014-02-15 00:16:071749
1750 std::string response_body;
robpercival214763f2016-07-01 23:27:011751 EXPECT_THAT(ReadTransaction(helper.trans(), &response_body), IsOk());
[email protected]35c3fc732014-02-15 00:16:071752 EXPECT_EQ(kUploadData, response_body);
1753 helper.VerifyDataConsumed();
[email protected]a5566f9702010-05-05 22:25:431754}
1755
[email protected]f9a26d72010-08-03 18:07:131756// The client upon cancellation tries to send a RST_STREAM frame. The mock
1757// socket causes the TCP write to return zero. This test checks that the client
1758// tries to queue up the RST_STREAM frame again.
bncd16676a2016-07-20 16:23:011759TEST_F(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
bncdf80d44fd2016-07-15 20:27:411760 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491761 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411762 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201763 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]f9a26d72010-08-03 18:07:131764 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411765 CreateMockWrite(req, 0, SYNCHRONOUS), MockWrite(SYNCHRONOUS, 0, 0, 2),
1766 CreateMockWrite(rst, 3, SYNCHRONOUS),
[email protected]f9a26d72010-08-03 18:07:131767 };
1768
bnc42331402016-07-25 13:36:151769 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]f9a26d72010-08-03 18:07:131770 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411771 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:131772 };
1773
mmenke666a6fea2015-12-19 04:16:331774 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361775 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011776 BoundNetLog(), NULL);
[email protected]f9a26d72010-08-03 18:07:131777 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:331778 helper.AddData(&data);
[email protected]f9a26d72010-08-03 18:07:131779 HttpNetworkTransaction* trans = helper.trans();
1780
[email protected]49639fa2011-12-20 23:22:411781 TestCompletionCallback callback;
1782 int rv = trans->Start(
1783 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011784 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]3b7828432010-08-18 18:33:271785
[email protected]f9a26d72010-08-03 18:07:131786 helper.ResetTrans();
mmenke666a6fea2015-12-19 04:16:331787 base::RunLoop().RunUntilIdle();
[email protected]3b7828432010-08-18 18:33:271788
[email protected]f9a26d72010-08-03 18:07:131789 helper.VerifyDataConsumed();
1790}
1791
[email protected]93300672009-10-24 13:22:511792// Test that the transaction doesn't crash when we don't have a reply.
bnc42331402016-07-25 13:36:151793TEST_F(SpdyNetworkTransactionTest, ResponseWithoutHeaders) {
bncdf80d44fd2016-07-15 20:27:411794 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141795 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411796 CreateMockRead(body, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]93300672009-10-24 13:22:511797 };
1798
bncdf80d44fd2016-07-15 20:27:411799 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491800 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411801 SpdySerializedFrame rst(
rch08e3aa3e2015-05-16 14:27:521802 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
1803 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411804 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
rch08e3aa3e2015-05-16 14:27:521805 };
1806 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361807 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011808 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:571809 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471810 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011811 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]93300672009-10-24 13:22:511812}
1813
[email protected]d30022352010-06-24 19:17:581814// Test that the transaction doesn't crash when we get two replies on the same
1815// stream ID. See http://crbug.com/45639.
bncd16676a2016-07-20 16:23:011816TEST_F(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
bncdf80d44fd2016-07-15 20:27:411817 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491818 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411819 SpdySerializedFrame rst(
[email protected]00b29472014-01-16 18:10:241820 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]2aeef782013-06-21 18:30:561821 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411822 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
[email protected]2aeef782013-06-21 18:30:561823 };
[email protected]d30022352010-06-24 19:17:581824
bnc42331402016-07-25 13:36:151825 SpdySerializedFrame resp0(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1826 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411827 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d30022352010-06-24 19:17:581828 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411829 CreateMockRead(resp0, 1), CreateMockRead(resp1, 2),
1830 CreateMockRead(body, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]d30022352010-06-24 19:17:581831 };
1832
rch08e3aa3e2015-05-16 14:27:521833 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d30022352010-06-24 19:17:581834
[email protected]262eec82013-03-19 21:01:361835 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011836 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:471837 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571838 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:471839
1840 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:581841
[email protected]49639fa2011-12-20 23:22:411842 TestCompletionCallback callback;
1843 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011844 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d30022352010-06-24 19:17:581845 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011846 EXPECT_THAT(rv, IsOk());
[email protected]d30022352010-06-24 19:17:581847
1848 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:521849 ASSERT_TRUE(response);
1850 EXPECT_TRUE(response->headers);
[email protected]d30022352010-06-24 19:17:581851 EXPECT_TRUE(response->was_fetched_via_spdy);
1852 std::string response_data;
[email protected]3caf5542010-07-16 15:19:471853 rv = ReadTransaction(trans, &response_data);
robpercival214763f2016-07-01 23:27:011854 EXPECT_THAT(rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]3caf5542010-07-16 15:19:471855
1856 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:581857}
1858
bncd16676a2016-07-20 16:23:011859TEST_F(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:251860 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411861 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491862 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411863 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201864 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:251865 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411866 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
[email protected]b3503002012-03-27 04:57:251867 };
1868
1869 const char* const headers[] = {
[email protected]513963e2013-06-15 01:53:041870 "transfer-encoding", "chunked"
[email protected]b3503002012-03-27 04:57:251871 };
bnc42331402016-07-25 13:36:151872 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(headers, 1, 1));
bncdf80d44fd2016-07-15 20:27:411873 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b3503002012-03-27 04:57:251874 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411875 CreateMockRead(resp, 1), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521876 MockRead(ASYNC, 0, 4) // EOF
[email protected]b3503002012-03-27 04:57:251877 };
1878
rch08e3aa3e2015-05-16 14:27:521879 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361880 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011881 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:571882 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:251883 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011884 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:251885
1886 helper.session()->spdy_session_pool()->CloseAllSessions();
1887 helper.VerifyDataConsumed();
1888}
1889
bncd16676a2016-07-20 16:23:011890TEST_F(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:251891 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411892 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491893 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411894 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201895 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:251896 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411897 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
[email protected]b3503002012-03-27 04:57:251898 };
1899
bnc42331402016-07-25 13:36:151900 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041901 const char* const headers[] = {
1902 "transfer-encoding", "chunked"
1903 };
bncdf80d44fd2016-07-15 20:27:411904 SpdySerializedFrame push(
rchebf12982015-04-10 01:15:001905 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2, 2, 1,
1906 GetDefaultUrlWithPath("/1").c_str()));
bncdf80d44fd2016-07-15 20:27:411907 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b3503002012-03-27 04:57:251908 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411909 CreateMockRead(resp, 1), CreateMockRead(push, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521910 MockRead(ASYNC, 0, 5) // EOF
[email protected]b3503002012-03-27 04:57:251911 };
1912
rch08e3aa3e2015-05-16 14:27:521913 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361914 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011915 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:571916 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:251917 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011918 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021919 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b3503002012-03-27 04:57:251920 EXPECT_EQ("hello!", out.response_data);
1921
1922 helper.session()->spdy_session_pool()->CloseAllSessions();
1923 helper.VerifyDataConsumed();
1924}
1925
bncd16676a2016-07-20 16:23:011926TEST_F(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:381927 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411928 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491929 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]34437af82009-11-06 02:28:491930 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411931 CreateMockWrite(req),
[email protected]34437af82009-11-06 02:28:491932 };
1933
bnc42331402016-07-25 13:36:151934 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]34437af82009-11-06 02:28:491935 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411936 CreateMockRead(resp),
1937 // This following read isn't used by the test, except during the
1938 // RunUntilIdle() call at the end since the SpdySession survives the
1939 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
1940 // MockRead will do here.
1941 MockRead(ASYNC, 0, 0) // EOF
[email protected]34437af82009-11-06 02:28:491942 };
1943
[email protected]31a2bfe2010-02-09 08:03:391944 StaticSocketDataProvider data(reads, arraysize(reads),
1945 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:471946
[email protected]262eec82013-03-19 21:01:361947 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011948 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:471949 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:581950 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:471951 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:491952
[email protected]49639fa2011-12-20 23:22:411953 TestCompletionCallback callback;
1954 int rv = trans->Start(
1955 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011956 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3caf5542010-07-16 15:19:471957 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:491958
[email protected]30c942b2010-07-21 16:59:591959 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:491960 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:171961 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:471962 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:491963}
[email protected]72552f02009-10-28 15:25:011964
[email protected]6c6ea172010-07-27 20:04:031965// Verify that the client sends a Rst Frame upon cancelling the stream.
bncd16676a2016-07-20 16:23:011966TEST_F(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
bncdf80d44fd2016-07-15 20:27:411967 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491968 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411969 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201970 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]6c6ea172010-07-27 20:04:031971 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411972 CreateMockWrite(req, 0, SYNCHRONOUS),
1973 CreateMockWrite(rst, 2, SYNCHRONOUS),
[email protected]6c6ea172010-07-27 20:04:031974 };
1975
bnc42331402016-07-25 13:36:151976 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]6c6ea172010-07-27 20:04:031977 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411978 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:031979 };
1980
mmenke666a6fea2015-12-19 04:16:331981 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]6c6ea172010-07-27 20:04:031982
[email protected]262eec82013-03-19 21:01:361983 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011984 BoundNetLog(), NULL);
[email protected]6c6ea172010-07-27 20:04:031985 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:331986 helper.AddData(&data);
[email protected]6c6ea172010-07-27 20:04:031987 HttpNetworkTransaction* trans = helper.trans();
1988
[email protected]49639fa2011-12-20 23:22:411989 TestCompletionCallback callback;
[email protected]6c6ea172010-07-27 20:04:031990
[email protected]49639fa2011-12-20 23:22:411991 int rv = trans->Start(
1992 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011993 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]6c6ea172010-07-27 20:04:031994
[email protected]3b7828432010-08-18 18:33:271995 helper.ResetTrans();
mmenke666a6fea2015-12-19 04:16:331996 base::RunLoop().RunUntilIdle();
[email protected]3b7828432010-08-18 18:33:271997
[email protected]6c6ea172010-07-27 20:04:031998 helper.VerifyDataConsumed();
1999}
2000
[email protected]b278eb72010-07-09 20:17:002001// Verify that the client can correctly deal with the user callback attempting
2002// to start another transaction on a session that is closing down. See
2003// http://crbug.com/47455
bncd16676a2016-07-20 16:23:012004TEST_F(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
bncdf80d44fd2016-07-15 20:27:412005 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:492006 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412007 MockWrite writes[] = {CreateMockWrite(req)};
2008 MockWrite writes2[] = {CreateMockWrite(req, 0)};
[email protected]b278eb72010-07-09 20:17:002009
[email protected]cbdd73162013-03-18 23:27:332010 // The indicated length of this frame is longer than its actual length. When
2011 // the session receives an empty frame after this one, it shuts down the
[email protected]b278eb72010-07-09 20:17:002012 // session, and calls the read callback with the incomplete data.
Avi Drissman13fc8932015-12-20 04:40:462013 const uint8_t kGetBodyFrame2[] = {
2014 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
2015 0x07, 'h', 'e', 'l', 'l', 'o', '!',
[email protected]b278eb72010-07-09 20:17:002016 };
2017
bnc42331402016-07-25 13:36:152018 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]b278eb72010-07-09 20:17:002019 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412020 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:092021 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2022 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2023 arraysize(kGetBodyFrame2), 3),
2024 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
2025 MockRead(ASYNC, 0, 0, 5), // EOF
[email protected]b278eb72010-07-09 20:17:002026 };
2027 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:412028 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 0, 2), // EOF
[email protected]b278eb72010-07-09 20:17:002029 };
2030
rch32320842015-05-16 15:57:092031 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
rch08e3aa3e2015-05-16 14:27:522032 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2033 arraysize(writes2));
[email protected]3caf5542010-07-16 15:19:472034
[email protected]262eec82013-03-19 21:01:362035 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012036 BoundNetLog(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582037 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572038 helper.AddData(&data);
2039 helper.AddData(&data2);
[email protected]3caf5542010-07-16 15:19:472040 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002041
2042 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412043 TestCompletionCallback callback;
2044 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012045 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b278eb72010-07-09 20:17:002046 rv = callback.WaitForResult();
2047
[email protected]b278eb72010-07-09 20:17:002048 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162049 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412050 rv = trans->Read(
rchebf12982015-04-10 01:15:002051 buf.get(), kSize,
[email protected]513963e2013-06-15 01:53:042052 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
bncb26024382016-06-29 02:39:452053 helper.session(), default_url_));
robpercival214763f2016-07-01 23:27:012054 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3caf5542010-07-16 15:19:472055 // This forces an err_IO_pending, which sets the callback.
mmenkee24011922015-12-17 22:12:592056 data.Resume();
2057 data.RunUntilPaused();
2058
[email protected]3caf5542010-07-16 15:19:472059 // This finishes the read.
mmenkee24011922015-12-17 22:12:592060 data.Resume();
2061 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472062 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002063}
2064
[email protected]9be804c82010-06-24 17:59:462065// Verify that the client can correctly deal with the user callback deleting the
2066// transaction. Failures will usually be valgrind errors. See
2067// http://crbug.com/46925
bncd16676a2016-07-20 16:23:012068TEST_F(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
bncdf80d44fd2016-07-15 20:27:412069 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:492070 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412071 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]9be804c82010-06-24 17:59:462072
bnc42331402016-07-25 13:36:152073 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412074 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462075 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412076 CreateMockRead(resp, 1),
2077 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2078 CreateMockRead(body, 3), MockRead(ASYNC, 0, 0, 4), // EOF
[email protected]9be804c82010-06-24 17:59:462079 };
2080
rch32320842015-05-16 15:57:092081 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472082
[email protected]262eec82013-03-19 21:01:362083 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012084 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:472085 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572086 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472087 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462088
2089 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412090 TestCompletionCallback callback;
2091 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012092 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9be804c82010-06-24 17:59:462093 rv = callback.WaitForResult();
2094
2095 // Setup a user callback which will delete the session, and clear out the
2096 // memory holding the stream object. Note that the callback deletes trans.
[email protected]9be804c82010-06-24 17:59:462097 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162098 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412099 rv = trans->Read(
[email protected]90499482013-06-01 00:39:502100 buf.get(),
2101 kSize,
[email protected]513963e2013-06-15 01:53:042102 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
[email protected]49639fa2011-12-20 23:22:412103 base::Unretained(&helper)));
robpercival214763f2016-07-01 23:27:012104 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
mmenkee24011922015-12-17 22:12:592105 data.Resume();
[email protected]9be804c82010-06-24 17:59:462106
2107 // Finish running rest of tasks.
[email protected]fc9d88472013-08-14 02:31:172108 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472109 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462110}
2111
bncce36dca22015-04-21 22:11:232112// Send a spdy request to www.example.org that gets redirected to www.foo.com.
bncd16676a2016-07-20 16:23:012113TEST_F(SpdyNetworkTransactionTest, DISABLED_RedirectGetRequest) {
bncb26024382016-06-29 02:39:452114 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc086b39e12016-06-24 13:05:262115 headers["user-agent"] = "";
2116 headers["accept-encoding"] = "gzip, deflate";
[email protected]e3ebba0f2010-08-05 17:59:582117
bncce36dca22015-04-21 22:11:232118 // Setup writes/reads to www.example.org
bncdf80d44fd2016-07-15 20:27:412119 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:152120 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
2121 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReplyRedirect(1));
[email protected]e3ebba0f2010-08-05 17:59:582122 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412123 CreateMockWrite(req, 1),
[email protected]e3ebba0f2010-08-05 17:59:582124 };
2125 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412126 CreateMockRead(resp, 2), MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582127 };
bnc086b39e12016-06-24 13:05:262128 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]e3ebba0f2010-08-05 17:59:582129
2130 // Setup writes/reads to www.foo.com
bnc086b39e12016-06-24 13:05:262131 SpdyHeaderBlock headers2(
2132 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2133 headers2["user-agent"] = "";
2134 headers2["accept-encoding"] = "gzip, deflate";
bncdf80d44fd2016-07-15 20:27:412135 SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:152136 spdy_util_.ConstructSpdyHeaders(1, std::move(headers2), LOWEST, true));
bnc086b39e12016-06-24 13:05:262137 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:412138 CreateMockWrite(req2, 1),
bnc086b39e12016-06-24 13:05:262139 };
2140
bnc42331402016-07-25 13:36:152141 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412142 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582143 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:412144 CreateMockRead(resp2, 2), CreateMockRead(body2, 3),
2145 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582146 };
bnc086b39e12016-06-24 13:05:262147
rch08e3aa3e2015-05-16 14:27:522148 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2149 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582150
2151 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582152 TestDelegate d;
2153 {
bnca9b9e222016-07-11 20:10:402154 SpdyURLRequestContext spdy_url_request_context;
danakjaee3e1ec2016-04-16 00:23:182155 std::unique_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
bncb26024382016-06-29 02:39:452156 default_url_, DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092157 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572158 AddSocketDataProvider(&data);
[email protected]ef2bf422012-05-11 03:27:092159 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572160 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582161
2162 d.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192163 r->Start();
[email protected]fc9d88472013-08-14 02:31:172164 base::RunLoop().Run();
[email protected]513963e2013-06-15 01:53:042165
[email protected]e3ebba0f2010-08-05 17:59:582166 EXPECT_EQ(1, d.received_redirect_count());
2167
[email protected]f7022f32014-08-21 16:32:192168 r->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172169 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582170 EXPECT_EQ(1, d.response_started_count());
2171 EXPECT_FALSE(d.received_data_before_response());
bnc301745a2015-03-10 03:22:162172 EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582173 std::string contents("hello!");
2174 EXPECT_EQ(contents, d.data_received());
2175 }
rch37de576c2015-05-17 20:28:172176 EXPECT_TRUE(data.AllReadDataConsumed());
2177 EXPECT_TRUE(data.AllWriteDataConsumed());
2178 EXPECT_TRUE(data2.AllReadDataConsumed());
2179 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582180}
2181
bncce36dca22015-04-21 22:11:232182// Send a spdy request to www.example.org. Get a pushed stream that redirects to
[email protected]e3ebba0f2010-08-05 17:59:582183// www.foo.com.
bncd16676a2016-07-20 16:23:012184TEST_F(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
bncb26024382016-06-29 02:39:452185 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc086b39e12016-06-24 13:05:262186 headers["user-agent"] = "";
2187 headers["accept-encoding"] = "gzip, deflate";
[email protected]3a8d6852011-03-11 23:43:442188
bncce36dca22015-04-21 22:11:232189 // Setup writes/reads to www.example.org
bncdf80d44fd2016-07-15 20:27:412190 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:152191 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
2192 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412193 SpdySerializedFrame rep(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002194 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
2195 "301 Moved Permanently", "http://www.foo.com/index.php"));
bncdf80d44fd2016-07-15 20:27:412196 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
2197 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:202198 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]3a8d6852011-03-11 23:43:442199 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412200 CreateMockWrite(req, 1), CreateMockWrite(rst, 6),
[email protected]3a8d6852011-03-11 23:43:442201 };
2202 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412203 CreateMockRead(resp, 2), CreateMockRead(rep, 3), CreateMockRead(body, 4),
2204 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2205 MockRead(ASYNC, 0, 0, 7) // EOF
[email protected]3a8d6852011-03-11 23:43:442206 };
2207
2208 // Setup writes/reads to www.foo.com
bnc086b39e12016-06-24 13:05:262209 SpdyHeaderBlock headers2(
[email protected]513963e2013-06-15 01:53:042210 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
bnc086b39e12016-06-24 13:05:262211 headers2["user-agent"] = "";
2212 headers2["accept-encoding"] = "gzip, deflate";
bncdf80d44fd2016-07-15 20:27:412213 SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:152214 spdy_util_.ConstructSpdyHeaders(1, std::move(headers2), LOWEST, true));
2215 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412216 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582217 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:412218 CreateMockWrite(req2, 1),
[email protected]e3ebba0f2010-08-05 17:59:582219 };
2220 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:412221 CreateMockRead(resp2, 2), CreateMockRead(body2, 3),
2222 MockRead(ASYNC, 0, 0, 5) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582223 };
rch08e3aa3e2015-05-16 14:27:522224 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2225 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2226 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582227
[email protected]e3ebba0f2010-08-05 17:59:582228 TestDelegate d;
2229 TestDelegate d2;
bnca9b9e222016-07-11 20:10:402230 SpdyURLRequestContext spdy_url_request_context;
[email protected]e3ebba0f2010-08-05 17:59:582231 {
danakjaee3e1ec2016-04-16 00:23:182232 std::unique_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
bncb26024382016-06-29 02:39:452233 default_url_, DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092234 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572235 AddSocketDataProvider(&data);
[email protected]e3ebba0f2010-08-05 17:59:582236
[email protected]f7022f32014-08-21 16:32:192237 r->Start();
[email protected]fc9d88472013-08-14 02:31:172238 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582239
2240 EXPECT_EQ(0, d.received_redirect_count());
2241 std::string contents("hello!");
2242 EXPECT_EQ(contents, d.data_received());
2243
danakjaee3e1ec2016-04-16 00:23:182244 std::unique_ptr<URLRequest> r2(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002245 GURL(GetDefaultUrlWithPath("/foo.dat")), DEFAULT_PRIORITY, &d2));
[email protected]ef2bf422012-05-11 03:27:092246 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572247 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582248
2249 d2.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192250 r2->Start();
[email protected]fc9d88472013-08-14 02:31:172251 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582252 EXPECT_EQ(1, d2.received_redirect_count());
2253
[email protected]f7022f32014-08-21 16:32:192254 r2->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172255 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582256 EXPECT_EQ(1, d2.response_started_count());
2257 EXPECT_FALSE(d2.received_data_before_response());
bnc301745a2015-03-10 03:22:162258 EXPECT_EQ(URLRequestStatus::SUCCESS, r2->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582259 std::string contents2("hello!");
2260 EXPECT_EQ(contents2, d2.data_received());
2261 }
rch08e3aa3e2015-05-16 14:27:522262 EXPECT_TRUE(data.AllReadDataConsumed());
2263 EXPECT_TRUE(data.AllWriteDataConsumed());
2264 EXPECT_TRUE(data2.AllReadDataConsumed());
2265 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582266}
2267
bncd16676a2016-07-20 16:23:012268TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
bncdf80d44fd2016-07-15 20:27:412269 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492270 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412271 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582272 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412273 CreateMockWrite(stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582274 };
2275
bncdf80d44fd2016-07-15 20:27:412276 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152277 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412278 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002279 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432280 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412281 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2282 2, kPushedData, strlen(kPushedData), true));
[email protected]e3ebba0f2010-08-05 17:59:582283 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412284 CreateMockRead(stream1_reply, 1),
2285 CreateMockRead(stream2_syn, 2),
2286 CreateMockRead(stream1_body, 3, SYNCHRONOUS),
2287 CreateMockRead(stream2_body, 4),
rch08e3aa3e2015-05-16 14:27:522288 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582289 };
2290
2291 HttpResponseInfo response;
2292 HttpResponseInfo response2;
[email protected]19ec8a72010-08-23 03:38:232293 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522294 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572295 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032296 &response,
2297 &response2,
2298 expected_push_result);
[email protected]e3ebba0f2010-08-05 17:59:582299
bnc42331402016-07-25 13:36:152300 // Verify the response headers.
wezca1070932016-05-26 20:30:522301 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022302 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582303
2304 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522305 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042306 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582307}
2308
bnc42331402016-07-25 13:36:152309TEST_F(SpdyNetworkTransactionTest, ServerPushBeforeHeaders) {
bncdf80d44fd2016-07-15 20:27:412310 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492311 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]a5b8eb29d2012-03-06 06:19:462312 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412313 CreateMockWrite(stream1_syn, 0),
[email protected]a5b8eb29d2012-03-06 06:19:462314 };
2315
bncdf80d44fd2016-07-15 20:27:412316 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc38dcd392016-02-09 23:19:492317 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:412318 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152319 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412320 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8a0fc822013-06-27 20:52:432321 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412322 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2323 2, kPushedData, strlen(kPushedData), true));
[email protected]a5b8eb29d2012-03-06 06:19:462324 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412325 CreateMockRead(stream2_syn, 1),
2326 CreateMockRead(stream1_reply, 2),
2327 CreateMockRead(stream1_body, 3, SYNCHRONOUS),
2328 CreateMockRead(stream2_body, 4),
rch08e3aa3e2015-05-16 14:27:522329 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]a5b8eb29d2012-03-06 06:19:462330 };
2331
2332 HttpResponseInfo response;
2333 HttpResponseInfo response2;
2334 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522335 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572336 RunServerPushTest(&data,
[email protected]a5b8eb29d2012-03-06 06:19:462337 &response,
2338 &response2,
2339 expected_push_result);
2340
bnc42331402016-07-25 13:36:152341 // Verify the response headers.
wezca1070932016-05-26 20:30:522342 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022343 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]a5b8eb29d2012-03-06 06:19:462344
2345 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522346 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042347 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]a5b8eb29d2012-03-06 06:19:462348}
2349
bncd16676a2016-07-20 16:23:012350TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
bncdf80d44fd2016-07-15 20:27:412351 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492352 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:522353 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412354 CreateMockWrite(stream1_syn, 0),
rch08e3aa3e2015-05-16 14:27:522355 };
[email protected]82918cc2010-08-25 17:24:502356
bncdf80d44fd2016-07-15 20:27:412357 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152358 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412359 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002360 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432361 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412362 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2363 2, kPushedData, strlen(kPushedData), true));
2364 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]82918cc2010-08-25 17:24:502365 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412366 CreateMockRead(stream1_reply, 1),
2367 CreateMockRead(stream2_syn, 2),
2368 CreateMockRead(stream2_body, 3),
2369 CreateMockRead(stream1_body, 4, SYNCHRONOUS),
rch08e3aa3e2015-05-16 14:27:522370 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]82918cc2010-08-25 17:24:502371 };
2372
2373 HttpResponseInfo response;
2374 HttpResponseInfo response2;
2375 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522376 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572377 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032378 &response,
2379 &response2,
2380 expected_push_result);
[email protected]82918cc2010-08-25 17:24:502381
bnc42331402016-07-25 13:36:152382 // Verify the response headers.
wezca1070932016-05-26 20:30:522383 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022384 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]82918cc2010-08-25 17:24:502385
2386 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522387 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042388 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]82918cc2010-08-25 17:24:502389}
2390
bncd16676a2016-07-20 16:23:012391TEST_F(SpdyNetworkTransactionTest, ServerPushServerAborted) {
bncdf80d44fd2016-07-15 20:27:412392 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492393 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412394 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582395 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412396 CreateMockWrite(stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582397 };
2398
bncdf80d44fd2016-07-15 20:27:412399 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152400 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412401 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002402 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:412403 SpdySerializedFrame stream2_rst(
[email protected]c10b20852013-05-15 21:29:202404 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582405 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412406 CreateMockRead(stream1_reply, 1),
2407 CreateMockRead(stream2_syn, 2),
2408 CreateMockRead(stream2_rst, 3),
2409 CreateMockRead(stream1_body, 4, SYNCHRONOUS),
rch08e3aa3e2015-05-16 14:27:522410 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582411 };
2412
rch08e3aa3e2015-05-16 14:27:522413 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362414 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012415 BoundNetLog(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582416
2417 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572418 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582419
2420 HttpNetworkTransaction* trans = helper.trans();
2421
2422 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412423 TestCompletionCallback callback;
2424 int rv = trans->Start(
2425 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012426 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:582427 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012428 EXPECT_THAT(rv, IsOk());
[email protected]19ec8a72010-08-23 03:38:232429
2430 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522431 EXPECT_TRUE(data.AllReadDataConsumed());
2432 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]19ec8a72010-08-23 03:38:232433
bnc42331402016-07-25 13:36:152434 // Verify the response headers.
[email protected]19ec8a72010-08-23 03:38:232435 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522436 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022437 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232438}
2439
[email protected]8a0fc822013-06-27 20:52:432440// Verify that we don't leak streams and that we properly send a reset
2441// if the server pushes the same stream twice.
bncd16676a2016-07-20 16:23:012442TEST_F(SpdyNetworkTransactionTest, ServerPushDuplicate) {
bncdf80d44fd2016-07-15 20:27:412443 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492444 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412445 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2446 SpdySerializedFrame stream3_rst(
[email protected]c10b20852013-05-15 21:29:202447 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
[email protected]fdc165a2010-09-03 03:51:292448 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412449 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream3_rst, 4),
[email protected]fdc165a2010-09-03 03:51:292450 };
2451
bncdf80d44fd2016-07-15 20:27:412452 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152453 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412454 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002455 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432456 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412457 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2458 2, kPushedData, strlen(kPushedData), true));
2459 SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002460 NULL, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]fdc165a2010-09-03 03:51:292461 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412462 CreateMockRead(stream1_reply, 1),
2463 CreateMockRead(stream2_syn, 2),
2464 CreateMockRead(stream3_syn, 3),
2465 CreateMockRead(stream1_body, 5),
2466 CreateMockRead(stream2_body, 6),
rch08e3aa3e2015-05-16 14:27:522467 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7), // Force a pause
[email protected]fdc165a2010-09-03 03:51:292468 };
2469
2470 HttpResponseInfo response;
2471 HttpResponseInfo response2;
2472 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522473 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572474 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032475 &response,
2476 &response2,
2477 expected_push_result);
[email protected]fdc165a2010-09-03 03:51:292478
bnc42331402016-07-25 13:36:152479 // Verify the response headers.
wezca1070932016-05-26 20:30:522480 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022481 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]fdc165a2010-09-03 03:51:292482
2483 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522484 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042485 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]fdc165a2010-09-03 03:51:292486}
2487
bncd16676a2016-07-20 16:23:012488TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
bncdf80d44fd2016-07-15 20:27:412489 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492490 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412491 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232492 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412493 CreateMockWrite(stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232494 };
2495
bncdf80d44fd2016-07-15 20:27:412496 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152497 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412498 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002499 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432500 static const char kPushedData[] = "pushed my darling hello my baby";
bncdf80d44fd2016-07-15 20:27:412501 SpdySerializedFrame stream2_body_base(spdy_util_.ConstructSpdyDataFrame(
2502 2, kPushedData, strlen(kPushedData), true));
[email protected]8a0fc822013-06-27 20:52:432503 const size_t kChunkSize = strlen(kPushedData) / 4;
bncdf80d44fd2016-07-15 20:27:412504 SpdySerializedFrame stream2_body1(stream2_body_base.data(), kChunkSize,
2505 false);
2506 SpdySerializedFrame stream2_body2(stream2_body_base.data() + kChunkSize,
2507 kChunkSize, false);
2508 SpdySerializedFrame stream2_body3(stream2_body_base.data() + 2 * kChunkSize,
2509 kChunkSize, false);
2510 SpdySerializedFrame stream2_body4(stream2_body_base.data() + 3 * kChunkSize,
2511 stream2_body_base.size() - 3 * kChunkSize,
2512 false);
[email protected]19ec8a72010-08-23 03:38:232513 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412514 CreateMockRead(stream1_reply, 1),
2515 CreateMockRead(stream2_syn, 2),
2516 CreateMockRead(stream2_body1, 3),
2517 CreateMockRead(stream2_body2, 4),
2518 CreateMockRead(stream2_body3, 5),
2519 CreateMockRead(stream2_body4, 6),
2520 CreateMockRead(stream1_body, 7, SYNCHRONOUS),
rch08e3aa3e2015-05-16 14:27:522521 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), // Force a pause
[email protected]19ec8a72010-08-23 03:38:232522 };
2523
2524 HttpResponseInfo response;
2525 HttpResponseInfo response2;
2526 std::string expected_push_result("pushed my darling hello my baby");
rch08e3aa3e2015-05-16 14:27:522527 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432528 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232529
bnc42331402016-07-25 13:36:152530 // Verify the response headers.
wezca1070932016-05-26 20:30:522531 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022532 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232533
2534 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522535 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042536 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232537}
2538
bncd16676a2016-07-20 16:23:012539TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
bncdf80d44fd2016-07-15 20:27:412540 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492541 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412542 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232543 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412544 CreateMockWrite(stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232545 };
2546
bncdf80d44fd2016-07-15 20:27:412547 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152548 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412549 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002550 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432551 static const char kPushedData[] = "pushed my darling hello my baby";
bncdf80d44fd2016-07-15 20:27:412552 SpdySerializedFrame stream2_body_base(spdy_util_.ConstructSpdyDataFrame(
2553 2, kPushedData, strlen(kPushedData), true));
[email protected]8a0fc822013-06-27 20:52:432554 const size_t kChunkSize = strlen(kPushedData) / 4;
bncdf80d44fd2016-07-15 20:27:412555 SpdySerializedFrame stream2_body1(stream2_body_base.data(), kChunkSize,
2556 false);
2557 SpdySerializedFrame stream2_body2(stream2_body_base.data() + kChunkSize,
2558 kChunkSize, false);
2559 SpdySerializedFrame stream2_body3(stream2_body_base.data() + 2 * kChunkSize,
2560 kChunkSize, false);
2561 SpdySerializedFrame stream2_body4(stream2_body_base.data() + 3 * kChunkSize,
2562 stream2_body_base.size() - 3 * kChunkSize,
2563 false);
[email protected]19ec8a72010-08-23 03:38:232564 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412565 CreateMockRead(stream1_reply, 1),
2566 CreateMockRead(stream2_syn, 2),
2567 CreateMockRead(stream2_body1, 3),
2568 CreateMockRead(stream2_body2, 4),
2569 CreateMockRead(stream2_body3, 5),
2570 CreateMockRead(stream2_body4, 6),
2571 CreateMockRead(stream1_body, 7, SYNCHRONOUS),
rch08e3aa3e2015-05-16 14:27:522572 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8) // Force a pause.
[email protected]19ec8a72010-08-23 03:38:232573 };
2574
2575 HttpResponseInfo response;
2576 HttpResponseInfo response2;
rch08e3aa3e2015-05-16 14:27:522577 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432578 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232579
bnc42331402016-07-25 13:36:152580 // Verify the response headers.
wezca1070932016-05-26 20:30:522581 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022582 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232583
2584 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522585 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042586 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232587}
2588
bncd16676a2016-07-20 16:23:012589TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
bncdf80d44fd2016-07-15 20:27:412590 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492591 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412592 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
2593 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_STREAM_ID)."));
[email protected]19ec8a72010-08-23 03:38:232594 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412595 CreateMockWrite(stream1_syn, 0), CreateMockWrite(goaway, 3),
[email protected]19ec8a72010-08-23 03:38:232596 };
2597
bncdf80d44fd2016-07-15 20:27:412598 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152599 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412600 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002601 NULL, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]19ec8a72010-08-23 03:38:232602 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412603 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
[email protected]19ec8a72010-08-23 03:38:232604 };
2605
rch08e3aa3e2015-05-16 14:27:522606 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362607 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012608 BoundNetLog(), NULL);
[email protected]19ec8a72010-08-23 03:38:232609
2610 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572611 helper.AddData(&data);
[email protected]19ec8a72010-08-23 03:38:232612
2613 HttpNetworkTransaction* trans = helper.trans();
2614
2615 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412616 TestCompletionCallback callback;
2617 int rv = trans->Start(
2618 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012619 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]19ec8a72010-08-23 03:38:232620 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012621 EXPECT_THAT(rv, IsOk());
[email protected]e3ebba0f2010-08-05 17:59:582622
2623 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522624 EXPECT_TRUE(data.AllReadDataConsumed());
2625 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582626
bnc42331402016-07-25 13:36:152627 // Verify the response headers.
[email protected]e3ebba0f2010-08-05 17:59:582628 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522629 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022630 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582631}
2632
bncd16676a2016-07-20 16:23:012633TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
bncdf80d44fd2016-07-15 20:27:412634 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492635 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412636 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2637 SpdySerializedFrame stream2_rst(
[email protected]c10b20852013-05-15 21:29:202638 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
[email protected]e3ebba0f2010-08-05 17:59:582639 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412640 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582641 };
2642
bncdf80d44fd2016-07-15 20:27:412643 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152644 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412645 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002646 NULL, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]e3ebba0f2010-08-05 17:59:582647 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412648 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2649 CreateMockRead(stream1_body, 4),
rch08e3aa3e2015-05-16 14:27:522650 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582651 };
2652
rch08e3aa3e2015-05-16 14:27:522653 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362654 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012655 BoundNetLog(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582656
2657 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572658 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582659
2660 HttpNetworkTransaction* trans = helper.trans();
2661
2662 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412663 TestCompletionCallback callback;
2664 int rv = trans->Start(
2665 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012666 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:582667 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012668 EXPECT_THAT(rv, IsOk());
[email protected]e3ebba0f2010-08-05 17:59:582669
2670 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522671 EXPECT_TRUE(data.AllReadDataConsumed());
2672 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582673
bnc42331402016-07-25 13:36:152674 // Verify the response headers.
[email protected]e3ebba0f2010-08-05 17:59:582675 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522676 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022677 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582678}
2679
bncd16676a2016-07-20 16:23:012680TEST_F(SpdyNetworkTransactionTest, ServerPushNoURL) {
bncdf80d44fd2016-07-15 20:27:412681 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492682 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412683 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2684 SpdySerializedFrame stream2_rst(
[email protected]c10b20852013-05-15 21:29:202685 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582686 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412687 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582688 };
2689
bncdf80d44fd2016-07-15 20:27:412690 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152691 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bnc086b39e12016-06-24 13:05:262692 SpdyHeaderBlock incomplete_headers;
2693 incomplete_headers[spdy_util_.GetStatusKey()] = "200 OK";
bnc086b39e12016-06-24 13:05:262694 incomplete_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:412695 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
2696 std::move(incomplete_headers), 2, 1));
[email protected]e3ebba0f2010-08-05 17:59:582697 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412698 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2699 CreateMockRead(stream1_body, 4),
rch08e3aa3e2015-05-16 14:27:522700 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582701 };
2702
rch08e3aa3e2015-05-16 14:27:522703 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362704 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012705 BoundNetLog(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582706
2707 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572708 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582709
2710 HttpNetworkTransaction* trans = helper.trans();
2711
2712 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412713 TestCompletionCallback callback;
2714 int rv = trans->Start(
2715 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012716 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:582717 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012718 EXPECT_THAT(rv, IsOk());
rch08e3aa3e2015-05-16 14:27:522719
[email protected]e3ebba0f2010-08-05 17:59:582720 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522721 EXPECT_TRUE(data.AllReadDataConsumed());
2722 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582723
bnc42331402016-07-25 13:36:152724 // Verify the response headers.
[email protected]e3ebba0f2010-08-05 17:59:582725 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522726 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022727 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582728}
2729
bnc0cb98b22016-03-04 17:10:522730// PUSH_PROMISE on a server-initiated stream should trigger GOAWAY.
bncd16676a2016-07-20 16:23:012731TEST_F(SpdyNetworkTransactionTest, ServerPushOnPushedStream) {
bncdf80d44fd2016-07-15 20:27:412732 SpdySerializedFrame stream1_syn(
bnc0cb98b22016-03-04 17:10:522733 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412734 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bnc0cb98b22016-03-04 17:10:522735 2, GOAWAY_PROTOCOL_ERROR, "Push on even stream id."));
2736 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412737 CreateMockWrite(stream1_syn, 0), CreateMockWrite(goaway, 4),
bnc0cb98b22016-03-04 17:10:522738 };
2739
bncdf80d44fd2016-07-15 20:27:412740 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152741 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412742 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:522743 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:412744 SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:522745 nullptr, 0, 4, 2, GetDefaultUrlWithPath("/bar.dat").c_str()));
2746 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412747 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2748 CreateMockRead(stream3_syn, 3),
bnc0cb98b22016-03-04 17:10:522749 };
2750
2751 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2752 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012753 BoundNetLog(), nullptr);
bnc0cb98b22016-03-04 17:10:522754 helper.RunToCompletion(&data);
2755}
2756
2757// PUSH_PROMISE on a closed client-initiated stream should trigger RST_STREAM.
bncd16676a2016-07-20 16:23:012758TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedStream) {
bncdf80d44fd2016-07-15 20:27:412759 SpdySerializedFrame stream1_syn(
bnc0cb98b22016-03-04 17:10:522760 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412761 SpdySerializedFrame rst(
bnc0cb98b22016-03-04 17:10:522762 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
2763 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412764 CreateMockWrite(stream1_syn, 0), CreateMockWrite(rst, 5),
bnc0cb98b22016-03-04 17:10:522765 };
2766
bncdf80d44fd2016-07-15 20:27:412767 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152768 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412769 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2770 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:522771 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2772 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412773 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_body, 2),
2774 CreateMockRead(stream2_syn, 3), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
bnc0cb98b22016-03-04 17:10:522775 };
2776
2777 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2778 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012779 BoundNetLog(), nullptr);
bnc0cb98b22016-03-04 17:10:522780 helper.RunPreTestSetup();
2781 helper.AddData(&data);
2782
2783 HttpNetworkTransaction* trans = helper.trans();
2784
2785 TestCompletionCallback callback;
2786 int rv =
2787 trans->Start(&CreateGetRequest(), callback.callback(), BoundNetLog());
2788 rv = callback.GetResult(rv);
robpercival214763f2016-07-01 23:27:012789 EXPECT_THAT(rv, IsOk());
bnc0cb98b22016-03-04 17:10:522790 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522791 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:522792 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
2793
2794 EXPECT_TRUE(data.AllReadDataConsumed());
2795 EXPECT_TRUE(data.AllWriteDataConsumed());
2796 VerifyStreamsClosed(helper);
2797}
2798
2799// PUSH_PROMISE on a server-initiated stream should trigger GOAWAY even if
2800// stream is closed.
bncd16676a2016-07-20 16:23:012801TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedPushedStream) {
bncdf80d44fd2016-07-15 20:27:412802 SpdySerializedFrame stream1_syn(
bnc0cb98b22016-03-04 17:10:522803 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412804 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bnc0cb98b22016-03-04 17:10:522805 2, GOAWAY_PROTOCOL_ERROR, "Push on even stream id."));
2806 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412807 CreateMockWrite(stream1_syn, 0), CreateMockWrite(goaway, 7),
bnc0cb98b22016-03-04 17:10:522808 };
2809
bncdf80d44fd2016-07-15 20:27:412810 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152811 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412812 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:522813 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:412814 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc0cb98b22016-03-04 17:10:522815 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412816 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2817 2, kPushedData, strlen(kPushedData), true));
2818 SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:522819 nullptr, 0, 4, 2, GetDefaultUrlWithPath("/bar.dat").c_str()));
2820
2821 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412822 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2823 CreateMockRead(stream1_body, 3), CreateMockRead(stream2_body, 4),
2824 MockRead(ASYNC, ERR_IO_PENDING, 5), CreateMockRead(stream3_syn, 6),
bnc0cb98b22016-03-04 17:10:522825 };
2826
2827 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2828 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012829 BoundNetLog(), nullptr);
bnc0cb98b22016-03-04 17:10:522830 helper.RunPreTestSetup();
2831 helper.AddData(&data);
2832
2833 HttpNetworkTransaction* trans1 = helper.trans();
2834 TestCompletionCallback callback1;
2835 int rv =
2836 trans1->Start(&CreateGetRequest(), callback1.callback(), BoundNetLog());
2837 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:012838 EXPECT_THAT(rv, IsOk());
bnc0cb98b22016-03-04 17:10:522839 HttpResponseInfo response = *trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:522840 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:522841 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
2842
bnc691fda62016-08-12 00:43:162843 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
bnc0cb98b22016-03-04 17:10:522844 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:162845 rv = trans2.Start(&CreateGetPushRequest(), callback2.callback(),
2846 BoundNetLog());
bnc0cb98b22016-03-04 17:10:522847 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:012848 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:162849 response = *trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:522850 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:522851 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
2852 std::string result;
bnc691fda62016-08-12 00:43:162853 ReadResult(&trans2, &result);
bnc0cb98b22016-03-04 17:10:522854 EXPECT_EQ(kPushedData, result);
2855
2856 data.Resume();
2857 base::RunLoop().RunUntilIdle();
2858
2859 EXPECT_TRUE(data.AllReadDataConsumed());
2860 EXPECT_TRUE(data.AllWriteDataConsumed());
2861}
2862
bnc42331402016-07-25 13:36:152863// Verify that various response headers parse correctly through the HTTP layer.
2864TEST_F(SpdyNetworkTransactionTest, ResponseHeaders) {
2865 struct ResponseHeadersTests {
[email protected]e7f75092010-07-01 22:39:132866 int num_headers;
2867 const char* extra_headers[5];
[email protected]513963e2013-06-15 01:53:042868 SpdyHeaderBlock expected_headers;
[email protected]8b070372009-11-16 22:01:252869 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:132870 // This uses a multi-valued cookie header.
2871 { 2,
2872 { "cookie", "val1",
2873 "cookie", "val2", // will get appended separated by NULL
2874 NULL
2875 },
[email protected]8b070372009-11-16 22:01:252876 },
[email protected]e7f75092010-07-01 22:39:132877 // This is the minimalist set of headers.
2878 { 0,
2879 { NULL },
[email protected]8b070372009-11-16 22:01:252880 },
[email protected]e7f75092010-07-01 22:39:132881 // Headers with a comma separated list.
2882 { 1,
2883 { "cookie", "val1,val2",
2884 NULL
2885 },
[email protected]8b070372009-11-16 22:01:252886 }
2887 };
2888
[email protected]513963e2013-06-15 01:53:042889 test_cases[0].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:042890 test_cases[1].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:042891 test_cases[2].expected_headers["status"] = "200";
[email protected]601e03f12014-04-06 16:26:392892
bnc7ecc1122015-09-28 13:22:492893 test_cases[0].expected_headers["hello"] = "bye";
2894 test_cases[1].expected_headers["hello"] = "bye";
2895 test_cases[2].expected_headers["hello"] = "bye";
2896
bnc2d247912016-04-21 23:34:372897 test_cases[0].expected_headers["cookie"] = base::StringPiece("val1\0val2", 9);
bnc7ecc1122015-09-28 13:22:492898 test_cases[2].expected_headers["cookie"] = "val1,val2";
2899
viettrungluue4a8b882014-10-16 06:17:382900 for (size_t i = 0; i < arraysize(test_cases); ++i) {
bncd16676a2016-07-20 16:23:012901 SpdyTestUtil spdy_test_util;
bncdf80d44fd2016-07-15 20:27:412902 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:492903 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412904 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8b070372009-11-16 22:01:252905
bnc42331402016-07-25 13:36:152906 SpdySerializedFrame resp(spdy_test_util.ConstructSpdyGetReply(
bncdf80d44fd2016-07-15 20:27:412907 test_cases[i].extra_headers, test_cases[i].num_headers, 1));
2908 SpdySerializedFrame body(spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]8b070372009-11-16 22:01:252909 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412910 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:522911 MockRead(ASYNC, 0, 3) // EOF
[email protected]8b070372009-11-16 22:01:252912 };
2913
rch08e3aa3e2015-05-16 14:27:522914 SequencedSocketData data(reads, arraysize(reads), writes,
2915 arraysize(writes));
[email protected]262eec82013-03-19 21:01:362916 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012917 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:572918 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:472919 TransactionHelperResult out = helper.output();
2920
robpercival214763f2016-07-01 23:27:012921 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:022922 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8b070372009-11-16 22:01:252923 EXPECT_EQ("hello!", out.response_data);
2924
2925 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
wezca1070932016-05-26 20:30:522926 EXPECT_TRUE(headers);
olli.raula33c282f2016-01-21 12:12:492927 size_t iter = 0;
[email protected]513963e2013-06-15 01:53:042928 std::string name, value;
2929 SpdyHeaderBlock header_block;
[email protected]8b070372009-11-16 22:01:252930 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
bnc7ecc1122015-09-28 13:22:492931 SpdyHeaderBlock::StringPieceProxy mutable_header_block_value =
2932 header_block[name];
bnc2d247912016-04-21 23:34:372933 if (static_cast<base::StringPiece>(mutable_header_block_value).empty()) {
bnc7ecc1122015-09-28 13:22:492934 mutable_header_block_value = value;
[email protected]513963e2013-06-15 01:53:042935 } else {
bnc7ecc1122015-09-28 13:22:492936 std::string joint_value = mutable_header_block_value.as_string();
2937 joint_value.append(1, '\0');
2938 joint_value.append(value);
2939 mutable_header_block_value = joint_value;
[email protected]513963e2013-06-15 01:53:042940 }
[email protected]8b070372009-11-16 22:01:252941 }
[email protected]513963e2013-06-15 01:53:042942 EXPECT_EQ(test_cases[i].expected_headers, header_block);
[email protected]8b070372009-11-16 22:01:252943 }
2944}
2945
bnc42331402016-07-25 13:36:152946// Verify that various response headers parse vary fields correctly through the
2947// HTTP layer, and the response matches the request.
2948TEST_F(SpdyNetworkTransactionTest, ResponseHeadersVary) {
[email protected]3f662f12010-03-25 19:56:122949 // Modify the following data to change/add test cases:
bnc42331402016-07-25 13:36:152950 struct ResponseTests {
[email protected]3f662f12010-03-25 19:56:122951 bool vary_matches;
2952 int num_headers[2];
2953 const char* extra_headers[2][16];
2954 } test_cases[] = {
bnc7ecc1122015-09-28 13:22:492955 // Test the case of a multi-valued cookie. When the value is delimited
2956 // with NUL characters, it needs to be unfolded into multiple headers.
2957 {true,
bnca9b9e222016-07-11 20:10:402958 {1, 3},
bnc7ecc1122015-09-28 13:22:492959 {{"cookie", "val1,val2", NULL},
2960 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
bnca9b9e222016-07-11 20:10:402961 "/index.php", "vary", "cookie", NULL}}},
bnc7ecc1122015-09-28 13:22:492962 {// Multiple vary fields.
2963 true,
bnc7ecc1122015-09-28 13:22:492964 {2, 4},
2965 {{"friend", "barney", "enemy", "snaggletooth", NULL},
2966 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
bnca9b9e222016-07-11 20:10:402967 "/index.php", "vary", "friend", "vary", "enemy", NULL}}},
2968 {// Test a '*' vary field.
2969 false,
2970 {1, 3},
2971 {{"cookie", "val1,val2", NULL},
2972 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
2973 "/index.php", "vary", "*", NULL}}},
2974 {// Multiple comma-separated vary fields.
2975 true,
2976 {2, 3},
2977 {{"friend", "barney", "enemy", "snaggletooth", NULL},
2978 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
2979 "/index.php", "vary", "friend,enemy", NULL}}}};
[email protected]3f662f12010-03-25 19:56:122980
viettrungluue4a8b882014-10-16 06:17:382981 for (size_t i = 0; i < arraysize(test_cases); ++i) {
bncd16676a2016-07-20 16:23:012982 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:492983
[email protected]3f662f12010-03-25 19:56:122984 // Construct the request.
bncdf80d44fd2016-07-15 20:27:412985 SpdySerializedFrame frame_req(spdy_test_util.ConstructSpdyGet(
2986 test_cases[i].extra_headers[0], test_cases[i].num_headers[0], 1, LOWEST,
2987 true));
[email protected]3f662f12010-03-25 19:56:122988
2989 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412990 CreateMockWrite(frame_req, 0),
[email protected]3f662f12010-03-25 19:56:122991 };
2992
2993 // Construct the reply.
[email protected]745aa9c2014-06-27 02:21:292994 SpdyHeaderBlock reply_headers;
2995 AppendToHeaderBlock(test_cases[i].extra_headers[1],
2996 test_cases[i].num_headers[1],
2997 &reply_headers);
bnc086b39e12016-06-24 13:05:262998 // Construct the expected header reply string before moving |reply_headers|.
2999 std::string expected_reply =
3000 spdy_test_util.ConstructSpdyReplyString(reply_headers);
3001
bncdf80d44fd2016-07-15 20:27:413002 SpdySerializedFrame frame_reply(
bnc086b39e12016-06-24 13:05:263003 spdy_test_util.ConstructSpdyReply(1, std::move(reply_headers)));
[email protected]3f662f12010-03-25 19:56:123004
bncdf80d44fd2016-07-15 20:27:413005 SpdySerializedFrame body(spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]3f662f12010-03-25 19:56:123006 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413007 CreateMockRead(frame_reply, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:523008 MockRead(ASYNC, 0, 3) // EOF
[email protected]3f662f12010-03-25 19:56:123009 };
3010
[email protected]3f662f12010-03-25 19:56:123011 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:433012 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:123013
[email protected]d3cee19d2010-06-22 18:42:183014 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:433015 for (int ct = 0; ct < header_count; ct++) {
3016 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3017 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3018 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:123019 }
3020
rch08e3aa3e2015-05-16 14:27:523021 SequencedSocketData data(reads, arraysize(reads), writes,
3022 arraysize(writes));
bncd16676a2016-07-20 16:23:013023 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
3024 NULL);
[email protected]dd54bd82012-07-19 23:44:573025 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473026 TransactionHelperResult out = helper.output();
3027
[email protected]3f662f12010-03-25 19:56:123028 EXPECT_EQ(OK, out.rv) << i;
bnc84e7fb52015-12-02 11:50:023029 EXPECT_EQ("HTTP/1.1 200", out.status_line) << i;
[email protected]3f662f12010-03-25 19:56:123030 EXPECT_EQ("hello!", out.response_data) << i;
3031
3032 // Test the response information.
[email protected]3f662f12010-03-25 19:56:123033 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3034 test_cases[i].vary_matches) << i;
3035
3036 // Check the headers.
3037 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
wezca1070932016-05-26 20:30:523038 ASSERT_TRUE(headers) << i;
olli.raula33c282f2016-01-21 12:12:493039 size_t iter = 0;
[email protected]3f662f12010-03-25 19:56:123040 std::string name, value, lines;
3041 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3042 lines.append(name);
3043 lines.append(": ");
3044 lines.append(value);
3045 lines.append("\n");
3046 }
3047
[email protected]9aa323192013-05-31 21:38:403048 EXPECT_EQ(expected_reply, lines) << i;
[email protected]3f662f12010-03-25 19:56:123049 }
3050}
3051
bnc42331402016-07-25 13:36:153052// Verify that we don't crash on invalid response headers.
3053TEST_F(SpdyNetworkTransactionTest, InvalidResponseHeaders) {
3054 struct InvalidResponseHeadersTests {
[email protected]e7f75092010-07-01 22:39:133055 int num_headers;
3056 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:483057 } test_cases[] = {
bnc42331402016-07-25 13:36:153058 // Response headers missing status header
bnc7ecc1122015-09-28 13:22:493059 {
bnca9b9e222016-07-11 20:10:403060 3,
3061 {spdy_util_.GetPathKey(), "/index.php", "cookie", "val1", "cookie",
3062 "val2", NULL},
[email protected]e7f75092010-07-01 22:39:133063 },
bnc42331402016-07-25 13:36:153064 // Response headers missing version header
bnc7ecc1122015-09-28 13:22:493065 {
bnca9b9e222016-07-11 20:10:403066 1, {spdy_util_.GetPathKey(), "/index.php", "status", "200", NULL},
[email protected]e7f75092010-07-01 22:39:133067 },
bnc42331402016-07-25 13:36:153068 // Response headers with no headers
bnc7ecc1122015-09-28 13:22:493069 {
3070 0, {NULL},
3071 },
[email protected]dd11b932009-11-30 19:39:483072 };
3073
viettrungluue4a8b882014-10-16 06:17:383074 for (size_t i = 0; i < arraysize(test_cases); ++i) {
bncd16676a2016-07-20 16:23:013075 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:493076
bncdf80d44fd2016-07-15 20:27:413077 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493078 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413079 SpdySerializedFrame rst(
bnc38dcd392016-02-09 23:19:493080 spdy_test_util.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:483081 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:413082 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
[email protected]dd11b932009-11-30 19:39:483083 };
3084
[email protected]745aa9c2014-06-27 02:21:293085 // Construct the reply.
3086 SpdyHeaderBlock reply_headers;
3087 AppendToHeaderBlock(
3088 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
bncdf80d44fd2016-07-15 20:27:413089 SpdySerializedFrame resp(
bnc086b39e12016-06-24 13:05:263090 spdy_test_util.ConstructSpdyReply(1, std::move(reply_headers)));
[email protected]dd11b932009-11-30 19:39:483091 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413092 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]dd11b932009-11-30 19:39:483093 };
3094
rch08e3aa3e2015-05-16 14:27:523095 SequencedSocketData data(reads, arraysize(reads), writes,
3096 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363097 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013098 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:573099 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473100 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013101 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:483102 }
3103}
3104
bncd16676a2016-07-20 16:23:013105TEST_F(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
bncdf80d44fd2016-07-15 20:27:413106 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493107 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413108 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bncf5012992016-04-19 16:36:263109 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 6 (DECOMPRESS_FAILURE)."));
bncdf80d44fd2016-07-15 20:27:413110 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]e3352df2014-03-19 05:55:423111
bnc38dcd392016-02-09 23:19:493112 // This is the length field that's too short.
bnc42331402016-07-25 13:36:153113 SpdySerializedFrame reply_wrong_length(
3114 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
diannahu86e7a8ab2016-08-03 20:11:143115 size_t right_size =
3116 reply_wrong_length.size() - SpdyConstants::GetFrameHeaderSize(HTTP2);
bnc38dcd392016-02-09 23:19:493117 size_t wrong_size = right_size - 4;
bnc42331402016-07-25 13:36:153118 test::SetFrameLength(&reply_wrong_length, wrong_size, HTTP2);
bnc38dcd392016-02-09 23:19:493119
[email protected]e3352df2014-03-19 05:55:423120 MockRead reads[] = {
bnc42331402016-07-25 13:36:153121 MockRead(ASYNC, reply_wrong_length.data(), reply_wrong_length.size() - 4,
3122 1),
[email protected]e3352df2014-03-19 05:55:423123 };
3124
rch08e3aa3e2015-05-16 14:27:523125 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]e3352df2014-03-19 05:55:423126 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013127 BoundNetLog(), NULL);
[email protected]e3352df2014-03-19 05:55:423128 helper.RunToCompletion(&data);
3129 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013130 EXPECT_THAT(out.rv, IsError(ERR_SPDY_COMPRESSION_ERROR));
[email protected]bdd1b222014-06-10 11:08:393131}
3132
bncd16676a2016-07-20 16:23:013133TEST_F(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
bncdf80d44fd2016-07-15 20:27:413134 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493135 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413136 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bncf5012992016-04-19 16:36:263137 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 6 (DECOMPRESS_FAILURE)."));
bncdf80d44fd2016-07-15 20:27:413138 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393139
3140 // Read HEADERS with corrupted payload.
bnc42331402016-07-25 13:36:153141 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:413142 memset(resp.data() + 12, 0xcf, resp.size() - 12);
3143 MockRead reads[] = {CreateMockRead(resp, 1)};
[email protected]bdd1b222014-06-10 11:08:393144
rch08e3aa3e2015-05-16 14:27:523145 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:013146 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3147 BoundNetLog(), NULL);
[email protected]bdd1b222014-06-10 11:08:393148 helper.RunToCompletion(&data);
3149 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013150 EXPECT_THAT(out.rv, IsError(ERR_SPDY_COMPRESSION_ERROR));
[email protected]bdd1b222014-06-10 11:08:393151}
3152
bncd16676a2016-07-20 16:23:013153TEST_F(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
bncdf80d44fd2016-07-15 20:27:413154 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493155 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413156 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bnc20df67c2016-04-07 01:36:183157 0, GOAWAY_FRAME_SIZE_ERROR,
dahollingsaf3796492016-05-25 19:21:353158 "Framer error: 15 (INVALID_CONTROL_FRAME_SIZE)."));
bncdf80d44fd2016-07-15 20:27:413159 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393160
3161 // Read WINDOW_UPDATE with incorrectly-sized payload.
bncdf80d44fd2016-07-15 20:27:413162 SpdySerializedFrame bad_window_update(
[email protected]bdd1b222014-06-10 11:08:393163 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
bncdf80d44fd2016-07-15 20:27:413164 test::SetFrameLength(&bad_window_update, bad_window_update.size() - 1, HTTP2);
3165 MockRead reads[] = {CreateMockRead(bad_window_update, 1)};
[email protected]bdd1b222014-06-10 11:08:393166
rch08e3aa3e2015-05-16 14:27:523167 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:013168 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3169 BoundNetLog(), NULL);
[email protected]bdd1b222014-06-10 11:08:393170 helper.RunToCompletion(&data);
3171 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013172 EXPECT_THAT(out.rv, IsError(ERR_SPDY_FRAME_SIZE_ERROR));
[email protected]e3352df2014-03-19 05:55:423173}
3174
[email protected]bf2491a92009-11-29 16:39:483175// Test that we shutdown correctly on write errors.
bncd16676a2016-07-20 16:23:013176TEST_F(SpdyNetworkTransactionTest, WriteError) {
bncdf80d44fd2016-07-15 20:27:413177 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493178 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483179 MockWrite writes[] = {
[email protected]bdd1b222014-06-10 11:08:393180 // We'll write 10 bytes successfully
bncdf80d44fd2016-07-15 20:27:413181 MockWrite(ASYNC, req.data(), 10, 1),
[email protected]bdd1b222014-06-10 11:08:393182 // Followed by ERROR!
[email protected]bdd1b222014-06-10 11:08:393183 MockWrite(ASYNC, ERR_FAILED, 2),
mmenke666a6fea2015-12-19 04:16:333184 // Session drains and attempts to write a GOAWAY: Another ERROR!
3185 MockWrite(ASYNC, ERR_FAILED, 3),
[email protected]bf2491a92009-11-29 16:39:483186 };
3187
mmenke666a6fea2015-12-19 04:16:333188 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
[email protected]238002d2013-10-17 02:01:403189
mmenke666a6fea2015-12-19 04:16:333190 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]238002d2013-10-17 02:01:403191
[email protected]262eec82013-03-19 21:01:363192 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013193 BoundNetLog(), NULL);
[email protected]238002d2013-10-17 02:01:403194 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:333195 helper.AddData(&data);
[email protected]238002d2013-10-17 02:01:403196 EXPECT_TRUE(helper.StartDefaultTest());
[email protected]238002d2013-10-17 02:01:403197 helper.FinishDefaultTest();
rch37de576c2015-05-17 20:28:173198 EXPECT_TRUE(data.AllWriteDataConsumed());
mmenke666a6fea2015-12-19 04:16:333199 EXPECT_TRUE(data.AllReadDataConsumed());
[email protected]3caf5542010-07-16 15:19:473200 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013201 EXPECT_THAT(out.rv, IsError(ERR_FAILED));
[email protected]bf2491a92009-11-29 16:39:483202}
3203
3204// Test that partial writes work.
bncd16676a2016-07-20 16:23:013205TEST_F(SpdyNetworkTransactionTest, PartialWrite) {
bnc42331402016-07-25 13:36:153206 // Chop the HEADERS frame into 5 chunks.
bncdf80d44fd2016-07-15 20:27:413207 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493208 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483209 const int kChunks = 5;
bncdf80d44fd2016-07-15 20:27:413210 std::unique_ptr<MockWrite[]> writes(ChopWriteFrame(req, kChunks));
rch08e3aa3e2015-05-16 14:27:523211 for (int i = 0; i < kChunks; ++i) {
3212 writes[i].sequence_number = i;
3213 }
[email protected]bf2491a92009-11-29 16:39:483214
bnc42331402016-07-25 13:36:153215 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:413216 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:483217 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413218 CreateMockRead(resp, kChunks), CreateMockRead(body, kChunks + 1),
rch08e3aa3e2015-05-16 14:27:523219 MockRead(ASYNC, 0, kChunks + 2) // EOF
[email protected]bf2491a92009-11-29 16:39:483220 };
3221
rch08e3aa3e2015-05-16 14:27:523222 SequencedSocketData data(reads, arraysize(reads), writes.get(), kChunks);
[email protected]262eec82013-03-19 21:01:363223 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013224 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:573225 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473226 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013227 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023228 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bf2491a92009-11-29 16:39:483229 EXPECT_EQ("hello!", out.response_data);
3230}
3231
[email protected]9e743cd2010-03-16 07:03:533232// Test that the NetLog contains good data for a simple GET request.
bncd16676a2016-07-20 16:23:013233TEST_F(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:403234 static const char* const kExtraHeaders[] = {
3235 "user-agent", "Chrome",
3236 };
bncdf80d44fd2016-07-15 20:27:413237 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493238 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413239 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]dac358042009-12-18 02:07:483240
bnc42331402016-07-25 13:36:153241 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:413242 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]dac358042009-12-18 02:07:483243 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413244 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:523245 MockRead(ASYNC, 0, 3) // EOF
[email protected]dac358042009-12-18 02:07:483246 };
3247
vishal.b62985ca92015-04-17 08:45:513248 BoundTestNetLog log;
[email protected]dac358042009-12-18 02:07:483249
rch08e3aa3e2015-05-16 14:27:523250 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3deb9a52010-11-11 00:24:403251 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
bncd16676a2016-07-20 16:23:013252 DEFAULT_PRIORITY, log.bound(), NULL);
[email protected]dd54bd82012-07-19 23:44:573253 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473254 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013255 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023256 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]dac358042009-12-18 02:07:483257 EXPECT_EQ("hello!", out.response_data);
3258
[email protected]9e743cd2010-03-16 07:03:533259 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:473260 // This test is intentionally non-specific about the exact ordering of the
3261 // log; instead we just check to make sure that certain events exist, and that
3262 // they are in the right order.
mmenke43758e62015-05-04 21:09:463263 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403264 log.GetEntries(&entries);
3265
3266 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:483267 int pos = 0;
bnc301745a2015-03-10 03:22:163268 pos = ExpectLogContainsSomewhere(entries, 0,
3269 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3270 NetLog::PHASE_BEGIN);
3271 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3272 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3273 NetLog::PHASE_END);
3274 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3275 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3276 NetLog::PHASE_BEGIN);
3277 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3278 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3279 NetLog::PHASE_END);
3280 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3281 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3282 NetLog::PHASE_BEGIN);
3283 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3284 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3285 NetLog::PHASE_END);
[email protected]3deb9a52010-11-11 00:24:403286
3287 // Check that we logged all the headers correctly
bnca9b9e222016-07-11 20:10:403288 pos = ExpectLogContainsSomewhere(
3289 entries, 0, NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS, NetLog::PHASE_NONE);
[email protected]3deb9a52010-11-11 00:24:403290
[email protected]ea5ef4c2013-06-13 22:50:273291 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:573292 ASSERT_TRUE(entries[pos].params.get());
3293 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3294
3295 std::vector<std::string> expected;
bncce36dca22015-04-21 22:11:233296 expected.push_back(std::string(spdy_util_.GetHostKey()) +
3297 ": www.example.org");
[email protected]513963e2013-06-15 01:53:043298 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
rchebf12982015-04-10 01:15:003299 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": " +
bncb26024382016-06-29 02:39:453300 default_url_.scheme());
[email protected]513963e2013-06-15 01:53:043301 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
[email protected]f3da152d2012-06-02 01:00:573302 expected.push_back("user-agent: Chrome");
[email protected]f3da152d2012-06-02 01:00:573303 EXPECT_EQ(expected.size(), header_list->GetSize());
3304 for (std::vector<std::string>::const_iterator it = expected.begin();
3305 it != expected.end();
3306 ++it) {
3307 base::StringValue header(*it);
3308 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3309 "Header not found: " << *it;
[email protected]3deb9a52010-11-11 00:24:403310 }
[email protected]dac358042009-12-18 02:07:483311}
3312
[email protected]79d84222010-02-26 00:01:443313// Since we buffer the IO from the stream to the renderer, this test verifies
3314// that when we read out the maximum amount of data (e.g. we received 50 bytes
3315// on the network, but issued a Read for only 5 of those bytes) that the data
3316// flow still works correctly.
bncd16676a2016-07-20 16:23:013317TEST_F(SpdyNetworkTransactionTest, BufferFull) {
bncdf80d44fd2016-07-15 20:27:413318 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493319 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413320 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]79d84222010-02-26 00:01:443321
[email protected]20d005f2010-07-02 19:55:433322 // 2 data frames in a single read.
bncdf80d44fd2016-07-15 20:27:413323 SpdySerializedFrame data_frame_1(
3324 spdy_util_.ConstructSpdyDataFrame(1, "goodby", 6, /*fin=*/false));
3325 SpdySerializedFrame data_frame_2(
3326 spdy_util_.ConstructSpdyDataFrame(1, "e worl", 6, /*fin=*/false));
bncb03b1092016-04-06 11:19:553327 const SpdySerializedFrame* data_frames[2] = {
bncdf80d44fd2016-07-15 20:27:413328 &data_frame_1, &data_frame_2,
[email protected]79d84222010-02-26 00:01:443329 };
[email protected]20d005f2010-07-02 19:55:433330 char combined_data_frames[100];
3331 int combined_data_frames_len =
3332 CombineFrames(data_frames, arraysize(data_frames),
3333 combined_data_frames, arraysize(combined_data_frames));
bncdf80d44fd2016-07-15 20:27:413334 SpdySerializedFrame last_frame(
3335 spdy_util_.ConstructSpdyDataFrame(1, "d", 1, /*fin=*/true));
[email protected]79d84222010-02-26 00:01:443336
bnc42331402016-07-25 13:36:153337 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]79d84222010-02-26 00:01:443338 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413339 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:093340 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3341 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3342 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
bncdf80d44fd2016-07-15 20:27:413343 CreateMockRead(last_frame, 5),
rch32320842015-05-16 15:57:093344 MockRead(ASYNC, 0, 6) // EOF
[email protected]79d84222010-02-26 00:01:443345 };
3346
rch32320842015-05-16 15:57:093347 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]79d84222010-02-26 00:01:443348
[email protected]49639fa2011-12-20 23:22:413349 TestCompletionCallback callback;
[email protected]79d84222010-02-26 00:01:443350
[email protected]262eec82013-03-19 21:01:363351 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013352 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473353 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573354 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473355 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413356 int rv = trans->Start(
3357 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013358 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79d84222010-02-26 00:01:443359
[email protected]3caf5542010-07-16 15:19:473360 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:443361 out.rv = callback.WaitForResult();
3362 EXPECT_EQ(out.rv, OK);
3363
3364 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523365 EXPECT_TRUE(response->headers);
[email protected]79d84222010-02-26 00:01:443366 EXPECT_TRUE(response->was_fetched_via_spdy);
3367 out.status_line = response->headers->GetStatusLine();
3368 out.response_info = *response; // Make a copy so we can verify.
3369
3370 // Read Data
[email protected]49639fa2011-12-20 23:22:413371 TestCompletionCallback read_callback;
[email protected]79d84222010-02-26 00:01:443372
3373 std::string content;
3374 do {
3375 // Read small chunks at a time.
3376 const int kSmallReadSize = 3;
bnc301745a2015-03-10 03:22:163377 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503378 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163379 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593380 data.Resume();
[email protected]79d84222010-02-26 00:01:443381 rv = read_callback.WaitForResult();
3382 }
3383 if (rv > 0) {
3384 content.append(buf->data(), rv);
3385 } else if (rv < 0) {
3386 NOTREACHED();
3387 }
3388 } while (rv > 0);
3389
3390 out.response_data.swap(content);
3391
[email protected]30c942b2010-07-21 16:59:593392 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553393 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173394 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553395
[email protected]79d84222010-02-26 00:01:443396 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473397 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:443398
robpercival214763f2016-07-01 23:27:013399 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023400 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]79d84222010-02-26 00:01:443401 EXPECT_EQ("goodbye world", out.response_data);
3402}
3403
[email protected]8918d282010-03-02 00:57:553404// Verify that basic buffering works; when multiple data frames arrive
3405// at the same time, ensure that we don't notify a read completion for
3406// each data frame individually.
bncd16676a2016-07-20 16:23:013407TEST_F(SpdyNetworkTransactionTest, Buffering) {
bncdf80d44fd2016-07-15 20:27:413408 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493409 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413410 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:553411
3412 // 4 data frames in a single read.
bncdf80d44fd2016-07-15 20:27:413413 SpdySerializedFrame data_frame(
3414 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
3415 SpdySerializedFrame data_frame_fin(
3416 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/true));
3417 const SpdySerializedFrame* data_frames[4] = {&data_frame, &data_frame,
3418 &data_frame, &data_frame_fin};
[email protected]20d005f2010-07-02 19:55:433419 char combined_data_frames[100];
3420 int combined_data_frames_len =
3421 CombineFrames(data_frames, arraysize(data_frames),
3422 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:553423
bnc42331402016-07-25 13:36:153424 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553425 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413426 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:093427 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3428 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3429 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553430 };
3431
rch32320842015-05-16 15:57:093432 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553433
[email protected]262eec82013-03-19 21:01:363434 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013435 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473436 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573437 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473438 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553439
[email protected]49639fa2011-12-20 23:22:413440 TestCompletionCallback callback;
3441 int rv = trans->Start(
3442 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013443 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:553444
[email protected]3caf5542010-07-16 15:19:473445 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553446 out.rv = callback.WaitForResult();
3447 EXPECT_EQ(out.rv, OK);
3448
3449 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523450 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:553451 EXPECT_TRUE(response->was_fetched_via_spdy);
3452 out.status_line = response->headers->GetStatusLine();
3453 out.response_info = *response; // Make a copy so we can verify.
3454
3455 // Read Data
[email protected]49639fa2011-12-20 23:22:413456 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553457
3458 std::string content;
3459 int reads_completed = 0;
3460 do {
3461 // Read small chunks at a time.
3462 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163463 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503464 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163465 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593466 data.Resume();
[email protected]8918d282010-03-02 00:57:553467 rv = read_callback.WaitForResult();
3468 }
3469 if (rv > 0) {
3470 EXPECT_EQ(kSmallReadSize, rv);
3471 content.append(buf->data(), rv);
3472 } else if (rv < 0) {
3473 FAIL() << "Unexpected read error: " << rv;
3474 }
3475 reads_completed++;
3476 } while (rv > 0);
3477
3478 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3479
3480 out.response_data.swap(content);
3481
[email protected]30c942b2010-07-21 16:59:593482 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553483 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173484 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553485
3486 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473487 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553488
robpercival214763f2016-07-01 23:27:013489 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023490 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:553491 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3492}
3493
3494// Verify the case where we buffer data but read it after it has been buffered.
bncd16676a2016-07-20 16:23:013495TEST_F(SpdyNetworkTransactionTest, BufferedAll) {
bncdf80d44fd2016-07-15 20:27:413496 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493497 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413498 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:553499
[email protected]20d005f2010-07-02 19:55:433500 // 5 data frames in a single read.
bnc42331402016-07-25 13:36:153501 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:413502 SpdySerializedFrame data_frame(
3503 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
3504 SpdySerializedFrame data_frame_fin(
3505 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/true));
3506 const SpdySerializedFrame* frames[5] = {&reply, &data_frame, &data_frame,
3507 &data_frame, &data_frame_fin};
[email protected]20d005f2010-07-02 19:55:433508 char combined_frames[200];
3509 int combined_frames_len =
3510 CombineFrames(frames, arraysize(frames),
3511 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:553512
3513 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523514 MockRead(ASYNC, combined_frames, combined_frames_len, 1),
3515 MockRead(ASYNC, 0, 2) // EOF
[email protected]8918d282010-03-02 00:57:553516 };
3517
rch08e3aa3e2015-05-16 14:27:523518 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553519
[email protected]262eec82013-03-19 21:01:363520 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013521 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473522 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573523 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473524 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553525
[email protected]49639fa2011-12-20 23:22:413526 TestCompletionCallback callback;
3527 int rv = trans->Start(
3528 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013529 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:553530
[email protected]3caf5542010-07-16 15:19:473531 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553532 out.rv = callback.WaitForResult();
3533 EXPECT_EQ(out.rv, OK);
3534
3535 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523536 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:553537 EXPECT_TRUE(response->was_fetched_via_spdy);
3538 out.status_line = response->headers->GetStatusLine();
3539 out.response_info = *response; // Make a copy so we can verify.
3540
3541 // Read Data
[email protected]49639fa2011-12-20 23:22:413542 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553543
3544 std::string content;
3545 int reads_completed = 0;
3546 do {
3547 // Read small chunks at a time.
3548 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163549 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503550 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:553551 if (rv > 0) {
3552 EXPECT_EQ(kSmallReadSize, rv);
3553 content.append(buf->data(), rv);
3554 } else if (rv < 0) {
3555 FAIL() << "Unexpected read error: " << rv;
3556 }
3557 reads_completed++;
3558 } while (rv > 0);
3559
3560 EXPECT_EQ(3, reads_completed);
3561
3562 out.response_data.swap(content);
3563
[email protected]30c942b2010-07-21 16:59:593564 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553565 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173566 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553567
3568 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473569 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553570
robpercival214763f2016-07-01 23:27:013571 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023572 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:553573 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3574}
3575
3576// Verify the case where we buffer data and close the connection.
bncd16676a2016-07-20 16:23:013577TEST_F(SpdyNetworkTransactionTest, BufferedClosed) {
bncdf80d44fd2016-07-15 20:27:413578 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493579 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413580 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:553581
3582 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:433583 // NOTE: We don't FIN the stream.
bncdf80d44fd2016-07-15 20:27:413584 SpdySerializedFrame data_frame(
3585 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
3586 const SpdySerializedFrame* data_frames[4] = {&data_frame, &data_frame,
3587 &data_frame, &data_frame};
[email protected]20d005f2010-07-02 19:55:433588 char combined_data_frames[100];
3589 int combined_data_frames_len =
3590 CombineFrames(data_frames, arraysize(data_frames),
3591 combined_data_frames, arraysize(combined_data_frames));
bnc42331402016-07-25 13:36:153592 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553593 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413594 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:093595 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3596 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3597 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553598 };
3599
rch32320842015-05-16 15:57:093600 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553601
[email protected]262eec82013-03-19 21:01:363602 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013603 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473604 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573605 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473606 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553607
[email protected]49639fa2011-12-20 23:22:413608 TestCompletionCallback callback;
[email protected]8918d282010-03-02 00:57:553609
[email protected]49639fa2011-12-20 23:22:413610 int rv = trans->Start(
3611 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013612 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:553613
[email protected]3caf5542010-07-16 15:19:473614 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553615 out.rv = callback.WaitForResult();
3616 EXPECT_EQ(out.rv, OK);
3617
3618 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523619 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:553620 EXPECT_TRUE(response->was_fetched_via_spdy);
3621 out.status_line = response->headers->GetStatusLine();
3622 out.response_info = *response; // Make a copy so we can verify.
3623
3624 // Read Data
[email protected]49639fa2011-12-20 23:22:413625 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553626
3627 std::string content;
3628 int reads_completed = 0;
3629 do {
3630 // Read small chunks at a time.
3631 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163632 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503633 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163634 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593635 data.Resume();
[email protected]8918d282010-03-02 00:57:553636 rv = read_callback.WaitForResult();
3637 }
3638 if (rv > 0) {
3639 content.append(buf->data(), rv);
3640 } else if (rv < 0) {
3641 // This test intentionally closes the connection, and will get an error.
robpercival214763f2016-07-01 23:27:013642 EXPECT_THAT(rv, IsError(ERR_CONNECTION_CLOSED));
[email protected]8918d282010-03-02 00:57:553643 break;
3644 }
3645 reads_completed++;
3646 } while (rv > 0);
3647
3648 EXPECT_EQ(0, reads_completed);
3649
3650 out.response_data.swap(content);
3651
[email protected]30c942b2010-07-21 16:59:593652 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553653 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173654 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553655
3656 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473657 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553658}
3659
[email protected]1ed7b3dc2010-03-04 05:41:453660// Verify the case where we buffer data and cancel the transaction.
bncd16676a2016-07-20 16:23:013661TEST_F(SpdyNetworkTransactionTest, BufferedCancelled) {
bncdf80d44fd2016-07-15 20:27:413662 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493663 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413664 SpdySerializedFrame rst(
[email protected]975da41a2014-06-05 03:36:243665 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
bncdf80d44fd2016-07-15 20:27:413666 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 4)};
[email protected]1ed7b3dc2010-03-04 05:41:453667
[email protected]20d005f2010-07-02 19:55:433668 // NOTE: We don't FIN the stream.
bncdf80d44fd2016-07-15 20:27:413669 SpdySerializedFrame data_frame(
3670 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
[email protected]1ed7b3dc2010-03-04 05:41:453671
bnc42331402016-07-25 13:36:153672 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:453673 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413674 CreateMockRead(resp, 1),
3675 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3676 CreateMockRead(data_frame, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]1ed7b3dc2010-03-04 05:41:453677 };
3678
rch32320842015-05-16 15:57:093679 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1ed7b3dc2010-03-04 05:41:453680
[email protected]262eec82013-03-19 21:01:363681 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013682 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473683 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573684 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473685 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413686 TestCompletionCallback callback;
[email protected]1ed7b3dc2010-03-04 05:41:453687
[email protected]49639fa2011-12-20 23:22:413688 int rv = trans->Start(
3689 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013690 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1ed7b3dc2010-03-04 05:41:453691
[email protected]3caf5542010-07-16 15:19:473692 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:453693 out.rv = callback.WaitForResult();
3694 EXPECT_EQ(out.rv, OK);
3695
3696 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523697 EXPECT_TRUE(response->headers);
[email protected]1ed7b3dc2010-03-04 05:41:453698 EXPECT_TRUE(response->was_fetched_via_spdy);
3699 out.status_line = response->headers->GetStatusLine();
3700 out.response_info = *response; // Make a copy so we can verify.
3701
3702 // Read Data
[email protected]49639fa2011-12-20 23:22:413703 TestCompletionCallback read_callback;
[email protected]1ed7b3dc2010-03-04 05:41:453704
[email protected]88c7b4be2014-03-19 23:04:013705 const int kReadSize = 256;
bnc301745a2015-03-10 03:22:163706 scoped_refptr<IOBuffer> buf(new IOBuffer(kReadSize));
[email protected]88c7b4be2014-03-19 23:04:013707 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163708 ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
[email protected]88c7b4be2014-03-19 23:04:013709
3710 // Complete the read now, which causes buffering to start.
mmenkee24011922015-12-17 22:12:593711 data.Resume();
3712 base::RunLoop().RunUntilIdle();
[email protected]88c7b4be2014-03-19 23:04:013713 // Destroy the transaction, causing the stream to get cancelled
3714 // and orphaning the buffered IO task.
3715 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:453716
3717 // Flush the MessageLoop; this will cause the buffered IO task
3718 // to run for the final time.
[email protected]fc9d88472013-08-14 02:31:173719 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:473720
3721 // Verify that we consumed all test data.
3722 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:453723}
3724
bncd16676a2016-07-20 16:23:013725TEST_F(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
bncdf80d44fd2016-07-15 20:27:413726 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493727 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413728 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]69d717bd2010-04-21 18:43:213729
bncdf80d44fd2016-07-15 20:27:413730 SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:213731 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413732 CreateMockRead(go_away, 1),
[email protected]58cebf8f2010-07-31 19:20:163733 };
3734
rch08e3aa3e2015-05-16 14:27:523735 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363736 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013737 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:573738 helper.AddData(&data);
3739 helper.RunToCompletion(&data);
[email protected]58cebf8f2010-07-31 19:20:163740 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013741 EXPECT_THAT(out.rv, IsError(ERR_ABORTED));
[email protected]69d717bd2010-04-21 18:43:213742}
3743
bncd16676a2016-07-20 16:23:013744TEST_F(SpdyNetworkTransactionTest, CloseWithActiveStream) {
bncdf80d44fd2016-07-15 20:27:413745 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493746 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413747 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]f5ed21552010-05-04 18:39:543748
bnc42331402016-07-25 13:36:153749 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]f5ed21552010-05-04 18:39:543750 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413751 CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
[email protected]f5ed21552010-05-04 18:39:543752 };
3753
rch08e3aa3e2015-05-16 14:27:523754 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]f5ed21552010-05-04 18:39:543755 BoundNetLog log;
bncd16676a2016-07-20 16:23:013756 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, log,
3757 NULL);
[email protected]3caf5542010-07-16 15:19:473758 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573759 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473760 HttpNetworkTransaction* trans = helper.trans();
[email protected]f5ed21552010-05-04 18:39:543761
[email protected]49639fa2011-12-20 23:22:413762 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:473763 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:413764 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
[email protected]3caf5542010-07-16 15:19:473765
[email protected]f5ed21552010-05-04 18:39:543766 EXPECT_EQ(out.rv, ERR_IO_PENDING);
3767 out.rv = callback.WaitForResult();
bncaa171332016-07-20 14:47:363768 EXPECT_EQ(out.rv, ERR_CONNECTION_CLOSED);
[email protected]f5ed21552010-05-04 18:39:543769
3770 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523771 EXPECT_TRUE(response->headers);
[email protected]f5ed21552010-05-04 18:39:543772 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]3caf5542010-07-16 15:19:473773 out.rv = ReadTransaction(trans, &out.response_data);
robpercival214763f2016-07-01 23:27:013774 EXPECT_THAT(out.rv, IsError(ERR_CONNECTION_CLOSED));
[email protected]f5ed21552010-05-04 18:39:543775
3776 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473777 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:543778}
[email protected]58cebf8f2010-07-31 19:20:163779
bncfacdd852015-01-09 19:22:543780// Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
3781// protocol negotiation happens, instead this test forces protocols for both
3782// sockets.
bncd16676a2016-07-20 16:23:013783TEST_F(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
bncfacdd852015-01-09 19:22:543784 HttpRequestInfo request;
3785 request.method = "GET";
bncb26024382016-06-29 02:39:453786 request.url = default_url_;
bncfacdd852015-01-09 19:22:543787 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:543788 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:013789 nullptr);
bncfacdd852015-01-09 19:22:543790
3791 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
bncb26024382016-06-29 02:39:453792 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bncdf80d44fd2016-07-15 20:27:413793 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:153794 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413795 MockWrite writes0[] = {CreateMockWrite(req, 0)};
3796 SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway(
bncfacdd852015-01-09 19:22:543797 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
bncdf80d44fd2016-07-15 20:27:413798 MockRead reads0[] = {CreateMockRead(go_away, 1)};
rch08e3aa3e2015-05-16 14:27:523799 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
3800 arraysize(writes0));
bncfacdd852015-01-09 19:22:543801
danakjaee3e1ec2016-04-16 00:23:183802 std::unique_ptr<SSLSocketDataProvider> ssl_provider0(
bncfacdd852015-01-09 19:22:543803 new SSLSocketDataProvider(ASYNC, OK));
3804 // Expect HTTP/2 protocols too in SSLConfig.
bnc06d22432015-06-29 12:39:433805 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
bnc3f0118e2016-02-02 15:42:223806 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
bncfacdd852015-01-09 19:22:543807 // Force SPDY.
bnc3cf2a592016-08-11 14:48:363808 ssl_provider0->next_proto = kProtoHTTP2;
dchengc7eeda422015-12-26 03:56:483809 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
bncfacdd852015-01-09 19:22:543810
3811 // Second socket: falling back to HTTP/1.1.
rch08e3aa3e2015-05-16 14:27:523812 MockWrite writes1[] = {MockWrite(ASYNC, 0,
3813 "GET / HTTP/1.1\r\n"
3814 "Host: www.example.org\r\n"
3815 "Connection: keep-alive\r\n\r\n")};
3816 MockRead reads1[] = {MockRead(ASYNC, 1,
3817 "HTTP/1.1 200 OK\r\n"
3818 "Content-Length: 5\r\n\r\n"
3819 "hello")};
3820 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
3821 arraysize(writes1));
bncfacdd852015-01-09 19:22:543822
danakjaee3e1ec2016-04-16 00:23:183823 std::unique_ptr<SSLSocketDataProvider> ssl_provider1(
bncfacdd852015-01-09 19:22:543824 new SSLSocketDataProvider(ASYNC, OK));
3825 // Expect only HTTP/1.1 protocol in SSLConfig.
3826 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
3827 // Force HTTP/1.1.
bnc3cf2a592016-08-11 14:48:363828 ssl_provider1->next_proto = kProtoHTTP11;
dchengc7eeda422015-12-26 03:56:483829 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
bncfacdd852015-01-09 19:22:543830
bnc525e175a2016-06-20 12:36:403831 HttpServerProperties* http_server_properties =
bncfacdd852015-01-09 19:22:543832 helper.session()->spdy_session_pool()->http_server_properties();
bncb26024382016-06-29 02:39:453833 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair_));
bncfacdd852015-01-09 19:22:543834
3835 helper.RunPreTestSetup();
3836 helper.StartDefaultTest();
3837 helper.FinishDefaultTestWithoutVerification();
3838 helper.VerifyDataConsumed();
bncb26024382016-06-29 02:39:453839 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair_));
bncfacdd852015-01-09 19:22:543840
3841 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:523842 ASSERT_TRUE(response);
3843 ASSERT_TRUE(response->headers);
bncfacdd852015-01-09 19:22:543844 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3845 EXPECT_FALSE(response->was_fetched_via_spdy);
mmenke8210acc2016-07-11 16:34:523846 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
3847 response->connection_info);
bncfacdd852015-01-09 19:22:543848 EXPECT_TRUE(response->was_npn_negotiated);
3849 EXPECT_TRUE(request.url.SchemeIs("https"));
3850 EXPECT_EQ("127.0.0.1", response->socket_address.host());
3851 EXPECT_EQ(443, response->socket_address.port());
3852 std::string response_data;
robpercival214763f2016-07-01 23:27:013853 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
bncfacdd852015-01-09 19:22:543854 EXPECT_EQ("hello", response_data);
3855}
3856
3857// Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
3858// proxy. Note that no actual protocol negotiation happens, instead this test
3859// forces protocols for both sockets.
bncd16676a2016-07-20 16:23:013860TEST_F(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
bncfacdd852015-01-09 19:22:543861 HttpRequestInfo request;
3862 request.method = "GET";
bncb26024382016-06-29 02:39:453863 request.url = default_url_;
bncd16676a2016-07-20 16:23:013864 auto session_deps = base::MakeUnique<SpdySessionDependencies>(
3865 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
bncfacdd852015-01-09 19:22:543866 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:543867 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:013868 std::move(session_deps));
bncfacdd852015-01-09 19:22:543869
3870 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
bncdf80d44fd2016-07-15 20:27:413871 SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:233872 nullptr, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
bncdf80d44fd2016-07-15 20:27:413873 MockWrite writes0[] = {CreateMockWrite(req, 0)};
3874 SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway(
bncfacdd852015-01-09 19:22:543875 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
bncdf80d44fd2016-07-15 20:27:413876 MockRead reads0[] = {CreateMockRead(go_away, 1)};
rch08e3aa3e2015-05-16 14:27:523877 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
3878 arraysize(writes0));
bncfacdd852015-01-09 19:22:543879
danakjaee3e1ec2016-04-16 00:23:183880 std::unique_ptr<SSLSocketDataProvider> ssl_provider0(
bncfacdd852015-01-09 19:22:543881 new SSLSocketDataProvider(ASYNC, OK));
3882 // Expect HTTP/2 protocols too in SSLConfig.
bnc06d22432015-06-29 12:39:433883 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
bnc3f0118e2016-02-02 15:42:223884 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
bncfacdd852015-01-09 19:22:543885 // Force SPDY.
bnc3cf2a592016-08-11 14:48:363886 ssl_provider0->next_proto = kProtoHTTP2;
dchengc7eeda422015-12-26 03:56:483887 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
bncfacdd852015-01-09 19:22:543888
3889 // Second socket: retry using HTTP/1.1.
3890 MockWrite writes1[] = {
rch08e3aa3e2015-05-16 14:27:523891 MockWrite(ASYNC, 0,
bncce36dca22015-04-21 22:11:233892 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173893 "Host: www.example.org:443\r\n"
bncfacdd852015-01-09 19:22:543894 "Proxy-Connection: keep-alive\r\n\r\n"),
rch08e3aa3e2015-05-16 14:27:523895 MockWrite(ASYNC, 2,
bncfacdd852015-01-09 19:22:543896 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:233897 "Host: www.example.org\r\n"
bncfacdd852015-01-09 19:22:543898 "Connection: keep-alive\r\n\r\n"),
3899 };
3900
3901 MockRead reads1[] = {
rch08e3aa3e2015-05-16 14:27:523902 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
3903 MockRead(ASYNC, 3,
bncfacdd852015-01-09 19:22:543904 "HTTP/1.1 200 OK\r\n"
3905 "Content-Length: 5\r\n\r\n"
3906 "hello"),
3907 };
rch08e3aa3e2015-05-16 14:27:523908 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
3909 arraysize(writes1));
bncfacdd852015-01-09 19:22:543910
danakjaee3e1ec2016-04-16 00:23:183911 std::unique_ptr<SSLSocketDataProvider> ssl_provider1(
bncfacdd852015-01-09 19:22:543912 new SSLSocketDataProvider(ASYNC, OK));
3913 // Expect only HTTP/1.1 protocol in SSLConfig.
3914 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
3915 // Force HTTP/1.1.
bnc3cf2a592016-08-11 14:48:363916 ssl_provider1->next_proto = kProtoHTTP11;
dchengc7eeda422015-12-26 03:56:483917 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
bncfacdd852015-01-09 19:22:543918
3919 // A third socket is needed for the tunnelled connection.
danakjaee3e1ec2016-04-16 00:23:183920 std::unique_ptr<SSLSocketDataProvider> ssl_provider2(
bncfacdd852015-01-09 19:22:543921 new SSLSocketDataProvider(ASYNC, OK));
3922 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
3923 ssl_provider2.get());
3924
bnc525e175a2016-06-20 12:36:403925 HttpServerProperties* http_server_properties =
bncfacdd852015-01-09 19:22:543926 helper.session()->spdy_session_pool()->http_server_properties();
3927 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
3928 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
3929
3930 helper.RunPreTestSetup();
3931 helper.StartDefaultTest();
3932 helper.FinishDefaultTestWithoutVerification();
3933 helper.VerifyDataConsumed();
3934 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
3935
3936 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:523937 ASSERT_TRUE(response);
3938 ASSERT_TRUE(response->headers);
bncfacdd852015-01-09 19:22:543939 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3940 EXPECT_FALSE(response->was_fetched_via_spdy);
mmenke8210acc2016-07-11 16:34:523941 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
3942 response->connection_info);
bncfacdd852015-01-09 19:22:543943 EXPECT_FALSE(response->was_npn_negotiated);
3944 EXPECT_TRUE(request.url.SchemeIs("https"));
3945 EXPECT_EQ("127.0.0.1", response->socket_address.host());
3946 EXPECT_EQ(70, response->socket_address.port());
3947 std::string response_data;
robpercival214763f2016-07-01 23:27:013948 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
bncfacdd852015-01-09 19:22:543949 EXPECT_EQ("hello", response_data);
3950}
3951
[email protected]b261d0e2010-08-02 19:13:243952// Test to make sure we can correctly connect through a proxy.
bncd16676a2016-07-20 16:23:013953TEST_F(SpdyNetworkTransactionTest, ProxyConnect) {
3954 auto session_deps = base::MakeUnique<SpdySessionDependencies>(
3955 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
[email protected]262eec82013-03-19 21:01:363956 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013957 BoundNetLog(), std::move(session_deps));
[email protected]b261d0e2010-08-02 19:13:243958 helper.RunPreTestSetup();
3959 HttpNetworkTransaction* trans = helper.trans();
3960
rchebf12982015-04-10 01:15:003961 const char kConnect443[] = {
bncce36dca22015-04-21 22:11:233962 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173963 "Host: www.example.org:443\r\n"
rchcb934f562015-04-07 16:25:123964 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:243965 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
bncdf80d44fd2016-07-15 20:27:413966 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493967 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:153968 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:413969 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:243970
rchebf12982015-04-10 01:15:003971 MockWrite writes[] = {
3972 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
bncdf80d44fd2016-07-15 20:27:413973 CreateMockWrite(req, 2),
[email protected]b261d0e2010-08-02 19:13:243974 };
rchebf12982015-04-10 01:15:003975 MockRead reads[] = {
3976 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
bncdf80d44fd2016-07-15 20:27:413977 CreateMockRead(resp, 3), CreateMockRead(body, 4),
rchebf12982015-04-10 01:15:003978 MockRead(ASYNC, 0, 0, 5),
[email protected]b261d0e2010-08-02 19:13:243979 };
danakjaee3e1ec2016-04-16 00:23:183980 std::unique_ptr<SequencedSocketData> data(new SequencedSocketData(
rchebf12982015-04-10 01:15:003981 reads, arraysize(reads), writes, arraysize(writes)));
[email protected]b261d0e2010-08-02 19:13:243982
3983 helper.AddData(data.get());
[email protected]49639fa2011-12-20 23:22:413984 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:243985
[email protected]49639fa2011-12-20 23:22:413986 int rv = trans->Start(
3987 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013988 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b261d0e2010-08-02 19:13:243989
3990 rv = callback.WaitForResult();
3991 EXPECT_EQ(0, rv);
3992
bnc42331402016-07-25 13:36:153993 // Verify the response headers.
[email protected]b261d0e2010-08-02 19:13:243994 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523995 ASSERT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:023996 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:243997
3998 std::string response_data;
robpercival214763f2016-07-01 23:27:013999 ASSERT_THAT(ReadTransaction(trans, &response_data), IsOk());
[email protected]b261d0e2010-08-02 19:13:244000 EXPECT_EQ("hello!", response_data);
4001 helper.VerifyDataConsumed();
4002}
4003
bncce36dca22015-04-21 22:11:234004// Test to make sure we can correctly connect through a proxy to
4005// www.example.org, if there already exists a direct spdy connection to
4006// www.example.org. See https://crbug.com/49874.
bncd16676a2016-07-20 16:23:014007TEST_F(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
[email protected]733b7a6d2010-08-25 01:38:434008 // Use a proxy service which returns a proxy fallback list from DIRECT to
4009 // myproxy:70. For this test there will be no fallback, so it is equivalent
4010 // to simply DIRECT. The reason for appending the second proxy is to verify
4011 // that the session pool key used does is just "DIRECT".
bncd16676a2016-07-20 16:23:014012 auto session_deps = base::MakeUnique<SpdySessionDependencies>(
rdsmith82957ad2015-09-16 19:42:034013 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70"));
bncd16676a2016-07-20 16:23:014014 // When setting up the first transaction, we store the SpdySessionPool so that
4015 // we can use the same pool in the second transaction.
4016 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4017 BoundNetLog(), std::move(session_deps));
[email protected]733b7a6d2010-08-25 01:38:434018
[email protected]87bfa3f2010-09-30 14:54:564019 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:244020 helper.RunPreTestSetup();
4021
4022 // Construct and send a simple GET request.
bncdf80d44fd2016-07-15 20:27:414023 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494024 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]b261d0e2010-08-02 19:13:244025 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414026 CreateMockWrite(req, 0),
[email protected]b261d0e2010-08-02 19:13:244027 };
4028
bnc42331402016-07-25 13:36:154029 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414030 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244031 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414032 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:524033 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3), // Force a pause
[email protected]b261d0e2010-08-02 19:13:244034 };
rch08e3aa3e2015-05-16 14:27:524035 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574036 helper.AddData(&data);
[email protected]b261d0e2010-08-02 19:13:244037 HttpNetworkTransaction* trans = helper.trans();
4038
[email protected]49639fa2011-12-20 23:22:414039 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244040 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414041 out.rv = trans->Start(
4042 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244043
4044 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4045 out.rv = callback.WaitForResult();
4046 EXPECT_EQ(out.rv, OK);
4047
4048 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524049 EXPECT_TRUE(response->headers);
[email protected]b261d0e2010-08-02 19:13:244050 EXPECT_TRUE(response->was_fetched_via_spdy);
4051 out.rv = ReadTransaction(trans, &out.response_data);
robpercival214763f2016-07-01 23:27:014052 EXPECT_THAT(out.rv, IsOk());
[email protected]b261d0e2010-08-02 19:13:244053 out.status_line = response->headers->GetStatusLine();
bnc84e7fb52015-12-02 11:50:024054 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b261d0e2010-08-02 19:13:244055 EXPECT_EQ("hello!", out.response_data);
4056
4057 // Check that the SpdySession is still in the SpdySessionPool.
bncb26024382016-06-29 02:39:454058 SpdySessionKey session_pool_key_direct(host_port_pair_, ProxyServer::Direct(),
4059 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264060 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
[email protected]e6d017652013-05-17 18:01:404061 SpdySessionKey session_pool_key_proxy(
bncb26024382016-06-29 02:39:454062 host_port_pair_,
[email protected]e6d017652013-05-17 18:01:404063 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
[email protected]314b03992014-04-01 01:28:534064 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264065 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:244066
rdsmithebb50aa2015-11-12 03:44:384067 // New SpdyTestUtil instance for the session that will be used for the
4068 // proxy connection.
bncd16676a2016-07-20 16:23:014069 SpdyTestUtil spdy_util_2;
rdsmithebb50aa2015-11-12 03:44:384070
[email protected]b261d0e2010-08-02 19:13:244071 // Set up data for the proxy connection.
bncce36dca22015-04-21 22:11:234072 const char kConnect443[] = {
4073 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174074 "Host: www.example.org:443\r\n"
bncce36dca22015-04-21 22:11:234075 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244076 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
bncdf80d44fd2016-07-15 20:27:414077 SpdySerializedFrame req2(spdy_util_2.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:494078 GetDefaultUrlWithPath("/foo.dat").c_str(), 1, LOWEST));
bnc42331402016-07-25 13:36:154079 SpdySerializedFrame resp2(spdy_util_2.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414080 SpdySerializedFrame body2(spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244081
rchebf12982015-04-10 01:15:004082 MockWrite writes2[] = {
4083 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
bncdf80d44fd2016-07-15 20:27:414084 CreateMockWrite(req2, 2),
[email protected]b261d0e2010-08-02 19:13:244085 };
rchebf12982015-04-10 01:15:004086 MockRead reads2[] = {
4087 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
bncdf80d44fd2016-07-15 20:27:414088 CreateMockRead(resp2, 3), CreateMockRead(body2, 4),
rchebf12982015-04-10 01:15:004089 MockRead(ASYNC, 0, 5) // EOF
[email protected]b261d0e2010-08-02 19:13:244090 };
4091
danakjaee3e1ec2016-04-16 00:23:184092 std::unique_ptr<SequencedSocketData> data_proxy(new SequencedSocketData(
rchebf12982015-04-10 01:15:004093 reads2, arraysize(reads2), writes2, arraysize(writes2)));
[email protected]b261d0e2010-08-02 19:13:244094
bncce36dca22015-04-21 22:11:234095 // Create another request to www.example.org, but this time through a proxy.
[email protected]b261d0e2010-08-02 19:13:244096 HttpRequestInfo request_proxy;
4097 request_proxy.method = "GET";
rchebf12982015-04-10 01:15:004098 request_proxy.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
[email protected]b261d0e2010-08-02 19:13:244099 request_proxy.load_flags = 0;
bncd16676a2016-07-20 16:23:014100 auto session_deps_proxy = base::MakeUnique<SpdySessionDependencies>(
bnc301745a2015-03-10 03:22:164101 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
bncd16676a2016-07-20 16:23:014102 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
4103 BoundNetLog(),
4104 std::move(session_deps_proxy));
[email protected]b261d0e2010-08-02 19:13:244105 helper_proxy.RunPreTestSetup();
4106 helper_proxy.AddData(data_proxy.get());
4107
4108 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
[email protected]49639fa2011-12-20 23:22:414109 TestCompletionCallback callback_proxy;
4110 int rv = trans_proxy->Start(
4111 &request_proxy, callback_proxy.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014112 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b261d0e2010-08-02 19:13:244113 rv = callback_proxy.WaitForResult();
4114 EXPECT_EQ(0, rv);
4115
4116 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
wezca1070932016-05-26 20:30:524117 ASSERT_TRUE(response_proxy.headers);
bnc84e7fb52015-12-02 11:50:024118 EXPECT_EQ("HTTP/1.1 200", response_proxy.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:244119
4120 std::string response_data;
robpercival214763f2016-07-01 23:27:014121 ASSERT_THAT(ReadTransaction(trans_proxy, &response_data), IsOk());
[email protected]b261d0e2010-08-02 19:13:244122 EXPECT_EQ("hello!", response_data);
4123
[email protected]b261d0e2010-08-02 19:13:244124 helper_proxy.VerifyDataConsumed();
4125}
4126
[email protected]58cebf8f2010-07-31 19:20:164127// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4128// on a new connection, if the connection was previously known to be good.
4129// This can happen when a server reboots without saying goodbye, or when
4130// we're behind a NAT that masked the RST.
bncd16676a2016-07-20 16:23:014131TEST_F(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
bnc42331402016-07-25 13:36:154132 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414133 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]58cebf8f2010-07-31 19:20:164134 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414135 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch32320842015-05-16 15:57:094136 MockRead(ASYNC, ERR_IO_PENDING, 3),
4137 MockRead(ASYNC, ERR_CONNECTION_RESET, 4),
[email protected]58cebf8f2010-07-31 19:20:164138 };
4139
4140 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:414141 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch32320842015-05-16 15:57:094142 MockRead(ASYNC, 0, 3) // EOF
[email protected]58cebf8f2010-07-31 19:20:164143 };
4144
bncdf80d44fd2016-07-15 20:27:414145 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494146 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:384147 // In all cases the connection will be reset before req3 can be
4148 // dispatched, destroying both streams.
4149 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:414150 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:494151 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414152 MockWrite writes1[] = {CreateMockWrite(req, 0), CreateMockWrite(req3, 5)};
4153 MockWrite writes2[] = {CreateMockWrite(req, 0)};
rchacdcbdc2015-05-16 17:16:004154
[email protected]58cebf8f2010-07-31 19:20:164155 // This test has a couple of variants.
4156 enum {
4157 // Induce the RST while waiting for our transaction to send.
rchacdcbdc2015-05-16 17:16:004158 VARIANT_RST_DURING_SEND_COMPLETION = 0,
[email protected]58cebf8f2010-07-31 19:20:164159 // Induce the RST while waiting for our transaction to read.
4160 // In this case, the send completed - everything copied into the SNDBUF.
rchacdcbdc2015-05-16 17:16:004161 VARIANT_RST_DURING_READ_COMPLETION = 1
[email protected]58cebf8f2010-07-31 19:20:164162 };
4163
4164 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4165 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4166 ++variant) {
rchacdcbdc2015-05-16 17:16:004167 SequencedSocketData data1(reads, arraysize(reads), writes1, 1 + variant);
[email protected]58cebf8f2010-07-31 19:20:164168
rchacdcbdc2015-05-16 17:16:004169 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
4170 arraysize(writes2));
[email protected]58cebf8f2010-07-31 19:20:164171
[email protected]262eec82013-03-19 21:01:364172 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014173 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:574174 helper.AddData(&data1);
4175 helper.AddData(&data2);
[email protected]58cebf8f2010-07-31 19:20:164176 helper.RunPreTestSetup();
4177
4178 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:164179 HttpNetworkTransaction trans(DEFAULT_PRIORITY, helper.session());
[email protected]58cebf8f2010-07-31 19:20:164180
[email protected]49639fa2011-12-20 23:22:414181 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:164182 int rv =
4183 trans.Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014184 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]58cebf8f2010-07-31 19:20:164185 // On the second transaction, we trigger the RST.
4186 if (i == 1) {
4187 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4188 // Writes to the socket complete asynchronously on SPDY by running
4189 // through the message loop. Complete the write here.
[email protected]fc9d88472013-08-14 02:31:174190 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164191 }
4192
4193 // Now schedule the ERR_CONNECTION_RESET.
mmenkee24011922015-12-17 22:12:594194 data1.Resume();
[email protected]58cebf8f2010-07-31 19:20:164195 }
4196 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014197 EXPECT_THAT(rv, IsOk());
[email protected]58cebf8f2010-07-31 19:20:164198
bnc691fda62016-08-12 00:43:164199 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:524200 ASSERT_TRUE(response);
4201 EXPECT_TRUE(response->headers);
[email protected]58cebf8f2010-07-31 19:20:164202 EXPECT_TRUE(response->was_fetched_via_spdy);
4203 std::string response_data;
bnc691fda62016-08-12 00:43:164204 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014205 EXPECT_THAT(rv, IsOk());
bnc84e7fb52015-12-02 11:50:024206 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]58cebf8f2010-07-31 19:20:164207 EXPECT_EQ("hello!", response_data);
rchacdcbdc2015-05-16 17:16:004208 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164209 }
4210
4211 helper.VerifyDataConsumed();
rchacdcbdc2015-05-16 17:16:004212 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164213 }
4214}
[email protected]1f418ee2010-10-16 19:46:564215
[email protected]018aabc2010-10-29 16:16:594216// Tests that Basic authentication works over SPDY
bncd16676a2016-07-20 16:23:014217TEST_F(SpdyNetworkTransactionTest, SpdyBasicAuth) {
[email protected]018aabc2010-10-29 16:16:594218 // The first request will be a bare GET, the second request will be a
4219 // GET with an Authorization header.
bncdf80d44fd2016-07-15 20:27:414220 SpdySerializedFrame req_get(
bnc38dcd392016-02-09 23:19:494221 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:384222 // Will be refused for lack of auth.
4223 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]018aabc2010-10-29 16:16:594224 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464225 "authorization", "Basic Zm9vOmJhcg=="
[email protected]018aabc2010-10-29 16:16:594226 };
bncdf80d44fd2016-07-15 20:27:414227 SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
4228 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders) / 2, 3,
4229 LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594230 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:414231 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]018aabc2010-10-29 16:16:594232 };
4233
4234 // The first response is a 401 authentication challenge, and the second
4235 // response will be a 200 response since the second request includes a valid
4236 // Authorization header.
4237 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:264238 "www-authenticate",
[email protected]018aabc2010-10-29 16:16:594239 "Basic realm=\"MyRealm\""
4240 };
bnc42331402016-07-25 13:36:154241 SpdySerializedFrame resp_authentication(spdy_util_.ConstructSpdyReplyError(
bncdf80d44fd2016-07-15 20:27:414242 "401 Authentication Required", kExtraAuthenticationHeaders,
4243 arraysize(kExtraAuthenticationHeaders) / 2, 1));
4244 SpdySerializedFrame body_authentication(
4245 spdy_util_.ConstructSpdyDataFrame(1, true));
bnc42331402016-07-25 13:36:154246 SpdySerializedFrame resp_data(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:414247 SpdySerializedFrame body_data(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]018aabc2010-10-29 16:16:594248 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414249 CreateMockRead(resp_authentication, 1),
4250 CreateMockRead(body_authentication, 2),
4251 CreateMockRead(resp_data, 4),
4252 CreateMockRead(body_data, 5),
rch08e3aa3e2015-05-16 14:27:524253 MockRead(ASYNC, 0, 6),
[email protected]018aabc2010-10-29 16:16:594254 };
4255
rch08e3aa3e2015-05-16 14:27:524256 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4257 arraysize(spdy_writes));
[email protected]018aabc2010-10-29 16:16:594258 HttpRequestInfo request(CreateGetRequest());
4259 BoundNetLog net_log;
bncd16676a2016-07-20 16:23:014260 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, net_log, NULL);
[email protected]018aabc2010-10-29 16:16:594261
4262 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574263 helper.AddData(&data);
[email protected]018aabc2010-10-29 16:16:594264 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:414265 TestCompletionCallback callback;
4266 const int rv_start = trans->Start(&request, callback.callback(), net_log);
robpercival214763f2016-07-01 23:27:014267 EXPECT_THAT(rv_start, IsError(ERR_IO_PENDING));
[email protected]49639fa2011-12-20 23:22:414268 const int rv_start_complete = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014269 EXPECT_THAT(rv_start_complete, IsOk());
[email protected]018aabc2010-10-29 16:16:594270
4271 // Make sure the response has an auth challenge.
4272 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524273 ASSERT_TRUE(response_start);
4274 ASSERT_TRUE(response_start->headers);
[email protected]018aabc2010-10-29 16:16:594275 EXPECT_EQ(401, response_start->headers->response_code());
4276 EXPECT_TRUE(response_start->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044277 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
wezca1070932016-05-26 20:30:524278 ASSERT_TRUE(auth_challenge);
[email protected]79cb5c12011-09-12 13:12:044279 EXPECT_FALSE(auth_challenge->is_proxy);
aberentbba302d2015-12-03 10:20:194280 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:044281 EXPECT_EQ("MyRealm", auth_challenge->realm);
[email protected]018aabc2010-10-29 16:16:594282
4283 // Restart with a username/password.
[email protected]ad65a3e2013-12-25 18:18:014284 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
4285 base::ASCIIToUTF16("bar"));
[email protected]49639fa2011-12-20 23:22:414286 TestCompletionCallback callback_restart;
4287 const int rv_restart = trans->RestartWithAuth(
4288 credentials, callback_restart.callback());
robpercival214763f2016-07-01 23:27:014289 EXPECT_THAT(rv_restart, IsError(ERR_IO_PENDING));
[email protected]018aabc2010-10-29 16:16:594290 const int rv_restart_complete = callback_restart.WaitForResult();
robpercival214763f2016-07-01 23:27:014291 EXPECT_THAT(rv_restart_complete, IsOk());
[email protected]018aabc2010-10-29 16:16:594292 // TODO(cbentzel): This is actually the same response object as before, but
4293 // data has changed.
4294 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524295 ASSERT_TRUE(response_restart);
4296 ASSERT_TRUE(response_restart->headers);
[email protected]018aabc2010-10-29 16:16:594297 EXPECT_EQ(200, response_restart->headers->response_code());
4298 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4299}
4300
bncd16676a2016-07-20 16:23:014301TEST_F(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
bncdf80d44fd2016-07-15 20:27:414302 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494303 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]d08358502010-12-03 22:04:034304 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414305 CreateMockWrite(stream1_syn, 0),
[email protected]d08358502010-12-03 22:04:034306 };
4307
bncdf80d44fd2016-07-15 20:27:414308 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154309 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc38dcd392016-02-09 23:19:494310
bnc086b39e12016-06-24 13:05:264311 SpdyHeaderBlock initial_headers;
rchebf12982015-04-10 01:15:004312 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
bnc086b39e12016-06-24 13:05:264313 &initial_headers);
bncdf80d44fd2016-07-15 20:27:414314 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4315 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:044316
bnc38dcd392016-02-09 23:19:494317 SpdyHeaderBlock late_headers;
4318 late_headers[spdy_util_.GetStatusKey()] = "200";
bnc38dcd392016-02-09 23:19:494319 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414320 SpdySerializedFrame stream2_headers(spdy_util_.ConstructSpdyResponseHeaders(
4321 2, std::move(late_headers), false));
[email protected]d08358502010-12-03 22:04:034322
bncdf80d44fd2016-07-15 20:27:414323 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc38dcd392016-02-09 23:19:494324
[email protected]8a0fc822013-06-27 20:52:434325 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414326 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
4327 2, kPushedData, strlen(kPushedData), true));
bnc38dcd392016-02-09 23:19:494328
[email protected]d08358502010-12-03 22:04:034329 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414330 CreateMockRead(stream1_reply, 1),
4331 CreateMockRead(stream2_syn, 2),
4332 CreateMockRead(stream2_headers, 3),
4333 CreateMockRead(stream1_body, 4, SYNCHRONOUS),
4334 CreateMockRead(stream2_body, 5),
rch08e3aa3e2015-05-16 14:27:524335 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]d08358502010-12-03 22:04:034336 };
4337
4338 HttpResponseInfo response;
4339 HttpResponseInfo response2;
4340 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:524341 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574342 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:034343 &response,
4344 &response2,
4345 expected_push_result);
4346
bnc42331402016-07-25 13:36:154347 // Verify the response headers.
wezca1070932016-05-26 20:30:524348 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024349 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034350
4351 // Verify the pushed stream.
wezca1070932016-05-26 20:30:524352 EXPECT_TRUE(response2.headers);
bnc84e7fb52015-12-02 11:50:024353 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034354}
4355
bncd16676a2016-07-20 16:23:014356TEST_F(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
[email protected]d08358502010-12-03 22:04:034357 // We push a stream and attempt to claim it before the headers come down.
bncdf80d44fd2016-07-15 20:27:414358 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494359 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]d08358502010-12-03 22:04:034360 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414361 CreateMockWrite(stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:034362 };
4363
bncdf80d44fd2016-07-15 20:27:414364 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154365 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc086b39e12016-06-24 13:05:264366 SpdyHeaderBlock initial_headers;
rchebf12982015-04-10 01:15:004367 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
bnc086b39e12016-06-24 13:05:264368 &initial_headers);
bncdf80d44fd2016-07-15 20:27:414369 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4370 std::move(initial_headers), 2, 1));
4371 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc38dcd392016-02-09 23:19:494372 SpdyHeaderBlock late_headers;
4373 late_headers[spdy_util_.GetStatusKey()] = "200";
bnc38dcd392016-02-09 23:19:494374 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414375 SpdySerializedFrame stream2_headers(spdy_util_.ConstructSpdyResponseHeaders(
4376 2, std::move(late_headers), false));
[email protected]8a0fc822013-06-27 20:52:434377 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414378 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
4379 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:034380 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414381 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
4382 CreateMockRead(stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
4383 CreateMockRead(stream2_headers, 5), CreateMockRead(stream2_body, 6),
4384 MockRead(ASYNC, ERR_IO_PENDING, 7), MockRead(ASYNC, 0, 8), // EOF
[email protected]d08358502010-12-03 22:04:034385 };
4386
4387 HttpResponseInfo response;
4388 HttpResponseInfo response2;
4389 std::string expected_push_result("pushed");
mmenke666a6fea2015-12-19 04:16:334390 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:034391
[email protected]262eec82013-03-19 21:01:364392 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014393 BoundNetLog(), NULL);
mmenke666a6fea2015-12-19 04:16:334394 helper.AddData(&data);
[email protected]d08358502010-12-03 22:04:034395 helper.RunPreTestSetup();
4396
4397 HttpNetworkTransaction* trans = helper.trans();
4398
[email protected]d08358502010-12-03 22:04:034399 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:414400 TestCompletionCallback callback;
4401 int rv = trans->Start(
4402 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014403 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bnc42331402016-07-25 13:36:154404 // Run until we've received the primary HEADERS, the pushed HEADERS,
mmenke666a6fea2015-12-19 04:16:334405 // and the body of the primary stream, but before we've received the HEADERS
4406 // for the pushed stream.
4407 data.RunUntilPaused();
robpercival214763f2016-07-01 23:27:014408 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d08358502010-12-03 22:04:034409
4410 // Request the pushed path. At this point, we've received the push, but the
4411 // headers are not yet complete.
bnc691fda62016-08-12 00:43:164412 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
4413 rv =
4414 trans2.Start(&CreateGetPushRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014415 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
mmenke666a6fea2015-12-19 04:16:334416 data.Resume();
4417 data.RunUntilPaused();
[email protected]fc9d88472013-08-14 02:31:174418 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:034419
4420 // Read the server push body.
4421 std::string result2;
bnc691fda62016-08-12 00:43:164422 ReadResult(&trans2, &result2);
[email protected]d08358502010-12-03 22:04:034423 // Read the response body.
4424 std::string result;
rch0aecfd82015-05-19 17:22:324425 ReadResult(trans, &result);
[email protected]d08358502010-12-03 22:04:034426
[email protected]d08358502010-12-03 22:04:034427 // Verify that the received push data is same as the expected push data.
4428 EXPECT_EQ(result2.compare(expected_push_result), 0)
4429 << "Received data: "
4430 << result2
4431 << "||||| Expected data: "
4432 << expected_push_result;
4433
bnc42331402016-07-25 13:36:154434 // Verify the response headers.
[email protected]d08358502010-12-03 22:04:034435 // Copy the response info, because trans goes away.
4436 response = *trans->GetResponseInfo();
bnc691fda62016-08-12 00:43:164437 response2 = *trans2.GetResponseInfo();
[email protected]d08358502010-12-03 22:04:034438
4439 VerifyStreamsClosed(helper);
4440
bnc42331402016-07-25 13:36:154441 // Verify the response headers.
wezca1070932016-05-26 20:30:524442 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024443 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034444
4445 // Verify the pushed stream.
wezca1070932016-05-26 20:30:524446 EXPECT_TRUE(response2.headers);
bnc84e7fb52015-12-02 11:50:024447 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d55b30a2012-07-21 00:35:394448
4449 // Read the final EOF (which will close the session)
mmenke666a6fea2015-12-19 04:16:334450 data.Resume();
4451 base::RunLoop().RunUntilIdle();
[email protected]d55b30a2012-07-21 00:35:394452
4453 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:174454 EXPECT_TRUE(data.AllReadDataConsumed());
4455 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:034456}
4457
[email protected]6cd63ba2014-06-12 16:14:564458// TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
bncd16676a2016-07-20 16:23:014459TEST_F(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
[email protected]d08358502010-12-03 22:04:034460 // We push a stream and attempt to claim it before the headers come down.
bncdf80d44fd2016-07-15 20:27:414461 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494462 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]d08358502010-12-03 22:04:034463 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414464 CreateMockWrite(stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:034465 };
4466
bncdf80d44fd2016-07-15 20:27:414467 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154468 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc38dcd392016-02-09 23:19:494469
bnc086b39e12016-06-24 13:05:264470 SpdyHeaderBlock initial_headers;
rchebf12982015-04-10 01:15:004471 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
bnc086b39e12016-06-24 13:05:264472 &initial_headers);
bncdf80d44fd2016-07-15 20:27:414473 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4474 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:044475
bncdf80d44fd2016-07-15 20:27:414476 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]513963e2013-06-15 01:53:044477
bnc38dcd392016-02-09 23:19:494478 SpdyHeaderBlock middle_headers;
4479 middle_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414480 SpdySerializedFrame stream2_headers1(spdy_util_.ConstructSpdyResponseHeaders(
4481 2, std::move(middle_headers), false));
bnc38dcd392016-02-09 23:19:494482
4483 SpdyHeaderBlock late_headers;
4484 late_headers[spdy_util_.GetStatusKey()] = "200";
bncdf80d44fd2016-07-15 20:27:414485 SpdySerializedFrame stream2_headers2(spdy_util_.ConstructSpdyResponseHeaders(
4486 2, std::move(late_headers), false));
[email protected]d08358502010-12-03 22:04:034487
[email protected]8a0fc822013-06-27 20:52:434488 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414489 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
4490 2, kPushedData, strlen(kPushedData), true));
bnc38dcd392016-02-09 23:19:494491
[email protected]d08358502010-12-03 22:04:034492 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414493 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
4494 CreateMockRead(stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
4495 CreateMockRead(stream2_headers1, 5),
mmenke666a6fea2015-12-19 04:16:334496 // This is needed to work around https://crbug.com/571102.
bncdf80d44fd2016-07-15 20:27:414497 MockRead(ASYNC, ERR_IO_PENDING, 6), CreateMockRead(stream2_headers2, 7),
4498 CreateMockRead(stream2_body, 8), MockRead(ASYNC, ERR_IO_PENDING, 9),
mmenke666a6fea2015-12-19 04:16:334499 MockRead(ASYNC, 0, 10), // EOF
[email protected]d08358502010-12-03 22:04:034500 };
4501
4502 HttpResponseInfo response;
4503 HttpResponseInfo response2;
4504 std::string expected_push_result("pushed");
mmenke666a6fea2015-12-19 04:16:334505 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:034506
[email protected]262eec82013-03-19 21:01:364507 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014508 BoundNetLog(), NULL);
mmenke666a6fea2015-12-19 04:16:334509 helper.AddData(&data);
[email protected]d08358502010-12-03 22:04:034510 helper.RunPreTestSetup();
4511
4512 HttpNetworkTransaction* trans = helper.trans();
4513
[email protected]d08358502010-12-03 22:04:034514 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:414515 TestCompletionCallback callback;
4516 int rv = trans->Start(
4517 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014518 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bnc42331402016-07-25 13:36:154519 // Run until we've received the primary HEADERS, the pushed HEADERS,
mmenke666a6fea2015-12-19 04:16:334520 // the first HEADERS frame, and the body of the primary stream, but before
4521 // we've received the final HEADERS for the pushed stream.
4522 data.RunUntilPaused();
4523 EXPECT_EQ(0, callback.WaitForResult());
[email protected]d08358502010-12-03 22:04:034524
4525 // Request the pushed path. At this point, we've received the push, but the
4526 // headers are not yet complete.
bnc691fda62016-08-12 00:43:164527 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
4528 rv =
4529 trans2.Start(&CreateGetPushRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014530 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
mmenke666a6fea2015-12-19 04:16:334531 data.Resume();
4532 data.RunUntilPaused();
4533 base::RunLoop().RunUntilIdle();
4534 // This is needed to work around https://crbug.com/571102.
4535 data.Resume();
4536 data.RunUntilPaused();
[email protected]fc9d88472013-08-14 02:31:174537 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:034538
4539 // Read the server push body.
4540 std::string result2;
bnc691fda62016-08-12 00:43:164541 ReadResult(&trans2, &result2);
[email protected]d08358502010-12-03 22:04:034542 // Read the response body.
4543 std::string result;
rch0aecfd82015-05-19 17:22:324544 ReadResult(trans, &result);
[email protected]d08358502010-12-03 22:04:034545
[email protected]d08358502010-12-03 22:04:034546 // Verify that the received push data is same as the expected push data.
[email protected]6d116e1a2013-06-24 07:42:154547 EXPECT_EQ(expected_push_result, result2);
[email protected]d08358502010-12-03 22:04:034548
bnc42331402016-07-25 13:36:154549 // Verify the response headers.
[email protected]d08358502010-12-03 22:04:034550 // Copy the response info, because trans goes away.
4551 response = *trans->GetResponseInfo();
bnc691fda62016-08-12 00:43:164552 response2 = *trans2.GetResponseInfo();
[email protected]d08358502010-12-03 22:04:034553
4554 VerifyStreamsClosed(helper);
4555
bnc42331402016-07-25 13:36:154556 // Verify the response headers.
wezca1070932016-05-26 20:30:524557 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024558 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034559
4560 // Verify the pushed stream.
wezca1070932016-05-26 20:30:524561 EXPECT_TRUE(response2.headers);
bnc84e7fb52015-12-02 11:50:024562 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034563
[email protected]6cd63ba2014-06-12 16:14:564564 // Verify we got all the headers from all header blocks.
[email protected]d08358502010-12-03 22:04:034565 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
4566 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
[email protected]d55b30a2012-07-21 00:35:394567
4568 // Read the final EOF (which will close the session)
mmenke666a6fea2015-12-19 04:16:334569 data.Resume();
4570 base::RunLoop().RunUntilIdle();
[email protected]d55b30a2012-07-21 00:35:394571
4572 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:174573 EXPECT_TRUE(data.AllReadDataConsumed());
4574 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:034575}
4576
bncd16676a2016-07-20 16:23:014577TEST_F(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
[email protected]5c6908e2012-08-06 18:53:474578 // We push a stream and attempt to claim it before the headers come down.
bncdf80d44fd2016-07-15 20:27:414579 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494580 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]5c6908e2012-08-06 18:53:474581 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414582 CreateMockWrite(stream1_syn, 0, SYNCHRONOUS),
[email protected]5c6908e2012-08-06 18:53:474583 };
4584
bncdf80d44fd2016-07-15 20:27:414585 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154586 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc38dcd392016-02-09 23:19:494587
bnc086b39e12016-06-24 13:05:264588 SpdyHeaderBlock initial_headers;
rchebf12982015-04-10 01:15:004589 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
bnc086b39e12016-06-24 13:05:264590 &initial_headers);
bncdf80d44fd2016-07-15 20:27:414591 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4592 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:044593
bncdf80d44fd2016-07-15 20:27:414594 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]5c6908e2012-08-06 18:53:474595
bnc38dcd392016-02-09 23:19:494596 SpdyHeaderBlock middle_headers;
4597 middle_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414598 SpdySerializedFrame stream2_headers1(spdy_util_.ConstructSpdyResponseHeaders(
4599 2, std::move(middle_headers), false));
bnc38dcd392016-02-09 23:19:494600
[email protected]8a0fc822013-06-27 20:52:434601 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414602 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
4603 2, kPushedData, strlen(kPushedData), true));
bnc38dcd392016-02-09 23:19:494604
[email protected]5c6908e2012-08-06 18:53:474605 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414606 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
4607 CreateMockRead(stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
4608 CreateMockRead(stream2_headers1, 5), CreateMockRead(stream2_body, 6),
4609 MockRead(ASYNC, ERR_IO_PENDING, 7), MockRead(ASYNC, 0, 8), // EOF
[email protected]5c6908e2012-08-06 18:53:474610 };
4611
mmenke666a6fea2015-12-19 04:16:334612 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]5c6908e2012-08-06 18:53:474613
[email protected]262eec82013-03-19 21:01:364614 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014615 BoundNetLog(), NULL);
mmenke666a6fea2015-12-19 04:16:334616 helper.AddData(&data);
[email protected]5c6908e2012-08-06 18:53:474617 helper.RunPreTestSetup();
4618
4619 HttpNetworkTransaction* trans = helper.trans();
4620
[email protected]5c6908e2012-08-06 18:53:474621 // Start the transaction.
4622 TestCompletionCallback callback;
4623 int rv = trans->Start(
4624 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014625 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bnc42331402016-07-25 13:36:154626 // Run until we've received the primary HEADERS, the pushed HEADERS,
mmenke666a6fea2015-12-19 04:16:334627 // the first HEADERS frame, and the body of the primary stream, but before
4628 // we've received the final HEADERS for the pushed stream.
4629 data.RunUntilPaused();
4630 EXPECT_EQ(0, callback.WaitForResult());
[email protected]5c6908e2012-08-06 18:53:474631
4632 // Request the pushed path. At this point, we've received the push, but the
4633 // headers are not yet complete.
bnc691fda62016-08-12 00:43:164634 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
4635 rv =
4636 trans2.Start(&CreateGetPushRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014637 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
mmenke666a6fea2015-12-19 04:16:334638 data.Resume();
4639 data.RunUntilPaused();
[email protected]fc9d88472013-08-14 02:31:174640 base::RunLoop().RunUntilIdle();
[email protected]5c6908e2012-08-06 18:53:474641
4642 // Read the server push body.
4643 std::string result2;
bnc691fda62016-08-12 00:43:164644 ReadResult(&trans2, &result2);
[email protected]5c6908e2012-08-06 18:53:474645 // Read the response body.
4646 std::string result;
rch0aecfd82015-05-19 17:22:324647 ReadResult(trans, &result);
[email protected]5c6908e2012-08-06 18:53:474648 EXPECT_EQ("hello!", result);
4649
4650 // Verify that we haven't received any push data.
4651 EXPECT_EQ("", result2);
4652
bnc42331402016-07-25 13:36:154653 // Verify the response headers.
[email protected]5c6908e2012-08-06 18:53:474654 // Copy the response info, because trans goes away.
4655 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]5c6908e2012-08-06 18:53:474656
4657 VerifyStreamsClosed(helper);
4658
bnc42331402016-07-25 13:36:154659 // Verify the response headers.
wezca1070932016-05-26 20:30:524660 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024661 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]5c6908e2012-08-06 18:53:474662
4663 // Read the final EOF (which will close the session).
mmenke666a6fea2015-12-19 04:16:334664 data.Resume();
4665 base::RunLoop().RunUntilIdle();
[email protected]5c6908e2012-08-06 18:53:474666
4667 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:174668 EXPECT_TRUE(data.AllReadDataConsumed());
4669 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]5c6908e2012-08-06 18:53:474670}
4671
bnc42331402016-07-25 13:36:154672TEST_F(SpdyNetworkTransactionTest, ResponseHeadersTwice) {
bncdf80d44fd2016-07-15 20:27:414673 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494674 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414675 SpdySerializedFrame rst(
[email protected]b771bb72013-06-24 09:55:414676 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
4677 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414678 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
[email protected]745aa9c2014-06-27 02:21:294679 };
[email protected]d08358502010-12-03 22:04:034680
bncdf80d44fd2016-07-15 20:27:414681 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154682 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:044683
bnc38dcd392016-02-09 23:19:494684 SpdyHeaderBlock late_headers;
4685 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414686 SpdySerializedFrame stream1_headers(spdy_util_.ConstructSpdyResponseHeaders(
4687 1, std::move(late_headers), false));
4688 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d08358502010-12-03 22:04:034689 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414690 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_headers, 2),
4691 CreateMockRead(stream1_body, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]d08358502010-12-03 22:04:034692 };
4693
rch08e3aa3e2015-05-16 14:27:524694 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364695 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014696 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:574697 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:034698 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014699 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d08358502010-12-03 22:04:034700}
4701
xunjieli294da722015-08-11 19:15:024702// Tests that receiving HEADERS, DATA, HEADERS, and DATA in that sequence will
4703// trigger a ERR_SPDY_PROTOCOL_ERROR because trailing HEADERS must not be
4704// followed by any DATA frames.
bncd16676a2016-07-20 16:23:014705TEST_F(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) {
bncdf80d44fd2016-07-15 20:27:414706 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494707 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414708 SpdySerializedFrame rst(
[email protected]b771bb72013-06-24 09:55:414709 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
4710 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414711 CreateMockWrite(req, 0), CreateMockWrite(rst, 5),
[email protected]b771bb72013-06-24 09:55:414712 };
[email protected]d08358502010-12-03 22:04:034713
bncdf80d44fd2016-07-15 20:27:414714 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154715 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414716 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, false));
bnc38dcd392016-02-09 23:19:494717
4718 SpdyHeaderBlock late_headers;
4719 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414720 SpdySerializedFrame stream1_headers(spdy_util_.ConstructSpdyResponseHeaders(
4721 1, std::move(late_headers), false));
4722 SpdySerializedFrame stream1_body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d08358502010-12-03 22:04:034723 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414724 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_body, 2),
4725 CreateMockRead(stream1_headers, 3), CreateMockRead(stream1_body2, 4),
rch08e3aa3e2015-05-16 14:27:524726 MockRead(ASYNC, 0, 6) // EOF
[email protected]d08358502010-12-03 22:04:034727 };
4728
rch32320842015-05-16 15:57:094729 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364730 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014731 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:574732 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:034733 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014734 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d08358502010-12-03 22:04:034735}
4736
bncd16676a2016-07-20 16:23:014737TEST_F(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
[email protected]a7a265ef2010-12-08 18:05:574738 // In this test we want to verify that we can't accidentally push content
4739 // which can't be pushed by this content server.
4740 // This test assumes that:
4741 // - if we're requesting http://www.foo.com/barbaz
4742 // - the browser has made a connection to "www.foo.com".
4743
4744 // A list of the URL to fetch, followed by the URL being pushed.
4745 static const char* const kTestCases[] = {
bncce36dca22015-04-21 22:11:234746 "https://www.example.org/foo.html",
bncce36dca22015-04-21 22:11:234747 "http://www.example.org/foo.js", // Bad protocol
[email protected]a7a265ef2010-12-08 18:05:574748
bncce36dca22015-04-21 22:11:234749 "https://www.example.org/foo.html",
4750 "ftp://www.example.org/foo.js", // Invalid Protocol
[email protected]a7a265ef2010-12-08 18:05:574751
bncce36dca22015-04-21 22:11:234752 "https://www.example.org/foo.html",
4753 "https://blat.www.example.org/foo.js", // Cross subdomain
[email protected]a7a265ef2010-12-08 18:05:574754
bncce36dca22015-04-21 22:11:234755 "https://www.example.org/foo.html",
rchebf12982015-04-10 01:15:004756 "https://www.foo.com/foo.js", // Cross domain
[email protected]a7a265ef2010-12-08 18:05:574757 };
4758
[email protected]b3f899332010-12-08 18:20:444759 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
[email protected]a7a265ef2010-12-08 18:05:574760 const char* url_to_fetch = kTestCases[index];
4761 const char* url_to_push = kTestCases[index + 1];
4762
bncd16676a2016-07-20 16:23:014763 SpdyTestUtil spdy_test_util;
bncdf80d44fd2016-07-15 20:27:414764 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494765 spdy_test_util.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414766 SpdySerializedFrame stream1_body(
4767 spdy_test_util.ConstructSpdyDataFrame(1, true));
4768 SpdySerializedFrame push_rst(
bnc38dcd392016-02-09 23:19:494769 spdy_test_util.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]a7a265ef2010-12-08 18:05:574770 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414771 CreateMockWrite(stream1_syn, 0), CreateMockWrite(push_rst, 3),
[email protected]a7a265ef2010-12-08 18:05:574772 };
4773
bncdf80d44fd2016-07-15 20:27:414774 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154775 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414776 SpdySerializedFrame stream2_syn(
bnc38dcd392016-02-09 23:19:494777 spdy_test_util.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
[email protected]8a0fc822013-06-27 20:52:434778 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414779 SpdySerializedFrame stream2_body(spdy_test_util.ConstructSpdyDataFrame(
4780 2, kPushedData, strlen(kPushedData), true));
4781 SpdySerializedFrame rst(
bnc38dcd392016-02-09 23:19:494782 spdy_test_util.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]a7a265ef2010-12-08 18:05:574783
4784 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414785 CreateMockRead(stream1_reply, 1),
4786 CreateMockRead(stream2_syn, 2),
4787 CreateMockRead(stream1_body, 4),
4788 CreateMockRead(stream2_body, 5),
rch08e3aa3e2015-05-16 14:27:524789 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]a7a265ef2010-12-08 18:05:574790 };
4791
4792 HttpResponseInfo response;
rch08e3aa3e2015-05-16 14:27:524793 SequencedSocketData data(reads, arraysize(reads), writes,
4794 arraysize(writes));
[email protected]a7a265ef2010-12-08 18:05:574795
4796 HttpRequestInfo request;
4797 request.method = "GET";
4798 request.url = GURL(url_to_fetch);
4799 request.load_flags = 0;
[email protected]a7a265ef2010-12-08 18:05:574800
[email protected]7c6f7ba2012-04-03 04:09:294801 // Enable cross-origin push. Since we are not using a proxy, this should
4802 // not actually enable cross-origin SPDY push.
bncd16676a2016-07-20 16:23:014803 auto session_deps = base::MakeUnique<SpdySessionDependencies>();
danakjaee3e1ec2016-04-16 00:23:184804 std::unique_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
tbansal28e68f82016-02-04 02:56:154805 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
4806 "https://123.45.67.89:443", net::ProxyServer::SCHEME_HTTP));
4807 session_deps->proxy_delegate.reset(proxy_delegate.release());
rdsmith82957ad2015-09-16 19:42:034808 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:014809 std::move(session_deps));
[email protected]61b4efc2012-04-27 18:12:504810 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574811 helper.AddData(&data);
[email protected]7c6f7ba2012-04-03 04:09:294812
[email protected]a7a265ef2010-12-08 18:05:574813 HttpNetworkTransaction* trans = helper.trans();
4814
4815 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:414816 TestCompletionCallback callback;
[email protected]a7a265ef2010-12-08 18:05:574817
[email protected]49639fa2011-12-20 23:22:414818 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014819 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a7a265ef2010-12-08 18:05:574820 rv = callback.WaitForResult();
4821
4822 // Read the response body.
4823 std::string result;
rch0aecfd82015-05-19 17:22:324824 ReadResult(trans, &result);
[email protected]a7a265ef2010-12-08 18:05:574825
4826 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:174827 EXPECT_TRUE(data.AllReadDataConsumed());
4828 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]a7a265ef2010-12-08 18:05:574829
bnc42331402016-07-25 13:36:154830 // Verify the response headers.
[email protected]a7a265ef2010-12-08 18:05:574831 // Copy the response info, because trans goes away.
4832 response = *trans->GetResponseInfo();
4833
4834 VerifyStreamsClosed(helper);
4835
bnc42331402016-07-25 13:36:154836 // Verify the response headers.
wezca1070932016-05-26 20:30:524837 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024838 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]a7a265ef2010-12-08 18:05:574839 }
4840}
4841
bnc3e79387f2016-03-15 14:49:204842// Verify that push works cross origin as long as the certificate is valid for
4843// the pushed authority.
bncd16676a2016-07-20 16:23:014844TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOrigin) {
bnc3e79387f2016-03-15 14:49:204845 // "spdy_pooling.pem" is valid for both www.example.org and mail.example.org.
4846 const char* url_to_fetch = "https://www.example.org";
4847 const char* url_to_push = "https://mail.example.org";
4848
bncdf80d44fd2016-07-15 20:27:414849 SpdySerializedFrame headers(
bnc3e79387f2016-03-15 14:49:204850 spdy_util_.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
4851 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414852 CreateMockWrite(headers, 0),
bnc3e79387f2016-03-15 14:49:204853 };
4854
bnc42331402016-07-25 13:36:154855 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414856 SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:204857 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
bncdf80d44fd2016-07-15 20:27:414858 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc3e79387f2016-03-15 14:49:204859 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414860 SpdySerializedFrame pushed_body(spdy_util_.ConstructSpdyDataFrame(
4861 2, kPushedData, strlen(kPushedData), true));
bnc3e79387f2016-03-15 14:49:204862 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414863 CreateMockRead(reply, 1),
4864 CreateMockRead(push, 2),
4865 CreateMockRead(body, 3),
4866 CreateMockRead(pushed_body, 4),
bnc3e79387f2016-03-15 14:49:204867 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
4868 };
4869
4870 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4871
4872 HttpRequestInfo request;
4873 request.method = "GET";
4874 request.url = GURL(url_to_fetch);
4875 request.load_flags = 0;
4876
4877 BoundNetLog log;
bncd16676a2016-07-20 16:23:014878 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, log, nullptr);
bnc3e79387f2016-03-15 14:49:204879 helper.RunPreTestSetup();
4880 helper.AddData(&data);
4881
4882 HttpNetworkTransaction* trans0 = helper.trans();
4883 TestCompletionCallback callback0;
4884 int rv = trans0->Start(&request, callback0.callback(), log);
4885 rv = callback0.GetResult(rv);
robpercival214763f2016-07-01 23:27:014886 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:204887
4888 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
bncb26024382016-06-29 02:39:454889 SpdySessionKey key(host_port_pair_, ProxyServer::Direct(),
bnc3e79387f2016-03-15 14:49:204890 PRIVACY_MODE_DISABLED);
4891 base::WeakPtr<SpdySession> spdy_session =
4892 spdy_session_pool->FindAvailableSession(key, GURL(), log);
4893
4894 EXPECT_FALSE(spdy_session->unclaimed_pushed_streams_.empty());
4895 EXPECT_EQ(1u, spdy_session->unclaimed_pushed_streams_.size());
4896 EXPECT_EQ(1u,
4897 spdy_session->unclaimed_pushed_streams_.count(GURL(url_to_push)));
4898
bnc691fda62016-08-12 00:43:164899 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:204900 HttpRequestInfo push_request;
4901 push_request.method = "GET";
4902 push_request.url = GURL(url_to_push);
4903 push_request.load_flags = 0;
4904 TestCompletionCallback callback1;
bnc691fda62016-08-12 00:43:164905 rv = trans1.Start(&push_request, callback1.callback(), log);
bnc3e79387f2016-03-15 14:49:204906 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:014907 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:204908
4909 EXPECT_TRUE(spdy_session->unclaimed_pushed_streams_.empty());
4910 EXPECT_EQ(0u, spdy_session->unclaimed_pushed_streams_.size());
4911
4912 helper.VerifyDataConsumed();
4913 VerifyStreamsClosed(helper);
4914
4915 HttpResponseInfo response = *trans0->GetResponseInfo();
wezca1070932016-05-26 20:30:524916 EXPECT_TRUE(response.headers);
bnc3e79387f2016-03-15 14:49:204917 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
4918
4919 std::string result0;
4920 ReadResult(trans0, &result0);
4921 EXPECT_EQ("hello!", result0);
4922
bnc691fda62016-08-12 00:43:164923 HttpResponseInfo push_response = *trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:524924 EXPECT_TRUE(push_response.headers);
bnc3e79387f2016-03-15 14:49:204925 EXPECT_EQ("HTTP/1.1 200", push_response.headers->GetStatusLine());
4926
4927 std::string result1;
bnc691fda62016-08-12 00:43:164928 ReadResult(&trans1, &result1);
bnc3e79387f2016-03-15 14:49:204929 EXPECT_EQ(kPushedData, result1);
4930}
4931
4932// Verify that push works cross origin, even if there is already a connection
4933// open to origin of pushed resource.
bncd16676a2016-07-20 16:23:014934TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOriginWithOpenSession) {
bnc3e79387f2016-03-15 14:49:204935 const char* url_to_fetch0 = "https://mail.example.org/foo";
4936 const char* url_to_fetch1 = "https://docs.example.org";
4937 const char* url_to_push = "https://mail.example.org/bar";
4938
bncd16676a2016-07-20 16:23:014939 SpdyTestUtil spdy_util_0;
bnc3e79387f2016-03-15 14:49:204940
bncdf80d44fd2016-07-15 20:27:414941 SpdySerializedFrame headers0(
bnc3e79387f2016-03-15 14:49:204942 spdy_util_0.ConstructSpdyGet(url_to_fetch0, 1, LOWEST));
4943 MockWrite writes0[] = {
bncdf80d44fd2016-07-15 20:27:414944 CreateMockWrite(headers0, 0),
bnc3e79387f2016-03-15 14:49:204945 };
4946
bnc42331402016-07-25 13:36:154947 SpdySerializedFrame reply0(spdy_util_0.ConstructSpdyGetReply(nullptr, 0, 1));
bnc3e79387f2016-03-15 14:49:204948 const char kData0[] = "first";
bncdf80d44fd2016-07-15 20:27:414949 SpdySerializedFrame body0(
4950 spdy_util_0.ConstructSpdyDataFrame(1, kData0, strlen(kData0), true));
4951 MockRead reads0[] = {CreateMockRead(reply0, 1), CreateMockRead(body0, 2),
4952 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
bnc3e79387f2016-03-15 14:49:204953
4954 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4955 arraysize(writes0));
4956
bncd16676a2016-07-20 16:23:014957 SpdyTestUtil spdy_util_1;
bnc3e79387f2016-03-15 14:49:204958
bncdf80d44fd2016-07-15 20:27:414959 SpdySerializedFrame headers1(
bnc3e79387f2016-03-15 14:49:204960 spdy_util_1.ConstructSpdyGet(url_to_fetch1, 1, LOWEST));
4961 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:414962 CreateMockWrite(headers1, 0),
bnc3e79387f2016-03-15 14:49:204963 };
4964
bnc42331402016-07-25 13:36:154965 SpdySerializedFrame reply1(spdy_util_1.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414966 SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:204967 spdy_util_1.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
4968 const char kData1[] = "second";
bncdf80d44fd2016-07-15 20:27:414969 SpdySerializedFrame body1(
4970 spdy_util_1.ConstructSpdyDataFrame(1, kData1, strlen(kData1), true));
bnc3e79387f2016-03-15 14:49:204971 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414972 SpdySerializedFrame pushed_body(spdy_util_1.ConstructSpdyDataFrame(
4973 2, kPushedData, strlen(kPushedData), true));
bnc3e79387f2016-03-15 14:49:204974
4975 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:414976 CreateMockRead(reply1, 1),
4977 CreateMockRead(push, 2),
4978 CreateMockRead(body1, 3),
4979 CreateMockRead(pushed_body, 4),
bnc3e79387f2016-03-15 14:49:204980 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
4981 };
4982
4983 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4984 arraysize(writes1));
4985
4986 // Request |url_to_fetch0| to open connection to mail.example.org.
4987 HttpRequestInfo request0;
4988 request0.method = "GET";
4989 request0.url = GURL(url_to_fetch0);
4990 request0.load_flags = 0;
4991
4992 BoundNetLog log;
bncd16676a2016-07-20 16:23:014993 NormalSpdyTransactionHelper helper(request0, DEFAULT_PRIORITY, log, nullptr);
bnc3e79387f2016-03-15 14:49:204994 helper.RunPreTestSetup();
4995
4996 // "spdy_pooling.pem" is valid for www.example.org, but not for
4997 // docs.example.org.
danakjaee3e1ec2016-04-16 00:23:184998 std::unique_ptr<SSLSocketDataProvider> ssl_provider0(
bnc3e79387f2016-03-15 14:49:204999 new SSLSocketDataProvider(ASYNC, OK));
5000 ssl_provider0->cert =
5001 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
5002 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
5003
5004 // "wildcard.pem" is valid for both www.example.org and docs.example.org.
danakjaee3e1ec2016-04-16 00:23:185005 std::unique_ptr<SSLSocketDataProvider> ssl_provider1(
bnc3e79387f2016-03-15 14:49:205006 new SSLSocketDataProvider(ASYNC, OK));
5007 ssl_provider1->cert =
5008 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
5009 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
5010
5011 HttpNetworkTransaction* trans0 = helper.trans();
5012 TestCompletionCallback callback0;
5013 int rv = trans0->Start(&request0, callback0.callback(), log);
5014 rv = callback0.GetResult(rv);
robpercival214763f2016-07-01 23:27:015015 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205016
5017 // Request |url_to_fetch1|, during which docs.example.org pushes
5018 // |url_to_push|, which happens to be for www.example.org, to which there is
5019 // already an open connection.
bnc691fda62016-08-12 00:43:165020 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:205021 HttpRequestInfo request1;
5022 request1.method = "GET";
5023 request1.url = GURL(url_to_fetch1);
5024 request1.load_flags = 0;
5025 TestCompletionCallback callback1;
bnc691fda62016-08-12 00:43:165026 rv = trans1.Start(&request1, callback1.callback(), log);
bnc3e79387f2016-03-15 14:49:205027 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:015028 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205029
5030 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5031 HostPortPair host_port_pair0("mail.example.org", 443);
5032 SpdySessionKey key0(host_port_pair0, ProxyServer::Direct(),
5033 PRIVACY_MODE_DISABLED);
5034 base::WeakPtr<SpdySession> spdy_session0 =
5035 spdy_session_pool->FindAvailableSession(key0, GURL(), log);
5036
5037 EXPECT_TRUE(spdy_session0->unclaimed_pushed_streams_.empty());
5038 EXPECT_EQ(0u, spdy_session0->unclaimed_pushed_streams_.size());
5039
5040 HostPortPair host_port_pair1("docs.example.org", 443);
5041 SpdySessionKey key1(host_port_pair1, ProxyServer::Direct(),
5042 PRIVACY_MODE_DISABLED);
5043 base::WeakPtr<SpdySession> spdy_session1 =
5044 spdy_session_pool->FindAvailableSession(key1, GURL(), log);
5045
5046 EXPECT_FALSE(spdy_session1->unclaimed_pushed_streams_.empty());
5047 EXPECT_EQ(1u, spdy_session1->unclaimed_pushed_streams_.size());
5048 EXPECT_EQ(1u,
5049 spdy_session1->unclaimed_pushed_streams_.count(GURL(url_to_push)));
5050
5051 // Request |url_to_push|, which should be served from the pushed resource.
bnc691fda62016-08-12 00:43:165052 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:205053 HttpRequestInfo push_request;
5054 push_request.method = "GET";
5055 push_request.url = GURL(url_to_push);
5056 push_request.load_flags = 0;
5057 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:165058 rv = trans2.Start(&push_request, callback2.callback(), log);
bnc3e79387f2016-03-15 14:49:205059 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:015060 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205061
5062 EXPECT_TRUE(spdy_session0->unclaimed_pushed_streams_.empty());
5063 EXPECT_EQ(0u, spdy_session0->unclaimed_pushed_streams_.size());
5064
5065 EXPECT_TRUE(spdy_session1->unclaimed_pushed_streams_.empty());
5066 EXPECT_EQ(0u, spdy_session1->unclaimed_pushed_streams_.size());
5067
5068 helper.VerifyDataConsumed();
5069 VerifyStreamsClosed(helper);
5070
5071 HttpResponseInfo response0 = *trans0->GetResponseInfo();
wezca1070932016-05-26 20:30:525072 EXPECT_TRUE(response0.headers);
bnc3e79387f2016-03-15 14:49:205073 EXPECT_EQ("HTTP/1.1 200", response0.headers->GetStatusLine());
5074
5075 std::string result0;
5076 ReadResult(trans0, &result0);
5077 EXPECT_EQ(kData0, result0);
5078
bnc691fda62016-08-12 00:43:165079 HttpResponseInfo response1 = *trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:525080 EXPECT_TRUE(response1.headers);
bnc3e79387f2016-03-15 14:49:205081 EXPECT_EQ("HTTP/1.1 200", response1.headers->GetStatusLine());
5082
5083 std::string result1;
bnc691fda62016-08-12 00:43:165084 ReadResult(&trans1, &result1);
bnc3e79387f2016-03-15 14:49:205085 EXPECT_EQ(kData1, result1);
5086
bnc691fda62016-08-12 00:43:165087 HttpResponseInfo push_response = *trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:525088 EXPECT_TRUE(push_response.headers);
bnc3e79387f2016-03-15 14:49:205089 EXPECT_EQ("HTTP/1.1 200", push_response.headers->GetStatusLine());
5090
5091 std::string result2;
bnc691fda62016-08-12 00:43:165092 ReadResult(&trans2, &result2);
bnc3e79387f2016-03-15 14:49:205093 EXPECT_EQ(kPushedData, result2);
5094}
5095
bncd16676a2016-07-20 16:23:015096TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidCrossOrigin) {
bnc3e79387f2016-03-15 14:49:205097 // "spdy_pooling.pem" is valid for www.example.org,
5098 // but not for invalid.example.org.
5099 const char* url_to_fetch = "https://www.example.org";
5100 const char* url_to_push = "https://invalid.example.org";
5101
bncdf80d44fd2016-07-15 20:27:415102 SpdySerializedFrame headers(
bnc3e79387f2016-03-15 14:49:205103 spdy_util_.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415104 SpdySerializedFrame rst(
bnc3e79387f2016-03-15 14:49:205105 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5106 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415107 CreateMockWrite(headers, 0), CreateMockWrite(rst, 3),
bnc3e79387f2016-03-15 14:49:205108 };
5109
bnc42331402016-07-25 13:36:155110 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:415111 SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:205112 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
bncdf80d44fd2016-07-15 20:27:415113 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc3e79387f2016-03-15 14:49:205114 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:415115 SpdySerializedFrame pushed_body(spdy_util_.ConstructSpdyDataFrame(
5116 2, kPushedData, strlen(kPushedData), true));
bnc3e79387f2016-03-15 14:49:205117 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415118 CreateMockRead(reply, 1),
5119 CreateMockRead(push, 2),
5120 CreateMockRead(body, 4),
5121 CreateMockRead(pushed_body, 5),
bnc3e79387f2016-03-15 14:49:205122 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
5123 };
5124
5125 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
5126
5127 HttpRequestInfo request;
5128 request.method = "GET";
5129 request.url = GURL(url_to_fetch);
5130 request.load_flags = 0;
5131
5132 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:015133 nullptr);
bnc3e79387f2016-03-15 14:49:205134 helper.RunToCompletion(&data);
5135 TransactionHelperResult out = helper.output();
5136 EXPECT_EQ("HTTP/1.1 200", out.status_line);
5137 EXPECT_EQ("hello!", out.response_data);
5138}
5139
bncd16676a2016-07-20 16:23:015140TEST_F(SpdyNetworkTransactionTest, RetryAfterRefused) {
[email protected]721c0ce2011-10-13 02:41:005141 // Construct the request.
bncdf80d44fd2016-07-15 20:27:415142 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:495143 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:385144 // Will be destroyed by the RST before stream 3 starts.
5145 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:415146 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:495147 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
[email protected]721c0ce2011-10-13 02:41:005148 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415149 CreateMockWrite(req, 0), CreateMockWrite(req2, 2),
[email protected]721c0ce2011-10-13 02:41:005150 };
5151
bncdf80d44fd2016-07-15 20:27:415152 SpdySerializedFrame refused(
[email protected]c10b20852013-05-15 21:29:205153 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
bnc42331402016-07-25 13:36:155154 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:415155 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]721c0ce2011-10-13 02:41:005156 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415157 CreateMockRead(refused, 1), CreateMockRead(resp, 3),
5158 CreateMockRead(body, 4), MockRead(ASYNC, 0, 5) // EOF
[email protected]721c0ce2011-10-13 02:41:005159 };
5160
rch08e3aa3e2015-05-16 14:27:525161 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365162 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:015163 BoundNetLog(), NULL);
[email protected]721c0ce2011-10-13 02:41:005164
5165 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575166 helper.AddData(&data);
[email protected]721c0ce2011-10-13 02:41:005167
5168 HttpNetworkTransaction* trans = helper.trans();
5169
5170 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415171 TestCompletionCallback callback;
5172 int rv = trans->Start(
5173 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015174 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]721c0ce2011-10-13 02:41:005175 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015176 EXPECT_THAT(rv, IsOk());
[email protected]721c0ce2011-10-13 02:41:005177
5178 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:525179 EXPECT_TRUE(data.AllReadDataConsumed());
5180 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]721c0ce2011-10-13 02:41:005181
bnc42331402016-07-25 13:36:155182 // Verify the response headers.
[email protected]721c0ce2011-10-13 02:41:005183 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525184 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:025185 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]721c0ce2011-10-13 02:41:005186}
5187
bnc42331402016-07-25 13:36:155188TEST_F(SpdyNetworkTransactionTest, OutOfOrderHeaders) {
[email protected]e1f58efa2012-05-15 18:23:405189 // This first request will start to establish the SpdySession.
5190 // Then we will start the second (MEDIUM priority) and then third
5191 // (HIGHEST priority) request in such a way that the third will actually
[email protected]c92f4b4542012-07-26 23:53:215192 // start before the second, causing the second to be numbered differently
[email protected]513963e2013-06-15 01:53:045193 // than the order they were created.
rdsmithebb50aa2015-11-12 03:44:385194 //
5195 // Note that the requests and responses created below are expectations
5196 // of what the above will produce on the wire, and hence are in the
5197 // initial->HIGHEST->LOWEST priority.
5198 //
5199 // Frames are created by SpdySession just before the write associated
5200 // with the frame is attempted, so stream dependencies will be based
5201 // on the streams alive at the point of the request write attempt. Thus
5202 // req1 is alive when req2 is attempted (during but not after the
5203 // |data.RunFor(2);| statement below) but not when req3 is attempted.
5204 // The call to spdy_util_.UpdateWithStreamDestruction() reflects this.
bncdf80d44fd2016-07-15 20:27:415205 SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:495206 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:415207 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:495208 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, HIGHEST, true));
rdsmithebb50aa2015-11-12 03:44:385209 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:415210 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:495211 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, MEDIUM, true));
[email protected]e1f58efa2012-05-15 18:23:405212 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415213 MockWrite(ASYNC, ERR_IO_PENDING, 0), CreateMockWrite(req1, 1),
5214 CreateMockWrite(req2, 5), CreateMockWrite(req3, 6),
[email protected]e1f58efa2012-05-15 18:23:405215 };
5216
bnc42331402016-07-25 13:36:155217 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:415218 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc42331402016-07-25 13:36:155219 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:415220 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
bnc42331402016-07-25 13:36:155221 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
bncdf80d44fd2016-07-15 20:27:415222 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]e1f58efa2012-05-15 18:23:405223 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415224 CreateMockRead(resp1, 2), MockRead(ASYNC, ERR_IO_PENDING, 3),
5225 CreateMockRead(body1, 4), CreateMockRead(resp2, 7),
5226 CreateMockRead(body2, 8), CreateMockRead(resp3, 9),
5227 CreateMockRead(body3, 10), MockRead(ASYNC, 0, 11) // EOF
[email protected]e1f58efa2012-05-15 18:23:405228 };
5229
mmenke666a6fea2015-12-19 04:16:335230 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:015231 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST, BoundNetLog(),
5232 NULL);
[email protected]e1f58efa2012-05-15 18:23:405233 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:335234 helper.AddData(&data);
[email protected]e1f58efa2012-05-15 18:23:405235
5236 // Start the first transaction to set up the SpdySession
5237 HttpNetworkTransaction* trans = helper.trans();
5238 TestCompletionCallback callback;
5239 HttpRequestInfo info1 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405240 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015241 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e1f58efa2012-05-15 18:23:405242
5243 // Run the message loop, but do not allow the write to complete.
5244 // This leaves the SpdySession with a write pending, which prevents
5245 // SpdySession from attempting subsequent writes until this write completes.
[email protected]fc9d88472013-08-14 02:31:175246 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405247
5248 // Now, start both new transactions
5249 HttpRequestInfo info2 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405250 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:165251 HttpNetworkTransaction trans2(MEDIUM, helper.session());
5252 rv = trans2.Start(&info2, callback2.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015253 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:175254 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405255
5256 HttpRequestInfo info3 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405257 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:165258 HttpNetworkTransaction trans3(HIGHEST, helper.session());
5259 rv = trans3.Start(&info3, callback3.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015260 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:175261 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405262
bnc42331402016-07-25 13:36:155263 // We now have two HEADERS frames queued up which will be
[email protected]e1f58efa2012-05-15 18:23:405264 // dequeued only once the first write completes, which we
5265 // now allow to happen.
mmenke666a6fea2015-12-19 04:16:335266 ASSERT_TRUE(data.IsPaused());
5267 data.Resume();
robpercival214763f2016-07-01 23:27:015268 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e1f58efa2012-05-15 18:23:405269
5270 // And now we can allow everything else to run to completion.
mmenke666a6fea2015-12-19 04:16:335271 data.Resume();
5272 base::RunLoop().RunUntilIdle();
robpercival214763f2016-07-01 23:27:015273 EXPECT_THAT(callback2.WaitForResult(), IsOk());
5274 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]e1f58efa2012-05-15 18:23:405275
5276 helper.VerifyDataConsumed();
5277}
5278
[email protected]d11b6912013-06-27 23:07:325279// Test that sent data frames and received WINDOW_UPDATE frames change
5280// the send_window_size_ correctly.
5281
5282// WINDOW_UPDATE is different than most other frames in that it can arrive
5283// while the client is still sending the request body. In order to enforce
5284// this scenario, we feed a couple of dummy frames and give a delay of 0 to
5285// socket data provider, so that initial read that is done as soon as the
5286// stream is created, succeeds and schedules another read. This way reads
5287// and writes are interleaved; after doing a full frame write, SpdyStream
5288// will break out of DoLoop and will read and process a WINDOW_UPDATE.
bnc42331402016-07-25 13:36:155289// Once our WINDOW_UPDATE is read, we cannot send HEADERS right away
[email protected]d11b6912013-06-27 23:07:325290// since request has not been completely written, therefore we feed
5291// enough number of WINDOW_UPDATEs to finish the first read and cause a
5292// write, leading to a complete write of request body; after that we send
5293// a reply with a body, to cause a graceful shutdown.
5294
5295// TODO(agayev): develop a socket data provider where both, reads and
5296// writes are ordered so that writing tests like these are easy and rewrite
5297// all these tests using it. Right now we are working around the
5298// limitations as described above and it's not deterministic, tests may
5299// fail under specific circumstances.
bncd16676a2016-07-20 16:23:015300TEST_F(SpdyNetworkTransactionTest, WindowUpdateReceived) {
[email protected]d11b6912013-06-27 23:07:325301 static int kFrameCount = 2;
danakjaee3e1ec2016-04-16 00:23:185302 std::unique_ptr<std::string> content(
[email protected]d11b6912013-06-27 23:07:325303 new std::string(kMaxSpdyFrameChunkSize, 'a'));
bncdf80d44fd2016-07-15 20:27:415304 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455305 kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
bncdf80d44fd2016-07-15 20:27:415306 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555307 1, content->c_str(), content->size(), false));
bncdf80d44fd2016-07-15 20:27:415308 SpdySerializedFrame body_end(spdy_util_.ConstructSpdyDataFrame(
5309 1, content->c_str(), content->size(), true));
[email protected]d11b6912013-06-27 23:07:325310
5311 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415312 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
5313 CreateMockWrite(body_end, 2),
[email protected]d11b6912013-06-27 23:07:325314 };
5315
Avi Drissman13fc8932015-12-20 04:40:465316 static const int32_t kDeltaWindowSize = 0xff;
[email protected]d11b6912013-06-27 23:07:325317 static const int kDeltaCount = 4;
bncdf80d44fd2016-07-15 20:27:415318 SpdySerializedFrame window_update(
[email protected]d11b6912013-06-27 23:07:325319 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
bncdf80d44fd2016-07-15 20:27:415320 SpdySerializedFrame window_update_dummy(
[email protected]d11b6912013-06-27 23:07:325321 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
bnc42331402016-07-25 13:36:155322 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]d11b6912013-06-27 23:07:325323 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415324 CreateMockRead(window_update_dummy, 3),
5325 CreateMockRead(window_update_dummy, 4),
5326 CreateMockRead(window_update_dummy, 5),
5327 CreateMockRead(window_update, 6), // Four updates, therefore window
5328 CreateMockRead(window_update, 7), // size should increase by
5329 CreateMockRead(window_update, 8), // kDeltaWindowSize * 4
5330 CreateMockRead(window_update, 9),
5331 CreateMockRead(resp, 10),
5332 MockRead(ASYNC, ERR_IO_PENDING, 11),
5333 CreateMockRead(body_end, 12),
mmenke666a6fea2015-12-19 04:16:335334 MockRead(ASYNC, 0, 13) // EOF
[email protected]d11b6912013-06-27 23:07:325335 };
5336
mmenke666a6fea2015-12-19 04:16:335337 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d11b6912013-06-27 23:07:325338
danakjaee3e1ec2016-04-16 00:23:185339 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:325340 for (int i = 0; i < kFrameCount; ++i) {
danakjaee3e1ec2016-04-16 00:23:185341 element_readers.push_back(base::WrapUnique(
olli.raula6df48b2a2015-11-26 07:40:225342 new UploadBytesElementReader(content->c_str(), content->size())));
[email protected]d11b6912013-06-27 23:07:325343 }
olli.raula6df48b2a2015-11-26 07:40:225344 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325345
5346 // Setup the request
5347 HttpRequestInfo request;
5348 request.method = "POST";
bncb26024382016-06-29 02:39:455349 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325350 request.upload_data_stream = &upload_data_stream;
5351
bncd16676a2016-07-20 16:23:015352 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
5353 NULL);
mmenke666a6fea2015-12-19 04:16:335354 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:325355 helper.RunPreTestSetup();
5356
5357 HttpNetworkTransaction* trans = helper.trans();
5358
5359 TestCompletionCallback callback;
5360 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5361
robpercival214763f2016-07-01 23:27:015362 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325363
mmenke666a6fea2015-12-19 04:16:335364 data.RunUntilPaused();
5365 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325366
5367 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525368 ASSERT_TRUE(stream);
5369 ASSERT_TRUE(stream->stream());
bncbca843ba2016-07-14 13:05:485370 EXPECT_EQ(static_cast<int>(kDefaultInitialWindowSize) +
5371 kDeltaWindowSize * kDeltaCount -
5372 kMaxSpdyFrameChunkSize * kFrameCount,
5373 stream->stream()->send_window_size());
[email protected]d11b6912013-06-27 23:07:325374
mmenke666a6fea2015-12-19 04:16:335375 data.Resume();
5376 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325377
5378 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015379 EXPECT_THAT(rv, IsOk());
[email protected]d11b6912013-06-27 23:07:325380
5381 helper.VerifyDataConsumed();
5382}
5383
5384// Test that received data frames and sent WINDOW_UPDATE frames change
5385// the recv_window_size_ correctly.
bncd16676a2016-07-20 16:23:015386TEST_F(SpdyNetworkTransactionTest, WindowUpdateSent) {
bnc8f0f3b62015-04-08 04:37:235387 // Session level maximum window size that is more than twice the default
5388 // initial window size so that an initial window update is sent.
Avi Drissman13fc8932015-12-20 04:40:465389 const int32_t session_max_recv_window_size = 5 * 64 * 1024;
bncbca843ba2016-07-14 13:05:485390 ASSERT_LT(2 * kDefaultInitialWindowSize, session_max_recv_window_size);
bnc8f0f3b62015-04-08 04:37:235391 // Stream level maximum window size that is less than the session level
5392 // maximum window size so that we test for confusion between the two.
Avi Drissman13fc8932015-12-20 04:40:465393 const int32_t stream_max_recv_window_size = 4 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:235394 ASSERT_GT(session_max_recv_window_size, stream_max_recv_window_size);
5395 // Size of body to be sent. Has to be less than or equal to both window sizes
5396 // so that we do not run out of receiving window. Also has to be greater than
5397 // half of them so that it triggers both a session level and a stream level
5398 // window update frame.
Avi Drissman13fc8932015-12-20 04:40:465399 const int32_t kTargetSize = 3 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:235400 ASSERT_GE(session_max_recv_window_size, kTargetSize);
5401 ASSERT_GE(stream_max_recv_window_size, kTargetSize);
5402 ASSERT_LT(session_max_recv_window_size / 2, kTargetSize);
5403 ASSERT_LT(stream_max_recv_window_size / 2, kTargetSize);
5404 // Size of each DATA frame.
Avi Drissman13fc8932015-12-20 04:40:465405 const int32_t kChunkSize = 4096;
bnc8f0f3b62015-04-08 04:37:235406 // Size of window updates.
5407 ASSERT_EQ(0, session_max_recv_window_size / 2 % kChunkSize);
Avi Drissman13fc8932015-12-20 04:40:465408 const int32_t session_window_update_delta =
bnc8f0f3b62015-04-08 04:37:235409 session_max_recv_window_size / 2 + kChunkSize;
5410 ASSERT_EQ(0, stream_max_recv_window_size / 2 % kChunkSize);
Avi Drissman13fc8932015-12-20 04:40:465411 const int32_t stream_window_update_delta =
bnc8f0f3b62015-04-08 04:37:235412 stream_max_recv_window_size / 2 + kChunkSize;
[email protected]d11b6912013-06-27 23:07:325413
bnc8f0f3b62015-04-08 04:37:235414 SettingsMap initial_settings;
5415 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
5416 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
5417 initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
5418 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size);
bncdf80d44fd2016-07-15 20:27:415419 SpdySerializedFrame initial_settings_frame(
bnc8f0f3b62015-04-08 04:37:235420 spdy_util_.ConstructSpdySettings(initial_settings));
bncdf80d44fd2016-07-15 20:27:415421 SpdySerializedFrame initial_window_update(
bnc8f0f3b62015-04-08 04:37:235422 spdy_util_.ConstructSpdyWindowUpdate(
5423 kSessionFlowControlStreamId,
bncbca843ba2016-07-14 13:05:485424 session_max_recv_window_size - kDefaultInitialWindowSize));
bncdf80d44fd2016-07-15 20:27:415425 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:495426 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:415427 SpdySerializedFrame session_window_update(
bnc8f0f3b62015-04-08 04:37:235428 spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta));
bncdf80d44fd2016-07-15 20:27:415429 SpdySerializedFrame stream_window_update(
bnc8f0f3b62015-04-08 04:37:235430 spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta));
[email protected]d11b6912013-06-27 23:07:325431
5432 std::vector<MockWrite> writes;
bnca9b9e222016-07-11 20:10:405433 writes.push_back(MockWrite(ASYNC, kHttp2ConnectionHeaderPrefix,
5434 kHttp2ConnectionHeaderPrefixSize, 0));
bncdf80d44fd2016-07-15 20:27:415435 writes.push_back(CreateMockWrite(initial_settings_frame, writes.size()));
5436 writes.push_back(CreateMockWrite(initial_window_update, writes.size()));
5437 writes.push_back(CreateMockWrite(req, writes.size()));
[email protected]d11b6912013-06-27 23:07:325438
[email protected]251029e2014-03-19 06:04:405439 std::vector<MockRead> reads;
bnc42331402016-07-25 13:36:155440 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:415441 reads.push_back(CreateMockRead(resp, writes.size() + reads.size()));
[email protected]d11b6912013-06-27 23:07:325442
bncdf80d44fd2016-07-15 20:27:415443 std::vector<SpdySerializedFrame> body_frames;
bnc8f0f3b62015-04-08 04:37:235444 const std::string body_data(kChunkSize, 'x');
[email protected]251029e2014-03-19 06:04:405445 for (size_t remaining = kTargetSize; remaining != 0;) {
5446 size_t frame_size = std::min(remaining, body_data.size());
bncdf80d44fd2016-07-15 20:27:415447 body_frames.push_back(spdy_util_.ConstructSpdyDataFrame(1, body_data.data(),
5448 frame_size, false));
rchacdcbdc2015-05-16 17:16:005449 reads.push_back(
bncdf80d44fd2016-07-15 20:27:415450 CreateMockRead(body_frames.back(), writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:405451 remaining -= frame_size;
5452 }
mmenkee24011922015-12-17 22:12:595453 // Yield.
rchacdcbdc2015-05-16 17:16:005454 reads.push_back(
mmenkee24011922015-12-17 22:12:595455 MockRead(SYNCHRONOUS, ERR_IO_PENDING, writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:405456
rchacdcbdc2015-05-16 17:16:005457 writes.push_back(
bncdf80d44fd2016-07-15 20:27:415458 CreateMockWrite(session_window_update, writes.size() + reads.size()));
rchacdcbdc2015-05-16 17:16:005459 writes.push_back(
bncdf80d44fd2016-07-15 20:27:415460 CreateMockWrite(stream_window_update, writes.size() + reads.size()));
rchacdcbdc2015-05-16 17:16:005461
davidben5f8b6bc2015-11-25 03:19:545462 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
5463 writes.size());
[email protected]d11b6912013-06-27 23:07:325464
5465 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:015466 BoundNetLog(), NULL);
[email protected]d11b6912013-06-27 23:07:325467 helper.AddData(&data);
5468 helper.RunPreTestSetup();
[email protected]d11b6912013-06-27 23:07:325469
bnc8f0f3b62015-04-08 04:37:235470 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5471 SpdySessionPoolPeer pool_peer(spdy_session_pool);
5472 pool_peer.SetEnableSendingInitialData(true);
5473 pool_peer.SetSessionMaxRecvWindowSize(session_max_recv_window_size);
5474 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
5475
5476 HttpNetworkTransaction* trans = helper.trans();
[email protected]d11b6912013-06-27 23:07:325477 TestCompletionCallback callback;
5478 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5479
robpercival214763f2016-07-01 23:27:015480 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325481 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015482 EXPECT_THAT(rv, IsOk());
[email protected]d11b6912013-06-27 23:07:325483
5484 SpdyHttpStream* stream =
5485 static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525486 ASSERT_TRUE(stream);
5487 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:325488
[email protected]251029e2014-03-19 06:04:405489 // All data has been read, but not consumed. The window reflects this.
bnc8f0f3b62015-04-08 04:37:235490 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size - kTargetSize),
[email protected]251029e2014-03-19 06:04:405491 stream->stream()->recv_window_size());
[email protected]d11b6912013-06-27 23:07:325492
5493 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525494 ASSERT_TRUE(response);
5495 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025496 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d11b6912013-06-27 23:07:325497 EXPECT_TRUE(response->was_fetched_via_spdy);
5498
5499 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5500 // size increased to default.
bnc301745a2015-03-10 03:22:165501 scoped_refptr<IOBuffer> buf(new IOBuffer(kTargetSize));
[email protected]251029e2014-03-19 06:04:405502 EXPECT_EQ(static_cast<int>(kTargetSize),
5503 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
bnc8f0f3b62015-04-08 04:37:235504 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size),
[email protected]251029e2014-03-19 06:04:405505 stream->stream()->recv_window_size());
5506 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
[email protected]d11b6912013-06-27 23:07:325507
[email protected]251029e2014-03-19 06:04:405508 // Allow scheduled WINDOW_UPDATE frames to write.
[email protected]fc9d88472013-08-14 02:31:175509 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325510 helper.VerifyDataConsumed();
5511}
5512
5513// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
bncd16676a2016-07-20 16:23:015514TEST_F(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]d11b6912013-06-27 23:07:325515 // Number of full frames we hope to write (but will not, used to
5516 // set content-length header correctly)
5517 static int kFrameCount = 3;
5518
danakjaee3e1ec2016-04-16 00:23:185519 std::unique_ptr<std::string> content(
[email protected]d11b6912013-06-27 23:07:325520 new std::string(kMaxSpdyFrameChunkSize, 'a'));
bncdf80d44fd2016-07-15 20:27:415521 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455522 kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
bncdf80d44fd2016-07-15 20:27:415523 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555524 1, content->c_str(), content->size(), false));
bncdf80d44fd2016-07-15 20:27:415525 SpdySerializedFrame rst(
[email protected]d11b6912013-06-27 23:07:325526 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
5527
5528 // We're not going to write a data frame with FIN, we'll receive a bad
5529 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
5530 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415531 CreateMockWrite(req, 0), CreateMockWrite(body, 2),
5532 CreateMockWrite(rst, 3),
[email protected]d11b6912013-06-27 23:07:325533 };
5534
Avi Drissman13fc8932015-12-20 04:40:465535 static const int32_t kDeltaWindowSize = 0x7fffffff; // cause an overflow
bncdf80d44fd2016-07-15 20:27:415536 SpdySerializedFrame window_update(
[email protected]d11b6912013-06-27 23:07:325537 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5538 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415539 CreateMockRead(window_update, 1), MockRead(ASYNC, 0, 4) // EOF
[email protected]d11b6912013-06-27 23:07:325540 };
5541
mmenke666a6fea2015-12-19 04:16:335542 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d11b6912013-06-27 23:07:325543
danakjaee3e1ec2016-04-16 00:23:185544 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:325545 for (int i = 0; i < kFrameCount; ++i) {
danakjaee3e1ec2016-04-16 00:23:185546 element_readers.push_back(base::WrapUnique(
olli.raula6df48b2a2015-11-26 07:40:225547 new UploadBytesElementReader(content->c_str(), content->size())));
[email protected]d11b6912013-06-27 23:07:325548 }
olli.raula6df48b2a2015-11-26 07:40:225549 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325550
5551 // Setup the request
5552 HttpRequestInfo request;
5553 request.method = "POST";
bncb26024382016-06-29 02:39:455554 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325555 request.upload_data_stream = &upload_data_stream;
5556
bncd16676a2016-07-20 16:23:015557 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
5558 NULL);
[email protected]d11b6912013-06-27 23:07:325559 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:335560 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:325561 HttpNetworkTransaction* trans = helper.trans();
5562
5563 TestCompletionCallback callback;
5564 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015565 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325566
mmenke666a6fea2015-12-19 04:16:335567 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325568 ASSERT_TRUE(callback.have_result());
robpercival214763f2016-07-01 23:27:015569 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d11b6912013-06-27 23:07:325570 helper.VerifyDataConsumed();
5571}
5572
5573// Test that after hitting a send window size of 0, the write process
5574// stalls and upon receiving WINDOW_UPDATE frame write resumes.
5575
5576// This test constructs a POST request followed by enough data frames
5577// containing 'a' that would make the window size 0, followed by another
5578// data frame containing default content (which is "hello!") and this frame
rchacdcbdc2015-05-16 17:16:005579// also contains a FIN flag. SequencedSocketData is used to enforce all
5580// writes, save the last, go through before a read could happen. The last frame
5581// ("hello!") is not permitted to go through since by the time its turn
[email protected]d11b6912013-06-27 23:07:325582// arrives, window size is 0. At this point MessageLoop::Run() called via
5583// callback would block. Therefore we call MessageLoop::RunUntilIdle()
5584// which returns after performing all possible writes. We use DCHECKS to
5585// ensure that last data frame is still there and stream has stalled.
5586// After that, next read is artifically enforced, which causes a
5587// WINDOW_UPDATE to be read and I/O process resumes.
bncd16676a2016-07-20 16:23:015588TEST_F(SpdyNetworkTransactionTest, FlowControlStallResume) {
bncbca843ba2016-07-14 13:05:485589 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:455590 // Number of upload data buffers we need to send to zero out the window size
5591 // is the minimal number of upload buffers takes to be bigger than
5592 // |initial_window_size|.
5593 size_t num_upload_buffers =
5594 ceil(static_cast<double>(initial_window_size) / kBufferSize);
5595 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
5596 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
5597 // which has kBufferSize % kMaxSpdyChunkSize bytes.
5598 size_t num_frames_in_one_upload_buffer =
5599 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:325600
5601 // Construct content for a data frame of maximum size.
5602 std::string content(kMaxSpdyFrameChunkSize, 'a');
5603
bncdf80d44fd2016-07-15 20:27:415604 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455605 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:455606 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
5607 LOWEST, NULL, 0));
[email protected]d11b6912013-06-27 23:07:325608
5609 // Full frames.
bncdf80d44fd2016-07-15 20:27:415610 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555611 1, content.c_str(), content.size(), false));
[email protected]d11b6912013-06-27 23:07:325612
xunjieli179a6e72016-04-26 19:47:455613 // Last frame in each upload data buffer.
bncdf80d44fd2016-07-15 20:27:415614 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455615 1, content.c_str(), kBufferSize % kMaxSpdyFrameChunkSize, false));
[email protected]d11b6912013-06-27 23:07:325616
xunjieli179a6e72016-04-26 19:47:455617 // The very last frame before the stalled frames.
bncdf80d44fd2016-07-15 20:27:415618 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455619 1, content.c_str(),
5620 initial_window_size % kBufferSize % kMaxSpdyFrameChunkSize, false));
5621
5622 // Data frames to be sent once WINDOW_UPDATE frame is received.
5623
5624 // If kBufferSize * num_upload_buffers > initial_window_size,
5625 // we need one additional frame to send the rest of 'a'.
5626 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
5627 'a');
bncdf80d44fd2016-07-15 20:27:415628 SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455629 1, last_body.c_str(), last_body.size(), false));
5630
5631 // Also send a "hello!" after WINDOW_UPDATE.
bncdf80d44fd2016-07-15 20:27:415632 SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:325633
5634 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:325635 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:455636 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:415637 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:455638 for (size_t j = 0; j < num_upload_buffers; j++) {
5639 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
5640 if (k == num_frames_in_one_upload_buffer - 1 &&
5641 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
5642 if (j == num_upload_buffers - 1 &&
5643 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:415644 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:455645 } else {
bncdf80d44fd2016-07-15 20:27:415646 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:455647 }
5648 } else {
bncdf80d44fd2016-07-15 20:27:415649 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:455650 }
5651 }
5652 }
[email protected]d11b6912013-06-27 23:07:325653
xunjieli179a6e72016-04-26 19:47:455654 // Fill in mock reads.
5655 std::vector<MockRead> reads;
5656 // Force a pause.
5657 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
5658 // Construct read frame for window updates that gives enough space to upload
5659 // the rest of the data.
bncdf80d44fd2016-07-15 20:27:415660 SpdySerializedFrame session_window_update(
xunjieli179a6e72016-04-26 19:47:455661 spdy_util_.ConstructSpdyWindowUpdate(0,
5662 kUploadDataSize + last_body.size()));
bncdf80d44fd2016-07-15 20:27:415663 SpdySerializedFrame window_update(spdy_util_.ConstructSpdyWindowUpdate(
5664 1, kUploadDataSize + last_body.size()));
xunjieli179a6e72016-04-26 19:47:455665
bncdf80d44fd2016-07-15 20:27:415666 reads.push_back(CreateMockRead(session_window_update, i++));
5667 reads.push_back(CreateMockRead(window_update, i++));
xunjieli179a6e72016-04-26 19:47:455668
5669 // Stalled frames which can be sent after receiving window updates.
5670 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:415671 writes.push_back(CreateMockWrite(body4, i++));
5672 writes.push_back(CreateMockWrite(body5, i++));
xunjieli179a6e72016-04-26 19:47:455673
bnc42331402016-07-25 13:36:155674 SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(NULL, 0));
bncdf80d44fd2016-07-15 20:27:415675 reads.push_back(CreateMockRead(reply, i++));
5676 reads.push_back(CreateMockRead(body2, i++));
5677 reads.push_back(CreateMockRead(body5, i++));
xunjieli179a6e72016-04-26 19:47:455678 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
[email protected]d11b6912013-06-27 23:07:325679
xunjieli179a6e72016-04-26 19:47:455680 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
5681 writes.size());
[email protected]d11b6912013-06-27 23:07:325682
danakjaee3e1ec2016-04-16 00:23:185683 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
xunjieli179a6e72016-04-26 19:47:455684 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:325685 upload_data_string.append(kUploadData, kUploadDataSize);
danakjaee3e1ec2016-04-16 00:23:185686 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader(
olli.raula6df48b2a2015-11-26 07:40:225687 upload_data_string.c_str(), upload_data_string.size())));
5688 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325689
5690 HttpRequestInfo request;
5691 request.method = "POST";
bncb26024382016-06-29 02:39:455692 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325693 request.upload_data_stream = &upload_data_stream;
xunjieli179a6e72016-04-26 19:47:455694 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:015695 NULL);
[email protected]d11b6912013-06-27 23:07:325696 helper.AddData(&data);
5697 helper.RunPreTestSetup();
5698
5699 HttpNetworkTransaction* trans = helper.trans();
5700
5701 TestCompletionCallback callback;
5702 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015703 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325704
[email protected]fc9d88472013-08-14 02:31:175705 base::RunLoop().RunUntilIdle(); // Write as much as we can.
[email protected]d11b6912013-06-27 23:07:325706
5707 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525708 ASSERT_TRUE(stream);
5709 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:325710 EXPECT_EQ(0, stream->stream()->send_window_size());
xunjieli179a6e72016-04-26 19:47:455711 if (initial_window_size % kBufferSize != 0) {
5712 // If it does not take whole number of full upload buffer to zero out
5713 // initial window size, then the upload data is not at EOF, because the
5714 // last read must be stalled.
5715 EXPECT_FALSE(upload_data_stream.IsEOF());
5716 } else {
5717 // All the body data should have been read.
5718 // TODO(satorux): This is because of the weirdness in reading the request
5719 // body in OnSendBodyComplete(). See crbug.com/113107.
5720 EXPECT_TRUE(upload_data_stream.IsEOF());
5721 }
[email protected]d11b6912013-06-27 23:07:325722 // But the body is not yet fully sent (kUploadData is not yet sent)
5723 // since we're send-stalled.
5724 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
5725
mmenkee24011922015-12-17 22:12:595726 data.Resume(); // Read in WINDOW_UPDATE frame.
[email protected]d11b6912013-06-27 23:07:325727 rv = callback.WaitForResult();
5728 helper.VerifyDataConsumed();
5729}
5730
5731// Test we correctly handle the case where the SETTINGS frame results in
5732// unstalling the send window.
bncd16676a2016-07-20 16:23:015733TEST_F(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
bncbca843ba2016-07-14 13:05:485734 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:455735 // Number of upload data buffers we need to send to zero out the window size
5736 // is the minimal number of upload buffers takes to be bigger than
5737 // |initial_window_size|.
5738 size_t num_upload_buffers =
5739 ceil(static_cast<double>(initial_window_size) / kBufferSize);
5740 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
5741 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
5742 // which has kBufferSize % kMaxSpdyChunkSize bytes.
5743 size_t num_frames_in_one_upload_buffer =
5744 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:325745
5746 // Construct content for a data frame of maximum size.
5747 std::string content(kMaxSpdyFrameChunkSize, 'a');
5748
bncdf80d44fd2016-07-15 20:27:415749 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455750 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:455751 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
5752 LOWEST, NULL, 0));
[email protected]d11b6912013-06-27 23:07:325753
5754 // Full frames.
bncdf80d44fd2016-07-15 20:27:415755 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555756 1, content.c_str(), content.size(), false));
[email protected]d11b6912013-06-27 23:07:325757
xunjieli179a6e72016-04-26 19:47:455758 // Last frame in each upload data buffer.
bncdf80d44fd2016-07-15 20:27:415759 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455760 1, content.c_str(), kBufferSize % kMaxSpdyFrameChunkSize, false));
[email protected]d11b6912013-06-27 23:07:325761
xunjieli179a6e72016-04-26 19:47:455762 // The very last frame before the stalled frames.
bncdf80d44fd2016-07-15 20:27:415763 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455764 1, content.c_str(),
5765 initial_window_size % kBufferSize % kMaxSpdyFrameChunkSize, false));
5766
5767 // Data frames to be sent once WINDOW_UPDATE frame is received.
5768
5769 // If kBufferSize * num_upload_buffers > initial_window_size,
5770 // we need one additional frame to send the rest of 'a'.
5771 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
5772 'a');
bncdf80d44fd2016-07-15 20:27:415773 SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455774 1, last_body.c_str(), last_body.size(), false));
5775
5776 // Also send a "hello!" after WINDOW_UPDATE.
bncdf80d44fd2016-07-15 20:27:415777 SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:325778
xunjieli179a6e72016-04-26 19:47:455779 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:325780 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:455781 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:415782 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:455783 for (size_t j = 0; j < num_upload_buffers; j++) {
5784 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
5785 if (k == num_frames_in_one_upload_buffer - 1 &&
5786 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
5787 if (j == num_upload_buffers - 1 &&
5788 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:415789 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:455790 } else {
bncdf80d44fd2016-07-15 20:27:415791 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:455792 }
5793 } else {
bncdf80d44fd2016-07-15 20:27:415794 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:455795 }
5796 }
5797 }
[email protected]d11b6912013-06-27 23:07:325798
xunjieli179a6e72016-04-26 19:47:455799 // Fill in mock reads.
5800 std::vector<MockRead> reads;
5801 // Force a pause.
mmenke666a6fea2015-12-19 04:16:335802 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
5803
[email protected]d11b6912013-06-27 23:07:325804 // Construct read frame for SETTINGS that gives enough space to upload the
5805 // rest of the data.
5806 SettingsMap settings;
5807 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:195808 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
bncdf80d44fd2016-07-15 20:27:415809 SpdySerializedFrame settings_frame_large(
[email protected]d11b6912013-06-27 23:07:325810 spdy_util_.ConstructSpdySettings(settings));
5811
bncdf80d44fd2016-07-15 20:27:415812 reads.push_back(CreateMockRead(settings_frame_large, i++));
[email protected]d11b6912013-06-27 23:07:325813
bncdf80d44fd2016-07-15 20:27:415814 SpdySerializedFrame session_window_update(
xunjieli179a6e72016-04-26 19:47:455815 spdy_util_.ConstructSpdyWindowUpdate(0,
5816 last_body.size() + kUploadDataSize));
bncdf80d44fd2016-07-15 20:27:415817 reads.push_back(CreateMockRead(session_window_update, i++));
[email protected]d11b6912013-06-27 23:07:325818
bncdf80d44fd2016-07-15 20:27:415819 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
5820 writes.push_back(CreateMockWrite(settings_ack, i++));
[email protected]d4a77c12014-05-15 20:45:215821
xunjieli179a6e72016-04-26 19:47:455822 // Stalled frames which can be sent after |settings_ack|.
5823 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:415824 writes.push_back(CreateMockWrite(body4, i++));
5825 writes.push_back(CreateMockWrite(body5, i++));
[email protected]d11b6912013-06-27 23:07:325826
bnc42331402016-07-25 13:36:155827 SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(NULL, 0));
bncdf80d44fd2016-07-15 20:27:415828 reads.push_back(CreateMockRead(reply, i++));
5829 reads.push_back(CreateMockRead(body2, i++));
5830 reads.push_back(CreateMockRead(body5, i++));
[email protected]d11b6912013-06-27 23:07:325831 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
5832
5833 // Force all writes to happen before any read, last write will not
5834 // actually queue a frame, due to window size being 0.
mmenke666a6fea2015-12-19 04:16:335835 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
5836 writes.size());
[email protected]d11b6912013-06-27 23:07:325837
danakjaee3e1ec2016-04-16 00:23:185838 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
xunjieli179a6e72016-04-26 19:47:455839 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:325840 upload_data_string.append(kUploadData, kUploadDataSize);
danakjaee3e1ec2016-04-16 00:23:185841 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader(
olli.raula6df48b2a2015-11-26 07:40:225842 upload_data_string.c_str(), upload_data_string.size())));
5843 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325844
5845 HttpRequestInfo request;
5846 request.method = "POST";
bncb26024382016-06-29 02:39:455847 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325848 request.upload_data_stream = &upload_data_stream;
bncd16676a2016-07-20 16:23:015849 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
5850 NULL);
[email protected]d11b6912013-06-27 23:07:325851 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:335852 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:325853
5854 HttpNetworkTransaction* trans = helper.trans();
5855
5856 TestCompletionCallback callback;
5857 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325859
mmenke666a6fea2015-12-19 04:16:335860 data.RunUntilPaused(); // Write as much as we can.
5861 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325862
5863 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525864 ASSERT_TRUE(stream);
5865 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:325866 EXPECT_EQ(0, stream->stream()->send_window_size());
5867
xunjieli179a6e72016-04-26 19:47:455868 if (initial_window_size % kBufferSize != 0) {
5869 // If it does not take whole number of full upload buffer to zero out
5870 // initial window size, then the upload data is not at EOF, because the
5871 // last read must be stalled.
5872 EXPECT_FALSE(upload_data_stream.IsEOF());
5873 } else {
5874 // All the body data should have been read.
5875 // TODO(satorux): This is because of the weirdness in reading the request
5876 // body in OnSendBodyComplete(). See crbug.com/113107.
5877 EXPECT_TRUE(upload_data_stream.IsEOF());
5878 }
[email protected]d11b6912013-06-27 23:07:325879 // But the body is not yet fully sent (kUploadData is not yet sent)
5880 // since we're send-stalled.
5881 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
5882
mmenke666a6fea2015-12-19 04:16:335883 // Read in SETTINGS frame to unstall.
5884 data.Resume();
5885 base::RunLoop().RunUntilIdle();
5886
[email protected]d11b6912013-06-27 23:07:325887 rv = callback.WaitForResult();
5888 helper.VerifyDataConsumed();
5889 // If stream is NULL, that means it was unstalled and closed.
5890 EXPECT_TRUE(stream->stream() == NULL);
5891}
5892
5893// Test we correctly handle the case where the SETTINGS frame results in a
5894// negative send window size.
bncd16676a2016-07-20 16:23:015895TEST_F(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
bncbca843ba2016-07-14 13:05:485896 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:455897 // Number of upload data buffers we need to send to zero out the window size
5898 // is the minimal number of upload buffers takes to be bigger than
5899 // |initial_window_size|.
5900 size_t num_upload_buffers =
5901 ceil(static_cast<double>(initial_window_size) / kBufferSize);
5902 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
5903 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
5904 // which has kBufferSize % kMaxSpdyChunkSize bytes.
5905 size_t num_frames_in_one_upload_buffer =
5906 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:325907
5908 // Construct content for a data frame of maximum size.
5909 std::string content(kMaxSpdyFrameChunkSize, 'a');
5910
bncdf80d44fd2016-07-15 20:27:415911 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455912 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:455913 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
5914 LOWEST, NULL, 0));
[email protected]d11b6912013-06-27 23:07:325915
5916 // Full frames.
bncdf80d44fd2016-07-15 20:27:415917 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555918 1, content.c_str(), content.size(), false));
[email protected]d11b6912013-06-27 23:07:325919
xunjieli179a6e72016-04-26 19:47:455920 // Last frame in each upload data buffer.
bncdf80d44fd2016-07-15 20:27:415921 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455922 1, content.c_str(), kBufferSize % kMaxSpdyFrameChunkSize, false));
[email protected]d11b6912013-06-27 23:07:325923
xunjieli179a6e72016-04-26 19:47:455924 // The very last frame before the stalled frames.
bncdf80d44fd2016-07-15 20:27:415925 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455926 1, content.c_str(),
5927 initial_window_size % kBufferSize % kMaxSpdyFrameChunkSize, false));
5928
5929 // Data frames to be sent once WINDOW_UPDATE frame is received.
5930
5931 // If kBufferSize * num_upload_buffers > initial_window_size,
5932 // we need one additional frame to send the rest of 'a'.
5933 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
5934 'a');
bncdf80d44fd2016-07-15 20:27:415935 SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455936 1, last_body.c_str(), last_body.size(), false));
5937
5938 // Also send a "hello!" after WINDOW_UPDATE.
bncdf80d44fd2016-07-15 20:27:415939 SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:325940
xunjieli179a6e72016-04-26 19:47:455941 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:325942 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:455943 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:415944 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:455945 for (size_t j = 0; j < num_upload_buffers; j++) {
5946 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
5947 if (k == num_frames_in_one_upload_buffer - 1 &&
5948 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
5949 if (j == num_upload_buffers - 1 &&
5950 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:415951 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:455952 } else {
bncdf80d44fd2016-07-15 20:27:415953 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:455954 }
5955 } else {
bncdf80d44fd2016-07-15 20:27:415956 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:455957 }
5958 }
5959 }
[email protected]d11b6912013-06-27 23:07:325960
xunjieli179a6e72016-04-26 19:47:455961 // Fill in mock reads.
5962 std::vector<MockRead> reads;
5963 // Force a pause.
mmenke666a6fea2015-12-19 04:16:335964 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
[email protected]d11b6912013-06-27 23:07:325965 // Construct read frame for SETTINGS that makes the send_window_size
5966 // negative.
5967 SettingsMap new_settings;
5968 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:195969 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
bncdf80d44fd2016-07-15 20:27:415970 SpdySerializedFrame settings_frame_small(
[email protected]d11b6912013-06-27 23:07:325971 spdy_util_.ConstructSpdySettings(new_settings));
5972 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
5973 // positive.
bncdf80d44fd2016-07-15 20:27:415974 SpdySerializedFrame session_window_update_init_size(
bnc2f54c832014-12-01 13:31:195975 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
bncdf80d44fd2016-07-15 20:27:415976 SpdySerializedFrame window_update_init_size(
bnc2f54c832014-12-01 13:31:195977 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
[email protected]d11b6912013-06-27 23:07:325978
bncdf80d44fd2016-07-15 20:27:415979 reads.push_back(CreateMockRead(settings_frame_small, i++));
5980 reads.push_back(CreateMockRead(session_window_update_init_size, i++));
5981 reads.push_back(CreateMockRead(window_update_init_size, i++));
[email protected]d11b6912013-06-27 23:07:325982
bncdf80d44fd2016-07-15 20:27:415983 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
5984 writes.push_back(CreateMockWrite(settings_ack, i++));
[email protected]d4a77c12014-05-15 20:45:215985
xunjieli179a6e72016-04-26 19:47:455986 // Stalled frames which can be sent after |settings_ack|.
5987 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:415988 writes.push_back(CreateMockWrite(body4, i++));
5989 writes.push_back(CreateMockWrite(body5, i++));
[email protected]d11b6912013-06-27 23:07:325990
bnc42331402016-07-25 13:36:155991 SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(NULL, 0));
bncdf80d44fd2016-07-15 20:27:415992 reads.push_back(CreateMockRead(reply, i++));
5993 reads.push_back(CreateMockRead(body2, i++));
5994 reads.push_back(CreateMockRead(body5, i++));
[email protected]d11b6912013-06-27 23:07:325995 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
5996
5997 // Force all writes to happen before any read, last write will not
5998 // actually queue a frame, due to window size being 0.
mmenke666a6fea2015-12-19 04:16:335999 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
6000 writes.size());
[email protected]d11b6912013-06-27 23:07:326001
danakjaee3e1ec2016-04-16 00:23:186002 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
xunjieli179a6e72016-04-26 19:47:456003 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:326004 upload_data_string.append(kUploadData, kUploadDataSize);
danakjaee3e1ec2016-04-16 00:23:186005 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader(
olli.raula6df48b2a2015-11-26 07:40:226006 upload_data_string.c_str(), upload_data_string.size())));
6007 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326008
6009 HttpRequestInfo request;
6010 request.method = "POST";
bncb26024382016-06-29 02:39:456011 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:326012 request.upload_data_stream = &upload_data_stream;
bncd16676a2016-07-20 16:23:016013 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
6014 NULL);
[email protected]d11b6912013-06-27 23:07:326015 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:336016 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:326017
6018 HttpNetworkTransaction* trans = helper.trans();
6019
6020 TestCompletionCallback callback;
6021 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016022 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:326023
mmenke666a6fea2015-12-19 04:16:336024 data.RunUntilPaused(); // Write as much as we can.
6025 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326026
6027 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:526028 ASSERT_TRUE(stream);
6029 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:326030 EXPECT_EQ(0, stream->stream()->send_window_size());
6031
xunjieli179a6e72016-04-26 19:47:456032 if (initial_window_size % kBufferSize != 0) {
6033 // If it does not take whole number of full upload buffer to zero out
6034 // initial window size, then the upload data is not at EOF, because the
6035 // last read must be stalled.
6036 EXPECT_FALSE(upload_data_stream.IsEOF());
6037 } else {
6038 // All the body data should have been read.
6039 // TODO(satorux): This is because of the weirdness in reading the request
6040 // body in OnSendBodyComplete(). See crbug.com/113107.
6041 EXPECT_TRUE(upload_data_stream.IsEOF());
6042 }
[email protected]d11b6912013-06-27 23:07:326043
6044 // Read in WINDOW_UPDATE or SETTINGS frame.
mmenke666a6fea2015-12-19 04:16:336045 data.Resume();
6046 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326047 rv = callback.WaitForResult();
6048 helper.VerifyDataConsumed();
6049}
6050
bncd16676a2016-07-20 16:23:016051TEST_F(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
bnc086b39e12016-06-24 13:05:266052 SpdyHeaderBlock push_headers;
6053 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat", &push_headers);
bncdf80d44fd2016-07-15 20:27:416054 SpdySerializedFrame push(
dchengc7eeda422015-12-26 03:56:486055 spdy_util_.ConstructInitialSpdyPushFrame(std::move(push_headers), 3, 1));
bncdf80d44fd2016-07-15 20:27:416056 MockRead reads[] = {CreateMockRead(push, 1)};
baranovich212a1292014-09-02 21:45:316057
bncdf80d44fd2016-07-15 20:27:416058 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:496059 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:416060 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
baranovich212a1292014-09-02 21:45:316061 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6062 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416063 CreateMockWrite(req, 0), CreateMockWrite(goaway, 2),
baranovich212a1292014-09-02 21:45:316064 };
6065
rch08e3aa3e2015-05-16 14:27:526066 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:016067 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6068 BoundNetLog(), NULL);
baranovich212a1292014-09-02 21:45:316069 helper.RunToCompletion(&data);
6070 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:016071 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
baranovich212a1292014-09-02 21:45:316072}
6073
bncd16676a2016-07-20 16:23:016074TEST_F(SpdyNetworkTransactionTest,
baranovich212a1292014-09-02 21:45:316075 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
bncdf80d44fd2016-07-15 20:27:416076 SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:006077 NULL, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
bnc086b39e12016-06-24 13:05:266078 SpdyHeaderBlock push_b_headers;
rchebf12982015-04-10 01:15:006079 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/b.dat"),
bnc086b39e12016-06-24 13:05:266080 &push_b_headers);
bncdf80d44fd2016-07-15 20:27:416081 SpdySerializedFrame push_b(spdy_util_.ConstructInitialSpdyPushFrame(
6082 std::move(push_b_headers), 2, 1));
baranovich212a1292014-09-02 21:45:316083 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416084 CreateMockRead(push_a, 1), CreateMockRead(push_b, 2),
baranovich212a1292014-09-02 21:45:316085 };
6086
bncdf80d44fd2016-07-15 20:27:416087 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:496088 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:416089 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bncb03b1092016-04-06 11:19:556090 4, GOAWAY_PROTOCOL_ERROR,
baranovich212a1292014-09-02 21:45:316091 "New push stream id must be greater than the last accepted."));
6092 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416093 CreateMockWrite(req, 0), CreateMockWrite(goaway, 3),
baranovich212a1292014-09-02 21:45:316094 };
6095
rch08e3aa3e2015-05-16 14:27:526096 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:016097 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6098 BoundNetLog(), NULL);
baranovich212a1292014-09-02 21:45:316099 helper.RunToCompletion(&data);
6100 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:016101 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
baranovich212a1292014-09-02 21:45:316102}
6103
bnc76598ab2015-06-29 12:43:076104// Regression test for https://crbug.com/493348: request header exceeds 16 kB
6105// and thus sent in multiple frames when using HTTP/2.
bncd16676a2016-07-20 16:23:016106TEST_F(SpdyNetworkTransactionTest, LargeRequest) {
bnc76598ab2015-06-29 12:43:076107 const std::string kKey("foo");
6108 const std::string kValue(1 << 15, 'z');
6109
6110 HttpRequestInfo request;
6111 request.method = "GET";
bncb26024382016-06-29 02:39:456112 request.url = default_url_;
bnc76598ab2015-06-29 12:43:076113 request.extra_headers.SetHeader(kKey, kValue);
6114
bncb26024382016-06-29 02:39:456115 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc086b39e12016-06-24 13:05:266116 headers[kKey] = kValue;
bncdf80d44fd2016-07-15 20:27:416117 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:156118 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bnc76598ab2015-06-29 12:43:076119 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416120 CreateMockWrite(req, 0),
bnc76598ab2015-06-29 12:43:076121 };
6122
bnc42331402016-07-25 13:36:156123 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:416124 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc76598ab2015-06-29 12:43:076125 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416126 CreateMockRead(resp, 1), CreateMockRead(body, 2),
bnc76598ab2015-06-29 12:43:076127 MockRead(ASYNC, 0, 3) // EOF
6128 };
6129
6130 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6131 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:016132 nullptr);
bnc76598ab2015-06-29 12:43:076133 helper.RunToCompletion(&data);
6134 TransactionHelperResult out = helper.output();
6135
robpercival214763f2016-07-01 23:27:016136 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:026137 EXPECT_EQ("HTTP/1.1 200", out.status_line);
bnc76598ab2015-06-29 12:43:076138 EXPECT_EQ("hello!", out.response_data);
6139}
6140
bncd67383342016-01-08 21:58:436141// Regression test for https://crbug.com/535629: response header exceeds 16 kB.
bncd16676a2016-07-20 16:23:016142TEST_F(SpdyNetworkTransactionTest, LargeResponseHeader) {
bncb26024382016-06-29 02:39:456143 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bncdf80d44fd2016-07-15 20:27:416144 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:156145 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bncd67383342016-01-08 21:58:436146 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416147 CreateMockWrite(req, 0),
bncd67383342016-01-08 21:58:436148 };
6149
6150 // HPACK decoder implementation limits string literal length to 16 kB.
6151 const char* response_headers[2];
6152 const std::string kKey(16 * 1024, 'a');
6153 response_headers[0] = kKey.data();
6154 const std::string kValue(16 * 1024, 'b');
6155 response_headers[1] = kValue.data();
6156
bncdf80d44fd2016-07-15 20:27:416157 SpdySerializedFrame resp(
bnc42331402016-07-25 13:36:156158 spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1));
bncdf80d44fd2016-07-15 20:27:416159 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bncd67383342016-01-08 21:58:436160 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416161 CreateMockRead(resp, 1), CreateMockRead(body, 2),
bncd67383342016-01-08 21:58:436162 MockRead(ASYNC, 0, 3) // EOF
6163 };
6164
6165 HttpRequestInfo request;
6166 request.method = "GET";
bncb26024382016-06-29 02:39:456167 request.url = default_url_;
bncd67383342016-01-08 21:58:436168 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:016169 nullptr);
bncd67383342016-01-08 21:58:436170
6171 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6172 helper.RunToCompletion(&data);
6173 TransactionHelperResult out = helper.output();
6174
robpercival214763f2016-07-01 23:27:016175 EXPECT_THAT(out.rv, IsOk());
bncd67383342016-01-08 21:58:436176 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6177 EXPECT_EQ("hello!", out.response_data);
6178 ASSERT_TRUE(out.response_info.headers->HasHeaderValue(kKey, kValue));
6179}
6180
bnc204a6d02016-08-01 14:34:276181// End of line delimiter is forbidden according to RFC 7230 Section 3.2.
6182TEST_F(SpdyNetworkTransactionTest, CRLFInHeaderValue) {
6183 SpdySerializedFrame req(
6184 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
6185 SpdySerializedFrame rst(
6186 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
6187 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 2)};
6188
6189 const char* response_headers[] = {"folded", "foo\r\nbar"};
6190 SpdySerializedFrame resp(
6191 spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1));
6192 MockRead reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3)};
6193
6194 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6195
6196 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6197 BoundNetLog(), nullptr);
6198 helper.RunToCompletion(&data);
6199 TransactionHelperResult out = helper.output();
6200
6201 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
6202}
6203
[email protected]514aeaf2014-05-23 10:31:516204class SpdyNetworkTransactionTLSUsageCheckTest
6205 : public SpdyNetworkTransactionTest {
6206 protected:
danakjaee3e1ec2016-04-16 00:23:186207 void RunTLSUsageCheckTest(
6208 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
bncdf80d44fd2016-07-15 20:27:416209 SpdySerializedFrame goaway(
[email protected]bdd1b222014-06-10 11:08:396210 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
bncdf80d44fd2016-07-15 20:27:416211 MockWrite writes[] = {CreateMockWrite(goaway)};
[email protected]514aeaf2014-05-23 10:31:516212
rch08e3aa3e2015-05-16 14:27:526213 StaticSocketDataProvider data(NULL, 0, writes, arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516214 HttpRequestInfo request;
6215 request.method = "GET";
bncb26024382016-06-29 02:39:456216 request.url = default_url_;
bncd16676a2016-07-20 16:23:016217 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
6218 NULL);
dchengc7eeda422015-12-26 03:56:486219 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516220 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:016221 EXPECT_THAT(out.rv, IsError(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
[email protected]514aeaf2014-05-23 10:31:516222 }
6223};
6224
bncd16676a2016-07-20 16:23:016225TEST_F(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
danakjaee3e1ec2016-04-16 00:23:186226 std::unique_ptr<SSLSocketDataProvider> ssl_provider(
[email protected]514aeaf2014-05-23 10:31:516227 new SSLSocketDataProvider(ASYNC, OK));
6228 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6229 &ssl_provider->connection_status);
6230
dchengc7eeda422015-12-26 03:56:486231 RunTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516232}
6233
bncd16676a2016-07-20 16:23:016234TEST_F(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
danakjaee3e1ec2016-04-16 00:23:186235 std::unique_ptr<SSLSocketDataProvider> ssl_provider(
[email protected]514aeaf2014-05-23 10:31:516236 new SSLSocketDataProvider(ASYNC, OK));
6237 // Set to TLS_RSA_WITH_NULL_MD5
6238 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6239
dchengc7eeda422015-12-26 03:56:486240 RunTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516241}
6242
[email protected]aea80602009-09-18 00:55:086243} // namespace net