blob: 6d4e264ff9833bf773773de999a3c23c1da21dee [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"
mikecirone8b85c432016-09-08 19:11:0033#include "net/log/net_log_event_type.h"
mmenke16a7cbdd2015-04-24 23:00:5634#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4635#include "net/log/test_net_log_entry.h"
36#include "net/log/test_net_log_util.h"
tbansal28e68f82016-02-04 02:56:1537#include "net/proxy/proxy_server.h"
[email protected]2d6728692011-03-12 01:39:5538#include "net/socket/client_socket_pool_base.h"
[email protected]bb88e1d32013-05-03 23:11:0739#include "net/socket/next_proto.h"
[email protected]f54c85792012-03-08 19:06:4140#include "net/spdy/buffered_spdy_framer.h"
[email protected]9be804c82010-06-24 17:59:4641#include "net/spdy/spdy_http_stream.h"
[email protected]9e1bdd32011-02-03 21:48:3442#include "net/spdy/spdy_http_utils.h"
[email protected]bdebd1b2010-08-09 20:18:0843#include "net/spdy/spdy_session.h"
[email protected]19ec8a72010-08-23 03:38:2344#include "net/spdy/spdy_session_pool.h"
[email protected]86aa87b2013-02-15 01:10:0345#include "net/spdy/spdy_test_util_common.h"
[email protected]a4bfdf72013-02-22 04:06:1646#include "net/spdy/spdy_test_utils.h"
[email protected]514aeaf2014-05-23 10:31:5147#include "net/ssl/ssl_connection_status_flags.h"
bncce36dca22015-04-21 22:11:2348#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0149#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4350#include "net/test/test_data_directory.h"
[email protected]d2db0292011-01-26 20:23:4451#include "net/url_request/url_request_test_util.h"
[email protected]251029e2014-03-19 06:04:4052#include "testing/gmock/include/gmock/gmock.h"
[email protected]aea80602009-09-18 00:55:0853#include "testing/platform_test.h"
54
robpercival214763f2016-07-01 23:27:0155using net::test::IsError;
56using net::test::IsOk;
57
[email protected]aea80602009-09-18 00:55:0858//-----------------------------------------------------------------------------
59
[email protected]d1eda932009-11-04 01:03:1060namespace net {
[email protected]dae22c52010-07-30 02:16:3561
[email protected]cbdd73162013-03-18 23:27:3362namespace {
[email protected]251029e2014-03-19 06:04:4063
64using testing::Each;
65using testing::Eq;
66
xunjieli179a6e72016-04-26 19:47:4567const int32_t kBufferSize = SpdyHttpStream::kRequestBodyBufferSize;
68
[email protected]513963e2013-06-15 01:53:0469} // namespace
70
bncd16676a2016-07-20 16:23:0171class SpdyNetworkTransactionTest : public ::testing::Test {
[email protected]34437af82009-11-06 02:28:4972 protected:
rdsmithebb50aa2015-11-12 03:44:3873 SpdyNetworkTransactionTest()
bncb26024382016-06-29 02:39:4574 : default_url_(kDefaultUrl),
bncd16676a2016-07-20 16:23:0175 host_port_pair_(HostPortPair::FromURL(default_url_)) {}
[email protected]2d6728692011-03-12 01:39:5576
bncd16676a2016-07-20 16:23:0177 ~SpdyNetworkTransactionTest() override {
mmenkecbc2b712014-10-09 20:29:0778 // UploadDataStream may post a deletion tasks back to the message loop on
[email protected]fc9d88472013-08-14 02:31:1779 // destruction.
80 upload_data_stream_.reset();
81 base::RunLoop().RunUntilIdle();
82 }
83
dcheng67be2b1f2014-10-27 21:47:2984 void SetUp() override {
bncce36dca22015-04-21 22:11:2385 get_request_initialized_ = false;
86 post_request_initialized_ = false;
87 chunked_post_request_initialized_ = false;
[email protected]69e6b4a2012-10-18 08:03:0188 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]aea80602009-09-18 00:55:0889 }
90
[email protected]72552f02009-10-28 15:25:0191 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:0892 int rv;
93 std::string status_line;
94 std::string response_data;
[email protected]8b070372009-11-16 22:01:2595 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:0896 };
97
[email protected]3caf5542010-07-16 15:19:4798 // A helper class that handles all the initial npn/ssl setup.
99 class NormalSpdyTransactionHelper {
100 public:
rdsmith82957ad2015-09-16 19:42:03101 NormalSpdyTransactionHelper(
102 const HttpRequestInfo& request,
103 RequestPriority priority,
104 const BoundNetLog& log,
danakjaee3e1ec2016-04-16 00:23:18105 std::unique_ptr<SpdySessionDependencies> session_deps)
[email protected]30c942b2010-07-21 16:59:59106 : request_(request),
[email protected]262eec82013-03-19 21:01:36107 priority_(priority),
bncd16676a2016-07-20 16:23:01108 session_deps_(session_deps.get() == NULL
109 ? base::MakeUnique<SpdySessionDependencies>()
110 : std::move(session_deps)),
rchebf12982015-04-10 01:15:00111 session_(
112 SpdySessionDependencies::SpdyCreateSession(session_deps_.get())),
bnc927c4962016-07-21 14:45:59113 log_(log) {}
[email protected]61b4efc2012-04-27 18:12:50114
[email protected]19ec8a72010-08-23 03:38:23115 ~NormalSpdyTransactionHelper() {
116 // Any test which doesn't close the socket by sending it an EOF will
117 // have a valid session left open, which leaks the entire session pool.
118 // This is just fine - in fact, some of our tests intentionally do this
119 // so that we can check consistency of the SpdySessionPool as the test
120 // finishes. If we had put an EOF on the socket, the SpdySession would
121 // have closed and we wouldn't be able to check the consistency.
122
123 // Forcefully close existing sessions here.
124 session()->spdy_session_pool()->CloseAllSessions();
125 }
126
[email protected]3caf5542010-07-16 15:19:47127 void RunPreTestSetup() {
[email protected]3caf5542010-07-16 15:19:47128 // We're now ready to use SSL-npn SPDY.
[email protected]90499482013-06-01 00:39:50129 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
[email protected]cb54b3b22010-06-03 16:28:55130 }
[email protected]aea80602009-09-18 00:55:08131
[email protected]3caf5542010-07-16 15:19:47132 // Start the transaction, read some data, finish.
133 void RunDefaultTest() {
[email protected]34b345f92013-02-22 03:27:26134 if (!StartDefaultTest())
135 return;
136 FinishDefaultTest();
137 }
138
139 bool StartDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51140 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
[email protected]aea80602009-09-18 00:55:08141
[email protected]3caf5542010-07-16 15:19:47142 // We expect an IO Pending or some sort of error.
143 EXPECT_LT(output_.rv, 0);
[email protected]34b345f92013-02-22 03:27:26144 return output_.rv == ERR_IO_PENDING;
145 }
[email protected]aea80602009-09-18 00:55:08146
[email protected]34b345f92013-02-22 03:27:26147 void FinishDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51148 output_.rv = callback_.WaitForResult();
[email protected]3caf5542010-07-16 15:19:47149 if (output_.rv != OK) {
bnc301745a2015-03-10 03:22:16150 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
[email protected]3caf5542010-07-16 15:19:47151 return;
152 }
[email protected]ff57bb82009-11-12 06:52:14153
[email protected]3caf5542010-07-16 15:19:47154 // Verify responses.
155 const HttpResponseInfo* response = trans_->GetResponseInfo();
wezca1070932016-05-26 20:30:52156 ASSERT_TRUE(response);
157 ASSERT_TRUE(response->headers);
bnc927c4962016-07-21 14:45:59158 EXPECT_EQ(HttpResponseInfo::ConnectionInfoFromNextProto(kProtoHTTP2),
159 response->connection_info);
160 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
161 EXPECT_TRUE(response->was_fetched_via_spdy);
162 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]80a09a82012-11-16 17:40:06163 EXPECT_EQ("127.0.0.1", response->socket_address.host());
bncb26024382016-06-29 02:39:45164 EXPECT_EQ(443, response->socket_address.port());
[email protected]3caf5542010-07-16 15:19:47165 output_.status_line = response->headers->GetStatusLine();
166 output_.response_info = *response; // Make a copy so we can verify.
167 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
[email protected]3caf5542010-07-16 15:19:47168 }
169
bncfacdd852015-01-09 19:22:54170 void FinishDefaultTestWithoutVerification() {
171 output_.rv = callback_.WaitForResult();
172 if (output_.rv != OK)
bnc301745a2015-03-10 03:22:16173 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
bncfacdd852015-01-09 19:22:54174 }
175
maksim.sisov8d2df66d2016-06-20 07:07:11176 void WaitForCallbackToComplete() { output_.rv = callback_.WaitForResult(); }
mmenke666a6fea2015-12-19 04:16:33177
[email protected]3caf5542010-07-16 15:19:47178 // Most tests will want to call this function. In particular, the MockReads
179 // should end with an empty read, and that read needs to be processed to
180 // ensure proper deletion of the spdy_session_pool.
181 void VerifyDataConsumed() {
rch08e3aa3e2015-05-16 14:27:52182 for (const SocketDataProvider* provider : data_vector_) {
183 EXPECT_TRUE(provider->AllReadDataConsumed());
184 EXPECT_TRUE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47185 }
186 }
187
188 // Occasionally a test will expect to error out before certain reads are
189 // processed. In that case we want to explicitly ensure that the reads were
190 // not processed.
191 void VerifyDataNotConsumed() {
rch08e3aa3e2015-05-16 14:27:52192 for (const SocketDataProvider* provider : data_vector_) {
193 EXPECT_FALSE(provider->AllReadDataConsumed());
194 EXPECT_FALSE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47195 }
196 }
197
rch08e3aa3e2015-05-16 14:27:52198 void RunToCompletion(SocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47199 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58200 AddData(data);
[email protected]3caf5542010-07-16 15:19:47201 RunDefaultTest();
202 VerifyDataConsumed();
203 }
[email protected]e6b06862010-07-20 16:32:58204
[email protected]514aeaf2014-05-23 10:31:51205 void RunToCompletionWithSSLData(
rch08e3aa3e2015-05-16 14:27:52206 SocketDataProvider* data,
danakjaee3e1ec2016-04-16 00:23:18207 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]514aeaf2014-05-23 10:31:51208 RunPreTestSetup();
dchengc7eeda422015-12-26 03:56:48209 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:51210 RunDefaultTest();
211 VerifyDataConsumed();
212 }
213
rch08e3aa3e2015-05-16 14:27:52214 void AddData(SocketDataProvider* data) {
danakjaee3e1ec2016-04-16 00:23:18215 std::unique_ptr<SSLSocketDataProvider> ssl_provider(
[email protected]514aeaf2014-05-23 10:31:51216 new SSLSocketDataProvider(ASYNC, OK));
bncce36dca22015-04-21 22:11:23217 ssl_provider->cert =
218 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
dchengc7eeda422015-12-26 03:56:48219 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:51220 }
221
222 void AddDataWithSSLSocketDataProvider(
rch08e3aa3e2015-05-16 14:27:52223 SocketDataProvider* data,
danakjaee3e1ec2016-04-16 00:23:18224 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]3caf5542010-07-16 15:19:47225 data_vector_.push_back(data);
bnc3cf2a592016-08-11 14:48:36226 if (ssl_provider->next_proto == kProtoUnknown)
227 ssl_provider->next_proto = kProtoHTTP2;
rchebf12982015-04-10 01:15:00228
229 session_deps_->socket_factory->AddSSLSocketDataProvider(
230 ssl_provider.get());
olli.raulaae011c422015-12-10 07:38:51231 ssl_vector_.push_back(std::move(ssl_provider));
[email protected]d4f00222012-07-10 06:24:51232
[email protected]3b7828432010-08-18 18:33:27233 session_deps_->socket_factory->AddSocketDataProvider(data);
[email protected]3b7828432010-08-18 18:33:27234 }
235
[email protected]3caf5542010-07-16 15:19:47236 HttpNetworkTransaction* trans() { return trans_.get(); }
237 void ResetTrans() { trans_.reset(); }
bnc4d782f492016-08-18 13:50:00238 const TransactionHelperResult& output() { return output_; }
[email protected]19ec8a72010-08-23 03:38:23239 const HttpRequestInfo& request() const { return request_; }
mmenkee65e7af2015-10-13 17:16:42240 HttpNetworkSession* session() const { return session_.get(); }
bncd16676a2016-07-20 16:23:01241 SpdySessionDependencies* session_deps() { return session_deps_.get(); }
[email protected]3caf5542010-07-16 15:19:47242
243 private:
rch08e3aa3e2015-05-16 14:27:52244 typedef std::vector<SocketDataProvider*> DataVector;
danakjaee3e1ec2016-04-16 00:23:18245 typedef std::vector<std::unique_ptr<SSLSocketDataProvider>> SSLVector;
246 typedef std::vector<std::unique_ptr<SocketDataProvider>> AlternateVector;
[email protected]3caf5542010-07-16 15:19:47247 HttpRequestInfo request_;
[email protected]262eec82013-03-19 21:01:36248 RequestPriority priority_;
danakjaee3e1ec2016-04-16 00:23:18249 std::unique_ptr<SpdySessionDependencies> session_deps_;
250 std::unique_ptr<HttpNetworkSession> session_;
[email protected]3caf5542010-07-16 15:19:47251 TransactionHelperResult output_;
[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_;
[email protected]3caf5542010-07-16 15:19:47255 DataVector data_vector_;
bnc29b1f072015-01-14 20:37:49256 const BoundNetLog log_;
[email protected]3caf5542010-07-16 15:19:47257 };
[email protected]aea80602009-09-18 00:55:08258
259 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
260 int expected_status);
261
262 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18263
[email protected]e3ebba0f2010-08-05 17:59:58264 const HttpRequestInfo& CreateGetPushRequest() {
bncce36dca22015-04-21 22:11:23265 get_push_request_.method = "GET";
266 get_push_request_.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
267 get_push_request_.load_flags = 0;
268 return get_push_request_;
[email protected]e3ebba0f2010-08-05 17:59:58269 }
270
[email protected]d3cee19d2010-06-22 18:42:18271 const HttpRequestInfo& CreateGetRequest() {
bncce36dca22015-04-21 22:11:23272 if (!get_request_initialized_) {
273 get_request_.method = "GET";
bncb26024382016-06-29 02:39:45274 get_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23275 get_request_.load_flags = 0;
276 get_request_initialized_ = true;
[email protected]d3cee19d2010-06-22 18:42:18277 }
bncce36dca22015-04-21 22:11:23278 return get_request_;
[email protected]d3cee19d2010-06-22 18:42:18279 }
280
[email protected]3deb9a52010-11-11 00:24:40281 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
bncce36dca22015-04-21 22:11:23282 if (!get_request_initialized_) {
283 get_request_.method = "GET";
bncb26024382016-06-29 02:39:45284 get_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23285 get_request_.load_flags = 0;
286 get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
287 get_request_initialized_ = true;
[email protected]3deb9a52010-11-11 00:24:40288 }
bncce36dca22015-04-21 22:11:23289 return get_request_;
[email protected]3deb9a52010-11-11 00:24:40290 }
291
[email protected]310240592010-08-05 21:04:19292 const HttpRequestInfo& CreatePostRequest() {
bncce36dca22015-04-21 22:11:23293 if (!post_request_initialized_) {
danakjaee3e1ec2016-04-16 00:23:18294 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
ricea2deef682016-09-09 08:04:07295 element_readers.push_back(base::MakeUnique<UploadBytesElementReader>(
296 kUploadData, kUploadDataSize));
[email protected]96c77a72013-09-24 09:49:20297 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22298 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27299
bncce36dca22015-04-21 22:11:23300 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45301 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23302 post_request_.upload_data_stream = upload_data_stream_.get();
303 post_request_initialized_ = true;
[email protected]310240592010-08-05 21:04:19304 }
bncce36dca22015-04-21 22:11:23305 return post_request_;
[email protected]310240592010-08-05 21:04:19306 }
307
[email protected]69e6b4a2012-10-18 08:03:01308 const HttpRequestInfo& CreateFilePostRequest() {
bncce36dca22015-04-21 22:11:23309 if (!post_request_initialized_) {
[email protected]6cdfd7f2013-02-08 20:40:15310 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52311 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01312 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30313 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01314
danakjaee3e1ec2016-04-16 00:23:18315 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
ricea2deef682016-09-09 08:04:07316 element_readers.push_back(base::MakeUnique<UploadFileElementReader>(
skyostil4891b25b2015-06-11 11:43:45317 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
ricea2deef682016-09-09 08:04:07318 kUploadDataSize, base::Time()));
[email protected]96c77a72013-09-24 09:49:20319 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22320 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27321
bncce36dca22015-04-21 22:11:23322 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45323 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23324 post_request_.upload_data_stream = upload_data_stream_.get();
325 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01326 }
bncce36dca22015-04-21 22:11:23327 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01328 }
329
[email protected]999dd8c2013-11-12 06:45:54330 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
bncce36dca22015-04-21 22:11:23331 if (post_request_initialized_)
332 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54333
334 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52335 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]999dd8c2013-11-12 06:45:54336 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30337 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]92be8eb2014-08-07 22:57:11338 CHECK(base::MakeFileUnreadable(file_path));
[email protected]999dd8c2013-11-12 06:45:54339
danakjaee3e1ec2016-04-16 00:23:18340 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
ricea2deef682016-09-09 08:04:07341 element_readers.push_back(base::MakeUnique<UploadFileElementReader>(
skyostil4891b25b2015-06-11 11:43:45342 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
ricea2deef682016-09-09 08:04:07343 kUploadDataSize, base::Time()));
[email protected]999dd8c2013-11-12 06:45:54344 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22345 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]999dd8c2013-11-12 06:45:54346
bncce36dca22015-04-21 22:11:23347 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45348 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23349 post_request_.upload_data_stream = upload_data_stream_.get();
350 post_request_initialized_ = true;
351 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54352 }
353
[email protected]69e6b4a2012-10-18 08:03:01354 const HttpRequestInfo& CreateComplexPostRequest() {
bncce36dca22015-04-21 22:11:23355 if (!post_request_initialized_) {
[email protected]69e6b4a2012-10-18 08:03:01356 const int kFileRangeOffset = 1;
357 const int kFileRangeLength = 3;
358 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
359
[email protected]6cdfd7f2013-02-08 20:40:15360 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52361 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01362 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30363 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01364
danakjaee3e1ec2016-04-16 00:23:18365 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
ricea2deef682016-09-09 08:04:07366 element_readers.push_back(base::MakeUnique<UploadBytesElementReader>(
367 kUploadData, kFileRangeOffset));
368 element_readers.push_back(base::MakeUnique<UploadFileElementReader>(
skyostil4891b25b2015-06-11 11:43:45369 base::ThreadTaskRunnerHandle::Get().get(), file_path,
ricea2deef682016-09-09 08:04:07370 kFileRangeOffset, kFileRangeLength, base::Time()));
371 element_readers.push_back(base::MakeUnique<UploadBytesElementReader>(
[email protected]69e6b4a2012-10-18 08:03:01372 kUploadData + kFileRangeOffset + kFileRangeLength,
ricea2deef682016-09-09 08:04:07373 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
[email protected]96c77a72013-09-24 09:49:20374 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22375 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27376
bncce36dca22015-04-21 22:11:23377 post_request_.method = "POST";
bncb26024382016-06-29 02:39:45378 post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23379 post_request_.upload_data_stream = upload_data_stream_.get();
380 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01381 }
bncce36dca22015-04-21 22:11:23382 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01383 }
384
[email protected]0c9bf872011-03-04 17:53:22385 const HttpRequestInfo& CreateChunkedPostRequest() {
bncce36dca22015-04-21 22:11:23386 if (!chunked_post_request_initialized_) {
mmenkecbc2b712014-10-09 20:29:07387 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
bncce36dca22015-04-21 22:11:23388 chunked_post_request_.method = "POST";
bncb26024382016-06-29 02:39:45389 chunked_post_request_.url = default_url_;
bncce36dca22015-04-21 22:11:23390 chunked_post_request_.upload_data_stream =
mmenkecbc2b712014-10-09 20:29:07391 upload_chunked_data_stream_.get();
bncce36dca22015-04-21 22:11:23392 chunked_post_request_initialized_ = true;
[email protected]0c9bf872011-03-04 17:53:22393 }
bncce36dca22015-04-21 22:11:23394 return chunked_post_request_;
[email protected]0c9bf872011-03-04 17:53:22395 }
396
[email protected]19ec8a72010-08-23 03:38:23397 // Read the result of a particular transaction, knowing that we've got
398 // multiple transactions in the read pipeline; so as we read, we may have
399 // to skip over data destined for other transactions while we consume
400 // the data for |trans|.
401 int ReadResult(HttpNetworkTransaction* trans,
[email protected]19ec8a72010-08-23 03:38:23402 std::string* result) {
403 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58404
[email protected]19ec8a72010-08-23 03:38:23405 int bytes_read = 0;
bnc301745a2015-03-10 03:22:16406 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(kSize));
[email protected]49639fa2011-12-20 23:22:41407 TestCompletionCallback callback;
[email protected]19ec8a72010-08-23 03:38:23408 while (true) {
[email protected]90499482013-06-01 00:39:50409 int rv = trans->Read(buf.get(), kSize, callback.callback());
[email protected]19ec8a72010-08-23 03:38:23410 if (rv == ERR_IO_PENDING) {
[email protected]19ec8a72010-08-23 03:38:23411 rv = callback.WaitForResult();
412 } else if (rv <= 0) {
413 break;
414 }
415 result->append(buf->data(), rv);
416 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58417 }
[email protected]19ec8a72010-08-23 03:38:23418 return bytes_read;
419 }
[email protected]e3ebba0f2010-08-05 17:59:58420
[email protected]19ec8a72010-08-23 03:38:23421 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
422 // This lengthy block is reaching into the pool to dig out the active
423 // session. Once we have the session, we verify that the streams are
424 // all closed and not leaked at this point.
425 const GURL& url = helper.request().url;
bncb26024382016-06-29 02:39:45426 SpdySessionKey key(HostPortPair::FromURL(url), ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:53427 PRIVACY_MODE_DISABLED);
[email protected]19ec8a72010-08-23 03:38:23428 BoundNetLog log;
mmenkee65e7af2015-10-13 17:16:42429 HttpNetworkSession* session = helper.session();
[email protected]795cbf82013-07-22 09:37:27430 base::WeakPtr<SpdySession> spdy_session =
bnc3e79387f2016-03-15 14:49:20431 session->spdy_session_pool()->FindAvailableSession(key, url, log);
wezca1070932016-05-26 20:30:52432 ASSERT_TRUE(spdy_session);
[email protected]19ec8a72010-08-23 03:38:23433 EXPECT_EQ(0u, spdy_session->num_active_streams());
434 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
435 }
[email protected]e3ebba0f2010-08-05 17:59:58436
rch08e3aa3e2015-05-16 14:27:52437 void RunServerPushTest(SequencedSocketData* data,
[email protected]e3ebba0f2010-08-05 17:59:58438 HttpResponseInfo* response,
[email protected]a7a265ef2010-12-08 18:05:57439 HttpResponseInfo* push_response,
[email protected]8a0fc822013-06-27 20:52:43440 const std::string& expected) {
[email protected]262eec82013-03-19 21:01:36441 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01442 BoundNetLog(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:58443 helper.RunPreTestSetup();
[email protected]d08358502010-12-03 22:04:03444 helper.AddData(data);
[email protected]e3ebba0f2010-08-05 17:59:58445
446 HttpNetworkTransaction* trans = helper.trans();
447
448 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:41449 TestCompletionCallback callback;
450 int rv = trans->Start(
451 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:01452 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:58453 rv = callback.WaitForResult();
454
455 // Request the pushed path.
bnc691fda62016-08-12 00:43:16456 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
457 rv = trans2.Start(&CreateGetPushRequest(), callback.callback(),
458 BoundNetLog());
robpercival214763f2016-07-01 23:27:01459 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:17460 base::RunLoop().RunUntilIdle();
[email protected]e3ebba0f2010-08-05 17:59:58461
[email protected]513963e2013-06-15 01:53:04462 // The data for the pushed path may be coming in more than 1 frame. Compile
[email protected]e3ebba0f2010-08-05 17:59:58463 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23464
465 // Read the server push body.
466 std::string result2;
bnc691fda62016-08-12 00:43:16467 ReadResult(&trans2, &result2);
[email protected]19ec8a72010-08-23 03:38:23468 // Read the response body.
[email protected]e3ebba0f2010-08-05 17:59:58469 std::string result;
rch0aecfd82015-05-19 17:22:32470 ReadResult(trans, &result);
[email protected]e3ebba0f2010-08-05 17:59:58471
472 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:17473 EXPECT_TRUE(data->AllReadDataConsumed());
474 EXPECT_TRUE(data->AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:58475
caseqe8340bc92016-04-20 00:02:57476 LoadTimingInfo load_timing_info;
477 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
478 EXPECT_TRUE(load_timing_info.push_start.is_null());
479 EXPECT_TRUE(load_timing_info.push_end.is_null());
480
481 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:16482 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
caseqe8340bc92016-04-20 00:02:57483 EXPECT_FALSE(load_timing_info2.push_start.is_null());
484 EXPECT_FALSE(load_timing_info2.push_end.is_null());
485
[email protected]e3ebba0f2010-08-05 17:59:58486 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23487 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
488 << result2
489 << "||||| Expected data: "
490 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58491
bnc42331402016-07-25 13:36:15492 // Verify the response HEADERS.
[email protected]e3ebba0f2010-08-05 17:59:58493 // Copy the response info, because trans goes away.
494 *response = *trans->GetResponseInfo();
bnc691fda62016-08-12 00:43:16495 *push_response = *trans2.GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23496
497 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58498 }
499
[email protected]49639fa2011-12-20 23:22:41500 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
501 int result) {
502 helper->ResetTrans();
503 }
504
mmenkee65e7af2015-10-13 17:16:42505 static void StartTransactionCallback(HttpNetworkSession* session,
506 GURL url,
507 int result) {
bnc691fda62016-08-12 00:43:16508 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]49639fa2011-12-20 23:22:41509 TestCompletionCallback callback;
510 HttpRequestInfo request;
511 request.method = "GET";
rchebf12982015-04-10 01:15:00512 request.url = url;
[email protected]49639fa2011-12-20 23:22:41513 request.load_flags = 0;
bnc691fda62016-08-12 00:43:16514 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:01515 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]49639fa2011-12-20 23:22:41516 callback.WaitForResult();
517 }
518
mmenkecbc2b712014-10-09 20:29:07519 ChunkedUploadDataStream* upload_chunked_data_stream() const {
520 return upload_chunked_data_stream_.get();
521 }
522
rchebf12982015-04-10 01:15:00523 std::string GetDefaultUrlWithPath(const char* path) {
bncb26024382016-06-29 02:39:45524 return std::string(kDefaultUrl) + path;
rchebf12982015-04-10 01:15:00525 }
526
bncb26024382016-06-29 02:39:45527 const GURL default_url_;
528 const HostPortPair host_port_pair_;
[email protected]9ec54f82013-05-10 02:53:05529 SpdyTestUtil spdy_util_;
530
[email protected]d3cee19d2010-06-22 18:42:18531 private:
danakjaee3e1ec2016-04-16 00:23:18532 std::unique_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
533 std::unique_ptr<UploadDataStream> upload_data_stream_;
bncce36dca22015-04-21 22:11:23534 bool get_request_initialized_;
535 bool post_request_initialized_;
536 bool chunked_post_request_initialized_;
537 HttpRequestInfo get_request_;
538 HttpRequestInfo post_request_;
539 HttpRequestInfo chunked_post_request_;
540 HttpRequestInfo get_push_request_;
[email protected]ea1a3f62012-11-16 20:34:23541 base::ScopedTempDir temp_dir_;
[email protected]aea80602009-09-18 00:55:08542};
543
[email protected]3caf5542010-07-16 15:19:47544// Verify HttpNetworkTransaction constructor.
bncd16676a2016-07-20 16:23:01545TEST_F(SpdyNetworkTransactionTest, Constructor) {
546 auto session_deps = base::MakeUnique<SpdySessionDependencies>();
danakjaee3e1ec2016-04-16 00:23:18547 std::unique_ptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:07548 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
bncd16676a2016-07-20 16:23:01549 auto trans =
550 base::MakeUnique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]aea80602009-09-18 00:55:08551}
552
bncd16676a2016-07-20 16:23:01553TEST_F(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38554 // Construct the request.
bncdf80d44fd2016-07-15 20:27:41555 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49556 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:41557 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]72552f02009-10-28 15:25:01558
bnc42331402016-07-25 13:36:15559 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:41560 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]72552f02009-10-28 15:25:01561 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41562 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:52563 MockRead(ASYNC, 0, 3) // EOF
[email protected]72552f02009-10-28 15:25:01564 };
565
rch08e3aa3e2015-05-16 14:27:52566 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:36567 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01568 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:57569 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:47570 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:01571 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02572 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]72552f02009-10-28 15:25:01573 EXPECT_EQ("hello!", out.response_data);
574}
575
bncd16676a2016-07-20 16:23:01576TEST_F(SpdyNetworkTransactionTest, GetAtEachPriority) {
[email protected]3d08dd382013-10-19 00:13:11577 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
[email protected]31ae7ab2012-04-24 21:09:05578 p = RequestPriority(p + 1)) {
bncd16676a2016-07-20 16:23:01579 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:49580
[email protected]c9c6f5c2010-07-31 01:30:03581 // Construct the request.
bncdf80d44fd2016-07-15 20:27:41582 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49583 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, p, true));
bncdf80d44fd2016-07-15 20:27:41584 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]c9c6f5c2010-07-31 01:30:03585
[email protected]86aa87b2013-02-15 01:10:03586 SpdyPriority spdy_prio = 0;
bncdf80d44fd2016-07-15 20:27:41587 EXPECT_TRUE(GetSpdyPriority(req, &spdy_prio));
[email protected]c9c6f5c2010-07-31 01:30:03588 // this repeats the RequestPriority-->SpdyPriority mapping from
589 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
590 // sure it's being done right.
bnc05808ff42016-01-08 23:48:25591 switch (p) {
592 case HIGHEST:
593 EXPECT_EQ(0, spdy_prio);
594 break;
595 case MEDIUM:
596 EXPECT_EQ(1, spdy_prio);
597 break;
598 case LOW:
599 EXPECT_EQ(2, spdy_prio);
600 break;
601 case LOWEST:
602 EXPECT_EQ(3, spdy_prio);
603 break;
604 case IDLE:
605 EXPECT_EQ(4, spdy_prio);
606 break;
607 default:
608 FAIL();
[email protected]c9c6f5c2010-07-31 01:30:03609 }
610
bncdf80d44fd2016-07-15 20:27:41611 SpdySerializedFrame resp(
bnc42331402016-07-25 13:36:15612 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:41613 SpdySerializedFrame body(spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]c9c6f5c2010-07-31 01:30:03614 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41615 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:52616 MockRead(ASYNC, 0, 3) // EOF
[email protected]c9c6f5c2010-07-31 01:30:03617 };
618
rch08e3aa3e2015-05-16 14:27:52619 SequencedSocketData data(reads, arraysize(reads), writes,
620 arraysize(writes));
[email protected]c9c6f5c2010-07-31 01:30:03621 HttpRequestInfo http_req = CreateGetRequest();
[email protected]c9c6f5c2010-07-31 01:30:03622
bncd16676a2016-07-20 16:23:01623 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:57624 helper.RunToCompletion(&data);
[email protected]c9c6f5c2010-07-31 01:30:03625 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:01626 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02627 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]c9c6f5c2010-07-31 01:30:03628 EXPECT_EQ("hello!", out.response_data);
629 }
630}
631
[email protected]2bd93022010-07-17 00:58:44632// Start three gets simultaniously; making sure that multiplexed
633// streams work properly.
634
635// This can't use the TransactionHelper method, since it only
636// handles a single transaction, and finishes them as soon
637// as it launches them.
638
639// TODO(gavinp): create a working generalized TransactionHelper that
640// can allow multiple streams in flight.
641
bncd16676a2016-07-20 16:23:01642TEST_F(SpdyNetworkTransactionTest, ThreeGets) {
bncdf80d44fd2016-07-15 20:27:41643 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49644 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:15645 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:41646 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
647 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2bd93022010-07-17 00:58:44648
bncdf80d44fd2016-07-15 20:27:41649 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49650 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:15651 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:41652 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
653 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2bd93022010-07-17 00:58:44654
bncdf80d44fd2016-07-15 20:27:41655 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:49656 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
bnc42331402016-07-25 13:36:15657 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
bncdf80d44fd2016-07-15 20:27:41658 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
659 SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44660
[email protected]1b323172011-03-01 17:50:17661 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41662 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
663 CreateMockWrite(req3, 6),
[email protected]2bd93022010-07-17 00:58:44664 };
665 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41666 CreateMockRead(resp, 1), CreateMockRead(body, 2),
667 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
668 CreateMockRead(resp3, 7), CreateMockRead(body3, 8),
[email protected]2bd93022010-07-17 00:58:44669
bncdf80d44fd2016-07-15 20:27:41670 CreateMockRead(fbody, 9), CreateMockRead(fbody2, 10),
671 CreateMockRead(fbody3, 11),
[email protected]2bd93022010-07-17 00:58:44672
rch08e3aa3e2015-05-16 14:27:52673 MockRead(ASYNC, 0, 12), // EOF
[email protected]2bd93022010-07-17 00:58:44674 };
rch08e3aa3e2015-05-16 14:27:52675 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
mmenkecc2298e2015-12-07 18:20:18676 SequencedSocketData data_placeholder1(NULL, 0, NULL, 0);
677 SequencedSocketData data_placeholder2(NULL, 0, NULL, 0);
[email protected]2bd93022010-07-17 00:58:44678
679 BoundNetLog log;
680 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36681 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01682 BoundNetLog(), NULL);
[email protected]bdebd1b2010-08-09 20:18:08683 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57684 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49685 // We require placeholder data because three get requests are sent out at
686 // the same time which results in three sockets being connected. The first
687 // on will negotiate SPDY and will be used for all requests.
mmenkecc2298e2015-12-07 18:20:18688 helper.AddData(&data_placeholder1);
689 helper.AddData(&data_placeholder2);
bnc691fda62016-08-12 00:43:16690 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
691 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
692 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
[email protected]2bd93022010-07-17 00:58:44693
[email protected]49639fa2011-12-20 23:22:41694 TestCompletionCallback callback1;
695 TestCompletionCallback callback2;
696 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44697
[email protected]bdebd1b2010-08-09 20:18:08698 HttpRequestInfo httpreq1 = CreateGetRequest();
699 HttpRequestInfo httpreq2 = CreateGetRequest();
700 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:44701
bnc691fda62016-08-12 00:43:16702 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:01703 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16704 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:01705 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16706 out.rv = trans3.Start(&httpreq3, callback3.callback(), log);
robpercival214763f2016-07-01 23:27:01707 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]2bd93022010-07-17 00:58:44708
[email protected]bdebd1b2010-08-09 20:18:08709 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01710 ASSERT_THAT(out.rv, IsOk());
[email protected]bdebd1b2010-08-09 20:18:08711 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:01712 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44713
bnc691fda62016-08-12 00:43:16714 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52715 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:08716 EXPECT_TRUE(response1->was_fetched_via_spdy);
717 out.status_line = response1->headers->GetStatusLine();
718 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:44719
bnc691fda62016-08-12 00:43:16720 trans2.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:44721
bnc691fda62016-08-12 00:43:16722 out.rv = ReadTransaction(&trans1, &out.response_data);
[email protected]bdebd1b2010-08-09 20:18:08723 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:01724 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44725
robpercival214763f2016-07-01 23:27:01726 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02727 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:44728 EXPECT_EQ("hello!hello!", out.response_data);
729}
730
bncd16676a2016-07-20 16:23:01731TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
bncdf80d44fd2016-07-15 20:27:41732 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49733 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:15734 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:41735 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
736 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1b323172011-03-01 17:50:17737
bncdf80d44fd2016-07-15 20:27:41738 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49739 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:15740 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:41741 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
742 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]1b323172011-03-01 17:50:17743
744 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41745 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
[email protected]1b323172011-03-01 17:50:17746 };
747 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41748 CreateMockRead(resp, 1), CreateMockRead(body, 2),
749 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
750 CreateMockRead(fbody, 6), CreateMockRead(fbody2, 7),
rch08e3aa3e2015-05-16 14:27:52751 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:17752 };
rch08e3aa3e2015-05-16 14:27:52753 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1b323172011-03-01 17:50:17754
[email protected]d973e99a2012-02-17 21:02:36755 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
rch08e3aa3e2015-05-16 14:27:52756 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:57757 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17758
759 BoundNetLog log;
760 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36761 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01762 BoundNetLog(), NULL);
[email protected]1b323172011-03-01 17:50:17763 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57764 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49765 // We require placeholder data because two requests are sent out at
766 // the same time which results in two sockets being connected. The first
767 // on will negotiate SPDY and will be used for all requests.
[email protected]dd54bd82012-07-19 23:44:57768 helper.AddData(&data_placeholder);
bnc691fda62016-08-12 00:43:16769 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
770 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]1b323172011-03-01 17:50:17771
[email protected]49639fa2011-12-20 23:22:41772 TestCompletionCallback callback1;
773 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:17774
775 HttpRequestInfo httpreq1 = CreateGetRequest();
776 HttpRequestInfo httpreq2 = CreateGetRequest();
777
bnc691fda62016-08-12 00:43:16778 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:01779 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16780 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:01781 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]1b323172011-03-01 17:50:17782
783 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01784 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17785 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:01786 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17787
bnc691fda62016-08-12 00:43:16788 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52789 EXPECT_TRUE(response1->headers);
[email protected]1b323172011-03-01 17:50:17790 EXPECT_TRUE(response1->was_fetched_via_spdy);
791 out.status_line = response1->headers->GetStatusLine();
792 out.response_info = *response1;
bnc691fda62016-08-12 00:43:16793 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:01794 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02795 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17796 EXPECT_EQ("hello!hello!", out.response_data);
797
bnc691fda62016-08-12 00:43:16798 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:52799 EXPECT_TRUE(response2->headers);
[email protected]1b323172011-03-01 17:50:17800 EXPECT_TRUE(response2->was_fetched_via_spdy);
801 out.status_line = response2->headers->GetStatusLine();
802 out.response_info = *response2;
bnc691fda62016-08-12 00:43:16803 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:01804 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02805 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17806 EXPECT_EQ("hello!hello!", out.response_data);
807
808 helper.VerifyDataConsumed();
809}
810
bncd16676a2016-07-20 16:23:01811TEST_F(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
bncdf80d44fd2016-07-15 20:27:41812 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49813 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:15814 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:41815 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
816 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1b323172011-03-01 17:50:17817
bncdf80d44fd2016-07-15 20:27:41818 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49819 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:15820 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:41821 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
822 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]1b323172011-03-01 17:50:17823
824 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41825 CreateMockWrite(req, 0), CreateMockWrite(req2, 3),
[email protected]1b323172011-03-01 17:50:17826 };
827 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41828 CreateMockRead(resp, 1), CreateMockRead(body, 2),
829 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
830 CreateMockRead(fbody, 6), CreateMockRead(fbody2, 7),
rch08e3aa3e2015-05-16 14:27:52831 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:17832 };
rch08e3aa3e2015-05-16 14:27:52833 SequencedSocketData preconnect_data(reads, arraysize(reads), writes,
834 arraysize(writes));
[email protected]1b323172011-03-01 17:50:17835
[email protected]d973e99a2012-02-17 21:02:36836 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
[email protected]1b323172011-03-01 17:50:17837
rch08e3aa3e2015-05-16 14:27:52838 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:57839 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17840
841 BoundNetLog log;
842 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36843 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01844 BoundNetLog(), NULL);
[email protected]1b323172011-03-01 17:50:17845 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57846 helper.AddData(&preconnect_data);
[email protected]1b323172011-03-01 17:50:17847 // We require placeholder data because 3 connections are attempted (first is
848 // the preconnect, 2nd and 3rd are the never finished connections.
[email protected]dd54bd82012-07-19 23:44:57849 helper.AddData(&data_placeholder);
850 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:17851
bnc691fda62016-08-12 00:43:16852 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
853 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]1b323172011-03-01 17:50:17854
[email protected]49639fa2011-12-20 23:22:41855 TestCompletionCallback callback1;
856 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:17857
858 HttpRequestInfo httpreq = CreateGetRequest();
859
860 // Preconnect the first.
[email protected]1b323172011-03-01 17:50:17861 HttpStreamFactory* http_stream_factory =
862 helper.session()->http_stream_factory();
[email protected]1b323172011-03-01 17:50:17863
nharper8cdb0fb2016-04-22 21:34:59864 http_stream_factory->PreconnectStreams(1, httpreq);
[email protected]1b323172011-03-01 17:50:17865
bnc691fda62016-08-12 00:43:16866 out.rv = trans1.Start(&httpreq, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:01867 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:16868 out.rv = trans2.Start(&httpreq, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:01869 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]1b323172011-03-01 17:50:17870
871 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01872 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17873 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:01874 ASSERT_THAT(out.rv, IsOk());
[email protected]1b323172011-03-01 17:50:17875
bnc691fda62016-08-12 00:43:16876 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52877 EXPECT_TRUE(response1->headers);
[email protected]1b323172011-03-01 17:50:17878 EXPECT_TRUE(response1->was_fetched_via_spdy);
879 out.status_line = response1->headers->GetStatusLine();
880 out.response_info = *response1;
bnc691fda62016-08-12 00:43:16881 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:01882 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02883 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17884 EXPECT_EQ("hello!hello!", out.response_data);
885
bnc691fda62016-08-12 00:43:16886 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:52887 EXPECT_TRUE(response2->headers);
[email protected]1b323172011-03-01 17:50:17888 EXPECT_TRUE(response2->was_fetched_via_spdy);
889 out.status_line = response2->headers->GetStatusLine();
890 out.response_info = *response2;
bnc691fda62016-08-12 00:43:16891 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:01892 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:02893 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17894 EXPECT_EQ("hello!hello!", out.response_data);
895
896 helper.VerifyDataConsumed();
897}
898
[email protected]2bd93022010-07-17 00:58:44899// Similar to ThreeGets above, however this test adds a SETTINGS
900// frame. The SETTINGS frame is read during the IO loop waiting on
901// the first transaction completion, and sets a maximum concurrent
902// stream limit of 1. This means that our IO loop exists after the
903// second transaction completes, so we can assert on read_index().
bncd16676a2016-07-20 16:23:01904TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:44905 // Construct the request.
rdsmithebb50aa2015-11-12 03:44:38906 // Each request fully completes before the next starts.
bncdf80d44fd2016-07-15 20:27:41907 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:49908 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:15909 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:41910 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
911 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:38912 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:44913
bncdf80d44fd2016-07-15 20:27:41914 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:49915 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:15916 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:41917 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
918 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:38919 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:44920
bncdf80d44fd2016-07-15 20:27:41921 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:49922 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
bnc42331402016-07-25 13:36:15923 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
bncdf80d44fd2016-07-15 20:27:41924 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false));
925 SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44926
[email protected]18b28ab2012-04-18 02:14:42927 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:46928 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:42929 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
930 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
bncdf80d44fd2016-07-15 20:27:41931 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:20932 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:41933 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:44934
[email protected]2d6728692011-03-12 01:39:55935 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:41936 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
937 CreateMockWrite(req2, 6), CreateMockWrite(req3, 10),
[email protected]2bd93022010-07-17 00:58:44938 };
[email protected]2d6728692011-03-12 01:39:55939
[email protected]2bd93022010-07-17 00:58:44940 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:41941 CreateMockRead(settings_frame, 1),
942 CreateMockRead(resp, 2),
943 CreateMockRead(body, 3),
944 CreateMockRead(fbody, 4),
945 CreateMockRead(resp2, 7),
946 CreateMockRead(body2, 8),
947 CreateMockRead(fbody2, 9),
948 CreateMockRead(resp3, 11),
949 CreateMockRead(body3, 12),
950 CreateMockRead(fbody3, 13),
[email protected]2bd93022010-07-17 00:58:44951
rch08e3aa3e2015-05-16 14:27:52952 MockRead(ASYNC, 0, 14), // EOF
[email protected]2bd93022010-07-17 00:58:44953 };
954
rch08e3aa3e2015-05-16 14:27:52955 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:44956
957 BoundNetLog log;
958 TransactionHelperResult out;
959 {
[email protected]262eec82013-03-19 21:01:36960 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:01961 BoundNetLog(), NULL);
[email protected]2d6728692011-03-12 01:39:55962 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57963 helper.AddData(&data);
bnc691fda62016-08-12 00:43:16964 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
965 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
966 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
[email protected]2bd93022010-07-17 00:58:44967
[email protected]49639fa2011-12-20 23:22:41968 TestCompletionCallback callback1;
969 TestCompletionCallback callback2;
970 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44971
972 HttpRequestInfo httpreq1 = CreateGetRequest();
973 HttpRequestInfo httpreq2 = CreateGetRequest();
974 HttpRequestInfo httpreq3 = CreateGetRequest();
975
bnc691fda62016-08-12 00:43:16976 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]2bd93022010-07-17 00:58:44977 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]513963e2013-06-15 01:53:04978 // Run transaction 1 through quickly to force a read of our SETTINGS
979 // frame.
[email protected]2bd93022010-07-17 00:58:44980 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:01981 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44982
bnc691fda62016-08-12 00:43:16983 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]2bd93022010-07-17 00:58:44984 ASSERT_EQ(out.rv, ERR_IO_PENDING);
bnc691fda62016-08-12 00:43:16985 out.rv = trans3.Start(&httpreq3, callback3.callback(), log);
[email protected]2bd93022010-07-17 00:58:44986 ASSERT_EQ(out.rv, ERR_IO_PENDING);
987 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:01988 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44989
990 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:01991 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:44992
bnc691fda62016-08-12 00:43:16993 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:52994 ASSERT_TRUE(response1);
995 EXPECT_TRUE(response1->headers);
[email protected]2bd93022010-07-17 00:58:44996 EXPECT_TRUE(response1->was_fetched_via_spdy);
997 out.status_line = response1->headers->GetStatusLine();
998 out.response_info = *response1;
bnc691fda62016-08-12 00:43:16999 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011000 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021001 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441002 EXPECT_EQ("hello!hello!", out.response_data);
1003
bnc691fda62016-08-12 00:43:161004 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:441005 out.status_line = response2->headers->GetStatusLine();
1006 out.response_info = *response2;
bnc691fda62016-08-12 00:43:161007 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011008 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021009 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441010 EXPECT_EQ("hello!hello!", out.response_data);
1011
bnc691fda62016-08-12 00:43:161012 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:441013 out.status_line = response3->headers->GetStatusLine();
1014 out.response_info = *response3;
bnc691fda62016-08-12 00:43:161015 out.rv = ReadTransaction(&trans3, &out.response_data);
robpercival214763f2016-07-01 23:27:011016 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021017 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441018 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:261019
1020 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441021 }
robpercival214763f2016-07-01 23:27:011022 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441023}
1024
1025// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1026// a fourth transaction. The third and fourth transactions have
1027// different data ("hello!" vs "hello!hello!") and because of the
1028// user specified priority, we expect to see them inverted in
1029// the response from the server.
bncd16676a2016-07-20 16:23:011030TEST_F(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:441031 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411032 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491033 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:151034 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411035 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1036 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381037 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441038
bncdf80d44fd2016-07-15 20:27:411039 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:491040 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:151041 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:411042 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1043 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:381044 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:441045
bncdf80d44fd2016-07-15 20:27:411046 SpdySerializedFrame req4(
bnc38dcd392016-02-09 23:19:491047 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, HIGHEST, true));
bnc42331402016-07-25 13:36:151048 SpdySerializedFrame resp4(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
bncdf80d44fd2016-07-15 20:27:411049 SpdySerializedFrame fbody4(spdy_util_.ConstructSpdyDataFrame(5, true));
rdsmithebb50aa2015-11-12 03:44:381050 spdy_util_.UpdateWithStreamDestruction(5);
[email protected]2bd93022010-07-17 00:58:441051
bncdf80d44fd2016-07-15 20:27:411052 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:491053 spdy_util_.ConstructSpdyGet(nullptr, 0, 7, LOWEST, true));
bnc42331402016-07-25 13:36:151054 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 7));
bncdf80d44fd2016-07-15 20:27:411055 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(7, false));
1056 SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(7, true));
[email protected]2bd93022010-07-17 00:58:441057
[email protected]18b28ab2012-04-18 02:14:421058 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461059 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421060 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1061 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
bncdf80d44fd2016-07-15 20:27:411062 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201063 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:411064 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
rch08e3aa3e2015-05-16 14:27:521065 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411066 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
rch08e3aa3e2015-05-16 14:27:521067 // By making these synchronous, it guarantees that they are not *started*
1068 // before their sequence number, which in turn verifies that only a single
1069 // request is in-flight at a time.
bncdf80d44fd2016-07-15 20:27:411070 CreateMockWrite(req2, 6, SYNCHRONOUS),
1071 CreateMockWrite(req4, 10, SYNCHRONOUS),
1072 CreateMockWrite(req3, 13, SYNCHRONOUS),
[email protected]2bd93022010-07-17 00:58:441073 };
1074 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411075 CreateMockRead(settings_frame, 1),
1076 CreateMockRead(resp, 2),
1077 CreateMockRead(body, 3),
1078 CreateMockRead(fbody, 4),
1079 CreateMockRead(resp2, 7),
1080 CreateMockRead(body2, 8),
1081 CreateMockRead(fbody2, 9),
1082 CreateMockRead(resp4, 11),
1083 CreateMockRead(fbody4, 12),
1084 CreateMockRead(resp3, 14),
1085 CreateMockRead(body3, 15),
1086 CreateMockRead(fbody3, 16),
[email protected]2bd93022010-07-17 00:58:441087
rch08e3aa3e2015-05-16 14:27:521088 MockRead(ASYNC, 0, 17), // EOF
[email protected]2bd93022010-07-17 00:58:441089 };
rch08e3aa3e2015-05-16 14:27:521090 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441091 BoundNetLog log;
1092 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361093 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011094 BoundNetLog(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081095 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571096 helper.AddData(&data);
rch08e3aa3e2015-05-16 14:27:521097
bnc691fda62016-08-12 00:43:161098 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1099 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
1100 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, helper.session());
1101 HttpNetworkTransaction trans4(HIGHEST, helper.session());
[email protected]2bd93022010-07-17 00:58:441102
[email protected]49639fa2011-12-20 23:22:411103 TestCompletionCallback callback1;
1104 TestCompletionCallback callback2;
1105 TestCompletionCallback callback3;
1106 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:441107
[email protected]bdebd1b2010-08-09 20:18:081108 HttpRequestInfo httpreq1 = CreateGetRequest();
1109 HttpRequestInfo httpreq2 = CreateGetRequest();
1110 HttpRequestInfo httpreq3 = CreateGetRequest();
1111 HttpRequestInfo httpreq4 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441112
bnc691fda62016-08-12 00:43:161113 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
robpercival214763f2016-07-01 23:27:011114 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]e0935cc2012-03-24 14:12:481115 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081116 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011117 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441118
bnc691fda62016-08-12 00:43:161119 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
robpercival214763f2016-07-01 23:27:011120 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:161121 out.rv = trans3.Start(&httpreq3, callback3.callback(), log);
robpercival214763f2016-07-01 23:27:011122 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
bnc691fda62016-08-12 00:43:161123 out.rv = trans4.Start(&httpreq4, callback4.callback(), log);
robpercival214763f2016-07-01 23:27:011124 ASSERT_THAT(out.rv, IsError(ERR_IO_PENDING));
[email protected]2bd93022010-07-17 00:58:441125
[email protected]bdebd1b2010-08-09 20:18:081126 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011127 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441128
[email protected]bdebd1b2010-08-09 20:18:081129 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011130 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441131
bnc691fda62016-08-12 00:43:161132 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521133 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:081134 EXPECT_TRUE(response1->was_fetched_via_spdy);
1135 out.status_line = response1->headers->GetStatusLine();
1136 out.response_info = *response1;
bnc691fda62016-08-12 00:43:161137 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011138 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021139 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081140 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441141
bnc691fda62016-08-12 00:43:161142 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081143 out.status_line = response2->headers->GetStatusLine();
1144 out.response_info = *response2;
bnc691fda62016-08-12 00:43:161145 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011146 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021147 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081148 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441149
[email protected]bdebd1b2010-08-09 20:18:081150 // notice: response3 gets two hellos, response4 gets one
1151 // hello, so we know dequeuing priority was respected.
bnc691fda62016-08-12 00:43:161152 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081153 out.status_line = response3->headers->GetStatusLine();
1154 out.response_info = *response3;
bnc691fda62016-08-12 00:43:161155 out.rv = ReadTransaction(&trans3, &out.response_data);
robpercival214763f2016-07-01 23:27:011156 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021157 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081158 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441159
[email protected]bdebd1b2010-08-09 20:18:081160 out.rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:011161 EXPECT_THAT(out.rv, IsOk());
bnc691fda62016-08-12 00:43:161162 const HttpResponseInfo* response4 = trans4.GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081163 out.status_line = response4->headers->GetStatusLine();
1164 out.response_info = *response4;
bnc691fda62016-08-12 00:43:161165 out.rv = ReadTransaction(&trans4, &out.response_data);
robpercival214763f2016-07-01 23:27:011166 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021167 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081168 EXPECT_EQ("hello!", out.response_data);
1169 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:011170 EXPECT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441171}
1172
1173// Similar to ThreeGetsMaxConcurrrent above, however, this test
rch08e3aa3e2015-05-16 14:27:521174// deletes a session in the middle of the transaction to ensure
[email protected]2bd93022010-07-17 00:58:441175// that we properly remove pendingcreatestream objects from
1176// the spdy_session
bncd16676a2016-07-20 16:23:011177TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:441178 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411179 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491180 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:151181 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411182 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1183 SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381184 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441185
bncdf80d44fd2016-07-15 20:27:411186 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:491187 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:151188 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:411189 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false));
1190 SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441191
[email protected]18b28ab2012-04-18 02:14:421192 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461193 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421194 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1195 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
bncdf80d44fd2016-07-15 20:27:411196 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201197 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:411198 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441199
[email protected]d4a77c12014-05-15 20:45:211200 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411201 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1202 CreateMockWrite(req2, 6),
[email protected]2bd93022010-07-17 00:58:441203 };
1204 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411205 CreateMockRead(settings_frame, 1), CreateMockRead(resp, 2),
1206 CreateMockRead(body, 3), CreateMockRead(fbody, 4),
1207 CreateMockRead(resp2, 7), CreateMockRead(body2, 8),
1208 CreateMockRead(fbody2, 9), MockRead(ASYNC, 0, 10), // EOF
[email protected]2bd93022010-07-17 00:58:441209 };
1210
rch08e3aa3e2015-05-16 14:27:521211 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441212
1213 BoundNetLog log;
1214 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361215 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011216 BoundNetLog(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081217 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571218 helper.AddData(&data);
danakjaee3e1ec2016-04-16 00:23:181219 std::unique_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421220 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
danakjaee3e1ec2016-04-16 00:23:181221 std::unique_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421222 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
danakjaee3e1ec2016-04-16 00:23:181223 std::unique_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:421224 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]2bd93022010-07-17 00:58:441225
[email protected]49639fa2011-12-20 23:22:411226 TestCompletionCallback callback1;
1227 TestCompletionCallback callback2;
1228 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441229
[email protected]bdebd1b2010-08-09 20:18:081230 HttpRequestInfo httpreq1 = CreateGetRequest();
1231 HttpRequestInfo httpreq2 = CreateGetRequest();
1232 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441233
[email protected]49639fa2011-12-20 23:22:411234 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081235 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481236 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081237 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011238 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441239
[email protected]49639fa2011-12-20 23:22:411240 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081241 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411242 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
olli.raula7ca9cd1d2016-01-04 06:50:371243 trans3.reset();
[email protected]bdebd1b2010-08-09 20:18:081244 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1245 out.rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:011246 ASSERT_THAT(out.rv, IsOk());
[email protected]2bd93022010-07-17 00:58:441247
[email protected]bdebd1b2010-08-09 20:18:081248 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:521249 ASSERT_TRUE(response1);
1250 EXPECT_TRUE(response1->headers);
[email protected]bdebd1b2010-08-09 20:18:081251 EXPECT_TRUE(response1->was_fetched_via_spdy);
1252 out.status_line = response1->headers->GetStatusLine();
1253 out.response_info = *response1;
1254 out.rv = ReadTransaction(trans1.get(), &out.response_data);
robpercival214763f2016-07-01 23:27:011255 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021256 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081257 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441258
[email protected]bdebd1b2010-08-09 20:18:081259 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:521260 ASSERT_TRUE(response2);
[email protected]bdebd1b2010-08-09 20:18:081261 out.status_line = response2->headers->GetStatusLine();
1262 out.response_info = *response2;
1263 out.rv = ReadTransaction(trans2.get(), &out.response_data);
robpercival214763f2016-07-01 23:27:011264 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021265 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081266 EXPECT_EQ("hello!hello!", out.response_data);
1267 helper.VerifyDataConsumed();
robpercival214763f2016-07-01 23:27:011268 EXPECT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261269}
[email protected]2bd93022010-07-17 00:58:441270
[email protected]448d4ca52012-03-04 04:12:231271namespace {
1272
[email protected]044dcc52010-09-17 15:44:261273// The KillerCallback will delete the transaction on error as part of the
1274// callback.
[email protected]49639fa2011-12-20 23:22:411275class KillerCallback : public TestCompletionCallbackBase {
[email protected]044dcc52010-09-17 15:44:261276 public:
1277 explicit KillerCallback(HttpNetworkTransaction* transaction)
[email protected]49639fa2011-12-20 23:22:411278 : transaction_(transaction),
[email protected]aa249b52013-04-30 01:04:321279 callback_(base::Bind(&KillerCallback::OnComplete,
1280 base::Unretained(this))) {
[email protected]044dcc52010-09-17 15:44:261281 }
1282
dchengb03027d2014-10-21 12:00:201283 ~KillerCallback() override {}
[email protected]49639fa2011-12-20 23:22:411284
1285 const CompletionCallback& callback() const { return callback_; }
1286
[email protected]044dcc52010-09-17 15:44:261287 private:
[email protected]49639fa2011-12-20 23:22:411288 void OnComplete(int result) {
1289 if (result < 0)
1290 delete transaction_;
1291
1292 SetResult(result);
1293 }
1294
[email protected]044dcc52010-09-17 15:44:261295 HttpNetworkTransaction* transaction_;
[email protected]49639fa2011-12-20 23:22:411296 CompletionCallback callback_;
[email protected]044dcc52010-09-17 15:44:261297};
1298
[email protected]448d4ca52012-03-04 04:12:231299} // namespace
1300
[email protected]044dcc52010-09-17 15:44:261301// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1302// closes the socket while we have a pending transaction waiting for
1303// a pending stream creation. http://crbug.com/52901
bncd16676a2016-07-20 16:23:011304TEST_F(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
[email protected]044dcc52010-09-17 15:44:261305 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411306 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491307 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:151308 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411309 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false));
1310 SpdySerializedFrame fin_body(spdy_util_.ConstructSpdyDataFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381311 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]044dcc52010-09-17 15:44:261312
bncdf80d44fd2016-07-15 20:27:411313 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:491314 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bnc42331402016-07-25 13:36:151315 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
[email protected]044dcc52010-09-17 15:44:261316
[email protected]18b28ab2012-04-18 02:14:421317 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461318 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421319 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1320 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
bncdf80d44fd2016-07-15 20:27:411321 SpdySerializedFrame settings_frame(
[email protected]c10b20852013-05-15 21:29:201322 spdy_util_.ConstructSpdySettings(settings));
bncdf80d44fd2016-07-15 20:27:411323 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]044dcc52010-09-17 15:44:261324
[email protected]d4a77c12014-05-15 20:45:211325 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411326 CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 5),
1327 CreateMockWrite(req2, 6),
[email protected]044dcc52010-09-17 15:44:261328 };
1329 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411330 CreateMockRead(settings_frame, 1),
1331 CreateMockRead(resp, 2),
1332 CreateMockRead(body, 3),
1333 CreateMockRead(fin_body, 4),
1334 CreateMockRead(resp2, 7),
rch08e3aa3e2015-05-16 14:27:521335 MockRead(ASYNC, ERR_CONNECTION_RESET, 8), // Abort!
[email protected]044dcc52010-09-17 15:44:261336 };
1337
rch08e3aa3e2015-05-16 14:27:521338 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1339 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]044dcc52010-09-17 15:44:261340
1341 BoundNetLog log;
1342 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361343 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011344 BoundNetLog(), NULL);
[email protected]044dcc52010-09-17 15:44:261345 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571346 helper.AddData(&data);
[email protected]044dcc52010-09-17 15:44:261347 // We require placeholder data because three get requests are sent out, so
1348 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571349 helper.AddData(&data_placeholder);
1350 helper.AddData(&data_placeholder);
mmenkee65e7af2015-10-13 17:16:421351 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1352 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]262eec82013-03-19 21:01:361353 HttpNetworkTransaction* trans3(
mmenkee65e7af2015-10-13 17:16:421354 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]044dcc52010-09-17 15:44:261355
[email protected]49639fa2011-12-20 23:22:411356 TestCompletionCallback callback1;
1357 TestCompletionCallback callback2;
[email protected]044dcc52010-09-17 15:44:261358 KillerCallback callback3(trans3);
1359
1360 HttpRequestInfo httpreq1 = CreateGetRequest();
1361 HttpRequestInfo httpreq2 = CreateGetRequest();
1362 HttpRequestInfo httpreq3 = CreateGetRequest();
1363
[email protected]49639fa2011-12-20 23:22:411364 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]044dcc52010-09-17 15:44:261365 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481366 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]044dcc52010-09-17 15:44:261367 out.rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011368 ASSERT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261369
[email protected]49639fa2011-12-20 23:22:411370 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]044dcc52010-09-17 15:44:261371 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411372 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]044dcc52010-09-17 15:44:261373 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1374 out.rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:011375 ASSERT_THAT(out.rv, IsError(ERR_ABORTED));
[email protected]044dcc52010-09-17 15:44:261376
[email protected]044dcc52010-09-17 15:44:261377 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:521378 ASSERT_TRUE(response1);
1379 EXPECT_TRUE(response1->headers);
[email protected]044dcc52010-09-17 15:44:261380 EXPECT_TRUE(response1->was_fetched_via_spdy);
1381 out.status_line = response1->headers->GetStatusLine();
1382 out.response_info = *response1;
1383 out.rv = ReadTransaction(&trans1, &out.response_data);
robpercival214763f2016-07-01 23:27:011384 EXPECT_THAT(out.rv, IsOk());
[email protected]044dcc52010-09-17 15:44:261385
1386 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:521387 ASSERT_TRUE(response2);
[email protected]044dcc52010-09-17 15:44:261388 out.status_line = response2->headers->GetStatusLine();
1389 out.response_info = *response2;
1390 out.rv = ReadTransaction(&trans2, &out.response_data);
robpercival214763f2016-07-01 23:27:011391 EXPECT_THAT(out.rv, IsError(ERR_CONNECTION_RESET));
[email protected]044dcc52010-09-17 15:44:261392
1393 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441394}
1395
[email protected]d8ef27b2010-08-06 17:34:391396// Test that a simple PUT request works.
bncd16676a2016-07-20 16:23:011397TEST_F(SpdyNetworkTransactionTest, Put) {
[email protected]d8ef27b2010-08-06 17:34:391398 // Setup the request
1399 HttpRequestInfo request;
1400 request.method = "PUT";
bncb26024382016-06-29 02:39:451401 request.url = default_url_;
[email protected]d8ef27b2010-08-06 17:34:391402
bnc086b39e12016-06-24 13:05:261403 SpdyHeaderBlock put_headers(
bncb26024382016-06-29 02:39:451404 spdy_util_.ConstructPutHeaderBlock(kDefaultUrl, 0));
bncdf80d44fd2016-07-15 20:27:411405 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151406 spdy_util_.ConstructSpdyHeaders(1, std::move(put_headers), LOWEST, true));
[email protected]d8ef27b2010-08-06 17:34:391407 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411408 CreateMockWrite(req, 0),
[email protected]d8ef27b2010-08-06 17:34:391409 };
1410
bnc42331402016-07-25 13:36:151411 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411412 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391413 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411414 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521415 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391416 };
1417
rch08e3aa3e2015-05-16 14:27:521418 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:011419 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
1420 NULL);
[email protected]dd54bd82012-07-19 23:44:571421 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391422 TransactionHelperResult out = helper.output();
1423
robpercival214763f2016-07-01 23:27:011424 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021425 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391426}
1427
1428// Test that a simple HEAD request works.
bncd16676a2016-07-20 16:23:011429TEST_F(SpdyNetworkTransactionTest, Head) {
[email protected]d8ef27b2010-08-06 17:34:391430 // Setup the request
1431 HttpRequestInfo request;
1432 request.method = "HEAD";
bncb26024382016-06-29 02:39:451433 request.url = default_url_;
[email protected]d8ef27b2010-08-06 17:34:391434
bnc086b39e12016-06-24 13:05:261435 SpdyHeaderBlock head_headers(
bncb26024382016-06-29 02:39:451436 spdy_util_.ConstructHeadHeaderBlock(kDefaultUrl, 0));
bnc42331402016-07-25 13:36:151437 SpdySerializedFrame req(spdy_util_.ConstructSpdyHeaders(
1438 1, std::move(head_headers), LOWEST, true));
[email protected]d8ef27b2010-08-06 17:34:391439 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411440 CreateMockWrite(req, 0),
[email protected]d8ef27b2010-08-06 17:34:391441 };
1442
bnc42331402016-07-25 13:36:151443 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411444 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391445 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411446 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521447 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391448 };
1449
rch08e3aa3e2015-05-16 14:27:521450 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:011451 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
1452 NULL);
[email protected]dd54bd82012-07-19 23:44:571453 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391454 TransactionHelperResult out = helper.output();
1455
robpercival214763f2016-07-01 23:27:011456 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021457 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391458}
1459
[email protected]72552f02009-10-28 15:25:011460// Test that a simple POST works.
bncd16676a2016-07-20 16:23:011461TEST_F(SpdyNetworkTransactionTest, Post) {
bncdf80d44fd2016-07-15 20:27:411462 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:451463 kDefaultUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
bncdf80d44fd2016-07-15 20:27:411464 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141465 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411466 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141467 };
[email protected]72552f02009-10-28 15:25:011468
bnc42331402016-07-25 13:36:151469 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]ff57bb82009-11-12 06:52:141470 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411471 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521472 MockRead(ASYNC, 0, 4) // EOF
[email protected]aea80602009-09-18 00:55:081473 };
1474
rch08e3aa3e2015-05-16 14:27:521475 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361476 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011477 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:571478 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471479 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011480 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021481 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]aea80602009-09-18 00:55:081482 EXPECT_EQ("hello!", out.response_data);
1483}
1484
[email protected]69e6b4a2012-10-18 08:03:011485// Test that a POST with a file works.
bncd16676a2016-07-20 16:23:011486TEST_F(SpdyNetworkTransactionTest, FilePost) {
bncdf80d44fd2016-07-15 20:27:411487 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:451488 kDefaultUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
bncdf80d44fd2016-07-15 20:27:411489 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011490 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411491 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011492 };
1493
bnc42331402016-07-25 13:36:151494 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011495 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411496 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521497 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011498 };
1499
rch08e3aa3e2015-05-16 14:27:521500 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361501 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011502 BoundNetLog(), NULL);
[email protected]69e6b4a2012-10-18 08:03:011503 helper.RunToCompletion(&data);
1504 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011505 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021506 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011507 EXPECT_EQ("hello!", out.response_data);
1508}
1509
[email protected]999dd8c2013-11-12 06:45:541510// Test that a POST with a unreadable file fails.
bncd16676a2016-07-20 16:23:011511TEST_F(SpdyNetworkTransactionTest, UnreadableFilePost) {
[email protected]999dd8c2013-11-12 06:45:541512 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521513 MockWrite(ASYNC, 0, 0) // EOF
[email protected]999dd8c2013-11-12 06:45:541514 };
1515 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521516 MockRead(ASYNC, 0, 1) // EOF
[email protected]999dd8c2013-11-12 06:45:541517 };
1518
rch08e3aa3e2015-05-16 14:27:521519 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]999dd8c2013-11-12 06:45:541520 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
bncd16676a2016-07-20 16:23:011521 DEFAULT_PRIORITY, BoundNetLog(), NULL);
[email protected]999dd8c2013-11-12 06:45:541522 helper.RunPreTestSetup();
1523 helper.AddData(&data);
1524 helper.RunDefaultTest();
1525
1526 base::RunLoop().RunUntilIdle();
1527 helper.VerifyDataNotConsumed();
robpercival214763f2016-07-01 23:27:011528 EXPECT_THAT(helper.output().rv, IsError(ERR_ACCESS_DENIED));
[email protected]999dd8c2013-11-12 06:45:541529}
1530
[email protected]69e6b4a2012-10-18 08:03:011531// Test that a complex POST works.
bncd16676a2016-07-20 16:23:011532TEST_F(SpdyNetworkTransactionTest, ComplexPost) {
bncdf80d44fd2016-07-15 20:27:411533 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:451534 kDefaultUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
bncdf80d44fd2016-07-15 20:27:411535 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011536 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411537 CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011538 };
1539
bnc42331402016-07-25 13:36:151540 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011541 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411542 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521543 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011544 };
1545
rch08e3aa3e2015-05-16 14:27:521546 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]69e6b4a2012-10-18 08:03:011547 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
bncd16676a2016-07-20 16:23:011548 DEFAULT_PRIORITY, BoundNetLog(), NULL);
[email protected]69e6b4a2012-10-18 08:03:011549 helper.RunToCompletion(&data);
1550 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011551 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021552 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011553 EXPECT_EQ("hello!", out.response_data);
1554}
1555
[email protected]0c9bf872011-03-04 17:53:221556// Test that a chunked POST works.
bncd16676a2016-07-20 16:23:011557TEST_F(SpdyNetworkTransactionTest, ChunkedPost) {
bncdf80d44fd2016-07-15 20:27:411558 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1559 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]0c9bf872011-03-04 17:53:221560 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411561 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
[email protected]0c9bf872011-03-04 17:53:221562 };
1563
bnc42331402016-07-25 13:36:151564 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]0c9bf872011-03-04 17:53:221565 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411566 CreateMockRead(resp, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521567 MockRead(ASYNC, 0, 4) // EOF
[email protected]0c9bf872011-03-04 17:53:221568 };
1569
rch08e3aa3e2015-05-16 14:27:521570 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]0c9bf872011-03-04 17:53:221571 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
bncd16676a2016-07-20 16:23:011572 DEFAULT_PRIORITY, BoundNetLog(), NULL);
[email protected]34b345f92013-02-22 03:27:261573
1574 // These chunks get merged into a single frame when being sent.
1575 const int kFirstChunkSize = kUploadDataSize/2;
mmenkecbc2b712014-10-09 20:29:071576 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1577 upload_chunked_data_stream()->AppendData(
[email protected]34b345f92013-02-22 03:27:261578 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1579
[email protected]dd54bd82012-07-19 23:44:571580 helper.RunToCompletion(&data);
[email protected]0c9bf872011-03-04 17:53:221581 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011582 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021583 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261584 EXPECT_EQ(kUploadData, out.response_data);
1585}
1586
1587// Test that a chunked POST works with chunks appended after transaction starts.
bncd16676a2016-07-20 16:23:011588TEST_F(SpdyNetworkTransactionTest, DelayedChunkedPost) {
bncdf80d44fd2016-07-15 20:27:411589 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1590 SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false));
1591 SpdySerializedFrame chunk2(spdy_util_.ConstructSpdyDataFrame(1, false));
1592 SpdySerializedFrame chunk3(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]34b345f92013-02-22 03:27:261593 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411594 CreateMockWrite(req, 0), CreateMockWrite(chunk1, 1),
1595 CreateMockWrite(chunk2, 2), CreateMockWrite(chunk3, 3),
[email protected]34b345f92013-02-22 03:27:261596 };
1597
bnc42331402016-07-25 13:36:151598 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]34b345f92013-02-22 03:27:261599 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411600 CreateMockRead(resp, 4), CreateMockRead(chunk1, 5),
1601 CreateMockRead(chunk2, 6), CreateMockRead(chunk3, 7),
rch08e3aa3e2015-05-16 14:27:521602 MockRead(ASYNC, 0, 8) // EOF
[email protected]34b345f92013-02-22 03:27:261603 };
1604
rch08e3aa3e2015-05-16 14:27:521605 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]34b345f92013-02-22 03:27:261606 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
bncd16676a2016-07-20 16:23:011607 DEFAULT_PRIORITY, BoundNetLog(), NULL);
[email protected]34b345f92013-02-22 03:27:261608
mmenkecbc2b712014-10-09 20:29:071609 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]34b345f92013-02-22 03:27:261610
1611 helper.RunPreTestSetup();
1612 helper.AddData(&data);
1613 ASSERT_TRUE(helper.StartDefaultTest());
1614
[email protected]fc9d88472013-08-14 02:31:171615 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071616 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]fc9d88472013-08-14 02:31:171617 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071618 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]34b345f92013-02-22 03:27:261619
1620 helper.FinishDefaultTest();
1621 helper.VerifyDataConsumed();
1622
1623 std::string expected_response;
1624 expected_response += kUploadData;
1625 expected_response += kUploadData;
1626 expected_response += kUploadData;
1627
1628 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011629 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021630 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261631 EXPECT_EQ(expected_response, out.response_data);
[email protected]0c9bf872011-03-04 17:53:221632}
1633
[email protected]a33cad2b62010-07-30 22:24:391634// Test that a POST without any post data works.
bncd16676a2016-07-20 16:23:011635TEST_F(SpdyNetworkTransactionTest, NullPost) {
[email protected]a33cad2b62010-07-30 22:24:391636 // Setup the request
1637 HttpRequestInfo request;
1638 request.method = "POST";
bncb26024382016-06-29 02:39:451639 request.url = default_url_;
[email protected]a33cad2b62010-07-30 22:24:391640 // Create an empty UploadData.
[email protected]329b68b2012-11-14 17:54:271641 request.upload_data_stream = NULL;
[email protected]a33cad2b62010-07-30 22:24:391642
[email protected]329b68b2012-11-14 17:54:271643 // When request.upload_data_stream is NULL for post, content-length is
[email protected]a33cad2b62010-07-30 22:24:391644 // expected to be 0.
bnc086b39e12016-06-24 13:05:261645 SpdyHeaderBlock req_block(
bncb26024382016-06-29 02:39:451646 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0));
bncdf80d44fd2016-07-15 20:27:411647 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151648 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block), LOWEST, true));
[email protected]d2c1a97b2014-03-03 19:25:091649
[email protected]a33cad2b62010-07-30 22:24:391650 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411651 CreateMockWrite(req, 0),
[email protected]a33cad2b62010-07-30 22:24:391652 };
1653
bnc42331402016-07-25 13:36:151654 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
bncdf80d44fd2016-07-15 20:27:411655 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]a33cad2b62010-07-30 22:24:391656 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411657 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521658 MockRead(ASYNC, 0, 3) // EOF
[email protected]a33cad2b62010-07-30 22:24:391659 };
1660
rch08e3aa3e2015-05-16 14:27:521661 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]a33cad2b62010-07-30 22:24:391662
bncd16676a2016-07-20 16:23:011663 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
1664 NULL);
[email protected]dd54bd82012-07-19 23:44:571665 helper.RunToCompletion(&data);
[email protected]a33cad2b62010-07-30 22:24:391666 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011667 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021668 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]a33cad2b62010-07-30 22:24:391669 EXPECT_EQ("hello!", out.response_data);
1670}
1671
[email protected]edd3b0a52009-11-24 18:56:361672// Test that a simple POST works.
bncd16676a2016-07-20 16:23:011673TEST_F(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]329b68b2012-11-14 17:54:271674 // Create an empty UploadDataStream.
danakjaee3e1ec2016-04-16 00:23:181675 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221676 ElementsUploadDataStream stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271677
[email protected]edd3b0a52009-11-24 18:56:361678 // Setup the request
1679 HttpRequestInfo request;
1680 request.method = "POST";
bncb26024382016-06-29 02:39:451681 request.url = default_url_;
[email protected]329b68b2012-11-14 17:54:271682 request.upload_data_stream = &stream;
[email protected]edd3b0a52009-11-24 18:56:361683
Avi Drissman13fc8932015-12-20 04:40:461684 const uint64_t kContentLength = 0;
[email protected]d2c1a97b2014-03-03 19:25:091685
bnc086b39e12016-06-24 13:05:261686 SpdyHeaderBlock req_block(
bncb26024382016-06-29 02:39:451687 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kContentLength));
bncdf80d44fd2016-07-15 20:27:411688 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:151689 spdy_util_.ConstructSpdyHeaders(1, std::move(req_block), LOWEST, true));
[email protected]d2c1a97b2014-03-03 19:25:091690
[email protected]edd3b0a52009-11-24 18:56:361691 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411692 CreateMockWrite(req, 0),
[email protected]edd3b0a52009-11-24 18:56:361693 };
1694
bnc42331402016-07-25 13:36:151695 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
bncdf80d44fd2016-07-15 20:27:411696 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361697 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411698 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:521699 MockRead(ASYNC, 0, 3) // EOF
[email protected]edd3b0a52009-11-24 18:56:361700 };
1701
rch08e3aa3e2015-05-16 14:27:521702 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bf2491a92009-11-29 16:39:481703
bncd16676a2016-07-20 16:23:011704 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
1705 NULL);
[email protected]dd54bd82012-07-19 23:44:571706 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471707 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011708 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021709 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]edd3b0a52009-11-24 18:56:361710 EXPECT_EQ("hello!", out.response_data);
1711}
1712
[email protected]35c3fc732014-02-15 00:16:071713// While we're doing a post, the server sends the reply before upload completes.
bncd16676a2016-07-20 16:23:011714TEST_F(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
bncdf80d44fd2016-07-15 20:27:411715 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1716 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]35c3fc732014-02-15 00:16:071717 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411718 CreateMockWrite(req, 0), CreateMockWrite(body, 3),
[email protected]35c3fc732014-02-15 00:16:071719 };
bnc42331402016-07-25 13:36:151720 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]a5566f9702010-05-05 22:25:431721 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411722 CreateMockRead(resp, 1), CreateMockRead(body, 2),
1723 MockRead(ASYNC, 0, 4) // EOF
[email protected]a5566f9702010-05-05 22:25:431724 };
1725
[email protected]35c3fc732014-02-15 00:16:071726 // Write the request headers, and read the complete response
1727 // while still waiting for chunked request data.
mmenke666a6fea2015-12-19 04:16:331728 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]35c3fc732014-02-15 00:16:071729 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
bncd16676a2016-07-20 16:23:011730 DEFAULT_PRIORITY, BoundNetLog(), NULL);
[email protected]c92f4b4542012-07-26 23:53:211731 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:331732 helper.AddData(&data);
[email protected]c92f4b4542012-07-26 23:53:211733
[email protected]35c3fc732014-02-15 00:16:071734 ASSERT_TRUE(helper.StartDefaultTest());
[email protected]c92f4b4542012-07-26 23:53:211735
maksim.sisov8d2df66d2016-06-20 07:07:111736 base::RunLoop().RunUntilIdle();
mmenke666a6fea2015-12-19 04:16:331737
bnc42331402016-07-25 13:36:151738 // Process the request headers, response headers, and response body.
[email protected]35c3fc732014-02-15 00:16:071739 // The request body is still in flight.
[email protected]35c3fc732014-02-15 00:16:071740 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
bnc84e7fb52015-12-02 11:50:021741 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]35c3fc732014-02-15 00:16:071742
1743 // Finish sending the request body.
mmenkecbc2b712014-10-09 20:29:071744 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
maksim.sisov8d2df66d2016-06-20 07:07:111745 helper.WaitForCallbackToComplete();
robpercival214763f2016-07-01 23:27:011746 EXPECT_THAT(helper.output().rv, IsOk());
[email protected]35c3fc732014-02-15 00:16:071747
1748 std::string response_body;
robpercival214763f2016-07-01 23:27:011749 EXPECT_THAT(ReadTransaction(helper.trans(), &response_body), IsOk());
[email protected]35c3fc732014-02-15 00:16:071750 EXPECT_EQ(kUploadData, response_body);
1751 helper.VerifyDataConsumed();
[email protected]a5566f9702010-05-05 22:25:431752}
1753
[email protected]f9a26d72010-08-03 18:07:131754// The client upon cancellation tries to send a RST_STREAM frame. The mock
1755// socket causes the TCP write to return zero. This test checks that the client
1756// tries to queue up the RST_STREAM frame again.
bncd16676a2016-07-20 16:23:011757TEST_F(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
bncdf80d44fd2016-07-15 20:27:411758 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491759 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411760 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201761 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]f9a26d72010-08-03 18:07:131762 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411763 CreateMockWrite(req, 0, SYNCHRONOUS), MockWrite(SYNCHRONOUS, 0, 0, 2),
1764 CreateMockWrite(rst, 3, SYNCHRONOUS),
[email protected]f9a26d72010-08-03 18:07:131765 };
1766
bnc42331402016-07-25 13:36:151767 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]f9a26d72010-08-03 18:07:131768 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411769 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:131770 };
1771
mmenke666a6fea2015-12-19 04:16:331772 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361773 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011774 BoundNetLog(), NULL);
[email protected]f9a26d72010-08-03 18:07:131775 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:331776 helper.AddData(&data);
bnc4d782f492016-08-18 13:50:001777 helper.StartDefaultTest();
1778 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
[email protected]f9a26d72010-08-03 18:07:131779
bnc4d782f492016-08-18 13:50:001780 helper.WaitForCallbackToComplete();
1781 EXPECT_THAT(helper.output().rv, IsOk());
[email protected]3b7828432010-08-18 18:33:271782
[email protected]f9a26d72010-08-03 18:07:131783 helper.ResetTrans();
mmenke666a6fea2015-12-19 04:16:331784 base::RunLoop().RunUntilIdle();
[email protected]3b7828432010-08-18 18:33:271785
[email protected]f9a26d72010-08-03 18:07:131786 helper.VerifyDataConsumed();
1787}
1788
[email protected]93300672009-10-24 13:22:511789// Test that the transaction doesn't crash when we don't have a reply.
bnc42331402016-07-25 13:36:151790TEST_F(SpdyNetworkTransactionTest, ResponseWithoutHeaders) {
bncdf80d44fd2016-07-15 20:27:411791 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141792 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411793 CreateMockRead(body, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]93300672009-10-24 13:22:511794 };
1795
bncdf80d44fd2016-07-15 20:27:411796 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491797 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411798 SpdySerializedFrame rst(
rch08e3aa3e2015-05-16 14:27:521799 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
1800 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411801 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
rch08e3aa3e2015-05-16 14:27:521802 };
1803 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361804 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011805 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:571806 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471807 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011808 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]93300672009-10-24 13:22:511809}
1810
[email protected]d30022352010-06-24 19:17:581811// Test that the transaction doesn't crash when we get two replies on the same
1812// stream ID. See http://crbug.com/45639.
bncd16676a2016-07-20 16:23:011813TEST_F(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
bncdf80d44fd2016-07-15 20:27:411814 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491815 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411816 SpdySerializedFrame rst(
[email protected]00b29472014-01-16 18:10:241817 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]2aeef782013-06-21 18:30:561818 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411819 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
[email protected]2aeef782013-06-21 18:30:561820 };
[email protected]d30022352010-06-24 19:17:581821
bnc42331402016-07-25 13:36:151822 SpdySerializedFrame resp0(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1823 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:411824 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d30022352010-06-24 19:17:581825 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411826 CreateMockRead(resp0, 1), CreateMockRead(resp1, 2),
1827 CreateMockRead(body, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]d30022352010-06-24 19:17:581828 };
1829
rch08e3aa3e2015-05-16 14:27:521830 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d30022352010-06-24 19:17:581831
[email protected]262eec82013-03-19 21:01:361832 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011833 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:471834 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571835 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:471836
1837 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:581838
[email protected]49639fa2011-12-20 23:22:411839 TestCompletionCallback callback;
1840 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011841 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d30022352010-06-24 19:17:581842 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011843 EXPECT_THAT(rv, IsOk());
[email protected]d30022352010-06-24 19:17:581844
1845 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:521846 ASSERT_TRUE(response);
1847 EXPECT_TRUE(response->headers);
[email protected]d30022352010-06-24 19:17:581848 EXPECT_TRUE(response->was_fetched_via_spdy);
1849 std::string response_data;
[email protected]3caf5542010-07-16 15:19:471850 rv = ReadTransaction(trans, &response_data);
robpercival214763f2016-07-01 23:27:011851 EXPECT_THAT(rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]3caf5542010-07-16 15:19:471852
1853 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:581854}
1855
bncd16676a2016-07-20 16:23:011856TEST_F(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:251857 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411858 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491859 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411860 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201861 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:251862 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411863 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
[email protected]b3503002012-03-27 04:57:251864 };
1865
1866 const char* const headers[] = {
[email protected]513963e2013-06-15 01:53:041867 "transfer-encoding", "chunked"
[email protected]b3503002012-03-27 04:57:251868 };
bnc42331402016-07-25 13:36:151869 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(headers, 1, 1));
bncdf80d44fd2016-07-15 20:27:411870 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b3503002012-03-27 04:57:251871 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411872 CreateMockRead(resp, 1), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521873 MockRead(ASYNC, 0, 4) // EOF
[email protected]b3503002012-03-27 04:57:251874 };
1875
rch08e3aa3e2015-05-16 14:27:521876 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361877 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011878 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:571879 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:251880 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011881 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:251882
1883 helper.session()->spdy_session_pool()->CloseAllSessions();
1884 helper.VerifyDataConsumed();
1885}
1886
bncd16676a2016-07-20 16:23:011887TEST_F(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:251888 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411889 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491890 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411891 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201892 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:251893 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411894 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
[email protected]b3503002012-03-27 04:57:251895 };
1896
bnc42331402016-07-25 13:36:151897 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041898 const char* const headers[] = {
1899 "transfer-encoding", "chunked"
1900 };
bncdf80d44fd2016-07-15 20:27:411901 SpdySerializedFrame push(
rchebf12982015-04-10 01:15:001902 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2, 2, 1,
1903 GetDefaultUrlWithPath("/1").c_str()));
bncdf80d44fd2016-07-15 20:27:411904 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b3503002012-03-27 04:57:251905 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411906 CreateMockRead(resp, 1), CreateMockRead(push, 2), CreateMockRead(body, 3),
rch08e3aa3e2015-05-16 14:27:521907 MockRead(ASYNC, 0, 5) // EOF
[email protected]b3503002012-03-27 04:57:251908 };
1909
rch08e3aa3e2015-05-16 14:27:521910 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361911 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011912 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:571913 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:251914 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:011915 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:021916 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b3503002012-03-27 04:57:251917 EXPECT_EQ("hello!", out.response_data);
1918
1919 helper.session()->spdy_session_pool()->CloseAllSessions();
1920 helper.VerifyDataConsumed();
1921}
1922
bncd16676a2016-07-20 16:23:011923TEST_F(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:381924 // Construct the request.
bncdf80d44fd2016-07-15 20:27:411925 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491926 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]34437af82009-11-06 02:28:491927 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411928 CreateMockWrite(req),
[email protected]34437af82009-11-06 02:28:491929 };
1930
bnc42331402016-07-25 13:36:151931 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]34437af82009-11-06 02:28:491932 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411933 CreateMockRead(resp),
1934 // This following read isn't used by the test, except during the
1935 // RunUntilIdle() call at the end since the SpdySession survives the
1936 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
1937 // MockRead will do here.
1938 MockRead(ASYNC, 0, 0) // EOF
[email protected]34437af82009-11-06 02:28:491939 };
1940
[email protected]31a2bfe2010-02-09 08:03:391941 StaticSocketDataProvider data(reads, arraysize(reads),
1942 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:471943
[email protected]262eec82013-03-19 21:01:361944 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011945 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:471946 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:581947 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:471948 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:491949
[email protected]49639fa2011-12-20 23:22:411950 TestCompletionCallback callback;
1951 int rv = trans->Start(
1952 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011953 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3caf5542010-07-16 15:19:471954 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:491955
[email protected]30c942b2010-07-21 16:59:591956 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:491957 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:171958 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:471959 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:491960}
[email protected]72552f02009-10-28 15:25:011961
[email protected]6c6ea172010-07-27 20:04:031962// Verify that the client sends a Rst Frame upon cancelling the stream.
bncd16676a2016-07-20 16:23:011963TEST_F(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
bncdf80d44fd2016-07-15 20:27:411964 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:491965 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:411966 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:201967 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]6c6ea172010-07-27 20:04:031968 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:411969 CreateMockWrite(req, 0, SYNCHRONOUS),
1970 CreateMockWrite(rst, 2, SYNCHRONOUS),
[email protected]6c6ea172010-07-27 20:04:031971 };
1972
bnc42331402016-07-25 13:36:151973 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]6c6ea172010-07-27 20:04:031974 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:411975 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:031976 };
1977
mmenke666a6fea2015-12-19 04:16:331978 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]6c6ea172010-07-27 20:04:031979
[email protected]262eec82013-03-19 21:01:361980 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:011981 BoundNetLog(), NULL);
[email protected]6c6ea172010-07-27 20:04:031982 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:331983 helper.AddData(&data);
[email protected]6c6ea172010-07-27 20:04:031984 HttpNetworkTransaction* trans = helper.trans();
1985
[email protected]49639fa2011-12-20 23:22:411986 TestCompletionCallback callback;
[email protected]6c6ea172010-07-27 20:04:031987
[email protected]49639fa2011-12-20 23:22:411988 int rv = trans->Start(
1989 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011990 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]6c6ea172010-07-27 20:04:031991
[email protected]3b7828432010-08-18 18:33:271992 helper.ResetTrans();
mmenke666a6fea2015-12-19 04:16:331993 base::RunLoop().RunUntilIdle();
[email protected]3b7828432010-08-18 18:33:271994
[email protected]6c6ea172010-07-27 20:04:031995 helper.VerifyDataConsumed();
1996}
1997
[email protected]b278eb72010-07-09 20:17:001998// Verify that the client can correctly deal with the user callback attempting
1999// to start another transaction on a session that is closing down. See
2000// http://crbug.com/47455
bncd16676a2016-07-20 16:23:012001TEST_F(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
bncdf80d44fd2016-07-15 20:27:412002 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:492003 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412004 MockWrite writes[] = {CreateMockWrite(req)};
2005 MockWrite writes2[] = {CreateMockWrite(req, 0)};
[email protected]b278eb72010-07-09 20:17:002006
[email protected]cbdd73162013-03-18 23:27:332007 // The indicated length of this frame is longer than its actual length. When
2008 // the session receives an empty frame after this one, it shuts down the
[email protected]b278eb72010-07-09 20:17:002009 // session, and calls the read callback with the incomplete data.
Avi Drissman13fc8932015-12-20 04:40:462010 const uint8_t kGetBodyFrame2[] = {
2011 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
2012 0x07, 'h', 'e', 'l', 'l', 'o', '!',
[email protected]b278eb72010-07-09 20:17:002013 };
2014
bnc42331402016-07-25 13:36:152015 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]b278eb72010-07-09 20:17:002016 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412017 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:092018 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2019 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2020 arraysize(kGetBodyFrame2), 3),
2021 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
2022 MockRead(ASYNC, 0, 0, 5), // EOF
[email protected]b278eb72010-07-09 20:17:002023 };
2024 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:412025 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 0, 2), // EOF
[email protected]b278eb72010-07-09 20:17:002026 };
2027
rch32320842015-05-16 15:57:092028 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
rch08e3aa3e2015-05-16 14:27:522029 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2030 arraysize(writes2));
[email protected]3caf5542010-07-16 15:19:472031
[email protected]262eec82013-03-19 21:01:362032 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012033 BoundNetLog(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582034 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572035 helper.AddData(&data);
2036 helper.AddData(&data2);
[email protected]3caf5542010-07-16 15:19:472037 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002038
2039 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412040 TestCompletionCallback callback;
2041 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012042 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b278eb72010-07-09 20:17:002043 rv = callback.WaitForResult();
2044
[email protected]b278eb72010-07-09 20:17:002045 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162046 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412047 rv = trans->Read(
rchebf12982015-04-10 01:15:002048 buf.get(), kSize,
[email protected]513963e2013-06-15 01:53:042049 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
bncb26024382016-06-29 02:39:452050 helper.session(), default_url_));
robpercival214763f2016-07-01 23:27:012051 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3caf5542010-07-16 15:19:472052 // This forces an err_IO_pending, which sets the callback.
mmenkee24011922015-12-17 22:12:592053 data.Resume();
2054 data.RunUntilPaused();
2055
[email protected]3caf5542010-07-16 15:19:472056 // This finishes the read.
mmenkee24011922015-12-17 22:12:592057 data.Resume();
2058 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472059 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002060}
2061
[email protected]9be804c82010-06-24 17:59:462062// Verify that the client can correctly deal with the user callback deleting the
2063// transaction. Failures will usually be valgrind errors. See
2064// http://crbug.com/46925
bncd16676a2016-07-20 16:23:012065TEST_F(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
bncdf80d44fd2016-07-15 20:27:412066 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:492067 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412068 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]9be804c82010-06-24 17:59:462069
bnc42331402016-07-25 13:36:152070 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412071 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462072 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412073 CreateMockRead(resp, 1),
2074 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2075 CreateMockRead(body, 3), MockRead(ASYNC, 0, 0, 4), // EOF
[email protected]9be804c82010-06-24 17:59:462076 };
2077
rch32320842015-05-16 15:57:092078 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472079
[email protected]262eec82013-03-19 21:01:362080 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012081 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:472082 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572083 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472084 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462085
2086 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412087 TestCompletionCallback callback;
2088 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012089 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9be804c82010-06-24 17:59:462090 rv = callback.WaitForResult();
2091
2092 // Setup a user callback which will delete the session, and clear out the
2093 // memory holding the stream object. Note that the callback deletes trans.
[email protected]9be804c82010-06-24 17:59:462094 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162095 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412096 rv = trans->Read(
[email protected]90499482013-06-01 00:39:502097 buf.get(),
2098 kSize,
[email protected]513963e2013-06-15 01:53:042099 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
[email protected]49639fa2011-12-20 23:22:412100 base::Unretained(&helper)));
robpercival214763f2016-07-01 23:27:012101 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
mmenkee24011922015-12-17 22:12:592102 data.Resume();
[email protected]9be804c82010-06-24 17:59:462103
2104 // Finish running rest of tasks.
[email protected]fc9d88472013-08-14 02:31:172105 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472106 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462107}
2108
allada71b2efb2016-09-09 04:57:482109TEST_F(SpdyNetworkTransactionTest, TestRawHeaderSizeSuccessfullRequest) {
2110 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2111 headers["user-agent"] = "";
2112 headers["accept-encoding"] = "gzip, deflate";
2113
2114 SpdySerializedFrame req(
2115 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
2116 MockWrite writes[] = {
2117 CreateMockWrite(req, 0),
2118 };
2119
2120 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2121
2122 SpdySerializedFrame response_body_frame(
2123 spdy_util_.ConstructSpdyDataFrame(1, "should not include", 18, true));
2124
2125 MockRead response_headers(CreateMockRead(resp, 1));
2126 MockRead reads[] = {
2127 response_headers, CreateMockRead(response_body_frame, 2),
2128 MockRead(ASYNC, 0, 0, 3) // EOF
2129 };
2130 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2131
2132 TestDelegate delegate;
2133 SpdyURLRequestContext spdy_url_request_context;
2134 TestNetworkDelegate network_delegate;
2135 spdy_url_request_context.set_network_delegate(&network_delegate);
2136 SSLSocketDataProvider ssl_data(ASYNC, OK);
2137 ssl_data.next_proto = kProtoHTTP2;
2138
2139 std::unique_ptr<URLRequest> request(spdy_url_request_context.CreateRequest(
2140 GURL(kDefaultUrl), DEFAULT_PRIORITY, &delegate));
2141 spdy_url_request_context.socket_factory().AddSSLSocketDataProvider(&ssl_data);
2142 spdy_url_request_context.socket_factory().AddSocketDataProvider(&data);
2143
2144 request->Start();
2145 base::RunLoop().Run();
2146
2147 EXPECT_LT(0, request->GetTotalSentBytes());
2148 EXPECT_LT(0, request->GetTotalReceivedBytes());
2149 EXPECT_EQ(network_delegate.total_network_bytes_sent(),
2150 request->GetTotalSentBytes());
2151 EXPECT_EQ(network_delegate.total_network_bytes_received(),
2152 request->GetTotalReceivedBytes());
2153 EXPECT_EQ(response_headers.data_len, request->raw_header_size());
2154 EXPECT_TRUE(data.AllReadDataConsumed());
2155 EXPECT_TRUE(data.AllWriteDataConsumed());
2156}
2157
2158TEST_F(SpdyNetworkTransactionTest,
2159 TestRawHeaderSizeSuccessfullPushHeadersFirst) {
2160 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
2161 headers["user-agent"] = "";
2162 headers["accept-encoding"] = "gzip, deflate";
2163
2164 SpdySerializedFrame req(
2165 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
2166 MockWrite writes[] = {
2167 CreateMockWrite(req, 0),
2168 };
2169
2170 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2171 SpdySerializedFrame response_body_frame(
2172 spdy_util_.ConstructSpdyDataFrame(1, "should not include", 18, true));
2173
2174 SpdyHeaderBlock push_headers;
2175 spdy_util_.AddUrlToHeaderBlock(std::string(kDefaultUrl) + "b.dat",
2176 &push_headers);
2177
2178 SpdySerializedFrame push_init_frame(
2179 spdy_util_.ConstructInitialSpdyPushFrame(std::move(push_headers), 2, 1));
2180
2181 SpdySerializedFrame push_headers_frame(
2182 spdy_util_.ConstructSpdyPushHeaders(2, nullptr, 0));
2183
2184 SpdySerializedFrame push_body_frame(spdy_util_.ConstructSpdyDataFrame(
2185 2, "should not include either", 25, false));
2186
2187 MockRead push_init_read(CreateMockRead(push_init_frame, 1));
2188 MockRead response_headers(CreateMockRead(resp, 4));
2189 // raw_header_size() will contain the size of the push promise frame
2190 // initialization.
2191 int expected_response_headers_size =
2192 response_headers.data_len + push_init_read.data_len;
2193
2194 MockRead reads[] = {
2195 push_init_read,
2196 CreateMockRead(push_headers_frame, 2),
2197 CreateMockRead(push_body_frame, 3),
2198 response_headers,
2199 CreateMockRead(response_body_frame, 5),
2200 MockRead(ASYNC, 0, 6) // EOF
2201 };
2202
2203 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2204
2205 TestDelegate delegate;
2206 SpdyURLRequestContext spdy_url_request_context;
2207 TestNetworkDelegate network_delegate;
2208 spdy_url_request_context.set_network_delegate(&network_delegate);
2209 SSLSocketDataProvider ssl_data(ASYNC, OK);
2210 ssl_data.next_proto = kProtoHTTP2;
2211
2212 std::unique_ptr<URLRequest> request(spdy_url_request_context.CreateRequest(
2213 GURL(kDefaultUrl), DEFAULT_PRIORITY, &delegate));
2214 spdy_url_request_context.socket_factory().AddSSLSocketDataProvider(&ssl_data);
2215 spdy_url_request_context.socket_factory().AddSocketDataProvider(&data);
2216
2217 request->Start();
2218 base::RunLoop().Run();
2219
2220 EXPECT_LT(0, request->GetTotalSentBytes());
2221 EXPECT_LT(0, request->GetTotalReceivedBytes());
2222 EXPECT_EQ(network_delegate.total_network_bytes_sent(),
2223 request->GetTotalSentBytes());
2224 EXPECT_EQ(network_delegate.total_network_bytes_received(),
2225 request->GetTotalReceivedBytes());
2226 EXPECT_EQ(expected_response_headers_size, request->raw_header_size());
2227 EXPECT_TRUE(data.AllReadDataConsumed());
2228 EXPECT_TRUE(data.AllWriteDataConsumed());
2229}
2230
bncce36dca22015-04-21 22:11:232231// Send a spdy request to www.example.org that gets redirected to www.foo.com.
bncd16676a2016-07-20 16:23:012232TEST_F(SpdyNetworkTransactionTest, DISABLED_RedirectGetRequest) {
bncb26024382016-06-29 02:39:452233 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc086b39e12016-06-24 13:05:262234 headers["user-agent"] = "";
2235 headers["accept-encoding"] = "gzip, deflate";
[email protected]e3ebba0f2010-08-05 17:59:582236
bncce36dca22015-04-21 22:11:232237 // Setup writes/reads to www.example.org
bncdf80d44fd2016-07-15 20:27:412238 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:152239 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
2240 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReplyRedirect(1));
[email protected]e3ebba0f2010-08-05 17:59:582241 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412242 CreateMockWrite(req, 1),
[email protected]e3ebba0f2010-08-05 17:59:582243 };
2244 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412245 CreateMockRead(resp, 2), MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582246 };
bnc086b39e12016-06-24 13:05:262247 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]e3ebba0f2010-08-05 17:59:582248
2249 // Setup writes/reads to www.foo.com
bnc086b39e12016-06-24 13:05:262250 SpdyHeaderBlock headers2(
2251 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2252 headers2["user-agent"] = "";
2253 headers2["accept-encoding"] = "gzip, deflate";
bncdf80d44fd2016-07-15 20:27:412254 SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:152255 spdy_util_.ConstructSpdyHeaders(1, std::move(headers2), LOWEST, true));
bnc086b39e12016-06-24 13:05:262256 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:412257 CreateMockWrite(req2, 1),
bnc086b39e12016-06-24 13:05:262258 };
2259
bnc42331402016-07-25 13:36:152260 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412261 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582262 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:412263 CreateMockRead(resp2, 2), CreateMockRead(body2, 3),
2264 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582265 };
bnc086b39e12016-06-24 13:05:262266
rch08e3aa3e2015-05-16 14:27:522267 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2268 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582269
2270 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582271 TestDelegate d;
2272 {
bnca9b9e222016-07-11 20:10:402273 SpdyURLRequestContext spdy_url_request_context;
danakjaee3e1ec2016-04-16 00:23:182274 std::unique_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
bncb26024382016-06-29 02:39:452275 default_url_, DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092276 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572277 AddSocketDataProvider(&data);
[email protected]ef2bf422012-05-11 03:27:092278 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572279 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582280
2281 d.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192282 r->Start();
[email protected]fc9d88472013-08-14 02:31:172283 base::RunLoop().Run();
[email protected]513963e2013-06-15 01:53:042284
[email protected]e3ebba0f2010-08-05 17:59:582285 EXPECT_EQ(1, d.received_redirect_count());
2286
[email protected]f7022f32014-08-21 16:32:192287 r->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172288 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582289 EXPECT_EQ(1, d.response_started_count());
2290 EXPECT_FALSE(d.received_data_before_response());
allada71b2efb2016-09-09 04:57:482291 EXPECT_EQ(OK, r->status().error());
[email protected]e3ebba0f2010-08-05 17:59:582292 std::string contents("hello!");
2293 EXPECT_EQ(contents, d.data_received());
2294 }
rch37de576c2015-05-17 20:28:172295 EXPECT_TRUE(data.AllReadDataConsumed());
2296 EXPECT_TRUE(data.AllWriteDataConsumed());
2297 EXPECT_TRUE(data2.AllReadDataConsumed());
2298 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582299}
2300
bncce36dca22015-04-21 22:11:232301// Send a spdy request to www.example.org. Get a pushed stream that redirects to
[email protected]e3ebba0f2010-08-05 17:59:582302// www.foo.com.
bncd16676a2016-07-20 16:23:012303TEST_F(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
bncb26024382016-06-29 02:39:452304 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc086b39e12016-06-24 13:05:262305 headers["user-agent"] = "";
2306 headers["accept-encoding"] = "gzip, deflate";
[email protected]3a8d6852011-03-11 23:43:442307
bncce36dca22015-04-21 22:11:232308 // Setup writes/reads to www.example.org
bncdf80d44fd2016-07-15 20:27:412309 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:152310 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
2311 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412312 SpdySerializedFrame rep(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002313 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
2314 "301 Moved Permanently", "http://www.foo.com/index.php"));
bncdf80d44fd2016-07-15 20:27:412315 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
2316 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:202317 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]3a8d6852011-03-11 23:43:442318 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412319 CreateMockWrite(req, 1), CreateMockWrite(rst, 6),
[email protected]3a8d6852011-03-11 23:43:442320 };
2321 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412322 CreateMockRead(resp, 2), CreateMockRead(rep, 3), CreateMockRead(body, 4),
2323 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2324 MockRead(ASYNC, 0, 0, 7) // EOF
[email protected]3a8d6852011-03-11 23:43:442325 };
2326
2327 // Setup writes/reads to www.foo.com
bnc086b39e12016-06-24 13:05:262328 SpdyHeaderBlock headers2(
[email protected]513963e2013-06-15 01:53:042329 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
bnc086b39e12016-06-24 13:05:262330 headers2["user-agent"] = "";
2331 headers2["accept-encoding"] = "gzip, deflate";
bncdf80d44fd2016-07-15 20:27:412332 SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:152333 spdy_util_.ConstructSpdyHeaders(1, std::move(headers2), LOWEST, true));
2334 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412335 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582336 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:412337 CreateMockWrite(req2, 1),
[email protected]e3ebba0f2010-08-05 17:59:582338 };
2339 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:412340 CreateMockRead(resp2, 2), CreateMockRead(body2, 3),
2341 MockRead(ASYNC, 0, 0, 5) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582342 };
rch08e3aa3e2015-05-16 14:27:522343 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2344 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2345 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582346
[email protected]e3ebba0f2010-08-05 17:59:582347 TestDelegate d;
2348 TestDelegate d2;
bnca9b9e222016-07-11 20:10:402349 SpdyURLRequestContext spdy_url_request_context;
[email protected]e3ebba0f2010-08-05 17:59:582350 {
danakjaee3e1ec2016-04-16 00:23:182351 std::unique_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
bncb26024382016-06-29 02:39:452352 default_url_, DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092353 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572354 AddSocketDataProvider(&data);
[email protected]e3ebba0f2010-08-05 17:59:582355
[email protected]f7022f32014-08-21 16:32:192356 r->Start();
[email protected]fc9d88472013-08-14 02:31:172357 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582358
2359 EXPECT_EQ(0, d.received_redirect_count());
2360 std::string contents("hello!");
2361 EXPECT_EQ(contents, d.data_received());
2362
danakjaee3e1ec2016-04-16 00:23:182363 std::unique_ptr<URLRequest> r2(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002364 GURL(GetDefaultUrlWithPath("/foo.dat")), DEFAULT_PRIORITY, &d2));
[email protected]ef2bf422012-05-11 03:27:092365 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572366 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582367
2368 d2.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192369 r2->Start();
[email protected]fc9d88472013-08-14 02:31:172370 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582371 EXPECT_EQ(1, d2.received_redirect_count());
2372
[email protected]f7022f32014-08-21 16:32:192373 r2->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172374 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582375 EXPECT_EQ(1, d2.response_started_count());
2376 EXPECT_FALSE(d2.received_data_before_response());
allada71b2efb2016-09-09 04:57:482377 EXPECT_EQ(OK, r2->status().error());
[email protected]e3ebba0f2010-08-05 17:59:582378 std::string contents2("hello!");
2379 EXPECT_EQ(contents2, d2.data_received());
2380 }
rch08e3aa3e2015-05-16 14:27:522381 EXPECT_TRUE(data.AllReadDataConsumed());
2382 EXPECT_TRUE(data.AllWriteDataConsumed());
2383 EXPECT_TRUE(data2.AllReadDataConsumed());
2384 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582385}
2386
bncd16676a2016-07-20 16:23:012387TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
bncdf80d44fd2016-07-15 20:27:412388 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492389 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412390 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582391 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412392 CreateMockWrite(stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582393 };
2394
bncdf80d44fd2016-07-15 20:27:412395 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152396 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412397 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002398 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432399 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412400 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2401 2, kPushedData, strlen(kPushedData), true));
[email protected]e3ebba0f2010-08-05 17:59:582402 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412403 CreateMockRead(stream1_reply, 1),
2404 CreateMockRead(stream2_syn, 2),
2405 CreateMockRead(stream1_body, 3, SYNCHRONOUS),
2406 CreateMockRead(stream2_body, 4),
rch08e3aa3e2015-05-16 14:27:522407 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582408 };
2409
2410 HttpResponseInfo response;
2411 HttpResponseInfo response2;
[email protected]19ec8a72010-08-23 03:38:232412 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522413 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572414 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032415 &response,
2416 &response2,
2417 expected_push_result);
[email protected]e3ebba0f2010-08-05 17:59:582418
bnc42331402016-07-25 13:36:152419 // Verify the response headers.
wezca1070932016-05-26 20:30:522420 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022421 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582422
2423 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522424 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042425 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582426}
2427
bnc42331402016-07-25 13:36:152428TEST_F(SpdyNetworkTransactionTest, ServerPushBeforeHeaders) {
bncdf80d44fd2016-07-15 20:27:412429 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492430 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]a5b8eb29d2012-03-06 06:19:462431 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412432 CreateMockWrite(stream1_syn, 0),
[email protected]a5b8eb29d2012-03-06 06:19:462433 };
2434
bncdf80d44fd2016-07-15 20:27:412435 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc38dcd392016-02-09 23:19:492436 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:412437 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152438 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412439 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8a0fc822013-06-27 20:52:432440 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412441 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2442 2, kPushedData, strlen(kPushedData), true));
[email protected]a5b8eb29d2012-03-06 06:19:462443 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412444 CreateMockRead(stream2_syn, 1),
2445 CreateMockRead(stream1_reply, 2),
2446 CreateMockRead(stream1_body, 3, SYNCHRONOUS),
2447 CreateMockRead(stream2_body, 4),
rch08e3aa3e2015-05-16 14:27:522448 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]a5b8eb29d2012-03-06 06:19:462449 };
2450
2451 HttpResponseInfo response;
2452 HttpResponseInfo response2;
2453 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522454 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572455 RunServerPushTest(&data,
[email protected]a5b8eb29d2012-03-06 06:19:462456 &response,
2457 &response2,
2458 expected_push_result);
2459
bnc42331402016-07-25 13:36:152460 // Verify the response headers.
wezca1070932016-05-26 20:30:522461 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022462 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]a5b8eb29d2012-03-06 06:19:462463
2464 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522465 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042466 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]a5b8eb29d2012-03-06 06:19:462467}
2468
bncd16676a2016-07-20 16:23:012469TEST_F(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
bncdf80d44fd2016-07-15 20:27:412470 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492471 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:522472 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412473 CreateMockWrite(stream1_syn, 0),
rch08e3aa3e2015-05-16 14:27:522474 };
[email protected]82918cc2010-08-25 17:24:502475
bncdf80d44fd2016-07-15 20:27:412476 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152477 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412478 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002479 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432480 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412481 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2482 2, kPushedData, strlen(kPushedData), true));
2483 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]82918cc2010-08-25 17:24:502484 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412485 CreateMockRead(stream1_reply, 1),
2486 CreateMockRead(stream2_syn, 2),
2487 CreateMockRead(stream2_body, 3),
2488 CreateMockRead(stream1_body, 4, SYNCHRONOUS),
rch08e3aa3e2015-05-16 14:27:522489 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]82918cc2010-08-25 17:24:502490 };
2491
2492 HttpResponseInfo response;
2493 HttpResponseInfo response2;
2494 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522495 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572496 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032497 &response,
2498 &response2,
2499 expected_push_result);
[email protected]82918cc2010-08-25 17:24:502500
bnc42331402016-07-25 13:36:152501 // Verify the response headers.
wezca1070932016-05-26 20:30:522502 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022503 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]82918cc2010-08-25 17:24:502504
2505 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522506 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042507 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]82918cc2010-08-25 17:24:502508}
2509
bncd16676a2016-07-20 16:23:012510TEST_F(SpdyNetworkTransactionTest, ServerPushServerAborted) {
bncdf80d44fd2016-07-15 20:27:412511 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492512 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412513 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582514 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412515 CreateMockWrite(stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582516 };
2517
bncdf80d44fd2016-07-15 20:27:412518 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152519 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412520 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002521 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:412522 SpdySerializedFrame stream2_rst(
[email protected]c10b20852013-05-15 21:29:202523 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582524 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412525 CreateMockRead(stream1_reply, 1),
2526 CreateMockRead(stream2_syn, 2),
2527 CreateMockRead(stream2_rst, 3),
2528 CreateMockRead(stream1_body, 4, SYNCHRONOUS),
rch08e3aa3e2015-05-16 14:27:522529 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582530 };
2531
rch08e3aa3e2015-05-16 14:27:522532 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362533 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012534 BoundNetLog(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582535
2536 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572537 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582538
2539 HttpNetworkTransaction* trans = helper.trans();
2540
2541 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412542 TestCompletionCallback callback;
2543 int rv = trans->Start(
2544 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012545 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:582546 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012547 EXPECT_THAT(rv, IsOk());
[email protected]19ec8a72010-08-23 03:38:232548
2549 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522550 EXPECT_TRUE(data.AllReadDataConsumed());
2551 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]19ec8a72010-08-23 03:38:232552
bnc42331402016-07-25 13:36:152553 // Verify the response headers.
[email protected]19ec8a72010-08-23 03:38:232554 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522555 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022556 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232557}
2558
[email protected]8a0fc822013-06-27 20:52:432559// Verify that we don't leak streams and that we properly send a reset
2560// if the server pushes the same stream twice.
bncd16676a2016-07-20 16:23:012561TEST_F(SpdyNetworkTransactionTest, ServerPushDuplicate) {
bncdf80d44fd2016-07-15 20:27:412562 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492563 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412564 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2565 SpdySerializedFrame stream3_rst(
[email protected]c10b20852013-05-15 21:29:202566 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
[email protected]fdc165a2010-09-03 03:51:292567 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412568 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream3_rst, 4),
[email protected]fdc165a2010-09-03 03:51:292569 };
2570
bncdf80d44fd2016-07-15 20:27:412571 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152572 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412573 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002574 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432575 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412576 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2577 2, kPushedData, strlen(kPushedData), true));
2578 SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002579 NULL, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]fdc165a2010-09-03 03:51:292580 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412581 CreateMockRead(stream1_reply, 1),
2582 CreateMockRead(stream2_syn, 2),
2583 CreateMockRead(stream3_syn, 3),
2584 CreateMockRead(stream1_body, 5),
2585 CreateMockRead(stream2_body, 6),
rch08e3aa3e2015-05-16 14:27:522586 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7), // Force a pause
[email protected]fdc165a2010-09-03 03:51:292587 };
2588
2589 HttpResponseInfo response;
2590 HttpResponseInfo response2;
2591 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522592 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572593 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032594 &response,
2595 &response2,
2596 expected_push_result);
[email protected]fdc165a2010-09-03 03:51:292597
bnc42331402016-07-25 13:36:152598 // Verify the response headers.
wezca1070932016-05-26 20:30:522599 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022600 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]fdc165a2010-09-03 03:51:292601
2602 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522603 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042604 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]fdc165a2010-09-03 03:51:292605}
2606
bncd16676a2016-07-20 16:23:012607TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
bncdf80d44fd2016-07-15 20:27:412608 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492609 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412610 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232611 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412612 CreateMockWrite(stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232613 };
2614
bncdf80d44fd2016-07-15 20:27:412615 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152616 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412617 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002618 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432619 static const char kPushedData[] = "pushed my darling hello my baby";
bncdf80d44fd2016-07-15 20:27:412620 SpdySerializedFrame stream2_body_base(spdy_util_.ConstructSpdyDataFrame(
2621 2, kPushedData, strlen(kPushedData), true));
[email protected]8a0fc822013-06-27 20:52:432622 const size_t kChunkSize = strlen(kPushedData) / 4;
bncdf80d44fd2016-07-15 20:27:412623 SpdySerializedFrame stream2_body1(stream2_body_base.data(), kChunkSize,
2624 false);
2625 SpdySerializedFrame stream2_body2(stream2_body_base.data() + kChunkSize,
2626 kChunkSize, false);
2627 SpdySerializedFrame stream2_body3(stream2_body_base.data() + 2 * kChunkSize,
2628 kChunkSize, false);
2629 SpdySerializedFrame stream2_body4(stream2_body_base.data() + 3 * kChunkSize,
2630 stream2_body_base.size() - 3 * kChunkSize,
2631 false);
[email protected]19ec8a72010-08-23 03:38:232632 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412633 CreateMockRead(stream1_reply, 1),
2634 CreateMockRead(stream2_syn, 2),
2635 CreateMockRead(stream2_body1, 3),
2636 CreateMockRead(stream2_body2, 4),
2637 CreateMockRead(stream2_body3, 5),
2638 CreateMockRead(stream2_body4, 6),
2639 CreateMockRead(stream1_body, 7, SYNCHRONOUS),
rch08e3aa3e2015-05-16 14:27:522640 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), // Force a pause
[email protected]19ec8a72010-08-23 03:38:232641 };
2642
2643 HttpResponseInfo response;
2644 HttpResponseInfo response2;
2645 std::string expected_push_result("pushed my darling hello my baby");
rch08e3aa3e2015-05-16 14:27:522646 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432647 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232648
bnc42331402016-07-25 13:36:152649 // Verify the response headers.
wezca1070932016-05-26 20:30:522650 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022651 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232652
2653 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522654 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042655 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232656}
2657
bncd16676a2016-07-20 16:23:012658TEST_F(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
bncdf80d44fd2016-07-15 20:27:412659 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492660 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412661 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232662 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412663 CreateMockWrite(stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232664 };
2665
bncdf80d44fd2016-07-15 20:27:412666 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152667 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412668 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002669 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432670 static const char kPushedData[] = "pushed my darling hello my baby";
bncdf80d44fd2016-07-15 20:27:412671 SpdySerializedFrame stream2_body_base(spdy_util_.ConstructSpdyDataFrame(
2672 2, kPushedData, strlen(kPushedData), true));
[email protected]8a0fc822013-06-27 20:52:432673 const size_t kChunkSize = strlen(kPushedData) / 4;
bncdf80d44fd2016-07-15 20:27:412674 SpdySerializedFrame stream2_body1(stream2_body_base.data(), kChunkSize,
2675 false);
2676 SpdySerializedFrame stream2_body2(stream2_body_base.data() + kChunkSize,
2677 kChunkSize, false);
2678 SpdySerializedFrame stream2_body3(stream2_body_base.data() + 2 * kChunkSize,
2679 kChunkSize, false);
2680 SpdySerializedFrame stream2_body4(stream2_body_base.data() + 3 * kChunkSize,
2681 stream2_body_base.size() - 3 * kChunkSize,
2682 false);
[email protected]19ec8a72010-08-23 03:38:232683 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412684 CreateMockRead(stream1_reply, 1),
2685 CreateMockRead(stream2_syn, 2),
2686 CreateMockRead(stream2_body1, 3),
2687 CreateMockRead(stream2_body2, 4),
2688 CreateMockRead(stream2_body3, 5),
2689 CreateMockRead(stream2_body4, 6),
2690 CreateMockRead(stream1_body, 7, SYNCHRONOUS),
rch08e3aa3e2015-05-16 14:27:522691 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8) // Force a pause.
[email protected]19ec8a72010-08-23 03:38:232692 };
2693
2694 HttpResponseInfo response;
2695 HttpResponseInfo response2;
rch08e3aa3e2015-05-16 14:27:522696 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432697 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232698
bnc42331402016-07-25 13:36:152699 // Verify the response headers.
wezca1070932016-05-26 20:30:522700 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022701 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232702
2703 // Verify the pushed stream.
wezca1070932016-05-26 20:30:522704 EXPECT_TRUE(response2.headers);
bnccdc749f2016-01-27 16:39:042705 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232706}
2707
bncd16676a2016-07-20 16:23:012708TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
bncdf80d44fd2016-07-15 20:27:412709 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492710 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412711 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
2712 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_STREAM_ID)."));
[email protected]19ec8a72010-08-23 03:38:232713 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412714 CreateMockWrite(stream1_syn, 0), CreateMockWrite(goaway, 3),
[email protected]19ec8a72010-08-23 03:38:232715 };
2716
bncdf80d44fd2016-07-15 20:27:412717 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152718 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412719 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002720 NULL, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]19ec8a72010-08-23 03:38:232721 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412722 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
[email protected]19ec8a72010-08-23 03:38:232723 };
2724
rch08e3aa3e2015-05-16 14:27:522725 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362726 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012727 BoundNetLog(), NULL);
[email protected]19ec8a72010-08-23 03:38:232728
2729 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572730 helper.AddData(&data);
[email protected]19ec8a72010-08-23 03:38:232731
2732 HttpNetworkTransaction* trans = helper.trans();
2733
2734 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412735 TestCompletionCallback callback;
2736 int rv = trans->Start(
2737 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012738 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]19ec8a72010-08-23 03:38:232739 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012740 EXPECT_THAT(rv, IsOk());
[email protected]e3ebba0f2010-08-05 17:59:582741
2742 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522743 EXPECT_TRUE(data.AllReadDataConsumed());
2744 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582745
bnc42331402016-07-25 13:36:152746 // Verify the response headers.
[email protected]e3ebba0f2010-08-05 17:59:582747 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522748 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022749 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582750}
2751
bncd16676a2016-07-20 16:23:012752TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
bncdf80d44fd2016-07-15 20:27:412753 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492754 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412755 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2756 SpdySerializedFrame stream2_rst(
[email protected]c10b20852013-05-15 21:29:202757 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
[email protected]e3ebba0f2010-08-05 17:59:582758 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412759 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582760 };
2761
bncdf80d44fd2016-07-15 20:27:412762 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152763 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412764 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:002765 NULL, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]e3ebba0f2010-08-05 17:59:582766 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412767 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2768 CreateMockRead(stream1_body, 4),
rch08e3aa3e2015-05-16 14:27:522769 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582770 };
2771
rch08e3aa3e2015-05-16 14:27:522772 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362773 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012774 BoundNetLog(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582775
2776 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572777 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582778
2779 HttpNetworkTransaction* trans = helper.trans();
2780
2781 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412782 TestCompletionCallback callback;
2783 int rv = trans->Start(
2784 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012785 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:582786 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012787 EXPECT_THAT(rv, IsOk());
[email protected]e3ebba0f2010-08-05 17:59:582788
2789 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522790 EXPECT_TRUE(data.AllReadDataConsumed());
2791 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582792
bnc42331402016-07-25 13:36:152793 // Verify the response headers.
[email protected]e3ebba0f2010-08-05 17:59:582794 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522795 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022796 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582797}
2798
bncd16676a2016-07-20 16:23:012799TEST_F(SpdyNetworkTransactionTest, ServerPushNoURL) {
bncdf80d44fd2016-07-15 20:27:412800 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:492801 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412802 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2803 SpdySerializedFrame stream2_rst(
[email protected]c10b20852013-05-15 21:29:202804 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582805 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412806 CreateMockWrite(stream1_syn, 0), CreateMockWrite(stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582807 };
2808
bncdf80d44fd2016-07-15 20:27:412809 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152810 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bnc086b39e12016-06-24 13:05:262811 SpdyHeaderBlock incomplete_headers;
2812 incomplete_headers[spdy_util_.GetStatusKey()] = "200 OK";
bnc086b39e12016-06-24 13:05:262813 incomplete_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:412814 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
2815 std::move(incomplete_headers), 2, 1));
[email protected]e3ebba0f2010-08-05 17:59:582816 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412817 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2818 CreateMockRead(stream1_body, 4),
rch08e3aa3e2015-05-16 14:27:522819 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582820 };
2821
rch08e3aa3e2015-05-16 14:27:522822 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362823 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012824 BoundNetLog(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582825
2826 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572827 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582828
2829 HttpNetworkTransaction* trans = helper.trans();
2830
2831 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412832 TestCompletionCallback callback;
2833 int rv = trans->Start(
2834 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012835 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e3ebba0f2010-08-05 17:59:582836 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012837 EXPECT_THAT(rv, IsOk());
rch08e3aa3e2015-05-16 14:27:522838
[email protected]e3ebba0f2010-08-05 17:59:582839 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522840 EXPECT_TRUE(data.AllReadDataConsumed());
2841 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582842
bnc42331402016-07-25 13:36:152843 // Verify the response headers.
[email protected]e3ebba0f2010-08-05 17:59:582844 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522845 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:022846 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582847}
2848
bnc0cb98b22016-03-04 17:10:522849// PUSH_PROMISE on a server-initiated stream should trigger GOAWAY.
bncd16676a2016-07-20 16:23:012850TEST_F(SpdyNetworkTransactionTest, ServerPushOnPushedStream) {
bncdf80d44fd2016-07-15 20:27:412851 SpdySerializedFrame stream1_syn(
bnc0cb98b22016-03-04 17:10:522852 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412853 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bnc0cb98b22016-03-04 17:10:522854 2, GOAWAY_PROTOCOL_ERROR, "Push on even stream id."));
2855 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412856 CreateMockWrite(stream1_syn, 0), CreateMockWrite(goaway, 4),
bnc0cb98b22016-03-04 17:10:522857 };
2858
bncdf80d44fd2016-07-15 20:27:412859 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152860 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:412861 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:522862 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:412863 SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:522864 nullptr, 0, 4, 2, GetDefaultUrlWithPath("/bar.dat").c_str()));
2865 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412866 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2867 CreateMockRead(stream3_syn, 3),
bnc0cb98b22016-03-04 17:10:522868 };
2869
2870 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2871 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012872 BoundNetLog(), nullptr);
bnc0cb98b22016-03-04 17:10:522873 helper.RunToCompletion(&data);
2874}
2875
2876// PUSH_PROMISE on a closed client-initiated stream should trigger RST_STREAM.
bncd16676a2016-07-20 16:23:012877TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedStream) {
bncdf80d44fd2016-07-15 20:27:412878 SpdySerializedFrame stream1_syn(
bnc0cb98b22016-03-04 17:10:522879 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412880 SpdySerializedFrame rst(
bnc0cb98b22016-03-04 17:10:522881 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
2882 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412883 CreateMockWrite(stream1_syn, 0), CreateMockWrite(rst, 5),
bnc0cb98b22016-03-04 17:10:522884 };
2885
bncdf80d44fd2016-07-15 20:27:412886 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152887 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412888 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
2889 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:522890 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2891 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412892 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_body, 2),
2893 CreateMockRead(stream2_syn, 3), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
bnc0cb98b22016-03-04 17:10:522894 };
2895
2896 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2897 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012898 BoundNetLog(), nullptr);
bnc0cb98b22016-03-04 17:10:522899 helper.RunPreTestSetup();
2900 helper.AddData(&data);
2901
2902 HttpNetworkTransaction* trans = helper.trans();
2903
2904 TestCompletionCallback callback;
2905 int rv =
2906 trans->Start(&CreateGetRequest(), callback.callback(), BoundNetLog());
2907 rv = callback.GetResult(rv);
robpercival214763f2016-07-01 23:27:012908 EXPECT_THAT(rv, IsOk());
bnc0cb98b22016-03-04 17:10:522909 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522910 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:522911 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
2912
2913 EXPECT_TRUE(data.AllReadDataConsumed());
2914 EXPECT_TRUE(data.AllWriteDataConsumed());
2915 VerifyStreamsClosed(helper);
2916}
2917
2918// PUSH_PROMISE on a server-initiated stream should trigger GOAWAY even if
2919// stream is closed.
bncd16676a2016-07-20 16:23:012920TEST_F(SpdyNetworkTransactionTest, ServerPushOnClosedPushedStream) {
bncdf80d44fd2016-07-15 20:27:412921 SpdySerializedFrame stream1_syn(
bnc0cb98b22016-03-04 17:10:522922 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:412923 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bnc0cb98b22016-03-04 17:10:522924 2, GOAWAY_PROTOCOL_ERROR, "Push on even stream id."));
2925 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:412926 CreateMockWrite(stream1_syn, 0), CreateMockWrite(goaway, 7),
bnc0cb98b22016-03-04 17:10:522927 };
2928
bncdf80d44fd2016-07-15 20:27:412929 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:152930 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:412931 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:522932 nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
bncdf80d44fd2016-07-15 20:27:412933 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc0cb98b22016-03-04 17:10:522934 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:412935 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
2936 2, kPushedData, strlen(kPushedData), true));
2937 SpdySerializedFrame stream3_syn(spdy_util_.ConstructSpdyPush(
bnc0cb98b22016-03-04 17:10:522938 nullptr, 0, 4, 2, GetDefaultUrlWithPath("/bar.dat").c_str()));
2939
2940 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:412941 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
2942 CreateMockRead(stream1_body, 3), CreateMockRead(stream2_body, 4),
2943 MockRead(ASYNC, ERR_IO_PENDING, 5), CreateMockRead(stream3_syn, 6),
bnc0cb98b22016-03-04 17:10:522944 };
2945
2946 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2947 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:012948 BoundNetLog(), nullptr);
bnc0cb98b22016-03-04 17:10:522949 helper.RunPreTestSetup();
2950 helper.AddData(&data);
2951
2952 HttpNetworkTransaction* trans1 = helper.trans();
2953 TestCompletionCallback callback1;
2954 int rv =
2955 trans1->Start(&CreateGetRequest(), callback1.callback(), BoundNetLog());
2956 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:012957 EXPECT_THAT(rv, IsOk());
bnc0cb98b22016-03-04 17:10:522958 HttpResponseInfo response = *trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:522959 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:522960 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
2961
bnc691fda62016-08-12 00:43:162962 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
bnc0cb98b22016-03-04 17:10:522963 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:162964 rv = trans2.Start(&CreateGetPushRequest(), callback2.callback(),
2965 BoundNetLog());
bnc0cb98b22016-03-04 17:10:522966 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:012967 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:162968 response = *trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:522969 EXPECT_TRUE(response.headers);
bnc0cb98b22016-03-04 17:10:522970 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
2971 std::string result;
bnc691fda62016-08-12 00:43:162972 ReadResult(&trans2, &result);
bnc0cb98b22016-03-04 17:10:522973 EXPECT_EQ(kPushedData, result);
2974
2975 data.Resume();
2976 base::RunLoop().RunUntilIdle();
2977
2978 EXPECT_TRUE(data.AllReadDataConsumed());
2979 EXPECT_TRUE(data.AllWriteDataConsumed());
2980}
2981
bnc42331402016-07-25 13:36:152982// Verify that various response headers parse correctly through the HTTP layer.
2983TEST_F(SpdyNetworkTransactionTest, ResponseHeaders) {
2984 struct ResponseHeadersTests {
[email protected]e7f75092010-07-01 22:39:132985 int num_headers;
2986 const char* extra_headers[5];
[email protected]513963e2013-06-15 01:53:042987 SpdyHeaderBlock expected_headers;
[email protected]8b070372009-11-16 22:01:252988 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:132989 // This uses a multi-valued cookie header.
2990 { 2,
2991 { "cookie", "val1",
2992 "cookie", "val2", // will get appended separated by NULL
2993 NULL
2994 },
[email protected]8b070372009-11-16 22:01:252995 },
[email protected]e7f75092010-07-01 22:39:132996 // This is the minimalist set of headers.
2997 { 0,
2998 { NULL },
[email protected]8b070372009-11-16 22:01:252999 },
[email protected]e7f75092010-07-01 22:39:133000 // Headers with a comma separated list.
3001 { 1,
3002 { "cookie", "val1,val2",
3003 NULL
3004 },
[email protected]8b070372009-11-16 22:01:253005 }
3006 };
3007
[email protected]513963e2013-06-15 01:53:043008 test_cases[0].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043009 test_cases[1].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043010 test_cases[2].expected_headers["status"] = "200";
[email protected]601e03f12014-04-06 16:26:393011
bnc7ecc1122015-09-28 13:22:493012 test_cases[0].expected_headers["hello"] = "bye";
3013 test_cases[1].expected_headers["hello"] = "bye";
3014 test_cases[2].expected_headers["hello"] = "bye";
3015
bnc2d247912016-04-21 23:34:373016 test_cases[0].expected_headers["cookie"] = base::StringPiece("val1\0val2", 9);
bnc7ecc1122015-09-28 13:22:493017 test_cases[2].expected_headers["cookie"] = "val1,val2";
3018
viettrungluue4a8b882014-10-16 06:17:383019 for (size_t i = 0; i < arraysize(test_cases); ++i) {
bncd16676a2016-07-20 16:23:013020 SpdyTestUtil spdy_test_util;
bncdf80d44fd2016-07-15 20:27:413021 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493022 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413023 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8b070372009-11-16 22:01:253024
bnc42331402016-07-25 13:36:153025 SpdySerializedFrame resp(spdy_test_util.ConstructSpdyGetReply(
bncdf80d44fd2016-07-15 20:27:413026 test_cases[i].extra_headers, test_cases[i].num_headers, 1));
3027 SpdySerializedFrame body(spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]8b070372009-11-16 22:01:253028 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413029 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:523030 MockRead(ASYNC, 0, 3) // EOF
[email protected]8b070372009-11-16 22:01:253031 };
3032
rch08e3aa3e2015-05-16 14:27:523033 SequencedSocketData data(reads, arraysize(reads), writes,
3034 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363035 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013036 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:573037 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473038 TransactionHelperResult out = helper.output();
3039
robpercival214763f2016-07-01 23:27:013040 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023041 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8b070372009-11-16 22:01:253042 EXPECT_EQ("hello!", out.response_data);
3043
3044 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
wezca1070932016-05-26 20:30:523045 EXPECT_TRUE(headers);
olli.raula33c282f2016-01-21 12:12:493046 size_t iter = 0;
[email protected]513963e2013-06-15 01:53:043047 std::string name, value;
3048 SpdyHeaderBlock header_block;
[email protected]8b070372009-11-16 22:01:253049 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
bnc7ecc1122015-09-28 13:22:493050 SpdyHeaderBlock::StringPieceProxy mutable_header_block_value =
3051 header_block[name];
bnc2d247912016-04-21 23:34:373052 if (static_cast<base::StringPiece>(mutable_header_block_value).empty()) {
bnc7ecc1122015-09-28 13:22:493053 mutable_header_block_value = value;
[email protected]513963e2013-06-15 01:53:043054 } else {
bnc7ecc1122015-09-28 13:22:493055 std::string joint_value = mutable_header_block_value.as_string();
3056 joint_value.append(1, '\0');
3057 joint_value.append(value);
3058 mutable_header_block_value = joint_value;
[email protected]513963e2013-06-15 01:53:043059 }
[email protected]8b070372009-11-16 22:01:253060 }
[email protected]513963e2013-06-15 01:53:043061 EXPECT_EQ(test_cases[i].expected_headers, header_block);
[email protected]8b070372009-11-16 22:01:253062 }
3063}
3064
bnc42331402016-07-25 13:36:153065// Verify that various response headers parse vary fields correctly through the
3066// HTTP layer, and the response matches the request.
3067TEST_F(SpdyNetworkTransactionTest, ResponseHeadersVary) {
[email protected]3f662f12010-03-25 19:56:123068 // Modify the following data to change/add test cases:
bnc42331402016-07-25 13:36:153069 struct ResponseTests {
[email protected]3f662f12010-03-25 19:56:123070 bool vary_matches;
3071 int num_headers[2];
3072 const char* extra_headers[2][16];
3073 } test_cases[] = {
bnc7ecc1122015-09-28 13:22:493074 // Test the case of a multi-valued cookie. When the value is delimited
3075 // with NUL characters, it needs to be unfolded into multiple headers.
3076 {true,
bnca9b9e222016-07-11 20:10:403077 {1, 3},
bnc7ecc1122015-09-28 13:22:493078 {{"cookie", "val1,val2", NULL},
3079 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
bnca9b9e222016-07-11 20:10:403080 "/index.php", "vary", "cookie", NULL}}},
bnc7ecc1122015-09-28 13:22:493081 {// Multiple vary fields.
3082 true,
bnc7ecc1122015-09-28 13:22:493083 {2, 4},
3084 {{"friend", "barney", "enemy", "snaggletooth", NULL},
3085 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
bnca9b9e222016-07-11 20:10:403086 "/index.php", "vary", "friend", "vary", "enemy", NULL}}},
3087 {// Test a '*' vary field.
3088 false,
3089 {1, 3},
3090 {{"cookie", "val1,val2", NULL},
3091 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
3092 "/index.php", "vary", "*", NULL}}},
3093 {// Multiple comma-separated vary fields.
3094 true,
3095 {2, 3},
3096 {{"friend", "barney", "enemy", "snaggletooth", NULL},
3097 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
3098 "/index.php", "vary", "friend,enemy", NULL}}}};
[email protected]3f662f12010-03-25 19:56:123099
viettrungluue4a8b882014-10-16 06:17:383100 for (size_t i = 0; i < arraysize(test_cases); ++i) {
bncd16676a2016-07-20 16:23:013101 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:493102
[email protected]3f662f12010-03-25 19:56:123103 // Construct the request.
bncdf80d44fd2016-07-15 20:27:413104 SpdySerializedFrame frame_req(spdy_test_util.ConstructSpdyGet(
3105 test_cases[i].extra_headers[0], test_cases[i].num_headers[0], 1, LOWEST,
3106 true));
[email protected]3f662f12010-03-25 19:56:123107
3108 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:413109 CreateMockWrite(frame_req, 0),
[email protected]3f662f12010-03-25 19:56:123110 };
3111
3112 // Construct the reply.
[email protected]745aa9c2014-06-27 02:21:293113 SpdyHeaderBlock reply_headers;
3114 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3115 test_cases[i].num_headers[1],
3116 &reply_headers);
bnc086b39e12016-06-24 13:05:263117 // Construct the expected header reply string before moving |reply_headers|.
3118 std::string expected_reply =
3119 spdy_test_util.ConstructSpdyReplyString(reply_headers);
3120
bncdf80d44fd2016-07-15 20:27:413121 SpdySerializedFrame frame_reply(
bnc086b39e12016-06-24 13:05:263122 spdy_test_util.ConstructSpdyReply(1, std::move(reply_headers)));
[email protected]3f662f12010-03-25 19:56:123123
bncdf80d44fd2016-07-15 20:27:413124 SpdySerializedFrame body(spdy_test_util.ConstructSpdyDataFrame(1, true));
[email protected]3f662f12010-03-25 19:56:123125 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413126 CreateMockRead(frame_reply, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:523127 MockRead(ASYNC, 0, 3) // EOF
[email protected]3f662f12010-03-25 19:56:123128 };
3129
[email protected]3f662f12010-03-25 19:56:123130 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:433131 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:123132
[email protected]d3cee19d2010-06-22 18:42:183133 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:433134 for (int ct = 0; ct < header_count; ct++) {
3135 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3136 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3137 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:123138 }
3139
rch08e3aa3e2015-05-16 14:27:523140 SequencedSocketData data(reads, arraysize(reads), writes,
3141 arraysize(writes));
bncd16676a2016-07-20 16:23:013142 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
3143 NULL);
[email protected]dd54bd82012-07-19 23:44:573144 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473145 TransactionHelperResult out = helper.output();
3146
[email protected]3f662f12010-03-25 19:56:123147 EXPECT_EQ(OK, out.rv) << i;
bnc84e7fb52015-12-02 11:50:023148 EXPECT_EQ("HTTP/1.1 200", out.status_line) << i;
[email protected]3f662f12010-03-25 19:56:123149 EXPECT_EQ("hello!", out.response_data) << i;
3150
3151 // Test the response information.
[email protected]3f662f12010-03-25 19:56:123152 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3153 test_cases[i].vary_matches) << i;
3154
3155 // Check the headers.
3156 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
wezca1070932016-05-26 20:30:523157 ASSERT_TRUE(headers) << i;
olli.raula33c282f2016-01-21 12:12:493158 size_t iter = 0;
[email protected]3f662f12010-03-25 19:56:123159 std::string name, value, lines;
3160 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3161 lines.append(name);
3162 lines.append(": ");
3163 lines.append(value);
3164 lines.append("\n");
3165 }
3166
[email protected]9aa323192013-05-31 21:38:403167 EXPECT_EQ(expected_reply, lines) << i;
[email protected]3f662f12010-03-25 19:56:123168 }
3169}
3170
bnc42331402016-07-25 13:36:153171// Verify that we don't crash on invalid response headers.
3172TEST_F(SpdyNetworkTransactionTest, InvalidResponseHeaders) {
3173 struct InvalidResponseHeadersTests {
[email protected]e7f75092010-07-01 22:39:133174 int num_headers;
3175 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:483176 } test_cases[] = {
bnc42331402016-07-25 13:36:153177 // Response headers missing status header
bnc7ecc1122015-09-28 13:22:493178 {
bnca9b9e222016-07-11 20:10:403179 3,
3180 {spdy_util_.GetPathKey(), "/index.php", "cookie", "val1", "cookie",
3181 "val2", NULL},
[email protected]e7f75092010-07-01 22:39:133182 },
bnc42331402016-07-25 13:36:153183 // Response headers missing version header
bnc7ecc1122015-09-28 13:22:493184 {
bnca9b9e222016-07-11 20:10:403185 1, {spdy_util_.GetPathKey(), "/index.php", "status", "200", NULL},
[email protected]e7f75092010-07-01 22:39:133186 },
bnc42331402016-07-25 13:36:153187 // Response headers with no headers
bnc7ecc1122015-09-28 13:22:493188 {
3189 0, {NULL},
3190 },
[email protected]dd11b932009-11-30 19:39:483191 };
3192
viettrungluue4a8b882014-10-16 06:17:383193 for (size_t i = 0; i < arraysize(test_cases); ++i) {
bncd16676a2016-07-20 16:23:013194 SpdyTestUtil spdy_test_util;
bnc38dcd392016-02-09 23:19:493195
bncdf80d44fd2016-07-15 20:27:413196 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493197 spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413198 SpdySerializedFrame rst(
bnc38dcd392016-02-09 23:19:493199 spdy_test_util.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:483200 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:413201 CreateMockWrite(req, 0), CreateMockWrite(rst, 2),
[email protected]dd11b932009-11-30 19:39:483202 };
3203
[email protected]745aa9c2014-06-27 02:21:293204 // Construct the reply.
3205 SpdyHeaderBlock reply_headers;
3206 AppendToHeaderBlock(
3207 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
bncdf80d44fd2016-07-15 20:27:413208 SpdySerializedFrame resp(
bnc086b39e12016-06-24 13:05:263209 spdy_test_util.ConstructSpdyReply(1, std::move(reply_headers)));
[email protected]dd11b932009-11-30 19:39:483210 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413211 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]dd11b932009-11-30 19:39:483212 };
3213
rch08e3aa3e2015-05-16 14:27:523214 SequencedSocketData data(reads, arraysize(reads), writes,
3215 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363216 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013217 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:573218 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473219 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013220 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:483221 }
3222}
3223
bncd16676a2016-07-20 16:23:013224TEST_F(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
bncdf80d44fd2016-07-15 20:27:413225 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493226 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413227 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bncf5012992016-04-19 16:36:263228 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 6 (DECOMPRESS_FAILURE)."));
bncdf80d44fd2016-07-15 20:27:413229 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]e3352df2014-03-19 05:55:423230
bnc38dcd392016-02-09 23:19:493231 // This is the length field that's too short.
bnc42331402016-07-25 13:36:153232 SpdySerializedFrame reply_wrong_length(
3233 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
diannahu86e7a8ab2016-08-03 20:11:143234 size_t right_size =
3235 reply_wrong_length.size() - SpdyConstants::GetFrameHeaderSize(HTTP2);
bnc38dcd392016-02-09 23:19:493236 size_t wrong_size = right_size - 4;
bnc42331402016-07-25 13:36:153237 test::SetFrameLength(&reply_wrong_length, wrong_size, HTTP2);
bnc38dcd392016-02-09 23:19:493238
[email protected]e3352df2014-03-19 05:55:423239 MockRead reads[] = {
bnc42331402016-07-25 13:36:153240 MockRead(ASYNC, reply_wrong_length.data(), reply_wrong_length.size() - 4,
3241 1),
[email protected]e3352df2014-03-19 05:55:423242 };
3243
rch08e3aa3e2015-05-16 14:27:523244 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]e3352df2014-03-19 05:55:423245 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013246 BoundNetLog(), NULL);
[email protected]e3352df2014-03-19 05:55:423247 helper.RunToCompletion(&data);
3248 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013249 EXPECT_THAT(out.rv, IsError(ERR_SPDY_COMPRESSION_ERROR));
[email protected]bdd1b222014-06-10 11:08:393250}
3251
bncd16676a2016-07-20 16:23:013252TEST_F(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
bncdf80d44fd2016-07-15 20:27:413253 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493254 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413255 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bncf5012992016-04-19 16:36:263256 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 6 (DECOMPRESS_FAILURE)."));
bncdf80d44fd2016-07-15 20:27:413257 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393258
3259 // Read HEADERS with corrupted payload.
bnc42331402016-07-25 13:36:153260 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:413261 memset(resp.data() + 12, 0xcf, resp.size() - 12);
3262 MockRead reads[] = {CreateMockRead(resp, 1)};
[email protected]bdd1b222014-06-10 11:08:393263
rch08e3aa3e2015-05-16 14:27:523264 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:013265 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3266 BoundNetLog(), NULL);
[email protected]bdd1b222014-06-10 11:08:393267 helper.RunToCompletion(&data);
3268 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013269 EXPECT_THAT(out.rv, IsError(ERR_SPDY_COMPRESSION_ERROR));
[email protected]bdd1b222014-06-10 11:08:393270}
3271
bncd16676a2016-07-20 16:23:013272TEST_F(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
bncdf80d44fd2016-07-15 20:27:413273 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493274 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413275 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bnc20df67c2016-04-07 01:36:183276 0, GOAWAY_FRAME_SIZE_ERROR,
dahollingsaf3796492016-05-25 19:21:353277 "Framer error: 15 (INVALID_CONTROL_FRAME_SIZE)."));
bncdf80d44fd2016-07-15 20:27:413278 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393279
3280 // Read WINDOW_UPDATE with incorrectly-sized payload.
bncdf80d44fd2016-07-15 20:27:413281 SpdySerializedFrame bad_window_update(
[email protected]bdd1b222014-06-10 11:08:393282 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
bncdf80d44fd2016-07-15 20:27:413283 test::SetFrameLength(&bad_window_update, bad_window_update.size() - 1, HTTP2);
3284 MockRead reads[] = {CreateMockRead(bad_window_update, 1)};
[email protected]bdd1b222014-06-10 11:08:393285
rch08e3aa3e2015-05-16 14:27:523286 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:013287 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3288 BoundNetLog(), NULL);
[email protected]bdd1b222014-06-10 11:08:393289 helper.RunToCompletion(&data);
3290 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013291 EXPECT_THAT(out.rv, IsError(ERR_SPDY_FRAME_SIZE_ERROR));
[email protected]e3352df2014-03-19 05:55:423292}
3293
[email protected]bf2491a92009-11-29 16:39:483294// Test that we shutdown correctly on write errors.
bncd16676a2016-07-20 16:23:013295TEST_F(SpdyNetworkTransactionTest, WriteError) {
bncdf80d44fd2016-07-15 20:27:413296 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493297 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483298 MockWrite writes[] = {
[email protected]bdd1b222014-06-10 11:08:393299 // We'll write 10 bytes successfully
bncdf80d44fd2016-07-15 20:27:413300 MockWrite(ASYNC, req.data(), 10, 1),
[email protected]bdd1b222014-06-10 11:08:393301 // Followed by ERROR!
[email protected]bdd1b222014-06-10 11:08:393302 MockWrite(ASYNC, ERR_FAILED, 2),
mmenke666a6fea2015-12-19 04:16:333303 // Session drains and attempts to write a GOAWAY: Another ERROR!
3304 MockWrite(ASYNC, ERR_FAILED, 3),
[email protected]bf2491a92009-11-29 16:39:483305 };
3306
mmenke666a6fea2015-12-19 04:16:333307 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
[email protected]238002d2013-10-17 02:01:403308
mmenke666a6fea2015-12-19 04:16:333309 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]238002d2013-10-17 02:01:403310
[email protected]262eec82013-03-19 21:01:363311 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013312 BoundNetLog(), NULL);
[email protected]238002d2013-10-17 02:01:403313 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:333314 helper.AddData(&data);
[email protected]238002d2013-10-17 02:01:403315 EXPECT_TRUE(helper.StartDefaultTest());
[email protected]238002d2013-10-17 02:01:403316 helper.FinishDefaultTest();
rch37de576c2015-05-17 20:28:173317 EXPECT_TRUE(data.AllWriteDataConsumed());
mmenke666a6fea2015-12-19 04:16:333318 EXPECT_TRUE(data.AllReadDataConsumed());
[email protected]3caf5542010-07-16 15:19:473319 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013320 EXPECT_THAT(out.rv, IsError(ERR_FAILED));
[email protected]bf2491a92009-11-29 16:39:483321}
3322
3323// Test that partial writes work.
bncd16676a2016-07-20 16:23:013324TEST_F(SpdyNetworkTransactionTest, PartialWrite) {
bnc42331402016-07-25 13:36:153325 // Chop the HEADERS frame into 5 chunks.
bncdf80d44fd2016-07-15 20:27:413326 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493327 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483328 const int kChunks = 5;
bncdf80d44fd2016-07-15 20:27:413329 std::unique_ptr<MockWrite[]> writes(ChopWriteFrame(req, kChunks));
rch08e3aa3e2015-05-16 14:27:523330 for (int i = 0; i < kChunks; ++i) {
3331 writes[i].sequence_number = i;
3332 }
[email protected]bf2491a92009-11-29 16:39:483333
bnc42331402016-07-25 13:36:153334 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:413335 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:483336 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413337 CreateMockRead(resp, kChunks), CreateMockRead(body, kChunks + 1),
rch08e3aa3e2015-05-16 14:27:523338 MockRead(ASYNC, 0, kChunks + 2) // EOF
[email protected]bf2491a92009-11-29 16:39:483339 };
3340
rch08e3aa3e2015-05-16 14:27:523341 SequencedSocketData data(reads, arraysize(reads), writes.get(), kChunks);
[email protected]262eec82013-03-19 21:01:363342 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013343 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:573344 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473345 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013346 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023347 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bf2491a92009-11-29 16:39:483348 EXPECT_EQ("hello!", out.response_data);
3349}
3350
[email protected]9e743cd2010-03-16 07:03:533351// Test that the NetLog contains good data for a simple GET request.
bncd16676a2016-07-20 16:23:013352TEST_F(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:403353 static const char* const kExtraHeaders[] = {
3354 "user-agent", "Chrome",
3355 };
bncdf80d44fd2016-07-15 20:27:413356 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493357 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413358 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]dac358042009-12-18 02:07:483359
bnc42331402016-07-25 13:36:153360 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:413361 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]dac358042009-12-18 02:07:483362 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413363 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:523364 MockRead(ASYNC, 0, 3) // EOF
[email protected]dac358042009-12-18 02:07:483365 };
3366
vishal.b62985ca92015-04-17 08:45:513367 BoundTestNetLog log;
[email protected]dac358042009-12-18 02:07:483368
rch08e3aa3e2015-05-16 14:27:523369 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3deb9a52010-11-11 00:24:403370 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
bncd16676a2016-07-20 16:23:013371 DEFAULT_PRIORITY, log.bound(), NULL);
[email protected]dd54bd82012-07-19 23:44:573372 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473373 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013374 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023375 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]dac358042009-12-18 02:07:483376 EXPECT_EQ("hello!", out.response_data);
3377
[email protected]9e743cd2010-03-16 07:03:533378 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:473379 // This test is intentionally non-specific about the exact ordering of the
3380 // log; instead we just check to make sure that certain events exist, and that
3381 // they are in the right order.
mmenke43758e62015-05-04 21:09:463382 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403383 log.GetEntries(&entries);
3384
3385 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:483386 int pos = 0;
mikecirone8b85c432016-09-08 19:11:003387 pos = ExpectLogContainsSomewhere(
3388 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST,
3389 NetLogEventPhase::BEGIN);
3390 pos = ExpectLogContainsSomewhere(
3391 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST,
3392 NetLogEventPhase::END);
3393 pos = ExpectLogContainsSomewhere(
3394 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_READ_HEADERS,
3395 NetLogEventPhase::BEGIN);
3396 pos = ExpectLogContainsSomewhere(
3397 entries, pos + 1, NetLogEventType::HTTP_TRANSACTION_READ_HEADERS,
3398 NetLogEventPhase::END);
bnc301745a2015-03-10 03:22:163399 pos = ExpectLogContainsSomewhere(entries, pos + 1,
mikecirone8b85c432016-09-08 19:11:003400 NetLogEventType::HTTP_TRANSACTION_READ_BODY,
3401 NetLogEventPhase::BEGIN);
bnc301745a2015-03-10 03:22:163402 pos = ExpectLogContainsSomewhere(entries, pos + 1,
mikecirone8b85c432016-09-08 19:11:003403 NetLogEventType::HTTP_TRANSACTION_READ_BODY,
3404 NetLogEventPhase::END);
[email protected]3deb9a52010-11-11 00:24:403405
3406 // Check that we logged all the headers correctly
mikecirone8b85c432016-09-08 19:11:003407 pos = ExpectLogContainsSomewhere(entries, 0,
3408 NetLogEventType::HTTP2_SESSION_SEND_HEADERS,
3409 NetLogEventPhase::NONE);
[email protected]3deb9a52010-11-11 00:24:403410
[email protected]ea5ef4c2013-06-13 22:50:273411 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:573412 ASSERT_TRUE(entries[pos].params.get());
3413 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3414
3415 std::vector<std::string> expected;
bncce36dca22015-04-21 22:11:233416 expected.push_back(std::string(spdy_util_.GetHostKey()) +
3417 ": www.example.org");
[email protected]513963e2013-06-15 01:53:043418 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
rchebf12982015-04-10 01:15:003419 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": " +
bncb26024382016-06-29 02:39:453420 default_url_.scheme());
[email protected]513963e2013-06-15 01:53:043421 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
[email protected]f3da152d2012-06-02 01:00:573422 expected.push_back("user-agent: Chrome");
[email protected]f3da152d2012-06-02 01:00:573423 EXPECT_EQ(expected.size(), header_list->GetSize());
3424 for (std::vector<std::string>::const_iterator it = expected.begin();
3425 it != expected.end();
3426 ++it) {
3427 base::StringValue header(*it);
3428 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3429 "Header not found: " << *it;
[email protected]3deb9a52010-11-11 00:24:403430 }
[email protected]dac358042009-12-18 02:07:483431}
3432
[email protected]79d84222010-02-26 00:01:443433// Since we buffer the IO from the stream to the renderer, this test verifies
3434// that when we read out the maximum amount of data (e.g. we received 50 bytes
3435// on the network, but issued a Read for only 5 of those bytes) that the data
3436// flow still works correctly.
bncd16676a2016-07-20 16:23:013437TEST_F(SpdyNetworkTransactionTest, BufferFull) {
bncdf80d44fd2016-07-15 20:27:413438 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493439 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413440 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]79d84222010-02-26 00:01:443441
[email protected]20d005f2010-07-02 19:55:433442 // 2 data frames in a single read.
bncdf80d44fd2016-07-15 20:27:413443 SpdySerializedFrame data_frame_1(
3444 spdy_util_.ConstructSpdyDataFrame(1, "goodby", 6, /*fin=*/false));
3445 SpdySerializedFrame data_frame_2(
3446 spdy_util_.ConstructSpdyDataFrame(1, "e worl", 6, /*fin=*/false));
bncb03b1092016-04-06 11:19:553447 const SpdySerializedFrame* data_frames[2] = {
bncdf80d44fd2016-07-15 20:27:413448 &data_frame_1, &data_frame_2,
[email protected]79d84222010-02-26 00:01:443449 };
[email protected]20d005f2010-07-02 19:55:433450 char combined_data_frames[100];
3451 int combined_data_frames_len =
3452 CombineFrames(data_frames, arraysize(data_frames),
3453 combined_data_frames, arraysize(combined_data_frames));
bncdf80d44fd2016-07-15 20:27:413454 SpdySerializedFrame last_frame(
3455 spdy_util_.ConstructSpdyDataFrame(1, "d", 1, /*fin=*/true));
[email protected]79d84222010-02-26 00:01:443456
bnc42331402016-07-25 13:36:153457 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]79d84222010-02-26 00:01:443458 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413459 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:093460 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3461 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3462 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
bncdf80d44fd2016-07-15 20:27:413463 CreateMockRead(last_frame, 5),
rch32320842015-05-16 15:57:093464 MockRead(ASYNC, 0, 6) // EOF
[email protected]79d84222010-02-26 00:01:443465 };
3466
rch32320842015-05-16 15:57:093467 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]79d84222010-02-26 00:01:443468
[email protected]49639fa2011-12-20 23:22:413469 TestCompletionCallback callback;
[email protected]79d84222010-02-26 00:01:443470
[email protected]262eec82013-03-19 21:01:363471 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013472 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473473 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573474 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473475 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413476 int rv = trans->Start(
3477 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013478 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79d84222010-02-26 00:01:443479
[email protected]3caf5542010-07-16 15:19:473480 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:443481 out.rv = callback.WaitForResult();
3482 EXPECT_EQ(out.rv, OK);
3483
3484 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523485 EXPECT_TRUE(response->headers);
[email protected]79d84222010-02-26 00:01:443486 EXPECT_TRUE(response->was_fetched_via_spdy);
3487 out.status_line = response->headers->GetStatusLine();
3488 out.response_info = *response; // Make a copy so we can verify.
3489
3490 // Read Data
[email protected]49639fa2011-12-20 23:22:413491 TestCompletionCallback read_callback;
[email protected]79d84222010-02-26 00:01:443492
3493 std::string content;
3494 do {
3495 // Read small chunks at a time.
3496 const int kSmallReadSize = 3;
bnc301745a2015-03-10 03:22:163497 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503498 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163499 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593500 data.Resume();
[email protected]79d84222010-02-26 00:01:443501 rv = read_callback.WaitForResult();
3502 }
3503 if (rv > 0) {
3504 content.append(buf->data(), rv);
3505 } else if (rv < 0) {
3506 NOTREACHED();
3507 }
3508 } while (rv > 0);
3509
3510 out.response_data.swap(content);
3511
[email protected]30c942b2010-07-21 16:59:593512 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553513 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173514 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553515
[email protected]79d84222010-02-26 00:01:443516 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473517 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:443518
robpercival214763f2016-07-01 23:27:013519 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023520 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]79d84222010-02-26 00:01:443521 EXPECT_EQ("goodbye world", out.response_data);
3522}
3523
[email protected]8918d282010-03-02 00:57:553524// Verify that basic buffering works; when multiple data frames arrive
3525// at the same time, ensure that we don't notify a read completion for
3526// each data frame individually.
bncd16676a2016-07-20 16:23:013527TEST_F(SpdyNetworkTransactionTest, Buffering) {
bncdf80d44fd2016-07-15 20:27:413528 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493529 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413530 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:553531
3532 // 4 data frames in a single read.
bncdf80d44fd2016-07-15 20:27:413533 SpdySerializedFrame data_frame(
3534 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
3535 SpdySerializedFrame data_frame_fin(
3536 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/true));
3537 const SpdySerializedFrame* data_frames[4] = {&data_frame, &data_frame,
3538 &data_frame, &data_frame_fin};
[email protected]20d005f2010-07-02 19:55:433539 char combined_data_frames[100];
3540 int combined_data_frames_len =
3541 CombineFrames(data_frames, arraysize(data_frames),
3542 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:553543
bnc42331402016-07-25 13:36:153544 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553545 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413546 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:093547 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3548 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3549 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553550 };
3551
rch32320842015-05-16 15:57:093552 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553553
[email protected]262eec82013-03-19 21:01:363554 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013555 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473556 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573557 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473558 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553559
[email protected]49639fa2011-12-20 23:22:413560 TestCompletionCallback callback;
3561 int rv = trans->Start(
3562 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013563 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:553564
[email protected]3caf5542010-07-16 15:19:473565 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553566 out.rv = callback.WaitForResult();
3567 EXPECT_EQ(out.rv, OK);
3568
3569 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523570 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:553571 EXPECT_TRUE(response->was_fetched_via_spdy);
3572 out.status_line = response->headers->GetStatusLine();
3573 out.response_info = *response; // Make a copy so we can verify.
3574
3575 // Read Data
[email protected]49639fa2011-12-20 23:22:413576 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553577
3578 std::string content;
3579 int reads_completed = 0;
3580 do {
3581 // Read small chunks at a time.
3582 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163583 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503584 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163585 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593586 data.Resume();
[email protected]8918d282010-03-02 00:57:553587 rv = read_callback.WaitForResult();
3588 }
3589 if (rv > 0) {
3590 EXPECT_EQ(kSmallReadSize, rv);
3591 content.append(buf->data(), rv);
3592 } else if (rv < 0) {
3593 FAIL() << "Unexpected read error: " << rv;
3594 }
3595 reads_completed++;
3596 } while (rv > 0);
3597
3598 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3599
3600 out.response_data.swap(content);
3601
[email protected]30c942b2010-07-21 16:59:593602 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553603 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173604 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553605
3606 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473607 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553608
robpercival214763f2016-07-01 23:27:013609 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023610 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:553611 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3612}
3613
3614// Verify the case where we buffer data but read it after it has been buffered.
bncd16676a2016-07-20 16:23:013615TEST_F(SpdyNetworkTransactionTest, BufferedAll) {
bncdf80d44fd2016-07-15 20:27:413616 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493617 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413618 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:553619
[email protected]20d005f2010-07-02 19:55:433620 // 5 data frames in a single read.
bnc42331402016-07-25 13:36:153621 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:413622 SpdySerializedFrame data_frame(
3623 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
3624 SpdySerializedFrame data_frame_fin(
3625 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/true));
3626 const SpdySerializedFrame* frames[5] = {&reply, &data_frame, &data_frame,
3627 &data_frame, &data_frame_fin};
[email protected]20d005f2010-07-02 19:55:433628 char combined_frames[200];
3629 int combined_frames_len =
3630 CombineFrames(frames, arraysize(frames),
3631 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:553632
3633 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523634 MockRead(ASYNC, combined_frames, combined_frames_len, 1),
3635 MockRead(ASYNC, 0, 2) // EOF
[email protected]8918d282010-03-02 00:57:553636 };
3637
rch08e3aa3e2015-05-16 14:27:523638 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553639
[email protected]262eec82013-03-19 21:01:363640 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013641 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473642 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573643 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473644 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553645
[email protected]49639fa2011-12-20 23:22:413646 TestCompletionCallback callback;
3647 int rv = trans->Start(
3648 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013649 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:553650
[email protected]3caf5542010-07-16 15:19:473651 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553652 out.rv = callback.WaitForResult();
3653 EXPECT_EQ(out.rv, OK);
3654
3655 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523656 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:553657 EXPECT_TRUE(response->was_fetched_via_spdy);
3658 out.status_line = response->headers->GetStatusLine();
3659 out.response_info = *response; // Make a copy so we can verify.
3660
3661 // Read Data
[email protected]49639fa2011-12-20 23:22:413662 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553663
3664 std::string content;
3665 int reads_completed = 0;
3666 do {
3667 // Read small chunks at a time.
3668 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163669 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503670 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:553671 if (rv > 0) {
3672 EXPECT_EQ(kSmallReadSize, rv);
3673 content.append(buf->data(), rv);
3674 } else if (rv < 0) {
3675 FAIL() << "Unexpected read error: " << rv;
3676 }
3677 reads_completed++;
3678 } while (rv > 0);
3679
3680 EXPECT_EQ(3, reads_completed);
3681
3682 out.response_data.swap(content);
3683
[email protected]30c942b2010-07-21 16:59:593684 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553685 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173686 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553687
3688 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473689 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553690
robpercival214763f2016-07-01 23:27:013691 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:023692 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:553693 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3694}
3695
3696// Verify the case where we buffer data and close the connection.
bncd16676a2016-07-20 16:23:013697TEST_F(SpdyNetworkTransactionTest, BufferedClosed) {
bncdf80d44fd2016-07-15 20:27:413698 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493699 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413700 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]8918d282010-03-02 00:57:553701
3702 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:433703 // NOTE: We don't FIN the stream.
bncdf80d44fd2016-07-15 20:27:413704 SpdySerializedFrame data_frame(
3705 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
3706 const SpdySerializedFrame* data_frames[4] = {&data_frame, &data_frame,
3707 &data_frame, &data_frame};
[email protected]20d005f2010-07-02 19:55:433708 char combined_data_frames[100];
3709 int combined_data_frames_len =
3710 CombineFrames(data_frames, arraysize(data_frames),
3711 combined_data_frames, arraysize(combined_data_frames));
bnc42331402016-07-25 13:36:153712 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553713 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413714 CreateMockRead(resp, 1),
rch32320842015-05-16 15:57:093715 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3716 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3717 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553718 };
3719
rch32320842015-05-16 15:57:093720 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553721
[email protected]262eec82013-03-19 21:01:363722 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013723 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473724 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573725 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473726 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553727
[email protected]49639fa2011-12-20 23:22:413728 TestCompletionCallback callback;
[email protected]8918d282010-03-02 00:57:553729
[email protected]49639fa2011-12-20 23:22:413730 int rv = trans->Start(
3731 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013732 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8918d282010-03-02 00:57:553733
[email protected]3caf5542010-07-16 15:19:473734 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553735 out.rv = callback.WaitForResult();
3736 EXPECT_EQ(out.rv, OK);
3737
3738 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523739 EXPECT_TRUE(response->headers);
[email protected]8918d282010-03-02 00:57:553740 EXPECT_TRUE(response->was_fetched_via_spdy);
3741 out.status_line = response->headers->GetStatusLine();
3742 out.response_info = *response; // Make a copy so we can verify.
3743
3744 // Read Data
[email protected]49639fa2011-12-20 23:22:413745 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553746
3747 std::string content;
3748 int reads_completed = 0;
3749 do {
3750 // Read small chunks at a time.
3751 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163752 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503753 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163754 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593755 data.Resume();
[email protected]8918d282010-03-02 00:57:553756 rv = read_callback.WaitForResult();
3757 }
3758 if (rv > 0) {
3759 content.append(buf->data(), rv);
3760 } else if (rv < 0) {
3761 // This test intentionally closes the connection, and will get an error.
robpercival214763f2016-07-01 23:27:013762 EXPECT_THAT(rv, IsError(ERR_CONNECTION_CLOSED));
[email protected]8918d282010-03-02 00:57:553763 break;
3764 }
3765 reads_completed++;
3766 } while (rv > 0);
3767
3768 EXPECT_EQ(0, reads_completed);
3769
3770 out.response_data.swap(content);
3771
[email protected]30c942b2010-07-21 16:59:593772 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553773 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173774 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553775
3776 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473777 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553778}
3779
[email protected]1ed7b3dc2010-03-04 05:41:453780// Verify the case where we buffer data and cancel the transaction.
bncd16676a2016-07-20 16:23:013781TEST_F(SpdyNetworkTransactionTest, BufferedCancelled) {
bncdf80d44fd2016-07-15 20:27:413782 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493783 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413784 SpdySerializedFrame rst(
[email protected]975da41a2014-06-05 03:36:243785 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
bncdf80d44fd2016-07-15 20:27:413786 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 4)};
[email protected]1ed7b3dc2010-03-04 05:41:453787
[email protected]20d005f2010-07-02 19:55:433788 // NOTE: We don't FIN the stream.
bncdf80d44fd2016-07-15 20:27:413789 SpdySerializedFrame data_frame(
3790 spdy_util_.ConstructSpdyDataFrame(1, "message", 7, /*fin=*/false));
[email protected]1ed7b3dc2010-03-04 05:41:453791
bnc42331402016-07-25 13:36:153792 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:453793 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413794 CreateMockRead(resp, 1),
3795 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3796 CreateMockRead(data_frame, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]1ed7b3dc2010-03-04 05:41:453797 };
3798
rch32320842015-05-16 15:57:093799 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1ed7b3dc2010-03-04 05:41:453800
[email protected]262eec82013-03-19 21:01:363801 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013802 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473803 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573804 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473805 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413806 TestCompletionCallback callback;
[email protected]1ed7b3dc2010-03-04 05:41:453807
[email protected]49639fa2011-12-20 23:22:413808 int rv = trans->Start(
3809 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013810 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1ed7b3dc2010-03-04 05:41:453811
[email protected]3caf5542010-07-16 15:19:473812 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:453813 out.rv = callback.WaitForResult();
3814 EXPECT_EQ(out.rv, OK);
3815
3816 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523817 EXPECT_TRUE(response->headers);
[email protected]1ed7b3dc2010-03-04 05:41:453818 EXPECT_TRUE(response->was_fetched_via_spdy);
3819 out.status_line = response->headers->GetStatusLine();
3820 out.response_info = *response; // Make a copy so we can verify.
3821
3822 // Read Data
[email protected]49639fa2011-12-20 23:22:413823 TestCompletionCallback read_callback;
[email protected]1ed7b3dc2010-03-04 05:41:453824
[email protected]88c7b4be2014-03-19 23:04:013825 const int kReadSize = 256;
bnc301745a2015-03-10 03:22:163826 scoped_refptr<IOBuffer> buf(new IOBuffer(kReadSize));
[email protected]88c7b4be2014-03-19 23:04:013827 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163828 ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
[email protected]88c7b4be2014-03-19 23:04:013829
3830 // Complete the read now, which causes buffering to start.
mmenkee24011922015-12-17 22:12:593831 data.Resume();
3832 base::RunLoop().RunUntilIdle();
[email protected]88c7b4be2014-03-19 23:04:013833 // Destroy the transaction, causing the stream to get cancelled
3834 // and orphaning the buffered IO task.
3835 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:453836
3837 // Flush the MessageLoop; this will cause the buffered IO task
3838 // to run for the final time.
[email protected]fc9d88472013-08-14 02:31:173839 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:473840
3841 // Verify that we consumed all test data.
3842 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:453843}
3844
bncd16676a2016-07-20 16:23:013845TEST_F(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
bncdf80d44fd2016-07-15 20:27:413846 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493847 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413848 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]69d717bd2010-04-21 18:43:213849
bncdf80d44fd2016-07-15 20:27:413850 SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:213851 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413852 CreateMockRead(go_away, 1),
[email protected]58cebf8f2010-07-31 19:20:163853 };
3854
rch08e3aa3e2015-05-16 14:27:523855 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363856 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:013857 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:573858 helper.AddData(&data);
3859 helper.RunToCompletion(&data);
[email protected]58cebf8f2010-07-31 19:20:163860 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:013861 EXPECT_THAT(out.rv, IsError(ERR_ABORTED));
[email protected]69d717bd2010-04-21 18:43:213862}
3863
bncd16676a2016-07-20 16:23:013864TEST_F(SpdyNetworkTransactionTest, CloseWithActiveStream) {
bncdf80d44fd2016-07-15 20:27:413865 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:493866 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413867 MockWrite writes[] = {CreateMockWrite(req, 0)};
[email protected]f5ed21552010-05-04 18:39:543868
bnc42331402016-07-25 13:36:153869 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]f5ed21552010-05-04 18:39:543870 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:413871 CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
[email protected]f5ed21552010-05-04 18:39:543872 };
3873
rch08e3aa3e2015-05-16 14:27:523874 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bnc4d782f492016-08-18 13:50:003875
3876 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3877 BoundNetLog(), NULL);
[email protected]3caf5542010-07-16 15:19:473878 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573879 helper.AddData(&data);
bnc4d782f492016-08-18 13:50:003880 helper.StartDefaultTest();
3881 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
[email protected]f5ed21552010-05-04 18:39:543882
bnc4d782f492016-08-18 13:50:003883 helper.WaitForCallbackToComplete();
3884 EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED));
[email protected]3caf5542010-07-16 15:19:473885
bnc4d782f492016-08-18 13:50:003886 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:523887 EXPECT_TRUE(response->headers);
[email protected]f5ed21552010-05-04 18:39:543888 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]f5ed21552010-05-04 18:39:543889
3890 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473891 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:543892}
[email protected]58cebf8f2010-07-31 19:20:163893
bncfacdd852015-01-09 19:22:543894// Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
3895// protocol negotiation happens, instead this test forces protocols for both
3896// sockets.
bncd16676a2016-07-20 16:23:013897TEST_F(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
bncfacdd852015-01-09 19:22:543898 HttpRequestInfo request;
3899 request.method = "GET";
bncb26024382016-06-29 02:39:453900 request.url = default_url_;
bncfacdd852015-01-09 19:22:543901 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:543902 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:013903 nullptr);
bncfacdd852015-01-09 19:22:543904
3905 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
bncb26024382016-06-29 02:39:453906 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bncdf80d44fd2016-07-15 20:27:413907 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:153908 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bncdf80d44fd2016-07-15 20:27:413909 MockWrite writes0[] = {CreateMockWrite(req, 0)};
3910 SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway(
bncfacdd852015-01-09 19:22:543911 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
bncdf80d44fd2016-07-15 20:27:413912 MockRead reads0[] = {CreateMockRead(go_away, 1)};
rch08e3aa3e2015-05-16 14:27:523913 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
3914 arraysize(writes0));
bncfacdd852015-01-09 19:22:543915
danakjaee3e1ec2016-04-16 00:23:183916 std::unique_ptr<SSLSocketDataProvider> ssl_provider0(
bncfacdd852015-01-09 19:22:543917 new SSLSocketDataProvider(ASYNC, OK));
3918 // Expect HTTP/2 protocols too in SSLConfig.
bnc06d22432015-06-29 12:39:433919 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
bnc3f0118e2016-02-02 15:42:223920 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
bncfacdd852015-01-09 19:22:543921 // Force SPDY.
bnc3cf2a592016-08-11 14:48:363922 ssl_provider0->next_proto = kProtoHTTP2;
dchengc7eeda422015-12-26 03:56:483923 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
bncfacdd852015-01-09 19:22:543924
3925 // Second socket: falling back to HTTP/1.1.
rch08e3aa3e2015-05-16 14:27:523926 MockWrite writes1[] = {MockWrite(ASYNC, 0,
3927 "GET / HTTP/1.1\r\n"
3928 "Host: www.example.org\r\n"
3929 "Connection: keep-alive\r\n\r\n")};
3930 MockRead reads1[] = {MockRead(ASYNC, 1,
3931 "HTTP/1.1 200 OK\r\n"
3932 "Content-Length: 5\r\n\r\n"
3933 "hello")};
3934 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
3935 arraysize(writes1));
bncfacdd852015-01-09 19:22:543936
danakjaee3e1ec2016-04-16 00:23:183937 std::unique_ptr<SSLSocketDataProvider> ssl_provider1(
bncfacdd852015-01-09 19:22:543938 new SSLSocketDataProvider(ASYNC, OK));
3939 // Expect only HTTP/1.1 protocol in SSLConfig.
3940 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
3941 // Force HTTP/1.1.
bnc3cf2a592016-08-11 14:48:363942 ssl_provider1->next_proto = kProtoHTTP11;
dchengc7eeda422015-12-26 03:56:483943 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
bncfacdd852015-01-09 19:22:543944
bnc525e175a2016-06-20 12:36:403945 HttpServerProperties* http_server_properties =
bncfacdd852015-01-09 19:22:543946 helper.session()->spdy_session_pool()->http_server_properties();
bncb26024382016-06-29 02:39:453947 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair_));
bncfacdd852015-01-09 19:22:543948
3949 helper.RunPreTestSetup();
3950 helper.StartDefaultTest();
3951 helper.FinishDefaultTestWithoutVerification();
3952 helper.VerifyDataConsumed();
bncb26024382016-06-29 02:39:453953 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair_));
bncfacdd852015-01-09 19:22:543954
3955 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:523956 ASSERT_TRUE(response);
3957 ASSERT_TRUE(response->headers);
bncfacdd852015-01-09 19:22:543958 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3959 EXPECT_FALSE(response->was_fetched_via_spdy);
mmenke8210acc2016-07-11 16:34:523960 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
3961 response->connection_info);
bncfacdd852015-01-09 19:22:543962 EXPECT_TRUE(response->was_npn_negotiated);
3963 EXPECT_TRUE(request.url.SchemeIs("https"));
3964 EXPECT_EQ("127.0.0.1", response->socket_address.host());
3965 EXPECT_EQ(443, response->socket_address.port());
3966 std::string response_data;
robpercival214763f2016-07-01 23:27:013967 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
bncfacdd852015-01-09 19:22:543968 EXPECT_EQ("hello", response_data);
3969}
3970
3971// Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
3972// proxy. Note that no actual protocol negotiation happens, instead this test
3973// forces protocols for both sockets.
bncd16676a2016-07-20 16:23:013974TEST_F(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
bncfacdd852015-01-09 19:22:543975 HttpRequestInfo request;
3976 request.method = "GET";
bncb26024382016-06-29 02:39:453977 request.url = default_url_;
bncd16676a2016-07-20 16:23:013978 auto session_deps = base::MakeUnique<SpdySessionDependencies>(
3979 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
bncfacdd852015-01-09 19:22:543980 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:543981 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:013982 std::move(session_deps));
bncfacdd852015-01-09 19:22:543983
3984 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
bncdf80d44fd2016-07-15 20:27:413985 SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:233986 nullptr, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
bncdf80d44fd2016-07-15 20:27:413987 MockWrite writes0[] = {CreateMockWrite(req, 0)};
3988 SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway(
bncfacdd852015-01-09 19:22:543989 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
bncdf80d44fd2016-07-15 20:27:413990 MockRead reads0[] = {CreateMockRead(go_away, 1)};
rch08e3aa3e2015-05-16 14:27:523991 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
3992 arraysize(writes0));
bncfacdd852015-01-09 19:22:543993
danakjaee3e1ec2016-04-16 00:23:183994 std::unique_ptr<SSLSocketDataProvider> ssl_provider0(
bncfacdd852015-01-09 19:22:543995 new SSLSocketDataProvider(ASYNC, OK));
3996 // Expect HTTP/2 protocols too in SSLConfig.
bnc06d22432015-06-29 12:39:433997 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
bnc3f0118e2016-02-02 15:42:223998 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
bncfacdd852015-01-09 19:22:543999 // Force SPDY.
bnc3cf2a592016-08-11 14:48:364000 ssl_provider0->next_proto = kProtoHTTP2;
dchengc7eeda422015-12-26 03:56:484001 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
bncfacdd852015-01-09 19:22:544002
4003 // Second socket: retry using HTTP/1.1.
4004 MockWrite writes1[] = {
rch08e3aa3e2015-05-16 14:27:524005 MockWrite(ASYNC, 0,
bncce36dca22015-04-21 22:11:234006 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174007 "Host: www.example.org:443\r\n"
bncfacdd852015-01-09 19:22:544008 "Proxy-Connection: keep-alive\r\n\r\n"),
rch08e3aa3e2015-05-16 14:27:524009 MockWrite(ASYNC, 2,
bncfacdd852015-01-09 19:22:544010 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:234011 "Host: www.example.org\r\n"
bncfacdd852015-01-09 19:22:544012 "Connection: keep-alive\r\n\r\n"),
4013 };
4014
4015 MockRead reads1[] = {
rch08e3aa3e2015-05-16 14:27:524016 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4017 MockRead(ASYNC, 3,
bncfacdd852015-01-09 19:22:544018 "HTTP/1.1 200 OK\r\n"
4019 "Content-Length: 5\r\n\r\n"
4020 "hello"),
4021 };
rch08e3aa3e2015-05-16 14:27:524022 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4023 arraysize(writes1));
bncfacdd852015-01-09 19:22:544024
danakjaee3e1ec2016-04-16 00:23:184025 std::unique_ptr<SSLSocketDataProvider> ssl_provider1(
bncfacdd852015-01-09 19:22:544026 new SSLSocketDataProvider(ASYNC, OK));
4027 // Expect only HTTP/1.1 protocol in SSLConfig.
4028 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4029 // Force HTTP/1.1.
bnc3cf2a592016-08-11 14:48:364030 ssl_provider1->next_proto = kProtoHTTP11;
dchengc7eeda422015-12-26 03:56:484031 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
bncfacdd852015-01-09 19:22:544032
4033 // A third socket is needed for the tunnelled connection.
danakjaee3e1ec2016-04-16 00:23:184034 std::unique_ptr<SSLSocketDataProvider> ssl_provider2(
bncfacdd852015-01-09 19:22:544035 new SSLSocketDataProvider(ASYNC, OK));
4036 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4037 ssl_provider2.get());
4038
bnc525e175a2016-06-20 12:36:404039 HttpServerProperties* http_server_properties =
bncfacdd852015-01-09 19:22:544040 helper.session()->spdy_session_pool()->http_server_properties();
4041 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
4042 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4043
4044 helper.RunPreTestSetup();
4045 helper.StartDefaultTest();
4046 helper.FinishDefaultTestWithoutVerification();
4047 helper.VerifyDataConsumed();
4048 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4049
4050 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
wezca1070932016-05-26 20:30:524051 ASSERT_TRUE(response);
4052 ASSERT_TRUE(response->headers);
bncfacdd852015-01-09 19:22:544053 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4054 EXPECT_FALSE(response->was_fetched_via_spdy);
mmenke8210acc2016-07-11 16:34:524055 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
4056 response->connection_info);
bncfacdd852015-01-09 19:22:544057 EXPECT_FALSE(response->was_npn_negotiated);
4058 EXPECT_TRUE(request.url.SchemeIs("https"));
4059 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4060 EXPECT_EQ(70, response->socket_address.port());
4061 std::string response_data;
robpercival214763f2016-07-01 23:27:014062 ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk());
bncfacdd852015-01-09 19:22:544063 EXPECT_EQ("hello", response_data);
4064}
4065
[email protected]b261d0e2010-08-02 19:13:244066// Test to make sure we can correctly connect through a proxy.
bncd16676a2016-07-20 16:23:014067TEST_F(SpdyNetworkTransactionTest, ProxyConnect) {
4068 auto session_deps = base::MakeUnique<SpdySessionDependencies>(
4069 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
[email protected]262eec82013-03-19 21:01:364070 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014071 BoundNetLog(), std::move(session_deps));
[email protected]b261d0e2010-08-02 19:13:244072 helper.RunPreTestSetup();
4073 HttpNetworkTransaction* trans = helper.trans();
4074
rchebf12982015-04-10 01:15:004075 const char kConnect443[] = {
bncce36dca22015-04-21 22:11:234076 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174077 "Host: www.example.org:443\r\n"
rchcb934f562015-04-07 16:25:124078 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244079 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
bncdf80d44fd2016-07-15 20:27:414080 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494081 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bnc42331402016-07-25 13:36:154082 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414083 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244084
rchebf12982015-04-10 01:15:004085 MockWrite writes[] = {
4086 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
bncdf80d44fd2016-07-15 20:27:414087 CreateMockWrite(req, 2),
[email protected]b261d0e2010-08-02 19:13:244088 };
rchebf12982015-04-10 01:15:004089 MockRead reads[] = {
4090 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
bncdf80d44fd2016-07-15 20:27:414091 CreateMockRead(resp, 3), CreateMockRead(body, 4),
rchebf12982015-04-10 01:15:004092 MockRead(ASYNC, 0, 0, 5),
[email protected]b261d0e2010-08-02 19:13:244093 };
danakjaee3e1ec2016-04-16 00:23:184094 std::unique_ptr<SequencedSocketData> data(new SequencedSocketData(
rchebf12982015-04-10 01:15:004095 reads, arraysize(reads), writes, arraysize(writes)));
[email protected]b261d0e2010-08-02 19:13:244096
4097 helper.AddData(data.get());
[email protected]49639fa2011-12-20 23:22:414098 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244099
[email protected]49639fa2011-12-20 23:22:414100 int rv = trans->Start(
4101 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014102 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b261d0e2010-08-02 19:13:244103
4104 rv = callback.WaitForResult();
4105 EXPECT_EQ(0, rv);
4106
bnc42331402016-07-25 13:36:154107 // Verify the response headers.
[email protected]b261d0e2010-08-02 19:13:244108 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524109 ASSERT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024110 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:244111
4112 std::string response_data;
robpercival214763f2016-07-01 23:27:014113 ASSERT_THAT(ReadTransaction(trans, &response_data), IsOk());
[email protected]b261d0e2010-08-02 19:13:244114 EXPECT_EQ("hello!", response_data);
4115 helper.VerifyDataConsumed();
4116}
4117
bncce36dca22015-04-21 22:11:234118// Test to make sure we can correctly connect through a proxy to
4119// www.example.org, if there already exists a direct spdy connection to
4120// www.example.org. See https://crbug.com/49874.
bncd16676a2016-07-20 16:23:014121TEST_F(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
[email protected]733b7a6d2010-08-25 01:38:434122 // Use a proxy service which returns a proxy fallback list from DIRECT to
4123 // myproxy:70. For this test there will be no fallback, so it is equivalent
4124 // to simply DIRECT. The reason for appending the second proxy is to verify
4125 // that the session pool key used does is just "DIRECT".
bncd16676a2016-07-20 16:23:014126 auto session_deps = base::MakeUnique<SpdySessionDependencies>(
rdsmith82957ad2015-09-16 19:42:034127 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70"));
bncd16676a2016-07-20 16:23:014128 // When setting up the first transaction, we store the SpdySessionPool so that
4129 // we can use the same pool in the second transaction.
4130 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4131 BoundNetLog(), std::move(session_deps));
[email protected]733b7a6d2010-08-25 01:38:434132
[email protected]87bfa3f2010-09-30 14:54:564133 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:244134 helper.RunPreTestSetup();
4135
4136 // Construct and send a simple GET request.
bncdf80d44fd2016-07-15 20:27:414137 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494138 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]b261d0e2010-08-02 19:13:244139 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414140 CreateMockWrite(req, 0),
[email protected]b261d0e2010-08-02 19:13:244141 };
4142
bnc42331402016-07-25 13:36:154143 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414144 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244145 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414146 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch08e3aa3e2015-05-16 14:27:524147 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3), // Force a pause
[email protected]b261d0e2010-08-02 19:13:244148 };
rch08e3aa3e2015-05-16 14:27:524149 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574150 helper.AddData(&data);
[email protected]b261d0e2010-08-02 19:13:244151 HttpNetworkTransaction* trans = helper.trans();
4152
[email protected]49639fa2011-12-20 23:22:414153 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244154 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414155 out.rv = trans->Start(
4156 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244157
4158 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4159 out.rv = callback.WaitForResult();
4160 EXPECT_EQ(out.rv, OK);
4161
4162 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524163 EXPECT_TRUE(response->headers);
[email protected]b261d0e2010-08-02 19:13:244164 EXPECT_TRUE(response->was_fetched_via_spdy);
4165 out.rv = ReadTransaction(trans, &out.response_data);
robpercival214763f2016-07-01 23:27:014166 EXPECT_THAT(out.rv, IsOk());
[email protected]b261d0e2010-08-02 19:13:244167 out.status_line = response->headers->GetStatusLine();
bnc84e7fb52015-12-02 11:50:024168 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b261d0e2010-08-02 19:13:244169 EXPECT_EQ("hello!", out.response_data);
4170
4171 // Check that the SpdySession is still in the SpdySessionPool.
bncb26024382016-06-29 02:39:454172 SpdySessionKey session_pool_key_direct(host_port_pair_, ProxyServer::Direct(),
4173 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264174 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
[email protected]e6d017652013-05-17 18:01:404175 SpdySessionKey session_pool_key_proxy(
bncb26024382016-06-29 02:39:454176 host_port_pair_,
[email protected]e6d017652013-05-17 18:01:404177 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
[email protected]314b03992014-04-01 01:28:534178 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264179 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:244180
rdsmithebb50aa2015-11-12 03:44:384181 // New SpdyTestUtil instance for the session that will be used for the
4182 // proxy connection.
bncd16676a2016-07-20 16:23:014183 SpdyTestUtil spdy_util_2;
rdsmithebb50aa2015-11-12 03:44:384184
[email protected]b261d0e2010-08-02 19:13:244185 // Set up data for the proxy connection.
bncce36dca22015-04-21 22:11:234186 const char kConnect443[] = {
4187 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174188 "Host: www.example.org:443\r\n"
bncce36dca22015-04-21 22:11:234189 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244190 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
bncdf80d44fd2016-07-15 20:27:414191 SpdySerializedFrame req2(spdy_util_2.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:494192 GetDefaultUrlWithPath("/foo.dat").c_str(), 1, LOWEST));
bnc42331402016-07-25 13:36:154193 SpdySerializedFrame resp2(spdy_util_2.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414194 SpdySerializedFrame body2(spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244195
rchebf12982015-04-10 01:15:004196 MockWrite writes2[] = {
4197 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
bncdf80d44fd2016-07-15 20:27:414198 CreateMockWrite(req2, 2),
[email protected]b261d0e2010-08-02 19:13:244199 };
rchebf12982015-04-10 01:15:004200 MockRead reads2[] = {
4201 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
bncdf80d44fd2016-07-15 20:27:414202 CreateMockRead(resp2, 3), CreateMockRead(body2, 4),
rchebf12982015-04-10 01:15:004203 MockRead(ASYNC, 0, 5) // EOF
[email protected]b261d0e2010-08-02 19:13:244204 };
4205
danakjaee3e1ec2016-04-16 00:23:184206 std::unique_ptr<SequencedSocketData> data_proxy(new SequencedSocketData(
rchebf12982015-04-10 01:15:004207 reads2, arraysize(reads2), writes2, arraysize(writes2)));
[email protected]b261d0e2010-08-02 19:13:244208
bncce36dca22015-04-21 22:11:234209 // Create another request to www.example.org, but this time through a proxy.
[email protected]b261d0e2010-08-02 19:13:244210 HttpRequestInfo request_proxy;
4211 request_proxy.method = "GET";
rchebf12982015-04-10 01:15:004212 request_proxy.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
[email protected]b261d0e2010-08-02 19:13:244213 request_proxy.load_flags = 0;
bncd16676a2016-07-20 16:23:014214 auto session_deps_proxy = base::MakeUnique<SpdySessionDependencies>(
bnc301745a2015-03-10 03:22:164215 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
bncd16676a2016-07-20 16:23:014216 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
4217 BoundNetLog(),
4218 std::move(session_deps_proxy));
[email protected]b261d0e2010-08-02 19:13:244219 helper_proxy.RunPreTestSetup();
4220 helper_proxy.AddData(data_proxy.get());
4221
4222 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
[email protected]49639fa2011-12-20 23:22:414223 TestCompletionCallback callback_proxy;
4224 int rv = trans_proxy->Start(
4225 &request_proxy, callback_proxy.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014226 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b261d0e2010-08-02 19:13:244227 rv = callback_proxy.WaitForResult();
4228 EXPECT_EQ(0, rv);
4229
4230 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
wezca1070932016-05-26 20:30:524231 ASSERT_TRUE(response_proxy.headers);
bnc84e7fb52015-12-02 11:50:024232 EXPECT_EQ("HTTP/1.1 200", response_proxy.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:244233
4234 std::string response_data;
robpercival214763f2016-07-01 23:27:014235 ASSERT_THAT(ReadTransaction(trans_proxy, &response_data), IsOk());
[email protected]b261d0e2010-08-02 19:13:244236 EXPECT_EQ("hello!", response_data);
4237
[email protected]b261d0e2010-08-02 19:13:244238 helper_proxy.VerifyDataConsumed();
4239}
4240
[email protected]58cebf8f2010-07-31 19:20:164241// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4242// on a new connection, if the connection was previously known to be good.
4243// This can happen when a server reboots without saying goodbye, or when
4244// we're behind a NAT that masked the RST.
bncd16676a2016-07-20 16:23:014245TEST_F(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
bnc42331402016-07-25 13:36:154246 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414247 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]58cebf8f2010-07-31 19:20:164248 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414249 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch32320842015-05-16 15:57:094250 MockRead(ASYNC, ERR_IO_PENDING, 3),
4251 MockRead(ASYNC, ERR_CONNECTION_RESET, 4),
[email protected]58cebf8f2010-07-31 19:20:164252 };
4253
4254 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:414255 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch32320842015-05-16 15:57:094256 MockRead(ASYNC, 0, 3) // EOF
[email protected]58cebf8f2010-07-31 19:20:164257 };
4258
bncdf80d44fd2016-07-15 20:27:414259 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494260 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:384261 // In all cases the connection will be reset before req3 can be
4262 // dispatched, destroying both streams.
4263 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:414264 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:494265 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414266 MockWrite writes1[] = {CreateMockWrite(req, 0), CreateMockWrite(req3, 5)};
4267 MockWrite writes2[] = {CreateMockWrite(req, 0)};
rchacdcbdc2015-05-16 17:16:004268
[email protected]58cebf8f2010-07-31 19:20:164269 // This test has a couple of variants.
4270 enum {
4271 // Induce the RST while waiting for our transaction to send.
rchacdcbdc2015-05-16 17:16:004272 VARIANT_RST_DURING_SEND_COMPLETION = 0,
[email protected]58cebf8f2010-07-31 19:20:164273 // Induce the RST while waiting for our transaction to read.
4274 // In this case, the send completed - everything copied into the SNDBUF.
rchacdcbdc2015-05-16 17:16:004275 VARIANT_RST_DURING_READ_COMPLETION = 1
[email protected]58cebf8f2010-07-31 19:20:164276 };
4277
4278 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4279 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4280 ++variant) {
rchacdcbdc2015-05-16 17:16:004281 SequencedSocketData data1(reads, arraysize(reads), writes1, 1 + variant);
[email protected]58cebf8f2010-07-31 19:20:164282
rchacdcbdc2015-05-16 17:16:004283 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
4284 arraysize(writes2));
[email protected]58cebf8f2010-07-31 19:20:164285
[email protected]262eec82013-03-19 21:01:364286 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014287 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:574288 helper.AddData(&data1);
4289 helper.AddData(&data2);
[email protected]58cebf8f2010-07-31 19:20:164290 helper.RunPreTestSetup();
4291
4292 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:164293 HttpNetworkTransaction trans(DEFAULT_PRIORITY, helper.session());
[email protected]58cebf8f2010-07-31 19:20:164294
[email protected]49639fa2011-12-20 23:22:414295 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:164296 int rv =
4297 trans.Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014298 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]58cebf8f2010-07-31 19:20:164299 // On the second transaction, we trigger the RST.
4300 if (i == 1) {
4301 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4302 // Writes to the socket complete asynchronously on SPDY by running
4303 // through the message loop. Complete the write here.
[email protected]fc9d88472013-08-14 02:31:174304 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164305 }
4306
4307 // Now schedule the ERR_CONNECTION_RESET.
mmenkee24011922015-12-17 22:12:594308 data1.Resume();
[email protected]58cebf8f2010-07-31 19:20:164309 }
4310 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014311 EXPECT_THAT(rv, IsOk());
[email protected]58cebf8f2010-07-31 19:20:164312
bnc691fda62016-08-12 00:43:164313 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:524314 ASSERT_TRUE(response);
4315 EXPECT_TRUE(response->headers);
[email protected]58cebf8f2010-07-31 19:20:164316 EXPECT_TRUE(response->was_fetched_via_spdy);
4317 std::string response_data;
bnc691fda62016-08-12 00:43:164318 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014319 EXPECT_THAT(rv, IsOk());
bnc84e7fb52015-12-02 11:50:024320 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]58cebf8f2010-07-31 19:20:164321 EXPECT_EQ("hello!", response_data);
rchacdcbdc2015-05-16 17:16:004322 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164323 }
4324
4325 helper.VerifyDataConsumed();
rchacdcbdc2015-05-16 17:16:004326 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164327 }
4328}
[email protected]1f418ee2010-10-16 19:46:564329
[email protected]018aabc2010-10-29 16:16:594330// Tests that Basic authentication works over SPDY
bncd16676a2016-07-20 16:23:014331TEST_F(SpdyNetworkTransactionTest, SpdyBasicAuth) {
[email protected]018aabc2010-10-29 16:16:594332 // The first request will be a bare GET, the second request will be a
4333 // GET with an Authorization header.
bncdf80d44fd2016-07-15 20:27:414334 SpdySerializedFrame req_get(
bnc38dcd392016-02-09 23:19:494335 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:384336 // Will be refused for lack of auth.
4337 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]018aabc2010-10-29 16:16:594338 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464339 "authorization", "Basic Zm9vOmJhcg=="
[email protected]018aabc2010-10-29 16:16:594340 };
bncdf80d44fd2016-07-15 20:27:414341 SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
4342 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders) / 2, 3,
4343 LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594344 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:414345 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]018aabc2010-10-29 16:16:594346 };
4347
4348 // The first response is a 401 authentication challenge, and the second
4349 // response will be a 200 response since the second request includes a valid
4350 // Authorization header.
4351 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:264352 "www-authenticate",
[email protected]018aabc2010-10-29 16:16:594353 "Basic realm=\"MyRealm\""
4354 };
bnc42331402016-07-25 13:36:154355 SpdySerializedFrame resp_authentication(spdy_util_.ConstructSpdyReplyError(
bncdf80d44fd2016-07-15 20:27:414356 "401 Authentication Required", kExtraAuthenticationHeaders,
4357 arraysize(kExtraAuthenticationHeaders) / 2, 1));
4358 SpdySerializedFrame body_authentication(
4359 spdy_util_.ConstructSpdyDataFrame(1, true));
bnc42331402016-07-25 13:36:154360 SpdySerializedFrame resp_data(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:414361 SpdySerializedFrame body_data(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]018aabc2010-10-29 16:16:594362 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414363 CreateMockRead(resp_authentication, 1),
4364 CreateMockRead(body_authentication, 2),
4365 CreateMockRead(resp_data, 4),
4366 CreateMockRead(body_data, 5),
rch08e3aa3e2015-05-16 14:27:524367 MockRead(ASYNC, 0, 6),
[email protected]018aabc2010-10-29 16:16:594368 };
4369
rch08e3aa3e2015-05-16 14:27:524370 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4371 arraysize(spdy_writes));
[email protected]018aabc2010-10-29 16:16:594372 HttpRequestInfo request(CreateGetRequest());
bnc4d782f492016-08-18 13:50:004373 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4374 NULL);
[email protected]018aabc2010-10-29 16:16:594375
4376 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574377 helper.AddData(&data);
bnc4d782f492016-08-18 13:50:004378 helper.StartDefaultTest();
4379 EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING));
4380
4381 helper.WaitForCallbackToComplete();
4382 EXPECT_THAT(helper.output().rv, IsOk());
[email protected]018aabc2010-10-29 16:16:594383
4384 // Make sure the response has an auth challenge.
bnc4d782f492016-08-18 13:50:004385 HttpNetworkTransaction* trans = helper.trans();
[email protected]018aabc2010-10-29 16:16:594386 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524387 ASSERT_TRUE(response_start);
4388 ASSERT_TRUE(response_start->headers);
[email protected]018aabc2010-10-29 16:16:594389 EXPECT_EQ(401, response_start->headers->response_code());
4390 EXPECT_TRUE(response_start->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044391 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
wezca1070932016-05-26 20:30:524392 ASSERT_TRUE(auth_challenge);
[email protected]79cb5c12011-09-12 13:12:044393 EXPECT_FALSE(auth_challenge->is_proxy);
aberentbba302d2015-12-03 10:20:194394 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:044395 EXPECT_EQ("MyRealm", auth_challenge->realm);
[email protected]018aabc2010-10-29 16:16:594396
4397 // Restart with a username/password.
[email protected]ad65a3e2013-12-25 18:18:014398 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
4399 base::ASCIIToUTF16("bar"));
[email protected]49639fa2011-12-20 23:22:414400 TestCompletionCallback callback_restart;
4401 const int rv_restart = trans->RestartWithAuth(
4402 credentials, callback_restart.callback());
robpercival214763f2016-07-01 23:27:014403 EXPECT_THAT(rv_restart, IsError(ERR_IO_PENDING));
[email protected]018aabc2010-10-29 16:16:594404 const int rv_restart_complete = callback_restart.WaitForResult();
robpercival214763f2016-07-01 23:27:014405 EXPECT_THAT(rv_restart_complete, IsOk());
[email protected]018aabc2010-10-29 16:16:594406 // TODO(cbentzel): This is actually the same response object as before, but
4407 // data has changed.
4408 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524409 ASSERT_TRUE(response_restart);
4410 ASSERT_TRUE(response_restart->headers);
[email protected]018aabc2010-10-29 16:16:594411 EXPECT_EQ(200, response_restart->headers->response_code());
4412 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4413}
4414
bncd16676a2016-07-20 16:23:014415TEST_F(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
bncdf80d44fd2016-07-15 20:27:414416 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494417 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]d08358502010-12-03 22:04:034418 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414419 CreateMockWrite(stream1_syn, 0),
[email protected]d08358502010-12-03 22:04:034420 };
4421
bncdf80d44fd2016-07-15 20:27:414422 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154423 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc38dcd392016-02-09 23:19:494424
bnc086b39e12016-06-24 13:05:264425 SpdyHeaderBlock initial_headers;
rchebf12982015-04-10 01:15:004426 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
bnc086b39e12016-06-24 13:05:264427 &initial_headers);
bncdf80d44fd2016-07-15 20:27:414428 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4429 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:044430
bnc38dcd392016-02-09 23:19:494431 SpdyHeaderBlock late_headers;
4432 late_headers[spdy_util_.GetStatusKey()] = "200";
bnc38dcd392016-02-09 23:19:494433 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414434 SpdySerializedFrame stream2_headers(spdy_util_.ConstructSpdyResponseHeaders(
4435 2, std::move(late_headers), false));
[email protected]d08358502010-12-03 22:04:034436
bncdf80d44fd2016-07-15 20:27:414437 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc38dcd392016-02-09 23:19:494438
[email protected]8a0fc822013-06-27 20:52:434439 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414440 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
4441 2, kPushedData, strlen(kPushedData), true));
bnc38dcd392016-02-09 23:19:494442
[email protected]d08358502010-12-03 22:04:034443 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414444 CreateMockRead(stream1_reply, 1),
4445 CreateMockRead(stream2_syn, 2),
4446 CreateMockRead(stream2_headers, 3),
4447 CreateMockRead(stream1_body, 4, SYNCHRONOUS),
4448 CreateMockRead(stream2_body, 5),
rch08e3aa3e2015-05-16 14:27:524449 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]d08358502010-12-03 22:04:034450 };
4451
4452 HttpResponseInfo response;
4453 HttpResponseInfo response2;
4454 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:524455 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574456 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:034457 &response,
4458 &response2,
4459 expected_push_result);
4460
bnc42331402016-07-25 13:36:154461 // Verify the response headers.
wezca1070932016-05-26 20:30:524462 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024463 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034464
4465 // Verify the pushed stream.
wezca1070932016-05-26 20:30:524466 EXPECT_TRUE(response2.headers);
bnc84e7fb52015-12-02 11:50:024467 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034468}
4469
bncd16676a2016-07-20 16:23:014470TEST_F(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
[email protected]d08358502010-12-03 22:04:034471 // We push a stream and attempt to claim it before the headers come down.
bncdf80d44fd2016-07-15 20:27:414472 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494473 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]d08358502010-12-03 22:04:034474 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414475 CreateMockWrite(stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:034476 };
4477
bncdf80d44fd2016-07-15 20:27:414478 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154479 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc086b39e12016-06-24 13:05:264480 SpdyHeaderBlock initial_headers;
rchebf12982015-04-10 01:15:004481 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
bnc086b39e12016-06-24 13:05:264482 &initial_headers);
bncdf80d44fd2016-07-15 20:27:414483 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4484 std::move(initial_headers), 2, 1));
4485 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc38dcd392016-02-09 23:19:494486 SpdyHeaderBlock late_headers;
4487 late_headers[spdy_util_.GetStatusKey()] = "200";
bnc38dcd392016-02-09 23:19:494488 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414489 SpdySerializedFrame stream2_headers(spdy_util_.ConstructSpdyResponseHeaders(
4490 2, std::move(late_headers), false));
[email protected]8a0fc822013-06-27 20:52:434491 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414492 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
4493 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:034494 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414495 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
4496 CreateMockRead(stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
4497 CreateMockRead(stream2_headers, 5), CreateMockRead(stream2_body, 6),
4498 MockRead(ASYNC, ERR_IO_PENDING, 7), MockRead(ASYNC, 0, 8), // EOF
[email protected]d08358502010-12-03 22:04:034499 };
4500
4501 HttpResponseInfo response;
4502 HttpResponseInfo response2;
4503 std::string expected_push_result("pushed");
mmenke666a6fea2015-12-19 04:16:334504 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:034505
[email protected]262eec82013-03-19 21:01:364506 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014507 BoundNetLog(), NULL);
mmenke666a6fea2015-12-19 04:16:334508 helper.AddData(&data);
[email protected]d08358502010-12-03 22:04:034509 helper.RunPreTestSetup();
4510
4511 HttpNetworkTransaction* trans = helper.trans();
4512
[email protected]d08358502010-12-03 22:04:034513 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:414514 TestCompletionCallback callback;
4515 int rv = trans->Start(
4516 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014517 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bnc42331402016-07-25 13:36:154518 // Run until we've received the primary HEADERS, the pushed HEADERS,
mmenke666a6fea2015-12-19 04:16:334519 // and the body of the primary stream, but before we've received the HEADERS
4520 // for the pushed stream.
4521 data.RunUntilPaused();
robpercival214763f2016-07-01 23:27:014522 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d08358502010-12-03 22:04:034523
4524 // Request the pushed path. At this point, we've received the push, but the
4525 // headers are not yet complete.
bnc691fda62016-08-12 00:43:164526 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
4527 rv =
4528 trans2.Start(&CreateGetPushRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014529 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
mmenke666a6fea2015-12-19 04:16:334530 data.Resume();
4531 data.RunUntilPaused();
[email protected]fc9d88472013-08-14 02:31:174532 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:034533
4534 // Read the server push body.
4535 std::string result2;
bnc691fda62016-08-12 00:43:164536 ReadResult(&trans2, &result2);
[email protected]d08358502010-12-03 22:04:034537 // Read the response body.
4538 std::string result;
rch0aecfd82015-05-19 17:22:324539 ReadResult(trans, &result);
[email protected]d08358502010-12-03 22:04:034540
[email protected]d08358502010-12-03 22:04:034541 // Verify that the received push data is same as the expected push data.
4542 EXPECT_EQ(result2.compare(expected_push_result), 0)
4543 << "Received data: "
4544 << result2
4545 << "||||| Expected data: "
4546 << expected_push_result;
4547
bnc42331402016-07-25 13:36:154548 // Verify the response headers.
[email protected]d08358502010-12-03 22:04:034549 // Copy the response info, because trans goes away.
4550 response = *trans->GetResponseInfo();
bnc691fda62016-08-12 00:43:164551 response2 = *trans2.GetResponseInfo();
[email protected]d08358502010-12-03 22:04:034552
4553 VerifyStreamsClosed(helper);
4554
bnc42331402016-07-25 13:36:154555 // Verify the response headers.
wezca1070932016-05-26 20:30:524556 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024557 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034558
4559 // Verify the pushed stream.
wezca1070932016-05-26 20:30:524560 EXPECT_TRUE(response2.headers);
bnc84e7fb52015-12-02 11:50:024561 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d55b30a2012-07-21 00:35:394562
4563 // Read the final EOF (which will close the session)
mmenke666a6fea2015-12-19 04:16:334564 data.Resume();
4565 base::RunLoop().RunUntilIdle();
[email protected]d55b30a2012-07-21 00:35:394566
4567 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:174568 EXPECT_TRUE(data.AllReadDataConsumed());
4569 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:034570}
4571
[email protected]6cd63ba2014-06-12 16:14:564572// TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
bncd16676a2016-07-20 16:23:014573TEST_F(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
[email protected]d08358502010-12-03 22:04:034574 // We push a stream and attempt to claim it before the headers come down.
bncdf80d44fd2016-07-15 20:27:414575 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494576 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]d08358502010-12-03 22:04:034577 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414578 CreateMockWrite(stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:034579 };
4580
bncdf80d44fd2016-07-15 20:27:414581 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154582 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc38dcd392016-02-09 23:19:494583
bnc086b39e12016-06-24 13:05:264584 SpdyHeaderBlock initial_headers;
rchebf12982015-04-10 01:15:004585 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
bnc086b39e12016-06-24 13:05:264586 &initial_headers);
bncdf80d44fd2016-07-15 20:27:414587 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4588 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:044589
bncdf80d44fd2016-07-15 20:27:414590 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]513963e2013-06-15 01:53:044591
bnc38dcd392016-02-09 23:19:494592 SpdyHeaderBlock middle_headers;
4593 middle_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414594 SpdySerializedFrame stream2_headers1(spdy_util_.ConstructSpdyResponseHeaders(
4595 2, std::move(middle_headers), false));
bnc38dcd392016-02-09 23:19:494596
4597 SpdyHeaderBlock late_headers;
4598 late_headers[spdy_util_.GetStatusKey()] = "200";
bncdf80d44fd2016-07-15 20:27:414599 SpdySerializedFrame stream2_headers2(spdy_util_.ConstructSpdyResponseHeaders(
4600 2, std::move(late_headers), false));
[email protected]d08358502010-12-03 22:04:034601
[email protected]8a0fc822013-06-27 20:52:434602 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414603 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
4604 2, kPushedData, strlen(kPushedData), true));
bnc38dcd392016-02-09 23:19:494605
[email protected]d08358502010-12-03 22:04:034606 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414607 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
4608 CreateMockRead(stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
4609 CreateMockRead(stream2_headers1, 5),
mmenke666a6fea2015-12-19 04:16:334610 // This is needed to work around https://crbug.com/571102.
bncdf80d44fd2016-07-15 20:27:414611 MockRead(ASYNC, ERR_IO_PENDING, 6), CreateMockRead(stream2_headers2, 7),
4612 CreateMockRead(stream2_body, 8), MockRead(ASYNC, ERR_IO_PENDING, 9),
mmenke666a6fea2015-12-19 04:16:334613 MockRead(ASYNC, 0, 10), // EOF
[email protected]d08358502010-12-03 22:04:034614 };
4615
4616 HttpResponseInfo response;
4617 HttpResponseInfo response2;
4618 std::string expected_push_result("pushed");
mmenke666a6fea2015-12-19 04:16:334619 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:034620
[email protected]262eec82013-03-19 21:01:364621 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014622 BoundNetLog(), NULL);
mmenke666a6fea2015-12-19 04:16:334623 helper.AddData(&data);
[email protected]d08358502010-12-03 22:04:034624 helper.RunPreTestSetup();
4625
4626 HttpNetworkTransaction* trans = helper.trans();
4627
[email protected]d08358502010-12-03 22:04:034628 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:414629 TestCompletionCallback callback;
4630 int rv = trans->Start(
4631 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014632 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bnc42331402016-07-25 13:36:154633 // Run until we've received the primary HEADERS, the pushed HEADERS,
mmenke666a6fea2015-12-19 04:16:334634 // the first HEADERS frame, and the body of the primary stream, but before
4635 // we've received the final HEADERS for the pushed stream.
4636 data.RunUntilPaused();
4637 EXPECT_EQ(0, callback.WaitForResult());
[email protected]d08358502010-12-03 22:04:034638
4639 // Request the pushed path. At this point, we've received the push, but the
4640 // headers are not yet complete.
bnc691fda62016-08-12 00:43:164641 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
4642 rv =
4643 trans2.Start(&CreateGetPushRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014644 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
mmenke666a6fea2015-12-19 04:16:334645 data.Resume();
4646 data.RunUntilPaused();
4647 base::RunLoop().RunUntilIdle();
4648 // This is needed to work around https://crbug.com/571102.
4649 data.Resume();
4650 data.RunUntilPaused();
[email protected]fc9d88472013-08-14 02:31:174651 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:034652
4653 // Read the server push body.
4654 std::string result2;
bnc691fda62016-08-12 00:43:164655 ReadResult(&trans2, &result2);
[email protected]d08358502010-12-03 22:04:034656 // Read the response body.
4657 std::string result;
rch0aecfd82015-05-19 17:22:324658 ReadResult(trans, &result);
[email protected]d08358502010-12-03 22:04:034659
[email protected]d08358502010-12-03 22:04:034660 // Verify that the received push data is same as the expected push data.
[email protected]6d116e1a2013-06-24 07:42:154661 EXPECT_EQ(expected_push_result, result2);
[email protected]d08358502010-12-03 22:04:034662
bnc42331402016-07-25 13:36:154663 // Verify the response headers.
[email protected]d08358502010-12-03 22:04:034664 // Copy the response info, because trans goes away.
4665 response = *trans->GetResponseInfo();
bnc691fda62016-08-12 00:43:164666 response2 = *trans2.GetResponseInfo();
[email protected]d08358502010-12-03 22:04:034667
4668 VerifyStreamsClosed(helper);
4669
bnc42331402016-07-25 13:36:154670 // Verify the response headers.
wezca1070932016-05-26 20:30:524671 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024672 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034673
4674 // Verify the pushed stream.
wezca1070932016-05-26 20:30:524675 EXPECT_TRUE(response2.headers);
bnc84e7fb52015-12-02 11:50:024676 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:034677
[email protected]6cd63ba2014-06-12 16:14:564678 // Verify we got all the headers from all header blocks.
[email protected]d08358502010-12-03 22:04:034679 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
4680 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
[email protected]d55b30a2012-07-21 00:35:394681
4682 // Read the final EOF (which will close the session)
mmenke666a6fea2015-12-19 04:16:334683 data.Resume();
4684 base::RunLoop().RunUntilIdle();
[email protected]d55b30a2012-07-21 00:35:394685
4686 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:174687 EXPECT_TRUE(data.AllReadDataConsumed());
4688 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:034689}
4690
bncd16676a2016-07-20 16:23:014691TEST_F(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
[email protected]5c6908e2012-08-06 18:53:474692 // We push a stream and attempt to claim it before the headers come down.
bncdf80d44fd2016-07-15 20:27:414693 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494694 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]5c6908e2012-08-06 18:53:474695 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414696 CreateMockWrite(stream1_syn, 0, SYNCHRONOUS),
[email protected]5c6908e2012-08-06 18:53:474697 };
4698
bncdf80d44fd2016-07-15 20:27:414699 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154700 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bnc38dcd392016-02-09 23:19:494701
bnc086b39e12016-06-24 13:05:264702 SpdyHeaderBlock initial_headers;
rchebf12982015-04-10 01:15:004703 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
bnc086b39e12016-06-24 13:05:264704 &initial_headers);
bncdf80d44fd2016-07-15 20:27:414705 SpdySerializedFrame stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4706 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:044707
bncdf80d44fd2016-07-15 20:27:414708 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]5c6908e2012-08-06 18:53:474709
bnc38dcd392016-02-09 23:19:494710 SpdyHeaderBlock middle_headers;
4711 middle_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414712 SpdySerializedFrame stream2_headers1(spdy_util_.ConstructSpdyResponseHeaders(
4713 2, std::move(middle_headers), false));
bnc38dcd392016-02-09 23:19:494714
[email protected]8a0fc822013-06-27 20:52:434715 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414716 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
4717 2, kPushedData, strlen(kPushedData), true));
bnc38dcd392016-02-09 23:19:494718
[email protected]5c6908e2012-08-06 18:53:474719 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414720 CreateMockRead(stream1_reply, 1), CreateMockRead(stream2_syn, 2),
4721 CreateMockRead(stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
4722 CreateMockRead(stream2_headers1, 5), CreateMockRead(stream2_body, 6),
4723 MockRead(ASYNC, ERR_IO_PENDING, 7), MockRead(ASYNC, 0, 8), // EOF
[email protected]5c6908e2012-08-06 18:53:474724 };
4725
mmenke666a6fea2015-12-19 04:16:334726 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]5c6908e2012-08-06 18:53:474727
[email protected]262eec82013-03-19 21:01:364728 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014729 BoundNetLog(), NULL);
mmenke666a6fea2015-12-19 04:16:334730 helper.AddData(&data);
[email protected]5c6908e2012-08-06 18:53:474731 helper.RunPreTestSetup();
4732
4733 HttpNetworkTransaction* trans = helper.trans();
4734
[email protected]5c6908e2012-08-06 18:53:474735 // Start the transaction.
4736 TestCompletionCallback callback;
4737 int rv = trans->Start(
4738 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014739 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bnc42331402016-07-25 13:36:154740 // Run until we've received the primary HEADERS, the pushed HEADERS,
mmenke666a6fea2015-12-19 04:16:334741 // the first HEADERS frame, and the body of the primary stream, but before
4742 // we've received the final HEADERS for the pushed stream.
4743 data.RunUntilPaused();
4744 EXPECT_EQ(0, callback.WaitForResult());
[email protected]5c6908e2012-08-06 18:53:474745
4746 // Request the pushed path. At this point, we've received the push, but the
4747 // headers are not yet complete.
bnc691fda62016-08-12 00:43:164748 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
4749 rv =
4750 trans2.Start(&CreateGetPushRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014751 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
mmenke666a6fea2015-12-19 04:16:334752 data.Resume();
4753 data.RunUntilPaused();
[email protected]fc9d88472013-08-14 02:31:174754 base::RunLoop().RunUntilIdle();
[email protected]5c6908e2012-08-06 18:53:474755
4756 // Read the server push body.
4757 std::string result2;
bnc691fda62016-08-12 00:43:164758 ReadResult(&trans2, &result2);
[email protected]5c6908e2012-08-06 18:53:474759 // Read the response body.
4760 std::string result;
rch0aecfd82015-05-19 17:22:324761 ReadResult(trans, &result);
[email protected]5c6908e2012-08-06 18:53:474762 EXPECT_EQ("hello!", result);
4763
4764 // Verify that we haven't received any push data.
4765 EXPECT_EQ("", result2);
4766
bnc42331402016-07-25 13:36:154767 // Verify the response headers.
[email protected]5c6908e2012-08-06 18:53:474768 // Copy the response info, because trans goes away.
4769 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]5c6908e2012-08-06 18:53:474770
4771 VerifyStreamsClosed(helper);
4772
bnc42331402016-07-25 13:36:154773 // Verify the response headers.
wezca1070932016-05-26 20:30:524774 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024775 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]5c6908e2012-08-06 18:53:474776
4777 // Read the final EOF (which will close the session).
mmenke666a6fea2015-12-19 04:16:334778 data.Resume();
4779 base::RunLoop().RunUntilIdle();
[email protected]5c6908e2012-08-06 18:53:474780
4781 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:174782 EXPECT_TRUE(data.AllReadDataConsumed());
4783 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]5c6908e2012-08-06 18:53:474784}
4785
bnc42331402016-07-25 13:36:154786TEST_F(SpdyNetworkTransactionTest, ResponseHeadersTwice) {
bncdf80d44fd2016-07-15 20:27:414787 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494788 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414789 SpdySerializedFrame rst(
[email protected]b771bb72013-06-24 09:55:414790 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
4791 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414792 CreateMockWrite(req, 0), CreateMockWrite(rst, 4),
[email protected]745aa9c2014-06-27 02:21:294793 };
[email protected]d08358502010-12-03 22:04:034794
bncdf80d44fd2016-07-15 20:27:414795 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154796 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:044797
bnc38dcd392016-02-09 23:19:494798 SpdyHeaderBlock late_headers;
4799 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414800 SpdySerializedFrame stream1_headers(spdy_util_.ConstructSpdyResponseHeaders(
4801 1, std::move(late_headers), false));
4802 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d08358502010-12-03 22:04:034803 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414804 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_headers, 2),
4805 CreateMockRead(stream1_body, 3), MockRead(ASYNC, 0, 5) // EOF
[email protected]d08358502010-12-03 22:04:034806 };
4807
rch08e3aa3e2015-05-16 14:27:524808 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364809 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014810 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:574811 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:034812 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014813 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d08358502010-12-03 22:04:034814}
4815
xunjieli294da722015-08-11 19:15:024816// Tests that receiving HEADERS, DATA, HEADERS, and DATA in that sequence will
4817// trigger a ERR_SPDY_PROTOCOL_ERROR because trailing HEADERS must not be
4818// followed by any DATA frames.
bncd16676a2016-07-20 16:23:014819TEST_F(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) {
bncdf80d44fd2016-07-15 20:27:414820 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:494821 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:414822 SpdySerializedFrame rst(
[email protected]b771bb72013-06-24 09:55:414823 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
4824 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414825 CreateMockWrite(req, 0), CreateMockWrite(rst, 5),
[email protected]b771bb72013-06-24 09:55:414826 };
[email protected]d08358502010-12-03 22:04:034827
bncdf80d44fd2016-07-15 20:27:414828 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154829 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414830 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, false));
bnc38dcd392016-02-09 23:19:494831
4832 SpdyHeaderBlock late_headers;
4833 late_headers["hello"] = "bye";
bncdf80d44fd2016-07-15 20:27:414834 SpdySerializedFrame stream1_headers(spdy_util_.ConstructSpdyResponseHeaders(
4835 1, std::move(late_headers), false));
4836 SpdySerializedFrame stream1_body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d08358502010-12-03 22:04:034837 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414838 CreateMockRead(stream1_reply, 1), CreateMockRead(stream1_body, 2),
4839 CreateMockRead(stream1_headers, 3), CreateMockRead(stream1_body2, 4),
rch08e3aa3e2015-05-16 14:27:524840 MockRead(ASYNC, 0, 6) // EOF
[email protected]d08358502010-12-03 22:04:034841 };
4842
rch32320842015-05-16 15:57:094843 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364844 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:014845 BoundNetLog(), NULL);
[email protected]dd54bd82012-07-19 23:44:574846 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:034847 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:014848 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d08358502010-12-03 22:04:034849}
4850
bncd16676a2016-07-20 16:23:014851TEST_F(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
[email protected]a7a265ef2010-12-08 18:05:574852 // In this test we want to verify that we can't accidentally push content
4853 // which can't be pushed by this content server.
4854 // This test assumes that:
4855 // - if we're requesting http://www.foo.com/barbaz
4856 // - the browser has made a connection to "www.foo.com".
4857
4858 // A list of the URL to fetch, followed by the URL being pushed.
4859 static const char* const kTestCases[] = {
bncce36dca22015-04-21 22:11:234860 "https://www.example.org/foo.html",
bncce36dca22015-04-21 22:11:234861 "http://www.example.org/foo.js", // Bad protocol
[email protected]a7a265ef2010-12-08 18:05:574862
bncce36dca22015-04-21 22:11:234863 "https://www.example.org/foo.html",
4864 "ftp://www.example.org/foo.js", // Invalid Protocol
[email protected]a7a265ef2010-12-08 18:05:574865
bncce36dca22015-04-21 22:11:234866 "https://www.example.org/foo.html",
4867 "https://blat.www.example.org/foo.js", // Cross subdomain
[email protected]a7a265ef2010-12-08 18:05:574868
bncce36dca22015-04-21 22:11:234869 "https://www.example.org/foo.html",
rchebf12982015-04-10 01:15:004870 "https://www.foo.com/foo.js", // Cross domain
[email protected]a7a265ef2010-12-08 18:05:574871 };
4872
[email protected]b3f899332010-12-08 18:20:444873 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
[email protected]a7a265ef2010-12-08 18:05:574874 const char* url_to_fetch = kTestCases[index];
4875 const char* url_to_push = kTestCases[index + 1];
4876
bncd16676a2016-07-20 16:23:014877 SpdyTestUtil spdy_test_util;
bncdf80d44fd2016-07-15 20:27:414878 SpdySerializedFrame stream1_syn(
bnc38dcd392016-02-09 23:19:494879 spdy_test_util.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414880 SpdySerializedFrame stream1_body(
4881 spdy_test_util.ConstructSpdyDataFrame(1, true));
4882 SpdySerializedFrame push_rst(
bnc38dcd392016-02-09 23:19:494883 spdy_test_util.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]a7a265ef2010-12-08 18:05:574884 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414885 CreateMockWrite(stream1_syn, 0), CreateMockWrite(push_rst, 3),
[email protected]a7a265ef2010-12-08 18:05:574886 };
4887
bncdf80d44fd2016-07-15 20:27:414888 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:154889 spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414890 SpdySerializedFrame stream2_syn(
bnc38dcd392016-02-09 23:19:494891 spdy_test_util.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
[email protected]8a0fc822013-06-27 20:52:434892 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414893 SpdySerializedFrame stream2_body(spdy_test_util.ConstructSpdyDataFrame(
4894 2, kPushedData, strlen(kPushedData), true));
4895 SpdySerializedFrame rst(
bnc38dcd392016-02-09 23:19:494896 spdy_test_util.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]a7a265ef2010-12-08 18:05:574897
4898 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414899 CreateMockRead(stream1_reply, 1),
4900 CreateMockRead(stream2_syn, 2),
4901 CreateMockRead(stream1_body, 4),
4902 CreateMockRead(stream2_body, 5),
rch08e3aa3e2015-05-16 14:27:524903 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]a7a265ef2010-12-08 18:05:574904 };
4905
4906 HttpResponseInfo response;
rch08e3aa3e2015-05-16 14:27:524907 SequencedSocketData data(reads, arraysize(reads), writes,
4908 arraysize(writes));
[email protected]a7a265ef2010-12-08 18:05:574909
4910 HttpRequestInfo request;
4911 request.method = "GET";
4912 request.url = GURL(url_to_fetch);
4913 request.load_flags = 0;
[email protected]a7a265ef2010-12-08 18:05:574914
[email protected]7c6f7ba2012-04-03 04:09:294915 // Enable cross-origin push. Since we are not using a proxy, this should
4916 // not actually enable cross-origin SPDY push.
bncd16676a2016-07-20 16:23:014917 auto session_deps = base::MakeUnique<SpdySessionDependencies>();
danakjaee3e1ec2016-04-16 00:23:184918 std::unique_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
tbansal28e68f82016-02-04 02:56:154919 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
4920 "https://123.45.67.89:443", net::ProxyServer::SCHEME_HTTP));
4921 session_deps->proxy_delegate.reset(proxy_delegate.release());
rdsmith82957ad2015-09-16 19:42:034922 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:014923 std::move(session_deps));
[email protected]61b4efc2012-04-27 18:12:504924 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574925 helper.AddData(&data);
[email protected]7c6f7ba2012-04-03 04:09:294926
[email protected]a7a265ef2010-12-08 18:05:574927 HttpNetworkTransaction* trans = helper.trans();
4928
4929 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:414930 TestCompletionCallback callback;
[email protected]a7a265ef2010-12-08 18:05:574931
[email protected]49639fa2011-12-20 23:22:414932 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014933 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a7a265ef2010-12-08 18:05:574934 rv = callback.WaitForResult();
4935
4936 // Read the response body.
4937 std::string result;
rch0aecfd82015-05-19 17:22:324938 ReadResult(trans, &result);
[email protected]a7a265ef2010-12-08 18:05:574939
4940 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:174941 EXPECT_TRUE(data.AllReadDataConsumed());
4942 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]a7a265ef2010-12-08 18:05:574943
bnc42331402016-07-25 13:36:154944 // Verify the response headers.
[email protected]a7a265ef2010-12-08 18:05:574945 // Copy the response info, because trans goes away.
4946 response = *trans->GetResponseInfo();
4947
4948 VerifyStreamsClosed(helper);
4949
bnc42331402016-07-25 13:36:154950 // Verify the response headers.
wezca1070932016-05-26 20:30:524951 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:024952 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]a7a265ef2010-12-08 18:05:574953 }
4954}
4955
bnc3e79387f2016-03-15 14:49:204956// Verify that push works cross origin as long as the certificate is valid for
4957// the pushed authority.
bncd16676a2016-07-20 16:23:014958TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOrigin) {
bnc3e79387f2016-03-15 14:49:204959 // "spdy_pooling.pem" is valid for both www.example.org and mail.example.org.
4960 const char* url_to_fetch = "https://www.example.org";
4961 const char* url_to_push = "https://mail.example.org";
4962
bncdf80d44fd2016-07-15 20:27:414963 SpdySerializedFrame headers(
bnc3e79387f2016-03-15 14:49:204964 spdy_util_.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
4965 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:414966 CreateMockWrite(headers, 0),
bnc3e79387f2016-03-15 14:49:204967 };
4968
bnc42331402016-07-25 13:36:154969 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414970 SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:204971 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
bncdf80d44fd2016-07-15 20:27:414972 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc3e79387f2016-03-15 14:49:204973 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:414974 SpdySerializedFrame pushed_body(spdy_util_.ConstructSpdyDataFrame(
4975 2, kPushedData, strlen(kPushedData), true));
bnc3e79387f2016-03-15 14:49:204976 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:414977 CreateMockRead(reply, 1),
4978 CreateMockRead(push, 2),
4979 CreateMockRead(body, 3),
4980 CreateMockRead(pushed_body, 4),
bnc3e79387f2016-03-15 14:49:204981 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
4982 };
4983
4984 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4985
4986 HttpRequestInfo request;
4987 request.method = "GET";
4988 request.url = GURL(url_to_fetch);
4989 request.load_flags = 0;
4990
4991 BoundNetLog log;
bncd16676a2016-07-20 16:23:014992 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, log, nullptr);
bnc3e79387f2016-03-15 14:49:204993 helper.RunPreTestSetup();
4994 helper.AddData(&data);
4995
4996 HttpNetworkTransaction* trans0 = helper.trans();
4997 TestCompletionCallback callback0;
4998 int rv = trans0->Start(&request, callback0.callback(), log);
4999 rv = callback0.GetResult(rv);
robpercival214763f2016-07-01 23:27:015000 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205001
5002 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
bncb26024382016-06-29 02:39:455003 SpdySessionKey key(host_port_pair_, ProxyServer::Direct(),
bnc3e79387f2016-03-15 14:49:205004 PRIVACY_MODE_DISABLED);
5005 base::WeakPtr<SpdySession> spdy_session =
5006 spdy_session_pool->FindAvailableSession(key, GURL(), log);
5007
5008 EXPECT_FALSE(spdy_session->unclaimed_pushed_streams_.empty());
5009 EXPECT_EQ(1u, spdy_session->unclaimed_pushed_streams_.size());
5010 EXPECT_EQ(1u,
5011 spdy_session->unclaimed_pushed_streams_.count(GURL(url_to_push)));
5012
bnc691fda62016-08-12 00:43:165013 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:205014 HttpRequestInfo push_request;
5015 push_request.method = "GET";
5016 push_request.url = GURL(url_to_push);
5017 push_request.load_flags = 0;
5018 TestCompletionCallback callback1;
bnc691fda62016-08-12 00:43:165019 rv = trans1.Start(&push_request, callback1.callback(), log);
bnc3e79387f2016-03-15 14:49:205020 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:015021 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205022
5023 EXPECT_TRUE(spdy_session->unclaimed_pushed_streams_.empty());
5024 EXPECT_EQ(0u, spdy_session->unclaimed_pushed_streams_.size());
5025
5026 helper.VerifyDataConsumed();
5027 VerifyStreamsClosed(helper);
5028
5029 HttpResponseInfo response = *trans0->GetResponseInfo();
wezca1070932016-05-26 20:30:525030 EXPECT_TRUE(response.headers);
bnc3e79387f2016-03-15 14:49:205031 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
5032
5033 std::string result0;
5034 ReadResult(trans0, &result0);
5035 EXPECT_EQ("hello!", result0);
5036
bnc691fda62016-08-12 00:43:165037 HttpResponseInfo push_response = *trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:525038 EXPECT_TRUE(push_response.headers);
bnc3e79387f2016-03-15 14:49:205039 EXPECT_EQ("HTTP/1.1 200", push_response.headers->GetStatusLine());
5040
5041 std::string result1;
bnc691fda62016-08-12 00:43:165042 ReadResult(&trans1, &result1);
bnc3e79387f2016-03-15 14:49:205043 EXPECT_EQ(kPushedData, result1);
5044}
5045
5046// Verify that push works cross origin, even if there is already a connection
5047// open to origin of pushed resource.
bncd16676a2016-07-20 16:23:015048TEST_F(SpdyNetworkTransactionTest, ServerPushValidCrossOriginWithOpenSession) {
bnc3e79387f2016-03-15 14:49:205049 const char* url_to_fetch0 = "https://mail.example.org/foo";
5050 const char* url_to_fetch1 = "https://docs.example.org";
5051 const char* url_to_push = "https://mail.example.org/bar";
5052
bncd16676a2016-07-20 16:23:015053 SpdyTestUtil spdy_util_0;
bnc3e79387f2016-03-15 14:49:205054
bncdf80d44fd2016-07-15 20:27:415055 SpdySerializedFrame headers0(
bnc3e79387f2016-03-15 14:49:205056 spdy_util_0.ConstructSpdyGet(url_to_fetch0, 1, LOWEST));
5057 MockWrite writes0[] = {
bncdf80d44fd2016-07-15 20:27:415058 CreateMockWrite(headers0, 0),
bnc3e79387f2016-03-15 14:49:205059 };
5060
bnc42331402016-07-25 13:36:155061 SpdySerializedFrame reply0(spdy_util_0.ConstructSpdyGetReply(nullptr, 0, 1));
bnc3e79387f2016-03-15 14:49:205062 const char kData0[] = "first";
bncdf80d44fd2016-07-15 20:27:415063 SpdySerializedFrame body0(
5064 spdy_util_0.ConstructSpdyDataFrame(1, kData0, strlen(kData0), true));
5065 MockRead reads0[] = {CreateMockRead(reply0, 1), CreateMockRead(body0, 2),
5066 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
bnc3e79387f2016-03-15 14:49:205067
5068 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
5069 arraysize(writes0));
5070
bncd16676a2016-07-20 16:23:015071 SpdyTestUtil spdy_util_1;
bnc3e79387f2016-03-15 14:49:205072
bncdf80d44fd2016-07-15 20:27:415073 SpdySerializedFrame headers1(
bnc3e79387f2016-03-15 14:49:205074 spdy_util_1.ConstructSpdyGet(url_to_fetch1, 1, LOWEST));
5075 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:415076 CreateMockWrite(headers1, 0),
bnc3e79387f2016-03-15 14:49:205077 };
5078
bnc42331402016-07-25 13:36:155079 SpdySerializedFrame reply1(spdy_util_1.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:415080 SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:205081 spdy_util_1.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
5082 const char kData1[] = "second";
bncdf80d44fd2016-07-15 20:27:415083 SpdySerializedFrame body1(
5084 spdy_util_1.ConstructSpdyDataFrame(1, kData1, strlen(kData1), true));
bnc3e79387f2016-03-15 14:49:205085 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:415086 SpdySerializedFrame pushed_body(spdy_util_1.ConstructSpdyDataFrame(
5087 2, kPushedData, strlen(kPushedData), true));
bnc3e79387f2016-03-15 14:49:205088
5089 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:415090 CreateMockRead(reply1, 1),
5091 CreateMockRead(push, 2),
5092 CreateMockRead(body1, 3),
5093 CreateMockRead(pushed_body, 4),
bnc3e79387f2016-03-15 14:49:205094 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
5095 };
5096
5097 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
5098 arraysize(writes1));
5099
5100 // Request |url_to_fetch0| to open connection to mail.example.org.
5101 HttpRequestInfo request0;
5102 request0.method = "GET";
5103 request0.url = GURL(url_to_fetch0);
5104 request0.load_flags = 0;
5105
5106 BoundNetLog log;
bncd16676a2016-07-20 16:23:015107 NormalSpdyTransactionHelper helper(request0, DEFAULT_PRIORITY, log, nullptr);
bnc3e79387f2016-03-15 14:49:205108 helper.RunPreTestSetup();
5109
5110 // "spdy_pooling.pem" is valid for www.example.org, but not for
5111 // docs.example.org.
danakjaee3e1ec2016-04-16 00:23:185112 std::unique_ptr<SSLSocketDataProvider> ssl_provider0(
bnc3e79387f2016-03-15 14:49:205113 new SSLSocketDataProvider(ASYNC, OK));
5114 ssl_provider0->cert =
5115 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
5116 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
5117
5118 // "wildcard.pem" is valid for both www.example.org and docs.example.org.
danakjaee3e1ec2016-04-16 00:23:185119 std::unique_ptr<SSLSocketDataProvider> ssl_provider1(
bnc3e79387f2016-03-15 14:49:205120 new SSLSocketDataProvider(ASYNC, OK));
5121 ssl_provider1->cert =
5122 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
5123 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
5124
5125 HttpNetworkTransaction* trans0 = helper.trans();
5126 TestCompletionCallback callback0;
5127 int rv = trans0->Start(&request0, callback0.callback(), log);
5128 rv = callback0.GetResult(rv);
robpercival214763f2016-07-01 23:27:015129 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205130
5131 // Request |url_to_fetch1|, during which docs.example.org pushes
5132 // |url_to_push|, which happens to be for www.example.org, to which there is
5133 // already an open connection.
bnc691fda62016-08-12 00:43:165134 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:205135 HttpRequestInfo request1;
5136 request1.method = "GET";
5137 request1.url = GURL(url_to_fetch1);
5138 request1.load_flags = 0;
5139 TestCompletionCallback callback1;
bnc691fda62016-08-12 00:43:165140 rv = trans1.Start(&request1, callback1.callback(), log);
bnc3e79387f2016-03-15 14:49:205141 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:015142 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205143
5144 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5145 HostPortPair host_port_pair0("mail.example.org", 443);
5146 SpdySessionKey key0(host_port_pair0, ProxyServer::Direct(),
5147 PRIVACY_MODE_DISABLED);
5148 base::WeakPtr<SpdySession> spdy_session0 =
5149 spdy_session_pool->FindAvailableSession(key0, GURL(), log);
5150
5151 EXPECT_TRUE(spdy_session0->unclaimed_pushed_streams_.empty());
5152 EXPECT_EQ(0u, spdy_session0->unclaimed_pushed_streams_.size());
5153
5154 HostPortPair host_port_pair1("docs.example.org", 443);
5155 SpdySessionKey key1(host_port_pair1, ProxyServer::Direct(),
5156 PRIVACY_MODE_DISABLED);
5157 base::WeakPtr<SpdySession> spdy_session1 =
5158 spdy_session_pool->FindAvailableSession(key1, GURL(), log);
5159
5160 EXPECT_FALSE(spdy_session1->unclaimed_pushed_streams_.empty());
5161 EXPECT_EQ(1u, spdy_session1->unclaimed_pushed_streams_.size());
5162 EXPECT_EQ(1u,
5163 spdy_session1->unclaimed_pushed_streams_.count(GURL(url_to_push)));
5164
5165 // Request |url_to_push|, which should be served from the pushed resource.
bnc691fda62016-08-12 00:43:165166 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
bnc3e79387f2016-03-15 14:49:205167 HttpRequestInfo push_request;
5168 push_request.method = "GET";
5169 push_request.url = GURL(url_to_push);
5170 push_request.load_flags = 0;
5171 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:165172 rv = trans2.Start(&push_request, callback2.callback(), log);
bnc3e79387f2016-03-15 14:49:205173 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:015174 EXPECT_THAT(rv, IsOk());
bnc3e79387f2016-03-15 14:49:205175
5176 EXPECT_TRUE(spdy_session0->unclaimed_pushed_streams_.empty());
5177 EXPECT_EQ(0u, spdy_session0->unclaimed_pushed_streams_.size());
5178
5179 EXPECT_TRUE(spdy_session1->unclaimed_pushed_streams_.empty());
5180 EXPECT_EQ(0u, spdy_session1->unclaimed_pushed_streams_.size());
5181
5182 helper.VerifyDataConsumed();
5183 VerifyStreamsClosed(helper);
5184
5185 HttpResponseInfo response0 = *trans0->GetResponseInfo();
wezca1070932016-05-26 20:30:525186 EXPECT_TRUE(response0.headers);
bnc3e79387f2016-03-15 14:49:205187 EXPECT_EQ("HTTP/1.1 200", response0.headers->GetStatusLine());
5188
5189 std::string result0;
5190 ReadResult(trans0, &result0);
5191 EXPECT_EQ(kData0, result0);
5192
bnc691fda62016-08-12 00:43:165193 HttpResponseInfo response1 = *trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:525194 EXPECT_TRUE(response1.headers);
bnc3e79387f2016-03-15 14:49:205195 EXPECT_EQ("HTTP/1.1 200", response1.headers->GetStatusLine());
5196
5197 std::string result1;
bnc691fda62016-08-12 00:43:165198 ReadResult(&trans1, &result1);
bnc3e79387f2016-03-15 14:49:205199 EXPECT_EQ(kData1, result1);
5200
bnc691fda62016-08-12 00:43:165201 HttpResponseInfo push_response = *trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:525202 EXPECT_TRUE(push_response.headers);
bnc3e79387f2016-03-15 14:49:205203 EXPECT_EQ("HTTP/1.1 200", push_response.headers->GetStatusLine());
5204
5205 std::string result2;
bnc691fda62016-08-12 00:43:165206 ReadResult(&trans2, &result2);
bnc3e79387f2016-03-15 14:49:205207 EXPECT_EQ(kPushedData, result2);
5208}
5209
bncd16676a2016-07-20 16:23:015210TEST_F(SpdyNetworkTransactionTest, ServerPushInvalidCrossOrigin) {
bnc3e79387f2016-03-15 14:49:205211 // "spdy_pooling.pem" is valid for www.example.org,
5212 // but not for invalid.example.org.
5213 const char* url_to_fetch = "https://www.example.org";
5214 const char* url_to_push = "https://invalid.example.org";
5215
bncdf80d44fd2016-07-15 20:27:415216 SpdySerializedFrame headers(
bnc3e79387f2016-03-15 14:49:205217 spdy_util_.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415218 SpdySerializedFrame rst(
bnc3e79387f2016-03-15 14:49:205219 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5220 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415221 CreateMockWrite(headers, 0), CreateMockWrite(rst, 3),
bnc3e79387f2016-03-15 14:49:205222 };
5223
bnc42331402016-07-25 13:36:155224 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:415225 SpdySerializedFrame push(
bnc3e79387f2016-03-15 14:49:205226 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
bncdf80d44fd2016-07-15 20:27:415227 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc3e79387f2016-03-15 14:49:205228 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:415229 SpdySerializedFrame pushed_body(spdy_util_.ConstructSpdyDataFrame(
5230 2, kPushedData, strlen(kPushedData), true));
bnc3e79387f2016-03-15 14:49:205231 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415232 CreateMockRead(reply, 1),
5233 CreateMockRead(push, 2),
5234 CreateMockRead(body, 4),
5235 CreateMockRead(pushed_body, 5),
bnc3e79387f2016-03-15 14:49:205236 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
5237 };
5238
5239 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
5240
5241 HttpRequestInfo request;
5242 request.method = "GET";
5243 request.url = GURL(url_to_fetch);
5244 request.load_flags = 0;
5245
5246 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:015247 nullptr);
bnc3e79387f2016-03-15 14:49:205248 helper.RunToCompletion(&data);
5249 TransactionHelperResult out = helper.output();
5250 EXPECT_EQ("HTTP/1.1 200", out.status_line);
5251 EXPECT_EQ("hello!", out.response_data);
5252}
5253
bncd16676a2016-07-20 16:23:015254TEST_F(SpdyNetworkTransactionTest, RetryAfterRefused) {
[email protected]721c0ce2011-10-13 02:41:005255 // Construct the request.
bncdf80d44fd2016-07-15 20:27:415256 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:495257 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:385258 // Will be destroyed by the RST before stream 3 starts.
5259 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:415260 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:495261 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
[email protected]721c0ce2011-10-13 02:41:005262 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415263 CreateMockWrite(req, 0), CreateMockWrite(req2, 2),
[email protected]721c0ce2011-10-13 02:41:005264 };
5265
bncdf80d44fd2016-07-15 20:27:415266 SpdySerializedFrame refused(
[email protected]c10b20852013-05-15 21:29:205267 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
bnc42331402016-07-25 13:36:155268 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:415269 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]721c0ce2011-10-13 02:41:005270 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415271 CreateMockRead(refused, 1), CreateMockRead(resp, 3),
5272 CreateMockRead(body, 4), MockRead(ASYNC, 0, 5) // EOF
[email protected]721c0ce2011-10-13 02:41:005273 };
5274
rch08e3aa3e2015-05-16 14:27:525275 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365276 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:015277 BoundNetLog(), NULL);
[email protected]721c0ce2011-10-13 02:41:005278
5279 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575280 helper.AddData(&data);
[email protected]721c0ce2011-10-13 02:41:005281
5282 HttpNetworkTransaction* trans = helper.trans();
5283
5284 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415285 TestCompletionCallback callback;
5286 int rv = trans->Start(
5287 &CreateGetRequest(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015288 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]721c0ce2011-10-13 02:41:005289 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015290 EXPECT_THAT(rv, IsOk());
[email protected]721c0ce2011-10-13 02:41:005291
5292 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:525293 EXPECT_TRUE(data.AllReadDataConsumed());
5294 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]721c0ce2011-10-13 02:41:005295
bnc42331402016-07-25 13:36:155296 // Verify the response headers.
[email protected]721c0ce2011-10-13 02:41:005297 HttpResponseInfo response = *trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525298 EXPECT_TRUE(response.headers);
bnc84e7fb52015-12-02 11:50:025299 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]721c0ce2011-10-13 02:41:005300}
5301
bnc42331402016-07-25 13:36:155302TEST_F(SpdyNetworkTransactionTest, OutOfOrderHeaders) {
[email protected]e1f58efa2012-05-15 18:23:405303 // This first request will start to establish the SpdySession.
5304 // Then we will start the second (MEDIUM priority) and then third
5305 // (HIGHEST priority) request in such a way that the third will actually
[email protected]c92f4b4542012-07-26 23:53:215306 // start before the second, causing the second to be numbered differently
[email protected]513963e2013-06-15 01:53:045307 // than the order they were created.
rdsmithebb50aa2015-11-12 03:44:385308 //
5309 // Note that the requests and responses created below are expectations
5310 // of what the above will produce on the wire, and hence are in the
5311 // initial->HIGHEST->LOWEST priority.
5312 //
5313 // Frames are created by SpdySession just before the write associated
5314 // with the frame is attempted, so stream dependencies will be based
5315 // on the streams alive at the point of the request write attempt. Thus
5316 // req1 is alive when req2 is attempted (during but not after the
5317 // |data.RunFor(2);| statement below) but not when req3 is attempted.
5318 // The call to spdy_util_.UpdateWithStreamDestruction() reflects this.
bncdf80d44fd2016-07-15 20:27:415319 SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:495320 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:415321 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:495322 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, HIGHEST, true));
rdsmithebb50aa2015-11-12 03:44:385323 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:415324 SpdySerializedFrame req3(
bnc38dcd392016-02-09 23:19:495325 spdy_util_.ConstructSpdyGet(nullptr, 0, 5, MEDIUM, true));
[email protected]e1f58efa2012-05-15 18:23:405326 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415327 MockWrite(ASYNC, ERR_IO_PENDING, 0), CreateMockWrite(req1, 1),
5328 CreateMockWrite(req2, 5), CreateMockWrite(req3, 6),
[email protected]e1f58efa2012-05-15 18:23:405329 };
5330
bnc42331402016-07-25 13:36:155331 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:415332 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc42331402016-07-25 13:36:155333 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:415334 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
bnc42331402016-07-25 13:36:155335 SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply(NULL, 0, 5));
bncdf80d44fd2016-07-15 20:27:415336 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true));
[email protected]e1f58efa2012-05-15 18:23:405337 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415338 CreateMockRead(resp1, 2), MockRead(ASYNC, ERR_IO_PENDING, 3),
5339 CreateMockRead(body1, 4), CreateMockRead(resp2, 7),
5340 CreateMockRead(body2, 8), CreateMockRead(resp3, 9),
5341 CreateMockRead(body3, 10), MockRead(ASYNC, 0, 11) // EOF
[email protected]e1f58efa2012-05-15 18:23:405342 };
5343
mmenke666a6fea2015-12-19 04:16:335344 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:015345 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST, BoundNetLog(),
5346 NULL);
[email protected]e1f58efa2012-05-15 18:23:405347 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:335348 helper.AddData(&data);
[email protected]e1f58efa2012-05-15 18:23:405349
5350 // Start the first transaction to set up the SpdySession
5351 HttpNetworkTransaction* trans = helper.trans();
5352 TestCompletionCallback callback;
5353 HttpRequestInfo info1 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405354 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015355 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e1f58efa2012-05-15 18:23:405356
5357 // Run the message loop, but do not allow the write to complete.
5358 // This leaves the SpdySession with a write pending, which prevents
5359 // SpdySession from attempting subsequent writes until this write completes.
[email protected]fc9d88472013-08-14 02:31:175360 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405361
5362 // Now, start both new transactions
5363 HttpRequestInfo info2 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405364 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:165365 HttpNetworkTransaction trans2(MEDIUM, helper.session());
5366 rv = trans2.Start(&info2, callback2.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015367 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:175368 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405369
5370 HttpRequestInfo info3 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405371 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:165372 HttpNetworkTransaction trans3(HIGHEST, helper.session());
5373 rv = trans3.Start(&info3, callback3.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015374 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]fc9d88472013-08-14 02:31:175375 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405376
bnc42331402016-07-25 13:36:155377 // We now have two HEADERS frames queued up which will be
[email protected]e1f58efa2012-05-15 18:23:405378 // dequeued only once the first write completes, which we
5379 // now allow to happen.
mmenke666a6fea2015-12-19 04:16:335380 ASSERT_TRUE(data.IsPaused());
5381 data.Resume();
robpercival214763f2016-07-01 23:27:015382 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e1f58efa2012-05-15 18:23:405383
5384 // And now we can allow everything else to run to completion.
mmenke666a6fea2015-12-19 04:16:335385 data.Resume();
5386 base::RunLoop().RunUntilIdle();
robpercival214763f2016-07-01 23:27:015387 EXPECT_THAT(callback2.WaitForResult(), IsOk());
5388 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]e1f58efa2012-05-15 18:23:405389
5390 helper.VerifyDataConsumed();
5391}
5392
[email protected]d11b6912013-06-27 23:07:325393// Test that sent data frames and received WINDOW_UPDATE frames change
5394// the send_window_size_ correctly.
5395
5396// WINDOW_UPDATE is different than most other frames in that it can arrive
5397// while the client is still sending the request body. In order to enforce
5398// this scenario, we feed a couple of dummy frames and give a delay of 0 to
5399// socket data provider, so that initial read that is done as soon as the
5400// stream is created, succeeds and schedules another read. This way reads
5401// and writes are interleaved; after doing a full frame write, SpdyStream
5402// will break out of DoLoop and will read and process a WINDOW_UPDATE.
bnc42331402016-07-25 13:36:155403// Once our WINDOW_UPDATE is read, we cannot send HEADERS right away
[email protected]d11b6912013-06-27 23:07:325404// since request has not been completely written, therefore we feed
5405// enough number of WINDOW_UPDATEs to finish the first read and cause a
5406// write, leading to a complete write of request body; after that we send
5407// a reply with a body, to cause a graceful shutdown.
5408
5409// TODO(agayev): develop a socket data provider where both, reads and
5410// writes are ordered so that writing tests like these are easy and rewrite
5411// all these tests using it. Right now we are working around the
5412// limitations as described above and it's not deterministic, tests may
5413// fail under specific circumstances.
bncd16676a2016-07-20 16:23:015414TEST_F(SpdyNetworkTransactionTest, WindowUpdateReceived) {
[email protected]d11b6912013-06-27 23:07:325415 static int kFrameCount = 2;
danakjaee3e1ec2016-04-16 00:23:185416 std::unique_ptr<std::string> content(
[email protected]d11b6912013-06-27 23:07:325417 new std::string(kMaxSpdyFrameChunkSize, 'a'));
bncdf80d44fd2016-07-15 20:27:415418 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455419 kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
bncdf80d44fd2016-07-15 20:27:415420 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555421 1, content->c_str(), content->size(), false));
bncdf80d44fd2016-07-15 20:27:415422 SpdySerializedFrame body_end(spdy_util_.ConstructSpdyDataFrame(
5423 1, content->c_str(), content->size(), true));
[email protected]d11b6912013-06-27 23:07:325424
5425 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415426 CreateMockWrite(req, 0), CreateMockWrite(body, 1),
5427 CreateMockWrite(body_end, 2),
[email protected]d11b6912013-06-27 23:07:325428 };
5429
Avi Drissman13fc8932015-12-20 04:40:465430 static const int32_t kDeltaWindowSize = 0xff;
[email protected]d11b6912013-06-27 23:07:325431 static const int kDeltaCount = 4;
bncdf80d44fd2016-07-15 20:27:415432 SpdySerializedFrame window_update(
[email protected]d11b6912013-06-27 23:07:325433 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
bncdf80d44fd2016-07-15 20:27:415434 SpdySerializedFrame window_update_dummy(
[email protected]d11b6912013-06-27 23:07:325435 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
bnc42331402016-07-25 13:36:155436 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(NULL, 0));
[email protected]d11b6912013-06-27 23:07:325437 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415438 CreateMockRead(window_update_dummy, 3),
5439 CreateMockRead(window_update_dummy, 4),
5440 CreateMockRead(window_update_dummy, 5),
5441 CreateMockRead(window_update, 6), // Four updates, therefore window
5442 CreateMockRead(window_update, 7), // size should increase by
5443 CreateMockRead(window_update, 8), // kDeltaWindowSize * 4
5444 CreateMockRead(window_update, 9),
5445 CreateMockRead(resp, 10),
5446 MockRead(ASYNC, ERR_IO_PENDING, 11),
5447 CreateMockRead(body_end, 12),
mmenke666a6fea2015-12-19 04:16:335448 MockRead(ASYNC, 0, 13) // EOF
[email protected]d11b6912013-06-27 23:07:325449 };
5450
mmenke666a6fea2015-12-19 04:16:335451 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d11b6912013-06-27 23:07:325452
danakjaee3e1ec2016-04-16 00:23:185453 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:325454 for (int i = 0; i < kFrameCount; ++i) {
danakjaee3e1ec2016-04-16 00:23:185455 element_readers.push_back(base::WrapUnique(
olli.raula6df48b2a2015-11-26 07:40:225456 new UploadBytesElementReader(content->c_str(), content->size())));
[email protected]d11b6912013-06-27 23:07:325457 }
olli.raula6df48b2a2015-11-26 07:40:225458 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325459
5460 // Setup the request
5461 HttpRequestInfo request;
5462 request.method = "POST";
bncb26024382016-06-29 02:39:455463 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325464 request.upload_data_stream = &upload_data_stream;
5465
bncd16676a2016-07-20 16:23:015466 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
5467 NULL);
mmenke666a6fea2015-12-19 04:16:335468 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:325469 helper.RunPreTestSetup();
5470
5471 HttpNetworkTransaction* trans = helper.trans();
5472
5473 TestCompletionCallback callback;
5474 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5475
robpercival214763f2016-07-01 23:27:015476 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325477
mmenke666a6fea2015-12-19 04:16:335478 data.RunUntilPaused();
5479 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325480
5481 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525482 ASSERT_TRUE(stream);
5483 ASSERT_TRUE(stream->stream());
bncbca843ba2016-07-14 13:05:485484 EXPECT_EQ(static_cast<int>(kDefaultInitialWindowSize) +
5485 kDeltaWindowSize * kDeltaCount -
5486 kMaxSpdyFrameChunkSize * kFrameCount,
5487 stream->stream()->send_window_size());
[email protected]d11b6912013-06-27 23:07:325488
mmenke666a6fea2015-12-19 04:16:335489 data.Resume();
5490 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325491
5492 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015493 EXPECT_THAT(rv, IsOk());
[email protected]d11b6912013-06-27 23:07:325494
5495 helper.VerifyDataConsumed();
5496}
5497
5498// Test that received data frames and sent WINDOW_UPDATE frames change
5499// the recv_window_size_ correctly.
bncd16676a2016-07-20 16:23:015500TEST_F(SpdyNetworkTransactionTest, WindowUpdateSent) {
bnc8f0f3b62015-04-08 04:37:235501 // Session level maximum window size that is more than twice the default
5502 // initial window size so that an initial window update is sent.
Avi Drissman13fc8932015-12-20 04:40:465503 const int32_t session_max_recv_window_size = 5 * 64 * 1024;
bncbca843ba2016-07-14 13:05:485504 ASSERT_LT(2 * kDefaultInitialWindowSize, session_max_recv_window_size);
bnc8f0f3b62015-04-08 04:37:235505 // Stream level maximum window size that is less than the session level
5506 // maximum window size so that we test for confusion between the two.
Avi Drissman13fc8932015-12-20 04:40:465507 const int32_t stream_max_recv_window_size = 4 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:235508 ASSERT_GT(session_max_recv_window_size, stream_max_recv_window_size);
5509 // Size of body to be sent. Has to be less than or equal to both window sizes
5510 // so that we do not run out of receiving window. Also has to be greater than
5511 // half of them so that it triggers both a session level and a stream level
5512 // window update frame.
Avi Drissman13fc8932015-12-20 04:40:465513 const int32_t kTargetSize = 3 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:235514 ASSERT_GE(session_max_recv_window_size, kTargetSize);
5515 ASSERT_GE(stream_max_recv_window_size, kTargetSize);
5516 ASSERT_LT(session_max_recv_window_size / 2, kTargetSize);
5517 ASSERT_LT(stream_max_recv_window_size / 2, kTargetSize);
5518 // Size of each DATA frame.
Avi Drissman13fc8932015-12-20 04:40:465519 const int32_t kChunkSize = 4096;
bnc8f0f3b62015-04-08 04:37:235520 // Size of window updates.
5521 ASSERT_EQ(0, session_max_recv_window_size / 2 % kChunkSize);
Avi Drissman13fc8932015-12-20 04:40:465522 const int32_t session_window_update_delta =
bnc8f0f3b62015-04-08 04:37:235523 session_max_recv_window_size / 2 + kChunkSize;
5524 ASSERT_EQ(0, stream_max_recv_window_size / 2 % kChunkSize);
Avi Drissman13fc8932015-12-20 04:40:465525 const int32_t stream_window_update_delta =
bnc8f0f3b62015-04-08 04:37:235526 stream_max_recv_window_size / 2 + kChunkSize;
[email protected]d11b6912013-06-27 23:07:325527
bnc8f0f3b62015-04-08 04:37:235528 SettingsMap initial_settings;
bncb3cafaa2016-09-02 16:59:565529 initial_settings[SETTINGS_HEADER_TABLE_SIZE] =
5530 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxHeaderTableSize);
bnc8f0f3b62015-04-08 04:37:235531 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
5532 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
5533 initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
5534 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size);
bncdf80d44fd2016-07-15 20:27:415535 SpdySerializedFrame initial_settings_frame(
bnc8f0f3b62015-04-08 04:37:235536 spdy_util_.ConstructSpdySettings(initial_settings));
bncdf80d44fd2016-07-15 20:27:415537 SpdySerializedFrame initial_window_update(
bnc8f0f3b62015-04-08 04:37:235538 spdy_util_.ConstructSpdyWindowUpdate(
5539 kSessionFlowControlStreamId,
bncbca843ba2016-07-14 13:05:485540 session_max_recv_window_size - kDefaultInitialWindowSize));
bncdf80d44fd2016-07-15 20:27:415541 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:495542 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:415543 SpdySerializedFrame session_window_update(
bnc8f0f3b62015-04-08 04:37:235544 spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta));
bncdf80d44fd2016-07-15 20:27:415545 SpdySerializedFrame stream_window_update(
bnc8f0f3b62015-04-08 04:37:235546 spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta));
[email protected]d11b6912013-06-27 23:07:325547
5548 std::vector<MockWrite> writes;
bnca9b9e222016-07-11 20:10:405549 writes.push_back(MockWrite(ASYNC, kHttp2ConnectionHeaderPrefix,
5550 kHttp2ConnectionHeaderPrefixSize, 0));
bncdf80d44fd2016-07-15 20:27:415551 writes.push_back(CreateMockWrite(initial_settings_frame, writes.size()));
5552 writes.push_back(CreateMockWrite(initial_window_update, writes.size()));
5553 writes.push_back(CreateMockWrite(req, writes.size()));
[email protected]d11b6912013-06-27 23:07:325554
[email protected]251029e2014-03-19 06:04:405555 std::vector<MockRead> reads;
bnc42331402016-07-25 13:36:155556 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:415557 reads.push_back(CreateMockRead(resp, writes.size() + reads.size()));
[email protected]d11b6912013-06-27 23:07:325558
bncdf80d44fd2016-07-15 20:27:415559 std::vector<SpdySerializedFrame> body_frames;
bnc8f0f3b62015-04-08 04:37:235560 const std::string body_data(kChunkSize, 'x');
[email protected]251029e2014-03-19 06:04:405561 for (size_t remaining = kTargetSize; remaining != 0;) {
5562 size_t frame_size = std::min(remaining, body_data.size());
bncdf80d44fd2016-07-15 20:27:415563 body_frames.push_back(spdy_util_.ConstructSpdyDataFrame(1, body_data.data(),
5564 frame_size, false));
rchacdcbdc2015-05-16 17:16:005565 reads.push_back(
bncdf80d44fd2016-07-15 20:27:415566 CreateMockRead(body_frames.back(), writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:405567 remaining -= frame_size;
5568 }
mmenkee24011922015-12-17 22:12:595569 // Yield.
rchacdcbdc2015-05-16 17:16:005570 reads.push_back(
mmenkee24011922015-12-17 22:12:595571 MockRead(SYNCHRONOUS, ERR_IO_PENDING, writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:405572
rchacdcbdc2015-05-16 17:16:005573 writes.push_back(
bncdf80d44fd2016-07-15 20:27:415574 CreateMockWrite(session_window_update, writes.size() + reads.size()));
rchacdcbdc2015-05-16 17:16:005575 writes.push_back(
bncdf80d44fd2016-07-15 20:27:415576 CreateMockWrite(stream_window_update, writes.size() + reads.size()));
rchacdcbdc2015-05-16 17:16:005577
davidben5f8b6bc2015-11-25 03:19:545578 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
5579 writes.size());
[email protected]d11b6912013-06-27 23:07:325580
5581 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
bncd16676a2016-07-20 16:23:015582 BoundNetLog(), NULL);
[email protected]d11b6912013-06-27 23:07:325583 helper.AddData(&data);
5584 helper.RunPreTestSetup();
[email protected]d11b6912013-06-27 23:07:325585
bnc8f0f3b62015-04-08 04:37:235586 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5587 SpdySessionPoolPeer pool_peer(spdy_session_pool);
5588 pool_peer.SetEnableSendingInitialData(true);
5589 pool_peer.SetSessionMaxRecvWindowSize(session_max_recv_window_size);
5590 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
5591
5592 HttpNetworkTransaction* trans = helper.trans();
[email protected]d11b6912013-06-27 23:07:325593 TestCompletionCallback callback;
5594 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5595
robpercival214763f2016-07-01 23:27:015596 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325597 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015598 EXPECT_THAT(rv, IsOk());
[email protected]d11b6912013-06-27 23:07:325599
5600 SpdyHttpStream* stream =
5601 static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525602 ASSERT_TRUE(stream);
5603 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:325604
[email protected]251029e2014-03-19 06:04:405605 // All data has been read, but not consumed. The window reflects this.
bnc8f0f3b62015-04-08 04:37:235606 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size - kTargetSize),
[email protected]251029e2014-03-19 06:04:405607 stream->stream()->recv_window_size());
[email protected]d11b6912013-06-27 23:07:325608
5609 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525610 ASSERT_TRUE(response);
5611 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025612 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d11b6912013-06-27 23:07:325613 EXPECT_TRUE(response->was_fetched_via_spdy);
5614
5615 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5616 // size increased to default.
bnc301745a2015-03-10 03:22:165617 scoped_refptr<IOBuffer> buf(new IOBuffer(kTargetSize));
[email protected]251029e2014-03-19 06:04:405618 EXPECT_EQ(static_cast<int>(kTargetSize),
5619 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
bnc8f0f3b62015-04-08 04:37:235620 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size),
[email protected]251029e2014-03-19 06:04:405621 stream->stream()->recv_window_size());
5622 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
[email protected]d11b6912013-06-27 23:07:325623
[email protected]251029e2014-03-19 06:04:405624 // Allow scheduled WINDOW_UPDATE frames to write.
[email protected]fc9d88472013-08-14 02:31:175625 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325626 helper.VerifyDataConsumed();
5627}
5628
5629// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
bncd16676a2016-07-20 16:23:015630TEST_F(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]d11b6912013-06-27 23:07:325631 // Number of full frames we hope to write (but will not, used to
5632 // set content-length header correctly)
5633 static int kFrameCount = 3;
5634
danakjaee3e1ec2016-04-16 00:23:185635 std::unique_ptr<std::string> content(
[email protected]d11b6912013-06-27 23:07:325636 new std::string(kMaxSpdyFrameChunkSize, 'a'));
bncdf80d44fd2016-07-15 20:27:415637 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455638 kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
bncdf80d44fd2016-07-15 20:27:415639 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555640 1, content->c_str(), content->size(), false));
bncdf80d44fd2016-07-15 20:27:415641 SpdySerializedFrame rst(
[email protected]d11b6912013-06-27 23:07:325642 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
5643
5644 // We're not going to write a data frame with FIN, we'll receive a bad
5645 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
5646 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:415647 CreateMockWrite(req, 0), CreateMockWrite(body, 2),
5648 CreateMockWrite(rst, 3),
[email protected]d11b6912013-06-27 23:07:325649 };
5650
Avi Drissman13fc8932015-12-20 04:40:465651 static const int32_t kDeltaWindowSize = 0x7fffffff; // cause an overflow
bncdf80d44fd2016-07-15 20:27:415652 SpdySerializedFrame window_update(
[email protected]d11b6912013-06-27 23:07:325653 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5654 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:415655 CreateMockRead(window_update, 1), MockRead(ASYNC, 0, 4) // EOF
[email protected]d11b6912013-06-27 23:07:325656 };
5657
mmenke666a6fea2015-12-19 04:16:335658 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d11b6912013-06-27 23:07:325659
danakjaee3e1ec2016-04-16 00:23:185660 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:325661 for (int i = 0; i < kFrameCount; ++i) {
danakjaee3e1ec2016-04-16 00:23:185662 element_readers.push_back(base::WrapUnique(
olli.raula6df48b2a2015-11-26 07:40:225663 new UploadBytesElementReader(content->c_str(), content->size())));
[email protected]d11b6912013-06-27 23:07:325664 }
olli.raula6df48b2a2015-11-26 07:40:225665 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325666
5667 // Setup the request
5668 HttpRequestInfo request;
5669 request.method = "POST";
bncb26024382016-06-29 02:39:455670 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325671 request.upload_data_stream = &upload_data_stream;
5672
bncd16676a2016-07-20 16:23:015673 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
5674 NULL);
[email protected]d11b6912013-06-27 23:07:325675 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:335676 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:325677 HttpNetworkTransaction* trans = helper.trans();
5678
5679 TestCompletionCallback callback;
5680 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015681 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325682
mmenke666a6fea2015-12-19 04:16:335683 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325684 ASSERT_TRUE(callback.have_result());
robpercival214763f2016-07-01 23:27:015685 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_SPDY_PROTOCOL_ERROR));
[email protected]d11b6912013-06-27 23:07:325686 helper.VerifyDataConsumed();
5687}
5688
5689// Test that after hitting a send window size of 0, the write process
5690// stalls and upon receiving WINDOW_UPDATE frame write resumes.
5691
5692// This test constructs a POST request followed by enough data frames
5693// containing 'a' that would make the window size 0, followed by another
5694// data frame containing default content (which is "hello!") and this frame
rchacdcbdc2015-05-16 17:16:005695// also contains a FIN flag. SequencedSocketData is used to enforce all
5696// writes, save the last, go through before a read could happen. The last frame
5697// ("hello!") is not permitted to go through since by the time its turn
[email protected]d11b6912013-06-27 23:07:325698// arrives, window size is 0. At this point MessageLoop::Run() called via
5699// callback would block. Therefore we call MessageLoop::RunUntilIdle()
5700// which returns after performing all possible writes. We use DCHECKS to
5701// ensure that last data frame is still there and stream has stalled.
5702// After that, next read is artifically enforced, which causes a
5703// WINDOW_UPDATE to be read and I/O process resumes.
bncd16676a2016-07-20 16:23:015704TEST_F(SpdyNetworkTransactionTest, FlowControlStallResume) {
bncbca843ba2016-07-14 13:05:485705 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:455706 // Number of upload data buffers we need to send to zero out the window size
5707 // is the minimal number of upload buffers takes to be bigger than
5708 // |initial_window_size|.
5709 size_t num_upload_buffers =
5710 ceil(static_cast<double>(initial_window_size) / kBufferSize);
5711 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
5712 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
5713 // which has kBufferSize % kMaxSpdyChunkSize bytes.
5714 size_t num_frames_in_one_upload_buffer =
5715 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:325716
5717 // Construct content for a data frame of maximum size.
5718 std::string content(kMaxSpdyFrameChunkSize, 'a');
5719
bncdf80d44fd2016-07-15 20:27:415720 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455721 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:455722 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
5723 LOWEST, NULL, 0));
[email protected]d11b6912013-06-27 23:07:325724
5725 // Full frames.
bncdf80d44fd2016-07-15 20:27:415726 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555727 1, content.c_str(), content.size(), false));
[email protected]d11b6912013-06-27 23:07:325728
xunjieli179a6e72016-04-26 19:47:455729 // Last frame in each upload data buffer.
bncdf80d44fd2016-07-15 20:27:415730 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455731 1, content.c_str(), kBufferSize % kMaxSpdyFrameChunkSize, false));
[email protected]d11b6912013-06-27 23:07:325732
xunjieli179a6e72016-04-26 19:47:455733 // The very last frame before the stalled frames.
bncdf80d44fd2016-07-15 20:27:415734 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455735 1, content.c_str(),
5736 initial_window_size % kBufferSize % kMaxSpdyFrameChunkSize, false));
5737
5738 // Data frames to be sent once WINDOW_UPDATE frame is received.
5739
5740 // If kBufferSize * num_upload_buffers > initial_window_size,
5741 // we need one additional frame to send the rest of 'a'.
5742 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
5743 'a');
bncdf80d44fd2016-07-15 20:27:415744 SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455745 1, last_body.c_str(), last_body.size(), false));
5746
5747 // Also send a "hello!" after WINDOW_UPDATE.
bncdf80d44fd2016-07-15 20:27:415748 SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:325749
5750 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:325751 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:455752 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:415753 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:455754 for (size_t j = 0; j < num_upload_buffers; j++) {
5755 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
5756 if (k == num_frames_in_one_upload_buffer - 1 &&
5757 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
5758 if (j == num_upload_buffers - 1 &&
5759 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:415760 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:455761 } else {
bncdf80d44fd2016-07-15 20:27:415762 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:455763 }
5764 } else {
bncdf80d44fd2016-07-15 20:27:415765 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:455766 }
5767 }
5768 }
[email protected]d11b6912013-06-27 23:07:325769
xunjieli179a6e72016-04-26 19:47:455770 // Fill in mock reads.
5771 std::vector<MockRead> reads;
5772 // Force a pause.
5773 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
5774 // Construct read frame for window updates that gives enough space to upload
5775 // the rest of the data.
bncdf80d44fd2016-07-15 20:27:415776 SpdySerializedFrame session_window_update(
xunjieli179a6e72016-04-26 19:47:455777 spdy_util_.ConstructSpdyWindowUpdate(0,
5778 kUploadDataSize + last_body.size()));
bncdf80d44fd2016-07-15 20:27:415779 SpdySerializedFrame window_update(spdy_util_.ConstructSpdyWindowUpdate(
5780 1, kUploadDataSize + last_body.size()));
xunjieli179a6e72016-04-26 19:47:455781
bncdf80d44fd2016-07-15 20:27:415782 reads.push_back(CreateMockRead(session_window_update, i++));
5783 reads.push_back(CreateMockRead(window_update, i++));
xunjieli179a6e72016-04-26 19:47:455784
5785 // Stalled frames which can be sent after receiving window updates.
5786 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:415787 writes.push_back(CreateMockWrite(body4, i++));
5788 writes.push_back(CreateMockWrite(body5, i++));
xunjieli179a6e72016-04-26 19:47:455789
bnc42331402016-07-25 13:36:155790 SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(NULL, 0));
bncdf80d44fd2016-07-15 20:27:415791 reads.push_back(CreateMockRead(reply, i++));
5792 reads.push_back(CreateMockRead(body2, i++));
5793 reads.push_back(CreateMockRead(body5, i++));
xunjieli179a6e72016-04-26 19:47:455794 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
[email protected]d11b6912013-06-27 23:07:325795
xunjieli179a6e72016-04-26 19:47:455796 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
5797 writes.size());
[email protected]d11b6912013-06-27 23:07:325798
danakjaee3e1ec2016-04-16 00:23:185799 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
xunjieli179a6e72016-04-26 19:47:455800 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:325801 upload_data_string.append(kUploadData, kUploadDataSize);
danakjaee3e1ec2016-04-16 00:23:185802 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader(
olli.raula6df48b2a2015-11-26 07:40:225803 upload_data_string.c_str(), upload_data_string.size())));
5804 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325805
5806 HttpRequestInfo request;
5807 request.method = "POST";
bncb26024382016-06-29 02:39:455808 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325809 request.upload_data_stream = &upload_data_stream;
xunjieli179a6e72016-04-26 19:47:455810 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:015811 NULL);
[email protected]d11b6912013-06-27 23:07:325812 helper.AddData(&data);
5813 helper.RunPreTestSetup();
5814
5815 HttpNetworkTransaction* trans = helper.trans();
5816
5817 TestCompletionCallback callback;
5818 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015819 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325820
[email protected]fc9d88472013-08-14 02:31:175821 base::RunLoop().RunUntilIdle(); // Write as much as we can.
[email protected]d11b6912013-06-27 23:07:325822
5823 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525824 ASSERT_TRUE(stream);
5825 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:325826 EXPECT_EQ(0, stream->stream()->send_window_size());
xunjieli179a6e72016-04-26 19:47:455827 if (initial_window_size % kBufferSize != 0) {
5828 // If it does not take whole number of full upload buffer to zero out
5829 // initial window size, then the upload data is not at EOF, because the
5830 // last read must be stalled.
5831 EXPECT_FALSE(upload_data_stream.IsEOF());
5832 } else {
5833 // All the body data should have been read.
5834 // TODO(satorux): This is because of the weirdness in reading the request
5835 // body in OnSendBodyComplete(). See crbug.com/113107.
5836 EXPECT_TRUE(upload_data_stream.IsEOF());
5837 }
[email protected]d11b6912013-06-27 23:07:325838 // But the body is not yet fully sent (kUploadData is not yet sent)
5839 // since we're send-stalled.
5840 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
5841
mmenkee24011922015-12-17 22:12:595842 data.Resume(); // Read in WINDOW_UPDATE frame.
[email protected]d11b6912013-06-27 23:07:325843 rv = callback.WaitForResult();
5844 helper.VerifyDataConsumed();
5845}
5846
5847// Test we correctly handle the case where the SETTINGS frame results in
5848// unstalling the send window.
bncd16676a2016-07-20 16:23:015849TEST_F(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
bncbca843ba2016-07-14 13:05:485850 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:455851 // Number of upload data buffers we need to send to zero out the window size
5852 // is the minimal number of upload buffers takes to be bigger than
5853 // |initial_window_size|.
5854 size_t num_upload_buffers =
5855 ceil(static_cast<double>(initial_window_size) / kBufferSize);
5856 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
5857 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
5858 // which has kBufferSize % kMaxSpdyChunkSize bytes.
5859 size_t num_frames_in_one_upload_buffer =
5860 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:325861
5862 // Construct content for a data frame of maximum size.
5863 std::string content(kMaxSpdyFrameChunkSize, 'a');
5864
bncdf80d44fd2016-07-15 20:27:415865 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:455866 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:455867 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
5868 LOWEST, NULL, 0));
[email protected]d11b6912013-06-27 23:07:325869
5870 // Full frames.
bncdf80d44fd2016-07-15 20:27:415871 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:555872 1, content.c_str(), content.size(), false));
[email protected]d11b6912013-06-27 23:07:325873
xunjieli179a6e72016-04-26 19:47:455874 // Last frame in each upload data buffer.
bncdf80d44fd2016-07-15 20:27:415875 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455876 1, content.c_str(), kBufferSize % kMaxSpdyFrameChunkSize, false));
[email protected]d11b6912013-06-27 23:07:325877
xunjieli179a6e72016-04-26 19:47:455878 // The very last frame before the stalled frames.
bncdf80d44fd2016-07-15 20:27:415879 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455880 1, content.c_str(),
5881 initial_window_size % kBufferSize % kMaxSpdyFrameChunkSize, false));
5882
5883 // Data frames to be sent once WINDOW_UPDATE frame is received.
5884
5885 // If kBufferSize * num_upload_buffers > initial_window_size,
5886 // we need one additional frame to send the rest of 'a'.
5887 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
5888 'a');
bncdf80d44fd2016-07-15 20:27:415889 SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:455890 1, last_body.c_str(), last_body.size(), false));
5891
5892 // Also send a "hello!" after WINDOW_UPDATE.
bncdf80d44fd2016-07-15 20:27:415893 SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:325894
xunjieli179a6e72016-04-26 19:47:455895 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:325896 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:455897 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:415898 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:455899 for (size_t j = 0; j < num_upload_buffers; j++) {
5900 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
5901 if (k == num_frames_in_one_upload_buffer - 1 &&
5902 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
5903 if (j == num_upload_buffers - 1 &&
5904 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:415905 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:455906 } else {
bncdf80d44fd2016-07-15 20:27:415907 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:455908 }
5909 } else {
bncdf80d44fd2016-07-15 20:27:415910 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:455911 }
5912 }
5913 }
[email protected]d11b6912013-06-27 23:07:325914
xunjieli179a6e72016-04-26 19:47:455915 // Fill in mock reads.
5916 std::vector<MockRead> reads;
5917 // Force a pause.
mmenke666a6fea2015-12-19 04:16:335918 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
5919
[email protected]d11b6912013-06-27 23:07:325920 // Construct read frame for SETTINGS that gives enough space to upload the
5921 // rest of the data.
5922 SettingsMap settings;
5923 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:195924 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
bncdf80d44fd2016-07-15 20:27:415925 SpdySerializedFrame settings_frame_large(
[email protected]d11b6912013-06-27 23:07:325926 spdy_util_.ConstructSpdySettings(settings));
5927
bncdf80d44fd2016-07-15 20:27:415928 reads.push_back(CreateMockRead(settings_frame_large, i++));
[email protected]d11b6912013-06-27 23:07:325929
bncdf80d44fd2016-07-15 20:27:415930 SpdySerializedFrame session_window_update(
xunjieli179a6e72016-04-26 19:47:455931 spdy_util_.ConstructSpdyWindowUpdate(0,
5932 last_body.size() + kUploadDataSize));
bncdf80d44fd2016-07-15 20:27:415933 reads.push_back(CreateMockRead(session_window_update, i++));
[email protected]d11b6912013-06-27 23:07:325934
bncdf80d44fd2016-07-15 20:27:415935 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
5936 writes.push_back(CreateMockWrite(settings_ack, i++));
[email protected]d4a77c12014-05-15 20:45:215937
xunjieli179a6e72016-04-26 19:47:455938 // Stalled frames which can be sent after |settings_ack|.
5939 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:415940 writes.push_back(CreateMockWrite(body4, i++));
5941 writes.push_back(CreateMockWrite(body5, i++));
[email protected]d11b6912013-06-27 23:07:325942
bnc42331402016-07-25 13:36:155943 SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(NULL, 0));
bncdf80d44fd2016-07-15 20:27:415944 reads.push_back(CreateMockRead(reply, i++));
5945 reads.push_back(CreateMockRead(body2, i++));
5946 reads.push_back(CreateMockRead(body5, i++));
[email protected]d11b6912013-06-27 23:07:325947 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
5948
5949 // Force all writes to happen before any read, last write will not
5950 // actually queue a frame, due to window size being 0.
mmenke666a6fea2015-12-19 04:16:335951 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
5952 writes.size());
[email protected]d11b6912013-06-27 23:07:325953
danakjaee3e1ec2016-04-16 00:23:185954 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
xunjieli179a6e72016-04-26 19:47:455955 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:325956 upload_data_string.append(kUploadData, kUploadDataSize);
danakjaee3e1ec2016-04-16 00:23:185957 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader(
olli.raula6df48b2a2015-11-26 07:40:225958 upload_data_string.c_str(), upload_data_string.size())));
5959 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325960
5961 HttpRequestInfo request;
5962 request.method = "POST";
bncb26024382016-06-29 02:39:455963 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:325964 request.upload_data_stream = &upload_data_stream;
bncd16676a2016-07-20 16:23:015965 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
5966 NULL);
[email protected]d11b6912013-06-27 23:07:325967 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:335968 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:325969
5970 HttpNetworkTransaction* trans = helper.trans();
5971
5972 TestCompletionCallback callback;
5973 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015974 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:325975
mmenke666a6fea2015-12-19 04:16:335976 data.RunUntilPaused(); // Write as much as we can.
5977 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325978
5979 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:525980 ASSERT_TRUE(stream);
5981 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:325982 EXPECT_EQ(0, stream->stream()->send_window_size());
5983
xunjieli179a6e72016-04-26 19:47:455984 if (initial_window_size % kBufferSize != 0) {
5985 // If it does not take whole number of full upload buffer to zero out
5986 // initial window size, then the upload data is not at EOF, because the
5987 // last read must be stalled.
5988 EXPECT_FALSE(upload_data_stream.IsEOF());
5989 } else {
5990 // All the body data should have been read.
5991 // TODO(satorux): This is because of the weirdness in reading the request
5992 // body in OnSendBodyComplete(). See crbug.com/113107.
5993 EXPECT_TRUE(upload_data_stream.IsEOF());
5994 }
[email protected]d11b6912013-06-27 23:07:325995 // But the body is not yet fully sent (kUploadData is not yet sent)
5996 // since we're send-stalled.
5997 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
5998
mmenke666a6fea2015-12-19 04:16:335999 // Read in SETTINGS frame to unstall.
6000 data.Resume();
6001 base::RunLoop().RunUntilIdle();
6002
[email protected]d11b6912013-06-27 23:07:326003 rv = callback.WaitForResult();
6004 helper.VerifyDataConsumed();
6005 // If stream is NULL, that means it was unstalled and closed.
6006 EXPECT_TRUE(stream->stream() == NULL);
6007}
6008
6009// Test we correctly handle the case where the SETTINGS frame results in a
6010// negative send window size.
bncd16676a2016-07-20 16:23:016011TEST_F(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
bncbca843ba2016-07-14 13:05:486012 const int32_t initial_window_size = kDefaultInitialWindowSize;
xunjieli179a6e72016-04-26 19:47:456013 // Number of upload data buffers we need to send to zero out the window size
6014 // is the minimal number of upload buffers takes to be bigger than
6015 // |initial_window_size|.
6016 size_t num_upload_buffers =
6017 ceil(static_cast<double>(initial_window_size) / kBufferSize);
6018 // Each upload data buffer consists of |num_frames_in_one_upload_buffer|
6019 // frames, each with |kMaxSpdyFrameChunkSize| bytes except the last frame,
6020 // which has kBufferSize % kMaxSpdyChunkSize bytes.
6021 size_t num_frames_in_one_upload_buffer =
6022 ceil(static_cast<double>(kBufferSize) / kMaxSpdyFrameChunkSize);
[email protected]d11b6912013-06-27 23:07:326023
6024 // Construct content for a data frame of maximum size.
6025 std::string content(kMaxSpdyFrameChunkSize, 'a');
6026
bncdf80d44fd2016-07-15 20:27:416027 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
bncb26024382016-06-29 02:39:456028 kDefaultUrl, 1,
xunjieli179a6e72016-04-26 19:47:456029 /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize,
6030 LOWEST, NULL, 0));
[email protected]d11b6912013-06-27 23:07:326031
6032 // Full frames.
bncdf80d44fd2016-07-15 20:27:416033 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:556034 1, content.c_str(), content.size(), false));
[email protected]d11b6912013-06-27 23:07:326035
xunjieli179a6e72016-04-26 19:47:456036 // Last frame in each upload data buffer.
bncdf80d44fd2016-07-15 20:27:416037 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:456038 1, content.c_str(), kBufferSize % kMaxSpdyFrameChunkSize, false));
[email protected]d11b6912013-06-27 23:07:326039
xunjieli179a6e72016-04-26 19:47:456040 // The very last frame before the stalled frames.
bncdf80d44fd2016-07-15 20:27:416041 SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:456042 1, content.c_str(),
6043 initial_window_size % kBufferSize % kMaxSpdyFrameChunkSize, false));
6044
6045 // Data frames to be sent once WINDOW_UPDATE frame is received.
6046
6047 // If kBufferSize * num_upload_buffers > initial_window_size,
6048 // we need one additional frame to send the rest of 'a'.
6049 std::string last_body(kBufferSize * num_upload_buffers - initial_window_size,
6050 'a');
bncdf80d44fd2016-07-15 20:27:416051 SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(
xunjieli179a6e72016-04-26 19:47:456052 1, last_body.c_str(), last_body.size(), false));
6053
6054 // Also send a "hello!" after WINDOW_UPDATE.
bncdf80d44fd2016-07-15 20:27:416055 SpdySerializedFrame body5(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d11b6912013-06-27 23:07:326056
xunjieli179a6e72016-04-26 19:47:456057 // Fill in mock writes.
[email protected]d11b6912013-06-27 23:07:326058 size_t i = 0;
xunjieli179a6e72016-04-26 19:47:456059 std::vector<MockWrite> writes;
bncdf80d44fd2016-07-15 20:27:416060 writes.push_back(CreateMockWrite(req, i++));
xunjieli179a6e72016-04-26 19:47:456061 for (size_t j = 0; j < num_upload_buffers; j++) {
6062 for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
6063 if (k == num_frames_in_one_upload_buffer - 1 &&
6064 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
6065 if (j == num_upload_buffers - 1 &&
6066 (initial_window_size % kBufferSize != 0)) {
bncdf80d44fd2016-07-15 20:27:416067 writes.push_back(CreateMockWrite(body3, i++));
xunjieli179a6e72016-04-26 19:47:456068 } else {
bncdf80d44fd2016-07-15 20:27:416069 writes.push_back(CreateMockWrite(body2, i++));
xunjieli179a6e72016-04-26 19:47:456070 }
6071 } else {
bncdf80d44fd2016-07-15 20:27:416072 writes.push_back(CreateMockWrite(body1, i++));
xunjieli179a6e72016-04-26 19:47:456073 }
6074 }
6075 }
[email protected]d11b6912013-06-27 23:07:326076
xunjieli179a6e72016-04-26 19:47:456077 // Fill in mock reads.
6078 std::vector<MockRead> reads;
6079 // Force a pause.
mmenke666a6fea2015-12-19 04:16:336080 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
[email protected]d11b6912013-06-27 23:07:326081 // Construct read frame for SETTINGS that makes the send_window_size
6082 // negative.
6083 SettingsMap new_settings;
6084 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:196085 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
bncdf80d44fd2016-07-15 20:27:416086 SpdySerializedFrame settings_frame_small(
[email protected]d11b6912013-06-27 23:07:326087 spdy_util_.ConstructSpdySettings(new_settings));
6088 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6089 // positive.
bncdf80d44fd2016-07-15 20:27:416090 SpdySerializedFrame session_window_update_init_size(
bnc2f54c832014-12-01 13:31:196091 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
bncdf80d44fd2016-07-15 20:27:416092 SpdySerializedFrame window_update_init_size(
bnc2f54c832014-12-01 13:31:196093 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
[email protected]d11b6912013-06-27 23:07:326094
bncdf80d44fd2016-07-15 20:27:416095 reads.push_back(CreateMockRead(settings_frame_small, i++));
6096 reads.push_back(CreateMockRead(session_window_update_init_size, i++));
6097 reads.push_back(CreateMockRead(window_update_init_size, i++));
[email protected]d11b6912013-06-27 23:07:326098
bncdf80d44fd2016-07-15 20:27:416099 SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
6100 writes.push_back(CreateMockWrite(settings_ack, i++));
[email protected]d4a77c12014-05-15 20:45:216101
xunjieli179a6e72016-04-26 19:47:456102 // Stalled frames which can be sent after |settings_ack|.
6103 if (last_body.size() > 0)
bncdf80d44fd2016-07-15 20:27:416104 writes.push_back(CreateMockWrite(body4, i++));
6105 writes.push_back(CreateMockWrite(body5, i++));
[email protected]d11b6912013-06-27 23:07:326106
bnc42331402016-07-25 13:36:156107 SpdySerializedFrame reply(spdy_util_.ConstructSpdyPostReply(NULL, 0));
bncdf80d44fd2016-07-15 20:27:416108 reads.push_back(CreateMockRead(reply, i++));
6109 reads.push_back(CreateMockRead(body2, i++));
6110 reads.push_back(CreateMockRead(body5, i++));
[email protected]d11b6912013-06-27 23:07:326111 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6112
6113 // Force all writes to happen before any read, last write will not
6114 // actually queue a frame, due to window size being 0.
mmenke666a6fea2015-12-19 04:16:336115 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
6116 writes.size());
[email protected]d11b6912013-06-27 23:07:326117
danakjaee3e1ec2016-04-16 00:23:186118 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
xunjieli179a6e72016-04-26 19:47:456119 std::string upload_data_string(kBufferSize * num_upload_buffers, 'a');
[email protected]d11b6912013-06-27 23:07:326120 upload_data_string.append(kUploadData, kUploadDataSize);
danakjaee3e1ec2016-04-16 00:23:186121 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader(
olli.raula6df48b2a2015-11-26 07:40:226122 upload_data_string.c_str(), upload_data_string.size())));
6123 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326124
6125 HttpRequestInfo request;
6126 request.method = "POST";
bncb26024382016-06-29 02:39:456127 request.url = default_url_;
[email protected]d11b6912013-06-27 23:07:326128 request.upload_data_stream = &upload_data_stream;
bncd16676a2016-07-20 16:23:016129 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
6130 NULL);
[email protected]d11b6912013-06-27 23:07:326131 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:336132 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:326133
6134 HttpNetworkTransaction* trans = helper.trans();
6135
6136 TestCompletionCallback callback;
6137 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016138 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d11b6912013-06-27 23:07:326139
mmenke666a6fea2015-12-19 04:16:336140 data.RunUntilPaused(); // Write as much as we can.
6141 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326142
6143 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
wezca1070932016-05-26 20:30:526144 ASSERT_TRUE(stream);
6145 ASSERT_TRUE(stream->stream());
[email protected]d11b6912013-06-27 23:07:326146 EXPECT_EQ(0, stream->stream()->send_window_size());
6147
xunjieli179a6e72016-04-26 19:47:456148 if (initial_window_size % kBufferSize != 0) {
6149 // If it does not take whole number of full upload buffer to zero out
6150 // initial window size, then the upload data is not at EOF, because the
6151 // last read must be stalled.
6152 EXPECT_FALSE(upload_data_stream.IsEOF());
6153 } else {
6154 // All the body data should have been read.
6155 // TODO(satorux): This is because of the weirdness in reading the request
6156 // body in OnSendBodyComplete(). See crbug.com/113107.
6157 EXPECT_TRUE(upload_data_stream.IsEOF());
6158 }
[email protected]d11b6912013-06-27 23:07:326159
6160 // Read in WINDOW_UPDATE or SETTINGS frame.
mmenke666a6fea2015-12-19 04:16:336161 data.Resume();
6162 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326163 rv = callback.WaitForResult();
6164 helper.VerifyDataConsumed();
6165}
6166
bncd16676a2016-07-20 16:23:016167TEST_F(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
bnc086b39e12016-06-24 13:05:266168 SpdyHeaderBlock push_headers;
6169 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat", &push_headers);
bncdf80d44fd2016-07-15 20:27:416170 SpdySerializedFrame push(
dchengc7eeda422015-12-26 03:56:486171 spdy_util_.ConstructInitialSpdyPushFrame(std::move(push_headers), 3, 1));
bncdf80d44fd2016-07-15 20:27:416172 MockRead reads[] = {CreateMockRead(push, 1)};
baranovich212a1292014-09-02 21:45:316173
bncdf80d44fd2016-07-15 20:27:416174 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:496175 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:416176 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
baranovich212a1292014-09-02 21:45:316177 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6178 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416179 CreateMockWrite(req, 0), CreateMockWrite(goaway, 2),
baranovich212a1292014-09-02 21:45:316180 };
6181
rch08e3aa3e2015-05-16 14:27:526182 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:016183 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6184 BoundNetLog(), NULL);
baranovich212a1292014-09-02 21:45:316185 helper.RunToCompletion(&data);
6186 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:016187 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
baranovich212a1292014-09-02 21:45:316188}
6189
bncd16676a2016-07-20 16:23:016190TEST_F(SpdyNetworkTransactionTest,
baranovich212a1292014-09-02 21:45:316191 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
bncdf80d44fd2016-07-15 20:27:416192 SpdySerializedFrame push_a(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:006193 NULL, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
bnc086b39e12016-06-24 13:05:266194 SpdyHeaderBlock push_b_headers;
rchebf12982015-04-10 01:15:006195 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/b.dat"),
bnc086b39e12016-06-24 13:05:266196 &push_b_headers);
bncdf80d44fd2016-07-15 20:27:416197 SpdySerializedFrame push_b(spdy_util_.ConstructInitialSpdyPushFrame(
6198 std::move(push_b_headers), 2, 1));
baranovich212a1292014-09-02 21:45:316199 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416200 CreateMockRead(push_a, 1), CreateMockRead(push_b, 2),
baranovich212a1292014-09-02 21:45:316201 };
6202
bncdf80d44fd2016-07-15 20:27:416203 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:496204 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:416205 SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
bncb03b1092016-04-06 11:19:556206 4, GOAWAY_PROTOCOL_ERROR,
baranovich212a1292014-09-02 21:45:316207 "New push stream id must be greater than the last accepted."));
6208 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416209 CreateMockWrite(req, 0), CreateMockWrite(goaway, 3),
baranovich212a1292014-09-02 21:45:316210 };
6211
rch08e3aa3e2015-05-16 14:27:526212 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
bncd16676a2016-07-20 16:23:016213 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6214 BoundNetLog(), NULL);
baranovich212a1292014-09-02 21:45:316215 helper.RunToCompletion(&data);
6216 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:016217 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
baranovich212a1292014-09-02 21:45:316218}
6219
bnc76598ab2015-06-29 12:43:076220// Regression test for https://crbug.com/493348: request header exceeds 16 kB
6221// and thus sent in multiple frames when using HTTP/2.
bncd16676a2016-07-20 16:23:016222TEST_F(SpdyNetworkTransactionTest, LargeRequest) {
bnc76598ab2015-06-29 12:43:076223 const std::string kKey("foo");
6224 const std::string kValue(1 << 15, 'z');
6225
6226 HttpRequestInfo request;
6227 request.method = "GET";
bncb26024382016-06-29 02:39:456228 request.url = default_url_;
bnc76598ab2015-06-29 12:43:076229 request.extra_headers.SetHeader(kKey, kValue);
6230
bncb26024382016-06-29 02:39:456231 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bnc086b39e12016-06-24 13:05:266232 headers[kKey] = kValue;
bncdf80d44fd2016-07-15 20:27:416233 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:156234 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bnc76598ab2015-06-29 12:43:076235 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416236 CreateMockWrite(req, 0),
bnc76598ab2015-06-29 12:43:076237 };
6238
bnc42331402016-07-25 13:36:156239 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:416240 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc76598ab2015-06-29 12:43:076241 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416242 CreateMockRead(resp, 1), CreateMockRead(body, 2),
bnc76598ab2015-06-29 12:43:076243 MockRead(ASYNC, 0, 3) // EOF
6244 };
6245
6246 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6247 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:016248 nullptr);
bnc76598ab2015-06-29 12:43:076249 helper.RunToCompletion(&data);
6250 TransactionHelperResult out = helper.output();
6251
robpercival214763f2016-07-01 23:27:016252 EXPECT_THAT(out.rv, IsOk());
bnc84e7fb52015-12-02 11:50:026253 EXPECT_EQ("HTTP/1.1 200", out.status_line);
bnc76598ab2015-06-29 12:43:076254 EXPECT_EQ("hello!", out.response_data);
6255}
6256
bncd67383342016-01-08 21:58:436257// Regression test for https://crbug.com/535629: response header exceeds 16 kB.
bncd16676a2016-07-20 16:23:016258TEST_F(SpdyNetworkTransactionTest, LargeResponseHeader) {
bncb26024382016-06-29 02:39:456259 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
bncdf80d44fd2016-07-15 20:27:416260 SpdySerializedFrame req(
bnc42331402016-07-25 13:36:156261 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
bncd67383342016-01-08 21:58:436262 MockWrite writes[] = {
bncdf80d44fd2016-07-15 20:27:416263 CreateMockWrite(req, 0),
bncd67383342016-01-08 21:58:436264 };
6265
6266 // HPACK decoder implementation limits string literal length to 16 kB.
6267 const char* response_headers[2];
6268 const std::string kKey(16 * 1024, 'a');
6269 response_headers[0] = kKey.data();
6270 const std::string kValue(16 * 1024, 'b');
6271 response_headers[1] = kValue.data();
6272
bncdf80d44fd2016-07-15 20:27:416273 SpdySerializedFrame resp(
bnc42331402016-07-25 13:36:156274 spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1));
bncdf80d44fd2016-07-15 20:27:416275 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
bncd67383342016-01-08 21:58:436276 MockRead reads[] = {
bncdf80d44fd2016-07-15 20:27:416277 CreateMockRead(resp, 1), CreateMockRead(body, 2),
bncd67383342016-01-08 21:58:436278 MockRead(ASYNC, 0, 3) // EOF
6279 };
6280
6281 HttpRequestInfo request;
6282 request.method = "GET";
bncb26024382016-06-29 02:39:456283 request.url = default_url_;
bncd67383342016-01-08 21:58:436284 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
bncd16676a2016-07-20 16:23:016285 nullptr);
bncd67383342016-01-08 21:58:436286
6287 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6288 helper.RunToCompletion(&data);
6289 TransactionHelperResult out = helper.output();
6290
robpercival214763f2016-07-01 23:27:016291 EXPECT_THAT(out.rv, IsOk());
bncd67383342016-01-08 21:58:436292 EXPECT_EQ("HTTP/1.1 200", out.status_line);
6293 EXPECT_EQ("hello!", out.response_data);
6294 ASSERT_TRUE(out.response_info.headers->HasHeaderValue(kKey, kValue));
6295}
6296
bnc204a6d02016-08-01 14:34:276297// End of line delimiter is forbidden according to RFC 7230 Section 3.2.
6298TEST_F(SpdyNetworkTransactionTest, CRLFInHeaderValue) {
6299 SpdySerializedFrame req(
6300 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
6301 SpdySerializedFrame rst(
6302 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
6303 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 2)};
6304
6305 const char* response_headers[] = {"folded", "foo\r\nbar"};
6306 SpdySerializedFrame resp(
6307 spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1));
6308 MockRead reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3)};
6309
6310 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6311
6312 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6313 BoundNetLog(), nullptr);
6314 helper.RunToCompletion(&data);
6315 TransactionHelperResult out = helper.output();
6316
6317 EXPECT_THAT(out.rv, IsError(ERR_SPDY_PROTOCOL_ERROR));
6318}
6319
[email protected]514aeaf2014-05-23 10:31:516320class SpdyNetworkTransactionTLSUsageCheckTest
6321 : public SpdyNetworkTransactionTest {
6322 protected:
danakjaee3e1ec2016-04-16 00:23:186323 void RunTLSUsageCheckTest(
6324 std::unique_ptr<SSLSocketDataProvider> ssl_provider) {
bncdf80d44fd2016-07-15 20:27:416325 SpdySerializedFrame goaway(
[email protected]bdd1b222014-06-10 11:08:396326 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
bncdf80d44fd2016-07-15 20:27:416327 MockWrite writes[] = {CreateMockWrite(goaway)};
[email protected]514aeaf2014-05-23 10:31:516328
rch08e3aa3e2015-05-16 14:27:526329 StaticSocketDataProvider data(NULL, 0, writes, arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516330 HttpRequestInfo request;
6331 request.method = "GET";
bncb26024382016-06-29 02:39:456332 request.url = default_url_;
bncd16676a2016-07-20 16:23:016333 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
6334 NULL);
dchengc7eeda422015-12-26 03:56:486335 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516336 TransactionHelperResult out = helper.output();
robpercival214763f2016-07-01 23:27:016337 EXPECT_THAT(out.rv, IsError(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
[email protected]514aeaf2014-05-23 10:31:516338 }
6339};
6340
bncd16676a2016-07-20 16:23:016341TEST_F(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
danakjaee3e1ec2016-04-16 00:23:186342 std::unique_ptr<SSLSocketDataProvider> ssl_provider(
[email protected]514aeaf2014-05-23 10:31:516343 new SSLSocketDataProvider(ASYNC, OK));
6344 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6345 &ssl_provider->connection_status);
6346
dchengc7eeda422015-12-26 03:56:486347 RunTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516348}
6349
bncd16676a2016-07-20 16:23:016350TEST_F(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
danakjaee3e1ec2016-04-16 00:23:186351 std::unique_ptr<SSLSocketDataProvider> ssl_provider(
[email protected]514aeaf2014-05-23 10:31:516352 new SSLSocketDataProvider(ASYNC, OK));
6353 // Set to TLS_RSA_WITH_NULL_MD5
6354 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6355
dchengc7eeda422015-12-26 03:56:486356 RunTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516357}
6358
[email protected]aea80602009-09-18 00:55:086359} // namespace net