blob: 1c41254df860030bdbc8f1838d93e1e5e981630b [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
[email protected]d8ef27b2010-08-06 17:34:395#include <string>
dchengc7eeda422015-12-26 03:56:486#include <utility>
[email protected]a33cad2b62010-07-30 22:24:397#include <vector>
8
[email protected]49639fa2011-12-20 23:22:419#include "base/bind.h"
10#include "base/bind_helpers.h"
thestigd8df0332014-09-04 06:33:2911#include "base/files/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2312#include "base/files/scoped_temp_dir.h"
olli.raula6df48b2a2015-11-26 07:40:2213#include "base/memory/scoped_ptr.h"
[email protected]fc9d88472013-08-14 02:31:1714#include "base/run_loop.h"
[email protected]251029e2014-03-19 06:04:4015#include "base/strings/string_piece.h"
[email protected]999dd8c2013-11-12 06:45:5416#include "base/test/test_file_util.h"
skyostil4891b25b2015-06-11 11:43:4517#include "base/thread_task_runner_handle.h"
[email protected]018aabc2010-10-29 16:16:5918#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0719#include "net/base/chunked_upload_data_stream.h"
20#include "net/base/elements_upload_data_stream.h"
[email protected]262eec82013-03-19 21:01:3621#include "net/base/request_priority.h"
bncce36dca22015-04-21 22:11:2322#include "net/base/test_data_directory.h"
[email protected]b2d26cfd2012-12-11 10:36:0623#include "net/base/upload_bytes_element_reader.h"
[email protected]b2d26cfd2012-12-11 10:36:0624#include "net/base/upload_file_element_reader.h"
aberentbba302d2015-12-03 10:20:1925#include "net/http/http_auth_scheme.h"
[email protected]87bfa3f2010-09-30 14:54:5626#include "net/http/http_network_session_peer.h"
[email protected]513963e2013-06-15 01:53:0427#include "net/http/http_network_transaction.h"
28#include "net/http/http_server_properties.h"
[email protected]c41737d2014-05-14 07:47:1929#include "net/http/http_transaction_test_util.h"
mmenke16a7cbdd2015-04-24 23:00:5630#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4631#include "net/log/test_net_log_entry.h"
32#include "net/log/test_net_log_util.h"
[email protected]2d6728692011-03-12 01:39:5533#include "net/socket/client_socket_pool_base.h"
[email protected]bb88e1d32013-05-03 23:11:0734#include "net/socket/next_proto.h"
[email protected]f54c85792012-03-08 19:06:4135#include "net/spdy/buffered_spdy_framer.h"
[email protected]9be804c82010-06-24 17:59:4636#include "net/spdy/spdy_http_stream.h"
[email protected]9e1bdd32011-02-03 21:48:3437#include "net/spdy/spdy_http_utils.h"
[email protected]bdebd1b2010-08-09 20:18:0838#include "net/spdy/spdy_session.h"
[email protected]19ec8a72010-08-23 03:38:2339#include "net/spdy/spdy_session_pool.h"
[email protected]86aa87b2013-02-15 01:10:0340#include "net/spdy/spdy_test_util_common.h"
[email protected]a4bfdf72013-02-22 04:06:1641#include "net/spdy/spdy_test_utils.h"
[email protected]514aeaf2014-05-23 10:31:5142#include "net/ssl/ssl_connection_status_flags.h"
bncce36dca22015-04-21 22:11:2343#include "net/test/cert_test_util.h"
[email protected]d2db0292011-01-26 20:23:4444#include "net/url_request/url_request_test_util.h"
[email protected]251029e2014-03-19 06:04:4045#include "testing/gmock/include/gmock/gmock.h"
[email protected]aea80602009-09-18 00:55:0846#include "testing/platform_test.h"
47
48//-----------------------------------------------------------------------------
49
[email protected]d1eda932009-11-04 01:03:1050namespace net {
[email protected]dae22c52010-07-30 02:16:3551
[email protected]cbdd73162013-03-18 23:27:3352namespace {
[email protected]251029e2014-03-19 06:04:4053
54using testing::Each;
55using testing::Eq;
56
[email protected]513963e2013-06-15 01:53:0457enum SpdyNetworkTransactionTestSSLType {
rchebf12982015-04-10 01:15:0058 // Request an https:// URL and use NPN (or ALPN) to negotiate SPDY during
59 // the TLS handshake.
60 HTTPS_SPDY_VIA_NPN,
61 // Request and http:// URL to a server that supports SPDY via Alternative
62 // Service on port 443.
63 // See: https//tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html
64 HTTP_SPDY_VIA_ALT_SVC,
[email protected]9e9e842e2010-07-23 23:09:1565};
[email protected]ca6459f862012-04-11 19:43:2066
[email protected]513963e2013-06-15 01:53:0467struct SpdyNetworkTransactionTestParams {
68 SpdyNetworkTransactionTestParams()
rdsmithebb50aa2015-11-12 03:44:3869 : protocol(kProtoSPDY31),
70 ssl_type(HTTPS_SPDY_VIA_NPN),
71 priority_to_dependency(false) {}
[email protected]513963e2013-06-15 01:53:0472
rchebf12982015-04-10 01:15:0073 SpdyNetworkTransactionTestParams(NextProto protocol,
rdsmithebb50aa2015-11-12 03:44:3874 SpdyNetworkTransactionTestSSLType ssl_type,
75 bool priority_to_dependency)
76 : protocol(protocol),
77 ssl_type(ssl_type),
78 priority_to_dependency(priority_to_dependency) {}
rchebf12982015-04-10 01:15:0079
80 friend std::ostream& operator<<(std::ostream& os,
81 const SpdyNetworkTransactionTestParams& p) {
82 std::string type_str;
83 switch (p.ssl_type) {
84 case HTTP_SPDY_VIA_ALT_SVC:
85 type_str = "HTTP_SPDY_VIA_ALT_SVC";
86 break;
87 case HTTPS_SPDY_VIA_NPN:
88 type_str = "HTTPS_SPDY_VIA_NPN";
89 break;
90 }
91 os << "{ protocol: " << SSLClientSocket::NextProtoToString(p.protocol)
rdsmithebb50aa2015-11-12 03:44:3892 << ", ssl_type: " << type_str
93 << ", priority_to_dependency: " << p.priority_to_dependency << " }";
rchebf12982015-04-10 01:15:0094 return os;
95 }
[email protected]513963e2013-06-15 01:53:0496
97 NextProto protocol;
98 SpdyNetworkTransactionTestSSLType ssl_type;
rdsmithebb50aa2015-11-12 03:44:3899 bool priority_to_dependency;
[email protected]513963e2013-06-15 01:53:04100};
101
rchebf12982015-04-10 01:15:00102void UpdateSpdySessionDependencies(SpdyNetworkTransactionTestParams test_params,
103 SpdySessionDependencies* session_deps) {
bnc55ff9da2015-08-19 18:42:35104 session_deps->use_alternative_services = true;
rchebf12982015-04-10 01:15:00105 session_deps->next_protos = SpdyNextProtos();
106 if (test_params.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
bnc7dc7e1b42015-07-28 14:43:12107 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
rchebf12982015-04-10 01:15:00108 session_deps->http_server_properties.SetAlternativeService(
bncce36dca22015-04-21 22:11:23109 HostPortPair("www.example.org", 80),
rchebf12982015-04-10 01:15:00110 AlternativeService(AlternateProtocolFromNextProto(test_params.protocol),
bncce36dca22015-04-21 22:11:23111 "www.example.org", 443),
bnc7dc7e1b42015-07-28 14:43:12112 1.0, expiration);
[email protected]d7599122014-05-24 03:37:23113 }
114}
115
rdsmith82957ad2015-09-16 19:42:03116scoped_ptr<SpdySessionDependencies> CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:04117 SpdyNetworkTransactionTestParams test_params) {
rdsmith82957ad2015-09-16 19:42:03118 scoped_ptr<SpdySessionDependencies> session_deps(
119 new SpdySessionDependencies(test_params.protocol));
120 UpdateSpdySessionDependencies(test_params, session_deps.get());
[email protected]d7599122014-05-24 03:37:23121 return session_deps;
[email protected]513963e2013-06-15 01:53:04122}
123
rdsmith82957ad2015-09-16 19:42:03124scoped_ptr<SpdySessionDependencies> CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:04125 SpdyNetworkTransactionTestParams test_params,
rdsmith82957ad2015-09-16 19:42:03126 scoped_ptr<ProxyService> proxy_service) {
dchengc7eeda422015-12-26 03:56:48127 scoped_ptr<SpdySessionDependencies> session_deps(new SpdySessionDependencies(
128 test_params.protocol, std::move(proxy_service)));
rdsmith82957ad2015-09-16 19:42:03129 UpdateSpdySessionDependencies(test_params, session_deps.get());
[email protected]d7599122014-05-24 03:37:23130 return session_deps;
[email protected]bb88e1d32013-05-03 23:11:07131}
132
[email protected]513963e2013-06-15 01:53:04133} // namespace
134
135class SpdyNetworkTransactionTest
136 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
[email protected]34437af82009-11-06 02:28:49137 protected:
rdsmithebb50aa2015-11-12 03:44:38138 SpdyNetworkTransactionTest()
139 : spdy_util_(GetParam().protocol, GetParam().priority_to_dependency) {
140 SpdySession::SetPriorityDependencyDefaultForTesting(
141 GetParam().priority_to_dependency);
rchebf12982015-04-10 01:15:00142 spdy_util_.set_default_url(GURL(GetDefaultUrl()));
[email protected]9ec54f82013-05-10 02:53:05143 }
[email protected]2d6728692011-03-12 01:39:55144
[email protected]fc9d88472013-08-14 02:31:17145 virtual ~SpdyNetworkTransactionTest() {
mmenkecbc2b712014-10-09 20:29:07146 // UploadDataStream may post a deletion tasks back to the message loop on
[email protected]fc9d88472013-08-14 02:31:17147 // destruction.
148 upload_data_stream_.reset();
149 base::RunLoop().RunUntilIdle();
rdsmithebb50aa2015-11-12 03:44:38150 SpdySession::SetPriorityDependencyDefaultForTesting(false);
[email protected]fc9d88472013-08-14 02:31:17151 }
152
dcheng67be2b1f2014-10-27 21:47:29153 void SetUp() override {
bncce36dca22015-04-21 22:11:23154 get_request_initialized_ = false;
155 post_request_initialized_ = false;
156 chunked_post_request_initialized_ = false;
[email protected]69e6b4a2012-10-18 08:03:01157 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]aea80602009-09-18 00:55:08158 }
159
[email protected]72552f02009-10-28 15:25:01160 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:08161 int rv;
162 std::string status_line;
163 std::string response_data;
[email protected]8b070372009-11-16 22:01:25164 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:08165 };
166
[email protected]3caf5542010-07-16 15:19:47167 // A helper class that handles all the initial npn/ssl setup.
168 class NormalSpdyTransactionHelper {
169 public:
rdsmith82957ad2015-09-16 19:42:03170 NormalSpdyTransactionHelper(
171 const HttpRequestInfo& request,
172 RequestPriority priority,
173 const BoundNetLog& log,
174 SpdyNetworkTransactionTestParams test_params,
175 scoped_ptr<SpdySessionDependencies> session_deps)
[email protected]30c942b2010-07-21 16:59:59176 : request_(request),
[email protected]262eec82013-03-19 21:01:36177 priority_(priority),
rdsmith82957ad2015-09-16 19:42:03178 session_deps_(session_deps.get() == NULL
rchebf12982015-04-10 01:15:00179 ? CreateSpdySessionDependencies(test_params)
dchengc7eeda422015-12-26 03:56:48180 : std::move(session_deps)),
rchebf12982015-04-10 01:15:00181 session_(
182 SpdySessionDependencies::SpdyCreateSession(session_deps_.get())),
[email protected]9e9e842e2010-07-23 23:09:15183 log_(log),
[email protected]513963e2013-06-15 01:53:04184 test_params_(test_params),
rchebf12982015-04-10 01:15:00185 port_(443),
rchebf12982015-04-10 01:15:00186 spdy_enabled_(true) {}
[email protected]61b4efc2012-04-27 18:12:50187
[email protected]19ec8a72010-08-23 03:38:23188 ~NormalSpdyTransactionHelper() {
189 // Any test which doesn't close the socket by sending it an EOF will
190 // have a valid session left open, which leaks the entire session pool.
191 // This is just fine - in fact, some of our tests intentionally do this
192 // so that we can check consistency of the SpdySessionPool as the test
193 // finishes. If we had put an EOF on the socket, the SpdySession would
194 // have closed and we wouldn't be able to check the consistency.
195
196 // Forcefully close existing sessions here.
197 session()->spdy_session_pool()->CloseAllSessions();
198 }
199
[email protected]1f418ee2010-10-16 19:46:56200 void SetSpdyDisabled() {
201 spdy_enabled_ = false;
rchebf12982015-04-10 01:15:00202 port_ = test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC ? 80 : 443;
[email protected]1f418ee2010-10-16 19:46:56203 }
204
[email protected]3caf5542010-07-16 15:19:47205 void RunPreTestSetup() {
[email protected]b261d0e2010-08-02 19:13:24206 if (!session_deps_.get())
rdsmith82957ad2015-09-16 19:42:03207 session_deps_ = CreateSpdySessionDependencies(test_params_);
[email protected]d7599122014-05-24 03:37:23208 if (!session_.get()) {
[email protected]b261d0e2010-08-02 19:13:24209 session_ = SpdySessionDependencies::SpdyCreateSession(
210 session_deps_.get());
[email protected]3caf5542010-07-16 15:19:47211 }
[email protected]aea80602009-09-18 00:55:08212
[email protected]3caf5542010-07-16 15:19:47213 // We're now ready to use SSL-npn SPDY.
[email protected]90499482013-06-01 00:39:50214 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
[email protected]cb54b3b22010-06-03 16:28:55215 }
[email protected]aea80602009-09-18 00:55:08216
[email protected]3caf5542010-07-16 15:19:47217 // Start the transaction, read some data, finish.
218 void RunDefaultTest() {
[email protected]34b345f92013-02-22 03:27:26219 if (!StartDefaultTest())
220 return;
221 FinishDefaultTest();
222 }
223
224 bool StartDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51225 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
[email protected]aea80602009-09-18 00:55:08226
[email protected]3caf5542010-07-16 15:19:47227 // We expect an IO Pending or some sort of error.
228 EXPECT_LT(output_.rv, 0);
[email protected]34b345f92013-02-22 03:27:26229 return output_.rv == ERR_IO_PENDING;
230 }
[email protected]aea80602009-09-18 00:55:08231
[email protected]34b345f92013-02-22 03:27:26232 void FinishDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51233 output_.rv = callback_.WaitForResult();
[email protected]3caf5542010-07-16 15:19:47234 if (output_.rv != OK) {
bnc301745a2015-03-10 03:22:16235 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
[email protected]3caf5542010-07-16 15:19:47236 return;
237 }
[email protected]ff57bb82009-11-12 06:52:14238
[email protected]3caf5542010-07-16 15:19:47239 // Verify responses.
240 const HttpResponseInfo* response = trans_->GetResponseInfo();
241 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:50242 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]808957c2013-03-13 03:51:27243 if (HttpStreamFactory::spdy_enabled()) {
[email protected]88a332622013-07-30 07:13:32244 EXPECT_EQ(
245 HttpResponseInfo::ConnectionInfoFromNextProto(
246 test_params_.protocol),
247 response->connection_info);
[email protected]808957c2013-03-13 03:51:27248 } else {
249 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
250 response->connection_info);
251 }
rchebf12982015-04-10 01:15:00252 if (spdy_enabled_) {
bnc84e7fb52015-12-02 11:50:02253 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
254 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]9e9e842e2010-07-23 23:09:15255 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]a33cad2b62010-07-30 22:24:39256 } else {
bnc84e7fb52015-12-02 11:50:02257 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
258 EXPECT_FALSE(response->was_fetched_via_spdy);
rchebf12982015-04-10 01:15:00259 // If SPDY is disabled, an HTTP request should not be diverted
260 // over an SSL session.
[email protected]1f418ee2010-10-16 19:46:56261 EXPECT_EQ(request_.url.SchemeIs("https"),
262 response->was_npn_negotiated);
263 }
[email protected]80a09a82012-11-16 17:40:06264 EXPECT_EQ("127.0.0.1", response->socket_address.host());
265 EXPECT_EQ(port_, response->socket_address.port());
[email protected]3caf5542010-07-16 15:19:47266 output_.status_line = response->headers->GetStatusLine();
267 output_.response_info = *response; // Make a copy so we can verify.
268 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
[email protected]3caf5542010-07-16 15:19:47269 }
270
bncfacdd852015-01-09 19:22:54271 void FinishDefaultTestWithoutVerification() {
272 output_.rv = callback_.WaitForResult();
273 if (output_.rv != OK)
bnc301745a2015-03-10 03:22:16274 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
bncfacdd852015-01-09 19:22:54275 }
276
mmenke666a6fea2015-12-19 04:16:33277 void WaitForHeaders() { output_.rv = callback_.WaitForResult(); }
278
[email protected]3caf5542010-07-16 15:19:47279 // Most tests will want to call this function. In particular, the MockReads
280 // should end with an empty read, and that read needs to be processed to
281 // ensure proper deletion of the spdy_session_pool.
282 void VerifyDataConsumed() {
rch08e3aa3e2015-05-16 14:27:52283 for (const SocketDataProvider* provider : data_vector_) {
284 EXPECT_TRUE(provider->AllReadDataConsumed());
285 EXPECT_TRUE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47286 }
287 }
288
289 // Occasionally a test will expect to error out before certain reads are
290 // processed. In that case we want to explicitly ensure that the reads were
291 // not processed.
292 void VerifyDataNotConsumed() {
rch08e3aa3e2015-05-16 14:27:52293 for (const SocketDataProvider* provider : data_vector_) {
294 EXPECT_FALSE(provider->AllReadDataConsumed());
295 EXPECT_FALSE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47296 }
297 }
298
rch08e3aa3e2015-05-16 14:27:52299 void RunToCompletion(SocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47300 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58301 AddData(data);
[email protected]3caf5542010-07-16 15:19:47302 RunDefaultTest();
303 VerifyDataConsumed();
304 }
[email protected]e6b06862010-07-20 16:32:58305
[email protected]514aeaf2014-05-23 10:31:51306 void RunToCompletionWithSSLData(
rch08e3aa3e2015-05-16 14:27:52307 SocketDataProvider* data,
[email protected]514aeaf2014-05-23 10:31:51308 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
309 RunPreTestSetup();
dchengc7eeda422015-12-26 03:56:48310 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:51311 RunDefaultTest();
312 VerifyDataConsumed();
313 }
314
rch08e3aa3e2015-05-16 14:27:52315 void AddData(SocketDataProvider* data) {
[email protected]514aeaf2014-05-23 10:31:51316 scoped_ptr<SSLSocketDataProvider> ssl_provider(
317 new SSLSocketDataProvider(ASYNC, OK));
bncce36dca22015-04-21 22:11:23318 ssl_provider->cert =
319 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
dchengc7eeda422015-12-26 03:56:48320 AddDataWithSSLSocketDataProvider(data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:51321 }
322
323 void AddDataWithSSLSocketDataProvider(
rch08e3aa3e2015-05-16 14:27:52324 SocketDataProvider* data,
[email protected]514aeaf2014-05-23 10:31:51325 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]3caf5542010-07-16 15:19:47326 data_vector_.push_back(data);
rchebf12982015-04-10 01:15:00327 if (ssl_provider->next_proto_status ==
328 SSLClientSocket::kNextProtoUnsupported) {
[email protected]513963e2013-06-15 01:53:04329 ssl_provider->SetNextProto(test_params_.protocol);
[email protected]514aeaf2014-05-23 10:31:51330 }
rchebf12982015-04-10 01:15:00331
332 session_deps_->socket_factory->AddSSLSocketDataProvider(
333 ssl_provider.get());
olli.raulaae011c422015-12-10 07:38:51334 ssl_vector_.push_back(std::move(ssl_provider));
[email protected]d4f00222012-07-10 06:24:51335
[email protected]3b7828432010-08-18 18:33:27336 session_deps_->socket_factory->AddSocketDataProvider(data);
rchebf12982015-04-10 01:15:00337 if (test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
338 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
olli.raulaae011c422015-12-10 07:38:51339 scoped_ptr<StaticSocketDataProvider> hanging_non_alt_svc_socket(
340 make_scoped_ptr(new StaticSocketDataProvider(NULL, 0, NULL, 0)));
rchebf12982015-04-10 01:15:00341 hanging_non_alt_svc_socket->set_connect_data(hanging_connect);
[email protected]2d6728692011-03-12 01:39:55342 session_deps_->socket_factory->AddSocketDataProvider(
olli.raulaae011c422015-12-10 07:38:51343 hanging_non_alt_svc_socket.get());
344 alternate_vector_.push_back(std::move(hanging_non_alt_svc_socket));
[email protected]2d6728692011-03-12 01:39:55345 }
[email protected]3b7828432010-08-18 18:33:27346 }
347
mmenkee65e7af2015-10-13 17:16:42348 void SetSession(scoped_ptr<HttpNetworkSession> session) {
dchengc7eeda422015-12-26 03:56:48349 session_ = std::move(session);
[email protected]3caf5542010-07-16 15:19:47350 }
351 HttpNetworkTransaction* trans() { return trans_.get(); }
352 void ResetTrans() { trans_.reset(); }
353 TransactionHelperResult& output() { return output_; }
[email protected]19ec8a72010-08-23 03:38:23354 const HttpRequestInfo& request() const { return request_; }
mmenkee65e7af2015-10-13 17:16:42355 HttpNetworkSession* session() const { return session_.get(); }
[email protected]b261d0e2010-08-02 19:13:24356 scoped_ptr<SpdySessionDependencies>& session_deps() {
357 return session_deps_;
358 }
[email protected]19ec8a72010-08-23 03:38:23359 int port() const { return port_; }
[email protected]513963e2013-06-15 01:53:04360 SpdyNetworkTransactionTestParams test_params() const {
361 return test_params_;
[email protected]448d4ca52012-03-04 04:12:23362 }
[email protected]3caf5542010-07-16 15:19:47363
364 private:
rch08e3aa3e2015-05-16 14:27:52365 typedef std::vector<SocketDataProvider*> DataVector;
olli.raulaae011c422015-12-10 07:38:51366 typedef std::vector<scoped_ptr<SSLSocketDataProvider>> SSLVector;
367 typedef std::vector<scoped_ptr<SocketDataProvider>> AlternateVector;
[email protected]3caf5542010-07-16 15:19:47368 HttpRequestInfo request_;
[email protected]262eec82013-03-19 21:01:36369 RequestPriority priority_;
[email protected]b261d0e2010-08-02 19:13:24370 scoped_ptr<SpdySessionDependencies> session_deps_;
mmenkee65e7af2015-10-13 17:16:42371 scoped_ptr<HttpNetworkSession> session_;
[email protected]3caf5542010-07-16 15:19:47372 TransactionHelperResult output_;
rch08e3aa3e2015-05-16 14:27:52373 scoped_ptr<SocketDataProvider> first_transaction_;
[email protected]3caf5542010-07-16 15:19:47374 SSLVector ssl_vector_;
[email protected]514aeaf2014-05-23 10:31:51375 TestCompletionCallback callback_;
[email protected]3caf5542010-07-16 15:19:47376 scoped_ptr<HttpNetworkTransaction> trans_;
377 scoped_ptr<HttpNetworkTransaction> trans_http_;
378 DataVector data_vector_;
[email protected]2d6728692011-03-12 01:39:55379 AlternateVector alternate_vector_;
bnc29b1f072015-01-14 20:37:49380 const BoundNetLog log_;
[email protected]513963e2013-06-15 01:53:04381 SpdyNetworkTransactionTestParams test_params_;
[email protected]9e9e842e2010-07-23 23:09:15382 int port_;
[email protected]1f418ee2010-10-16 19:46:56383 bool spdy_enabled_;
[email protected]3caf5542010-07-16 15:19:47384 };
[email protected]aea80602009-09-18 00:55:08385
386 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
387 int expected_status);
388
389 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18390
[email protected]e3ebba0f2010-08-05 17:59:58391 const HttpRequestInfo& CreateGetPushRequest() {
bncce36dca22015-04-21 22:11:23392 get_push_request_.method = "GET";
393 get_push_request_.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
394 get_push_request_.load_flags = 0;
395 return get_push_request_;
[email protected]e3ebba0f2010-08-05 17:59:58396 }
397
[email protected]d3cee19d2010-06-22 18:42:18398 const HttpRequestInfo& CreateGetRequest() {
bncce36dca22015-04-21 22:11:23399 if (!get_request_initialized_) {
400 get_request_.method = "GET";
401 get_request_.url = GURL(GetDefaultUrl());
402 get_request_.load_flags = 0;
403 get_request_initialized_ = true;
[email protected]d3cee19d2010-06-22 18:42:18404 }
bncce36dca22015-04-21 22:11:23405 return get_request_;
[email protected]d3cee19d2010-06-22 18:42:18406 }
407
[email protected]3deb9a52010-11-11 00:24:40408 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
bncce36dca22015-04-21 22:11:23409 if (!get_request_initialized_) {
410 get_request_.method = "GET";
411 get_request_.url = GURL(GetDefaultUrl());
412 get_request_.load_flags = 0;
413 get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
414 get_request_initialized_ = true;
[email protected]3deb9a52010-11-11 00:24:40415 }
bncce36dca22015-04-21 22:11:23416 return get_request_;
[email protected]3deb9a52010-11-11 00:24:40417 }
418
[email protected]310240592010-08-05 21:04:19419 const HttpRequestInfo& CreatePostRequest() {
bncce36dca22015-04-21 22:11:23420 if (!post_request_initialized_) {
olli.raula6df48b2a2015-11-26 07:40:22421 std::vector<scoped_ptr<UploadElementReader>> element_readers;
422 element_readers.push_back(make_scoped_ptr(
423 new UploadBytesElementReader(kUploadData, kUploadDataSize)));
[email protected]96c77a72013-09-24 09:49:20424 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22425 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27426
bncce36dca22015-04-21 22:11:23427 post_request_.method = "POST";
428 post_request_.url = GURL(GetDefaultUrl());
429 post_request_.upload_data_stream = upload_data_stream_.get();
430 post_request_initialized_ = true;
[email protected]310240592010-08-05 21:04:19431 }
bncce36dca22015-04-21 22:11:23432 return post_request_;
[email protected]310240592010-08-05 21:04:19433 }
434
[email protected]69e6b4a2012-10-18 08:03:01435 const HttpRequestInfo& CreateFilePostRequest() {
bncce36dca22015-04-21 22:11:23436 if (!post_request_initialized_) {
[email protected]6cdfd7f2013-02-08 20:40:15437 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52438 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01439 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30440 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01441
olli.raula6df48b2a2015-11-26 07:40:22442 std::vector<scoped_ptr<UploadElementReader>> element_readers;
443 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
skyostil4891b25b2015-06-11 11:43:45444 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
olli.raula6df48b2a2015-11-26 07:40:22445 kUploadDataSize, base::Time())));
[email protected]96c77a72013-09-24 09:49:20446 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22447 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27448
bncce36dca22015-04-21 22:11:23449 post_request_.method = "POST";
450 post_request_.url = GURL(GetDefaultUrl());
451 post_request_.upload_data_stream = upload_data_stream_.get();
452 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01453 }
bncce36dca22015-04-21 22:11:23454 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01455 }
456
[email protected]999dd8c2013-11-12 06:45:54457 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
bncce36dca22015-04-21 22:11:23458 if (post_request_initialized_)
459 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54460
461 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52462 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]999dd8c2013-11-12 06:45:54463 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30464 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]92be8eb2014-08-07 22:57:11465 CHECK(base::MakeFileUnreadable(file_path));
[email protected]999dd8c2013-11-12 06:45:54466
olli.raula6df48b2a2015-11-26 07:40:22467 std::vector<scoped_ptr<UploadElementReader>> element_readers;
468 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
skyostil4891b25b2015-06-11 11:43:45469 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
olli.raula6df48b2a2015-11-26 07:40:22470 kUploadDataSize, base::Time())));
[email protected]999dd8c2013-11-12 06:45:54471 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22472 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]999dd8c2013-11-12 06:45:54473
bncce36dca22015-04-21 22:11:23474 post_request_.method = "POST";
475 post_request_.url = GURL(GetDefaultUrl());
476 post_request_.upload_data_stream = upload_data_stream_.get();
477 post_request_initialized_ = true;
478 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54479 }
480
[email protected]69e6b4a2012-10-18 08:03:01481 const HttpRequestInfo& CreateComplexPostRequest() {
bncce36dca22015-04-21 22:11:23482 if (!post_request_initialized_) {
[email protected]69e6b4a2012-10-18 08:03:01483 const int kFileRangeOffset = 1;
484 const int kFileRangeLength = 3;
485 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
486
[email protected]6cdfd7f2013-02-08 20:40:15487 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52488 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01489 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30490 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01491
olli.raula6df48b2a2015-11-26 07:40:22492 std::vector<scoped_ptr<UploadElementReader>> element_readers;
493 element_readers.push_back(make_scoped_ptr(
494 new UploadBytesElementReader(kUploadData, kFileRangeOffset)));
495 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
skyostil4891b25b2015-06-11 11:43:45496 base::ThreadTaskRunnerHandle::Get().get(), file_path,
olli.raula6df48b2a2015-11-26 07:40:22497 kFileRangeOffset, kFileRangeLength, base::Time())));
498 element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader(
[email protected]69e6b4a2012-10-18 08:03:01499 kUploadData + kFileRangeOffset + kFileRangeLength,
olli.raula6df48b2a2015-11-26 07:40:22500 kUploadDataSize - (kFileRangeOffset + kFileRangeLength))));
[email protected]96c77a72013-09-24 09:49:20501 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22502 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27503
bncce36dca22015-04-21 22:11:23504 post_request_.method = "POST";
505 post_request_.url = GURL(GetDefaultUrl());
506 post_request_.upload_data_stream = upload_data_stream_.get();
507 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01508 }
bncce36dca22015-04-21 22:11:23509 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01510 }
511
[email protected]0c9bf872011-03-04 17:53:22512 const HttpRequestInfo& CreateChunkedPostRequest() {
bncce36dca22015-04-21 22:11:23513 if (!chunked_post_request_initialized_) {
mmenkecbc2b712014-10-09 20:29:07514 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
bncce36dca22015-04-21 22:11:23515 chunked_post_request_.method = "POST";
516 chunked_post_request_.url = GURL(GetDefaultUrl());
517 chunked_post_request_.upload_data_stream =
mmenkecbc2b712014-10-09 20:29:07518 upload_chunked_data_stream_.get();
bncce36dca22015-04-21 22:11:23519 chunked_post_request_initialized_ = true;
[email protected]0c9bf872011-03-04 17:53:22520 }
bncce36dca22015-04-21 22:11:23521 return chunked_post_request_;
[email protected]0c9bf872011-03-04 17:53:22522 }
523
[email protected]19ec8a72010-08-23 03:38:23524 // Read the result of a particular transaction, knowing that we've got
525 // multiple transactions in the read pipeline; so as we read, we may have
526 // to skip over data destined for other transactions while we consume
527 // the data for |trans|.
528 int ReadResult(HttpNetworkTransaction* trans,
[email protected]19ec8a72010-08-23 03:38:23529 std::string* result) {
530 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58531
[email protected]19ec8a72010-08-23 03:38:23532 int bytes_read = 0;
bnc301745a2015-03-10 03:22:16533 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(kSize));
[email protected]49639fa2011-12-20 23:22:41534 TestCompletionCallback callback;
[email protected]19ec8a72010-08-23 03:38:23535 while (true) {
[email protected]90499482013-06-01 00:39:50536 int rv = trans->Read(buf.get(), kSize, callback.callback());
[email protected]19ec8a72010-08-23 03:38:23537 if (rv == ERR_IO_PENDING) {
[email protected]19ec8a72010-08-23 03:38:23538 rv = callback.WaitForResult();
539 } else if (rv <= 0) {
540 break;
541 }
542 result->append(buf->data(), rv);
543 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58544 }
[email protected]19ec8a72010-08-23 03:38:23545 return bytes_read;
546 }
[email protected]e3ebba0f2010-08-05 17:59:58547
[email protected]19ec8a72010-08-23 03:38:23548 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
549 // This lengthy block is reaching into the pool to dig out the active
550 // session. Once we have the session, we verify that the streams are
551 // all closed and not leaked at this point.
552 const GURL& url = helper.request().url;
rchebf12982015-04-10 01:15:00553 HostPortPair host_port_pair(url.host(), 443);
[email protected]e6d017652013-05-17 18:01:40554 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:53555 PRIVACY_MODE_DISABLED);
[email protected]19ec8a72010-08-23 03:38:23556 BoundNetLog log;
mmenkee65e7af2015-10-13 17:16:42557 HttpNetworkSession* session = helper.session();
[email protected]795cbf82013-07-22 09:37:27558 base::WeakPtr<SpdySession> spdy_session =
[email protected]04644d42013-07-08 04:29:59559 session->spdy_session_pool()->FindAvailableSession(key, log);
[email protected]41d64e82013-07-03 22:44:26560 ASSERT_TRUE(spdy_session != NULL);
[email protected]19ec8a72010-08-23 03:38:23561 EXPECT_EQ(0u, spdy_session->num_active_streams());
562 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
563 }
[email protected]e3ebba0f2010-08-05 17:59:58564
rch08e3aa3e2015-05-16 14:27:52565 void RunServerPushTest(SequencedSocketData* data,
[email protected]e3ebba0f2010-08-05 17:59:58566 HttpResponseInfo* response,
[email protected]a7a265ef2010-12-08 18:05:57567 HttpResponseInfo* push_response,
[email protected]8a0fc822013-06-27 20:52:43568 const std::string& expected) {
[email protected]262eec82013-03-19 21:01:36569 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50570 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:58571 helper.RunPreTestSetup();
[email protected]d08358502010-12-03 22:04:03572 helper.AddData(data);
[email protected]e3ebba0f2010-08-05 17:59:58573
574 HttpNetworkTransaction* trans = helper.trans();
575
576 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:41577 TestCompletionCallback callback;
578 int rv = trans->Start(
579 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:58580 EXPECT_EQ(ERR_IO_PENDING, rv);
581 rv = callback.WaitForResult();
582
583 // Request the pushed path.
[email protected]e3ebba0f2010-08-05 17:59:58584 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:42585 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]49639fa2011-12-20 23:22:41586 rv = trans2->Start(
587 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:58588 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:17589 base::RunLoop().RunUntilIdle();
[email protected]e3ebba0f2010-08-05 17:59:58590
[email protected]513963e2013-06-15 01:53:04591 // The data for the pushed path may be coming in more than 1 frame. Compile
[email protected]e3ebba0f2010-08-05 17:59:58592 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23593
594 // Read the server push body.
595 std::string result2;
rch0aecfd82015-05-19 17:22:32596 ReadResult(trans2.get(), &result2);
[email protected]19ec8a72010-08-23 03:38:23597 // Read the response body.
[email protected]e3ebba0f2010-08-05 17:59:58598 std::string result;
rch0aecfd82015-05-19 17:22:32599 ReadResult(trans, &result);
[email protected]e3ebba0f2010-08-05 17:59:58600
601 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:17602 EXPECT_TRUE(data->AllReadDataConsumed());
603 EXPECT_TRUE(data->AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:58604
605 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23606 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
607 << result2
608 << "||||| Expected data: "
609 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58610
611 // Verify the SYN_REPLY.
612 // Copy the response info, because trans goes away.
613 *response = *trans->GetResponseInfo();
[email protected]a7a265ef2010-12-08 18:05:57614 *push_response = *trans2->GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23615
616 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58617 }
618
[email protected]49639fa2011-12-20 23:22:41619 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
620 int result) {
621 helper->ResetTrans();
622 }
623
mmenkee65e7af2015-10-13 17:16:42624 static void StartTransactionCallback(HttpNetworkSession* session,
625 GURL url,
626 int result) {
[email protected]49639fa2011-12-20 23:22:41627 scoped_ptr<HttpNetworkTransaction> trans(
mmenkee65e7af2015-10-13 17:16:42628 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
[email protected]49639fa2011-12-20 23:22:41629 TestCompletionCallback callback;
630 HttpRequestInfo request;
631 request.method = "GET";
rchebf12982015-04-10 01:15:00632 request.url = url;
[email protected]49639fa2011-12-20 23:22:41633 request.load_flags = 0;
634 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
635 EXPECT_EQ(ERR_IO_PENDING, rv);
636 callback.WaitForResult();
637 }
638
mmenkecbc2b712014-10-09 20:29:07639 ChunkedUploadDataStream* upload_chunked_data_stream() const {
640 return upload_chunked_data_stream_.get();
641 }
642
rchebf12982015-04-10 01:15:00643 const char* GetDefaultUrl() {
644 switch (GetParam().ssl_type) {
645 case HTTP_SPDY_VIA_ALT_SVC:
bncce36dca22015-04-21 22:11:23646 return "http://www.example.org";
rchebf12982015-04-10 01:15:00647 case HTTPS_SPDY_VIA_NPN:
bncce36dca22015-04-21 22:11:23648 return "https://www.example.org";
rchebf12982015-04-10 01:15:00649 default:
650 NOTREACHED();
651 return "";
652 }
653 }
654
655 std::string GetDefaultUrlWithPath(const char* path) {
656 return std::string(GetDefaultUrl()) + path;
657 }
658
[email protected]9ec54f82013-05-10 02:53:05659 SpdyTestUtil spdy_util_;
660
[email protected]d3cee19d2010-06-22 18:42:18661 private:
mmenkecbc2b712014-10-09 20:29:07662 scoped_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
[email protected]329b68b2012-11-14 17:54:27663 scoped_ptr<UploadDataStream> upload_data_stream_;
bncce36dca22015-04-21 22:11:23664 bool get_request_initialized_;
665 bool post_request_initialized_;
666 bool chunked_post_request_initialized_;
667 HttpRequestInfo get_request_;
668 HttpRequestInfo post_request_;
669 HttpRequestInfo chunked_post_request_;
670 HttpRequestInfo get_push_request_;
[email protected]ea1a3f62012-11-16 20:34:23671 base::ScopedTempDir temp_dir_;
[email protected]aea80602009-09-18 00:55:08672};
673
674//-----------------------------------------------------------------------------
[email protected]9e9e842e2010-07-23 23:09:15675// All tests are run with three different connection types: SPDY after NPN
676// negotiation, SPDY without SSL, and SPDY with SSL.
[email protected]513963e2013-06-15 01:53:04677//
678// TODO(akalin): Use ::testing::Combine() when we are able to use
679// <tr1/tuple>.
680INSTANTIATE_TEST_CASE_P(
681 Spdy,
682 SpdyNetworkTransactionTest,
683 ::testing::Values(
rdsmithebb50aa2015-11-12 03:44:38684 SpdyNetworkTransactionTestParams(kProtoSPDY31,
685 HTTPS_SPDY_VIA_NPN,
686 false),
687 SpdyNetworkTransactionTestParams(kProtoSPDY31,
688 HTTP_SPDY_VIA_ALT_SVC,
689 false),
690 SpdyNetworkTransactionTestParams(kProtoHTTP2,
691 HTTPS_SPDY_VIA_NPN,
692 false),
693 SpdyNetworkTransactionTestParams(kProtoHTTP2, HTTPS_SPDY_VIA_NPN, true),
694 SpdyNetworkTransactionTestParams(kProtoHTTP2,
695 HTTP_SPDY_VIA_ALT_SVC,
696 false),
697 SpdyNetworkTransactionTestParams(kProtoHTTP2,
698 HTTP_SPDY_VIA_ALT_SVC,
699 true)));
[email protected]aea80602009-09-18 00:55:08700
[email protected]3caf5542010-07-16 15:19:47701// Verify HttpNetworkTransaction constructor.
[email protected]513963e2013-06-15 01:53:04702TEST_P(SpdyNetworkTransactionTest, Constructor) {
[email protected]bb88e1d32013-05-03 23:11:07703 scoped_ptr<SpdySessionDependencies> session_deps(
[email protected]513963e2013-06-15 01:53:04704 CreateSpdySessionDependencies(GetParam()));
mmenkee65e7af2015-10-13 17:16:42705 scoped_ptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:07706 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
[email protected]262eec82013-03-19 21:01:36707 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:50708 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]aea80602009-09-18 00:55:08709}
710
[email protected]513963e2013-06-15 01:53:04711TEST_P(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38712 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:46713 scoped_ptr<SpdyFrame> req(
714 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:52715 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]72552f02009-10-28 15:25:01716
[email protected]513963e2013-06-15 01:53:04717 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
718 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]72552f02009-10-28 15:25:01719 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52720 CreateMockRead(*resp, 1),
721 CreateMockRead(*body, 2),
722 MockRead(ASYNC, 0, 3) // EOF
[email protected]72552f02009-10-28 15:25:01723 };
724
rch08e3aa3e2015-05-16 14:27:52725 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:36726 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50727 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:57728 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:47729 TransactionHelperResult out = helper.output();
[email protected]72552f02009-10-28 15:25:01730 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:02731 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]72552f02009-10-28 15:25:01732 EXPECT_EQ("hello!", out.response_data);
733}
734
[email protected]513963e2013-06-15 01:53:04735TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
[email protected]3d08dd382013-10-19 00:13:11736 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
[email protected]31ae7ab2012-04-24 21:09:05737 p = RequestPriority(p + 1)) {
[email protected]c9c6f5c2010-07-31 01:30:03738 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:46739 scoped_ptr<SpdyFrame> req(
740 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
rdsmithebb50aa2015-11-12 03:44:38741 spdy_util_.UpdateWithStreamDestruction(1);
rch08e3aa3e2015-05-16 14:27:52742 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]c9c6f5c2010-07-31 01:30:03743
[email protected]86aa87b2013-02-15 01:10:03744 SpdyPriority spdy_prio = 0;
[email protected]513963e2013-06-15 01:53:04745 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
[email protected]c9c6f5c2010-07-31 01:30:03746 // this repeats the RequestPriority-->SpdyPriority mapping from
747 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
748 // sure it's being done right.
[email protected]513963e2013-06-15 01:53:04749 if (spdy_util_.spdy_version() < SPDY3) {
mmenkecbc2b712014-10-09 20:29:07750 switch (p) {
[email protected]513963e2013-06-15 01:53:04751 case HIGHEST:
752 EXPECT_EQ(0, spdy_prio);
753 break;
754 case MEDIUM:
755 EXPECT_EQ(1, spdy_prio);
756 break;
757 case LOW:
758 case LOWEST:
759 EXPECT_EQ(2, spdy_prio);
760 break;
761 case IDLE:
762 EXPECT_EQ(3, spdy_prio);
763 break;
764 default:
765 FAIL();
766 }
767 } else {
bnce8aa2702015-08-17 18:11:05768 switch (p) {
[email protected]513963e2013-06-15 01:53:04769 case HIGHEST:
770 EXPECT_EQ(0, spdy_prio);
771 break;
772 case MEDIUM:
773 EXPECT_EQ(1, spdy_prio);
774 break;
775 case LOW:
776 EXPECT_EQ(2, spdy_prio);
777 break;
778 case LOWEST:
779 EXPECT_EQ(3, spdy_prio);
780 break;
781 case IDLE:
782 EXPECT_EQ(4, spdy_prio);
783 break;
784 default:
785 FAIL();
786 }
[email protected]c9c6f5c2010-07-31 01:30:03787 }
788
[email protected]513963e2013-06-15 01:53:04789 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
790 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c9c6f5c2010-07-31 01:30:03791 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52792 CreateMockRead(*resp, 1),
793 CreateMockRead(*body, 2),
794 MockRead(ASYNC, 0, 3) // EOF
[email protected]c9c6f5c2010-07-31 01:30:03795 };
796
rch08e3aa3e2015-05-16 14:27:52797 SequencedSocketData data(reads, arraysize(reads), writes,
798 arraysize(writes));
[email protected]c9c6f5c2010-07-31 01:30:03799 HttpRequestInfo http_req = CreateGetRequest();
[email protected]c9c6f5c2010-07-31 01:30:03800
[email protected]262eec82013-03-19 21:01:36801 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
[email protected]61b4efc2012-04-27 18:12:50802 GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:57803 helper.RunToCompletion(&data);
[email protected]c9c6f5c2010-07-31 01:30:03804 TransactionHelperResult out = helper.output();
805 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:02806 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]c9c6f5c2010-07-31 01:30:03807 EXPECT_EQ("hello!", out.response_data);
808 }
809}
810
[email protected]2bd93022010-07-17 00:58:44811// Start three gets simultaniously; making sure that multiplexed
812// streams work properly.
813
814// This can't use the TransactionHelper method, since it only
815// handles a single transaction, and finishes them as soon
816// as it launches them.
817
818// TODO(gavinp): create a working generalized TransactionHelper that
819// can allow multiple streams in flight.
820
[email protected]513963e2013-06-15 01:53:04821TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
[email protected]cdf8f7e72013-05-23 10:56:46822 scoped_ptr<SpdyFrame> req(
823 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04824 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
825 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
826 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:44827
[email protected]cdf8f7e72013-05-23 10:56:46828 scoped_ptr<SpdyFrame> req2(
829 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04830 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
831 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
832 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:44833
[email protected]cdf8f7e72013-05-23 10:56:46834 scoped_ptr<SpdyFrame> req3(
835 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04836 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
837 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
838 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44839
[email protected]1b323172011-03-01 17:50:17840 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:52841 CreateMockWrite(*req, 0),
842 CreateMockWrite(*req2, 3),
843 CreateMockWrite(*req3, 6),
[email protected]2bd93022010-07-17 00:58:44844 };
845 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52846 CreateMockRead(*resp, 1),
847 CreateMockRead(*body, 2),
848 CreateMockRead(*resp2, 4),
849 CreateMockRead(*body2, 5),
850 CreateMockRead(*resp3, 7),
851 CreateMockRead(*body3, 8),
[email protected]2bd93022010-07-17 00:58:44852
rch08e3aa3e2015-05-16 14:27:52853 CreateMockRead(*fbody, 9),
854 CreateMockRead(*fbody2, 10),
855 CreateMockRead(*fbody3, 11),
[email protected]2bd93022010-07-17 00:58:44856
rch08e3aa3e2015-05-16 14:27:52857 MockRead(ASYNC, 0, 12), // EOF
[email protected]2bd93022010-07-17 00:58:44858 };
rch08e3aa3e2015-05-16 14:27:52859 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
mmenkecc2298e2015-12-07 18:20:18860 SequencedSocketData data_placeholder1(NULL, 0, NULL, 0);
861 SequencedSocketData data_placeholder2(NULL, 0, NULL, 0);
[email protected]2bd93022010-07-17 00:58:44862
863 BoundNetLog log;
864 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36865 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50866 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:08867 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57868 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49869 // We require placeholder data because three get requests are sent out at
870 // the same time which results in three sockets being connected. The first
871 // on will negotiate SPDY and will be used for all requests.
mmenkecc2298e2015-12-07 18:20:18872 helper.AddData(&data_placeholder1);
873 helper.AddData(&data_placeholder2);
[email protected]bdebd1b2010-08-09 20:18:08874 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:42875 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:08876 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:42877 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:08878 scoped_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:42879 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]2bd93022010-07-17 00:58:44880
[email protected]49639fa2011-12-20 23:22:41881 TestCompletionCallback callback1;
882 TestCompletionCallback callback2;
883 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44884
[email protected]bdebd1b2010-08-09 20:18:08885 HttpRequestInfo httpreq1 = CreateGetRequest();
886 HttpRequestInfo httpreq2 = CreateGetRequest();
887 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:44888
[email protected]49639fa2011-12-20 23:22:41889 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08890 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41891 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08892 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41893 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08894 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:44895
[email protected]bdebd1b2010-08-09 20:18:08896 out.rv = callback1.WaitForResult();
897 ASSERT_EQ(OK, out.rv);
898 out.rv = callback3.WaitForResult();
899 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44900
[email protected]bdebd1b2010-08-09 20:18:08901 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:50902 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:08903 EXPECT_TRUE(response1->was_fetched_via_spdy);
904 out.status_line = response1->headers->GetStatusLine();
905 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:44906
[email protected]bdebd1b2010-08-09 20:18:08907 trans2->GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:44908
[email protected]bdebd1b2010-08-09 20:18:08909 out.rv = ReadTransaction(trans1.get(), &out.response_data);
910 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:44911 EXPECT_EQ(OK, out.rv);
912
[email protected]2bd93022010-07-17 00:58:44913 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:02914 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:44915 EXPECT_EQ("hello!hello!", out.response_data);
916}
917
[email protected]513963e2013-06-15 01:53:04918TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
[email protected]cdf8f7e72013-05-23 10:56:46919 scoped_ptr<SpdyFrame> req(
920 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04921 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
922 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
923 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1b323172011-03-01 17:50:17924
[email protected]cdf8f7e72013-05-23 10:56:46925 scoped_ptr<SpdyFrame> req2(
926 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04927 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
928 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
929 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]1b323172011-03-01 17:50:17930
931 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:52932 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 3),
[email protected]1b323172011-03-01 17:50:17933 };
934 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52935 CreateMockRead(*resp, 1),
936 CreateMockRead(*body, 2),
937 CreateMockRead(*resp2, 4),
938 CreateMockRead(*body2, 5),
939 CreateMockRead(*fbody, 6),
940 CreateMockRead(*fbody2, 7),
941 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:17942 };
rch08e3aa3e2015-05-16 14:27:52943 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1b323172011-03-01 17:50:17944
[email protected]d973e99a2012-02-17 21:02:36945 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
rch08e3aa3e2015-05-16 14:27:52946 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:57947 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17948
949 BoundNetLog log;
950 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36951 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50952 BoundNetLog(), GetParam(), NULL);
[email protected]1b323172011-03-01 17:50:17953 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57954 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49955 // We require placeholder data because two requests are sent out at
956 // the same time which results in two sockets being connected. The first
957 // on will negotiate SPDY and will be used for all requests.
[email protected]dd54bd82012-07-19 23:44:57958 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:17959 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:42960 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]1b323172011-03-01 17:50:17961 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:42962 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]1b323172011-03-01 17:50:17963
[email protected]49639fa2011-12-20 23:22:41964 TestCompletionCallback callback1;
965 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:17966
967 HttpRequestInfo httpreq1 = CreateGetRequest();
968 HttpRequestInfo httpreq2 = CreateGetRequest();
969
[email protected]49639fa2011-12-20 23:22:41970 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]1b323172011-03-01 17:50:17971 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41972 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]1b323172011-03-01 17:50:17973 ASSERT_EQ(ERR_IO_PENDING, out.rv);
974
975 out.rv = callback1.WaitForResult();
976 ASSERT_EQ(OK, out.rv);
977 out.rv = callback2.WaitForResult();
978 ASSERT_EQ(OK, out.rv);
979
980 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:50981 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:17982 EXPECT_TRUE(response1->was_fetched_via_spdy);
983 out.status_line = response1->headers->GetStatusLine();
984 out.response_info = *response1;
985 out.rv = ReadTransaction(trans1.get(), &out.response_data);
986 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:02987 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17988 EXPECT_EQ("hello!hello!", out.response_data);
989
990 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
[email protected]90499482013-06-01 00:39:50991 EXPECT_TRUE(response2->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:17992 EXPECT_TRUE(response2->was_fetched_via_spdy);
993 out.status_line = response2->headers->GetStatusLine();
994 out.response_info = *response2;
995 out.rv = ReadTransaction(trans2.get(), &out.response_data);
996 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:02997 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:17998 EXPECT_EQ("hello!hello!", out.response_data);
999
1000 helper.VerifyDataConsumed();
1001}
1002
[email protected]513963e2013-06-15 01:53:041003TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
[email protected]cdf8f7e72013-05-23 10:56:461004 scoped_ptr<SpdyFrame> req(
1005 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041006 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1007 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1008 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1b323172011-03-01 17:50:171009
[email protected]cdf8f7e72013-05-23 10:56:461010 scoped_ptr<SpdyFrame> req2(
1011 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041012 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1013 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1014 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]1b323172011-03-01 17:50:171015
1016 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521017 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 3),
[email protected]1b323172011-03-01 17:50:171018 };
1019 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521020 CreateMockRead(*resp, 1),
1021 CreateMockRead(*body, 2),
1022 CreateMockRead(*resp2, 4),
1023 CreateMockRead(*body2, 5),
1024 CreateMockRead(*fbody, 6),
1025 CreateMockRead(*fbody2, 7),
1026 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:171027 };
rch08e3aa3e2015-05-16 14:27:521028 SequencedSocketData preconnect_data(reads, arraysize(reads), writes,
1029 arraysize(writes));
[email protected]1b323172011-03-01 17:50:171030
[email protected]d973e99a2012-02-17 21:02:361031 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
[email protected]1b323172011-03-01 17:50:171032
rch08e3aa3e2015-05-16 14:27:521033 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:571034 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:171035
1036 BoundNetLog log;
1037 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361038 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501039 BoundNetLog(), GetParam(), NULL);
[email protected]1b323172011-03-01 17:50:171040 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571041 helper.AddData(&preconnect_data);
[email protected]1b323172011-03-01 17:50:171042 // We require placeholder data because 3 connections are attempted (first is
1043 // the preconnect, 2nd and 3rd are the never finished connections.
[email protected]dd54bd82012-07-19 23:44:571044 helper.AddData(&data_placeholder);
1045 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:171046
1047 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421048 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]1b323172011-03-01 17:50:171049 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421050 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]1b323172011-03-01 17:50:171051
[email protected]49639fa2011-12-20 23:22:411052 TestCompletionCallback callback1;
1053 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:171054
1055 HttpRequestInfo httpreq = CreateGetRequest();
1056
1057 // Preconnect the first.
1058 SSLConfig preconnect_ssl_config;
1059 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1060 HttpStreamFactory* http_stream_factory =
1061 helper.session()->http_stream_factory();
bnc1f295372015-10-21 23:24:221062 helper.session()->GetAlpnProtos(&preconnect_ssl_config.alpn_protos);
1063 helper.session()->GetNpnProtos(&preconnect_ssl_config.npn_protos);
[email protected]1b323172011-03-01 17:50:171064
mmenked1205bd3972015-07-15 22:26:351065 http_stream_factory->PreconnectStreams(1, httpreq, preconnect_ssl_config,
1066 preconnect_ssl_config);
[email protected]1b323172011-03-01 17:50:171067
[email protected]49639fa2011-12-20 23:22:411068 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
[email protected]1b323172011-03-01 17:50:171069 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411070 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
[email protected]1b323172011-03-01 17:50:171071 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1072
1073 out.rv = callback1.WaitForResult();
1074 ASSERT_EQ(OK, out.rv);
1075 out.rv = callback2.WaitForResult();
1076 ASSERT_EQ(OK, out.rv);
1077
1078 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501079 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171080 EXPECT_TRUE(response1->was_fetched_via_spdy);
1081 out.status_line = response1->headers->GetStatusLine();
1082 out.response_info = *response1;
1083 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1084 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021085 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:171086 EXPECT_EQ("hello!hello!", out.response_data);
1087
1088 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501089 EXPECT_TRUE(response2->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171090 EXPECT_TRUE(response2->was_fetched_via_spdy);
1091 out.status_line = response2->headers->GetStatusLine();
1092 out.response_info = *response2;
1093 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1094 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021095 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:171096 EXPECT_EQ("hello!hello!", out.response_data);
1097
1098 helper.VerifyDataConsumed();
1099}
1100
[email protected]2bd93022010-07-17 00:58:441101// Similar to ThreeGets above, however this test adds a SETTINGS
1102// frame. The SETTINGS frame is read during the IO loop waiting on
1103// the first transaction completion, and sets a maximum concurrent
1104// stream limit of 1. This means that our IO loop exists after the
1105// second transaction completes, so we can assert on read_index().
[email protected]513963e2013-06-15 01:53:041106TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:441107 // Construct the request.
rdsmithebb50aa2015-11-12 03:44:381108 // Each request fully completes before the next starts.
[email protected]cdf8f7e72013-05-23 10:56:461109 scoped_ptr<SpdyFrame> req(
1110 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041111 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1112 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1113 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381114 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441115
[email protected]cdf8f7e72013-05-23 10:56:461116 scoped_ptr<SpdyFrame> req2(
1117 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041118 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1119 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1120 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:381121 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:441122
[email protected]cdf8f7e72013-05-23 10:56:461123 scoped_ptr<SpdyFrame> req3(
1124 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041125 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1126 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1127 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:441128
[email protected]18b28ab2012-04-18 02:14:421129 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461130 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421131 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1132 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201133 scoped_ptr<SpdyFrame> settings_frame(
1134 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211135 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441136
[email protected]2d6728692011-03-12 01:39:551137 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521138 CreateMockWrite(*req, 0),
1139 CreateMockWrite(*settings_ack, 5),
1140 CreateMockWrite(*req2, 6),
1141 CreateMockWrite(*req3, 10),
[email protected]2bd93022010-07-17 00:58:441142 };
[email protected]2d6728692011-03-12 01:39:551143
[email protected]2bd93022010-07-17 00:58:441144 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521145 CreateMockRead(*settings_frame, 1),
1146 CreateMockRead(*resp, 2),
1147 CreateMockRead(*body, 3),
1148 CreateMockRead(*fbody, 4),
1149 CreateMockRead(*resp2, 7),
1150 CreateMockRead(*body2, 8),
1151 CreateMockRead(*fbody2, 9),
1152 CreateMockRead(*resp3, 11),
1153 CreateMockRead(*body3, 12),
1154 CreateMockRead(*fbody3, 13),
[email protected]2bd93022010-07-17 00:58:441155
rch08e3aa3e2015-05-16 14:27:521156 MockRead(ASYNC, 0, 14), // EOF
[email protected]2bd93022010-07-17 00:58:441157 };
1158
rch08e3aa3e2015-05-16 14:27:521159 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441160
1161 BoundNetLog log;
1162 TransactionHelperResult out;
1163 {
[email protected]262eec82013-03-19 21:01:361164 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501165 BoundNetLog(), GetParam(), NULL);
[email protected]2d6728692011-03-12 01:39:551166 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571167 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:081168 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421169 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081170 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421171 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081172 scoped_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:421173 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]2bd93022010-07-17 00:58:441174
[email protected]49639fa2011-12-20 23:22:411175 TestCompletionCallback callback1;
1176 TestCompletionCallback callback2;
1177 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441178
1179 HttpRequestInfo httpreq1 = CreateGetRequest();
1180 HttpRequestInfo httpreq2 = CreateGetRequest();
1181 HttpRequestInfo httpreq3 = CreateGetRequest();
1182
[email protected]49639fa2011-12-20 23:22:411183 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]2bd93022010-07-17 00:58:441184 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]513963e2013-06-15 01:53:041185 // Run transaction 1 through quickly to force a read of our SETTINGS
1186 // frame.
[email protected]2bd93022010-07-17 00:58:441187 out.rv = callback1.WaitForResult();
[email protected]bdebd1b2010-08-09 20:18:081188 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441189
[email protected]49639fa2011-12-20 23:22:411190 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]2bd93022010-07-17 00:58:441191 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411192 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]2bd93022010-07-17 00:58:441193 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1194 out.rv = callback2.WaitForResult();
1195 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441196
1197 out.rv = callback3.WaitForResult();
1198 ASSERT_EQ(OK, out.rv);
1199
1200 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081201 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501202 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]2bd93022010-07-17 00:58:441203 EXPECT_TRUE(response1->was_fetched_via_spdy);
1204 out.status_line = response1->headers->GetStatusLine();
1205 out.response_info = *response1;
1206 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1207 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021208 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441209 EXPECT_EQ("hello!hello!", out.response_data);
1210
1211 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1212 out.status_line = response2->headers->GetStatusLine();
1213 out.response_info = *response2;
1214 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1215 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021216 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441217 EXPECT_EQ("hello!hello!", out.response_data);
1218
1219 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1220 out.status_line = response3->headers->GetStatusLine();
1221 out.response_info = *response3;
1222 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1223 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021224 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441225 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:261226
1227 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441228 }
1229 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441230}
1231
1232// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1233// a fourth transaction. The third and fourth transactions have
1234// different data ("hello!" vs "hello!hello!") and because of the
1235// user specified priority, we expect to see them inverted in
1236// the response from the server.
[email protected]513963e2013-06-15 01:53:041237TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:441238 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461239 scoped_ptr<SpdyFrame> req(
1240 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041241 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1242 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1243 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381244 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441245
[email protected]cdf8f7e72013-05-23 10:56:461246 scoped_ptr<SpdyFrame> req2(
1247 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041248 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1249 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1250 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:381251 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:441252
[email protected]ff98d7f02012-03-22 21:44:191253 scoped_ptr<SpdyFrame> req4(
[email protected]cdf8f7e72013-05-23 10:56:461254 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
[email protected]513963e2013-06-15 01:53:041255 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1256 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
rdsmithebb50aa2015-11-12 03:44:381257 spdy_util_.UpdateWithStreamDestruction(5);
[email protected]2bd93022010-07-17 00:58:441258
[email protected]cdf8f7e72013-05-23 10:56:461259 scoped_ptr<SpdyFrame> req3(
1260 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041261 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1262 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1263 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
[email protected]2bd93022010-07-17 00:58:441264
[email protected]18b28ab2012-04-18 02:14:421265 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461266 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421267 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1268 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201269 scoped_ptr<SpdyFrame> settings_frame(
1270 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211271 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
rch08e3aa3e2015-05-16 14:27:521272 MockWrite writes[] = {
1273 CreateMockWrite(*req, 0),
1274 CreateMockWrite(*settings_ack, 5),
1275 // By making these synchronous, it guarantees that they are not *started*
1276 // before their sequence number, which in turn verifies that only a single
1277 // request is in-flight at a time.
1278 CreateMockWrite(*req2, 6, SYNCHRONOUS),
1279 CreateMockWrite(*req4, 10, SYNCHRONOUS),
1280 CreateMockWrite(*req3, 13, SYNCHRONOUS),
[email protected]2bd93022010-07-17 00:58:441281 };
1282 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521283 CreateMockRead(*settings_frame, 1),
1284 CreateMockRead(*resp, 2),
1285 CreateMockRead(*body, 3),
1286 CreateMockRead(*fbody, 4),
1287 CreateMockRead(*resp2, 7),
1288 CreateMockRead(*body2, 8),
1289 CreateMockRead(*fbody2, 9),
1290 CreateMockRead(*resp4, 11),
1291 CreateMockRead(*fbody4, 12),
1292 CreateMockRead(*resp3, 14),
1293 CreateMockRead(*body3, 15),
1294 CreateMockRead(*fbody3, 16),
[email protected]2bd93022010-07-17 00:58:441295
rch08e3aa3e2015-05-16 14:27:521296 MockRead(ASYNC, 0, 17), // EOF
[email protected]2bd93022010-07-17 00:58:441297 };
rch08e3aa3e2015-05-16 14:27:521298 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441299 BoundNetLog log;
1300 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361301 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1302 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081303 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571304 helper.AddData(&data);
rch08e3aa3e2015-05-16 14:27:521305
[email protected]bdebd1b2010-08-09 20:18:081306 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421307 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081308 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421309 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081310 scoped_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:421311 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081312 scoped_ptr<HttpNetworkTransaction> trans4(
mmenkee65e7af2015-10-13 17:16:421313 new HttpNetworkTransaction(HIGHEST, helper.session()));
[email protected]2bd93022010-07-17 00:58:441314
[email protected]49639fa2011-12-20 23:22:411315 TestCompletionCallback callback1;
1316 TestCompletionCallback callback2;
1317 TestCompletionCallback callback3;
1318 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:441319
[email protected]bdebd1b2010-08-09 20:18:081320 HttpRequestInfo httpreq1 = CreateGetRequest();
1321 HttpRequestInfo httpreq2 = CreateGetRequest();
1322 HttpRequestInfo httpreq3 = CreateGetRequest();
1323 HttpRequestInfo httpreq4 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441324
[email protected]49639fa2011-12-20 23:22:411325 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081326 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]e0935cc2012-03-24 14:12:481327 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081328 out.rv = callback1.WaitForResult();
1329 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441330
[email protected]49639fa2011-12-20 23:22:411331 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081332 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411333 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081334 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411335 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081336 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:441337
[email protected]bdebd1b2010-08-09 20:18:081338 out.rv = callback2.WaitForResult();
1339 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441340
[email protected]bdebd1b2010-08-09 20:18:081341 out.rv = callback3.WaitForResult();
1342 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441343
[email protected]bdebd1b2010-08-09 20:18:081344 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501345 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:081346 EXPECT_TRUE(response1->was_fetched_via_spdy);
1347 out.status_line = response1->headers->GetStatusLine();
1348 out.response_info = *response1;
1349 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1350 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021351 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081352 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441353
[email protected]bdebd1b2010-08-09 20:18:081354 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1355 out.status_line = response2->headers->GetStatusLine();
1356 out.response_info = *response2;
1357 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1358 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021359 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081360 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441361
[email protected]bdebd1b2010-08-09 20:18:081362 // notice: response3 gets two hellos, response4 gets one
1363 // hello, so we know dequeuing priority was respected.
1364 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1365 out.status_line = response3->headers->GetStatusLine();
1366 out.response_info = *response3;
1367 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1368 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021369 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081370 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441371
[email protected]bdebd1b2010-08-09 20:18:081372 out.rv = callback4.WaitForResult();
1373 EXPECT_EQ(OK, out.rv);
1374 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1375 out.status_line = response4->headers->GetStatusLine();
1376 out.response_info = *response4;
1377 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1378 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021379 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081380 EXPECT_EQ("hello!", out.response_data);
1381 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441382 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441383}
1384
1385// Similar to ThreeGetsMaxConcurrrent above, however, this test
rch08e3aa3e2015-05-16 14:27:521386// deletes a session in the middle of the transaction to ensure
[email protected]2bd93022010-07-17 00:58:441387// that we properly remove pendingcreatestream objects from
1388// the spdy_session
[email protected]513963e2013-06-15 01:53:041389TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:441390 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461391 scoped_ptr<SpdyFrame> req(
1392 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041393 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1394 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1395 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381396 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441397
[email protected]cdf8f7e72013-05-23 10:56:461398 scoped_ptr<SpdyFrame> req2(
1399 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041400 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1401 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1402 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441403
[email protected]18b28ab2012-04-18 02:14:421404 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461405 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421406 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1407 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201408 scoped_ptr<SpdyFrame> settings_frame(
1409 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211410 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441411
[email protected]d4a77c12014-05-15 20:45:211412 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521413 CreateMockWrite(*req, 0),
1414 CreateMockWrite(*settings_ack, 5),
1415 CreateMockWrite(*req2, 6),
[email protected]2bd93022010-07-17 00:58:441416 };
1417 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521418 CreateMockRead(*settings_frame, 1),
1419 CreateMockRead(*resp, 2),
1420 CreateMockRead(*body, 3),
1421 CreateMockRead(*fbody, 4),
1422 CreateMockRead(*resp2, 7),
1423 CreateMockRead(*body2, 8),
1424 CreateMockRead(*fbody2, 9),
1425 MockRead(ASYNC, 0, 10), // EOF
[email protected]2bd93022010-07-17 00:58:441426 };
1427
rch08e3aa3e2015-05-16 14:27:521428 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441429
1430 BoundNetLog log;
1431 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361432 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1433 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081434 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571435 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:081436 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421437 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081438 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421439 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081440 scoped_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:421441 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]2bd93022010-07-17 00:58:441442
[email protected]49639fa2011-12-20 23:22:411443 TestCompletionCallback callback1;
1444 TestCompletionCallback callback2;
1445 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441446
[email protected]bdebd1b2010-08-09 20:18:081447 HttpRequestInfo httpreq1 = CreateGetRequest();
1448 HttpRequestInfo httpreq2 = CreateGetRequest();
1449 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441450
[email protected]49639fa2011-12-20 23:22:411451 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081452 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481453 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081454 out.rv = callback1.WaitForResult();
1455 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441456
[email protected]49639fa2011-12-20 23:22:411457 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081458 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411459 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081460 delete trans3.release();
1461 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1462 out.rv = callback2.WaitForResult();
1463 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441464
[email protected]bdebd1b2010-08-09 20:18:081465 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1466 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501467 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:081468 EXPECT_TRUE(response1->was_fetched_via_spdy);
1469 out.status_line = response1->headers->GetStatusLine();
1470 out.response_info = *response1;
1471 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1472 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021473 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081474 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441475
[email protected]bdebd1b2010-08-09 20:18:081476 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1477 ASSERT_TRUE(response2 != NULL);
1478 out.status_line = response2->headers->GetStatusLine();
1479 out.response_info = *response2;
1480 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1481 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021482 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081483 EXPECT_EQ("hello!hello!", out.response_data);
1484 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441485 EXPECT_EQ(OK, out.rv);
[email protected]044dcc52010-09-17 15:44:261486}
[email protected]2bd93022010-07-17 00:58:441487
[email protected]448d4ca52012-03-04 04:12:231488namespace {
1489
[email protected]044dcc52010-09-17 15:44:261490// The KillerCallback will delete the transaction on error as part of the
1491// callback.
[email protected]49639fa2011-12-20 23:22:411492class KillerCallback : public TestCompletionCallbackBase {
[email protected]044dcc52010-09-17 15:44:261493 public:
1494 explicit KillerCallback(HttpNetworkTransaction* transaction)
[email protected]49639fa2011-12-20 23:22:411495 : transaction_(transaction),
[email protected]aa249b52013-04-30 01:04:321496 callback_(base::Bind(&KillerCallback::OnComplete,
1497 base::Unretained(this))) {
[email protected]044dcc52010-09-17 15:44:261498 }
1499
dchengb03027d2014-10-21 12:00:201500 ~KillerCallback() override {}
[email protected]49639fa2011-12-20 23:22:411501
1502 const CompletionCallback& callback() const { return callback_; }
1503
[email protected]044dcc52010-09-17 15:44:261504 private:
[email protected]49639fa2011-12-20 23:22:411505 void OnComplete(int result) {
1506 if (result < 0)
1507 delete transaction_;
1508
1509 SetResult(result);
1510 }
1511
[email protected]044dcc52010-09-17 15:44:261512 HttpNetworkTransaction* transaction_;
[email protected]49639fa2011-12-20 23:22:411513 CompletionCallback callback_;
[email protected]044dcc52010-09-17 15:44:261514};
1515
[email protected]448d4ca52012-03-04 04:12:231516} // namespace
1517
[email protected]044dcc52010-09-17 15:44:261518// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1519// closes the socket while we have a pending transaction waiting for
1520// a pending stream creation. http://crbug.com/52901
[email protected]513963e2013-06-15 01:53:041521TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
[email protected]044dcc52010-09-17 15:44:261522 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461523 scoped_ptr<SpdyFrame> req(
1524 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041525 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1526 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1527 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381528 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]044dcc52010-09-17 15:44:261529
[email protected]cdf8f7e72013-05-23 10:56:461530 scoped_ptr<SpdyFrame> req2(
1531 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041532 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]044dcc52010-09-17 15:44:261533
[email protected]18b28ab2012-04-18 02:14:421534 SettingsMap settings;
Avi Drissman13fc8932015-12-20 04:40:461535 const uint32_t max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421536 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1537 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201538 scoped_ptr<SpdyFrame> settings_frame(
1539 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211540 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]044dcc52010-09-17 15:44:261541
[email protected]d4a77c12014-05-15 20:45:211542 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521543 CreateMockWrite(*req, 0),
1544 CreateMockWrite(*settings_ack, 5),
1545 CreateMockWrite(*req2, 6),
[email protected]044dcc52010-09-17 15:44:261546 };
1547 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521548 CreateMockRead(*settings_frame, 1),
1549 CreateMockRead(*resp, 2),
1550 CreateMockRead(*body, 3),
1551 CreateMockRead(*fin_body, 4),
1552 CreateMockRead(*resp2, 7),
1553 MockRead(ASYNC, ERR_CONNECTION_RESET, 8), // Abort!
[email protected]044dcc52010-09-17 15:44:261554 };
1555
rch08e3aa3e2015-05-16 14:27:521556 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1557 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]044dcc52010-09-17 15:44:261558
1559 BoundNetLog log;
1560 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361561 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1562 BoundNetLog(), GetParam(), NULL);
[email protected]044dcc52010-09-17 15:44:261563 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571564 helper.AddData(&data);
[email protected]044dcc52010-09-17 15:44:261565 // We require placeholder data because three get requests are sent out, so
1566 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571567 helper.AddData(&data_placeholder);
1568 helper.AddData(&data_placeholder);
mmenkee65e7af2015-10-13 17:16:421569 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1570 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]262eec82013-03-19 21:01:361571 HttpNetworkTransaction* trans3(
mmenkee65e7af2015-10-13 17:16:421572 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]044dcc52010-09-17 15:44:261573
[email protected]49639fa2011-12-20 23:22:411574 TestCompletionCallback callback1;
1575 TestCompletionCallback callback2;
[email protected]044dcc52010-09-17 15:44:261576 KillerCallback callback3(trans3);
1577
1578 HttpRequestInfo httpreq1 = CreateGetRequest();
1579 HttpRequestInfo httpreq2 = CreateGetRequest();
1580 HttpRequestInfo httpreq3 = CreateGetRequest();
1581
[email protected]49639fa2011-12-20 23:22:411582 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]044dcc52010-09-17 15:44:261583 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481584 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]044dcc52010-09-17 15:44:261585 out.rv = callback1.WaitForResult();
1586 ASSERT_EQ(OK, out.rv);
1587
[email protected]49639fa2011-12-20 23:22:411588 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]044dcc52010-09-17 15:44:261589 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411590 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]044dcc52010-09-17 15:44:261591 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1592 out.rv = callback3.WaitForResult();
1593 ASSERT_EQ(ERR_ABORTED, out.rv);
1594
[email protected]044dcc52010-09-17 15:44:261595 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1596 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501597 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]044dcc52010-09-17 15:44:261598 EXPECT_TRUE(response1->was_fetched_via_spdy);
1599 out.status_line = response1->headers->GetStatusLine();
1600 out.response_info = *response1;
1601 out.rv = ReadTransaction(&trans1, &out.response_data);
1602 EXPECT_EQ(OK, out.rv);
1603
1604 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1605 ASSERT_TRUE(response2 != NULL);
1606 out.status_line = response2->headers->GetStatusLine();
1607 out.response_info = *response2;
1608 out.rv = ReadTransaction(&trans2, &out.response_data);
1609 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1610
1611 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441612}
1613
[email protected]d8ef27b2010-08-06 17:34:391614// Test that a simple PUT request works.
[email protected]513963e2013-06-15 01:53:041615TEST_P(SpdyNetworkTransactionTest, Put) {
[email protected]d8ef27b2010-08-06 17:34:391616 // Setup the request
1617 HttpRequestInfo request;
1618 request.method = "PUT";
rchebf12982015-04-10 01:15:001619 request.url = GURL(GetDefaultUrl());
[email protected]d8ef27b2010-08-06 17:34:391620
[email protected]513963e2013-06-15 01:53:041621 scoped_ptr<SpdyHeaderBlock> put_headers(
rchebf12982015-04-10 01:15:001622 spdy_util_.ConstructPutHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291623 scoped_ptr<SpdyFrame> req(
1624 spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
[email protected]d8ef27b2010-08-06 17:34:391625 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521626 CreateMockWrite(*req, 0),
[email protected]d8ef27b2010-08-06 17:34:391627 };
1628
[email protected]745aa9c2014-06-27 02:21:291629 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041630 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391631 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521632 CreateMockRead(*resp, 1),
1633 CreateMockRead(*body, 2),
1634 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391635 };
1636
rch08e3aa3e2015-05-16 14:27:521637 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361638 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501639 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571640 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391641 TransactionHelperResult out = helper.output();
1642
1643 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021644 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391645}
1646
1647// Test that a simple HEAD request works.
[email protected]513963e2013-06-15 01:53:041648TEST_P(SpdyNetworkTransactionTest, Head) {
[email protected]d8ef27b2010-08-06 17:34:391649 // Setup the request
1650 HttpRequestInfo request;
1651 request.method = "HEAD";
rchebf12982015-04-10 01:15:001652 request.url = GURL(GetDefaultUrl());
[email protected]d8ef27b2010-08-06 17:34:391653
[email protected]513963e2013-06-15 01:53:041654 scoped_ptr<SpdyHeaderBlock> head_headers(
rchebf12982015-04-10 01:15:001655 spdy_util_.ConstructHeadHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291656 scoped_ptr<SpdyFrame> req(
1657 spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
[email protected]d8ef27b2010-08-06 17:34:391658 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521659 CreateMockWrite(*req, 0),
[email protected]d8ef27b2010-08-06 17:34:391660 };
1661
[email protected]745aa9c2014-06-27 02:21:291662 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041663 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391664 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521665 CreateMockRead(*resp, 1),
1666 CreateMockRead(*body, 2),
1667 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391668 };
1669
rch08e3aa3e2015-05-16 14:27:521670 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361671 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501672 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571673 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391674 TransactionHelperResult out = helper.output();
1675
1676 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021677 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391678}
1679
[email protected]72552f02009-10-28 15:25:011680// Test that a simple POST works.
[email protected]513963e2013-06-15 01:53:041681TEST_P(SpdyNetworkTransactionTest, Post) {
rchebf12982015-04-10 01:15:001682 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1683 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041684 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141685 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521686 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141687 };
[email protected]72552f02009-10-28 15:25:011688
[email protected]513963e2013-06-15 01:53:041689 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]ff57bb82009-11-12 06:52:141690 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521691 CreateMockRead(*resp, 2),
1692 CreateMockRead(*body, 3),
1693 MockRead(ASYNC, 0, 4) // EOF
[email protected]aea80602009-09-18 00:55:081694 };
1695
rch08e3aa3e2015-05-16 14:27:521696 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361697 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501698 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571699 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471700 TransactionHelperResult out = helper.output();
[email protected]aea80602009-09-18 00:55:081701 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021702 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]aea80602009-09-18 00:55:081703 EXPECT_EQ("hello!", out.response_data);
1704}
1705
[email protected]69e6b4a2012-10-18 08:03:011706// Test that a POST with a file works.
[email protected]513963e2013-06-15 01:53:041707TEST_P(SpdyNetworkTransactionTest, FilePost) {
rchebf12982015-04-10 01:15:001708 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1709 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041710 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011711 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521712 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011713 };
1714
[email protected]513963e2013-06-15 01:53:041715 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011716 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521717 CreateMockRead(*resp, 2),
1718 CreateMockRead(*body, 3),
1719 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011720 };
1721
rch08e3aa3e2015-05-16 14:27:521722 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361723 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
[email protected]69e6b4a2012-10-18 08:03:011724 BoundNetLog(), GetParam(), NULL);
1725 helper.RunToCompletion(&data);
1726 TransactionHelperResult out = helper.output();
1727 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021728 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011729 EXPECT_EQ("hello!", out.response_data);
1730}
1731
[email protected]999dd8c2013-11-12 06:45:541732// Test that a POST with a unreadable file fails.
1733TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1734 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521735 MockWrite(ASYNC, 0, 0) // EOF
[email protected]999dd8c2013-11-12 06:45:541736 };
1737 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521738 MockRead(ASYNC, 0, 1) // EOF
[email protected]999dd8c2013-11-12 06:45:541739 };
1740
rch08e3aa3e2015-05-16 14:27:521741 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]999dd8c2013-11-12 06:45:541742 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1743 DEFAULT_PRIORITY,
1744 BoundNetLog(), GetParam(), NULL);
1745 helper.RunPreTestSetup();
1746 helper.AddData(&data);
1747 helper.RunDefaultTest();
1748
1749 base::RunLoop().RunUntilIdle();
1750 helper.VerifyDataNotConsumed();
1751 EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1752}
1753
[email protected]69e6b4a2012-10-18 08:03:011754// Test that a complex POST works.
[email protected]513963e2013-06-15 01:53:041755TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
rchebf12982015-04-10 01:15:001756 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1757 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041758 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011759 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521760 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011761 };
1762
[email protected]513963e2013-06-15 01:53:041763 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011764 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521765 CreateMockRead(*resp, 2),
1766 CreateMockRead(*body, 3),
1767 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011768 };
1769
rch08e3aa3e2015-05-16 14:27:521770 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]69e6b4a2012-10-18 08:03:011771 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
[email protected]262eec82013-03-19 21:01:361772 DEFAULT_PRIORITY,
[email protected]69e6b4a2012-10-18 08:03:011773 BoundNetLog(), GetParam(), NULL);
1774 helper.RunToCompletion(&data);
1775 TransactionHelperResult out = helper.output();
1776 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021777 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011778 EXPECT_EQ("hello!", out.response_data);
1779}
1780
[email protected]0c9bf872011-03-04 17:53:221781// Test that a chunked POST works.
[email protected]513963e2013-06-15 01:53:041782TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
[email protected]513963e2013-06-15 01:53:041783 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1784 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]0c9bf872011-03-04 17:53:221785 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521786 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1),
[email protected]0c9bf872011-03-04 17:53:221787 };
1788
[email protected]513963e2013-06-15 01:53:041789 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]0c9bf872011-03-04 17:53:221790 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521791 CreateMockRead(*resp, 2),
1792 CreateMockRead(*body, 3),
1793 MockRead(ASYNC, 0, 4) // EOF
[email protected]0c9bf872011-03-04 17:53:221794 };
1795
rch08e3aa3e2015-05-16 14:27:521796 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]0c9bf872011-03-04 17:53:221797 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
[email protected]262eec82013-03-19 21:01:361798 DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501799 BoundNetLog(), GetParam(), NULL);
[email protected]34b345f92013-02-22 03:27:261800
1801 // These chunks get merged into a single frame when being sent.
1802 const int kFirstChunkSize = kUploadDataSize/2;
mmenkecbc2b712014-10-09 20:29:071803 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1804 upload_chunked_data_stream()->AppendData(
[email protected]34b345f92013-02-22 03:27:261805 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1806
[email protected]dd54bd82012-07-19 23:44:571807 helper.RunToCompletion(&data);
[email protected]0c9bf872011-03-04 17:53:221808 TransactionHelperResult out = helper.output();
1809 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021810 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261811 EXPECT_EQ(kUploadData, out.response_data);
1812}
1813
1814// Test that a chunked POST works with chunks appended after transaction starts.
[email protected]513963e2013-06-15 01:53:041815TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
[email protected]513963e2013-06-15 01:53:041816 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1817 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1818 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1819 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]34b345f92013-02-22 03:27:261820 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521821 CreateMockWrite(*req, 0),
1822 CreateMockWrite(*chunk1, 1),
1823 CreateMockWrite(*chunk2, 2),
1824 CreateMockWrite(*chunk3, 3),
[email protected]34b345f92013-02-22 03:27:261825 };
1826
[email protected]513963e2013-06-15 01:53:041827 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]34b345f92013-02-22 03:27:261828 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521829 CreateMockRead(*resp, 4),
1830 CreateMockRead(*chunk1, 5),
1831 CreateMockRead(*chunk2, 6),
1832 CreateMockRead(*chunk3, 7),
1833 MockRead(ASYNC, 0, 8) // EOF
[email protected]34b345f92013-02-22 03:27:261834 };
1835
rch08e3aa3e2015-05-16 14:27:521836 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]34b345f92013-02-22 03:27:261837 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
[email protected]262eec82013-03-19 21:01:361838 DEFAULT_PRIORITY,
[email protected]34b345f92013-02-22 03:27:261839 BoundNetLog(), GetParam(), NULL);
1840
mmenkecbc2b712014-10-09 20:29:071841 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]34b345f92013-02-22 03:27:261842
1843 helper.RunPreTestSetup();
1844 helper.AddData(&data);
1845 ASSERT_TRUE(helper.StartDefaultTest());
1846
[email protected]fc9d88472013-08-14 02:31:171847 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071848 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]fc9d88472013-08-14 02:31:171849 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071850 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]34b345f92013-02-22 03:27:261851
1852 helper.FinishDefaultTest();
1853 helper.VerifyDataConsumed();
1854
1855 std::string expected_response;
1856 expected_response += kUploadData;
1857 expected_response += kUploadData;
1858 expected_response += kUploadData;
1859
1860 TransactionHelperResult out = helper.output();
1861 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021862 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261863 EXPECT_EQ(expected_response, out.response_data);
[email protected]0c9bf872011-03-04 17:53:221864}
1865
[email protected]a33cad2b62010-07-30 22:24:391866// Test that a POST without any post data works.
[email protected]513963e2013-06-15 01:53:041867TEST_P(SpdyNetworkTransactionTest, NullPost) {
[email protected]d2c1a97b2014-03-03 19:25:091868 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]a33cad2b62010-07-30 22:24:391869 // Setup the request
1870 HttpRequestInfo request;
1871 request.method = "POST";
rchebf12982015-04-10 01:15:001872 request.url = GURL(GetDefaultUrl());
[email protected]a33cad2b62010-07-30 22:24:391873 // Create an empty UploadData.
[email protected]329b68b2012-11-14 17:54:271874 request.upload_data_stream = NULL;
[email protected]a33cad2b62010-07-30 22:24:391875
[email protected]329b68b2012-11-14 17:54:271876 // When request.upload_data_stream is NULL for post, content-length is
[email protected]a33cad2b62010-07-30 22:24:391877 // expected to be 0.
[email protected]745aa9c2014-06-27 02:21:291878 scoped_ptr<SpdyHeaderBlock> req_block(
rchebf12982015-04-10 01:15:001879 spdy_util_.ConstructPostHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291880 scoped_ptr<SpdyFrame> req(
1881 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
[email protected]d2c1a97b2014-03-03 19:25:091882
[email protected]a33cad2b62010-07-30 22:24:391883 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521884 CreateMockWrite(*req, 0),
[email protected]a33cad2b62010-07-30 22:24:391885 };
1886
[email protected]513963e2013-06-15 01:53:041887 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1888 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]a33cad2b62010-07-30 22:24:391889 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521890 CreateMockRead(*resp, 1),
1891 CreateMockRead(*body, 2),
1892 MockRead(ASYNC, 0, 3) // EOF
[email protected]a33cad2b62010-07-30 22:24:391893 };
1894
rch08e3aa3e2015-05-16 14:27:521895 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]a33cad2b62010-07-30 22:24:391896
[email protected]262eec82013-03-19 21:01:361897 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501898 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571899 helper.RunToCompletion(&data);
[email protected]a33cad2b62010-07-30 22:24:391900 TransactionHelperResult out = helper.output();
1901 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021902 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]a33cad2b62010-07-30 22:24:391903 EXPECT_EQ("hello!", out.response_data);
1904}
1905
[email protected]edd3b0a52009-11-24 18:56:361906// Test that a simple POST works.
[email protected]513963e2013-06-15 01:53:041907TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]d2c1a97b2014-03-03 19:25:091908 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]329b68b2012-11-14 17:54:271909 // Create an empty UploadDataStream.
olli.raula6df48b2a2015-11-26 07:40:221910 std::vector<scoped_ptr<UploadElementReader>> element_readers;
1911 ElementsUploadDataStream stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271912
[email protected]edd3b0a52009-11-24 18:56:361913 // Setup the request
1914 HttpRequestInfo request;
1915 request.method = "POST";
rchebf12982015-04-10 01:15:001916 request.url = GURL(GetDefaultUrl());
[email protected]329b68b2012-11-14 17:54:271917 request.upload_data_stream = &stream;
[email protected]edd3b0a52009-11-24 18:56:361918
Avi Drissman13fc8932015-12-20 04:40:461919 const uint64_t kContentLength = 0;
[email protected]d2c1a97b2014-03-03 19:25:091920
[email protected]745aa9c2014-06-27 02:21:291921 scoped_ptr<SpdyHeaderBlock> req_block(
rchebf12982015-04-10 01:15:001922 spdy_util_.ConstructPostHeaderBlock(GetDefaultUrl(), kContentLength));
[email protected]745aa9c2014-06-27 02:21:291923 scoped_ptr<SpdyFrame> req(
1924 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
[email protected]d2c1a97b2014-03-03 19:25:091925
[email protected]edd3b0a52009-11-24 18:56:361926 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521927 CreateMockWrite(*req, 0),
[email protected]edd3b0a52009-11-24 18:56:361928 };
1929
[email protected]513963e2013-06-15 01:53:041930 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1931 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361932 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521933 CreateMockRead(*resp, 1),
1934 CreateMockRead(*body, 2),
1935 MockRead(ASYNC, 0, 3) // EOF
[email protected]edd3b0a52009-11-24 18:56:361936 };
1937
rch08e3aa3e2015-05-16 14:27:521938 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bf2491a92009-11-29 16:39:481939
[email protected]262eec82013-03-19 21:01:361940 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1941 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571942 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471943 TransactionHelperResult out = helper.output();
[email protected]edd3b0a52009-11-24 18:56:361944 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021945 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]edd3b0a52009-11-24 18:56:361946 EXPECT_EQ("hello!", out.response_data);
1947}
1948
[email protected]35c3fc732014-02-15 00:16:071949// While we're doing a post, the server sends the reply before upload completes.
1950TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
1951 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1952 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1953 MockWrite writes[] = {
1954 CreateMockWrite(*req, 0),
1955 CreateMockWrite(*body, 3),
1956 };
1957 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]a5566f9702010-05-05 22:25:431958 MockRead reads[] = {
[email protected]35c3fc732014-02-15 00:16:071959 CreateMockRead(*resp, 1),
1960 CreateMockRead(*body, 2),
[email protected]099bc7e2013-07-18 04:19:161961 MockRead(ASYNC, 0, 4) // EOF
[email protected]a5566f9702010-05-05 22:25:431962 };
1963
[email protected]35c3fc732014-02-15 00:16:071964 // Write the request headers, and read the complete response
1965 // while still waiting for chunked request data.
mmenke666a6fea2015-12-19 04:16:331966 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]35c3fc732014-02-15 00:16:071967 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1968 DEFAULT_PRIORITY,
[email protected]c92f4b4542012-07-26 23:53:211969 BoundNetLog(), GetParam(), NULL);
[email protected]c92f4b4542012-07-26 23:53:211970 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:331971 helper.AddData(&data);
[email protected]c92f4b4542012-07-26 23:53:211972
[email protected]35c3fc732014-02-15 00:16:071973 ASSERT_TRUE(helper.StartDefaultTest());
[email protected]c92f4b4542012-07-26 23:53:211974
mmenke666a6fea2015-12-19 04:16:331975 helper.WaitForHeaders();
1976 EXPECT_EQ(OK, helper.output().rv);
1977
[email protected]35c3fc732014-02-15 00:16:071978 // Process the request headers, SYN_REPLY, and response body.
1979 // The request body is still in flight.
[email protected]35c3fc732014-02-15 00:16:071980 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
bnc84e7fb52015-12-02 11:50:021981 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]35c3fc732014-02-15 00:16:071982
1983 // Finish sending the request body.
mmenkecbc2b712014-10-09 20:29:071984 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]35c3fc732014-02-15 00:16:071985
1986 std::string response_body;
1987 EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
1988 EXPECT_EQ(kUploadData, response_body);
1989 helper.VerifyDataConsumed();
[email protected]a5566f9702010-05-05 22:25:431990}
1991
[email protected]f9a26d72010-08-03 18:07:131992// The client upon cancellation tries to send a RST_STREAM frame. The mock
1993// socket causes the TCP write to return zero. This test checks that the client
1994// tries to queue up the RST_STREAM frame again.
[email protected]513963e2013-06-15 01:53:041995TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
[email protected]cdf8f7e72013-05-23 10:56:461996 scoped_ptr<SpdyFrame> req(
1997 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]ff98d7f02012-03-22 21:44:191998 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:201999 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]f9a26d72010-08-03 18:07:132000 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:062001 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2002 MockWrite(SYNCHRONOUS, 0, 0, 2),
2003 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
[email protected]f9a26d72010-08-03 18:07:132004 };
2005
[email protected]513963e2013-06-15 01:53:042006 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f9a26d72010-08-03 18:07:132007 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:062008 CreateMockRead(*resp.get(), 1, ASYNC),
2009 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:132010 };
2011
mmenke666a6fea2015-12-19 04:16:332012 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362013 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502014 BoundNetLog(), GetParam(), NULL);
[email protected]f9a26d72010-08-03 18:07:132015 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:332016 helper.AddData(&data);
[email protected]f9a26d72010-08-03 18:07:132017 HttpNetworkTransaction* trans = helper.trans();
2018
[email protected]49639fa2011-12-20 23:22:412019 TestCompletionCallback callback;
2020 int rv = trans->Start(
2021 &CreateGetRequest(), callback.callback(), BoundNetLog());
mmenke666a6fea2015-12-19 04:16:332022 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]3b7828432010-08-18 18:33:272023
[email protected]f9a26d72010-08-03 18:07:132024 helper.ResetTrans();
mmenke666a6fea2015-12-19 04:16:332025 base::RunLoop().RunUntilIdle();
[email protected]3b7828432010-08-18 18:33:272026
[email protected]f9a26d72010-08-03 18:07:132027 helper.VerifyDataConsumed();
2028}
2029
[email protected]93300672009-10-24 13:22:512030// Test that the transaction doesn't crash when we don't have a reply.
[email protected]513963e2013-06-15 01:53:042031TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
[email protected]513963e2013-06-15 01:53:042032 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:142033 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522034 CreateMockRead(*body, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]93300672009-10-24 13:22:512035 };
2036
rch08e3aa3e2015-05-16 14:27:522037 scoped_ptr<SpdyFrame> req(
2038 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2039 scoped_ptr<SpdyFrame> rst(
2040 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2041 MockWrite writes[] = {
2042 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
2043 };
2044 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362045 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502046 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572047 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:472048 TransactionHelperResult out = helper.output();
[email protected]2aeef782013-06-21 18:30:562049 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]93300672009-10-24 13:22:512050}
2051
[email protected]d30022352010-06-24 19:17:582052// Test that the transaction doesn't crash when we get two replies on the same
2053// stream ID. See http://crbug.com/45639.
[email protected]513963e2013-06-15 01:53:042054TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
[email protected]cdf8f7e72013-05-23 10:56:462055 scoped_ptr<SpdyFrame> req(
2056 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]2aeef782013-06-21 18:30:562057 scoped_ptr<SpdyFrame> rst(
[email protected]00b29472014-01-16 18:10:242058 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]2aeef782013-06-21 18:30:562059 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522060 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]2aeef782013-06-21 18:30:562061 };
[email protected]d30022352010-06-24 19:17:582062
[email protected]513963e2013-06-15 01:53:042063 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2064 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d30022352010-06-24 19:17:582065 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522066 CreateMockRead(*resp, 1),
2067 CreateMockRead(*resp, 2),
2068 CreateMockRead(*body, 3),
2069 MockRead(ASYNC, 0, 5) // EOF
[email protected]d30022352010-06-24 19:17:582070 };
2071
rch08e3aa3e2015-05-16 14:27:522072 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d30022352010-06-24 19:17:582073
[email protected]262eec82013-03-19 21:01:362074 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502075 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472076 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572077 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472078
2079 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:582080
[email protected]49639fa2011-12-20 23:22:412081 TestCompletionCallback callback;
2082 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]d30022352010-06-24 19:17:582083 EXPECT_EQ(ERR_IO_PENDING, rv);
2084 rv = callback.WaitForResult();
2085 EXPECT_EQ(OK, rv);
2086
2087 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a5c493b92010-08-06 23:04:292088 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:502089 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]d30022352010-06-24 19:17:582090 EXPECT_TRUE(response->was_fetched_via_spdy);
2091 std::string response_data;
[email protected]3caf5542010-07-16 15:19:472092 rv = ReadTransaction(trans, &response_data);
[email protected]d30022352010-06-24 19:17:582093 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
[email protected]3caf5542010-07-16 15:19:472094
2095 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:582096}
2097
[email protected]513963e2013-06-15 01:53:042098TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252099 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462100 scoped_ptr<SpdyFrame> req(
2101 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]5a7bb252013-02-09 00:21:052102 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202103 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252104 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522105 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
[email protected]b3503002012-03-27 04:57:252106 };
2107
2108 const char* const headers[] = {
[email protected]513963e2013-06-15 01:53:042109 "transfer-encoding", "chunked"
[email protected]b3503002012-03-27 04:57:252110 };
[email protected]513963e2013-06-15 01:53:042111 scoped_ptr<SpdyFrame> resp(
2112 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2113 scoped_ptr<SpdyFrame> body(
2114 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b3503002012-03-27 04:57:252115 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522116 CreateMockRead(*resp, 1),
2117 CreateMockRead(*body, 3),
2118 MockRead(ASYNC, 0, 4) // EOF
[email protected]b3503002012-03-27 04:57:252119 };
2120
rch08e3aa3e2015-05-16 14:27:522121 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362122 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502123 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572124 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252125 TransactionHelperResult out = helper.output();
2126 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2127
2128 helper.session()->spdy_session_pool()->CloseAllSessions();
2129 helper.VerifyDataConsumed();
2130}
2131
[email protected]513963e2013-06-15 01:53:042132TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252133 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462134 scoped_ptr<SpdyFrame> req(
2135 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]5a7bb252013-02-09 00:21:052136 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202137 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252138 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522139 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]b3503002012-03-27 04:57:252140 };
2141
[email protected]513963e2013-06-15 01:53:042142 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2143 const char* const headers[] = {
2144 "transfer-encoding", "chunked"
2145 };
2146 scoped_ptr<SpdyFrame> push(
rchebf12982015-04-10 01:15:002147 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2, 2, 1,
2148 GetDefaultUrlWithPath("/1").c_str()));
[email protected]513963e2013-06-15 01:53:042149 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b3503002012-03-27 04:57:252150 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522151 CreateMockRead(*resp, 1),
2152 CreateMockRead(*push, 2),
2153 CreateMockRead(*body, 3),
2154 MockRead(ASYNC, 0, 5) // EOF
[email protected]b3503002012-03-27 04:57:252155 };
2156
rch08e3aa3e2015-05-16 14:27:522157 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362158 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502159 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572160 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252161 TransactionHelperResult out = helper.output();
2162 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:022163 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b3503002012-03-27 04:57:252164 EXPECT_EQ("hello!", out.response_data);
2165
2166 helper.session()->spdy_session_pool()->CloseAllSessions();
2167 helper.VerifyDataConsumed();
2168}
2169
[email protected]513963e2013-06-15 01:53:042170TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:382171 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462172 scoped_ptr<SpdyFrame> req(
2173 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]34437af82009-11-06 02:28:492174 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:132175 CreateMockWrite(*req),
[email protected]34437af82009-11-06 02:28:492176 };
2177
[email protected]513963e2013-06-15 01:53:042178 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]34437af82009-11-06 02:28:492179 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132180 CreateMockRead(*resp),
[email protected]34437af82009-11-06 02:28:492181 // This following read isn't used by the test, except during the
[email protected]b4c62eb2012-11-14 18:36:512182 // RunUntilIdle() call at the end since the SpdySession survives the
[email protected]3caf5542010-07-16 15:19:472183 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
[email protected]34437af82009-11-06 02:28:492184 // MockRead will do here.
[email protected]8ddf8322012-02-23 18:08:062185 MockRead(ASYNC, 0, 0) // EOF
[email protected]34437af82009-11-06 02:28:492186 };
2187
[email protected]31a2bfe2010-02-09 08:03:392188 StaticSocketDataProvider data(reads, arraysize(reads),
2189 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472190
[email protected]262eec82013-03-19 21:01:362191 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502192 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472193 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:582194 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472195 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:492196
[email protected]49639fa2011-12-20 23:22:412197 TestCompletionCallback callback;
2198 int rv = trans->Start(
2199 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]34437af82009-11-06 02:28:492200 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472201 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:492202
[email protected]30c942b2010-07-21 16:59:592203 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:492204 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:172205 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472206 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:492207}
[email protected]72552f02009-10-28 15:25:012208
[email protected]6c6ea172010-07-27 20:04:032209// Verify that the client sends a Rst Frame upon cancelling the stream.
[email protected]513963e2013-06-15 01:53:042210TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
[email protected]cdf8f7e72013-05-23 10:56:462211 scoped_ptr<SpdyFrame> req(
2212 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]ff98d7f02012-03-22 21:44:192213 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202214 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]6c6ea172010-07-27 20:04:032215 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:062216 CreateMockWrite(*req, 0, SYNCHRONOUS),
2217 CreateMockWrite(*rst, 2, SYNCHRONOUS),
[email protected]6c6ea172010-07-27 20:04:032218 };
2219
[email protected]513963e2013-06-15 01:53:042220 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]6c6ea172010-07-27 20:04:032221 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:062222 CreateMockRead(*resp, 1, ASYNC),
2223 MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:032224 };
2225
mmenke666a6fea2015-12-19 04:16:332226 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]6c6ea172010-07-27 20:04:032227
[email protected]262eec82013-03-19 21:01:362228 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]6c6ea172010-07-27 20:04:032229 BoundNetLog(),
[email protected]61b4efc2012-04-27 18:12:502230 GetParam(), NULL);
[email protected]6c6ea172010-07-27 20:04:032231 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:332232 helper.AddData(&data);
[email protected]6c6ea172010-07-27 20:04:032233 HttpNetworkTransaction* trans = helper.trans();
2234
[email protected]49639fa2011-12-20 23:22:412235 TestCompletionCallback callback;
[email protected]6c6ea172010-07-27 20:04:032236
[email protected]49639fa2011-12-20 23:22:412237 int rv = trans->Start(
2238 &CreateGetRequest(), callback.callback(), BoundNetLog());
mmenke666a6fea2015-12-19 04:16:332239 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]6c6ea172010-07-27 20:04:032240
[email protected]3b7828432010-08-18 18:33:272241 helper.ResetTrans();
mmenke666a6fea2015-12-19 04:16:332242 base::RunLoop().RunUntilIdle();
[email protected]3b7828432010-08-18 18:33:272243
[email protected]6c6ea172010-07-27 20:04:032244 helper.VerifyDataConsumed();
2245}
2246
[email protected]b278eb72010-07-09 20:17:002247// Verify that the client can correctly deal with the user callback attempting
2248// to start another transaction on a session that is closing down. See
2249// http://crbug.com/47455
[email protected]513963e2013-06-15 01:53:042250TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
[email protected]cdf8f7e72013-05-23 10:56:462251 scoped_ptr<SpdyFrame> req(
2252 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:522253 MockWrite writes[] = {CreateMockWrite(*req)};
2254 MockWrite writes2[] = {CreateMockWrite(*req, 0)};
[email protected]b278eb72010-07-09 20:17:002255
[email protected]cbdd73162013-03-18 23:27:332256 // The indicated length of this frame is longer than its actual length. When
2257 // the session receives an empty frame after this one, it shuts down the
[email protected]b278eb72010-07-09 20:17:002258 // session, and calls the read callback with the incomplete data.
Avi Drissman13fc8932015-12-20 04:40:462259 const uint8_t kGetBodyFrame2[] = {
2260 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
2261 0x07, 'h', 'e', 'l', 'l', 'o', '!',
[email protected]b278eb72010-07-09 20:17:002262 };
2263
[email protected]513963e2013-06-15 01:53:042264 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]b278eb72010-07-09 20:17:002265 MockRead reads[] = {
rch32320842015-05-16 15:57:092266 CreateMockRead(*resp, 1),
2267 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2268 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2269 arraysize(kGetBodyFrame2), 3),
2270 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
2271 MockRead(ASYNC, 0, 0, 5), // EOF
[email protected]b278eb72010-07-09 20:17:002272 };
2273 MockRead reads2[] = {
rch08e3aa3e2015-05-16 14:27:522274 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 0, 2), // EOF
[email protected]b278eb72010-07-09 20:17:002275 };
2276
rch32320842015-05-16 15:57:092277 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
rch08e3aa3e2015-05-16 14:27:522278 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2279 arraysize(writes2));
[email protected]3caf5542010-07-16 15:19:472280
[email protected]262eec82013-03-19 21:01:362281 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502282 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582283 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572284 helper.AddData(&data);
2285 helper.AddData(&data2);
[email protected]3caf5542010-07-16 15:19:472286 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002287
2288 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412289 TestCompletionCallback callback;
2290 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]b278eb72010-07-09 20:17:002291 EXPECT_EQ(ERR_IO_PENDING, rv);
2292 rv = callback.WaitForResult();
2293
[email protected]b278eb72010-07-09 20:17:002294 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162295 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412296 rv = trans->Read(
rchebf12982015-04-10 01:15:002297 buf.get(), kSize,
[email protected]513963e2013-06-15 01:53:042298 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
rchebf12982015-04-10 01:15:002299 helper.session(), GURL(GetDefaultUrl())));
rch32320842015-05-16 15:57:092300 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472301 // This forces an err_IO_pending, which sets the callback.
mmenkee24011922015-12-17 22:12:592302 data.Resume();
2303 data.RunUntilPaused();
2304
[email protected]3caf5542010-07-16 15:19:472305 // This finishes the read.
mmenkee24011922015-12-17 22:12:592306 data.Resume();
2307 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472308 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002309}
2310
[email protected]9be804c82010-06-24 17:59:462311// Verify that the client can correctly deal with the user callback deleting the
2312// transaction. Failures will usually be valgrind errors. See
2313// http://crbug.com/46925
[email protected]513963e2013-06-15 01:53:042314TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
[email protected]cdf8f7e72013-05-23 10:56:462315 scoped_ptr<SpdyFrame> req(
2316 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch32320842015-05-16 15:57:092317 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]9be804c82010-06-24 17:59:462318
[email protected]513963e2013-06-15 01:53:042319 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2320 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462321 MockRead reads[] = {
rch32320842015-05-16 15:57:092322 CreateMockRead(*resp.get(), 1),
2323 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2324 CreateMockRead(*body.get(), 3),
2325 MockRead(ASYNC, 0, 0, 4), // EOF
[email protected]9be804c82010-06-24 17:59:462326 };
2327
rch32320842015-05-16 15:57:092328 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472329
[email protected]262eec82013-03-19 21:01:362330 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502331 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472332 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572333 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472334 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462335
2336 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412337 TestCompletionCallback callback;
2338 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]9be804c82010-06-24 17:59:462339 EXPECT_EQ(ERR_IO_PENDING, rv);
2340 rv = callback.WaitForResult();
2341
2342 // Setup a user callback which will delete the session, and clear out the
2343 // memory holding the stream object. Note that the callback deletes trans.
[email protected]9be804c82010-06-24 17:59:462344 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162345 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412346 rv = trans->Read(
[email protected]90499482013-06-01 00:39:502347 buf.get(),
2348 kSize,
[email protected]513963e2013-06-15 01:53:042349 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
[email protected]49639fa2011-12-20 23:22:412350 base::Unretained(&helper)));
[email protected]9be804c82010-06-24 17:59:462351 ASSERT_EQ(ERR_IO_PENDING, rv);
mmenkee24011922015-12-17 22:12:592352 data.Resume();
[email protected]9be804c82010-06-24 17:59:462353
2354 // Finish running rest of tasks.
[email protected]fc9d88472013-08-14 02:31:172355 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472356 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462357}
2358
bncce36dca22015-04-21 22:11:232359// Send a spdy request to www.example.org that gets redirected to www.foo.com.
rchebf12982015-04-10 01:15:002360TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectGetRequest) {
[email protected]513963e2013-06-15 01:53:042361 scoped_ptr<SpdyHeaderBlock> headers(
rchebf12982015-04-10 01:15:002362 spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
[email protected]513963e2013-06-15 01:53:042363 (*headers)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062364 (*headers)["accept-encoding"] = "gzip, deflate";
[email protected]513963e2013-06-15 01:53:042365 scoped_ptr<SpdyHeaderBlock> headers2(
2366 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2367 (*headers2)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062368 (*headers2)["accept-encoding"] = "gzip, deflate";
[email protected]e3ebba0f2010-08-05 17:59:582369
bncce36dca22015-04-21 22:11:232370 // Setup writes/reads to www.example.org
[email protected]745aa9c2014-06-27 02:21:292371 scoped_ptr<SpdyFrame> req(
2372 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2373 scoped_ptr<SpdyFrame> req2(
2374 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042375 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
[email protected]e3ebba0f2010-08-05 17:59:582376 MockWrite writes[] = {
2377 CreateMockWrite(*req, 1),
2378 };
2379 MockRead reads[] = {
2380 CreateMockRead(*resp, 2),
[email protected]8ddf8322012-02-23 18:08:062381 MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582382 };
2383
2384 // Setup writes/reads to www.foo.com
[email protected]513963e2013-06-15 01:53:042385 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2386 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582387 MockWrite writes2[] = {
2388 CreateMockWrite(*req2, 1),
2389 };
2390 MockRead reads2[] = {
2391 CreateMockRead(*resp2, 2),
2392 CreateMockRead(*body2, 3),
[email protected]8ddf8322012-02-23 18:08:062393 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582394 };
rch08e3aa3e2015-05-16 14:27:522395 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2396 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2397 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582398
2399 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582400 TestDelegate d;
2401 {
rchebf12982015-04-10 01:15:002402 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
davidben151423e2015-03-23 18:48:362403 scoped_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002404 GURL(GetDefaultUrl()), DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092405 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572406 AddSocketDataProvider(&data);
[email protected]ef2bf422012-05-11 03:27:092407 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572408 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582409
2410 d.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192411 r->Start();
[email protected]fc9d88472013-08-14 02:31:172412 base::RunLoop().Run();
[email protected]513963e2013-06-15 01:53:042413
[email protected]e3ebba0f2010-08-05 17:59:582414 EXPECT_EQ(1, d.received_redirect_count());
2415
[email protected]f7022f32014-08-21 16:32:192416 r->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172417 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582418 EXPECT_EQ(1, d.response_started_count());
2419 EXPECT_FALSE(d.received_data_before_response());
bnc301745a2015-03-10 03:22:162420 EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582421 std::string contents("hello!");
2422 EXPECT_EQ(contents, d.data_received());
2423 }
rch37de576c2015-05-17 20:28:172424 EXPECT_TRUE(data.AllReadDataConsumed());
2425 EXPECT_TRUE(data.AllWriteDataConsumed());
2426 EXPECT_TRUE(data2.AllReadDataConsumed());
2427 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582428}
2429
bncce36dca22015-04-21 22:11:232430// Send a spdy request to www.example.org. Get a pushed stream that redirects to
[email protected]e3ebba0f2010-08-05 17:59:582431// www.foo.com.
rchebf12982015-04-10 01:15:002432TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
[email protected]513963e2013-06-15 01:53:042433 scoped_ptr<SpdyHeaderBlock> headers(
rchebf12982015-04-10 01:15:002434 spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
[email protected]513963e2013-06-15 01:53:042435 (*headers)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062436 (*headers)["accept-encoding"] = "gzip, deflate";
[email protected]3a8d6852011-03-11 23:43:442437
bncce36dca22015-04-21 22:11:232438 // Setup writes/reads to www.example.org
[email protected]ff98d7f02012-03-22 21:44:192439 scoped_ptr<SpdyFrame> req(
[email protected]745aa9c2014-06-27 02:21:292440 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042441 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002442 scoped_ptr<SpdyFrame> rep(spdy_util_.ConstructSpdyPush(
2443 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
2444 "301 Moved Permanently", "http://www.foo.com/index.php"));
[email protected]513963e2013-06-15 01:53:042445 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202446 scoped_ptr<SpdyFrame> rst(
2447 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]3a8d6852011-03-11 23:43:442448 MockWrite writes[] = {
2449 CreateMockWrite(*req, 1),
2450 CreateMockWrite(*rst, 6),
2451 };
2452 MockRead reads[] = {
2453 CreateMockRead(*resp, 2),
2454 CreateMockRead(*rep, 3),
2455 CreateMockRead(*body, 4),
[email protected]8ddf8322012-02-23 18:08:062456 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2457 MockRead(ASYNC, 0, 0, 7) // EOF
[email protected]3a8d6852011-03-11 23:43:442458 };
2459
2460 // Setup writes/reads to www.foo.com
[email protected]513963e2013-06-15 01:53:042461 scoped_ptr<SpdyHeaderBlock> headers2(
2462 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2463 (*headers2)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062464 (*headers2)["accept-encoding"] = "gzip, deflate";
[email protected]ff98d7f02012-03-22 21:44:192465 scoped_ptr<SpdyFrame> req2(
[email protected]745aa9c2014-06-27 02:21:292466 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042467 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2468 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582469 MockWrite writes2[] = {
2470 CreateMockWrite(*req2, 1),
2471 };
2472 MockRead reads2[] = {
2473 CreateMockRead(*resp2, 2),
2474 CreateMockRead(*body2, 3),
[email protected]8ddf8322012-02-23 18:08:062475 MockRead(ASYNC, 0, 0, 5) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582476 };
rch08e3aa3e2015-05-16 14:27:522477 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2478 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2479 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582480
2481 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582482 TestDelegate d;
2483 TestDelegate d2;
rchebf12982015-04-10 01:15:002484 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
[email protected]e3ebba0f2010-08-05 17:59:582485 {
davidben151423e2015-03-23 18:48:362486 scoped_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002487 GURL(GetDefaultUrl()), DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092488 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572489 AddSocketDataProvider(&data);
[email protected]e3ebba0f2010-08-05 17:59:582490
[email protected]f7022f32014-08-21 16:32:192491 r->Start();
[email protected]fc9d88472013-08-14 02:31:172492 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582493
2494 EXPECT_EQ(0, d.received_redirect_count());
2495 std::string contents("hello!");
2496 EXPECT_EQ(contents, d.data_received());
2497
davidben151423e2015-03-23 18:48:362498 scoped_ptr<URLRequest> r2(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002499 GURL(GetDefaultUrlWithPath("/foo.dat")), DEFAULT_PRIORITY, &d2));
[email protected]ef2bf422012-05-11 03:27:092500 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572501 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582502
2503 d2.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192504 r2->Start();
[email protected]fc9d88472013-08-14 02:31:172505 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582506 EXPECT_EQ(1, d2.received_redirect_count());
2507
[email protected]f7022f32014-08-21 16:32:192508 r2->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172509 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582510 EXPECT_EQ(1, d2.response_started_count());
2511 EXPECT_FALSE(d2.received_data_before_response());
bnc301745a2015-03-10 03:22:162512 EXPECT_EQ(URLRequestStatus::SUCCESS, r2->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582513 std::string contents2("hello!");
2514 EXPECT_EQ(contents2, d2.data_received());
2515 }
rch08e3aa3e2015-05-16 14:27:522516 EXPECT_TRUE(data.AllReadDataConsumed());
2517 EXPECT_TRUE(data.AllWriteDataConsumed());
2518 EXPECT_TRUE(data2.AllReadDataConsumed());
2519 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582520}
2521
[email protected]513963e2013-06-15 01:53:042522TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
[email protected]cdf8f7e72013-05-23 10:56:462523 scoped_ptr<SpdyFrame> stream1_syn(
2524 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042525 scoped_ptr<SpdyFrame> stream1_body(
2526 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582527 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522528 CreateMockWrite(*stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582529 };
2530
[email protected]ff98d7f02012-03-22 21:44:192531 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042532 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002533 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2534 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432535 const char kPushedData[] = "pushed";
2536 scoped_ptr<SpdyFrame> stream2_body(
2537 spdy_util_.ConstructSpdyBodyFrame(
2538 2, kPushedData, strlen(kPushedData), true));
[email protected]e3ebba0f2010-08-05 17:59:582539 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522540 CreateMockRead(*stream1_reply, 1),
2541 CreateMockRead(*stream2_syn, 2),
2542 CreateMockRead(*stream1_body, 3, SYNCHRONOUS),
2543 CreateMockRead(*stream2_body, 4),
2544 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582545 };
2546
2547 HttpResponseInfo response;
2548 HttpResponseInfo response2;
[email protected]19ec8a72010-08-23 03:38:232549 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522550 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572551 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032552 &response,
2553 &response2,
2554 expected_push_result);
[email protected]e3ebba0f2010-08-05 17:59:582555
2556 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502557 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022558 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582559
2560 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502561 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582562 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2563}
2564
[email protected]513963e2013-06-15 01:53:042565TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
[email protected]cdf8f7e72013-05-23 10:56:462566 scoped_ptr<SpdyFrame> stream1_syn(
2567 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042568 scoped_ptr<SpdyFrame> stream1_body(
2569 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]a5b8eb29d2012-03-06 06:19:462570 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522571 CreateMockWrite(*stream1_syn, 0),
[email protected]a5b8eb29d2012-03-06 06:19:462572 };
2573
[email protected]ff98d7f02012-03-22 21:44:192574 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042575 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002576 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2577 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432578 const char kPushedData[] = "pushed";
2579 scoped_ptr<SpdyFrame> stream2_body(
2580 spdy_util_.ConstructSpdyBodyFrame(
2581 2, kPushedData, strlen(kPushedData), true));
[email protected]a5b8eb29d2012-03-06 06:19:462582 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522583 CreateMockRead(*stream2_syn, 1),
2584 CreateMockRead(*stream1_reply, 2),
2585 CreateMockRead(*stream1_body, 3, SYNCHRONOUS),
2586 CreateMockRead(*stream2_body, 4),
2587 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]a5b8eb29d2012-03-06 06:19:462588 };
2589
2590 HttpResponseInfo response;
2591 HttpResponseInfo response2;
2592 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522593 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572594 RunServerPushTest(&data,
[email protected]a5b8eb29d2012-03-06 06:19:462595 &response,
2596 &response2,
2597 expected_push_result);
2598
2599 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502600 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022601 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]a5b8eb29d2012-03-06 06:19:462602
2603 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502604 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]a5b8eb29d2012-03-06 06:19:462605 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2606}
2607
[email protected]513963e2013-06-15 01:53:042608TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
[email protected]cdf8f7e72013-05-23 10:56:462609 scoped_ptr<SpdyFrame> stream1_syn(
2610 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:522611 MockWrite writes[] = {
2612 CreateMockWrite(*stream1_syn, 0),
2613 };
[email protected]82918cc2010-08-25 17:24:502614
[email protected]ff98d7f02012-03-22 21:44:192615 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042616 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002617 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2618 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432619 const char kPushedData[] = "pushed";
2620 scoped_ptr<SpdyFrame> stream2_body(
2621 spdy_util_.ConstructSpdyBodyFrame(
2622 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:192623 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042624 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]82918cc2010-08-25 17:24:502625 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522626 CreateMockRead(*stream1_reply, 1),
2627 CreateMockRead(*stream2_syn, 2),
2628 CreateMockRead(*stream2_body, 3),
2629 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2630 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]82918cc2010-08-25 17:24:502631 };
2632
2633 HttpResponseInfo response;
2634 HttpResponseInfo response2;
2635 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522636 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572637 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032638 &response,
2639 &response2,
2640 expected_push_result);
[email protected]82918cc2010-08-25 17:24:502641
2642 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502643 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022644 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]82918cc2010-08-25 17:24:502645
2646 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502647 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]82918cc2010-08-25 17:24:502648 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2649}
2650
[email protected]513963e2013-06-15 01:53:042651TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
[email protected]cdf8f7e72013-05-23 10:56:462652 scoped_ptr<SpdyFrame> stream1_syn(
2653 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042654 scoped_ptr<SpdyFrame> stream1_body(
2655 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582656 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522657 CreateMockWrite(*stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582658 };
2659
[email protected]ff98d7f02012-03-22 21:44:192660 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042661 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002662 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2663 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]c10b20852013-05-15 21:29:202664 scoped_ptr<SpdyFrame> stream2_rst(
2665 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582666 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522667 CreateMockRead(*stream1_reply, 1),
2668 CreateMockRead(*stream2_syn, 2),
2669 CreateMockRead(*stream2_rst, 3),
2670 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2671 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582672 };
2673
rch08e3aa3e2015-05-16 14:27:522674 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362675 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502676 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582677
2678 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572679 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582680
2681 HttpNetworkTransaction* trans = helper.trans();
2682
2683 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412684 TestCompletionCallback callback;
2685 int rv = trans->Start(
2686 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:582687 EXPECT_EQ(ERR_IO_PENDING, rv);
2688 rv = callback.WaitForResult();
[email protected]19ec8a72010-08-23 03:38:232689 EXPECT_EQ(OK, rv);
2690
2691 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522692 EXPECT_TRUE(data.AllReadDataConsumed());
2693 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]19ec8a72010-08-23 03:38:232694
2695 // Verify the SYN_REPLY.
2696 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502697 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022698 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232699}
2700
[email protected]8a0fc822013-06-27 20:52:432701// Verify that we don't leak streams and that we properly send a reset
2702// if the server pushes the same stream twice.
[email protected]513963e2013-06-15 01:53:042703TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
[email protected]cdf8f7e72013-05-23 10:56:462704 scoped_ptr<SpdyFrame> stream1_syn(
2705 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042706 scoped_ptr<SpdyFrame> stream1_body(
2707 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202708 scoped_ptr<SpdyFrame> stream3_rst(
2709 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
[email protected]fdc165a2010-09-03 03:51:292710 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522711 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream3_rst, 4),
[email protected]fdc165a2010-09-03 03:51:292712 };
2713
[email protected]ff98d7f02012-03-22 21:44:192714 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042715 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002716 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2717 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432718 const char kPushedData[] = "pushed";
2719 scoped_ptr<SpdyFrame> stream2_body(
2720 spdy_util_.ConstructSpdyBodyFrame(
2721 2, kPushedData, strlen(kPushedData), true));
rchebf12982015-04-10 01:15:002722 scoped_ptr<SpdyFrame> stream3_syn(spdy_util_.ConstructSpdyPush(
2723 NULL, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]fdc165a2010-09-03 03:51:292724 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522725 CreateMockRead(*stream1_reply, 1),
2726 CreateMockRead(*stream2_syn, 2),
2727 CreateMockRead(*stream3_syn, 3),
2728 CreateMockRead(*stream1_body, 5),
2729 CreateMockRead(*stream2_body, 6),
2730 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7), // Force a pause
[email protected]fdc165a2010-09-03 03:51:292731 };
2732
2733 HttpResponseInfo response;
2734 HttpResponseInfo response2;
2735 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522736 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572737 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032738 &response,
2739 &response2,
2740 expected_push_result);
[email protected]fdc165a2010-09-03 03:51:292741
2742 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502743 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022744 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]fdc165a2010-09-03 03:51:292745
2746 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502747 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]fdc165a2010-09-03 03:51:292748 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2749}
2750
[email protected]513963e2013-06-15 01:53:042751TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
[email protected]cdf8f7e72013-05-23 10:56:462752 scoped_ptr<SpdyFrame> stream1_syn(
2753 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042754 scoped_ptr<SpdyFrame> stream1_body(
2755 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232756 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522757 CreateMockWrite(*stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232758 };
2759
[email protected]ff98d7f02012-03-22 21:44:192760 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042761 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002762 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2763 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432764 static const char kPushedData[] = "pushed my darling hello my baby";
2765 scoped_ptr<SpdyFrame> stream2_body_base(
2766 spdy_util_.ConstructSpdyBodyFrame(
2767 2, kPushedData, strlen(kPushedData), true));
2768 const size_t kChunkSize = strlen(kPushedData) / 4;
2769 scoped_ptr<SpdyFrame> stream2_body1(
2770 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2771 scoped_ptr<SpdyFrame> stream2_body2(
2772 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2773 scoped_ptr<SpdyFrame> stream2_body3(
2774 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2775 kChunkSize, false));
2776 scoped_ptr<SpdyFrame> stream2_body4(
2777 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2778 stream2_body_base->size() - 3 * kChunkSize, false));
[email protected]19ec8a72010-08-23 03:38:232779 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522780 CreateMockRead(*stream1_reply, 1),
2781 CreateMockRead(*stream2_syn, 2),
2782 CreateMockRead(*stream2_body1, 3),
2783 CreateMockRead(*stream2_body2, 4),
2784 CreateMockRead(*stream2_body3, 5),
2785 CreateMockRead(*stream2_body4, 6),
2786 CreateMockRead(*stream1_body, 7, SYNCHRONOUS),
2787 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), // Force a pause
[email protected]19ec8a72010-08-23 03:38:232788 };
2789
2790 HttpResponseInfo response;
2791 HttpResponseInfo response2;
2792 std::string expected_push_result("pushed my darling hello my baby");
rch08e3aa3e2015-05-16 14:27:522793 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432794 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232795
2796 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502797 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022798 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232799
2800 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502801 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232802 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2803}
2804
[email protected]513963e2013-06-15 01:53:042805TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
[email protected]cdf8f7e72013-05-23 10:56:462806 scoped_ptr<SpdyFrame> stream1_syn(
2807 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042808 scoped_ptr<SpdyFrame> stream1_body(
2809 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232810 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522811 CreateMockWrite(*stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232812 };
2813
[email protected]ff98d7f02012-03-22 21:44:192814 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042815 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002816 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2817 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432818 static const char kPushedData[] = "pushed my darling hello my baby";
2819 scoped_ptr<SpdyFrame> stream2_body_base(
2820 spdy_util_.ConstructSpdyBodyFrame(
2821 2, kPushedData, strlen(kPushedData), true));
2822 const size_t kChunkSize = strlen(kPushedData) / 4;
2823 scoped_ptr<SpdyFrame> stream2_body1(
2824 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2825 scoped_ptr<SpdyFrame> stream2_body2(
2826 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2827 scoped_ptr<SpdyFrame> stream2_body3(
2828 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2829 kChunkSize, false));
2830 scoped_ptr<SpdyFrame> stream2_body4(
2831 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2832 stream2_body_base->size() - 3 * kChunkSize, false));
[email protected]19ec8a72010-08-23 03:38:232833 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522834 CreateMockRead(*stream1_reply, 1),
2835 CreateMockRead(*stream2_syn, 2),
2836 CreateMockRead(*stream2_body1, 3),
2837 CreateMockRead(*stream2_body2, 4),
2838 CreateMockRead(*stream2_body3, 5),
2839 CreateMockRead(*stream2_body4, 6),
2840 CreateMockRead(*stream1_body.get(), 7, SYNCHRONOUS),
2841 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8) // Force a pause.
[email protected]19ec8a72010-08-23 03:38:232842 };
2843
2844 HttpResponseInfo response;
2845 HttpResponseInfo response2;
rch08e3aa3e2015-05-16 14:27:522846 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432847 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232848
2849 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502850 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022851 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232852
2853 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502854 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232855 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2856}
2857
[email protected]513963e2013-06-15 01:53:042858TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
bncacac4f8a2015-06-18 12:24:492859 if (spdy_util_.spdy_version() == HTTP2) {
[email protected]0338bc62014-06-20 17:09:562860 // PUSH_PROMISE with stream id 0 is connection-level error.
2861 // TODO(baranovich): Test session going away.
[email protected]00b29472014-01-16 18:10:242862 return;
2863 }
[email protected]0338bc62014-06-20 17:09:562864
[email protected]cdf8f7e72013-05-23 10:56:462865 scoped_ptr<SpdyFrame> stream1_syn(
2866 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042867 scoped_ptr<SpdyFrame> stream1_body(
2868 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202869 scoped_ptr<SpdyFrame> stream2_rst(
2870 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]19ec8a72010-08-23 03:38:232871 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522872 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]19ec8a72010-08-23 03:38:232873 };
2874
[email protected]ff98d7f02012-03-22 21:44:192875 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042876 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002877 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2878 NULL, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]19ec8a72010-08-23 03:38:232879 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522880 CreateMockRead(*stream1_reply, 1),
2881 CreateMockRead(*stream2_syn, 2),
2882 CreateMockRead(*stream1_body, 4),
2883 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]19ec8a72010-08-23 03:38:232884 };
2885
rch08e3aa3e2015-05-16 14:27:522886 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362887 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502888 BoundNetLog(), GetParam(), NULL);
[email protected]19ec8a72010-08-23 03:38:232889
2890 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572891 helper.AddData(&data);
[email protected]19ec8a72010-08-23 03:38:232892
2893 HttpNetworkTransaction* trans = helper.trans();
2894
2895 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412896 TestCompletionCallback callback;
2897 int rv = trans->Start(
2898 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]19ec8a72010-08-23 03:38:232899 EXPECT_EQ(ERR_IO_PENDING, rv);
2900 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:582901 EXPECT_EQ(OK, rv);
2902
2903 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522904 EXPECT_TRUE(data.AllReadDataConsumed());
2905 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582906
2907 // Verify the SYN_REPLY.
2908 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502909 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022910 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582911}
2912
[email protected]513963e2013-06-15 01:53:042913TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
[email protected]cdf8f7e72013-05-23 10:56:462914 scoped_ptr<SpdyFrame> stream1_syn(
2915 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042916 scoped_ptr<SpdyFrame> stream1_body(
2917 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202918 scoped_ptr<SpdyFrame> stream2_rst(
2919 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
[email protected]e3ebba0f2010-08-05 17:59:582920 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522921 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582922 };
2923
[email protected]ff98d7f02012-03-22 21:44:192924 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042925 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002926 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2927 NULL, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]e3ebba0f2010-08-05 17:59:582928 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522929 CreateMockRead(*stream1_reply, 1),
2930 CreateMockRead(*stream2_syn, 2),
2931 CreateMockRead(*stream1_body, 4),
2932 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582933 };
2934
rch08e3aa3e2015-05-16 14:27:522935 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362936 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502937 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582938
2939 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572940 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582941
2942 HttpNetworkTransaction* trans = helper.trans();
2943
2944 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412945 TestCompletionCallback callback;
2946 int rv = trans->Start(
2947 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:582948 EXPECT_EQ(ERR_IO_PENDING, rv);
2949 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:582950 EXPECT_EQ(OK, rv);
2951
2952 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522953 EXPECT_TRUE(data.AllReadDataConsumed());
2954 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582955
2956 // Verify the SYN_REPLY.
2957 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502958 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022959 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582960}
2961
[email protected]513963e2013-06-15 01:53:042962TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
[email protected]cdf8f7e72013-05-23 10:56:462963 scoped_ptr<SpdyFrame> stream1_syn(
2964 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042965 scoped_ptr<SpdyFrame> stream1_body(
2966 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202967 scoped_ptr<SpdyFrame> stream2_rst(
2968 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582969 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522970 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582971 };
2972
[email protected]ff98d7f02012-03-22 21:44:192973 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042974 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8b9211d2013-06-24 05:54:452975 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
[email protected]8b9211d2013-06-24 05:54:452976 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
2977 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
bnc7ecc1122015-09-28 13:22:492978 (*incomplete_headers)["hello"] = "bye";
[email protected]0338bc62014-06-20 17:09:562979 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
dchengc7eeda422015-12-26 03:56:482980 std::move(incomplete_headers), 2, 1));
[email protected]e3ebba0f2010-08-05 17:59:582981 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522982 CreateMockRead(*stream1_reply, 1),
2983 CreateMockRead(*stream2_syn, 2),
2984 CreateMockRead(*stream1_body, 4),
2985 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582986 };
2987
rch08e3aa3e2015-05-16 14:27:522988 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362989 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502990 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582991
2992 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572993 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582994
2995 HttpNetworkTransaction* trans = helper.trans();
2996
2997 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412998 TestCompletionCallback callback;
2999 int rv = trans->Start(
3000 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:583001 EXPECT_EQ(ERR_IO_PENDING, rv);
3002 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583003 EXPECT_EQ(OK, rv);
rch08e3aa3e2015-05-16 14:27:523004
[email protected]e3ebba0f2010-08-05 17:59:583005 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:523006 EXPECT_TRUE(data.AllReadDataConsumed());
3007 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:583008
3009 // Verify the SYN_REPLY.
3010 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503011 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:023012 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:583013}
3014
[email protected]8b070372009-11-16 22:01:253015// Verify that various SynReply headers parse correctly through the
3016// HTTP layer.
[email protected]513963e2013-06-15 01:53:043017TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
[email protected]e7f75092010-07-01 22:39:133018 struct SynReplyHeadersTests {
3019 int num_headers;
3020 const char* extra_headers[5];
[email protected]513963e2013-06-15 01:53:043021 SpdyHeaderBlock expected_headers;
[email protected]8b070372009-11-16 22:01:253022 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133023 // This uses a multi-valued cookie header.
3024 { 2,
3025 { "cookie", "val1",
3026 "cookie", "val2", // will get appended separated by NULL
3027 NULL
3028 },
[email protected]8b070372009-11-16 22:01:253029 },
[email protected]e7f75092010-07-01 22:39:133030 // This is the minimalist set of headers.
3031 { 0,
3032 { NULL },
[email protected]8b070372009-11-16 22:01:253033 },
[email protected]e7f75092010-07-01 22:39:133034 // Headers with a comma separated list.
3035 { 1,
3036 { "cookie", "val1,val2",
3037 NULL
3038 },
[email protected]8b070372009-11-16 22:01:253039 }
3040 };
3041
[email protected]513963e2013-06-15 01:53:043042 test_cases[0].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043043 test_cases[1].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043044 test_cases[2].expected_headers["status"] = "200";
[email protected]601e03f12014-04-06 16:26:393045
bnc7ecc1122015-09-28 13:22:493046 // HTTP/2 eliminates use of the :version header.
bncacac4f8a2015-06-18 12:24:493047 if (spdy_util_.spdy_version() < HTTP2) {
[email protected]601e03f12014-04-06 16:26:393048 test_cases[0].expected_headers["version"] = "HTTP/1.1";
3049 test_cases[1].expected_headers["version"] = "HTTP/1.1";
3050 test_cases[2].expected_headers["version"] = "HTTP/1.1";
3051 }
[email protected]513963e2013-06-15 01:53:043052
bnc7ecc1122015-09-28 13:22:493053 test_cases[0].expected_headers["hello"] = "bye";
3054 test_cases[1].expected_headers["hello"] = "bye";
3055 test_cases[2].expected_headers["hello"] = "bye";
3056
3057 test_cases[0].expected_headers["cookie"] = StringPiece("val1\0val2", 9);
3058 test_cases[2].expected_headers["cookie"] = "val1,val2";
3059
viettrungluue4a8b882014-10-16 06:17:383060 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193061 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463062 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523063 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8b070372009-11-16 22:01:253064
[email protected]ff98d7f02012-03-22 21:44:193065 scoped_ptr<SpdyFrame> resp(
[email protected]513963e2013-06-15 01:53:043066 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
[email protected]2bd93022010-07-17 00:58:443067 test_cases[i].num_headers,
3068 1));
[email protected]513963e2013-06-15 01:53:043069 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:383070 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]8b070372009-11-16 22:01:253071 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523072 CreateMockRead(*resp, 1),
3073 CreateMockRead(*body, 2),
3074 MockRead(ASYNC, 0, 3) // EOF
[email protected]8b070372009-11-16 22:01:253075 };
3076
rch08e3aa3e2015-05-16 14:27:523077 SequencedSocketData data(reads, arraysize(reads), writes,
3078 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363079 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503080 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573081 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473082 TransactionHelperResult out = helper.output();
3083
[email protected]8b070372009-11-16 22:01:253084 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023085 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8b070372009-11-16 22:01:253086 EXPECT_EQ("hello!", out.response_data);
3087
3088 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3089 EXPECT_TRUE(headers.get() != NULL);
3090 void* iter = NULL;
[email protected]513963e2013-06-15 01:53:043091 std::string name, value;
3092 SpdyHeaderBlock header_block;
[email protected]8b070372009-11-16 22:01:253093 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
bnc7ecc1122015-09-28 13:22:493094 SpdyHeaderBlock::StringPieceProxy mutable_header_block_value =
3095 header_block[name];
3096 if (static_cast<StringPiece>(mutable_header_block_value).empty()) {
3097 mutable_header_block_value = value;
[email protected]513963e2013-06-15 01:53:043098 } else {
bnc7ecc1122015-09-28 13:22:493099 std::string joint_value = mutable_header_block_value.as_string();
3100 joint_value.append(1, '\0');
3101 joint_value.append(value);
3102 mutable_header_block_value = joint_value;
[email protected]513963e2013-06-15 01:53:043103 }
[email protected]8b070372009-11-16 22:01:253104 }
[email protected]513963e2013-06-15 01:53:043105 EXPECT_EQ(test_cases[i].expected_headers, header_block);
[email protected]8b070372009-11-16 22:01:253106 }
3107}
3108
[email protected]3f662f12010-03-25 19:56:123109// Verify that various SynReply headers parse vary fields correctly
3110// through the HTTP layer, and the response matches the request.
[email protected]513963e2013-06-15 01:53:043111TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
[email protected]3f662f12010-03-25 19:56:123112 // Modify the following data to change/add test cases:
3113 struct SynReplyTests {
[email protected]3f662f12010-03-25 19:56:123114 bool vary_matches;
3115 int num_headers[2];
3116 const char* extra_headers[2][16];
3117 } test_cases[] = {
bnc7ecc1122015-09-28 13:22:493118 // Test the case of a multi-valued cookie. When the value is delimited
3119 // with NUL characters, it needs to be unfolded into multiple headers.
3120 {true,
3121 {1, 4},
3122 {{"cookie", "val1,val2", NULL},
3123 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
3124 "/index.php", spdy_util_.GetVersionKey(), "HTTP/1.1", "vary", "cookie",
3125 NULL}}},
3126 {// Multiple vary fields.
3127 true,
3128 {2, 5},
3129 {{"friend", "barney", "enemy", "snaggletooth", NULL},
3130 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
3131 "/index.php", spdy_util_.GetVersionKey(), "HTTP/1.1", "vary", "friend",
3132 "vary", "enemy", NULL}}},
3133 {// Test a '*' vary field.
3134 false,
3135 {1, 4},
3136 {{"cookie", "val1,val2", NULL},
3137 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
3138 "/index.php", spdy_util_.GetVersionKey(), "HTTP/1.1", "vary", "*",
3139 NULL}}},
3140 {// Multiple comma-separated vary fields.
3141 true,
3142 {2, 4},
3143 {{"friend", "barney", "enemy", "snaggletooth", NULL},
3144 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
3145 "/index.php", spdy_util_.GetVersionKey(), "HTTP/1.1", "vary",
3146 "friend,enemy", NULL}}}};
[email protected]3f662f12010-03-25 19:56:123147
viettrungluue4a8b882014-10-16 06:17:383148 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]3f662f12010-03-25 19:56:123149 // Construct the request.
[email protected]ff98d7f02012-03-22 21:44:193150 scoped_ptr<SpdyFrame> frame_req(
[email protected]cdf8f7e72013-05-23 10:56:463151 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3152 test_cases[i].num_headers[0],
3153 false, 1, LOWEST, true));
[email protected]3f662f12010-03-25 19:56:123154
3155 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:523156 CreateMockWrite(*frame_req, 0),
[email protected]3f662f12010-03-25 19:56:123157 };
3158
3159 // Construct the reply.
[email protected]745aa9c2014-06-27 02:21:293160 SpdyHeaderBlock reply_headers;
3161 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3162 test_cases[i].num_headers[1],
3163 &reply_headers);
[email protected]ff98d7f02012-03-22 21:44:193164 scoped_ptr<SpdyFrame> frame_reply(
[email protected]745aa9c2014-06-27 02:21:293165 spdy_util_.ConstructSpdyReply(1, reply_headers));
[email protected]3f662f12010-03-25 19:56:123166
[email protected]513963e2013-06-15 01:53:043167 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:383168 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]3f662f12010-03-25 19:56:123169 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523170 CreateMockRead(*frame_reply, 1),
3171 CreateMockRead(*body, 2),
3172 MockRead(ASYNC, 0, 3) // EOF
[email protected]3f662f12010-03-25 19:56:123173 };
3174
[email protected]3f662f12010-03-25 19:56:123175 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:433176 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:123177
[email protected]d3cee19d2010-06-22 18:42:183178 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:433179 for (int ct = 0; ct < header_count; ct++) {
3180 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3181 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3182 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:123183 }
3184
rch08e3aa3e2015-05-16 14:27:523185 SequencedSocketData data(reads, arraysize(reads), writes,
3186 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363187 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503188 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573189 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473190 TransactionHelperResult out = helper.output();
3191
[email protected]3f662f12010-03-25 19:56:123192 EXPECT_EQ(OK, out.rv) << i;
bnc84e7fb52015-12-02 11:50:023193 EXPECT_EQ("HTTP/1.1 200", out.status_line) << i;
[email protected]3f662f12010-03-25 19:56:123194 EXPECT_EQ("hello!", out.response_data) << i;
3195
3196 // Test the response information.
[email protected]3f662f12010-03-25 19:56:123197 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3198 test_cases[i].vary_matches) << i;
3199
3200 // Check the headers.
3201 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3202 ASSERT_TRUE(headers.get() != NULL) << i;
3203 void* iter = NULL;
3204 std::string name, value, lines;
3205 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3206 lines.append(name);
3207 lines.append(": ");
3208 lines.append(value);
3209 lines.append("\n");
3210 }
3211
3212 // Construct the expected header reply string.
[email protected]9aa323192013-05-31 21:38:403213 std::string expected_reply =
3214 spdy_util_.ConstructSpdyReplyString(reply_headers);
3215 EXPECT_EQ(expected_reply, lines) << i;
[email protected]3f662f12010-03-25 19:56:123216 }
3217}
3218
[email protected]dd11b932009-11-30 19:39:483219// Verify that we don't crash on invalid SynReply responses.
[email protected]513963e2013-06-15 01:53:043220TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
[email protected]e7f75092010-07-01 22:39:133221 struct InvalidSynReplyTests {
3222 int num_headers;
3223 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:483224 } test_cases[] = {
bnc7ecc1122015-09-28 13:22:493225 // SYN_REPLY missing status header
3226 {
3227 4,
3228 {spdy_util_.GetPathKey(), "/index.php", spdy_util_.GetVersionKey(),
3229 "HTTP/1.1", "cookie", "val1", "cookie", "val2", NULL},
[email protected]e7f75092010-07-01 22:39:133230 },
bnc7ecc1122015-09-28 13:22:493231 // SYN_REPLY missing version header
3232 {
3233 2, {spdy_util_.GetPathKey(), "/index.php", "status", "200", NULL},
[email protected]e7f75092010-07-01 22:39:133234 },
bnc7ecc1122015-09-28 13:22:493235 // SYN_REPLY with no headers
3236 {
3237 0, {NULL},
3238 },
[email protected]dd11b932009-11-30 19:39:483239 };
3240
viettrungluue4a8b882014-10-16 06:17:383241 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193242 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463243 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:413244 scoped_ptr<SpdyFrame> rst(
3245 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
rdsmithebb50aa2015-11-12 03:44:383246 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dd11b932009-11-30 19:39:483247 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:523248 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
[email protected]dd11b932009-11-30 19:39:483249 };
3250
[email protected]745aa9c2014-06-27 02:21:293251 // Construct the reply.
3252 SpdyHeaderBlock reply_headers;
3253 AppendToHeaderBlock(
3254 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
3255 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
[email protected]dd11b932009-11-30 19:39:483256 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523257 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]dd11b932009-11-30 19:39:483258 };
3259
rch08e3aa3e2015-05-16 14:27:523260 SequencedSocketData data(reads, arraysize(reads), writes,
3261 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363262 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503263 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573264 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473265 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:413266 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]dd11b932009-11-30 19:39:483267 }
3268}
3269
[email protected]94d78132010-01-22 00:53:003270// Verify that we don't crash on some corrupt frames.
bncacac4f8a2015-06-18 12:24:493271// TODO(jgraettinger): HTTP/2 treats a header decompression failure as a
[email protected]e3352df2014-03-19 05:55:423272// connection error. I'd like to backport this behavior to SPDY3 as well.
[email protected]513963e2013-06-15 01:53:043273TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
bncacac4f8a2015-06-18 12:24:493274 if (spdy_util_.spdy_version() >= HTTP2) {
[email protected]e3352df2014-03-19 05:55:423275 return;
3276 }
[email protected]61c83f782011-01-27 21:00:243277 // This is the length field that's too short.
[email protected]ff98d7f02012-03-22 21:44:193278 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
[email protected]513963e2013-06-15 01:53:043279 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:043280 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]8a0fc822013-06-27 20:52:433281 size_t right_size =
bncacac4f8a2015-06-18 12:24:493282 (spdy_util_.spdy_version() < HTTP2)
3283 ? syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize()
3284 : syn_reply_wrong_length->size();
[email protected]8a0fc822013-06-27 20:52:433285 size_t wrong_size = right_size - 4;
[email protected]a4bfdf72013-02-22 04:06:163286 test::SetFrameLength(syn_reply_wrong_length.get(),
[email protected]8a0fc822013-06-27 20:52:433287 wrong_size,
[email protected]513963e2013-06-15 01:53:043288 spdy_util_.spdy_version());
[email protected]94d78132010-01-22 00:53:003289
3290 struct SynReplyTests {
[email protected]ff98d7f02012-03-22 21:44:193291 const SpdyFrame* syn_reply;
[email protected]94d78132010-01-22 00:53:003292 } test_cases[] = {
[email protected]61c83f782011-01-27 21:00:243293 { syn_reply_wrong_length.get(), },
[email protected]94d78132010-01-22 00:53:003294 };
3295
viettrungluue4a8b882014-10-16 06:17:383296 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193297 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463298 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]099bc7e2013-07-18 04:19:163299 scoped_ptr<SpdyFrame> rst(
3300 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3301 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:523302 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
[email protected]94d78132010-01-22 00:53:003303 };
3304
[email protected]513963e2013-06-15 01:53:043305 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003306 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523307 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size, 1),
3308 CreateMockRead(*body, 2),
3309 MockRead(ASYNC, 0, 4) // EOF
[email protected]94d78132010-01-22 00:53:003310 };
3311
rch08e3aa3e2015-05-16 14:27:523312 SequencedSocketData data(reads, arraysize(reads), writes,
3313 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363314 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503315 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573316 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473317 TransactionHelperResult out = helper.output();
[email protected]955fc2e72010-02-08 20:37:303318 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003319 }
3320}
3321
bncacac4f8a2015-06-18 12:24:493322// HTTP/2 treats a header decompression failure as a connection-level error.
[email protected]e3352df2014-03-19 05:55:423323TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
bncacac4f8a2015-06-18 12:24:493324 if (spdy_util_.spdy_version() < HTTP2) {
[email protected]e3352df2014-03-19 05:55:423325 return;
3326 }
3327 // This is the length field that's too short.
3328 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3329 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3330 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3331 size_t right_size =
[email protected]c143f2742014-03-31 00:48:543332 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
[email protected]e3352df2014-03-19 05:55:423333 size_t wrong_size = right_size - 4;
3334 test::SetFrameLength(syn_reply_wrong_length.get(),
3335 wrong_size,
3336 spdy_util_.spdy_version());
3337
[email protected]e3352df2014-03-19 05:55:423338 scoped_ptr<SpdyFrame> req(
3339 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bdd1b222014-06-10 11:08:393340 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3341 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch08e3aa3e2015-05-16 14:27:523342 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]e3352df2014-03-19 05:55:423343
3344 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3345 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523346 MockRead(ASYNC, syn_reply_wrong_length->data(),
3347 syn_reply_wrong_length->size() - 4, 1),
[email protected]e3352df2014-03-19 05:55:423348 };
3349
rch08e3aa3e2015-05-16 14:27:523350 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]e3352df2014-03-19 05:55:423351 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3352 BoundNetLog(), GetParam(), NULL);
3353 helper.RunToCompletion(&data);
3354 TransactionHelperResult out = helper.output();
[email protected]bdd1b222014-06-10 11:08:393355 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3356}
3357
3358TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
bnc9b79a572015-09-02 12:25:033359 if (GetParam().protocol < kProtoHTTP2) {
[email protected]bdd1b222014-06-10 11:08:393360 // Decompression failures are a stream error in SPDY3 and above.
3361 return;
3362 }
3363 scoped_ptr<SpdyFrame> req(
3364 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3365 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3366 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch08e3aa3e2015-05-16 14:27:523367 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393368
3369 // Read HEADERS with corrupted payload.
3370 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3371 memset(resp->data() + 12, 0xff, resp->size() - 12);
rch08e3aa3e2015-05-16 14:27:523372 MockRead reads[] = {CreateMockRead(*resp, 1)};
[email protected]bdd1b222014-06-10 11:08:393373
rch08e3aa3e2015-05-16 14:27:523374 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bdd1b222014-06-10 11:08:393375 NormalSpdyTransactionHelper helper(
3376 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3377 helper.RunToCompletion(&data);
3378 TransactionHelperResult out = helper.output();
3379 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3380}
3381
3382TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3383 scoped_ptr<SpdyFrame> req(
3384 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3385 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3386 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
rch08e3aa3e2015-05-16 14:27:523387 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393388
3389 // Read WINDOW_UPDATE with incorrectly-sized payload.
3390 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3391 // which is mapped to a protocol error, and not a frame size error.
3392 scoped_ptr<SpdyFrame> bad_window_update(
3393 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3394 test::SetFrameLength(bad_window_update.get(),
3395 bad_window_update->size() - 1,
3396 spdy_util_.spdy_version());
rch08e3aa3e2015-05-16 14:27:523397 MockRead reads[] = {CreateMockRead(*bad_window_update, 1)};
[email protected]bdd1b222014-06-10 11:08:393398
rch08e3aa3e2015-05-16 14:27:523399 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bdd1b222014-06-10 11:08:393400 NormalSpdyTransactionHelper helper(
3401 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3402 helper.RunToCompletion(&data);
3403 TransactionHelperResult out = helper.output();
[email protected]e3352df2014-03-19 05:55:423404 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3405}
3406
[email protected]bf2491a92009-11-29 16:39:483407// Test that we shutdown correctly on write errors.
[email protected]513963e2013-06-15 01:53:043408TEST_P(SpdyNetworkTransactionTest, WriteError) {
[email protected]cdf8f7e72013-05-23 10:56:463409 scoped_ptr<SpdyFrame> req(
3410 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483411 MockWrite writes[] = {
[email protected]bdd1b222014-06-10 11:08:393412 // We'll write 10 bytes successfully
mmenke666a6fea2015-12-19 04:16:333413 MockWrite(ASYNC, req->data(), 10, 1),
[email protected]bdd1b222014-06-10 11:08:393414 // Followed by ERROR!
[email protected]bdd1b222014-06-10 11:08:393415 MockWrite(ASYNC, ERR_FAILED, 2),
mmenke666a6fea2015-12-19 04:16:333416 // Session drains and attempts to write a GOAWAY: Another ERROR!
3417 MockWrite(ASYNC, ERR_FAILED, 3),
[email protected]bf2491a92009-11-29 16:39:483418 };
3419
mmenke666a6fea2015-12-19 04:16:333420 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
[email protected]238002d2013-10-17 02:01:403421
mmenke666a6fea2015-12-19 04:16:333422 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]238002d2013-10-17 02:01:403423
[email protected]262eec82013-03-19 21:01:363424 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503425 BoundNetLog(), GetParam(), NULL);
[email protected]238002d2013-10-17 02:01:403426 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:333427 helper.AddData(&data);
[email protected]238002d2013-10-17 02:01:403428 EXPECT_TRUE(helper.StartDefaultTest());
[email protected]238002d2013-10-17 02:01:403429 helper.FinishDefaultTest();
rch37de576c2015-05-17 20:28:173430 EXPECT_TRUE(data.AllWriteDataConsumed());
mmenke666a6fea2015-12-19 04:16:333431 EXPECT_TRUE(data.AllReadDataConsumed());
[email protected]3caf5542010-07-16 15:19:473432 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483433 EXPECT_EQ(ERR_FAILED, out.rv);
3434}
3435
3436// Test that partial writes work.
[email protected]513963e2013-06-15 01:53:043437TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
[email protected]bf2491a92009-11-29 16:39:483438 // Chop the SYN_STREAM frame into 5 chunks.
[email protected]cdf8f7e72013-05-23 10:56:463439 scoped_ptr<SpdyFrame> req(
3440 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483441 const int kChunks = 5;
[email protected]4356f0f2013-04-07 00:58:173442 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
rch08e3aa3e2015-05-16 14:27:523443 for (int i = 0; i < kChunks; ++i) {
3444 writes[i].sequence_number = i;
3445 }
[email protected]bf2491a92009-11-29 16:39:483446
[email protected]513963e2013-06-15 01:53:043447 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3448 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:483449 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523450 CreateMockRead(*resp, kChunks),
3451 CreateMockRead(*body, kChunks + 1),
3452 MockRead(ASYNC, 0, kChunks + 2) // EOF
[email protected]bf2491a92009-11-29 16:39:483453 };
3454
rch08e3aa3e2015-05-16 14:27:523455 SequencedSocketData data(reads, arraysize(reads), writes.get(), kChunks);
[email protected]262eec82013-03-19 21:01:363456 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503457 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573458 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473459 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483460 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023461 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bf2491a92009-11-29 16:39:483462 EXPECT_EQ("hello!", out.response_data);
3463}
3464
[email protected]94d78132010-01-22 00:53:003465// In this test, we enable compression, but get a uncompressed SynReply from
3466// the server. Verify that teardown is all clean.
[email protected]513963e2013-06-15 01:53:043467TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
bncacac4f8a2015-06-18 12:24:493468 if (spdy_util_.spdy_version() >= HTTP2) {
[email protected]e3352df2014-03-19 05:55:423469 // HPACK doesn't use deflate compression.
3470 return;
3471 }
[email protected]ff98d7f02012-03-22 21:44:193472 scoped_ptr<SpdyFrame> compressed(
[email protected]cdf8f7e72013-05-23 10:56:463473 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
[email protected]bdd1b222014-06-10 11:08:393474 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3475 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch08e3aa3e2015-05-16 14:27:523476 MockWrite writes[] = {CreateMockWrite(*compressed, 0),
3477 CreateMockWrite(*goaway, 2)};
[email protected]94d78132010-01-22 00:53:003478
[email protected]513963e2013-06-15 01:53:043479 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3480 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003481 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523482 CreateMockRead(*resp, 1),
[email protected]94d78132010-01-22 00:53:003483 };
3484
rch08e3aa3e2015-05-16 14:27:523485 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
rdsmith82957ad2015-09-16 19:42:033486 scoped_ptr<SpdySessionDependencies> session_deps =
[email protected]513963e2013-06-15 01:53:043487 CreateSpdySessionDependencies(GetParam());
[email protected]f9cf5572012-12-04 15:52:093488 session_deps->enable_compression = true;
[email protected]262eec82013-03-19 21:01:363489 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
rdsmith82957ad2015-09-16 19:42:033490 BoundNetLog(), GetParam(),
dchengc7eeda422015-12-26 03:56:483491 std::move(session_deps));
[email protected]dd54bd82012-07-19 23:44:573492 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473493 TransactionHelperResult out = helper.output();
[email protected]bdd1b222014-06-10 11:08:393494 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003495}
3496
[email protected]9e743cd2010-03-16 07:03:533497// Test that the NetLog contains good data for a simple GET request.
[email protected]513963e2013-06-15 01:53:043498TEST_P(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:403499 static const char* const kExtraHeaders[] = {
3500 "user-agent", "Chrome",
3501 };
[email protected]cdf8f7e72013-05-23 10:56:463502 scoped_ptr<SpdyFrame> req(
3503 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523504 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]dac358042009-12-18 02:07:483505
[email protected]513963e2013-06-15 01:53:043506 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3507 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]dac358042009-12-18 02:07:483508 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523509 CreateMockRead(*resp, 1),
3510 CreateMockRead(*body, 2),
3511 MockRead(ASYNC, 0, 3) // EOF
[email protected]dac358042009-12-18 02:07:483512 };
3513
vishal.b62985ca92015-04-17 08:45:513514 BoundTestNetLog log;
[email protected]dac358042009-12-18 02:07:483515
rch08e3aa3e2015-05-16 14:27:523516 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3deb9a52010-11-11 00:24:403517 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
[email protected]262eec82013-03-19 21:01:363518 DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503519 log.bound(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573520 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473521 TransactionHelperResult out = helper.output();
[email protected]dac358042009-12-18 02:07:483522 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023523 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]dac358042009-12-18 02:07:483524 EXPECT_EQ("hello!", out.response_data);
3525
[email protected]9e743cd2010-03-16 07:03:533526 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:473527 // This test is intentionally non-specific about the exact ordering of the
3528 // log; instead we just check to make sure that certain events exist, and that
3529 // they are in the right order.
mmenke43758e62015-05-04 21:09:463530 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403531 log.GetEntries(&entries);
3532
3533 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:483534 int pos = 0;
bnc301745a2015-03-10 03:22:163535 pos = ExpectLogContainsSomewhere(entries, 0,
3536 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3537 NetLog::PHASE_BEGIN);
3538 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3539 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3540 NetLog::PHASE_END);
3541 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3542 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3543 NetLog::PHASE_BEGIN);
3544 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3545 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3546 NetLog::PHASE_END);
3547 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3548 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3549 NetLog::PHASE_BEGIN);
3550 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3551 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3552 NetLog::PHASE_END);
[email protected]3deb9a52010-11-11 00:24:403553
3554 // Check that we logged all the headers correctly
bnc301745a2015-03-10 03:22:163555 const NetLog::EventType type = (GetParam().protocol <= kProtoSPDY31)
3556 ? NetLog::TYPE_HTTP2_SESSION_SYN_STREAM
3557 : NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS;
3558 pos = ExpectLogContainsSomewhere(entries, 0, type, NetLog::PHASE_NONE);
[email protected]3deb9a52010-11-11 00:24:403559
[email protected]ea5ef4c2013-06-13 22:50:273560 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:573561 ASSERT_TRUE(entries[pos].params.get());
3562 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3563
3564 std::vector<std::string> expected;
bncce36dca22015-04-21 22:11:233565 expected.push_back(std::string(spdy_util_.GetHostKey()) +
3566 ": www.example.org");
[email protected]513963e2013-06-15 01:53:043567 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
rchebf12982015-04-10 01:15:003568 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": " +
3569 spdy_util_.default_url().scheme());
[email protected]513963e2013-06-15 01:53:043570 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
[email protected]f3da152d2012-06-02 01:00:573571 expected.push_back("user-agent: Chrome");
bncacac4f8a2015-06-18 12:24:493572 if (spdy_util_.spdy_version() < HTTP2) {
3573 // HTTP/2 eliminates use of the :version header.
[email protected]601e03f12014-04-06 16:26:393574 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3575 }
[email protected]f3da152d2012-06-02 01:00:573576 EXPECT_EQ(expected.size(), header_list->GetSize());
3577 for (std::vector<std::string>::const_iterator it = expected.begin();
3578 it != expected.end();
3579 ++it) {
3580 base::StringValue header(*it);
3581 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3582 "Header not found: " << *it;
[email protected]3deb9a52010-11-11 00:24:403583 }
[email protected]dac358042009-12-18 02:07:483584}
3585
[email protected]79d84222010-02-26 00:01:443586// Since we buffer the IO from the stream to the renderer, this test verifies
3587// that when we read out the maximum amount of data (e.g. we received 50 bytes
3588// on the network, but issued a Read for only 5 of those bytes) that the data
3589// flow still works correctly.
[email protected]513963e2013-06-15 01:53:043590TEST_P(SpdyNetworkTransactionTest, BufferFull) {
[email protected]513963e2013-06-15 01:53:043591 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433592
[email protected]cdf8f7e72013-05-23 10:56:463593 scoped_ptr<SpdyFrame> req(
3594 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523595 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]79d84222010-02-26 00:01:443596
[email protected]20d005f2010-07-02 19:55:433597 // 2 data frames in a single read.
[email protected]ff98d7f02012-03-22 21:44:193598 scoped_ptr<SpdyFrame> data_frame_1(
3599 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3600 scoped_ptr<SpdyFrame> data_frame_2(
3601 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3602 const SpdyFrame* data_frames[2] = {
[email protected]20d005f2010-07-02 19:55:433603 data_frame_1.get(),
3604 data_frame_2.get(),
[email protected]79d84222010-02-26 00:01:443605 };
[email protected]20d005f2010-07-02 19:55:433606 char combined_data_frames[100];
3607 int combined_data_frames_len =
3608 CombineFrames(data_frames, arraysize(data_frames),
3609 combined_data_frames, arraysize(combined_data_frames));
[email protected]ff98d7f02012-03-22 21:44:193610 scoped_ptr<SpdyFrame> last_frame(
3611 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
[email protected]79d84222010-02-26 00:01:443612
[email protected]513963e2013-06-15 01:53:043613 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]79d84222010-02-26 00:01:443614 MockRead reads[] = {
rch32320842015-05-16 15:57:093615 CreateMockRead(*resp, 1),
3616 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3617 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3618 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
3619 CreateMockRead(*last_frame, 5),
3620 MockRead(ASYNC, 0, 6) // EOF
[email protected]79d84222010-02-26 00:01:443621 };
3622
rch32320842015-05-16 15:57:093623 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]79d84222010-02-26 00:01:443624
[email protected]49639fa2011-12-20 23:22:413625 TestCompletionCallback callback;
[email protected]79d84222010-02-26 00:01:443626
[email protected]262eec82013-03-19 21:01:363627 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503628 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473629 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573630 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473631 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413632 int rv = trans->Start(
3633 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]79d84222010-02-26 00:01:443634 EXPECT_EQ(ERR_IO_PENDING, rv);
3635
[email protected]3caf5542010-07-16 15:19:473636 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:443637 out.rv = callback.WaitForResult();
3638 EXPECT_EQ(out.rv, OK);
3639
3640 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503641 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]79d84222010-02-26 00:01:443642 EXPECT_TRUE(response->was_fetched_via_spdy);
3643 out.status_line = response->headers->GetStatusLine();
3644 out.response_info = *response; // Make a copy so we can verify.
3645
3646 // Read Data
[email protected]49639fa2011-12-20 23:22:413647 TestCompletionCallback read_callback;
[email protected]79d84222010-02-26 00:01:443648
3649 std::string content;
3650 do {
3651 // Read small chunks at a time.
3652 const int kSmallReadSize = 3;
bnc301745a2015-03-10 03:22:163653 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503654 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163655 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593656 data.Resume();
[email protected]79d84222010-02-26 00:01:443657 rv = read_callback.WaitForResult();
3658 }
3659 if (rv > 0) {
3660 content.append(buf->data(), rv);
3661 } else if (rv < 0) {
3662 NOTREACHED();
3663 }
3664 } while (rv > 0);
3665
3666 out.response_data.swap(content);
3667
[email protected]30c942b2010-07-21 16:59:593668 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553669 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173670 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553671
[email protected]79d84222010-02-26 00:01:443672 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473673 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:443674
3675 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023676 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]79d84222010-02-26 00:01:443677 EXPECT_EQ("goodbye world", out.response_data);
3678}
3679
[email protected]8918d282010-03-02 00:57:553680// Verify that basic buffering works; when multiple data frames arrive
3681// at the same time, ensure that we don't notify a read completion for
3682// each data frame individually.
[email protected]513963e2013-06-15 01:53:043683TEST_P(SpdyNetworkTransactionTest, Buffering) {
[email protected]513963e2013-06-15 01:53:043684 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433685
[email protected]cdf8f7e72013-05-23 10:56:463686 scoped_ptr<SpdyFrame> req(
3687 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch32320842015-05-16 15:57:093688 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8918d282010-03-02 00:57:553689
3690 // 4 data frames in a single read.
[email protected]ff98d7f02012-03-22 21:44:193691 scoped_ptr<SpdyFrame> data_frame(
3692 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3693 scoped_ptr<SpdyFrame> data_frame_fin(
3694 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3695 const SpdyFrame* data_frames[4] = {
[email protected]20d005f2010-07-02 19:55:433696 data_frame.get(),
3697 data_frame.get(),
3698 data_frame.get(),
3699 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:553700 };
[email protected]20d005f2010-07-02 19:55:433701 char combined_data_frames[100];
3702 int combined_data_frames_len =
3703 CombineFrames(data_frames, arraysize(data_frames),
3704 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:553705
[email protected]513963e2013-06-15 01:53:043706 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553707 MockRead reads[] = {
rch32320842015-05-16 15:57:093708 CreateMockRead(*resp, 1),
3709 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3710 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3711 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553712 };
3713
rch32320842015-05-16 15:57:093714 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553715
[email protected]262eec82013-03-19 21:01:363716 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503717 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473718 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573719 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473720 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553721
[email protected]49639fa2011-12-20 23:22:413722 TestCompletionCallback callback;
3723 int rv = trans->Start(
3724 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553725 EXPECT_EQ(ERR_IO_PENDING, rv);
3726
[email protected]3caf5542010-07-16 15:19:473727 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553728 out.rv = callback.WaitForResult();
3729 EXPECT_EQ(out.rv, OK);
3730
3731 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503732 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553733 EXPECT_TRUE(response->was_fetched_via_spdy);
3734 out.status_line = response->headers->GetStatusLine();
3735 out.response_info = *response; // Make a copy so we can verify.
3736
3737 // Read Data
[email protected]49639fa2011-12-20 23:22:413738 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553739
3740 std::string content;
3741 int reads_completed = 0;
3742 do {
3743 // Read small chunks at a time.
3744 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163745 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503746 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163747 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593748 data.Resume();
[email protected]8918d282010-03-02 00:57:553749 rv = read_callback.WaitForResult();
3750 }
3751 if (rv > 0) {
3752 EXPECT_EQ(kSmallReadSize, rv);
3753 content.append(buf->data(), rv);
3754 } else if (rv < 0) {
3755 FAIL() << "Unexpected read error: " << rv;
3756 }
3757 reads_completed++;
3758 } while (rv > 0);
3759
3760 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3761
3762 out.response_data.swap(content);
3763
[email protected]30c942b2010-07-21 16:59:593764 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553765 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173766 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553767
3768 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473769 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553770
3771 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023772 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:553773 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3774}
3775
3776// Verify the case where we buffer data but read it after it has been buffered.
[email protected]513963e2013-06-15 01:53:043777TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
[email protected]513963e2013-06-15 01:53:043778 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433779
[email protected]cdf8f7e72013-05-23 10:56:463780 scoped_ptr<SpdyFrame> req(
3781 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523782 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8918d282010-03-02 00:57:553783
[email protected]20d005f2010-07-02 19:55:433784 // 5 data frames in a single read.
[email protected]745aa9c2014-06-27 02:21:293785 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:193786 scoped_ptr<SpdyFrame> data_frame(
3787 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3788 scoped_ptr<SpdyFrame> data_frame_fin(
3789 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
[email protected]745aa9c2014-06-27 02:21:293790 const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
3791 data_frame.get(), data_frame_fin.get()};
[email protected]20d005f2010-07-02 19:55:433792 char combined_frames[200];
3793 int combined_frames_len =
3794 CombineFrames(frames, arraysize(frames),
3795 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:553796
3797 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523798 MockRead(ASYNC, combined_frames, combined_frames_len, 1),
3799 MockRead(ASYNC, 0, 2) // EOF
[email protected]8918d282010-03-02 00:57:553800 };
3801
rch08e3aa3e2015-05-16 14:27:523802 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553803
[email protected]262eec82013-03-19 21:01:363804 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503805 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473806 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573807 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473808 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553809
[email protected]49639fa2011-12-20 23:22:413810 TestCompletionCallback callback;
3811 int rv = trans->Start(
3812 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553813 EXPECT_EQ(ERR_IO_PENDING, rv);
3814
[email protected]3caf5542010-07-16 15:19:473815 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553816 out.rv = callback.WaitForResult();
3817 EXPECT_EQ(out.rv, OK);
3818
3819 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503820 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553821 EXPECT_TRUE(response->was_fetched_via_spdy);
3822 out.status_line = response->headers->GetStatusLine();
3823 out.response_info = *response; // Make a copy so we can verify.
3824
3825 // Read Data
[email protected]49639fa2011-12-20 23:22:413826 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553827
3828 std::string content;
3829 int reads_completed = 0;
3830 do {
3831 // Read small chunks at a time.
3832 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163833 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503834 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:553835 if (rv > 0) {
3836 EXPECT_EQ(kSmallReadSize, rv);
3837 content.append(buf->data(), rv);
3838 } else if (rv < 0) {
3839 FAIL() << "Unexpected read error: " << rv;
3840 }
3841 reads_completed++;
3842 } while (rv > 0);
3843
3844 EXPECT_EQ(3, reads_completed);
3845
3846 out.response_data.swap(content);
3847
[email protected]30c942b2010-07-21 16:59:593848 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553849 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173850 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553851
3852 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473853 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553854
3855 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023856 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:553857 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3858}
3859
3860// Verify the case where we buffer data and close the connection.
[email protected]513963e2013-06-15 01:53:043861TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
[email protected]513963e2013-06-15 01:53:043862 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433863
[email protected]cdf8f7e72013-05-23 10:56:463864 scoped_ptr<SpdyFrame> req(
3865 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch32320842015-05-16 15:57:093866 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8918d282010-03-02 00:57:553867
3868 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:433869 // NOTE: We don't FIN the stream.
[email protected]ff98d7f02012-03-22 21:44:193870 scoped_ptr<SpdyFrame> data_frame(
3871 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3872 const SpdyFrame* data_frames[4] = {
[email protected]20d005f2010-07-02 19:55:433873 data_frame.get(),
3874 data_frame.get(),
3875 data_frame.get(),
3876 data_frame.get()
[email protected]8918d282010-03-02 00:57:553877 };
[email protected]20d005f2010-07-02 19:55:433878 char combined_data_frames[100];
3879 int combined_data_frames_len =
3880 CombineFrames(data_frames, arraysize(data_frames),
3881 combined_data_frames, arraysize(combined_data_frames));
[email protected]513963e2013-06-15 01:53:043882 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553883 MockRead reads[] = {
rch32320842015-05-16 15:57:093884 CreateMockRead(*resp, 1),
3885 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3886 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3887 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553888 };
3889
rch32320842015-05-16 15:57:093890 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553891
[email protected]262eec82013-03-19 21:01:363892 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503893 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473894 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573895 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473896 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553897
[email protected]49639fa2011-12-20 23:22:413898 TestCompletionCallback callback;
[email protected]8918d282010-03-02 00:57:553899
[email protected]49639fa2011-12-20 23:22:413900 int rv = trans->Start(
3901 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553902 EXPECT_EQ(ERR_IO_PENDING, rv);
3903
[email protected]3caf5542010-07-16 15:19:473904 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553905 out.rv = callback.WaitForResult();
3906 EXPECT_EQ(out.rv, OK);
3907
3908 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503909 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553910 EXPECT_TRUE(response->was_fetched_via_spdy);
3911 out.status_line = response->headers->GetStatusLine();
3912 out.response_info = *response; // Make a copy so we can verify.
3913
3914 // Read Data
[email protected]49639fa2011-12-20 23:22:413915 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553916
3917 std::string content;
3918 int reads_completed = 0;
3919 do {
3920 // Read small chunks at a time.
3921 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163922 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503923 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163924 if (rv == ERR_IO_PENDING) {
mmenkee24011922015-12-17 22:12:593925 data.Resume();
[email protected]8918d282010-03-02 00:57:553926 rv = read_callback.WaitForResult();
3927 }
3928 if (rv > 0) {
3929 content.append(buf->data(), rv);
3930 } else if (rv < 0) {
3931 // This test intentionally closes the connection, and will get an error.
3932 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
3933 break;
3934 }
3935 reads_completed++;
3936 } while (rv > 0);
3937
3938 EXPECT_EQ(0, reads_completed);
3939
3940 out.response_data.swap(content);
3941
[email protected]30c942b2010-07-21 16:59:593942 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553943 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173944 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553945
3946 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473947 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553948}
3949
[email protected]1ed7b3dc2010-03-04 05:41:453950// Verify the case where we buffer data and cancel the transaction.
[email protected]513963e2013-06-15 01:53:043951TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
[email protected]513963e2013-06-15 01:53:043952 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433953
[email protected]cdf8f7e72013-05-23 10:56:463954 scoped_ptr<SpdyFrame> req(
3955 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]975da41a2014-06-05 03:36:243956 scoped_ptr<SpdyFrame> rst(
3957 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
rch32320842015-05-16 15:57:093958 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
[email protected]1ed7b3dc2010-03-04 05:41:453959
[email protected]20d005f2010-07-02 19:55:433960 // NOTE: We don't FIN the stream.
[email protected]ff98d7f02012-03-22 21:44:193961 scoped_ptr<SpdyFrame> data_frame(
3962 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
[email protected]1ed7b3dc2010-03-04 05:41:453963
[email protected]513963e2013-06-15 01:53:043964 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:453965 MockRead reads[] = {
rch32320842015-05-16 15:57:093966 CreateMockRead(*resp, 1),
3967 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3968 CreateMockRead(*data_frame, 3),
3969 MockRead(ASYNC, 0, 5) // EOF
[email protected]1ed7b3dc2010-03-04 05:41:453970 };
3971
rch32320842015-05-16 15:57:093972 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1ed7b3dc2010-03-04 05:41:453973
[email protected]262eec82013-03-19 21:01:363974 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503975 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473976 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573977 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473978 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413979 TestCompletionCallback callback;
[email protected]1ed7b3dc2010-03-04 05:41:453980
[email protected]49639fa2011-12-20 23:22:413981 int rv = trans->Start(
3982 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]1ed7b3dc2010-03-04 05:41:453983 EXPECT_EQ(ERR_IO_PENDING, rv);
3984
[email protected]3caf5542010-07-16 15:19:473985 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:453986 out.rv = callback.WaitForResult();
3987 EXPECT_EQ(out.rv, OK);
3988
3989 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503990 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]1ed7b3dc2010-03-04 05:41:453991 EXPECT_TRUE(response->was_fetched_via_spdy);
3992 out.status_line = response->headers->GetStatusLine();
3993 out.response_info = *response; // Make a copy so we can verify.
3994
3995 // Read Data
[email protected]49639fa2011-12-20 23:22:413996 TestCompletionCallback read_callback;
[email protected]1ed7b3dc2010-03-04 05:41:453997
[email protected]88c7b4be2014-03-19 23:04:013998 const int kReadSize = 256;
bnc301745a2015-03-10 03:22:163999 scoped_refptr<IOBuffer> buf(new IOBuffer(kReadSize));
[email protected]88c7b4be2014-03-19 23:04:014000 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:164001 ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
[email protected]88c7b4be2014-03-19 23:04:014002
4003 // Complete the read now, which causes buffering to start.
mmenkee24011922015-12-17 22:12:594004 data.Resume();
4005 base::RunLoop().RunUntilIdle();
[email protected]88c7b4be2014-03-19 23:04:014006 // Destroy the transaction, causing the stream to get cancelled
4007 // and orphaning the buffered IO task.
4008 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:454009
4010 // Flush the MessageLoop; this will cause the buffered IO task
4011 // to run for the final time.
[email protected]fc9d88472013-08-14 02:31:174012 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:474013
4014 // Verify that we consumed all test data.
4015 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:454016}
4017
[email protected]74188f22010-04-09 20:18:504018// Test that if the server requests persistence of settings, that we save
[email protected]18b28ab2012-04-18 02:14:424019// the settings in the HttpServerProperties.
[email protected]513963e2013-06-15 01:53:044020TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
bncacac4f8a2015-06-18 12:24:494021 if (spdy_util_.spdy_version() >= HTTP2) {
4022 // HTTP/2 doesn't support settings persistence.
[email protected]8a7bc7a2014-02-28 21:25:224023 return;
4024 }
[email protected]74188f22010-04-09 20:18:504025 static const SpdyHeaderInfo kSynReplyInfo = {
[email protected]ff98d7f02012-03-22 21:44:194026 SYN_REPLY, // Syn Reply
[email protected]e0935cc2012-03-24 14:12:484027 1, // Stream ID
4028 0, // Associated Stream ID
[email protected]513963e2013-06-15 01:53:044029 ConvertRequestPriorityToSpdyPriority(
4030 LOWEST, spdy_util_.spdy_version()),
[email protected]ff98d7f02012-03-22 21:44:194031 CONTROL_FLAG_NONE, // Control Flags
[email protected]e0935cc2012-03-24 14:12:484032 false, // Compressed
[email protected]5a7bb252013-02-09 00:21:054033 RST_STREAM_INVALID, // Status
[email protected]e0935cc2012-03-24 14:12:484034 NULL, // Data
4035 0, // Data Length
[email protected]ff98d7f02012-03-22 21:44:194036 DATA_FLAG_NONE // Data Flags
[email protected]74188f22010-04-09 20:18:504037 };
[email protected]74188f22010-04-09 20:18:504038
[email protected]c0168822011-12-10 01:24:274039 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364040 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4041 net_log, GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:584042 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504043
4044 // Verify that no settings exist initially.
bncce36dca22015-04-21 22:11:234045 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]102e27c2011-02-23 01:01:314046 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]53bfa31c2011-11-15 19:20:314047 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4048 host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504049
4050 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:464051 scoped_ptr<SpdyFrame> req(
4052 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524053 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]74188f22010-04-09 20:18:504054
4055 // Construct the reply.
[email protected]513963e2013-06-15 01:53:044056 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4057 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4058 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]ff98d7f02012-03-22 21:44:194059 scoped_ptr<SpdyFrame> reply(
dchengc7eeda422015-12-26 03:56:484060 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, std::move(reply_headers)));
[email protected]74188f22010-04-09 20:18:504061
[email protected]e0935cc2012-03-24 14:12:484062 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
[email protected]74188f22010-04-09 20:18:504063 unsigned int kSampleValue1 = 0x0a0a0a0a;
[email protected]e0935cc2012-03-24 14:12:484064 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
[email protected]74188f22010-04-09 20:18:504065 unsigned int kSampleValue2 = 0x0b0b0b0b;
[email protected]e0935cc2012-03-24 14:12:484066 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
[email protected]74188f22010-04-09 20:18:504067 unsigned int kSampleValue3 = 0x0c0c0c0c;
[email protected]ff98d7f02012-03-22 21:44:194068 scoped_ptr<SpdyFrame> settings_frame;
[email protected]74188f22010-04-09 20:18:504069 {
4070 // Construct the SETTINGS frame.
[email protected]18b28ab2012-04-18 02:14:424071 SettingsMap settings;
[email protected]e0935cc2012-03-24 14:12:484072 // First add a persisted setting.
[email protected]18b28ab2012-04-18 02:14:424073 settings[kSampleId1] =
4074 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
[email protected]e0935cc2012-03-24 14:12:484075 // Next add a non-persisted setting.
[email protected]18b28ab2012-04-18 02:14:424076 settings[kSampleId2] =
4077 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
[email protected]e0935cc2012-03-24 14:12:484078 // Next add another persisted setting.
[email protected]18b28ab2012-04-18 02:14:424079 settings[kSampleId3] =
4080 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
[email protected]c10b20852013-05-15 21:29:204081 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
[email protected]74188f22010-04-09 20:18:504082 }
4083
[email protected]513963e2013-06-15 01:53:044084 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504085 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524086 CreateMockRead(*reply, 1),
4087 CreateMockRead(*body, 2),
4088 CreateMockRead(*settings_frame, 3),
4089 MockRead(ASYNC, 0, 4) // EOF
[email protected]74188f22010-04-09 20:18:504090 };
4091
rch08e3aa3e2015-05-16 14:27:524092 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574093 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:584094 helper.RunDefaultTest();
4095 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474096 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504097 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:024098 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]74188f22010-04-09 20:18:504099 EXPECT_EQ("hello!", out.response_data);
4100
4101 {
4102 // Verify we had two persisted settings.
[email protected]e0935cc2012-03-24 14:12:484103 const SettingsMap& settings_map =
[email protected]53bfa31c2011-11-15 19:20:314104 spdy_session_pool->http_server_properties()->GetSpdySettings(
4105 host_port_pair);
[email protected]e0935cc2012-03-24 14:12:484106 ASSERT_EQ(2u, settings_map.size());
[email protected]74188f22010-04-09 20:18:504107
4108 // Verify the first persisted setting.
[email protected]e0935cc2012-03-24 14:12:484109 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4110 EXPECT_TRUE(it1 != settings_map.end());
4111 SettingsFlagsAndValue flags_and_value1 = it1->second;
4112 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4113 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
[email protected]74188f22010-04-09 20:18:504114
4115 // Verify the second persisted setting.
[email protected]e0935cc2012-03-24 14:12:484116 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4117 EXPECT_TRUE(it3 != settings_map.end());
4118 SettingsFlagsAndValue flags_and_value3 = it3->second;
4119 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4120 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
[email protected]74188f22010-04-09 20:18:504121 }
4122}
4123
4124// Test that when there are settings saved that they are sent back to the
4125// server upon session establishment.
[email protected]513963e2013-06-15 01:53:044126TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
bncacac4f8a2015-06-18 12:24:494127 if (spdy_util_.spdy_version() >= HTTP2) {
4128 // HTTP/2 doesn't support settings persistence.
[email protected]745aa9c2014-06-27 02:21:294129 return;
4130 }
[email protected]74188f22010-04-09 20:18:504131 static const SpdyHeaderInfo kSynReplyInfo = {
[email protected]ff98d7f02012-03-22 21:44:194132 SYN_REPLY, // Syn Reply
[email protected]e0935cc2012-03-24 14:12:484133 1, // Stream ID
4134 0, // Associated Stream ID
[email protected]513963e2013-06-15 01:53:044135 ConvertRequestPriorityToSpdyPriority(
4136 LOWEST, spdy_util_.spdy_version()),
[email protected]ff98d7f02012-03-22 21:44:194137 CONTROL_FLAG_NONE, // Control Flags
[email protected]e0935cc2012-03-24 14:12:484138 false, // Compressed
[email protected]5a7bb252013-02-09 00:21:054139 RST_STREAM_INVALID, // Status
[email protected]e0935cc2012-03-24 14:12:484140 NULL, // Data
4141 0, // Data Length
[email protected]ff98d7f02012-03-22 21:44:194142 DATA_FLAG_NONE // Data Flags
[email protected]74188f22010-04-09 20:18:504143 };
[email protected]74188f22010-04-09 20:18:504144
[email protected]c0168822011-12-10 01:24:274145 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364146 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4147 net_log, GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:584148 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504149
[email protected]b40f7fa2013-08-01 16:13:054150 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4151
4152 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4153 pool_peer.SetEnableSendingInitialData(true);
4154
[email protected]74188f22010-04-09 20:18:504155 // Verify that no settings exist initially.
bncce36dca22015-04-21 22:11:234156 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]53bfa31c2011-11-15 19:20:314157 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4158 host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504159
[email protected]c143f2742014-03-31 00:48:544160 const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
[email protected]74188f22010-04-09 20:18:504161 unsigned int kSampleValue1 = 0x0a0a0a0a;
[email protected]c143f2742014-03-31 00:48:544162 const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
[email protected]74188f22010-04-09 20:18:504163 unsigned int kSampleValue2 = 0x0c0c0c0c;
[email protected]74188f22010-04-09 20:18:504164
[email protected]e0935cc2012-03-24 14:12:484165 // First add a persisted setting.
4166 spdy_session_pool->http_server_properties()->SetSpdySetting(
4167 host_port_pair,
4168 kSampleId1,
4169 SETTINGS_FLAG_PLEASE_PERSIST,
4170 kSampleValue1);
4171
4172 // Next add another persisted setting.
4173 spdy_session_pool->http_server_properties()->SetSpdySetting(
4174 host_port_pair,
4175 kSampleId2,
4176 SETTINGS_FLAG_PLEASE_PERSIST,
4177 kSampleValue2);
[email protected]74188f22010-04-09 20:18:504178
[email protected]53bfa31c2011-11-15 19:20:314179 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4180 host_port_pair).size());
[email protected]74188f22010-04-09 20:18:504181
[email protected]b40f7fa2013-08-01 16:13:054182 // Construct the initial SETTINGS frame.
4183 SettingsMap initial_settings;
4184 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4185 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4186 scoped_ptr<SpdyFrame> initial_settings_frame(
4187 spdy_util_.ConstructSpdySettings(initial_settings));
4188
[email protected]b40f7fa2013-08-01 16:13:054189 // Construct the persisted SETTINGS frame.
[email protected]18b28ab2012-04-18 02:14:424190 const SettingsMap& settings =
[email protected]53bfa31c2011-11-15 19:20:314191 spdy_session_pool->http_server_properties()->GetSpdySettings(
4192 host_port_pair);
[email protected]c10b20852013-05-15 21:29:204193 scoped_ptr<SpdyFrame> settings_frame(
4194 spdy_util_.ConstructSpdySettings(settings));
[email protected]74188f22010-04-09 20:18:504195
4196 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:464197 scoped_ptr<SpdyFrame> req(
4198 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]74188f22010-04-09 20:18:504199
rch32320842015-05-16 15:57:094200 MockWrite writes[] = {
4201 CreateMockWrite(*initial_settings_frame, 0),
4202 CreateMockWrite(*settings_frame, 1),
4203 CreateMockWrite(*req, 2),
4204 };
[email protected]74188f22010-04-09 20:18:504205
4206 // Construct the reply.
[email protected]513963e2013-06-15 01:53:044207 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4208 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4209 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]ff98d7f02012-03-22 21:44:194210 scoped_ptr<SpdyFrame> reply(
dchengc7eeda422015-12-26 03:56:484211 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, std::move(reply_headers)));
[email protected]74188f22010-04-09 20:18:504212
[email protected]513963e2013-06-15 01:53:044213 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504214 MockRead reads[] = {
rch32320842015-05-16 15:57:094215 CreateMockRead(*reply, 3),
4216 CreateMockRead(*body, 4),
4217 MockRead(ASYNC, 0, 5) // EOF
[email protected]74188f22010-04-09 20:18:504218 };
4219
rch32320842015-05-16 15:57:094220 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574221 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:584222 helper.RunDefaultTest();
4223 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474224 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504225 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:024226 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]74188f22010-04-09 20:18:504227 EXPECT_EQ("hello!", out.response_data);
4228
4229 {
4230 // Verify we had two persisted settings.
[email protected]e0935cc2012-03-24 14:12:484231 const SettingsMap& settings_map =
[email protected]53bfa31c2011-11-15 19:20:314232 spdy_session_pool->http_server_properties()->GetSpdySettings(
4233 host_port_pair);
[email protected]e0935cc2012-03-24 14:12:484234 ASSERT_EQ(2u, settings_map.size());
[email protected]74188f22010-04-09 20:18:504235
4236 // Verify the first persisted setting.
[email protected]e0935cc2012-03-24 14:12:484237 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4238 EXPECT_TRUE(it1 != settings_map.end());
4239 SettingsFlagsAndValue flags_and_value1 = it1->second;
4240 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4241 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
[email protected]74188f22010-04-09 20:18:504242
4243 // Verify the second persisted setting.
[email protected]e0935cc2012-03-24 14:12:484244 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4245 EXPECT_TRUE(it2 != settings_map.end());
4246 SettingsFlagsAndValue flags_and_value2 = it2->second;
4247 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4248 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
[email protected]74188f22010-04-09 20:18:504249 }
4250}
4251
[email protected]513963e2013-06-15 01:53:044252TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
[email protected]cdf8f7e72013-05-23 10:56:464253 scoped_ptr<SpdyFrame> req(
4254 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524255 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]69d717bd2010-04-21 18:43:214256
[email protected]c10b20852013-05-15 21:29:204257 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:214258 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524259 CreateMockRead(*go_away, 1),
[email protected]58cebf8f2010-07-31 19:20:164260 };
4261
rch08e3aa3e2015-05-16 14:27:524262 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364263 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504264 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574265 helper.AddData(&data);
4266 helper.RunToCompletion(&data);
[email protected]58cebf8f2010-07-31 19:20:164267 TransactionHelperResult out = helper.output();
[email protected]c9336d22010-08-10 00:04:184268 EXPECT_EQ(ERR_ABORTED, out.rv);
[email protected]69d717bd2010-04-21 18:43:214269}
4270
[email protected]513963e2013-06-15 01:53:044271TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
[email protected]cdf8f7e72013-05-23 10:56:464272 scoped_ptr<SpdyFrame> req(
4273 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524274 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]f5ed21552010-05-04 18:39:544275
[email protected]513963e2013-06-15 01:53:044276 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f5ed21552010-05-04 18:39:544277 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524278 CreateMockRead(*resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
[email protected]f5ed21552010-05-04 18:39:544279 };
4280
rch08e3aa3e2015-05-16 14:27:524281 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]f5ed21552010-05-04 18:39:544282 BoundNetLog log;
[email protected]262eec82013-03-19 21:01:364283 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504284 log, GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474285 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574286 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474287 HttpNetworkTransaction* trans = helper.trans();
[email protected]f5ed21552010-05-04 18:39:544288
[email protected]49639fa2011-12-20 23:22:414289 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:474290 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414291 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
[email protected]3caf5542010-07-16 15:19:474292
[email protected]f5ed21552010-05-04 18:39:544293 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4294 out.rv = callback.WaitForResult();
4295 EXPECT_EQ(out.rv, OK);
4296
4297 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504298 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]f5ed21552010-05-04 18:39:544299 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]3caf5542010-07-16 15:19:474300 out.rv = ReadTransaction(trans, &out.response_data);
[email protected]f5ed21552010-05-04 18:39:544301 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4302
4303 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474304 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:544305}
[email protected]58cebf8f2010-07-31 19:20:164306
bnca7f994a2015-01-20 19:39:414307// HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4308TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredError) {
bncacac4f8a2015-06-18 12:24:494309 // HTTP_1_1_REQUIRED is only supported by HTTP/2.
4310 if (spdy_util_.spdy_version() < HTTP2)
bnca7f994a2015-01-20 19:39:414311 return;
4312
4313 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4314 BoundNetLog(), GetParam(), nullptr);
4315
4316 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4317 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4318 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524319 CreateMockRead(*go_away, 0),
bnca7f994a2015-01-20 19:39:414320 };
rch08e3aa3e2015-05-16 14:27:524321 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
bnca7f994a2015-01-20 19:39:414322
4323 helper.RunToCompletion(&data);
4324 TransactionHelperResult out = helper.output();
4325 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED, out.rv);
4326}
4327
bncfacdd852015-01-09 19:22:544328// Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4329// protocol negotiation happens, instead this test forces protocols for both
4330// sockets.
4331TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
bncacac4f8a2015-06-18 12:24:494332 // HTTP_1_1_REQUIRED is only supported by HTTP/2.
4333 if (spdy_util_.spdy_version() < HTTP2)
bncfacdd852015-01-09 19:22:544334 return;
4335 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4336 // only spoken over SSL.
rchebf12982015-04-10 01:15:004337 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
bncfacdd852015-01-09 19:22:544338 return;
4339
4340 HttpRequestInfo request;
4341 request.method = "GET";
bncce36dca22015-04-21 22:11:234342 request.url = GURL("https://www.example.org/");
bncfacdd852015-01-09 19:22:544343 scoped_ptr<SpdySessionDependencies> session_deps(
4344 CreateSpdySessionDependencies(GetParam()));
4345 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:544346 session_deps->next_protos = SpdyNextProtos();
4347 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
dchengc7eeda422015-12-26 03:56:484348 GetParam(), std::move(session_deps));
bncfacdd852015-01-09 19:22:544349
4350 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
rchebf12982015-04-10 01:15:004351 const char* url = request.url.spec().c_str();
bncfacdd852015-01-09 19:22:544352 scoped_ptr<SpdyHeaderBlock> headers(spdy_util_.ConstructGetHeaderBlock(url));
4353 scoped_ptr<SpdyFrame> req(
4354 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
rch08e3aa3e2015-05-16 14:27:524355 MockWrite writes0[] = {CreateMockWrite(*req, 0)};
bncfacdd852015-01-09 19:22:544356 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4357 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
rch08e3aa3e2015-05-16 14:27:524358 MockRead reads0[] = {CreateMockRead(*go_away, 1)};
4359 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4360 arraysize(writes0));
bncfacdd852015-01-09 19:22:544361
4362 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4363 new SSLSocketDataProvider(ASYNC, OK));
4364 // Expect HTTP/2 protocols too in SSLConfig.
4365 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4366 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
bnc06d22432015-06-29 12:39:434367 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
bncfacdd852015-01-09 19:22:544368 // Force SPDY.
4369 ssl_provider0->SetNextProto(GetParam().protocol);
dchengc7eeda422015-12-26 03:56:484370 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
bncfacdd852015-01-09 19:22:544371
4372 // Second socket: falling back to HTTP/1.1.
rch08e3aa3e2015-05-16 14:27:524373 MockWrite writes1[] = {MockWrite(ASYNC, 0,
4374 "GET / HTTP/1.1\r\n"
4375 "Host: www.example.org\r\n"
4376 "Connection: keep-alive\r\n\r\n")};
4377 MockRead reads1[] = {MockRead(ASYNC, 1,
4378 "HTTP/1.1 200 OK\r\n"
4379 "Content-Length: 5\r\n\r\n"
4380 "hello")};
4381 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4382 arraysize(writes1));
bncfacdd852015-01-09 19:22:544383
4384 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4385 new SSLSocketDataProvider(ASYNC, OK));
4386 // Expect only HTTP/1.1 protocol in SSLConfig.
4387 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4388 // Force HTTP/1.1.
4389 ssl_provider1->SetNextProto(kProtoHTTP11);
dchengc7eeda422015-12-26 03:56:484390 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
bncfacdd852015-01-09 19:22:544391
4392 base::WeakPtr<HttpServerProperties> http_server_properties =
4393 helper.session()->spdy_session_pool()->http_server_properties();
4394 const HostPortPair host_port_pair = HostPortPair::FromURL(GURL(url));
4395 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair));
4396
4397 helper.RunPreTestSetup();
4398 helper.StartDefaultTest();
4399 helper.FinishDefaultTestWithoutVerification();
4400 helper.VerifyDataConsumed();
4401 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair));
4402
4403 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4404 ASSERT_TRUE(response != nullptr);
4405 ASSERT_TRUE(response->headers.get() != nullptr);
4406 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4407 EXPECT_FALSE(response->was_fetched_via_spdy);
4408 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4409 EXPECT_TRUE(response->was_npn_negotiated);
4410 EXPECT_TRUE(request.url.SchemeIs("https"));
4411 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4412 EXPECT_EQ(443, response->socket_address.port());
4413 std::string response_data;
4414 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4415 EXPECT_EQ("hello", response_data);
4416}
4417
4418// Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4419// proxy. Note that no actual protocol negotiation happens, instead this test
4420// forces protocols for both sockets.
4421TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
bncacac4f8a2015-06-18 12:24:494422 // HTTP_1_1_REQUIRED is only supported by HTTP/2.
4423 if (spdy_util_.spdy_version() < HTTP2)
bncfacdd852015-01-09 19:22:544424 return;
4425 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4426 // only spoken over SSL.
rchebf12982015-04-10 01:15:004427 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
bncfacdd852015-01-09 19:22:544428 return;
4429
4430 HttpRequestInfo request;
4431 request.method = "GET";
bncce36dca22015-04-21 22:11:234432 request.url = GURL("https://www.example.org/");
bncfacdd852015-01-09 19:22:544433 scoped_ptr<SpdySessionDependencies> session_deps(
4434 CreateSpdySessionDependencies(
4435 GetParam(),
4436 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4437 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:544438 session_deps->next_protos = SpdyNextProtos();
4439 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
dchengc7eeda422015-12-26 03:56:484440 GetParam(), std::move(session_deps));
bncfacdd852015-01-09 19:22:544441
4442 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4443 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234444 nullptr, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
rch08e3aa3e2015-05-16 14:27:524445 MockWrite writes0[] = {CreateMockWrite(*req, 0)};
bncfacdd852015-01-09 19:22:544446 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4447 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
rch08e3aa3e2015-05-16 14:27:524448 MockRead reads0[] = {CreateMockRead(*go_away, 1)};
4449 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4450 arraysize(writes0));
bncfacdd852015-01-09 19:22:544451
4452 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4453 new SSLSocketDataProvider(ASYNC, OK));
4454 // Expect HTTP/2 protocols too in SSLConfig.
4455 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4456 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
bnc06d22432015-06-29 12:39:434457 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
bncfacdd852015-01-09 19:22:544458 // Force SPDY.
4459 ssl_provider0->SetNextProto(GetParam().protocol);
dchengc7eeda422015-12-26 03:56:484460 helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
bncfacdd852015-01-09 19:22:544461
4462 // Second socket: retry using HTTP/1.1.
4463 MockWrite writes1[] = {
rch08e3aa3e2015-05-16 14:27:524464 MockWrite(ASYNC, 0,
bncce36dca22015-04-21 22:11:234465 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174466 "Host: www.example.org:443\r\n"
bncfacdd852015-01-09 19:22:544467 "Proxy-Connection: keep-alive\r\n\r\n"),
rch08e3aa3e2015-05-16 14:27:524468 MockWrite(ASYNC, 2,
bncfacdd852015-01-09 19:22:544469 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:234470 "Host: www.example.org\r\n"
bncfacdd852015-01-09 19:22:544471 "Connection: keep-alive\r\n\r\n"),
4472 };
4473
4474 MockRead reads1[] = {
rch08e3aa3e2015-05-16 14:27:524475 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4476 MockRead(ASYNC, 3,
bncfacdd852015-01-09 19:22:544477 "HTTP/1.1 200 OK\r\n"
4478 "Content-Length: 5\r\n\r\n"
4479 "hello"),
4480 };
rch08e3aa3e2015-05-16 14:27:524481 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4482 arraysize(writes1));
bncfacdd852015-01-09 19:22:544483
4484 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4485 new SSLSocketDataProvider(ASYNC, OK));
4486 // Expect only HTTP/1.1 protocol in SSLConfig.
4487 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4488 // Force HTTP/1.1.
4489 ssl_provider1->SetNextProto(kProtoHTTP11);
dchengc7eeda422015-12-26 03:56:484490 helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
bncfacdd852015-01-09 19:22:544491
4492 // A third socket is needed for the tunnelled connection.
4493 scoped_ptr<SSLSocketDataProvider> ssl_provider2(
4494 new SSLSocketDataProvider(ASYNC, OK));
4495 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4496 ssl_provider2.get());
4497
4498 base::WeakPtr<HttpServerProperties> http_server_properties =
4499 helper.session()->spdy_session_pool()->http_server_properties();
4500 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
4501 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4502
4503 helper.RunPreTestSetup();
4504 helper.StartDefaultTest();
4505 helper.FinishDefaultTestWithoutVerification();
4506 helper.VerifyDataConsumed();
4507 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4508
4509 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4510 ASSERT_TRUE(response != nullptr);
4511 ASSERT_TRUE(response->headers.get() != nullptr);
4512 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4513 EXPECT_FALSE(response->was_fetched_via_spdy);
4514 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4515 EXPECT_FALSE(response->was_npn_negotiated);
4516 EXPECT_TRUE(request.url.SchemeIs("https"));
4517 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4518 EXPECT_EQ(70, response->socket_address.port());
4519 std::string response_data;
4520 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4521 EXPECT_EQ("hello", response_data);
4522}
4523
[email protected]b261d0e2010-08-02 19:13:244524// Test to make sure we can correctly connect through a proxy.
[email protected]513963e2013-06-15 01:53:044525TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
[email protected]262eec82013-03-19 21:01:364526 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504527 BoundNetLog(), GetParam(), NULL);
rdsmith82957ad2015-09-16 19:42:034528 helper.session_deps() = CreateSpdySessionDependencies(
4529 GetParam(), ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
mmenkee65e7af2015-10-13 17:16:424530 helper.SetSession(
4531 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get()));
[email protected]b261d0e2010-08-02 19:13:244532 helper.RunPreTestSetup();
4533 HttpNetworkTransaction* trans = helper.trans();
4534
rchebf12982015-04-10 01:15:004535 const char kConnect443[] = {
bncce36dca22015-04-21 22:11:234536 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174537 "Host: www.example.org:443\r\n"
rchcb934f562015-04-07 16:25:124538 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244539 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
[email protected]cdf8f7e72013-05-23 10:56:464540 scoped_ptr<SpdyFrame> req(
4541 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:044542 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4543 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244544
rchebf12982015-04-10 01:15:004545 MockWrite writes[] = {
4546 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4547 CreateMockWrite(*req, 2),
[email protected]b261d0e2010-08-02 19:13:244548 };
rchebf12982015-04-10 01:15:004549 MockRead reads[] = {
4550 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4551 CreateMockRead(*resp, 3),
4552 CreateMockRead(*body.get(), 4),
4553 MockRead(ASYNC, 0, 0, 5),
[email protected]b261d0e2010-08-02 19:13:244554 };
rch08e3aa3e2015-05-16 14:27:524555 scoped_ptr<SequencedSocketData> data(new SequencedSocketData(
rchebf12982015-04-10 01:15:004556 reads, arraysize(reads), writes, arraysize(writes)));
[email protected]b261d0e2010-08-02 19:13:244557
4558 helper.AddData(data.get());
[email protected]49639fa2011-12-20 23:22:414559 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244560
[email protected]49639fa2011-12-20 23:22:414561 int rv = trans->Start(
4562 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244563 EXPECT_EQ(ERR_IO_PENDING, rv);
4564
4565 rv = callback.WaitForResult();
4566 EXPECT_EQ(0, rv);
4567
4568 // Verify the SYN_REPLY.
4569 HttpResponseInfo response = *trans->GetResponseInfo();
rsleevidb16bb02015-11-12 23:47:174570 ASSERT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024571 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:244572
4573 std::string response_data;
4574 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4575 EXPECT_EQ("hello!", response_data);
4576 helper.VerifyDataConsumed();
4577}
4578
bncce36dca22015-04-21 22:11:234579// Test to make sure we can correctly connect through a proxy to
4580// www.example.org, if there already exists a direct spdy connection to
4581// www.example.org. See https://crbug.com/49874.
[email protected]513963e2013-06-15 01:53:044582TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
[email protected]b261d0e2010-08-02 19:13:244583 // When setting up the first transaction, we store the SpdySessionPool so that
4584 // we can use the same pool in the second transaction.
[email protected]262eec82013-03-19 21:01:364585 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504586 BoundNetLog(), GetParam(), NULL);
[email protected]733b7a6d2010-08-25 01:38:434587
4588 // Use a proxy service which returns a proxy fallback list from DIRECT to
4589 // myproxy:70. For this test there will be no fallback, so it is equivalent
4590 // to simply DIRECT. The reason for appending the second proxy is to verify
4591 // that the session pool key used does is just "DIRECT".
rdsmith82957ad2015-09-16 19:42:034592 helper.session_deps() = CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:044593 GetParam(),
rdsmith82957ad2015-09-16 19:42:034594 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70"));
mmenkee65e7af2015-10-13 17:16:424595 helper.SetSession(
4596 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get()));
[email protected]733b7a6d2010-08-25 01:38:434597
[email protected]87bfa3f2010-09-30 14:54:564598 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:244599 helper.RunPreTestSetup();
4600
4601 // Construct and send a simple GET request.
[email protected]cdf8f7e72013-05-23 10:56:464602 scoped_ptr<SpdyFrame> req(
4603 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b261d0e2010-08-02 19:13:244604 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:524605 CreateMockWrite(*req, 0),
[email protected]b261d0e2010-08-02 19:13:244606 };
4607
[email protected]513963e2013-06-15 01:53:044608 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4609 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244610 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524611 CreateMockRead(*resp, 1),
4612 CreateMockRead(*body, 2),
4613 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3), // Force a pause
[email protected]b261d0e2010-08-02 19:13:244614 };
rch08e3aa3e2015-05-16 14:27:524615 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574616 helper.AddData(&data);
[email protected]b261d0e2010-08-02 19:13:244617 HttpNetworkTransaction* trans = helper.trans();
4618
[email protected]49639fa2011-12-20 23:22:414619 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244620 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414621 out.rv = trans->Start(
4622 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244623
4624 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4625 out.rv = callback.WaitForResult();
4626 EXPECT_EQ(out.rv, OK);
4627
4628 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504629 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244630 EXPECT_TRUE(response->was_fetched_via_spdy);
4631 out.rv = ReadTransaction(trans, &out.response_data);
4632 EXPECT_EQ(OK, out.rv);
4633 out.status_line = response->headers->GetStatusLine();
bnc84e7fb52015-12-02 11:50:024634 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b261d0e2010-08-02 19:13:244635 EXPECT_EQ("hello!", out.response_data);
4636
4637 // Check that the SpdySession is still in the SpdySessionPool.
bncce36dca22015-04-21 22:11:234638 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]e6d017652013-05-17 18:01:404639 SpdySessionKey session_pool_key_direct(
[email protected]314b03992014-04-01 01:28:534640 host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264641 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
[email protected]e6d017652013-05-17 18:01:404642 SpdySessionKey session_pool_key_proxy(
[email protected]31e68d72010-08-25 06:36:584643 host_port_pair,
[email protected]e6d017652013-05-17 18:01:404644 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
[email protected]314b03992014-04-01 01:28:534645 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264646 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:244647
rdsmithebb50aa2015-11-12 03:44:384648 // New SpdyTestUtil instance for the session that will be used for the
4649 // proxy connection.
4650 SpdyTestUtil spdy_util_2(GetParam().protocol,
4651 GetParam().priority_to_dependency);
4652
[email protected]b261d0e2010-08-02 19:13:244653 // Set up data for the proxy connection.
bncce36dca22015-04-21 22:11:234654 const char kConnect443[] = {
4655 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174656 "Host: www.example.org:443\r\n"
bncce36dca22015-04-21 22:11:234657 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244658 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
rdsmithebb50aa2015-11-12 03:44:384659 scoped_ptr<SpdyFrame> req2(spdy_util_2.ConstructSpdyGet(
rchebf12982015-04-10 01:15:004660 GetDefaultUrlWithPath("/foo.dat").c_str(), false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:384661 scoped_ptr<SpdyFrame> resp2(spdy_util_2.ConstructSpdyGetSynReply(NULL, 0, 1));
4662 scoped_ptr<SpdyFrame> body2(spdy_util_2.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244663
rchebf12982015-04-10 01:15:004664 MockWrite writes2[] = {
4665 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4666 CreateMockWrite(*req2, 2),
[email protected]b261d0e2010-08-02 19:13:244667 };
rchebf12982015-04-10 01:15:004668 MockRead reads2[] = {
4669 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4670 CreateMockRead(*resp2, 3),
4671 CreateMockRead(*body2, 4),
4672 MockRead(ASYNC, 0, 5) // EOF
[email protected]b261d0e2010-08-02 19:13:244673 };
4674
rch08e3aa3e2015-05-16 14:27:524675 scoped_ptr<SequencedSocketData> data_proxy(new SequencedSocketData(
rchebf12982015-04-10 01:15:004676 reads2, arraysize(reads2), writes2, arraysize(writes2)));
[email protected]b261d0e2010-08-02 19:13:244677
bncce36dca22015-04-21 22:11:234678 // Create another request to www.example.org, but this time through a proxy.
[email protected]b261d0e2010-08-02 19:13:244679 HttpRequestInfo request_proxy;
4680 request_proxy.method = "GET";
rchebf12982015-04-10 01:15:004681 request_proxy.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
[email protected]b261d0e2010-08-02 19:13:244682 request_proxy.load_flags = 0;
[email protected]bb88e1d32013-05-03 23:11:074683 scoped_ptr<SpdySessionDependencies> ssd_proxy(
[email protected]513963e2013-06-15 01:53:044684 CreateSpdySessionDependencies(GetParam()));
[email protected]b261d0e2010-08-02 19:13:244685 // Ensure that this transaction uses the same SpdySessionPool.
mmenkee65e7af2015-10-13 17:16:424686 scoped_ptr<HttpNetworkSession> session_proxy(
[email protected]ad8e04a2010-11-01 04:16:274687 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
[email protected]262eec82013-03-19 21:01:364688 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504689 BoundNetLog(), GetParam(), NULL);
mmenkee65e7af2015-10-13 17:16:424690 HttpNetworkSessionPeer session_peer(session_proxy.get());
bnc301745a2015-03-10 03:22:164691 scoped_ptr<ProxyService> proxy_service(
4692 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
[email protected]6104ea5d2011-04-27 21:37:124693 session_peer.SetProxyService(proxy_service.get());
[email protected]b261d0e2010-08-02 19:13:244694 helper_proxy.session_deps().swap(ssd_proxy);
dchengc7eeda422015-12-26 03:56:484695 helper_proxy.SetSession(std::move(session_proxy));
[email protected]b261d0e2010-08-02 19:13:244696 helper_proxy.RunPreTestSetup();
4697 helper_proxy.AddData(data_proxy.get());
4698
4699 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
[email protected]49639fa2011-12-20 23:22:414700 TestCompletionCallback callback_proxy;
4701 int rv = trans_proxy->Start(
4702 &request_proxy, callback_proxy.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244703 EXPECT_EQ(ERR_IO_PENDING, rv);
4704 rv = callback_proxy.WaitForResult();
4705 EXPECT_EQ(0, rv);
4706
4707 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
rsleevidb16bb02015-11-12 23:47:174708 ASSERT_TRUE(response_proxy.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024709 EXPECT_EQ("HTTP/1.1 200", response_proxy.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:244710
4711 std::string response_data;
4712 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4713 EXPECT_EQ("hello!", response_data);
4714
[email protected]b261d0e2010-08-02 19:13:244715 helper_proxy.VerifyDataConsumed();
4716}
4717
[email protected]58cebf8f2010-07-31 19:20:164718// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4719// on a new connection, if the connection was previously known to be good.
4720// This can happen when a server reboots without saying goodbye, or when
4721// we're behind a NAT that masked the RST.
[email protected]513963e2013-06-15 01:53:044722TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
[email protected]513963e2013-06-15 01:53:044723 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4724 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]58cebf8f2010-07-31 19:20:164725 MockRead reads[] = {
rch32320842015-05-16 15:57:094726 CreateMockRead(*resp, 1),
4727 CreateMockRead(*body, 2),
4728 MockRead(ASYNC, ERR_IO_PENDING, 3),
4729 MockRead(ASYNC, ERR_CONNECTION_RESET, 4),
[email protected]58cebf8f2010-07-31 19:20:164730 };
4731
4732 MockRead reads2[] = {
rch32320842015-05-16 15:57:094733 CreateMockRead(*resp, 1),
4734 CreateMockRead(*body, 2),
4735 MockRead(ASYNC, 0, 3) // EOF
[email protected]58cebf8f2010-07-31 19:20:164736 };
4737
rchacdcbdc2015-05-16 17:16:004738 scoped_ptr<SpdyFrame> req(
4739 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:384740 // In all cases the connection will be reset before req3 can be
4741 // dispatched, destroying both streams.
4742 spdy_util_.UpdateWithStreamDestruction(1);
rchacdcbdc2015-05-16 17:16:004743 scoped_ptr<SpdyFrame> req3(
4744 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
4745 MockWrite writes1[] = {CreateMockWrite(*req, 0), CreateMockWrite(*req3, 5)};
4746 MockWrite writes2[] = {CreateMockWrite(*req, 0)};
4747
[email protected]58cebf8f2010-07-31 19:20:164748 // This test has a couple of variants.
4749 enum {
4750 // Induce the RST while waiting for our transaction to send.
rchacdcbdc2015-05-16 17:16:004751 VARIANT_RST_DURING_SEND_COMPLETION = 0,
[email protected]58cebf8f2010-07-31 19:20:164752 // Induce the RST while waiting for our transaction to read.
4753 // In this case, the send completed - everything copied into the SNDBUF.
rchacdcbdc2015-05-16 17:16:004754 VARIANT_RST_DURING_READ_COMPLETION = 1
[email protected]58cebf8f2010-07-31 19:20:164755 };
4756
4757 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4758 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4759 ++variant) {
rchacdcbdc2015-05-16 17:16:004760 SequencedSocketData data1(reads, arraysize(reads), writes1, 1 + variant);
[email protected]58cebf8f2010-07-31 19:20:164761
rchacdcbdc2015-05-16 17:16:004762 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
4763 arraysize(writes2));
[email protected]58cebf8f2010-07-31 19:20:164764
[email protected]262eec82013-03-19 21:01:364765 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504766 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574767 helper.AddData(&data1);
4768 helper.AddData(&data2);
[email protected]58cebf8f2010-07-31 19:20:164769 helper.RunPreTestSetup();
4770
4771 for (int i = 0; i < 2; ++i) {
4772 scoped_ptr<HttpNetworkTransaction> trans(
mmenkee65e7af2015-10-13 17:16:424773 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]58cebf8f2010-07-31 19:20:164774
[email protected]49639fa2011-12-20 23:22:414775 TestCompletionCallback callback;
4776 int rv = trans->Start(
4777 &helper.request(), callback.callback(), BoundNetLog());
[email protected]58cebf8f2010-07-31 19:20:164778 EXPECT_EQ(ERR_IO_PENDING, rv);
4779 // On the second transaction, we trigger the RST.
4780 if (i == 1) {
4781 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4782 // Writes to the socket complete asynchronously on SPDY by running
4783 // through the message loop. Complete the write here.
[email protected]fc9d88472013-08-14 02:31:174784 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164785 }
4786
4787 // Now schedule the ERR_CONNECTION_RESET.
mmenkee24011922015-12-17 22:12:594788 data1.Resume();
[email protected]58cebf8f2010-07-31 19:20:164789 }
4790 rv = callback.WaitForResult();
4791 EXPECT_EQ(OK, rv);
4792
4793 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]351ab642010-08-05 16:55:314794 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504795 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]58cebf8f2010-07-31 19:20:164796 EXPECT_TRUE(response->was_fetched_via_spdy);
4797 std::string response_data;
4798 rv = ReadTransaction(trans.get(), &response_data);
4799 EXPECT_EQ(OK, rv);
bnc84e7fb52015-12-02 11:50:024800 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]58cebf8f2010-07-31 19:20:164801 EXPECT_EQ("hello!", response_data);
rchacdcbdc2015-05-16 17:16:004802 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164803 }
4804
4805 helper.VerifyDataConsumed();
rchacdcbdc2015-05-16 17:16:004806 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164807 }
4808}
[email protected]1f418ee2010-10-16 19:46:564809
4810// Test that turning SPDY on and off works properly.
[email protected]513963e2013-06-15 01:53:044811TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
[email protected]d7599122014-05-24 03:37:234812 HttpStreamFactory::set_spdy_enabled(true);
[email protected]cdf8f7e72013-05-23 10:56:464813 scoped_ptr<SpdyFrame> req(
4814 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524815 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]1f418ee2010-10-16 19:46:564816
[email protected]513963e2013-06-15 01:53:044817 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4818 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1f418ee2010-10-16 19:46:564819 MockRead spdy_reads[] = {
rch08e3aa3e2015-05-16 14:27:524820 CreateMockRead(*resp, 1),
4821 CreateMockRead(*body, 2),
4822 MockRead(ASYNC, 0, 3) // EOF
[email protected]1f418ee2010-10-16 19:46:564823 };
4824
rch08e3aa3e2015-05-16 14:27:524825 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4826 arraysize(spdy_writes));
[email protected]262eec82013-03-19 21:01:364827 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504828 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574829 helper.RunToCompletion(&data);
[email protected]1f418ee2010-10-16 19:46:564830 TransactionHelperResult out = helper.output();
4831 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:024832 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1f418ee2010-10-16 19:46:564833 EXPECT_EQ("hello!", out.response_data);
4834
bnc301745a2015-03-10 03:22:164835 HttpStreamFactory::set_spdy_enabled(false);
rch08e3aa3e2015-05-16 14:27:524836 MockWrite http_writes[] = {
4837 MockWrite(SYNCHRONOUS, 0,
4838 "GET / HTTP/1.1\r\n"
4839 "Host: www.example.org\r\n"
4840 "Connection: keep-alive\r\n\r\n"),
rch73e17422015-05-04 19:52:064841 };
rch08e3aa3e2015-05-16 14:27:524842
4843 MockRead http_reads[] = {
4844 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4845 MockRead(SYNCHRONOUS, 2, "hello from http"),
4846 MockRead(SYNCHRONOUS, OK, 3),
4847 };
4848 SequencedSocketData data2(http_reads, arraysize(http_reads), http_writes,
4849 arraysize(http_writes));
[email protected]262eec82013-03-19 21:01:364850 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504851 BoundNetLog(), GetParam(), NULL);
[email protected]1f418ee2010-10-16 19:46:564852 helper2.SetSpdyDisabled();
[email protected]dd54bd82012-07-19 23:44:574853 helper2.RunToCompletion(&data2);
[email protected]1f418ee2010-10-16 19:46:564854 TransactionHelperResult out2 = helper2.output();
4855 EXPECT_EQ(OK, out2.rv);
4856 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4857 EXPECT_EQ("hello from http", out2.response_data);
4858
bnc301745a2015-03-10 03:22:164859 HttpStreamFactory::set_spdy_enabled(true);
[email protected]1f418ee2010-10-16 19:46:564860}
[email protected]018aabc2010-10-29 16:16:594861
4862// Tests that Basic authentication works over SPDY
[email protected]513963e2013-06-15 01:53:044863TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
bnc301745a2015-03-10 03:22:164864 HttpStreamFactory::set_spdy_enabled(true);
[email protected]018aabc2010-10-29 16:16:594865
4866 // The first request will be a bare GET, the second request will be a
4867 // GET with an Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194868 scoped_ptr<SpdyFrame> req_get(
[email protected]cdf8f7e72013-05-23 10:56:464869 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:384870 // Will be refused for lack of auth.
4871 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]018aabc2010-10-29 16:16:594872 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464873 "authorization", "Basic Zm9vOmJhcg=="
[email protected]018aabc2010-10-29 16:16:594874 };
[email protected]ff98d7f02012-03-22 21:44:194875 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464876 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4877 arraysize(kExtraAuthorizationHeaders) / 2,
4878 false, 3, LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594879 MockWrite spdy_writes[] = {
rch08e3aa3e2015-05-16 14:27:524880 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
[email protected]018aabc2010-10-29 16:16:594881 };
4882
4883 // The first response is a 401 authentication challenge, and the second
4884 // response will be a 200 response since the second request includes a valid
4885 // Authorization header.
4886 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:264887 "www-authenticate",
[email protected]018aabc2010-10-29 16:16:594888 "Basic realm=\"MyRealm\""
4889 };
[email protected]ff98d7f02012-03-22 21:44:194890 scoped_ptr<SpdyFrame> resp_authentication(
[email protected]513963e2013-06-15 01:53:044891 spdy_util_.ConstructSpdySynReplyError(
[email protected]018aabc2010-10-29 16:16:594892 "401 Authentication Required",
[email protected]d08358502010-12-03 22:04:034893 kExtraAuthenticationHeaders,
4894 arraysize(kExtraAuthenticationHeaders) / 2,
[email protected]018aabc2010-10-29 16:16:594895 1));
[email protected]ff98d7f02012-03-22 21:44:194896 scoped_ptr<SpdyFrame> body_authentication(
[email protected]513963e2013-06-15 01:53:044897 spdy_util_.ConstructSpdyBodyFrame(1, true));
4898 scoped_ptr<SpdyFrame> resp_data(
4899 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4900 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]018aabc2010-10-29 16:16:594901 MockRead spdy_reads[] = {
rch08e3aa3e2015-05-16 14:27:524902 CreateMockRead(*resp_authentication, 1),
4903 CreateMockRead(*body_authentication, 2),
4904 CreateMockRead(*resp_data, 4),
4905 CreateMockRead(*body_data, 5),
4906 MockRead(ASYNC, 0, 6),
[email protected]018aabc2010-10-29 16:16:594907 };
4908
rch08e3aa3e2015-05-16 14:27:524909 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4910 arraysize(spdy_writes));
[email protected]018aabc2010-10-29 16:16:594911 HttpRequestInfo request(CreateGetRequest());
4912 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364913 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
4914 net_log, GetParam(), NULL);
[email protected]018aabc2010-10-29 16:16:594915
4916 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574917 helper.AddData(&data);
[email protected]018aabc2010-10-29 16:16:594918 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:414919 TestCompletionCallback callback;
4920 const int rv_start = trans->Start(&request, callback.callback(), net_log);
[email protected]018aabc2010-10-29 16:16:594921 EXPECT_EQ(ERR_IO_PENDING, rv_start);
[email protected]49639fa2011-12-20 23:22:414922 const int rv_start_complete = callback.WaitForResult();
[email protected]018aabc2010-10-29 16:16:594923 EXPECT_EQ(OK, rv_start_complete);
4924
4925 // Make sure the response has an auth challenge.
4926 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4927 ASSERT_TRUE(response_start != NULL);
[email protected]90499482013-06-01 00:39:504928 ASSERT_TRUE(response_start->headers.get() != NULL);
[email protected]018aabc2010-10-29 16:16:594929 EXPECT_EQ(401, response_start->headers->response_code());
4930 EXPECT_TRUE(response_start->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044931 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
4932 ASSERT_TRUE(auth_challenge != NULL);
4933 EXPECT_FALSE(auth_challenge->is_proxy);
aberentbba302d2015-12-03 10:20:194934 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:044935 EXPECT_EQ("MyRealm", auth_challenge->realm);
[email protected]018aabc2010-10-29 16:16:594936
4937 // Restart with a username/password.
[email protected]ad65a3e2013-12-25 18:18:014938 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
4939 base::ASCIIToUTF16("bar"));
[email protected]49639fa2011-12-20 23:22:414940 TestCompletionCallback callback_restart;
4941 const int rv_restart = trans->RestartWithAuth(
4942 credentials, callback_restart.callback());
[email protected]018aabc2010-10-29 16:16:594943 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
4944 const int rv_restart_complete = callback_restart.WaitForResult();
4945 EXPECT_EQ(OK, rv_restart_complete);
4946 // TODO(cbentzel): This is actually the same response object as before, but
4947 // data has changed.
4948 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4949 ASSERT_TRUE(response_restart != NULL);
[email protected]90499482013-06-01 00:39:504950 ASSERT_TRUE(response_restart->headers.get() != NULL);
[email protected]018aabc2010-10-29 16:16:594951 EXPECT_EQ(200, response_restart->headers->response_code());
4952 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4953}
4954
[email protected]513963e2013-06-15 01:53:044955TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:464956 scoped_ptr<SpdyFrame> stream1_syn(
4957 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:044958 scoped_ptr<SpdyFrame> stream1_body(
4959 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:034960 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:524961 CreateMockWrite(*stream1_syn, 0),
[email protected]d08358502010-12-03 22:04:034962 };
4963
[email protected]513963e2013-06-15 01:53:044964 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:004965 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
4966 initial_headers.get());
dchengc7eeda422015-12-26 03:56:484967 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
4968 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:044969
4970 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
[email protected]513963e2013-06-15 01:53:044971 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
4972 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
bnc7ecc1122015-09-28 13:22:494973 (*late_headers)["hello"] = "bye";
dchengc7eeda422015-12-26 03:56:484974 scoped_ptr<SpdyFrame> stream2_headers(spdy_util_.ConstructSpdyControlFrame(
4975 std::move(late_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
4976 0));
[email protected]d08358502010-12-03 22:04:034977
[email protected]ff98d7f02012-03-22 21:44:194978 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:044979 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:434980 const char kPushedData[] = "pushed";
4981 scoped_ptr<SpdyFrame> stream2_body(
4982 spdy_util_.ConstructSpdyBodyFrame(
4983 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:034984 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524985 CreateMockRead(*stream1_reply, 1),
4986 CreateMockRead(*stream2_syn, 2),
4987 CreateMockRead(*stream2_headers, 3),
4988 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
4989 CreateMockRead(*stream2_body, 5),
4990 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]d08358502010-12-03 22:04:034991 };
4992
4993 HttpResponseInfo response;
4994 HttpResponseInfo response2;
4995 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:524996 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574997 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:034998 &response,
4999 &response2,
5000 expected_push_result);
5001
5002 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505003 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025004 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:035005
5006 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505007 EXPECT_TRUE(response2.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025008 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:035009}
5010
[email protected]513963e2013-06-15 01:53:045011TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
[email protected]d08358502010-12-03 22:04:035012 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465013 scoped_ptr<SpdyFrame> stream1_syn(
5014 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045015 scoped_ptr<SpdyFrame> stream1_body(
5016 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035017 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:065018 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:035019 };
5020
[email protected]513963e2013-06-15 01:53:045021 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005022 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5023 initial_headers.get());
dchengc7eeda422015-12-26 03:56:485024 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
5025 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:045026
5027 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
[email protected]513963e2013-06-15 01:53:045028 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5029 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
bnc7ecc1122015-09-28 13:22:495030 (*late_headers)["hello"] = "bye";
dchengc7eeda422015-12-26 03:56:485031 scoped_ptr<SpdyFrame> stream2_headers(spdy_util_.ConstructSpdyControlFrame(
5032 std::move(late_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
5033 0));
[email protected]d08358502010-12-03 22:04:035034
[email protected]ff98d7f02012-03-22 21:44:195035 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045036 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435037 const char kPushedData[] = "pushed";
5038 scoped_ptr<SpdyFrame> stream2_body(
5039 spdy_util_.ConstructSpdyBodyFrame(
5040 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035041 MockRead reads[] = {
mmenke666a6fea2015-12-19 04:16:335042 CreateMockRead(*stream1_reply, 1), CreateMockRead(*stream2_syn, 2),
5043 CreateMockRead(*stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
5044 CreateMockRead(*stream2_headers, 5), CreateMockRead(*stream2_body, 6),
5045 MockRead(ASYNC, ERR_IO_PENDING, 7), MockRead(ASYNC, 0, 8), // EOF
[email protected]d08358502010-12-03 22:04:035046 };
5047
5048 HttpResponseInfo response;
5049 HttpResponseInfo response2;
5050 std::string expected_push_result("pushed");
mmenke666a6fea2015-12-19 04:16:335051 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:035052
[email protected]262eec82013-03-19 21:01:365053 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505054 BoundNetLog(), GetParam(), NULL);
mmenke666a6fea2015-12-19 04:16:335055 helper.AddData(&data);
[email protected]d08358502010-12-03 22:04:035056 helper.RunPreTestSetup();
5057
5058 HttpNetworkTransaction* trans = helper.trans();
5059
[email protected]d08358502010-12-03 22:04:035060 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:415061 TestCompletionCallback callback;
5062 int rv = trans->Start(
5063 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035064 EXPECT_EQ(ERR_IO_PENDING, rv);
mmenke666a6fea2015-12-19 04:16:335065 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5066 // and the body of the primary stream, but before we've received the HEADERS
5067 // for the pushed stream.
5068 data.RunUntilPaused();
5069 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]d08358502010-12-03 22:04:035070
5071 // Request the pushed path. At this point, we've received the push, but the
5072 // headers are not yet complete.
5073 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:425074 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]49639fa2011-12-20 23:22:415075 rv = trans2->Start(
5076 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035077 EXPECT_EQ(ERR_IO_PENDING, rv);
mmenke666a6fea2015-12-19 04:16:335078 data.Resume();
5079 data.RunUntilPaused();
[email protected]fc9d88472013-08-14 02:31:175080 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:035081
5082 // Read the server push body.
5083 std::string result2;
rch0aecfd82015-05-19 17:22:325084 ReadResult(trans2.get(), &result2);
[email protected]d08358502010-12-03 22:04:035085 // Read the response body.
5086 std::string result;
rch0aecfd82015-05-19 17:22:325087 ReadResult(trans, &result);
[email protected]d08358502010-12-03 22:04:035088
[email protected]d08358502010-12-03 22:04:035089 // Verify that the received push data is same as the expected push data.
5090 EXPECT_EQ(result2.compare(expected_push_result), 0)
5091 << "Received data: "
5092 << result2
5093 << "||||| Expected data: "
5094 << expected_push_result;
5095
5096 // Verify the SYN_REPLY.
5097 // Copy the response info, because trans goes away.
5098 response = *trans->GetResponseInfo();
5099 response2 = *trans2->GetResponseInfo();
5100
5101 VerifyStreamsClosed(helper);
5102
5103 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505104 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025105 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:035106
5107 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505108 EXPECT_TRUE(response2.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025109 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d55b30a2012-07-21 00:35:395110
5111 // Read the final EOF (which will close the session)
mmenke666a6fea2015-12-19 04:16:335112 data.Resume();
5113 base::RunLoop().RunUntilIdle();
[email protected]d55b30a2012-07-21 00:35:395114
5115 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:175116 EXPECT_TRUE(data.AllReadDataConsumed());
5117 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:035118}
5119
[email protected]6cd63ba2014-06-12 16:14:565120// TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
[email protected]513963e2013-06-15 01:53:045121TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
[email protected]d08358502010-12-03 22:04:035122 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465123 scoped_ptr<SpdyFrame> stream1_syn(
5124 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045125 scoped_ptr<SpdyFrame> stream1_body(
5126 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035127 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:065128 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:035129 };
5130
[email protected]513963e2013-06-15 01:53:045131 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
bncacac4f8a2015-06-18 12:24:495132 if (spdy_util_.spdy_version() < HTTP2) {
5133 // In HTTP/2 PUSH_PROMISE headers won't show up in the response headers.
[email protected]0338bc62014-06-20 17:09:565134 (*initial_headers)["alpha"] = "beta";
5135 }
rchebf12982015-04-10 01:15:005136 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5137 initial_headers.get());
dchengc7eeda422015-12-26 03:56:485138 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
5139 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:045140
5141 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5142 (*middle_headers)["hello"] = "bye";
dchengc7eeda422015-12-26 03:56:485143 scoped_ptr<SpdyFrame> stream2_headers1(spdy_util_.ConstructSpdyControlFrame(
5144 std::move(middle_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
5145 0));
[email protected]513963e2013-06-15 01:53:045146
5147 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5148 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
bncacac4f8a2015-06-18 12:24:495149 if (spdy_util_.spdy_version() < HTTP2) {
5150 // HTTP/2 eliminates use of the :version header.
[email protected]601e03f12014-04-06 16:26:395151 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5152 }
dchengc7eeda422015-12-26 03:56:485153 scoped_ptr<SpdyFrame> stream2_headers2(spdy_util_.ConstructSpdyControlFrame(
5154 std::move(late_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
5155 0));
[email protected]d08358502010-12-03 22:04:035156
[email protected]ff98d7f02012-03-22 21:44:195157 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045158 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435159 const char kPushedData[] = "pushed";
5160 scoped_ptr<SpdyFrame> stream2_body(
5161 spdy_util_.ConstructSpdyBodyFrame(
5162 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035163 MockRead reads[] = {
mmenke666a6fea2015-12-19 04:16:335164 CreateMockRead(*stream1_reply, 1), CreateMockRead(*stream2_syn, 2),
5165 CreateMockRead(*stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
5166 CreateMockRead(*stream2_headers1, 5),
5167 // This is needed to work around https://crbug.com/571102.
5168 MockRead(ASYNC, ERR_IO_PENDING, 6), CreateMockRead(*stream2_headers2, 7),
5169 CreateMockRead(*stream2_body, 8), MockRead(ASYNC, ERR_IO_PENDING, 9),
5170 MockRead(ASYNC, 0, 10), // EOF
[email protected]d08358502010-12-03 22:04:035171 };
5172
5173 HttpResponseInfo response;
5174 HttpResponseInfo response2;
5175 std::string expected_push_result("pushed");
mmenke666a6fea2015-12-19 04:16:335176 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:035177
[email protected]262eec82013-03-19 21:01:365178 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505179 BoundNetLog(), GetParam(), NULL);
mmenke666a6fea2015-12-19 04:16:335180 helper.AddData(&data);
[email protected]d08358502010-12-03 22:04:035181 helper.RunPreTestSetup();
5182
5183 HttpNetworkTransaction* trans = helper.trans();
5184
[email protected]d08358502010-12-03 22:04:035185 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:415186 TestCompletionCallback callback;
5187 int rv = trans->Start(
5188 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035189 EXPECT_EQ(ERR_IO_PENDING, rv);
mmenke666a6fea2015-12-19 04:16:335190 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5191 // the first HEADERS frame, and the body of the primary stream, but before
5192 // we've received the final HEADERS for the pushed stream.
5193 data.RunUntilPaused();
5194 EXPECT_EQ(0, callback.WaitForResult());
[email protected]d08358502010-12-03 22:04:035195
5196 // Request the pushed path. At this point, we've received the push, but the
5197 // headers are not yet complete.
5198 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:425199 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]49639fa2011-12-20 23:22:415200 rv = trans2->Start(
5201 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035202 EXPECT_EQ(ERR_IO_PENDING, rv);
mmenke666a6fea2015-12-19 04:16:335203 data.Resume();
5204 data.RunUntilPaused();
5205 base::RunLoop().RunUntilIdle();
5206 // This is needed to work around https://crbug.com/571102.
5207 data.Resume();
5208 data.RunUntilPaused();
[email protected]fc9d88472013-08-14 02:31:175209 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:035210
5211 // Read the server push body.
5212 std::string result2;
rch0aecfd82015-05-19 17:22:325213 ReadResult(trans2.get(), &result2);
[email protected]d08358502010-12-03 22:04:035214 // Read the response body.
5215 std::string result;
rch0aecfd82015-05-19 17:22:325216 ReadResult(trans, &result);
[email protected]d08358502010-12-03 22:04:035217
[email protected]d08358502010-12-03 22:04:035218 // Verify that the received push data is same as the expected push data.
[email protected]6d116e1a2013-06-24 07:42:155219 EXPECT_EQ(expected_push_result, result2);
[email protected]d08358502010-12-03 22:04:035220
5221 // Verify the SYN_REPLY.
5222 // Copy the response info, because trans goes away.
5223 response = *trans->GetResponseInfo();
5224 response2 = *trans2->GetResponseInfo();
5225
5226 VerifyStreamsClosed(helper);
5227
5228 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505229 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025230 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:035231
5232 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505233 EXPECT_TRUE(response2.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025234 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:035235
[email protected]6cd63ba2014-06-12 16:14:565236 // Verify we got all the headers from all header blocks.
bncacac4f8a2015-06-18 12:24:495237 if (spdy_util_.spdy_version() < HTTP2)
[email protected]0338bc62014-06-20 17:09:565238 EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
[email protected]d08358502010-12-03 22:04:035239 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5240 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
[email protected]d55b30a2012-07-21 00:35:395241
5242 // Read the final EOF (which will close the session)
mmenke666a6fea2015-12-19 04:16:335243 data.Resume();
5244 base::RunLoop().RunUntilIdle();
[email protected]d55b30a2012-07-21 00:35:395245
5246 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:175247 EXPECT_TRUE(data.AllReadDataConsumed());
5248 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:035249}
5250
[email protected]513963e2013-06-15 01:53:045251TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
[email protected]5c6908e2012-08-06 18:53:475252 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465253 scoped_ptr<SpdyFrame> stream1_syn(
5254 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045255 scoped_ptr<SpdyFrame> stream1_body(
5256 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]5c6908e2012-08-06 18:53:475257 MockWrite writes[] = {
5258 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5259 };
5260
[email protected]513963e2013-06-15 01:53:045261 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005262 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5263 initial_headers.get());
dchengc7eeda422015-12-26 03:56:485264 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
5265 std::move(initial_headers), 2, 1));
[email protected]513963e2013-06-15 01:53:045266
5267 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5268 (*middle_headers)["hello"] = "bye";
dchengc7eeda422015-12-26 03:56:485269 scoped_ptr<SpdyFrame> stream2_headers1(spdy_util_.ConstructSpdyControlFrame(
5270 std::move(middle_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
5271 0));
[email protected]5c6908e2012-08-06 18:53:475272
5273 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045274 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435275 const char kPushedData[] = "pushed";
5276 scoped_ptr<SpdyFrame> stream2_body(
5277 spdy_util_.ConstructSpdyBodyFrame(
5278 2, kPushedData, strlen(kPushedData), true));
[email protected]5c6908e2012-08-06 18:53:475279 MockRead reads[] = {
mmenke666a6fea2015-12-19 04:16:335280 CreateMockRead(*stream1_reply, 1), CreateMockRead(*stream2_syn, 2),
5281 CreateMockRead(*stream1_body, 3), MockRead(ASYNC, ERR_IO_PENDING, 4),
5282 CreateMockRead(*stream2_headers1, 5), CreateMockRead(*stream2_body, 6),
5283 MockRead(ASYNC, ERR_IO_PENDING, 7), MockRead(ASYNC, 0, 8), // EOF
[email protected]5c6908e2012-08-06 18:53:475284 };
5285
mmenke666a6fea2015-12-19 04:16:335286 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]5c6908e2012-08-06 18:53:475287
[email protected]262eec82013-03-19 21:01:365288 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]5c6908e2012-08-06 18:53:475289 BoundNetLog(), GetParam(), NULL);
mmenke666a6fea2015-12-19 04:16:335290 helper.AddData(&data);
[email protected]5c6908e2012-08-06 18:53:475291 helper.RunPreTestSetup();
5292
5293 HttpNetworkTransaction* trans = helper.trans();
5294
[email protected]5c6908e2012-08-06 18:53:475295 // Start the transaction.
5296 TestCompletionCallback callback;
5297 int rv = trans->Start(
5298 &CreateGetRequest(), callback.callback(), BoundNetLog());
5299 EXPECT_EQ(ERR_IO_PENDING, rv);
mmenke666a6fea2015-12-19 04:16:335300 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5301 // the first HEADERS frame, and the body of the primary stream, but before
5302 // we've received the final HEADERS for the pushed stream.
5303 data.RunUntilPaused();
5304 EXPECT_EQ(0, callback.WaitForResult());
[email protected]5c6908e2012-08-06 18:53:475305
5306 // Request the pushed path. At this point, we've received the push, but the
5307 // headers are not yet complete.
5308 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:425309 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]5c6908e2012-08-06 18:53:475310 rv = trans2->Start(
5311 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5312 EXPECT_EQ(ERR_IO_PENDING, rv);
mmenke666a6fea2015-12-19 04:16:335313 data.Resume();
5314 data.RunUntilPaused();
[email protected]fc9d88472013-08-14 02:31:175315 base::RunLoop().RunUntilIdle();
[email protected]5c6908e2012-08-06 18:53:475316
5317 // Read the server push body.
5318 std::string result2;
rch0aecfd82015-05-19 17:22:325319 ReadResult(trans2.get(), &result2);
[email protected]5c6908e2012-08-06 18:53:475320 // Read the response body.
5321 std::string result;
rch0aecfd82015-05-19 17:22:325322 ReadResult(trans, &result);
[email protected]5c6908e2012-08-06 18:53:475323 EXPECT_EQ("hello!", result);
5324
5325 // Verify that we haven't received any push data.
5326 EXPECT_EQ("", result2);
5327
5328 // Verify the SYN_REPLY.
5329 // Copy the response info, because trans goes away.
5330 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]5c6908e2012-08-06 18:53:475331
5332 VerifyStreamsClosed(helper);
5333
5334 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505335 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025336 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]5c6908e2012-08-06 18:53:475337
5338 // Read the final EOF (which will close the session).
mmenke666a6fea2015-12-19 04:16:335339 data.Resume();
5340 base::RunLoop().RunUntilIdle();
[email protected]5c6908e2012-08-06 18:53:475341
5342 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:175343 EXPECT_TRUE(data.AllReadDataConsumed());
5344 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]5c6908e2012-08-06 18:53:475345}
5346
[email protected]513963e2013-06-15 01:53:045347TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:465348 scoped_ptr<SpdyFrame> req(
5349 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:415350 scoped_ptr<SpdyFrame> rst(
5351 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5352 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525353 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]745aa9c2014-06-27 02:21:295354 };
[email protected]d08358502010-12-03 22:04:035355
[email protected]4bd46222013-05-14 19:32:235356 scoped_ptr<SpdyFrame> stream1_reply(
[email protected]745aa9c2014-06-27 02:21:295357 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:045358
5359 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5360 (*late_headers)["hello"] = "bye";
dchengc7eeda422015-12-26 03:56:485361 scoped_ptr<SpdyFrame> stream1_headers(spdy_util_.ConstructSpdyControlFrame(
5362 std::move(late_headers), false, 1, LOWEST, HEADERS, CONTROL_FLAG_NONE,
5363 0));
[email protected]513963e2013-06-15 01:53:045364 scoped_ptr<SpdyFrame> stream1_body(
5365 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035366 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525367 CreateMockRead(*stream1_reply, 1),
5368 CreateMockRead(*stream1_headers, 2),
5369 CreateMockRead(*stream1_body, 3),
5370 MockRead(ASYNC, 0, 5) // EOF
[email protected]d08358502010-12-03 22:04:035371 };
5372
rch08e3aa3e2015-05-16 14:27:525373 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365374 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505375 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:575376 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035377 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:415378 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]d08358502010-12-03 22:04:035379}
5380
xunjieli294da722015-08-11 19:15:025381// Tests that receiving HEADERS, DATA, HEADERS, and DATA in that sequence will
5382// trigger a ERR_SPDY_PROTOCOL_ERROR because trailing HEADERS must not be
5383// followed by any DATA frames.
5384TEST_P(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) {
[email protected]cdf8f7e72013-05-23 10:56:465385 scoped_ptr<SpdyFrame> req(
5386 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:415387 scoped_ptr<SpdyFrame> rst(
5388 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5389 MockWrite writes[] = {
xunjieli294da722015-08-11 19:15:025390 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
[email protected]b771bb72013-06-24 09:55:415391 };
[email protected]d08358502010-12-03 22:04:035392
[email protected]4bd46222013-05-14 19:32:235393 scoped_ptr<SpdyFrame> stream1_reply(
[email protected]745aa9c2014-06-27 02:21:295394 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:045395
5396 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5397 (*late_headers)["hello"] = "bye";
dchengc7eeda422015-12-26 03:56:485398 scoped_ptr<SpdyFrame> stream1_headers(spdy_util_.ConstructSpdyControlFrame(
5399 std::move(late_headers), false, 1, LOWEST, HEADERS, CONTROL_FLAG_NONE,
5400 0));
[email protected]513963e2013-06-15 01:53:045401 scoped_ptr<SpdyFrame> stream1_body(
5402 spdy_util_.ConstructSpdyBodyFrame(1, false));
5403 scoped_ptr<SpdyFrame> stream1_body2(
5404 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035405 MockRead reads[] = {
xunjieli294da722015-08-11 19:15:025406 CreateMockRead(*stream1_reply, 1), CreateMockRead(*stream1_body, 2),
5407 CreateMockRead(*stream1_headers, 3), CreateMockRead(*stream1_body2, 4),
rch08e3aa3e2015-05-16 14:27:525408 MockRead(ASYNC, 0, 6) // EOF
[email protected]d08358502010-12-03 22:04:035409 };
5410
rch32320842015-05-16 15:57:095411 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365412 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505413 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:575414 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035415 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:415416 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]d08358502010-12-03 22:04:035417}
5418
[email protected]513963e2013-06-15 01:53:045419TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
rchebf12982015-04-10 01:15:005420 // Running these tests via Alt-Svc is too complicated to be worthwhile.
5421 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
5422 return;
5423
[email protected]a7a265ef2010-12-08 18:05:575424 // In this test we want to verify that we can't accidentally push content
5425 // which can't be pushed by this content server.
5426 // This test assumes that:
5427 // - if we're requesting http://www.foo.com/barbaz
5428 // - the browser has made a connection to "www.foo.com".
5429
5430 // A list of the URL to fetch, followed by the URL being pushed.
5431 static const char* const kTestCases[] = {
bncce36dca22015-04-21 22:11:235432 "https://www.example.org/foo.html",
5433 "https://www.example.org:81/foo.js", // Bad port
[email protected]a7a265ef2010-12-08 18:05:575434
bncce36dca22015-04-21 22:11:235435 "https://www.example.org/foo.html",
5436 "http://www.example.org/foo.js", // Bad protocol
[email protected]a7a265ef2010-12-08 18:05:575437
bncce36dca22015-04-21 22:11:235438 "https://www.example.org/foo.html",
5439 "ftp://www.example.org/foo.js", // Invalid Protocol
[email protected]a7a265ef2010-12-08 18:05:575440
bncce36dca22015-04-21 22:11:235441 "https://www.example.org/foo.html",
5442 "https://blat.www.example.org/foo.js", // Cross subdomain
[email protected]a7a265ef2010-12-08 18:05:575443
bncce36dca22015-04-21 22:11:235444 "https://www.example.org/foo.html",
rchebf12982015-04-10 01:15:005445 "https://www.foo.com/foo.js", // Cross domain
[email protected]a7a265ef2010-12-08 18:05:575446 };
5447
[email protected]b3f899332010-12-08 18:20:445448 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
[email protected]a7a265ef2010-12-08 18:05:575449 const char* url_to_fetch = kTestCases[index];
5450 const char* url_to_push = kTestCases[index + 1];
5451
[email protected]cdf8f7e72013-05-23 10:56:465452 scoped_ptr<SpdyFrame> stream1_syn(
5453 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
[email protected]513963e2013-06-15 01:53:045454 scoped_ptr<SpdyFrame> stream1_body(
5455 spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:385456 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]ff98d7f02012-03-22 21:44:195457 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:205458 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]a7a265ef2010-12-08 18:05:575459 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525460 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*push_rst, 3),
[email protected]a7a265ef2010-12-08 18:05:575461 };
5462
[email protected]ff98d7f02012-03-22 21:44:195463 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045464 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:195465 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045466 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5467 0,
5468 2,
5469 1,
5470 url_to_push));
[email protected]8a0fc822013-06-27 20:52:435471 const char kPushedData[] = "pushed";
5472 scoped_ptr<SpdyFrame> stream2_body(
5473 spdy_util_.ConstructSpdyBodyFrame(
5474 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:195475 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:205476 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]a7a265ef2010-12-08 18:05:575477
5478 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525479 CreateMockRead(*stream1_reply, 1),
5480 CreateMockRead(*stream2_syn, 2),
5481 CreateMockRead(*stream1_body, 4),
5482 CreateMockRead(*stream2_body, 5),
5483 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]a7a265ef2010-12-08 18:05:575484 };
5485
5486 HttpResponseInfo response;
rch08e3aa3e2015-05-16 14:27:525487 SequencedSocketData data(reads, arraysize(reads), writes,
5488 arraysize(writes));
[email protected]a7a265ef2010-12-08 18:05:575489
5490 HttpRequestInfo request;
5491 request.method = "GET";
5492 request.url = GURL(url_to_fetch);
5493 request.load_flags = 0;
[email protected]a7a265ef2010-12-08 18:05:575494
[email protected]7c6f7ba2012-04-03 04:09:295495 // Enable cross-origin push. Since we are not using a proxy, this should
5496 // not actually enable cross-origin SPDY push.
[email protected]61b4efc2012-04-27 18:12:505497 scoped_ptr<SpdySessionDependencies> session_deps(
[email protected]513963e2013-06-15 01:53:045498 CreateSpdySessionDependencies(GetParam()));
[email protected]61b4efc2012-04-27 18:12:505499 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
rdsmith82957ad2015-09-16 19:42:035500 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
dchengc7eeda422015-12-26 03:56:485501 GetParam(), std::move(session_deps));
[email protected]61b4efc2012-04-27 18:12:505502 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575503 helper.AddData(&data);
[email protected]7c6f7ba2012-04-03 04:09:295504
[email protected]a7a265ef2010-12-08 18:05:575505 HttpNetworkTransaction* trans = helper.trans();
5506
5507 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415508 TestCompletionCallback callback;
[email protected]a7a265ef2010-12-08 18:05:575509
[email protected]49639fa2011-12-20 23:22:415510 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]a7a265ef2010-12-08 18:05:575511 EXPECT_EQ(ERR_IO_PENDING, rv);
5512 rv = callback.WaitForResult();
5513
5514 // Read the response body.
5515 std::string result;
rch0aecfd82015-05-19 17:22:325516 ReadResult(trans, &result);
[email protected]a7a265ef2010-12-08 18:05:575517
5518 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:175519 EXPECT_TRUE(data.AllReadDataConsumed());
5520 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]a7a265ef2010-12-08 18:05:575521
5522 // Verify the SYN_REPLY.
5523 // Copy the response info, because trans goes away.
5524 response = *trans->GetResponseInfo();
5525
5526 VerifyStreamsClosed(helper);
5527
5528 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505529 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025530 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]a7a265ef2010-12-08 18:05:575531 }
5532}
5533
[email protected]513963e2013-06-15 01:53:045534TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
[email protected]721c0ce2011-10-13 02:41:005535 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:465536 scoped_ptr<SpdyFrame> req(
5537 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:385538 // Will be destroyed by the RST before stream 3 starts.
5539 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:465540 scoped_ptr<SpdyFrame> req2(
5541 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]721c0ce2011-10-13 02:41:005542 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525543 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 2),
[email protected]721c0ce2011-10-13 02:41:005544 };
5545
[email protected]ff98d7f02012-03-22 21:44:195546 scoped_ptr<SpdyFrame> refused(
[email protected]c10b20852013-05-15 21:29:205547 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
[email protected]513963e2013-06-15 01:53:045548 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5549 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]721c0ce2011-10-13 02:41:005550 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525551 CreateMockRead(*refused, 1),
5552 CreateMockRead(*resp, 3),
5553 CreateMockRead(*body, 4),
5554 MockRead(ASYNC, 0, 5) // EOF
[email protected]721c0ce2011-10-13 02:41:005555 };
5556
rch08e3aa3e2015-05-16 14:27:525557 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365558 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505559 BoundNetLog(), GetParam(), NULL);
[email protected]721c0ce2011-10-13 02:41:005560
5561 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575562 helper.AddData(&data);
[email protected]721c0ce2011-10-13 02:41:005563
5564 HttpNetworkTransaction* trans = helper.trans();
5565
5566 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415567 TestCompletionCallback callback;
5568 int rv = trans->Start(
5569 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]721c0ce2011-10-13 02:41:005570 EXPECT_EQ(ERR_IO_PENDING, rv);
5571 rv = callback.WaitForResult();
5572 EXPECT_EQ(OK, rv);
5573
5574 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:525575 EXPECT_TRUE(data.AllReadDataConsumed());
5576 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]721c0ce2011-10-13 02:41:005577
5578 // Verify the SYN_REPLY.
5579 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:505580 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025581 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]721c0ce2011-10-13 02:41:005582}
5583
[email protected]513963e2013-06-15 01:53:045584TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
[email protected]e1f58efa2012-05-15 18:23:405585 // This first request will start to establish the SpdySession.
5586 // Then we will start the second (MEDIUM priority) and then third
5587 // (HIGHEST priority) request in such a way that the third will actually
[email protected]c92f4b4542012-07-26 23:53:215588 // start before the second, causing the second to be numbered differently
[email protected]513963e2013-06-15 01:53:045589 // than the order they were created.
rdsmithebb50aa2015-11-12 03:44:385590 //
5591 // Note that the requests and responses created below are expectations
5592 // of what the above will produce on the wire, and hence are in the
5593 // initial->HIGHEST->LOWEST priority.
5594 //
5595 // Frames are created by SpdySession just before the write associated
5596 // with the frame is attempted, so stream dependencies will be based
5597 // on the streams alive at the point of the request write attempt. Thus
5598 // req1 is alive when req2 is attempted (during but not after the
5599 // |data.RunFor(2);| statement below) but not when req3 is attempted.
5600 // The call to spdy_util_.UpdateWithStreamDestruction() reflects this.
[email protected]cdf8f7e72013-05-23 10:56:465601 scoped_ptr<SpdyFrame> req1(
5602 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5603 scoped_ptr<SpdyFrame> req2(
5604 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
rdsmithebb50aa2015-11-12 03:44:385605 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:465606 scoped_ptr<SpdyFrame> req3(
5607 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
[email protected]e1f58efa2012-05-15 18:23:405608 MockWrite writes[] = {
mmenke666a6fea2015-12-19 04:16:335609 MockWrite(ASYNC, ERR_IO_PENDING, 0), CreateMockWrite(*req1, 1),
5610 CreateMockWrite(*req2, 5), CreateMockWrite(*req3, 6),
[email protected]e1f58efa2012-05-15 18:23:405611 };
5612
[email protected]513963e2013-06-15 01:53:045613 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5614 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5615 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5616 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5617 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5618 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]e1f58efa2012-05-15 18:23:405619 MockRead reads[] = {
mmenke666a6fea2015-12-19 04:16:335620 CreateMockRead(*resp1, 2), MockRead(ASYNC, ERR_IO_PENDING, 3),
5621 CreateMockRead(*body1, 4), CreateMockRead(*resp2, 7),
5622 CreateMockRead(*body2, 8), CreateMockRead(*resp3, 9),
5623 CreateMockRead(*body3, 10), MockRead(ASYNC, 0, 11) // EOF
[email protected]e1f58efa2012-05-15 18:23:405624 };
5625
mmenke666a6fea2015-12-19 04:16:335626 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365627 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
[email protected]e1f58efa2012-05-15 18:23:405628 BoundNetLog(), GetParam(), NULL);
[email protected]e1f58efa2012-05-15 18:23:405629 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:335630 helper.AddData(&data);
[email protected]e1f58efa2012-05-15 18:23:405631
5632 // Start the first transaction to set up the SpdySession
5633 HttpNetworkTransaction* trans = helper.trans();
5634 TestCompletionCallback callback;
5635 HttpRequestInfo info1 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405636 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
5637 EXPECT_EQ(ERR_IO_PENDING, rv);
5638
5639 // Run the message loop, but do not allow the write to complete.
5640 // This leaves the SpdySession with a write pending, which prevents
5641 // SpdySession from attempting subsequent writes until this write completes.
[email protected]fc9d88472013-08-14 02:31:175642 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405643
5644 // Now, start both new transactions
5645 HttpRequestInfo info2 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405646 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:505647 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:425648 new HttpNetworkTransaction(MEDIUM, helper.session()));
[email protected]e1f58efa2012-05-15 18:23:405649 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
5650 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:175651 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405652
5653 HttpRequestInfo info3 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405654 TestCompletionCallback callback3;
5655 scoped_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:425656 new HttpNetworkTransaction(HIGHEST, helper.session()));
[email protected]e1f58efa2012-05-15 18:23:405657 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5658 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:175659 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405660
5661 // We now have two SYN_STREAM frames queued up which will be
5662 // dequeued only once the first write completes, which we
5663 // now allow to happen.
mmenke666a6fea2015-12-19 04:16:335664 ASSERT_TRUE(data.IsPaused());
5665 data.Resume();
[email protected]e1f58efa2012-05-15 18:23:405666 EXPECT_EQ(OK, callback.WaitForResult());
5667
5668 // And now we can allow everything else to run to completion.
mmenke666a6fea2015-12-19 04:16:335669 data.Resume();
5670 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405671 EXPECT_EQ(OK, callback2.WaitForResult());
5672 EXPECT_EQ(OK, callback3.WaitForResult());
5673
5674 helper.VerifyDataConsumed();
5675}
5676
[email protected]d11b6912013-06-27 23:07:325677// The tests below are only for SPDY/3 and above.
5678
5679// Test that sent data frames and received WINDOW_UPDATE frames change
5680// the send_window_size_ correctly.
5681
5682// WINDOW_UPDATE is different than most other frames in that it can arrive
5683// while the client is still sending the request body. In order to enforce
5684// this scenario, we feed a couple of dummy frames and give a delay of 0 to
5685// socket data provider, so that initial read that is done as soon as the
5686// stream is created, succeeds and schedules another read. This way reads
5687// and writes are interleaved; after doing a full frame write, SpdyStream
5688// will break out of DoLoop and will read and process a WINDOW_UPDATE.
5689// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5690// since request has not been completely written, therefore we feed
5691// enough number of WINDOW_UPDATEs to finish the first read and cause a
5692// write, leading to a complete write of request body; after that we send
5693// a reply with a body, to cause a graceful shutdown.
5694
5695// TODO(agayev): develop a socket data provider where both, reads and
5696// writes are ordered so that writing tests like these are easy and rewrite
5697// all these tests using it. Right now we are working around the
5698// limitations as described above and it's not deterministic, tests may
5699// fail under specific circumstances.
5700TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
[email protected]d11b6912013-06-27 23:07:325701 static int kFrameCount = 2;
5702 scoped_ptr<std::string> content(
5703 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5704 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:005705 GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL,
5706 0));
[email protected]d11b6912013-06-27 23:07:325707 scoped_ptr<SpdyFrame> body(
5708 spdy_util_.ConstructSpdyBodyFrame(
5709 1, content->c_str(), content->size(), false));
5710 scoped_ptr<SpdyFrame> body_end(
5711 spdy_util_.ConstructSpdyBodyFrame(
5712 1, content->c_str(), content->size(), true));
5713
5714 MockWrite writes[] = {
5715 CreateMockWrite(*req, 0),
5716 CreateMockWrite(*body, 1),
5717 CreateMockWrite(*body_end, 2),
5718 };
5719
Avi Drissman13fc8932015-12-20 04:40:465720 static const int32_t kDeltaWindowSize = 0xff;
[email protected]d11b6912013-06-27 23:07:325721 static const int kDeltaCount = 4;
5722 scoped_ptr<SpdyFrame> window_update(
5723 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5724 scoped_ptr<SpdyFrame> window_update_dummy(
5725 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5726 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
5727 MockRead reads[] = {
mmenke666a6fea2015-12-19 04:16:335728 CreateMockRead(*window_update_dummy, 3),
5729 CreateMockRead(*window_update_dummy, 4),
5730 CreateMockRead(*window_update_dummy, 5),
5731 CreateMockRead(*window_update, 6), // Four updates, therefore window
5732 CreateMockRead(*window_update, 7), // size should increase by
5733 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
5734 CreateMockRead(*window_update, 9), CreateMockRead(*resp, 10),
5735 MockRead(ASYNC, ERR_IO_PENDING, 11), CreateMockRead(*body_end, 12),
5736 MockRead(ASYNC, 0, 13) // EOF
[email protected]d11b6912013-06-27 23:07:325737 };
5738
mmenke666a6fea2015-12-19 04:16:335739 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d11b6912013-06-27 23:07:325740
olli.raula6df48b2a2015-11-26 07:40:225741 std::vector<scoped_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:325742 for (int i = 0; i < kFrameCount; ++i) {
olli.raula6df48b2a2015-11-26 07:40:225743 element_readers.push_back(make_scoped_ptr(
5744 new UploadBytesElementReader(content->c_str(), content->size())));
[email protected]d11b6912013-06-27 23:07:325745 }
olli.raula6df48b2a2015-11-26 07:40:225746 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325747
5748 // Setup the request
5749 HttpRequestInfo request;
5750 request.method = "POST";
rchebf12982015-04-10 01:15:005751 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:325752 request.upload_data_stream = &upload_data_stream;
5753
5754 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5755 BoundNetLog(), GetParam(), NULL);
mmenke666a6fea2015-12-19 04:16:335756 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:325757 helper.RunPreTestSetup();
5758
5759 HttpNetworkTransaction* trans = helper.trans();
5760
5761 TestCompletionCallback callback;
5762 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5763
5764 EXPECT_EQ(ERR_IO_PENDING, rv);
5765
mmenke666a6fea2015-12-19 04:16:335766 data.RunUntilPaused();
5767 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325768
5769 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5770 ASSERT_TRUE(stream != NULL);
5771 ASSERT_TRUE(stream->stream() != NULL);
bnc638c4702015-04-09 18:01:185772 EXPECT_EQ(static_cast<int>(
5773 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol)) +
5774 kDeltaWindowSize * kDeltaCount -
5775 kMaxSpdyFrameChunkSize * kFrameCount,
5776 stream->stream()->send_window_size());
[email protected]d11b6912013-06-27 23:07:325777
mmenke666a6fea2015-12-19 04:16:335778 data.Resume();
5779 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325780
5781 rv = callback.WaitForResult();
5782 EXPECT_EQ(OK, rv);
5783
5784 helper.VerifyDataConsumed();
5785}
5786
5787// Test that received data frames and sent WINDOW_UPDATE frames change
5788// the recv_window_size_ correctly.
5789TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
Avi Drissman13fc8932015-12-20 04:40:465790 const int32_t default_initial_window_size =
bnc638c4702015-04-09 18:01:185791 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
bnc8f0f3b62015-04-08 04:37:235792 // Session level maximum window size that is more than twice the default
5793 // initial window size so that an initial window update is sent.
Avi Drissman13fc8932015-12-20 04:40:465794 const int32_t session_max_recv_window_size = 5 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:235795 ASSERT_LT(2 * default_initial_window_size, session_max_recv_window_size);
5796 // Stream level maximum window size that is less than the session level
5797 // maximum window size so that we test for confusion between the two.
Avi Drissman13fc8932015-12-20 04:40:465798 const int32_t stream_max_recv_window_size = 4 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:235799 ASSERT_GT(session_max_recv_window_size, stream_max_recv_window_size);
5800 // Size of body to be sent. Has to be less than or equal to both window sizes
5801 // so that we do not run out of receiving window. Also has to be greater than
5802 // half of them so that it triggers both a session level and a stream level
5803 // window update frame.
Avi Drissman13fc8932015-12-20 04:40:465804 const int32_t kTargetSize = 3 * 64 * 1024;
bnc8f0f3b62015-04-08 04:37:235805 ASSERT_GE(session_max_recv_window_size, kTargetSize);
5806 ASSERT_GE(stream_max_recv_window_size, kTargetSize);
5807 ASSERT_LT(session_max_recv_window_size / 2, kTargetSize);
5808 ASSERT_LT(stream_max_recv_window_size / 2, kTargetSize);
5809 // Size of each DATA frame.
Avi Drissman13fc8932015-12-20 04:40:465810 const int32_t kChunkSize = 4096;
bnc8f0f3b62015-04-08 04:37:235811 // Size of window updates.
5812 ASSERT_EQ(0, session_max_recv_window_size / 2 % kChunkSize);
Avi Drissman13fc8932015-12-20 04:40:465813 const int32_t session_window_update_delta =
bnc8f0f3b62015-04-08 04:37:235814 session_max_recv_window_size / 2 + kChunkSize;
5815 ASSERT_EQ(0, stream_max_recv_window_size / 2 % kChunkSize);
Avi Drissman13fc8932015-12-20 04:40:465816 const int32_t stream_window_update_delta =
bnc8f0f3b62015-04-08 04:37:235817 stream_max_recv_window_size / 2 + kChunkSize;
[email protected]d11b6912013-06-27 23:07:325818
bnc8f0f3b62015-04-08 04:37:235819 SettingsMap initial_settings;
5820 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
5821 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
5822 initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
5823 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size);
5824 scoped_ptr<SpdyFrame> initial_settings_frame(
5825 spdy_util_.ConstructSpdySettings(initial_settings));
5826 scoped_ptr<SpdyFrame> initial_window_update(
5827 spdy_util_.ConstructSpdyWindowUpdate(
5828 kSessionFlowControlStreamId,
5829 session_max_recv_window_size - default_initial_window_size));
[email protected]d11b6912013-06-27 23:07:325830 scoped_ptr<SpdyFrame> req(
5831 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5832 scoped_ptr<SpdyFrame> session_window_update(
bnc8f0f3b62015-04-08 04:37:235833 spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta));
5834 scoped_ptr<SpdyFrame> stream_window_update(
5835 spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta));
[email protected]d11b6912013-06-27 23:07:325836
5837 std::vector<MockWrite> writes;
bnc9b79a572015-09-02 12:25:035838 if (GetParam().protocol == kProtoHTTP2) {
bnc8f0f3b62015-04-08 04:37:235839 writes.push_back(MockWrite(ASYNC, kHttp2ConnectionHeaderPrefix,
5840 kHttp2ConnectionHeaderPrefixSize, 0));
5841 }
rchacdcbdc2015-05-16 17:16:005842 writes.push_back(CreateMockWrite(*initial_settings_frame, writes.size()));
5843 writes.push_back(CreateMockWrite(*initial_window_update, writes.size()));
5844 writes.push_back(CreateMockWrite(*req, writes.size()));
[email protected]d11b6912013-06-27 23:07:325845
[email protected]251029e2014-03-19 06:04:405846 std::vector<MockRead> reads;
[email protected]d11b6912013-06-27 23:07:325847 scoped_ptr<SpdyFrame> resp(
5848 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchacdcbdc2015-05-16 17:16:005849 reads.push_back(CreateMockRead(*resp, writes.size() + reads.size()));
[email protected]d11b6912013-06-27 23:07:325850
olli.raula1b621142015-12-15 07:04:135851 std::vector<scoped_ptr<SpdyFrame>> body_frames;
bnc8f0f3b62015-04-08 04:37:235852 const std::string body_data(kChunkSize, 'x');
[email protected]251029e2014-03-19 06:04:405853 for (size_t remaining = kTargetSize; remaining != 0;) {
5854 size_t frame_size = std::min(remaining, body_data.size());
olli.raula1b621142015-12-15 07:04:135855 body_frames.push_back(make_scoped_ptr(spdy_util_.ConstructSpdyBodyFrame(
5856 1, body_data.data(), frame_size, false)));
rchacdcbdc2015-05-16 17:16:005857 reads.push_back(
5858 CreateMockRead(*body_frames.back(), writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:405859 remaining -= frame_size;
5860 }
mmenkee24011922015-12-17 22:12:595861 // Yield.
rchacdcbdc2015-05-16 17:16:005862 reads.push_back(
mmenkee24011922015-12-17 22:12:595863 MockRead(SYNCHRONOUS, ERR_IO_PENDING, writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:405864
rchacdcbdc2015-05-16 17:16:005865 writes.push_back(
5866 CreateMockWrite(*session_window_update, writes.size() + reads.size()));
5867 writes.push_back(
5868 CreateMockWrite(*stream_window_update, writes.size() + reads.size()));
5869
davidben5f8b6bc2015-11-25 03:19:545870 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
5871 writes.size());
[email protected]d11b6912013-06-27 23:07:325872
5873 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5874 BoundNetLog(), GetParam(), NULL);
5875 helper.AddData(&data);
5876 helper.RunPreTestSetup();
[email protected]d11b6912013-06-27 23:07:325877
bnc8f0f3b62015-04-08 04:37:235878 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5879 SpdySessionPoolPeer pool_peer(spdy_session_pool);
5880 pool_peer.SetEnableSendingInitialData(true);
5881 pool_peer.SetSessionMaxRecvWindowSize(session_max_recv_window_size);
5882 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
5883
5884 HttpNetworkTransaction* trans = helper.trans();
[email protected]d11b6912013-06-27 23:07:325885 TestCompletionCallback callback;
5886 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5887
5888 EXPECT_EQ(ERR_IO_PENDING, rv);
5889 rv = callback.WaitForResult();
5890 EXPECT_EQ(OK, rv);
5891
5892 SpdyHttpStream* stream =
5893 static_cast<SpdyHttpStream*>(trans->stream_.get());
5894 ASSERT_TRUE(stream != NULL);
5895 ASSERT_TRUE(stream->stream() != NULL);
5896
[email protected]251029e2014-03-19 06:04:405897 // All data has been read, but not consumed. The window reflects this.
bnc8f0f3b62015-04-08 04:37:235898 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size - kTargetSize),
[email protected]251029e2014-03-19 06:04:405899 stream->stream()->recv_window_size());
[email protected]d11b6912013-06-27 23:07:325900
5901 const HttpResponseInfo* response = trans->GetResponseInfo();
5902 ASSERT_TRUE(response != NULL);
5903 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025904 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d11b6912013-06-27 23:07:325905 EXPECT_TRUE(response->was_fetched_via_spdy);
5906
5907 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5908 // size increased to default.
bnc301745a2015-03-10 03:22:165909 scoped_refptr<IOBuffer> buf(new IOBuffer(kTargetSize));
[email protected]251029e2014-03-19 06:04:405910 EXPECT_EQ(static_cast<int>(kTargetSize),
5911 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
bnc8f0f3b62015-04-08 04:37:235912 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size),
[email protected]251029e2014-03-19 06:04:405913 stream->stream()->recv_window_size());
5914 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
[email protected]d11b6912013-06-27 23:07:325915
[email protected]251029e2014-03-19 06:04:405916 // Allow scheduled WINDOW_UPDATE frames to write.
[email protected]fc9d88472013-08-14 02:31:175917 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325918 helper.VerifyDataConsumed();
5919}
5920
5921// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
5922TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]d11b6912013-06-27 23:07:325923 // Number of full frames we hope to write (but will not, used to
5924 // set content-length header correctly)
5925 static int kFrameCount = 3;
5926
5927 scoped_ptr<std::string> content(
5928 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5929 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:005930 GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL,
5931 0));
[email protected]d11b6912013-06-27 23:07:325932 scoped_ptr<SpdyFrame> body(
5933 spdy_util_.ConstructSpdyBodyFrame(
5934 1, content->c_str(), content->size(), false));
5935 scoped_ptr<SpdyFrame> rst(
5936 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
5937
5938 // We're not going to write a data frame with FIN, we'll receive a bad
5939 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
5940 MockWrite writes[] = {
5941 CreateMockWrite(*req, 0),
5942 CreateMockWrite(*body, 2),
5943 CreateMockWrite(*rst, 3),
5944 };
5945
Avi Drissman13fc8932015-12-20 04:40:465946 static const int32_t kDeltaWindowSize = 0x7fffffff; // cause an overflow
[email protected]d11b6912013-06-27 23:07:325947 scoped_ptr<SpdyFrame> window_update(
5948 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5949 MockRead reads[] = {
5950 CreateMockRead(*window_update, 1),
5951 MockRead(ASYNC, 0, 4) // EOF
5952 };
5953
mmenke666a6fea2015-12-19 04:16:335954 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d11b6912013-06-27 23:07:325955
olli.raula6df48b2a2015-11-26 07:40:225956 std::vector<scoped_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:325957 for (int i = 0; i < kFrameCount; ++i) {
olli.raula6df48b2a2015-11-26 07:40:225958 element_readers.push_back(make_scoped_ptr(
5959 new UploadBytesElementReader(content->c_str(), content->size())));
[email protected]d11b6912013-06-27 23:07:325960 }
olli.raula6df48b2a2015-11-26 07:40:225961 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325962
5963 // Setup the request
5964 HttpRequestInfo request;
5965 request.method = "POST";
rchebf12982015-04-10 01:15:005966 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:325967 request.upload_data_stream = &upload_data_stream;
5968
5969 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5970 BoundNetLog(), GetParam(), NULL);
[email protected]d11b6912013-06-27 23:07:325971 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:335972 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:325973 HttpNetworkTransaction* trans = helper.trans();
5974
5975 TestCompletionCallback callback;
5976 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5977 ASSERT_EQ(ERR_IO_PENDING, rv);
5978
mmenke666a6fea2015-12-19 04:16:335979 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325980 ASSERT_TRUE(callback.have_result());
5981 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
5982 helper.VerifyDataConsumed();
5983}
5984
5985// Test that after hitting a send window size of 0, the write process
5986// stalls and upon receiving WINDOW_UPDATE frame write resumes.
5987
5988// This test constructs a POST request followed by enough data frames
5989// containing 'a' that would make the window size 0, followed by another
5990// data frame containing default content (which is "hello!") and this frame
rchacdcbdc2015-05-16 17:16:005991// also contains a FIN flag. SequencedSocketData is used to enforce all
5992// writes, save the last, go through before a read could happen. The last frame
5993// ("hello!") is not permitted to go through since by the time its turn
[email protected]d11b6912013-06-27 23:07:325994// arrives, window size is 0. At this point MessageLoop::Run() called via
5995// callback would block. Therefore we call MessageLoop::RunUntilIdle()
5996// which returns after performing all possible writes. We use DCHECKS to
5997// ensure that last data frame is still there and stream has stalled.
5998// After that, next read is artifically enforced, which causes a
5999// WINDOW_UPDATE to be read and I/O process resumes.
6000TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
Avi Drissman13fc8932015-12-20 04:40:466001 const int32_t initial_window_size =
bnc638c4702015-04-09 18:01:186002 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
[email protected]d11b6912013-06-27 23:07:326003 // Number of frames we need to send to zero out the window size: data
6004 // frames plus SYN_STREAM plus the last data frame; also we need another
6005 // data frame that we will send once the WINDOW_UPDATE is received,
6006 // therefore +3.
bnc2f54c832014-12-01 13:31:196007 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326008
6009 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196010 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326011
6012 // Construct content for a data frame of maximum size.
6013 std::string content(kMaxSpdyFrameChunkSize, 'a');
6014
6015 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006016 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6017 0));
[email protected]d11b6912013-06-27 23:07:326018
6019 // Full frames.
6020 scoped_ptr<SpdyFrame> body1(
6021 spdy_util_.ConstructSpdyBodyFrame(
6022 1, content.c_str(), content.size(), false));
6023
6024 // Last frame to zero out the window size.
6025 scoped_ptr<SpdyFrame> body2(
6026 spdy_util_.ConstructSpdyBodyFrame(
6027 1, content.c_str(), last_frame_size, false));
6028
6029 // Data frame to be sent once WINDOW_UPDATE frame is received.
6030 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6031
6032 // Fill in mock writes.
6033 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6034 size_t i = 0;
rchacdcbdc2015-05-16 17:16:006035 writes[i] = CreateMockWrite(*req, i);
[email protected]d11b6912013-06-27 23:07:326036 for (i = 1; i < num_writes - 2; i++)
rchacdcbdc2015-05-16 17:16:006037 writes[i] = CreateMockWrite(*body1, i);
6038 writes[i] = CreateMockWrite(*body2, i);
6039 // The last write must not be attempted until after the WINDOW_UPDATES
6040 // have been received.
6041 writes[i + 1] = CreateMockWrite(*body3, i + 4, SYNCHRONOUS);
[email protected]d11b6912013-06-27 23:07:326042
6043 // Construct read frame, give enough space to upload the rest of the
6044 // data.
6045 scoped_ptr<SpdyFrame> session_window_update(
6046 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6047 scoped_ptr<SpdyFrame> window_update(
6048 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6049 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6050 MockRead reads[] = {
rchacdcbdc2015-05-16 17:16:006051 MockRead(ASYNC, ERR_IO_PENDING, i + 1), // Force a pause
6052 CreateMockRead(*session_window_update, i + 2),
6053 CreateMockRead(*window_update, i + 3),
6054 // Now the last write will occur.
6055 CreateMockRead(*reply, i + 5),
6056 CreateMockRead(*body2, i + 6),
6057 CreateMockRead(*body3, i + 7),
6058 MockRead(ASYNC, 0, i + 8) // EOF
[email protected]d11b6912013-06-27 23:07:326059 };
6060
rchacdcbdc2015-05-16 17:16:006061 SequencedSocketData data(reads, arraysize(reads), writes.get(), num_writes);
[email protected]d11b6912013-06-27 23:07:326062
olli.raula6df48b2a2015-11-26 07:40:226063 std::vector<scoped_ptr<UploadElementReader>> element_readers;
bnc2f54c832014-12-01 13:31:196064 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326065 upload_data_string.append(kUploadData, kUploadDataSize);
olli.raula6df48b2a2015-11-26 07:40:226066 element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader(
6067 upload_data_string.c_str(), upload_data_string.size())));
6068 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326069
6070 HttpRequestInfo request;
6071 request.method = "POST";
rchebf12982015-04-10 01:15:006072 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326073 request.upload_data_stream = &upload_data_stream;
6074 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6075 BoundNetLog(), GetParam(), NULL);
6076 helper.AddData(&data);
6077 helper.RunPreTestSetup();
6078
6079 HttpNetworkTransaction* trans = helper.trans();
6080
6081 TestCompletionCallback callback;
6082 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6083 EXPECT_EQ(ERR_IO_PENDING, rv);
6084
[email protected]fc9d88472013-08-14 02:31:176085 base::RunLoop().RunUntilIdle(); // Write as much as we can.
[email protected]d11b6912013-06-27 23:07:326086
6087 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6088 ASSERT_TRUE(stream != NULL);
6089 ASSERT_TRUE(stream->stream() != NULL);
6090 EXPECT_EQ(0, stream->stream()->send_window_size());
6091 // All the body data should have been read.
6092 // TODO(satorux): This is because of the weirdness in reading the request
6093 // body in OnSendBodyComplete(). See crbug.com/113107.
6094 EXPECT_TRUE(upload_data_stream.IsEOF());
6095 // But the body is not yet fully sent (kUploadData is not yet sent)
6096 // since we're send-stalled.
6097 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6098
mmenkee24011922015-12-17 22:12:596099 data.Resume(); // Read in WINDOW_UPDATE frame.
[email protected]d11b6912013-06-27 23:07:326100 rv = callback.WaitForResult();
6101 helper.VerifyDataConsumed();
6102}
6103
6104// Test we correctly handle the case where the SETTINGS frame results in
6105// unstalling the send window.
6106TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
Avi Drissman13fc8932015-12-20 04:40:466107 const int32_t initial_window_size =
bnc638c4702015-04-09 18:01:186108 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
bnc2f54c832014-12-01 13:31:196109
[email protected]d11b6912013-06-27 23:07:326110 // Number of frames we need to send to zero out the window size: data
6111 // frames plus SYN_STREAM plus the last data frame; also we need another
6112 // data frame that we will send once the SETTING is received, therefore +3.
bnc2f54c832014-12-01 13:31:196113 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326114
6115 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196116 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326117
6118 // Construct content for a data frame of maximum size.
6119 std::string content(kMaxSpdyFrameChunkSize, 'a');
6120
6121 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006122 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6123 0));
[email protected]d11b6912013-06-27 23:07:326124
6125 // Full frames.
6126 scoped_ptr<SpdyFrame> body1(
6127 spdy_util_.ConstructSpdyBodyFrame(
6128 1, content.c_str(), content.size(), false));
6129
6130 // Last frame to zero out the window size.
6131 scoped_ptr<SpdyFrame> body2(
6132 spdy_util_.ConstructSpdyBodyFrame(
6133 1, content.c_str(), last_frame_size, false));
6134
6135 // Data frame to be sent once SETTINGS frame is received.
6136 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6137
6138 // Fill in mock reads/writes.
6139 std::vector<MockRead> reads;
6140 std::vector<MockWrite> writes;
6141 size_t i = 0;
6142 writes.push_back(CreateMockWrite(*req, i++));
6143 while (i < num_writes - 2)
6144 writes.push_back(CreateMockWrite(*body1, i++));
6145 writes.push_back(CreateMockWrite(*body2, i++));
6146
mmenke666a6fea2015-12-19 04:16:336147 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
6148
[email protected]d11b6912013-06-27 23:07:326149 // Construct read frame for SETTINGS that gives enough space to upload the
6150 // rest of the data.
6151 SettingsMap settings;
6152 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:196153 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
[email protected]d11b6912013-06-27 23:07:326154 scoped_ptr<SpdyFrame> settings_frame_large(
6155 spdy_util_.ConstructSpdySettings(settings));
6156
6157 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6158
6159 scoped_ptr<SpdyFrame> session_window_update(
6160 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6161 if (GetParam().protocol >= kProtoSPDY31)
6162 reads.push_back(CreateMockRead(*session_window_update, i++));
6163
[email protected]d4a77c12014-05-15 20:45:216164 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6165 writes.push_back(CreateMockWrite(*settings_ack, i++));
6166
[email protected]d11b6912013-06-27 23:07:326167 writes.push_back(CreateMockWrite(*body3, i++));
6168
6169 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6170 reads.push_back(CreateMockRead(*reply, i++));
6171 reads.push_back(CreateMockRead(*body2, i++));
6172 reads.push_back(CreateMockRead(*body3, i++));
6173 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6174
6175 // Force all writes to happen before any read, last write will not
6176 // actually queue a frame, due to window size being 0.
mmenke666a6fea2015-12-19 04:16:336177 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
6178 writes.size());
[email protected]d11b6912013-06-27 23:07:326179
olli.raula6df48b2a2015-11-26 07:40:226180 std::vector<scoped_ptr<UploadElementReader>> element_readers;
bnc2f54c832014-12-01 13:31:196181 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326182 upload_data_string.append(kUploadData, kUploadDataSize);
olli.raula6df48b2a2015-11-26 07:40:226183 element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader(
6184 upload_data_string.c_str(), upload_data_string.size())));
6185 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326186
6187 HttpRequestInfo request;
6188 request.method = "POST";
rchebf12982015-04-10 01:15:006189 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326190 request.upload_data_stream = &upload_data_stream;
6191 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6192 BoundNetLog(), GetParam(), NULL);
[email protected]d11b6912013-06-27 23:07:326193 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:336194 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:326195
6196 HttpNetworkTransaction* trans = helper.trans();
6197
6198 TestCompletionCallback callback;
6199 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6200 EXPECT_EQ(ERR_IO_PENDING, rv);
6201
mmenke666a6fea2015-12-19 04:16:336202 data.RunUntilPaused(); // Write as much as we can.
6203 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326204
6205 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6206 ASSERT_TRUE(stream != NULL);
6207 ASSERT_TRUE(stream->stream() != NULL);
6208 EXPECT_EQ(0, stream->stream()->send_window_size());
6209
6210 // All the body data should have been read.
6211 // TODO(satorux): This is because of the weirdness in reading the request
6212 // body in OnSendBodyComplete(). See crbug.com/113107.
6213 EXPECT_TRUE(upload_data_stream.IsEOF());
6214 // But the body is not yet fully sent (kUploadData is not yet sent)
6215 // since we're send-stalled.
6216 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6217
mmenke666a6fea2015-12-19 04:16:336218 // Read in SETTINGS frame to unstall.
6219 data.Resume();
6220 base::RunLoop().RunUntilIdle();
6221
[email protected]d11b6912013-06-27 23:07:326222 rv = callback.WaitForResult();
6223 helper.VerifyDataConsumed();
6224 // If stream is NULL, that means it was unstalled and closed.
6225 EXPECT_TRUE(stream->stream() == NULL);
6226}
6227
6228// Test we correctly handle the case where the SETTINGS frame results in a
6229// negative send window size.
6230TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
Avi Drissman13fc8932015-12-20 04:40:466231 const int32_t initial_window_size =
bnc638c4702015-04-09 18:01:186232 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
[email protected]d11b6912013-06-27 23:07:326233 // Number of frames we need to send to zero out the window size: data
6234 // frames plus SYN_STREAM plus the last data frame; also we need another
6235 // data frame that we will send once the SETTING is received, therefore +3.
bnc2f54c832014-12-01 13:31:196236 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326237
6238 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196239 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326240
6241 // Construct content for a data frame of maximum size.
6242 std::string content(kMaxSpdyFrameChunkSize, 'a');
6243
6244 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006245 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6246 0));
[email protected]d11b6912013-06-27 23:07:326247
6248 // Full frames.
6249 scoped_ptr<SpdyFrame> body1(
6250 spdy_util_.ConstructSpdyBodyFrame(
6251 1, content.c_str(), content.size(), false));
6252
6253 // Last frame to zero out the window size.
6254 scoped_ptr<SpdyFrame> body2(
6255 spdy_util_.ConstructSpdyBodyFrame(
6256 1, content.c_str(), last_frame_size, false));
6257
6258 // Data frame to be sent once SETTINGS frame is received.
6259 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6260
6261 // Fill in mock reads/writes.
6262 std::vector<MockRead> reads;
6263 std::vector<MockWrite> writes;
6264 size_t i = 0;
6265 writes.push_back(CreateMockWrite(*req, i++));
6266 while (i < num_writes - 2)
6267 writes.push_back(CreateMockWrite(*body1, i++));
6268 writes.push_back(CreateMockWrite(*body2, i++));
6269
mmenke666a6fea2015-12-19 04:16:336270 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, i++));
6271
[email protected]d11b6912013-06-27 23:07:326272 // Construct read frame for SETTINGS that makes the send_window_size
6273 // negative.
6274 SettingsMap new_settings;
6275 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:196276 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
[email protected]d11b6912013-06-27 23:07:326277 scoped_ptr<SpdyFrame> settings_frame_small(
6278 spdy_util_.ConstructSpdySettings(new_settings));
6279 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6280 // positive.
6281 scoped_ptr<SpdyFrame> session_window_update_init_size(
bnc2f54c832014-12-01 13:31:196282 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
[email protected]d11b6912013-06-27 23:07:326283 scoped_ptr<SpdyFrame> window_update_init_size(
bnc2f54c832014-12-01 13:31:196284 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
[email protected]d11b6912013-06-27 23:07:326285
6286 reads.push_back(CreateMockRead(*settings_frame_small, i++));
bnc33b8cef42014-11-19 17:30:386287 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
[email protected]d11b6912013-06-27 23:07:326288 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6289
[email protected]d4a77c12014-05-15 20:45:216290 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6291 writes.push_back(CreateMockWrite(*settings_ack, i++));
6292
[email protected]d11b6912013-06-27 23:07:326293 writes.push_back(CreateMockWrite(*body3, i++));
6294
6295 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6296 reads.push_back(CreateMockRead(*reply, i++));
6297 reads.push_back(CreateMockRead(*body2, i++));
6298 reads.push_back(CreateMockRead(*body3, i++));
6299 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6300
6301 // Force all writes to happen before any read, last write will not
6302 // actually queue a frame, due to window size being 0.
mmenke666a6fea2015-12-19 04:16:336303 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
6304 writes.size());
[email protected]d11b6912013-06-27 23:07:326305
olli.raula6df48b2a2015-11-26 07:40:226306 std::vector<scoped_ptr<UploadElementReader>> element_readers;
bnc2f54c832014-12-01 13:31:196307 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326308 upload_data_string.append(kUploadData, kUploadDataSize);
olli.raula6df48b2a2015-11-26 07:40:226309 element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader(
6310 upload_data_string.c_str(), upload_data_string.size())));
6311 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326312
6313 HttpRequestInfo request;
6314 request.method = "POST";
rchebf12982015-04-10 01:15:006315 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326316 request.upload_data_stream = &upload_data_stream;
6317 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6318 BoundNetLog(), GetParam(), NULL);
[email protected]d11b6912013-06-27 23:07:326319 helper.RunPreTestSetup();
mmenke666a6fea2015-12-19 04:16:336320 helper.AddData(&data);
[email protected]d11b6912013-06-27 23:07:326321
6322 HttpNetworkTransaction* trans = helper.trans();
6323
6324 TestCompletionCallback callback;
6325 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6326 EXPECT_EQ(ERR_IO_PENDING, rv);
6327
mmenke666a6fea2015-12-19 04:16:336328 data.RunUntilPaused(); // Write as much as we can.
6329 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326330
6331 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6332 ASSERT_TRUE(stream != NULL);
6333 ASSERT_TRUE(stream->stream() != NULL);
6334 EXPECT_EQ(0, stream->stream()->send_window_size());
6335
6336 // All the body data should have been read.
6337 // TODO(satorux): This is because of the weirdness in reading the request
6338 // body in OnSendBodyComplete(). See crbug.com/113107.
6339 EXPECT_TRUE(upload_data_stream.IsEOF());
6340 // But the body is not yet fully sent (kUploadData is not yet sent)
6341 // since we're send-stalled.
6342 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6343
6344 // Read in WINDOW_UPDATE or SETTINGS frame.
mmenke666a6fea2015-12-19 04:16:336345 data.Resume();
6346 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326347 rv = callback.WaitForResult();
6348 helper.VerifyDataConsumed();
6349}
6350
baranovich212a1292014-09-02 21:45:316351TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
6352 if (spdy_util_.spdy_version() < SPDY3)
6353 return;
6354
6355 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
bncce36dca22015-04-21 22:11:236356 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat",
baranovich212a1292014-09-02 21:45:316357 push_headers.get());
6358 scoped_ptr<SpdyFrame> push(
dchengc7eeda422015-12-26 03:56:486359 spdy_util_.ConstructInitialSpdyPushFrame(std::move(push_headers), 3, 1));
baranovich212a1292014-09-02 21:45:316360 MockRead reads[] = {CreateMockRead(*push, 1)};
6361
6362 scoped_ptr<SpdyFrame> req(
6363 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6364 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6365 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6366 MockWrite writes[] = {
6367 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
6368 };
6369
rch08e3aa3e2015-05-16 14:27:526370 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
baranovich212a1292014-09-02 21:45:316371 NormalSpdyTransactionHelper helper(
6372 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6373 helper.RunToCompletion(&data);
6374 TransactionHelperResult out = helper.output();
6375 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6376}
6377
6378TEST_P(SpdyNetworkTransactionTest,
6379 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
6380 if (spdy_util_.spdy_version() < SPDY3)
6381 return;
6382
6383 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:006384 NULL, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
baranovich212a1292014-09-02 21:45:316385 scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
rchebf12982015-04-10 01:15:006386 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/b.dat"),
baranovich212a1292014-09-02 21:45:316387 push_b_headers.get());
dchengc7eeda422015-12-26 03:56:486388 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructInitialSpdyPushFrame(
6389 std::move(push_b_headers), 2, 1));
baranovich212a1292014-09-02 21:45:316390 MockRead reads[] = {
6391 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
6392 };
6393
6394 scoped_ptr<SpdyFrame> req(
6395 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6396 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6397 4,
6398 GOAWAY_PROTOCOL_ERROR,
6399 "New push stream id must be greater than the last accepted."));
6400 MockWrite writes[] = {
6401 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
6402 };
6403
rch08e3aa3e2015-05-16 14:27:526404 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
baranovich212a1292014-09-02 21:45:316405 NormalSpdyTransactionHelper helper(
6406 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6407 helper.RunToCompletion(&data);
6408 TransactionHelperResult out = helper.output();
6409 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6410}
6411
bnc76598ab2015-06-29 12:43:076412// Regression test for https://crbug.com/493348: request header exceeds 16 kB
6413// and thus sent in multiple frames when using HTTP/2.
6414TEST_P(SpdyNetworkTransactionTest, LargeRequest) {
6415 const std::string kKey("foo");
6416 const std::string kValue(1 << 15, 'z');
6417
6418 HttpRequestInfo request;
6419 request.method = "GET";
6420 request.url = GURL(GetDefaultUrl());
6421 request.extra_headers.SetHeader(kKey, kValue);
6422
6423 scoped_ptr<SpdyHeaderBlock> headers(
6424 spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
6425 (*headers)[kKey] = kValue;
6426 scoped_ptr<SpdyFrame> req(
6427 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
6428 MockWrite writes[] = {
6429 CreateMockWrite(*req, 0),
6430 };
6431
6432 scoped_ptr<SpdyFrame> resp(
6433 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
6434 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6435 MockRead reads[] = {
6436 CreateMockRead(*resp, 1),
6437 CreateMockRead(*body, 2),
6438 MockRead(ASYNC, 0, 3) // EOF
6439 };
6440
6441 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6442 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
6443 GetParam(), nullptr);
6444 helper.RunToCompletion(&data);
6445 TransactionHelperResult out = helper.output();
6446
6447 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:026448 EXPECT_EQ("HTTP/1.1 200", out.status_line);
bnc76598ab2015-06-29 12:43:076449 EXPECT_EQ("hello!", out.response_data);
6450}
6451
[email protected]514aeaf2014-05-23 10:31:516452class SpdyNetworkTransactionNoTLSUsageCheckTest
6453 : public SpdyNetworkTransactionTest {
6454 protected:
6455 void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6456 // Construct the request.
rchebf12982015-04-10 01:15:006457 scoped_ptr<SpdyFrame> req(
6458 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:526459 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]514aeaf2014-05-23 10:31:516460
6461 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6462 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6463 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:526464 CreateMockRead(*resp, 1),
6465 CreateMockRead(*body, 2),
6466 MockRead(ASYNC, 0, 3) // EOF
[email protected]514aeaf2014-05-23 10:31:516467 };
6468
rch08e3aa3e2015-05-16 14:27:526469 SequencedSocketData data(reads, arraysize(reads), writes,
6470 arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516471 HttpRequestInfo request;
6472 request.method = "GET";
bncce36dca22015-04-21 22:11:236473 request.url = GURL("https://www.example.org/");
[email protected]514aeaf2014-05-23 10:31:516474 NormalSpdyTransactionHelper helper(
6475 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
dchengc7eeda422015-12-26 03:56:486476 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516477 TransactionHelperResult out = helper.output();
6478 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:026479 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]514aeaf2014-05-23 10:31:516480 EXPECT_EQ("hello!", out.response_data);
6481 }
6482};
6483
6484//-----------------------------------------------------------------------------
6485// All tests are run with three different connection types: SPDY after NPN
6486// negotiation, SPDY without SSL, and SPDY with SSL.
6487//
6488// TODO(akalin): Use ::testing::Combine() when we are able to use
6489// <tr1/tuple>.
6490INSTANTIATE_TEST_CASE_P(
6491 Spdy,
6492 SpdyNetworkTransactionNoTLSUsageCheckTest,
rchebf12982015-04-10 01:15:006493 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31,
rdsmithebb50aa2015-11-12 03:44:386494 HTTPS_SPDY_VIA_NPN,
6495 false)));
[email protected]514aeaf2014-05-23 10:31:516496
6497TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6498 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6499 new SSLSocketDataProvider(ASYNC, OK));
6500 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6501 &ssl_provider->connection_status);
6502
dchengc7eeda422015-12-26 03:56:486503 RunNoTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516504}
6505
6506TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6507 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6508 new SSLSocketDataProvider(ASYNC, OK));
6509 // Set to TLS_RSA_WITH_NULL_MD5
6510 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6511
dchengc7eeda422015-12-26 03:56:486512 RunNoTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516513}
6514
6515class SpdyNetworkTransactionTLSUsageCheckTest
6516 : public SpdyNetworkTransactionTest {
6517 protected:
6518 void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]bdd1b222014-06-10 11:08:396519 scoped_ptr<SpdyFrame> goaway(
6520 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6521 MockWrite writes[] = {CreateMockWrite(*goaway)};
[email protected]514aeaf2014-05-23 10:31:516522
rch08e3aa3e2015-05-16 14:27:526523 StaticSocketDataProvider data(NULL, 0, writes, arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516524 HttpRequestInfo request;
6525 request.method = "GET";
bncce36dca22015-04-21 22:11:236526 request.url = GURL("https://www.example.org/");
[email protected]514aeaf2014-05-23 10:31:516527 NormalSpdyTransactionHelper helper(
6528 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
dchengc7eeda422015-12-26 03:56:486529 helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516530 TransactionHelperResult out = helper.output();
6531 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6532 }
6533};
6534
6535INSTANTIATE_TEST_CASE_P(
6536 Spdy,
6537 SpdyNetworkTransactionTLSUsageCheckTest,
rdsmithebb50aa2015-11-12 03:44:386538 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoHTTP2,
6539 HTTPS_SPDY_VIA_NPN,
6540 false),
6541 SpdyNetworkTransactionTestParams(kProtoHTTP2,
6542 HTTPS_SPDY_VIA_NPN,
6543 true)));
[email protected]514aeaf2014-05-23 10:31:516544
6545TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6546 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6547 new SSLSocketDataProvider(ASYNC, OK));
6548 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6549 &ssl_provider->connection_status);
6550
dchengc7eeda422015-12-26 03:56:486551 RunTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516552}
6553
6554TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6555 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6556 new SSLSocketDataProvider(ASYNC, OK));
6557 // Set to TLS_RSA_WITH_NULL_MD5
6558 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6559
dchengc7eeda422015-12-26 03:56:486560 RunTLSUsageCheckTest(std::move(ssl_provider));
[email protected]514aeaf2014-05-23 10:31:516561}
6562
[email protected]aea80602009-09-18 00:55:086563} // namespace net