blob: 292074abb6744a6bc6ec3a15c85c61fc172cfb30 [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>
[email protected]a33cad2b62010-07-30 22:24:396#include <vector>
7
[email protected]49639fa2011-12-20 23:22:418#include "base/bind.h"
9#include "base/bind_helpers.h"
thestigd8df0332014-09-04 06:33:2910#include "base/files/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2311#include "base/files/scoped_temp_dir.h"
olli.raula6df48b2a2015-11-26 07:40:2212#include "base/memory/scoped_ptr.h"
[email protected]fc9d88472013-08-14 02:31:1713#include "base/run_loop.h"
[email protected]251029e2014-03-19 06:04:4014#include "base/strings/string_piece.h"
[email protected]999dd8c2013-11-12 06:45:5415#include "base/test/test_file_util.h"
skyostil4891b25b2015-06-11 11:43:4516#include "base/thread_task_runner_handle.h"
[email protected]018aabc2010-10-29 16:16:5917#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0718#include "net/base/chunked_upload_data_stream.h"
19#include "net/base/elements_upload_data_stream.h"
[email protected]262eec82013-03-19 21:01:3620#include "net/base/request_priority.h"
bncce36dca22015-04-21 22:11:2321#include "net/base/test_data_directory.h"
[email protected]b2d26cfd2012-12-11 10:36:0622#include "net/base/upload_bytes_element_reader.h"
[email protected]b2d26cfd2012-12-11 10:36:0623#include "net/base/upload_file_element_reader.h"
aberentbba302d2015-12-03 10:20:1924#include "net/http/http_auth_scheme.h"
[email protected]87bfa3f2010-09-30 14:54:5625#include "net/http/http_network_session_peer.h"
[email protected]513963e2013-06-15 01:53:0426#include "net/http/http_network_transaction.h"
27#include "net/http/http_server_properties.h"
[email protected]c41737d2014-05-14 07:47:1928#include "net/http/http_transaction_test_util.h"
mmenke16a7cbdd2015-04-24 23:00:5629#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4630#include "net/log/test_net_log_entry.h"
31#include "net/log/test_net_log_util.h"
[email protected]2d6728692011-03-12 01:39:5532#include "net/socket/client_socket_pool_base.h"
[email protected]bb88e1d32013-05-03 23:11:0733#include "net/socket/next_proto.h"
[email protected]f54c85792012-03-08 19:06:4134#include "net/spdy/buffered_spdy_framer.h"
[email protected]9be804c82010-06-24 17:59:4635#include "net/spdy/spdy_http_stream.h"
[email protected]9e1bdd32011-02-03 21:48:3436#include "net/spdy/spdy_http_utils.h"
[email protected]bdebd1b2010-08-09 20:18:0837#include "net/spdy/spdy_session.h"
[email protected]19ec8a72010-08-23 03:38:2338#include "net/spdy/spdy_session_pool.h"
[email protected]86aa87b2013-02-15 01:10:0339#include "net/spdy/spdy_test_util_common.h"
[email protected]a4bfdf72013-02-22 04:06:1640#include "net/spdy/spdy_test_utils.h"
[email protected]514aeaf2014-05-23 10:31:5141#include "net/ssl/ssl_connection_status_flags.h"
bncce36dca22015-04-21 22:11:2342#include "net/test/cert_test_util.h"
[email protected]d2db0292011-01-26 20:23:4443#include "net/url_request/url_request_test_util.h"
[email protected]251029e2014-03-19 06:04:4044#include "testing/gmock/include/gmock/gmock.h"
[email protected]aea80602009-09-18 00:55:0845#include "testing/platform_test.h"
46
47//-----------------------------------------------------------------------------
48
[email protected]d1eda932009-11-04 01:03:1049namespace net {
[email protected]dae22c52010-07-30 02:16:3550
[email protected]cbdd73162013-03-18 23:27:3351namespace {
[email protected]251029e2014-03-19 06:04:4052
53using testing::Each;
54using testing::Eq;
55
[email protected]513963e2013-06-15 01:53:0456enum SpdyNetworkTransactionTestSSLType {
rchebf12982015-04-10 01:15:0057 // Request an https:// URL and use NPN (or ALPN) to negotiate SPDY during
58 // the TLS handshake.
59 HTTPS_SPDY_VIA_NPN,
60 // Request and http:// URL to a server that supports SPDY via Alternative
61 // Service on port 443.
62 // See: https//tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html
63 HTTP_SPDY_VIA_ALT_SVC,
[email protected]9e9e842e2010-07-23 23:09:1564};
[email protected]ca6459f862012-04-11 19:43:2065
[email protected]513963e2013-06-15 01:53:0466struct SpdyNetworkTransactionTestParams {
67 SpdyNetworkTransactionTestParams()
rdsmithebb50aa2015-11-12 03:44:3868 : protocol(kProtoSPDY31),
69 ssl_type(HTTPS_SPDY_VIA_NPN),
70 priority_to_dependency(false) {}
[email protected]513963e2013-06-15 01:53:0471
rchebf12982015-04-10 01:15:0072 SpdyNetworkTransactionTestParams(NextProto protocol,
rdsmithebb50aa2015-11-12 03:44:3873 SpdyNetworkTransactionTestSSLType ssl_type,
74 bool priority_to_dependency)
75 : protocol(protocol),
76 ssl_type(ssl_type),
77 priority_to_dependency(priority_to_dependency) {}
rchebf12982015-04-10 01:15:0078
79 friend std::ostream& operator<<(std::ostream& os,
80 const SpdyNetworkTransactionTestParams& p) {
81 std::string type_str;
82 switch (p.ssl_type) {
83 case HTTP_SPDY_VIA_ALT_SVC:
84 type_str = "HTTP_SPDY_VIA_ALT_SVC";
85 break;
86 case HTTPS_SPDY_VIA_NPN:
87 type_str = "HTTPS_SPDY_VIA_NPN";
88 break;
89 }
90 os << "{ protocol: " << SSLClientSocket::NextProtoToString(p.protocol)
rdsmithebb50aa2015-11-12 03:44:3891 << ", ssl_type: " << type_str
92 << ", priority_to_dependency: " << p.priority_to_dependency << " }";
rchebf12982015-04-10 01:15:0093 return os;
94 }
[email protected]513963e2013-06-15 01:53:0495
96 NextProto protocol;
97 SpdyNetworkTransactionTestSSLType ssl_type;
rdsmithebb50aa2015-11-12 03:44:3898 bool priority_to_dependency;
[email protected]513963e2013-06-15 01:53:0499};
100
rchebf12982015-04-10 01:15:00101void UpdateSpdySessionDependencies(SpdyNetworkTransactionTestParams test_params,
102 SpdySessionDependencies* session_deps) {
bnc55ff9da2015-08-19 18:42:35103 session_deps->use_alternative_services = true;
rchebf12982015-04-10 01:15:00104 session_deps->next_protos = SpdyNextProtos();
105 if (test_params.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
bnc7dc7e1b42015-07-28 14:43:12106 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
rchebf12982015-04-10 01:15:00107 session_deps->http_server_properties.SetAlternativeService(
bncce36dca22015-04-21 22:11:23108 HostPortPair("www.example.org", 80),
rchebf12982015-04-10 01:15:00109 AlternativeService(AlternateProtocolFromNextProto(test_params.protocol),
bncce36dca22015-04-21 22:11:23110 "www.example.org", 443),
bnc7dc7e1b42015-07-28 14:43:12111 1.0, expiration);
[email protected]d7599122014-05-24 03:37:23112 }
113}
114
rdsmith82957ad2015-09-16 19:42:03115scoped_ptr<SpdySessionDependencies> CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:04116 SpdyNetworkTransactionTestParams test_params) {
rdsmith82957ad2015-09-16 19:42:03117 scoped_ptr<SpdySessionDependencies> session_deps(
118 new SpdySessionDependencies(test_params.protocol));
119 UpdateSpdySessionDependencies(test_params, session_deps.get());
[email protected]d7599122014-05-24 03:37:23120 return session_deps;
[email protected]513963e2013-06-15 01:53:04121}
122
rdsmith82957ad2015-09-16 19:42:03123scoped_ptr<SpdySessionDependencies> CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:04124 SpdyNetworkTransactionTestParams test_params,
rdsmith82957ad2015-09-16 19:42:03125 scoped_ptr<ProxyService> proxy_service) {
126 scoped_ptr<SpdySessionDependencies> session_deps(
127 new SpdySessionDependencies(test_params.protocol, proxy_service.Pass()));
128 UpdateSpdySessionDependencies(test_params, session_deps.get());
[email protected]d7599122014-05-24 03:37:23129 return session_deps;
[email protected]bb88e1d32013-05-03 23:11:07130}
131
[email protected]513963e2013-06-15 01:53:04132} // namespace
133
134class SpdyNetworkTransactionTest
135 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
[email protected]34437af82009-11-06 02:28:49136 protected:
rdsmithebb50aa2015-11-12 03:44:38137 SpdyNetworkTransactionTest()
138 : spdy_util_(GetParam().protocol, GetParam().priority_to_dependency) {
139 SpdySession::SetPriorityDependencyDefaultForTesting(
140 GetParam().priority_to_dependency);
rchebf12982015-04-10 01:15:00141 spdy_util_.set_default_url(GURL(GetDefaultUrl()));
[email protected]9ec54f82013-05-10 02:53:05142 }
[email protected]2d6728692011-03-12 01:39:55143
[email protected]fc9d88472013-08-14 02:31:17144 virtual ~SpdyNetworkTransactionTest() {
mmenkecbc2b712014-10-09 20:29:07145 // UploadDataStream may post a deletion tasks back to the message loop on
[email protected]fc9d88472013-08-14 02:31:17146 // destruction.
147 upload_data_stream_.reset();
148 base::RunLoop().RunUntilIdle();
rdsmithebb50aa2015-11-12 03:44:38149 SpdySession::SetPriorityDependencyDefaultForTesting(false);
[email protected]fc9d88472013-08-14 02:31:17150 }
151
dcheng67be2b1f2014-10-27 21:47:29152 void SetUp() override {
bncce36dca22015-04-21 22:11:23153 get_request_initialized_ = false;
154 post_request_initialized_ = false;
155 chunked_post_request_initialized_ = false;
[email protected]69e6b4a2012-10-18 08:03:01156 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]aea80602009-09-18 00:55:08157 }
158
[email protected]72552f02009-10-28 15:25:01159 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:08160 int rv;
161 std::string status_line;
162 std::string response_data;
[email protected]8b070372009-11-16 22:01:25163 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:08164 };
165
[email protected]3caf5542010-07-16 15:19:47166 // A helper class that handles all the initial npn/ssl setup.
167 class NormalSpdyTransactionHelper {
168 public:
rdsmith82957ad2015-09-16 19:42:03169 NormalSpdyTransactionHelper(
170 const HttpRequestInfo& request,
171 RequestPriority priority,
172 const BoundNetLog& log,
173 SpdyNetworkTransactionTestParams test_params,
174 scoped_ptr<SpdySessionDependencies> session_deps)
[email protected]30c942b2010-07-21 16:59:59175 : request_(request),
[email protected]262eec82013-03-19 21:01:36176 priority_(priority),
rdsmith82957ad2015-09-16 19:42:03177 session_deps_(session_deps.get() == NULL
rchebf12982015-04-10 01:15:00178 ? CreateSpdySessionDependencies(test_params)
rdsmith82957ad2015-09-16 19:42:03179 : session_deps.Pass()),
rchebf12982015-04-10 01:15:00180 session_(
181 SpdySessionDependencies::SpdyCreateSession(session_deps_.get())),
[email protected]9e9e842e2010-07-23 23:09:15182 log_(log),
[email protected]513963e2013-06-15 01:53:04183 test_params_(test_params),
rchebf12982015-04-10 01:15:00184 port_(443),
[email protected]1f418ee2010-10-16 19:46:56185 deterministic_(false),
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]3b7828432010-08-18 18:33:27200 void SetDeterministic() {
201 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
202 session_deps_.get());
203 deterministic_ = true;
204 }
205
[email protected]1f418ee2010-10-16 19:46:56206 void SetSpdyDisabled() {
207 spdy_enabled_ = false;
rchebf12982015-04-10 01:15:00208 port_ = test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC ? 80 : 443;
[email protected]1f418ee2010-10-16 19:46:56209 }
210
[email protected]3caf5542010-07-16 15:19:47211 void RunPreTestSetup() {
[email protected]b261d0e2010-08-02 19:13:24212 if (!session_deps_.get())
rdsmith82957ad2015-09-16 19:42:03213 session_deps_ = CreateSpdySessionDependencies(test_params_);
[email protected]d7599122014-05-24 03:37:23214 if (!session_.get()) {
[email protected]b261d0e2010-08-02 19:13:24215 session_ = SpdySessionDependencies::SpdyCreateSession(
216 session_deps_.get());
[email protected]3caf5542010-07-16 15:19:47217 }
[email protected]aea80602009-09-18 00:55:08218
[email protected]3caf5542010-07-16 15:19:47219 // We're now ready to use SSL-npn SPDY.
[email protected]90499482013-06-01 00:39:50220 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
[email protected]cb54b3b22010-06-03 16:28:55221 }
[email protected]aea80602009-09-18 00:55:08222
[email protected]3caf5542010-07-16 15:19:47223 // Start the transaction, read some data, finish.
224 void RunDefaultTest() {
[email protected]34b345f92013-02-22 03:27:26225 if (!StartDefaultTest())
226 return;
227 FinishDefaultTest();
228 }
229
230 bool StartDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51231 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
[email protected]aea80602009-09-18 00:55:08232
[email protected]3caf5542010-07-16 15:19:47233 // We expect an IO Pending or some sort of error.
234 EXPECT_LT(output_.rv, 0);
[email protected]34b345f92013-02-22 03:27:26235 return output_.rv == ERR_IO_PENDING;
236 }
[email protected]aea80602009-09-18 00:55:08237
[email protected]34b345f92013-02-22 03:27:26238 void FinishDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51239 output_.rv = callback_.WaitForResult();
[email protected]3caf5542010-07-16 15:19:47240 if (output_.rv != OK) {
bnc301745a2015-03-10 03:22:16241 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
[email protected]3caf5542010-07-16 15:19:47242 return;
243 }
[email protected]ff57bb82009-11-12 06:52:14244
[email protected]3caf5542010-07-16 15:19:47245 // Verify responses.
246 const HttpResponseInfo* response = trans_->GetResponseInfo();
247 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:50248 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]808957c2013-03-13 03:51:27249 if (HttpStreamFactory::spdy_enabled()) {
[email protected]88a332622013-07-30 07:13:32250 EXPECT_EQ(
251 HttpResponseInfo::ConnectionInfoFromNextProto(
252 test_params_.protocol),
253 response->connection_info);
[email protected]808957c2013-03-13 03:51:27254 } else {
255 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
256 response->connection_info);
257 }
rchebf12982015-04-10 01:15:00258 if (spdy_enabled_) {
bnc84e7fb52015-12-02 11:50:02259 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
260 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]9e9e842e2010-07-23 23:09:15261 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]a33cad2b62010-07-30 22:24:39262 } else {
bnc84e7fb52015-12-02 11:50:02263 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
264 EXPECT_FALSE(response->was_fetched_via_spdy);
rchebf12982015-04-10 01:15:00265 // If SPDY is disabled, an HTTP request should not be diverted
266 // over an SSL session.
[email protected]1f418ee2010-10-16 19:46:56267 EXPECT_EQ(request_.url.SchemeIs("https"),
268 response->was_npn_negotiated);
269 }
[email protected]80a09a82012-11-16 17:40:06270 EXPECT_EQ("127.0.0.1", response->socket_address.host());
271 EXPECT_EQ(port_, response->socket_address.port());
[email protected]3caf5542010-07-16 15:19:47272 output_.status_line = response->headers->GetStatusLine();
273 output_.response_info = *response; // Make a copy so we can verify.
274 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
[email protected]3caf5542010-07-16 15:19:47275 }
276
bncfacdd852015-01-09 19:22:54277 void FinishDefaultTestWithoutVerification() {
278 output_.rv = callback_.WaitForResult();
279 if (output_.rv != OK)
bnc301745a2015-03-10 03:22:16280 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
bncfacdd852015-01-09 19:22:54281 }
282
[email protected]3caf5542010-07-16 15:19:47283 // Most tests will want to call this function. In particular, the MockReads
284 // should end with an empty read, and that read needs to be processed to
285 // ensure proper deletion of the spdy_session_pool.
286 void VerifyDataConsumed() {
rch08e3aa3e2015-05-16 14:27:52287 for (const SocketDataProvider* provider : data_vector_) {
288 EXPECT_TRUE(provider->AllReadDataConsumed());
289 EXPECT_TRUE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47290 }
rch08051ef2015-05-19 20:07:18291 for (const DeterministicSocketData* provider :
292 deterministic_data_vector_) {
rch0aecfd82015-05-19 17:22:32293 EXPECT_TRUE(provider->AllReadDataConsumed());
294 EXPECT_TRUE(provider->AllWriteDataConsumed());
295 }
[email protected]3caf5542010-07-16 15:19:47296 }
297
298 // Occasionally a test will expect to error out before certain reads are
299 // processed. In that case we want to explicitly ensure that the reads were
300 // not processed.
301 void VerifyDataNotConsumed() {
rch08e3aa3e2015-05-16 14:27:52302 for (const SocketDataProvider* provider : data_vector_) {
303 EXPECT_FALSE(provider->AllReadDataConsumed());
304 EXPECT_FALSE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47305 }
rch08051ef2015-05-19 20:07:18306 for (const DeterministicSocketData* provider :
307 deterministic_data_vector_) {
rch0aecfd82015-05-19 17:22:32308 EXPECT_FALSE(provider->AllReadDataConsumed());
309 EXPECT_FALSE(provider->AllWriteDataConsumed());
310 }
[email protected]3caf5542010-07-16 15:19:47311 }
312
rch08e3aa3e2015-05-16 14:27:52313 void RunToCompletion(SocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47314 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58315 AddData(data);
[email protected]3caf5542010-07-16 15:19:47316 RunDefaultTest();
317 VerifyDataConsumed();
318 }
[email protected]e6b06862010-07-20 16:32:58319
[email protected]514aeaf2014-05-23 10:31:51320 void RunToCompletionWithSSLData(
rch08e3aa3e2015-05-16 14:27:52321 SocketDataProvider* data,
[email protected]514aeaf2014-05-23 10:31:51322 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
323 RunPreTestSetup();
324 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
325 RunDefaultTest();
326 VerifyDataConsumed();
327 }
328
rch08e3aa3e2015-05-16 14:27:52329 void AddData(SocketDataProvider* data) {
[email protected]514aeaf2014-05-23 10:31:51330 scoped_ptr<SSLSocketDataProvider> ssl_provider(
331 new SSLSocketDataProvider(ASYNC, OK));
bncce36dca22015-04-21 22:11:23332 ssl_provider->cert =
333 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
[email protected]514aeaf2014-05-23 10:31:51334 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
335 }
336
337 void AddDataWithSSLSocketDataProvider(
rch08e3aa3e2015-05-16 14:27:52338 SocketDataProvider* data,
[email protected]514aeaf2014-05-23 10:31:51339 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]3b7828432010-08-18 18:33:27340 DCHECK(!deterministic_);
[email protected]3caf5542010-07-16 15:19:47341 data_vector_.push_back(data);
rchebf12982015-04-10 01:15:00342 if (ssl_provider->next_proto_status ==
343 SSLClientSocket::kNextProtoUnsupported) {
[email protected]513963e2013-06-15 01:53:04344 ssl_provider->SetNextProto(test_params_.protocol);
[email protected]514aeaf2014-05-23 10:31:51345 }
rchebf12982015-04-10 01:15:00346
347 session_deps_->socket_factory->AddSSLSocketDataProvider(
348 ssl_provider.get());
olli.raulaae011c422015-12-10 07:38:51349 ssl_vector_.push_back(std::move(ssl_provider));
[email protected]d4f00222012-07-10 06:24:51350
[email protected]3b7828432010-08-18 18:33:27351 session_deps_->socket_factory->AddSocketDataProvider(data);
rchebf12982015-04-10 01:15:00352 if (test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
353 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
olli.raulaae011c422015-12-10 07:38:51354 scoped_ptr<StaticSocketDataProvider> hanging_non_alt_svc_socket(
355 make_scoped_ptr(new StaticSocketDataProvider(NULL, 0, NULL, 0)));
rchebf12982015-04-10 01:15:00356 hanging_non_alt_svc_socket->set_connect_data(hanging_connect);
[email protected]2d6728692011-03-12 01:39:55357 session_deps_->socket_factory->AddSocketDataProvider(
olli.raulaae011c422015-12-10 07:38:51358 hanging_non_alt_svc_socket.get());
359 alternate_vector_.push_back(std::move(hanging_non_alt_svc_socket));
[email protected]2d6728692011-03-12 01:39:55360 }
[email protected]3b7828432010-08-18 18:33:27361 }
362
363 void AddDeterministicData(DeterministicSocketData* data) {
364 DCHECK(deterministic_);
rch0aecfd82015-05-19 17:22:32365 deterministic_data_vector_.push_back(data);
olli.raulaae011c422015-12-10 07:38:51366 scoped_ptr<SSLSocketDataProvider> ssl_provider(
367 make_scoped_ptr(new SSLSocketDataProvider(ASYNC, OK)));
rchebf12982015-04-10 01:15:00368 ssl_provider->SetNextProto(test_params_.protocol);
bncce36dca22015-04-21 22:11:23369 ssl_provider->cert =
370 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
rchebf12982015-04-10 01:15:00371 session_deps_->deterministic_socket_factory->AddSSLSocketDataProvider(
olli.raulaae011c422015-12-10 07:38:51372 ssl_provider.get());
373 ssl_vector_.push_back(std::move(ssl_provider));
rchebf12982015-04-10 01:15:00374
[email protected]3b7828432010-08-18 18:33:27375 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
rchebf12982015-04-10 01:15:00376 if (test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
377 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
olli.raulaae011c422015-12-10 07:38:51378 scoped_ptr<DeterministicSocketData> hanging_non_alt_svc_socket(
379 make_scoped_ptr(new DeterministicSocketData(NULL, 0, NULL, 0)));
rchebf12982015-04-10 01:15:00380 hanging_non_alt_svc_socket->set_connect_data(hanging_connect);
[email protected]2d6728692011-03-12 01:39:55381 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
olli.raulaae011c422015-12-10 07:38:51382 hanging_non_alt_svc_socket.get());
383 alternate_deterministic_vector_.push_back(
384 std::move(hanging_non_alt_svc_socket));
[email protected]2d6728692011-03-12 01:39:55385 }
[email protected]3caf5542010-07-16 15:19:47386 }
387
mmenkee65e7af2015-10-13 17:16:42388 void SetSession(scoped_ptr<HttpNetworkSession> session) {
389 session_ = session.Pass();
[email protected]3caf5542010-07-16 15:19:47390 }
391 HttpNetworkTransaction* trans() { return trans_.get(); }
392 void ResetTrans() { trans_.reset(); }
393 TransactionHelperResult& output() { return output_; }
[email protected]19ec8a72010-08-23 03:38:23394 const HttpRequestInfo& request() const { return request_; }
mmenkee65e7af2015-10-13 17:16:42395 HttpNetworkSession* session() const { return session_.get(); }
[email protected]b261d0e2010-08-02 19:13:24396 scoped_ptr<SpdySessionDependencies>& session_deps() {
397 return session_deps_;
398 }
[email protected]19ec8a72010-08-23 03:38:23399 int port() const { return port_; }
[email protected]513963e2013-06-15 01:53:04400 SpdyNetworkTransactionTestParams test_params() const {
401 return test_params_;
[email protected]448d4ca52012-03-04 04:12:23402 }
[email protected]3caf5542010-07-16 15:19:47403
404 private:
rch08e3aa3e2015-05-16 14:27:52405 typedef std::vector<SocketDataProvider*> DataVector;
rch0aecfd82015-05-19 17:22:32406 typedef std::vector<DeterministicSocketData*> DeterministicDataVector;
olli.raulaae011c422015-12-10 07:38:51407 typedef std::vector<scoped_ptr<SSLSocketDataProvider>> SSLVector;
408 typedef std::vector<scoped_ptr<SocketDataProvider>> AlternateVector;
409 typedef std::vector<scoped_ptr<DeterministicSocketData>>
410 AlternateDeterministicVector;
[email protected]3caf5542010-07-16 15:19:47411 HttpRequestInfo request_;
[email protected]262eec82013-03-19 21:01:36412 RequestPriority priority_;
[email protected]b261d0e2010-08-02 19:13:24413 scoped_ptr<SpdySessionDependencies> session_deps_;
mmenkee65e7af2015-10-13 17:16:42414 scoped_ptr<HttpNetworkSession> session_;
[email protected]3caf5542010-07-16 15:19:47415 TransactionHelperResult output_;
rch08e3aa3e2015-05-16 14:27:52416 scoped_ptr<SocketDataProvider> first_transaction_;
[email protected]3caf5542010-07-16 15:19:47417 SSLVector ssl_vector_;
[email protected]514aeaf2014-05-23 10:31:51418 TestCompletionCallback callback_;
[email protected]3caf5542010-07-16 15:19:47419 scoped_ptr<HttpNetworkTransaction> trans_;
420 scoped_ptr<HttpNetworkTransaction> trans_http_;
421 DataVector data_vector_;
rch0aecfd82015-05-19 17:22:32422 DeterministicDataVector deterministic_data_vector_;
[email protected]2d6728692011-03-12 01:39:55423 AlternateVector alternate_vector_;
424 AlternateDeterministicVector alternate_deterministic_vector_;
bnc29b1f072015-01-14 20:37:49425 const BoundNetLog log_;
[email protected]513963e2013-06-15 01:53:04426 SpdyNetworkTransactionTestParams test_params_;
[email protected]9e9e842e2010-07-23 23:09:15427 int port_;
[email protected]3b7828432010-08-18 18:33:27428 bool deterministic_;
[email protected]1f418ee2010-10-16 19:46:56429 bool spdy_enabled_;
[email protected]3caf5542010-07-16 15:19:47430 };
[email protected]aea80602009-09-18 00:55:08431
432 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
433 int expected_status);
434
435 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18436
[email protected]e3ebba0f2010-08-05 17:59:58437 const HttpRequestInfo& CreateGetPushRequest() {
bncce36dca22015-04-21 22:11:23438 get_push_request_.method = "GET";
439 get_push_request_.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
440 get_push_request_.load_flags = 0;
441 return get_push_request_;
[email protected]e3ebba0f2010-08-05 17:59:58442 }
443
[email protected]d3cee19d2010-06-22 18:42:18444 const HttpRequestInfo& CreateGetRequest() {
bncce36dca22015-04-21 22:11:23445 if (!get_request_initialized_) {
446 get_request_.method = "GET";
447 get_request_.url = GURL(GetDefaultUrl());
448 get_request_.load_flags = 0;
449 get_request_initialized_ = true;
[email protected]d3cee19d2010-06-22 18:42:18450 }
bncce36dca22015-04-21 22:11:23451 return get_request_;
[email protected]d3cee19d2010-06-22 18:42:18452 }
453
[email protected]3deb9a52010-11-11 00:24:40454 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
bncce36dca22015-04-21 22:11:23455 if (!get_request_initialized_) {
456 get_request_.method = "GET";
457 get_request_.url = GURL(GetDefaultUrl());
458 get_request_.load_flags = 0;
459 get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
460 get_request_initialized_ = true;
[email protected]3deb9a52010-11-11 00:24:40461 }
bncce36dca22015-04-21 22:11:23462 return get_request_;
[email protected]3deb9a52010-11-11 00:24:40463 }
464
[email protected]310240592010-08-05 21:04:19465 const HttpRequestInfo& CreatePostRequest() {
bncce36dca22015-04-21 22:11:23466 if (!post_request_initialized_) {
olli.raula6df48b2a2015-11-26 07:40:22467 std::vector<scoped_ptr<UploadElementReader>> element_readers;
468 element_readers.push_back(make_scoped_ptr(
469 new UploadBytesElementReader(kUploadData, kUploadDataSize)));
[email protected]96c77a72013-09-24 09:49:20470 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22471 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27472
bncce36dca22015-04-21 22:11:23473 post_request_.method = "POST";
474 post_request_.url = GURL(GetDefaultUrl());
475 post_request_.upload_data_stream = upload_data_stream_.get();
476 post_request_initialized_ = true;
[email protected]310240592010-08-05 21:04:19477 }
bncce36dca22015-04-21 22:11:23478 return post_request_;
[email protected]310240592010-08-05 21:04:19479 }
480
[email protected]69e6b4a2012-10-18 08:03:01481 const HttpRequestInfo& CreateFilePostRequest() {
bncce36dca22015-04-21 22:11:23482 if (!post_request_initialized_) {
[email protected]6cdfd7f2013-02-08 20:40:15483 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52484 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01485 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30486 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01487
olli.raula6df48b2a2015-11-26 07:40:22488 std::vector<scoped_ptr<UploadElementReader>> element_readers;
489 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
skyostil4891b25b2015-06-11 11:43:45490 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
olli.raula6df48b2a2015-11-26 07:40:22491 kUploadDataSize, base::Time())));
[email protected]96c77a72013-09-24 09:49:20492 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22493 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27494
bncce36dca22015-04-21 22:11:23495 post_request_.method = "POST";
496 post_request_.url = GURL(GetDefaultUrl());
497 post_request_.upload_data_stream = upload_data_stream_.get();
498 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01499 }
bncce36dca22015-04-21 22:11:23500 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01501 }
502
[email protected]999dd8c2013-11-12 06:45:54503 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
bncce36dca22015-04-21 22:11:23504 if (post_request_initialized_)
505 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54506
507 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52508 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]999dd8c2013-11-12 06:45:54509 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30510 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]92be8eb2014-08-07 22:57:11511 CHECK(base::MakeFileUnreadable(file_path));
[email protected]999dd8c2013-11-12 06:45:54512
olli.raula6df48b2a2015-11-26 07:40:22513 std::vector<scoped_ptr<UploadElementReader>> element_readers;
514 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
skyostil4891b25b2015-06-11 11:43:45515 base::ThreadTaskRunnerHandle::Get().get(), file_path, 0,
olli.raula6df48b2a2015-11-26 07:40:22516 kUploadDataSize, base::Time())));
[email protected]999dd8c2013-11-12 06:45:54517 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22518 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]999dd8c2013-11-12 06:45:54519
bncce36dca22015-04-21 22:11:23520 post_request_.method = "POST";
521 post_request_.url = GURL(GetDefaultUrl());
522 post_request_.upload_data_stream = upload_data_stream_.get();
523 post_request_initialized_ = true;
524 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54525 }
526
[email protected]69e6b4a2012-10-18 08:03:01527 const HttpRequestInfo& CreateComplexPostRequest() {
bncce36dca22015-04-21 22:11:23528 if (!post_request_initialized_) {
[email protected]69e6b4a2012-10-18 08:03:01529 const int kFileRangeOffset = 1;
530 const int kFileRangeLength = 3;
531 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
532
[email protected]6cdfd7f2013-02-08 20:40:15533 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52534 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01535 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30536 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01537
olli.raula6df48b2a2015-11-26 07:40:22538 std::vector<scoped_ptr<UploadElementReader>> element_readers;
539 element_readers.push_back(make_scoped_ptr(
540 new UploadBytesElementReader(kUploadData, kFileRangeOffset)));
541 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
skyostil4891b25b2015-06-11 11:43:45542 base::ThreadTaskRunnerHandle::Get().get(), file_path,
olli.raula6df48b2a2015-11-26 07:40:22543 kFileRangeOffset, kFileRangeLength, base::Time())));
544 element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader(
[email protected]69e6b4a2012-10-18 08:03:01545 kUploadData + kFileRangeOffset + kFileRangeLength,
olli.raula6df48b2a2015-11-26 07:40:22546 kUploadDataSize - (kFileRangeOffset + kFileRangeLength))));
[email protected]96c77a72013-09-24 09:49:20547 upload_data_stream_.reset(
olli.raula6df48b2a2015-11-26 07:40:22548 new ElementsUploadDataStream(std::move(element_readers), 0));
[email protected]329b68b2012-11-14 17:54:27549
bncce36dca22015-04-21 22:11:23550 post_request_.method = "POST";
551 post_request_.url = GURL(GetDefaultUrl());
552 post_request_.upload_data_stream = upload_data_stream_.get();
553 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01554 }
bncce36dca22015-04-21 22:11:23555 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01556 }
557
[email protected]0c9bf872011-03-04 17:53:22558 const HttpRequestInfo& CreateChunkedPostRequest() {
bncce36dca22015-04-21 22:11:23559 if (!chunked_post_request_initialized_) {
mmenkecbc2b712014-10-09 20:29:07560 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
bncce36dca22015-04-21 22:11:23561 chunked_post_request_.method = "POST";
562 chunked_post_request_.url = GURL(GetDefaultUrl());
563 chunked_post_request_.upload_data_stream =
mmenkecbc2b712014-10-09 20:29:07564 upload_chunked_data_stream_.get();
bncce36dca22015-04-21 22:11:23565 chunked_post_request_initialized_ = true;
[email protected]0c9bf872011-03-04 17:53:22566 }
bncce36dca22015-04-21 22:11:23567 return chunked_post_request_;
[email protected]0c9bf872011-03-04 17:53:22568 }
569
[email protected]19ec8a72010-08-23 03:38:23570 // Read the result of a particular transaction, knowing that we've got
571 // multiple transactions in the read pipeline; so as we read, we may have
572 // to skip over data destined for other transactions while we consume
573 // the data for |trans|.
574 int ReadResult(HttpNetworkTransaction* trans,
[email protected]19ec8a72010-08-23 03:38:23575 std::string* result) {
576 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58577
[email protected]19ec8a72010-08-23 03:38:23578 int bytes_read = 0;
bnc301745a2015-03-10 03:22:16579 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(kSize));
[email protected]49639fa2011-12-20 23:22:41580 TestCompletionCallback callback;
[email protected]19ec8a72010-08-23 03:38:23581 while (true) {
[email protected]90499482013-06-01 00:39:50582 int rv = trans->Read(buf.get(), kSize, callback.callback());
[email protected]19ec8a72010-08-23 03:38:23583 if (rv == ERR_IO_PENDING) {
[email protected]19ec8a72010-08-23 03:38:23584 rv = callback.WaitForResult();
585 } else if (rv <= 0) {
586 break;
587 }
588 result->append(buf->data(), rv);
589 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58590 }
[email protected]19ec8a72010-08-23 03:38:23591 return bytes_read;
592 }
[email protected]e3ebba0f2010-08-05 17:59:58593
[email protected]19ec8a72010-08-23 03:38:23594 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
595 // This lengthy block is reaching into the pool to dig out the active
596 // session. Once we have the session, we verify that the streams are
597 // all closed and not leaked at this point.
598 const GURL& url = helper.request().url;
rchebf12982015-04-10 01:15:00599 HostPortPair host_port_pair(url.host(), 443);
[email protected]e6d017652013-05-17 18:01:40600 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:53601 PRIVACY_MODE_DISABLED);
[email protected]19ec8a72010-08-23 03:38:23602 BoundNetLog log;
mmenkee65e7af2015-10-13 17:16:42603 HttpNetworkSession* session = helper.session();
[email protected]795cbf82013-07-22 09:37:27604 base::WeakPtr<SpdySession> spdy_session =
[email protected]04644d42013-07-08 04:29:59605 session->spdy_session_pool()->FindAvailableSession(key, log);
[email protected]41d64e82013-07-03 22:44:26606 ASSERT_TRUE(spdy_session != NULL);
[email protected]19ec8a72010-08-23 03:38:23607 EXPECT_EQ(0u, spdy_session->num_active_streams());
608 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
609 }
[email protected]e3ebba0f2010-08-05 17:59:58610
rch08e3aa3e2015-05-16 14:27:52611 void RunServerPushTest(SequencedSocketData* data,
[email protected]e3ebba0f2010-08-05 17:59:58612 HttpResponseInfo* response,
[email protected]a7a265ef2010-12-08 18:05:57613 HttpResponseInfo* push_response,
[email protected]8a0fc822013-06-27 20:52:43614 const std::string& expected) {
[email protected]262eec82013-03-19 21:01:36615 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50616 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:58617 helper.RunPreTestSetup();
[email protected]d08358502010-12-03 22:04:03618 helper.AddData(data);
[email protected]e3ebba0f2010-08-05 17:59:58619
620 HttpNetworkTransaction* trans = helper.trans();
621
622 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:41623 TestCompletionCallback callback;
624 int rv = trans->Start(
625 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:58626 EXPECT_EQ(ERR_IO_PENDING, rv);
627 rv = callback.WaitForResult();
628
629 // Request the pushed path.
[email protected]e3ebba0f2010-08-05 17:59:58630 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:42631 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]49639fa2011-12-20 23:22:41632 rv = trans2->Start(
633 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:58634 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:17635 base::RunLoop().RunUntilIdle();
[email protected]e3ebba0f2010-08-05 17:59:58636
[email protected]513963e2013-06-15 01:53:04637 // The data for the pushed path may be coming in more than 1 frame. Compile
[email protected]e3ebba0f2010-08-05 17:59:58638 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23639
640 // Read the server push body.
641 std::string result2;
rch0aecfd82015-05-19 17:22:32642 ReadResult(trans2.get(), &result2);
[email protected]19ec8a72010-08-23 03:38:23643 // Read the response body.
[email protected]e3ebba0f2010-08-05 17:59:58644 std::string result;
rch0aecfd82015-05-19 17:22:32645 ReadResult(trans, &result);
[email protected]e3ebba0f2010-08-05 17:59:58646
647 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:17648 EXPECT_TRUE(data->AllReadDataConsumed());
649 EXPECT_TRUE(data->AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:58650
651 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23652 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
653 << result2
654 << "||||| Expected data: "
655 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58656
657 // Verify the SYN_REPLY.
658 // Copy the response info, because trans goes away.
659 *response = *trans->GetResponseInfo();
[email protected]a7a265ef2010-12-08 18:05:57660 *push_response = *trans2->GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23661
662 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58663 }
664
[email protected]49639fa2011-12-20 23:22:41665 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
666 int result) {
667 helper->ResetTrans();
668 }
669
mmenkee65e7af2015-10-13 17:16:42670 static void StartTransactionCallback(HttpNetworkSession* session,
671 GURL url,
672 int result) {
[email protected]49639fa2011-12-20 23:22:41673 scoped_ptr<HttpNetworkTransaction> trans(
mmenkee65e7af2015-10-13 17:16:42674 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
[email protected]49639fa2011-12-20 23:22:41675 TestCompletionCallback callback;
676 HttpRequestInfo request;
677 request.method = "GET";
rchebf12982015-04-10 01:15:00678 request.url = url;
[email protected]49639fa2011-12-20 23:22:41679 request.load_flags = 0;
680 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
681 EXPECT_EQ(ERR_IO_PENDING, rv);
682 callback.WaitForResult();
683 }
684
mmenkecbc2b712014-10-09 20:29:07685 ChunkedUploadDataStream* upload_chunked_data_stream() const {
686 return upload_chunked_data_stream_.get();
687 }
688
rchebf12982015-04-10 01:15:00689 const char* GetDefaultUrl() {
690 switch (GetParam().ssl_type) {
691 case HTTP_SPDY_VIA_ALT_SVC:
bncce36dca22015-04-21 22:11:23692 return "http://www.example.org";
rchebf12982015-04-10 01:15:00693 case HTTPS_SPDY_VIA_NPN:
bncce36dca22015-04-21 22:11:23694 return "https://www.example.org";
rchebf12982015-04-10 01:15:00695 default:
696 NOTREACHED();
697 return "";
698 }
699 }
700
701 std::string GetDefaultUrlWithPath(const char* path) {
702 return std::string(GetDefaultUrl()) + path;
703 }
704
[email protected]9ec54f82013-05-10 02:53:05705 SpdyTestUtil spdy_util_;
706
[email protected]d3cee19d2010-06-22 18:42:18707 private:
mmenkecbc2b712014-10-09 20:29:07708 scoped_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
[email protected]329b68b2012-11-14 17:54:27709 scoped_ptr<UploadDataStream> upload_data_stream_;
bncce36dca22015-04-21 22:11:23710 bool get_request_initialized_;
711 bool post_request_initialized_;
712 bool chunked_post_request_initialized_;
713 HttpRequestInfo get_request_;
714 HttpRequestInfo post_request_;
715 HttpRequestInfo chunked_post_request_;
716 HttpRequestInfo get_push_request_;
[email protected]ea1a3f62012-11-16 20:34:23717 base::ScopedTempDir temp_dir_;
[email protected]aea80602009-09-18 00:55:08718};
719
720//-----------------------------------------------------------------------------
[email protected]9e9e842e2010-07-23 23:09:15721// All tests are run with three different connection types: SPDY after NPN
722// negotiation, SPDY without SSL, and SPDY with SSL.
[email protected]513963e2013-06-15 01:53:04723//
724// TODO(akalin): Use ::testing::Combine() when we are able to use
725// <tr1/tuple>.
726INSTANTIATE_TEST_CASE_P(
727 Spdy,
728 SpdyNetworkTransactionTest,
729 ::testing::Values(
rdsmithebb50aa2015-11-12 03:44:38730 SpdyNetworkTransactionTestParams(kProtoSPDY31,
731 HTTPS_SPDY_VIA_NPN,
732 false),
733 SpdyNetworkTransactionTestParams(kProtoSPDY31,
734 HTTP_SPDY_VIA_ALT_SVC,
735 false),
736 SpdyNetworkTransactionTestParams(kProtoHTTP2,
737 HTTPS_SPDY_VIA_NPN,
738 false),
739 SpdyNetworkTransactionTestParams(kProtoHTTP2, HTTPS_SPDY_VIA_NPN, true),
740 SpdyNetworkTransactionTestParams(kProtoHTTP2,
741 HTTP_SPDY_VIA_ALT_SVC,
742 false),
743 SpdyNetworkTransactionTestParams(kProtoHTTP2,
744 HTTP_SPDY_VIA_ALT_SVC,
745 true)));
[email protected]aea80602009-09-18 00:55:08746
[email protected]3caf5542010-07-16 15:19:47747// Verify HttpNetworkTransaction constructor.
[email protected]513963e2013-06-15 01:53:04748TEST_P(SpdyNetworkTransactionTest, Constructor) {
[email protected]bb88e1d32013-05-03 23:11:07749 scoped_ptr<SpdySessionDependencies> session_deps(
[email protected]513963e2013-06-15 01:53:04750 CreateSpdySessionDependencies(GetParam()));
mmenkee65e7af2015-10-13 17:16:42751 scoped_ptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:07752 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
[email protected]262eec82013-03-19 21:01:36753 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:50754 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]aea80602009-09-18 00:55:08755}
756
[email protected]513963e2013-06-15 01:53:04757TEST_P(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38758 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:46759 scoped_ptr<SpdyFrame> req(
760 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:52761 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]72552f02009-10-28 15:25:01762
[email protected]513963e2013-06-15 01:53:04763 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
764 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]72552f02009-10-28 15:25:01765 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52766 CreateMockRead(*resp, 1),
767 CreateMockRead(*body, 2),
768 MockRead(ASYNC, 0, 3) // EOF
[email protected]72552f02009-10-28 15:25:01769 };
770
rch08e3aa3e2015-05-16 14:27:52771 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:36772 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50773 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:57774 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:47775 TransactionHelperResult out = helper.output();
[email protected]72552f02009-10-28 15:25:01776 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:02777 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]72552f02009-10-28 15:25:01778 EXPECT_EQ("hello!", out.response_data);
779}
780
[email protected]513963e2013-06-15 01:53:04781TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
[email protected]3d08dd382013-10-19 00:13:11782 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
[email protected]31ae7ab2012-04-24 21:09:05783 p = RequestPriority(p + 1)) {
[email protected]c9c6f5c2010-07-31 01:30:03784 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:46785 scoped_ptr<SpdyFrame> req(
786 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
rdsmithebb50aa2015-11-12 03:44:38787 spdy_util_.UpdateWithStreamDestruction(1);
rch08e3aa3e2015-05-16 14:27:52788 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]c9c6f5c2010-07-31 01:30:03789
[email protected]86aa87b2013-02-15 01:10:03790 SpdyPriority spdy_prio = 0;
[email protected]513963e2013-06-15 01:53:04791 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
[email protected]c9c6f5c2010-07-31 01:30:03792 // this repeats the RequestPriority-->SpdyPriority mapping from
793 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
794 // sure it's being done right.
[email protected]513963e2013-06-15 01:53:04795 if (spdy_util_.spdy_version() < SPDY3) {
mmenkecbc2b712014-10-09 20:29:07796 switch (p) {
[email protected]513963e2013-06-15 01:53:04797 case HIGHEST:
798 EXPECT_EQ(0, spdy_prio);
799 break;
800 case MEDIUM:
801 EXPECT_EQ(1, spdy_prio);
802 break;
803 case LOW:
804 case LOWEST:
805 EXPECT_EQ(2, spdy_prio);
806 break;
807 case IDLE:
808 EXPECT_EQ(3, spdy_prio);
809 break;
810 default:
811 FAIL();
812 }
813 } else {
bnce8aa2702015-08-17 18:11:05814 switch (p) {
[email protected]513963e2013-06-15 01:53:04815 case HIGHEST:
816 EXPECT_EQ(0, spdy_prio);
817 break;
818 case MEDIUM:
819 EXPECT_EQ(1, spdy_prio);
820 break;
821 case LOW:
822 EXPECT_EQ(2, spdy_prio);
823 break;
824 case LOWEST:
825 EXPECT_EQ(3, spdy_prio);
826 break;
827 case IDLE:
828 EXPECT_EQ(4, spdy_prio);
829 break;
830 default:
831 FAIL();
832 }
[email protected]c9c6f5c2010-07-31 01:30:03833 }
834
[email protected]513963e2013-06-15 01:53:04835 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
836 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c9c6f5c2010-07-31 01:30:03837 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52838 CreateMockRead(*resp, 1),
839 CreateMockRead(*body, 2),
840 MockRead(ASYNC, 0, 3) // EOF
[email protected]c9c6f5c2010-07-31 01:30:03841 };
842
rch08e3aa3e2015-05-16 14:27:52843 SequencedSocketData data(reads, arraysize(reads), writes,
844 arraysize(writes));
[email protected]c9c6f5c2010-07-31 01:30:03845 HttpRequestInfo http_req = CreateGetRequest();
[email protected]c9c6f5c2010-07-31 01:30:03846
[email protected]262eec82013-03-19 21:01:36847 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
[email protected]61b4efc2012-04-27 18:12:50848 GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:57849 helper.RunToCompletion(&data);
[email protected]c9c6f5c2010-07-31 01:30:03850 TransactionHelperResult out = helper.output();
851 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:02852 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]c9c6f5c2010-07-31 01:30:03853 EXPECT_EQ("hello!", out.response_data);
854 }
855}
856
[email protected]2bd93022010-07-17 00:58:44857// Start three gets simultaniously; making sure that multiplexed
858// streams work properly.
859
860// This can't use the TransactionHelper method, since it only
861// handles a single transaction, and finishes them as soon
862// as it launches them.
863
864// TODO(gavinp): create a working generalized TransactionHelper that
865// can allow multiple streams in flight.
866
[email protected]513963e2013-06-15 01:53:04867TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
[email protected]cdf8f7e72013-05-23 10:56:46868 scoped_ptr<SpdyFrame> req(
869 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04870 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
871 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
872 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:44873
[email protected]cdf8f7e72013-05-23 10:56:46874 scoped_ptr<SpdyFrame> req2(
875 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04876 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
877 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
878 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:44879
[email protected]cdf8f7e72013-05-23 10:56:46880 scoped_ptr<SpdyFrame> req3(
881 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04882 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
883 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
884 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44885
[email protected]1b323172011-03-01 17:50:17886 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:52887 CreateMockWrite(*req, 0),
888 CreateMockWrite(*req2, 3),
889 CreateMockWrite(*req3, 6),
[email protected]2bd93022010-07-17 00:58:44890 };
891 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52892 CreateMockRead(*resp, 1),
893 CreateMockRead(*body, 2),
894 CreateMockRead(*resp2, 4),
895 CreateMockRead(*body2, 5),
896 CreateMockRead(*resp3, 7),
897 CreateMockRead(*body3, 8),
[email protected]2bd93022010-07-17 00:58:44898
rch08e3aa3e2015-05-16 14:27:52899 CreateMockRead(*fbody, 9),
900 CreateMockRead(*fbody2, 10),
901 CreateMockRead(*fbody3, 11),
[email protected]2bd93022010-07-17 00:58:44902
rch08e3aa3e2015-05-16 14:27:52903 MockRead(ASYNC, 0, 12), // EOF
[email protected]2bd93022010-07-17 00:58:44904 };
rch08e3aa3e2015-05-16 14:27:52905 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
mmenkecc2298e2015-12-07 18:20:18906 SequencedSocketData data_placeholder1(NULL, 0, NULL, 0);
907 SequencedSocketData data_placeholder2(NULL, 0, NULL, 0);
[email protected]2bd93022010-07-17 00:58:44908
909 BoundNetLog log;
910 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36911 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50912 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:08913 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57914 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49915 // We require placeholder data because three get requests are sent out at
916 // the same time which results in three sockets being connected. The first
917 // on will negotiate SPDY and will be used for all requests.
mmenkecc2298e2015-12-07 18:20:18918 helper.AddData(&data_placeholder1);
919 helper.AddData(&data_placeholder2);
[email protected]bdebd1b2010-08-09 20:18:08920 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:42921 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:08922 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:42923 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:08924 scoped_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:42925 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]2bd93022010-07-17 00:58:44926
[email protected]49639fa2011-12-20 23:22:41927 TestCompletionCallback callback1;
928 TestCompletionCallback callback2;
929 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44930
[email protected]bdebd1b2010-08-09 20:18:08931 HttpRequestInfo httpreq1 = CreateGetRequest();
932 HttpRequestInfo httpreq2 = CreateGetRequest();
933 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:44934
[email protected]49639fa2011-12-20 23:22:41935 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08936 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41937 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08938 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41939 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08940 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:44941
[email protected]bdebd1b2010-08-09 20:18:08942 out.rv = callback1.WaitForResult();
943 ASSERT_EQ(OK, out.rv);
944 out.rv = callback3.WaitForResult();
945 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44946
[email protected]bdebd1b2010-08-09 20:18:08947 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:50948 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:08949 EXPECT_TRUE(response1->was_fetched_via_spdy);
950 out.status_line = response1->headers->GetStatusLine();
951 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:44952
[email protected]bdebd1b2010-08-09 20:18:08953 trans2->GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:44954
[email protected]bdebd1b2010-08-09 20:18:08955 out.rv = ReadTransaction(trans1.get(), &out.response_data);
956 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:44957 EXPECT_EQ(OK, out.rv);
958
[email protected]2bd93022010-07-17 00:58:44959 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:02960 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:44961 EXPECT_EQ("hello!hello!", out.response_data);
962}
963
[email protected]513963e2013-06-15 01:53:04964TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
[email protected]cdf8f7e72013-05-23 10:56:46965 scoped_ptr<SpdyFrame> req(
966 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04967 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
968 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
969 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1b323172011-03-01 17:50:17970
[email protected]cdf8f7e72013-05-23 10:56:46971 scoped_ptr<SpdyFrame> req2(
972 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04973 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
974 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
975 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]1b323172011-03-01 17:50:17976
977 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:52978 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 3),
[email protected]1b323172011-03-01 17:50:17979 };
980 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52981 CreateMockRead(*resp, 1),
982 CreateMockRead(*body, 2),
983 CreateMockRead(*resp2, 4),
984 CreateMockRead(*body2, 5),
985 CreateMockRead(*fbody, 6),
986 CreateMockRead(*fbody2, 7),
987 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:17988 };
rch08e3aa3e2015-05-16 14:27:52989 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1b323172011-03-01 17:50:17990
[email protected]d973e99a2012-02-17 21:02:36991 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
rch08e3aa3e2015-05-16 14:27:52992 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:57993 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17994
995 BoundNetLog log;
996 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36997 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50998 BoundNetLog(), GetParam(), NULL);
[email protected]1b323172011-03-01 17:50:17999 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571000 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:491001 // We require placeholder data because two requests are sent out at
1002 // the same time which results in two sockets being connected. The first
1003 // on will negotiate SPDY and will be used for all requests.
[email protected]dd54bd82012-07-19 23:44:571004 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:171005 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421006 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]1b323172011-03-01 17:50:171007 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421008 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]1b323172011-03-01 17:50:171009
[email protected]49639fa2011-12-20 23:22:411010 TestCompletionCallback callback1;
1011 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:171012
1013 HttpRequestInfo httpreq1 = CreateGetRequest();
1014 HttpRequestInfo httpreq2 = CreateGetRequest();
1015
[email protected]49639fa2011-12-20 23:22:411016 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]1b323172011-03-01 17:50:171017 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411018 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]1b323172011-03-01 17:50:171019 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1020
1021 out.rv = callback1.WaitForResult();
1022 ASSERT_EQ(OK, out.rv);
1023 out.rv = callback2.WaitForResult();
1024 ASSERT_EQ(OK, out.rv);
1025
1026 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501027 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171028 EXPECT_TRUE(response1->was_fetched_via_spdy);
1029 out.status_line = response1->headers->GetStatusLine();
1030 out.response_info = *response1;
1031 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1032 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021033 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:171034 EXPECT_EQ("hello!hello!", out.response_data);
1035
1036 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501037 EXPECT_TRUE(response2->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171038 EXPECT_TRUE(response2->was_fetched_via_spdy);
1039 out.status_line = response2->headers->GetStatusLine();
1040 out.response_info = *response2;
1041 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1042 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021043 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:171044 EXPECT_EQ("hello!hello!", out.response_data);
1045
1046 helper.VerifyDataConsumed();
1047}
1048
[email protected]513963e2013-06-15 01:53:041049TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
[email protected]cdf8f7e72013-05-23 10:56:461050 scoped_ptr<SpdyFrame> req(
1051 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041052 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1053 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1054 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1b323172011-03-01 17:50:171055
[email protected]cdf8f7e72013-05-23 10:56:461056 scoped_ptr<SpdyFrame> req2(
1057 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041058 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1059 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1060 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]1b323172011-03-01 17:50:171061
1062 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521063 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 3),
[email protected]1b323172011-03-01 17:50:171064 };
1065 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521066 CreateMockRead(*resp, 1),
1067 CreateMockRead(*body, 2),
1068 CreateMockRead(*resp2, 4),
1069 CreateMockRead(*body2, 5),
1070 CreateMockRead(*fbody, 6),
1071 CreateMockRead(*fbody2, 7),
1072 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:171073 };
rch08e3aa3e2015-05-16 14:27:521074 SequencedSocketData preconnect_data(reads, arraysize(reads), writes,
1075 arraysize(writes));
[email protected]1b323172011-03-01 17:50:171076
[email protected]d973e99a2012-02-17 21:02:361077 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
[email protected]1b323172011-03-01 17:50:171078
rch08e3aa3e2015-05-16 14:27:521079 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:571080 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:171081
1082 BoundNetLog log;
1083 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361084 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501085 BoundNetLog(), GetParam(), NULL);
[email protected]1b323172011-03-01 17:50:171086 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571087 helper.AddData(&preconnect_data);
[email protected]1b323172011-03-01 17:50:171088 // We require placeholder data because 3 connections are attempted (first is
1089 // the preconnect, 2nd and 3rd are the never finished connections.
[email protected]dd54bd82012-07-19 23:44:571090 helper.AddData(&data_placeholder);
1091 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:171092
1093 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421094 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]1b323172011-03-01 17:50:171095 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421096 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]1b323172011-03-01 17:50:171097
[email protected]49639fa2011-12-20 23:22:411098 TestCompletionCallback callback1;
1099 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:171100
1101 HttpRequestInfo httpreq = CreateGetRequest();
1102
1103 // Preconnect the first.
1104 SSLConfig preconnect_ssl_config;
1105 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1106 HttpStreamFactory* http_stream_factory =
1107 helper.session()->http_stream_factory();
bnc1f295372015-10-21 23:24:221108 helper.session()->GetAlpnProtos(&preconnect_ssl_config.alpn_protos);
1109 helper.session()->GetNpnProtos(&preconnect_ssl_config.npn_protos);
[email protected]1b323172011-03-01 17:50:171110
mmenked1205bd3972015-07-15 22:26:351111 http_stream_factory->PreconnectStreams(1, httpreq, preconnect_ssl_config,
1112 preconnect_ssl_config);
[email protected]1b323172011-03-01 17:50:171113
[email protected]49639fa2011-12-20 23:22:411114 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
[email protected]1b323172011-03-01 17:50:171115 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411116 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
[email protected]1b323172011-03-01 17:50:171117 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1118
1119 out.rv = callback1.WaitForResult();
1120 ASSERT_EQ(OK, out.rv);
1121 out.rv = callback2.WaitForResult();
1122 ASSERT_EQ(OK, out.rv);
1123
1124 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501125 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171126 EXPECT_TRUE(response1->was_fetched_via_spdy);
1127 out.status_line = response1->headers->GetStatusLine();
1128 out.response_info = *response1;
1129 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1130 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021131 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:171132 EXPECT_EQ("hello!hello!", out.response_data);
1133
1134 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501135 EXPECT_TRUE(response2->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171136 EXPECT_TRUE(response2->was_fetched_via_spdy);
1137 out.status_line = response2->headers->GetStatusLine();
1138 out.response_info = *response2;
1139 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1140 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021141 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1b323172011-03-01 17:50:171142 EXPECT_EQ("hello!hello!", out.response_data);
1143
1144 helper.VerifyDataConsumed();
1145}
1146
[email protected]2bd93022010-07-17 00:58:441147// Similar to ThreeGets above, however this test adds a SETTINGS
1148// frame. The SETTINGS frame is read during the IO loop waiting on
1149// the first transaction completion, and sets a maximum concurrent
1150// stream limit of 1. This means that our IO loop exists after the
1151// second transaction completes, so we can assert on read_index().
[email protected]513963e2013-06-15 01:53:041152TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:441153 // Construct the request.
rdsmithebb50aa2015-11-12 03:44:381154 // Each request fully completes before the next starts.
[email protected]cdf8f7e72013-05-23 10:56:461155 scoped_ptr<SpdyFrame> req(
1156 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041157 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1158 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1159 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381160 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441161
[email protected]cdf8f7e72013-05-23 10:56:461162 scoped_ptr<SpdyFrame> req2(
1163 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041164 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1165 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1166 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:381167 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:441168
[email protected]cdf8f7e72013-05-23 10:56:461169 scoped_ptr<SpdyFrame> req3(
1170 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041171 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1172 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1173 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:441174
[email protected]18b28ab2012-04-18 02:14:421175 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281176 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421177 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1178 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201179 scoped_ptr<SpdyFrame> settings_frame(
1180 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211181 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441182
[email protected]2d6728692011-03-12 01:39:551183 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521184 CreateMockWrite(*req, 0),
1185 CreateMockWrite(*settings_ack, 5),
1186 CreateMockWrite(*req2, 6),
1187 CreateMockWrite(*req3, 10),
[email protected]2bd93022010-07-17 00:58:441188 };
[email protected]2d6728692011-03-12 01:39:551189
[email protected]2bd93022010-07-17 00:58:441190 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521191 CreateMockRead(*settings_frame, 1),
1192 CreateMockRead(*resp, 2),
1193 CreateMockRead(*body, 3),
1194 CreateMockRead(*fbody, 4),
1195 CreateMockRead(*resp2, 7),
1196 CreateMockRead(*body2, 8),
1197 CreateMockRead(*fbody2, 9),
1198 CreateMockRead(*resp3, 11),
1199 CreateMockRead(*body3, 12),
1200 CreateMockRead(*fbody3, 13),
[email protected]2bd93022010-07-17 00:58:441201
rch08e3aa3e2015-05-16 14:27:521202 MockRead(ASYNC, 0, 14), // EOF
[email protected]2bd93022010-07-17 00:58:441203 };
1204
rch08e3aa3e2015-05-16 14:27:521205 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441206
1207 BoundNetLog log;
1208 TransactionHelperResult out;
1209 {
[email protected]262eec82013-03-19 21:01:361210 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501211 BoundNetLog(), GetParam(), NULL);
[email protected]2d6728692011-03-12 01:39:551212 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571213 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:081214 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421215 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081216 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421217 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081218 scoped_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:421219 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]2bd93022010-07-17 00:58:441220
[email protected]49639fa2011-12-20 23:22:411221 TestCompletionCallback callback1;
1222 TestCompletionCallback callback2;
1223 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441224
1225 HttpRequestInfo httpreq1 = CreateGetRequest();
1226 HttpRequestInfo httpreq2 = CreateGetRequest();
1227 HttpRequestInfo httpreq3 = CreateGetRequest();
1228
[email protected]49639fa2011-12-20 23:22:411229 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]2bd93022010-07-17 00:58:441230 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]513963e2013-06-15 01:53:041231 // Run transaction 1 through quickly to force a read of our SETTINGS
1232 // frame.
[email protected]2bd93022010-07-17 00:58:441233 out.rv = callback1.WaitForResult();
[email protected]bdebd1b2010-08-09 20:18:081234 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441235
[email protected]49639fa2011-12-20 23:22:411236 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]2bd93022010-07-17 00:58:441237 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411238 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]2bd93022010-07-17 00:58:441239 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1240 out.rv = callback2.WaitForResult();
1241 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441242
1243 out.rv = callback3.WaitForResult();
1244 ASSERT_EQ(OK, out.rv);
1245
1246 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081247 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501248 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]2bd93022010-07-17 00:58:441249 EXPECT_TRUE(response1->was_fetched_via_spdy);
1250 out.status_line = response1->headers->GetStatusLine();
1251 out.response_info = *response1;
1252 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1253 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021254 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441255 EXPECT_EQ("hello!hello!", out.response_data);
1256
1257 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1258 out.status_line = response2->headers->GetStatusLine();
1259 out.response_info = *response2;
1260 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1261 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021262 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441263 EXPECT_EQ("hello!hello!", out.response_data);
1264
1265 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1266 out.status_line = response3->headers->GetStatusLine();
1267 out.response_info = *response3;
1268 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1269 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021270 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]2bd93022010-07-17 00:58:441271 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:261272
1273 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441274 }
1275 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441276}
1277
1278// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1279// a fourth transaction. The third and fourth transactions have
1280// different data ("hello!" vs "hello!hello!") and because of the
1281// user specified priority, we expect to see them inverted in
1282// the response from the server.
[email protected]513963e2013-06-15 01:53:041283TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:441284 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461285 scoped_ptr<SpdyFrame> req(
1286 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041287 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1288 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1289 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381290 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441291
[email protected]cdf8f7e72013-05-23 10:56:461292 scoped_ptr<SpdyFrame> req2(
1293 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041294 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1295 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1296 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
rdsmithebb50aa2015-11-12 03:44:381297 spdy_util_.UpdateWithStreamDestruction(3);
[email protected]2bd93022010-07-17 00:58:441298
[email protected]ff98d7f02012-03-22 21:44:191299 scoped_ptr<SpdyFrame> req4(
[email protected]cdf8f7e72013-05-23 10:56:461300 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
[email protected]513963e2013-06-15 01:53:041301 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1302 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
rdsmithebb50aa2015-11-12 03:44:381303 spdy_util_.UpdateWithStreamDestruction(5);
[email protected]2bd93022010-07-17 00:58:441304
[email protected]cdf8f7e72013-05-23 10:56:461305 scoped_ptr<SpdyFrame> req3(
1306 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041307 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1308 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1309 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
[email protected]2bd93022010-07-17 00:58:441310
[email protected]18b28ab2012-04-18 02:14:421311 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281312 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421313 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1314 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201315 scoped_ptr<SpdyFrame> settings_frame(
1316 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211317 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
rch08e3aa3e2015-05-16 14:27:521318 MockWrite writes[] = {
1319 CreateMockWrite(*req, 0),
1320 CreateMockWrite(*settings_ack, 5),
1321 // By making these synchronous, it guarantees that they are not *started*
1322 // before their sequence number, which in turn verifies that only a single
1323 // request is in-flight at a time.
1324 CreateMockWrite(*req2, 6, SYNCHRONOUS),
1325 CreateMockWrite(*req4, 10, SYNCHRONOUS),
1326 CreateMockWrite(*req3, 13, SYNCHRONOUS),
[email protected]2bd93022010-07-17 00:58:441327 };
1328 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521329 CreateMockRead(*settings_frame, 1),
1330 CreateMockRead(*resp, 2),
1331 CreateMockRead(*body, 3),
1332 CreateMockRead(*fbody, 4),
1333 CreateMockRead(*resp2, 7),
1334 CreateMockRead(*body2, 8),
1335 CreateMockRead(*fbody2, 9),
1336 CreateMockRead(*resp4, 11),
1337 CreateMockRead(*fbody4, 12),
1338 CreateMockRead(*resp3, 14),
1339 CreateMockRead(*body3, 15),
1340 CreateMockRead(*fbody3, 16),
[email protected]2bd93022010-07-17 00:58:441341
rch08e3aa3e2015-05-16 14:27:521342 MockRead(ASYNC, 0, 17), // EOF
[email protected]2bd93022010-07-17 00:58:441343 };
rch08e3aa3e2015-05-16 14:27:521344 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441345 BoundNetLog log;
1346 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361347 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1348 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081349 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571350 helper.AddData(&data);
rch08e3aa3e2015-05-16 14:27:521351
[email protected]bdebd1b2010-08-09 20:18:081352 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421353 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081354 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421355 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081356 scoped_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:421357 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081358 scoped_ptr<HttpNetworkTransaction> trans4(
mmenkee65e7af2015-10-13 17:16:421359 new HttpNetworkTransaction(HIGHEST, helper.session()));
[email protected]2bd93022010-07-17 00:58:441360
[email protected]49639fa2011-12-20 23:22:411361 TestCompletionCallback callback1;
1362 TestCompletionCallback callback2;
1363 TestCompletionCallback callback3;
1364 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:441365
[email protected]bdebd1b2010-08-09 20:18:081366 HttpRequestInfo httpreq1 = CreateGetRequest();
1367 HttpRequestInfo httpreq2 = CreateGetRequest();
1368 HttpRequestInfo httpreq3 = CreateGetRequest();
1369 HttpRequestInfo httpreq4 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441370
[email protected]49639fa2011-12-20 23:22:411371 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081372 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]e0935cc2012-03-24 14:12:481373 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081374 out.rv = callback1.WaitForResult();
1375 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441376
[email protected]49639fa2011-12-20 23:22:411377 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081378 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411379 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081380 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411381 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081382 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:441383
[email protected]bdebd1b2010-08-09 20:18:081384 out.rv = callback2.WaitForResult();
1385 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441386
[email protected]bdebd1b2010-08-09 20:18:081387 out.rv = callback3.WaitForResult();
1388 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441389
[email protected]bdebd1b2010-08-09 20:18:081390 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501391 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:081392 EXPECT_TRUE(response1->was_fetched_via_spdy);
1393 out.status_line = response1->headers->GetStatusLine();
1394 out.response_info = *response1;
1395 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1396 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021397 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081398 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441399
[email protected]bdebd1b2010-08-09 20:18:081400 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1401 out.status_line = response2->headers->GetStatusLine();
1402 out.response_info = *response2;
1403 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1404 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021405 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081406 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441407
[email protected]bdebd1b2010-08-09 20:18:081408 // notice: response3 gets two hellos, response4 gets one
1409 // hello, so we know dequeuing priority was respected.
1410 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1411 out.status_line = response3->headers->GetStatusLine();
1412 out.response_info = *response3;
1413 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1414 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021415 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081416 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441417
[email protected]bdebd1b2010-08-09 20:18:081418 out.rv = callback4.WaitForResult();
1419 EXPECT_EQ(OK, out.rv);
1420 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1421 out.status_line = response4->headers->GetStatusLine();
1422 out.response_info = *response4;
1423 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1424 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021425 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081426 EXPECT_EQ("hello!", out.response_data);
1427 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441428 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441429}
1430
1431// Similar to ThreeGetsMaxConcurrrent above, however, this test
rch08e3aa3e2015-05-16 14:27:521432// deletes a session in the middle of the transaction to ensure
[email protected]2bd93022010-07-17 00:58:441433// that we properly remove pendingcreatestream objects from
1434// the spdy_session
[email protected]513963e2013-06-15 01:53:041435TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:441436 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461437 scoped_ptr<SpdyFrame> req(
1438 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041439 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1440 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1441 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381442 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]2bd93022010-07-17 00:58:441443
[email protected]cdf8f7e72013-05-23 10:56:461444 scoped_ptr<SpdyFrame> req2(
1445 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041446 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1447 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1448 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441449
[email protected]18b28ab2012-04-18 02:14:421450 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281451 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421452 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1453 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201454 scoped_ptr<SpdyFrame> settings_frame(
1455 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211456 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441457
[email protected]d4a77c12014-05-15 20:45:211458 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521459 CreateMockWrite(*req, 0),
1460 CreateMockWrite(*settings_ack, 5),
1461 CreateMockWrite(*req2, 6),
[email protected]2bd93022010-07-17 00:58:441462 };
1463 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521464 CreateMockRead(*settings_frame, 1),
1465 CreateMockRead(*resp, 2),
1466 CreateMockRead(*body, 3),
1467 CreateMockRead(*fbody, 4),
1468 CreateMockRead(*resp2, 7),
1469 CreateMockRead(*body2, 8),
1470 CreateMockRead(*fbody2, 9),
1471 MockRead(ASYNC, 0, 10), // EOF
[email protected]2bd93022010-07-17 00:58:441472 };
1473
rch08e3aa3e2015-05-16 14:27:521474 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441475
1476 BoundNetLog log;
1477 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361478 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1479 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081480 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571481 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:081482 scoped_ptr<HttpNetworkTransaction> trans1(
mmenkee65e7af2015-10-13 17:16:421483 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081484 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:421485 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]bdebd1b2010-08-09 20:18:081486 scoped_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:421487 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]2bd93022010-07-17 00:58:441488
[email protected]49639fa2011-12-20 23:22:411489 TestCompletionCallback callback1;
1490 TestCompletionCallback callback2;
1491 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441492
[email protected]bdebd1b2010-08-09 20:18:081493 HttpRequestInfo httpreq1 = CreateGetRequest();
1494 HttpRequestInfo httpreq2 = CreateGetRequest();
1495 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441496
[email protected]49639fa2011-12-20 23:22:411497 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081498 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481499 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081500 out.rv = callback1.WaitForResult();
1501 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441502
[email protected]49639fa2011-12-20 23:22:411503 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081504 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411505 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081506 delete trans3.release();
1507 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1508 out.rv = callback2.WaitForResult();
1509 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441510
[email protected]bdebd1b2010-08-09 20:18:081511 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1512 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501513 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:081514 EXPECT_TRUE(response1->was_fetched_via_spdy);
1515 out.status_line = response1->headers->GetStatusLine();
1516 out.response_info = *response1;
1517 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1518 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021519 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081520 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441521
[email protected]bdebd1b2010-08-09 20:18:081522 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1523 ASSERT_TRUE(response2 != NULL);
1524 out.status_line = response2->headers->GetStatusLine();
1525 out.response_info = *response2;
1526 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1527 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021528 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bdebd1b2010-08-09 20:18:081529 EXPECT_EQ("hello!hello!", out.response_data);
1530 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441531 EXPECT_EQ(OK, out.rv);
[email protected]044dcc52010-09-17 15:44:261532}
[email protected]2bd93022010-07-17 00:58:441533
[email protected]448d4ca52012-03-04 04:12:231534namespace {
1535
[email protected]044dcc52010-09-17 15:44:261536// The KillerCallback will delete the transaction on error as part of the
1537// callback.
[email protected]49639fa2011-12-20 23:22:411538class KillerCallback : public TestCompletionCallbackBase {
[email protected]044dcc52010-09-17 15:44:261539 public:
1540 explicit KillerCallback(HttpNetworkTransaction* transaction)
[email protected]49639fa2011-12-20 23:22:411541 : transaction_(transaction),
[email protected]aa249b52013-04-30 01:04:321542 callback_(base::Bind(&KillerCallback::OnComplete,
1543 base::Unretained(this))) {
[email protected]044dcc52010-09-17 15:44:261544 }
1545
dchengb03027d2014-10-21 12:00:201546 ~KillerCallback() override {}
[email protected]49639fa2011-12-20 23:22:411547
1548 const CompletionCallback& callback() const { return callback_; }
1549
[email protected]044dcc52010-09-17 15:44:261550 private:
[email protected]49639fa2011-12-20 23:22:411551 void OnComplete(int result) {
1552 if (result < 0)
1553 delete transaction_;
1554
1555 SetResult(result);
1556 }
1557
[email protected]044dcc52010-09-17 15:44:261558 HttpNetworkTransaction* transaction_;
[email protected]49639fa2011-12-20 23:22:411559 CompletionCallback callback_;
[email protected]044dcc52010-09-17 15:44:261560};
1561
[email protected]448d4ca52012-03-04 04:12:231562} // namespace
1563
[email protected]044dcc52010-09-17 15:44:261564// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1565// closes the socket while we have a pending transaction waiting for
1566// a pending stream creation. http://crbug.com/52901
[email protected]513963e2013-06-15 01:53:041567TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
[email protected]044dcc52010-09-17 15:44:261568 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461569 scoped_ptr<SpdyFrame> req(
1570 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041571 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1572 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1573 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:381574 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]044dcc52010-09-17 15:44:261575
[email protected]cdf8f7e72013-05-23 10:56:461576 scoped_ptr<SpdyFrame> req2(
1577 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041578 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]044dcc52010-09-17 15:44:261579
[email protected]18b28ab2012-04-18 02:14:421580 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281581 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421582 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1583 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201584 scoped_ptr<SpdyFrame> settings_frame(
1585 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211586 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]044dcc52010-09-17 15:44:261587
[email protected]d4a77c12014-05-15 20:45:211588 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521589 CreateMockWrite(*req, 0),
1590 CreateMockWrite(*settings_ack, 5),
1591 CreateMockWrite(*req2, 6),
[email protected]044dcc52010-09-17 15:44:261592 };
1593 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521594 CreateMockRead(*settings_frame, 1),
1595 CreateMockRead(*resp, 2),
1596 CreateMockRead(*body, 3),
1597 CreateMockRead(*fin_body, 4),
1598 CreateMockRead(*resp2, 7),
1599 MockRead(ASYNC, ERR_CONNECTION_RESET, 8), // Abort!
[email protected]044dcc52010-09-17 15:44:261600 };
1601
rch08e3aa3e2015-05-16 14:27:521602 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1603 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]044dcc52010-09-17 15:44:261604
1605 BoundNetLog log;
1606 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361607 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1608 BoundNetLog(), GetParam(), NULL);
[email protected]044dcc52010-09-17 15:44:261609 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571610 helper.AddData(&data);
[email protected]044dcc52010-09-17 15:44:261611 // We require placeholder data because three get requests are sent out, so
1612 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571613 helper.AddData(&data_placeholder);
1614 helper.AddData(&data_placeholder);
mmenkee65e7af2015-10-13 17:16:421615 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
1616 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
[email protected]262eec82013-03-19 21:01:361617 HttpNetworkTransaction* trans3(
mmenkee65e7af2015-10-13 17:16:421618 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]044dcc52010-09-17 15:44:261619
[email protected]49639fa2011-12-20 23:22:411620 TestCompletionCallback callback1;
1621 TestCompletionCallback callback2;
[email protected]044dcc52010-09-17 15:44:261622 KillerCallback callback3(trans3);
1623
1624 HttpRequestInfo httpreq1 = CreateGetRequest();
1625 HttpRequestInfo httpreq2 = CreateGetRequest();
1626 HttpRequestInfo httpreq3 = CreateGetRequest();
1627
[email protected]49639fa2011-12-20 23:22:411628 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]044dcc52010-09-17 15:44:261629 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481630 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]044dcc52010-09-17 15:44:261631 out.rv = callback1.WaitForResult();
1632 ASSERT_EQ(OK, out.rv);
1633
[email protected]49639fa2011-12-20 23:22:411634 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]044dcc52010-09-17 15:44:261635 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411636 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]044dcc52010-09-17 15:44:261637 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1638 out.rv = callback3.WaitForResult();
1639 ASSERT_EQ(ERR_ABORTED, out.rv);
1640
[email protected]044dcc52010-09-17 15:44:261641 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1642 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501643 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]044dcc52010-09-17 15:44:261644 EXPECT_TRUE(response1->was_fetched_via_spdy);
1645 out.status_line = response1->headers->GetStatusLine();
1646 out.response_info = *response1;
1647 out.rv = ReadTransaction(&trans1, &out.response_data);
1648 EXPECT_EQ(OK, out.rv);
1649
1650 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1651 ASSERT_TRUE(response2 != NULL);
1652 out.status_line = response2->headers->GetStatusLine();
1653 out.response_info = *response2;
1654 out.rv = ReadTransaction(&trans2, &out.response_data);
1655 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1656
1657 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441658}
1659
[email protected]d8ef27b2010-08-06 17:34:391660// Test that a simple PUT request works.
[email protected]513963e2013-06-15 01:53:041661TEST_P(SpdyNetworkTransactionTest, Put) {
[email protected]d8ef27b2010-08-06 17:34:391662 // Setup the request
1663 HttpRequestInfo request;
1664 request.method = "PUT";
rchebf12982015-04-10 01:15:001665 request.url = GURL(GetDefaultUrl());
[email protected]d8ef27b2010-08-06 17:34:391666
[email protected]513963e2013-06-15 01:53:041667 scoped_ptr<SpdyHeaderBlock> put_headers(
rchebf12982015-04-10 01:15:001668 spdy_util_.ConstructPutHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291669 scoped_ptr<SpdyFrame> req(
1670 spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
[email protected]d8ef27b2010-08-06 17:34:391671 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521672 CreateMockWrite(*req, 0),
[email protected]d8ef27b2010-08-06 17:34:391673 };
1674
[email protected]745aa9c2014-06-27 02:21:291675 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041676 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391677 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521678 CreateMockRead(*resp, 1),
1679 CreateMockRead(*body, 2),
1680 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391681 };
1682
rch08e3aa3e2015-05-16 14:27:521683 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361684 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501685 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571686 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391687 TransactionHelperResult out = helper.output();
1688
1689 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021690 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391691}
1692
1693// Test that a simple HEAD request works.
[email protected]513963e2013-06-15 01:53:041694TEST_P(SpdyNetworkTransactionTest, Head) {
[email protected]d8ef27b2010-08-06 17:34:391695 // Setup the request
1696 HttpRequestInfo request;
1697 request.method = "HEAD";
rchebf12982015-04-10 01:15:001698 request.url = GURL(GetDefaultUrl());
[email protected]d8ef27b2010-08-06 17:34:391699
[email protected]513963e2013-06-15 01:53:041700 scoped_ptr<SpdyHeaderBlock> head_headers(
rchebf12982015-04-10 01:15:001701 spdy_util_.ConstructHeadHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291702 scoped_ptr<SpdyFrame> req(
1703 spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
[email protected]d8ef27b2010-08-06 17:34:391704 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521705 CreateMockWrite(*req, 0),
[email protected]d8ef27b2010-08-06 17:34:391706 };
1707
[email protected]745aa9c2014-06-27 02:21:291708 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041709 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391710 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521711 CreateMockRead(*resp, 1),
1712 CreateMockRead(*body, 2),
1713 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391714 };
1715
rch08e3aa3e2015-05-16 14:27:521716 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361717 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501718 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571719 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391720 TransactionHelperResult out = helper.output();
1721
1722 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021723 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]d8ef27b2010-08-06 17:34:391724}
1725
[email protected]72552f02009-10-28 15:25:011726// Test that a simple POST works.
[email protected]513963e2013-06-15 01:53:041727TEST_P(SpdyNetworkTransactionTest, Post) {
rchebf12982015-04-10 01:15:001728 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1729 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041730 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141731 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521732 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141733 };
[email protected]72552f02009-10-28 15:25:011734
[email protected]513963e2013-06-15 01:53:041735 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]ff57bb82009-11-12 06:52:141736 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521737 CreateMockRead(*resp, 2),
1738 CreateMockRead(*body, 3),
1739 MockRead(ASYNC, 0, 4) // EOF
[email protected]aea80602009-09-18 00:55:081740 };
1741
rch08e3aa3e2015-05-16 14:27:521742 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361743 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501744 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571745 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471746 TransactionHelperResult out = helper.output();
[email protected]aea80602009-09-18 00:55:081747 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021748 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]aea80602009-09-18 00:55:081749 EXPECT_EQ("hello!", out.response_data);
1750}
1751
[email protected]69e6b4a2012-10-18 08:03:011752// Test that a POST with a file works.
[email protected]513963e2013-06-15 01:53:041753TEST_P(SpdyNetworkTransactionTest, FilePost) {
rchebf12982015-04-10 01:15:001754 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1755 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041756 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011757 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521758 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011759 };
1760
[email protected]513963e2013-06-15 01:53:041761 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011762 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521763 CreateMockRead(*resp, 2),
1764 CreateMockRead(*body, 3),
1765 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011766 };
1767
rch08e3aa3e2015-05-16 14:27:521768 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361769 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
[email protected]69e6b4a2012-10-18 08:03:011770 BoundNetLog(), GetParam(), NULL);
1771 helper.RunToCompletion(&data);
1772 TransactionHelperResult out = helper.output();
1773 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021774 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011775 EXPECT_EQ("hello!", out.response_data);
1776}
1777
[email protected]999dd8c2013-11-12 06:45:541778// Test that a POST with a unreadable file fails.
1779TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1780 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521781 MockWrite(ASYNC, 0, 0) // EOF
[email protected]999dd8c2013-11-12 06:45:541782 };
1783 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521784 MockRead(ASYNC, 0, 1) // EOF
[email protected]999dd8c2013-11-12 06:45:541785 };
1786
rch08e3aa3e2015-05-16 14:27:521787 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]999dd8c2013-11-12 06:45:541788 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1789 DEFAULT_PRIORITY,
1790 BoundNetLog(), GetParam(), NULL);
1791 helper.RunPreTestSetup();
1792 helper.AddData(&data);
1793 helper.RunDefaultTest();
1794
1795 base::RunLoop().RunUntilIdle();
1796 helper.VerifyDataNotConsumed();
1797 EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1798}
1799
[email protected]69e6b4a2012-10-18 08:03:011800// Test that a complex POST works.
[email protected]513963e2013-06-15 01:53:041801TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
rchebf12982015-04-10 01:15:001802 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1803 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041804 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011805 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521806 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011807 };
1808
[email protected]513963e2013-06-15 01:53:041809 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011810 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521811 CreateMockRead(*resp, 2),
1812 CreateMockRead(*body, 3),
1813 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011814 };
1815
rch08e3aa3e2015-05-16 14:27:521816 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]69e6b4a2012-10-18 08:03:011817 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
[email protected]262eec82013-03-19 21:01:361818 DEFAULT_PRIORITY,
[email protected]69e6b4a2012-10-18 08:03:011819 BoundNetLog(), GetParam(), NULL);
1820 helper.RunToCompletion(&data);
1821 TransactionHelperResult out = helper.output();
1822 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021823 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]69e6b4a2012-10-18 08:03:011824 EXPECT_EQ("hello!", out.response_data);
1825}
1826
[email protected]0c9bf872011-03-04 17:53:221827// Test that a chunked POST works.
[email protected]513963e2013-06-15 01:53:041828TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
[email protected]513963e2013-06-15 01:53:041829 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1830 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]0c9bf872011-03-04 17:53:221831 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521832 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1),
[email protected]0c9bf872011-03-04 17:53:221833 };
1834
[email protected]513963e2013-06-15 01:53:041835 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]0c9bf872011-03-04 17:53:221836 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521837 CreateMockRead(*resp, 2),
1838 CreateMockRead(*body, 3),
1839 MockRead(ASYNC, 0, 4) // EOF
[email protected]0c9bf872011-03-04 17:53:221840 };
1841
rch08e3aa3e2015-05-16 14:27:521842 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]0c9bf872011-03-04 17:53:221843 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
[email protected]262eec82013-03-19 21:01:361844 DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501845 BoundNetLog(), GetParam(), NULL);
[email protected]34b345f92013-02-22 03:27:261846
1847 // These chunks get merged into a single frame when being sent.
1848 const int kFirstChunkSize = kUploadDataSize/2;
mmenkecbc2b712014-10-09 20:29:071849 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1850 upload_chunked_data_stream()->AppendData(
[email protected]34b345f92013-02-22 03:27:261851 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1852
[email protected]dd54bd82012-07-19 23:44:571853 helper.RunToCompletion(&data);
[email protected]0c9bf872011-03-04 17:53:221854 TransactionHelperResult out = helper.output();
1855 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021856 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261857 EXPECT_EQ(kUploadData, out.response_data);
1858}
1859
1860// Test that a chunked POST works with chunks appended after transaction starts.
[email protected]513963e2013-06-15 01:53:041861TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
[email protected]513963e2013-06-15 01:53:041862 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1863 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1864 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1865 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]34b345f92013-02-22 03:27:261866 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521867 CreateMockWrite(*req, 0),
1868 CreateMockWrite(*chunk1, 1),
1869 CreateMockWrite(*chunk2, 2),
1870 CreateMockWrite(*chunk3, 3),
[email protected]34b345f92013-02-22 03:27:261871 };
1872
[email protected]513963e2013-06-15 01:53:041873 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]34b345f92013-02-22 03:27:261874 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521875 CreateMockRead(*resp, 4),
1876 CreateMockRead(*chunk1, 5),
1877 CreateMockRead(*chunk2, 6),
1878 CreateMockRead(*chunk3, 7),
1879 MockRead(ASYNC, 0, 8) // EOF
[email protected]34b345f92013-02-22 03:27:261880 };
1881
rch08e3aa3e2015-05-16 14:27:521882 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]34b345f92013-02-22 03:27:261883 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
[email protected]262eec82013-03-19 21:01:361884 DEFAULT_PRIORITY,
[email protected]34b345f92013-02-22 03:27:261885 BoundNetLog(), GetParam(), NULL);
1886
mmenkecbc2b712014-10-09 20:29:071887 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]34b345f92013-02-22 03:27:261888
1889 helper.RunPreTestSetup();
1890 helper.AddData(&data);
1891 ASSERT_TRUE(helper.StartDefaultTest());
1892
[email protected]fc9d88472013-08-14 02:31:171893 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071894 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]fc9d88472013-08-14 02:31:171895 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071896 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]34b345f92013-02-22 03:27:261897
1898 helper.FinishDefaultTest();
1899 helper.VerifyDataConsumed();
1900
1901 std::string expected_response;
1902 expected_response += kUploadData;
1903 expected_response += kUploadData;
1904 expected_response += kUploadData;
1905
1906 TransactionHelperResult out = helper.output();
1907 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021908 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]34b345f92013-02-22 03:27:261909 EXPECT_EQ(expected_response, out.response_data);
[email protected]0c9bf872011-03-04 17:53:221910}
1911
[email protected]a33cad2b62010-07-30 22:24:391912// Test that a POST without any post data works.
[email protected]513963e2013-06-15 01:53:041913TEST_P(SpdyNetworkTransactionTest, NullPost) {
[email protected]d2c1a97b2014-03-03 19:25:091914 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]a33cad2b62010-07-30 22:24:391915 // Setup the request
1916 HttpRequestInfo request;
1917 request.method = "POST";
rchebf12982015-04-10 01:15:001918 request.url = GURL(GetDefaultUrl());
[email protected]a33cad2b62010-07-30 22:24:391919 // Create an empty UploadData.
[email protected]329b68b2012-11-14 17:54:271920 request.upload_data_stream = NULL;
[email protected]a33cad2b62010-07-30 22:24:391921
[email protected]329b68b2012-11-14 17:54:271922 // When request.upload_data_stream is NULL for post, content-length is
[email protected]a33cad2b62010-07-30 22:24:391923 // expected to be 0.
[email protected]745aa9c2014-06-27 02:21:291924 scoped_ptr<SpdyHeaderBlock> req_block(
rchebf12982015-04-10 01:15:001925 spdy_util_.ConstructPostHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291926 scoped_ptr<SpdyFrame> req(
1927 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
[email protected]d2c1a97b2014-03-03 19:25:091928
[email protected]a33cad2b62010-07-30 22:24:391929 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521930 CreateMockWrite(*req, 0),
[email protected]a33cad2b62010-07-30 22:24:391931 };
1932
[email protected]513963e2013-06-15 01:53:041933 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1934 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]a33cad2b62010-07-30 22:24:391935 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521936 CreateMockRead(*resp, 1),
1937 CreateMockRead(*body, 2),
1938 MockRead(ASYNC, 0, 3) // EOF
[email protected]a33cad2b62010-07-30 22:24:391939 };
1940
rch08e3aa3e2015-05-16 14:27:521941 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]a33cad2b62010-07-30 22:24:391942
[email protected]262eec82013-03-19 21:01:361943 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501944 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571945 helper.RunToCompletion(&data);
[email protected]a33cad2b62010-07-30 22:24:391946 TransactionHelperResult out = helper.output();
1947 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021948 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]a33cad2b62010-07-30 22:24:391949 EXPECT_EQ("hello!", out.response_data);
1950}
1951
[email protected]edd3b0a52009-11-24 18:56:361952// Test that a simple POST works.
[email protected]513963e2013-06-15 01:53:041953TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]d2c1a97b2014-03-03 19:25:091954 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]329b68b2012-11-14 17:54:271955 // Create an empty UploadDataStream.
olli.raula6df48b2a2015-11-26 07:40:221956 std::vector<scoped_ptr<UploadElementReader>> element_readers;
1957 ElementsUploadDataStream stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271958
[email protected]edd3b0a52009-11-24 18:56:361959 // Setup the request
1960 HttpRequestInfo request;
1961 request.method = "POST";
rchebf12982015-04-10 01:15:001962 request.url = GURL(GetDefaultUrl());
[email protected]329b68b2012-11-14 17:54:271963 request.upload_data_stream = &stream;
[email protected]edd3b0a52009-11-24 18:56:361964
[email protected]ad91dc52012-09-01 03:46:061965 const uint64 kContentLength = 0;
[email protected]d2c1a97b2014-03-03 19:25:091966
[email protected]745aa9c2014-06-27 02:21:291967 scoped_ptr<SpdyHeaderBlock> req_block(
rchebf12982015-04-10 01:15:001968 spdy_util_.ConstructPostHeaderBlock(GetDefaultUrl(), kContentLength));
[email protected]745aa9c2014-06-27 02:21:291969 scoped_ptr<SpdyFrame> req(
1970 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
[email protected]d2c1a97b2014-03-03 19:25:091971
[email protected]edd3b0a52009-11-24 18:56:361972 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521973 CreateMockWrite(*req, 0),
[email protected]edd3b0a52009-11-24 18:56:361974 };
1975
[email protected]513963e2013-06-15 01:53:041976 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1977 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361978 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521979 CreateMockRead(*resp, 1),
1980 CreateMockRead(*body, 2),
1981 MockRead(ASYNC, 0, 3) // EOF
[email protected]edd3b0a52009-11-24 18:56:361982 };
1983
rch08e3aa3e2015-05-16 14:27:521984 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bf2491a92009-11-29 16:39:481985
[email protected]262eec82013-03-19 21:01:361986 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1987 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571988 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471989 TransactionHelperResult out = helper.output();
[email protected]edd3b0a52009-11-24 18:56:361990 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:021991 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]edd3b0a52009-11-24 18:56:361992 EXPECT_EQ("hello!", out.response_data);
1993}
1994
[email protected]35c3fc732014-02-15 00:16:071995// While we're doing a post, the server sends the reply before upload completes.
1996TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
1997 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1998 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1999 MockWrite writes[] = {
2000 CreateMockWrite(*req, 0),
2001 CreateMockWrite(*body, 3),
2002 };
2003 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]a5566f9702010-05-05 22:25:432004 MockRead reads[] = {
[email protected]35c3fc732014-02-15 00:16:072005 CreateMockRead(*resp, 1),
2006 CreateMockRead(*body, 2),
[email protected]099bc7e2013-07-18 04:19:162007 MockRead(ASYNC, 0, 4) // EOF
[email protected]a5566f9702010-05-05 22:25:432008 };
2009
[email protected]35c3fc732014-02-15 00:16:072010 // Write the request headers, and read the complete response
2011 // while still waiting for chunked request data.
[email protected]c92f4b4542012-07-26 23:53:212012 DeterministicSocketData data(reads, arraysize(reads),
2013 writes, arraysize(writes));
[email protected]35c3fc732014-02-15 00:16:072014 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
2015 DEFAULT_PRIORITY,
[email protected]c92f4b4542012-07-26 23:53:212016 BoundNetLog(), GetParam(), NULL);
2017 helper.SetDeterministic();
2018 helper.RunPreTestSetup();
2019 helper.AddDeterministicData(&data);
[email protected]c92f4b4542012-07-26 23:53:212020
[email protected]35c3fc732014-02-15 00:16:072021 ASSERT_TRUE(helper.StartDefaultTest());
[email protected]c92f4b4542012-07-26 23:53:212022
[email protected]35c3fc732014-02-15 00:16:072023 // Process the request headers, SYN_REPLY, and response body.
2024 // The request body is still in flight.
2025 data.RunFor(3);
2026
2027 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
bnc84e7fb52015-12-02 11:50:022028 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]35c3fc732014-02-15 00:16:072029
2030 // Finish sending the request body.
mmenkecbc2b712014-10-09 20:29:072031 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]35c3fc732014-02-15 00:16:072032 data.RunFor(2);
2033
2034 std::string response_body;
2035 EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
2036 EXPECT_EQ(kUploadData, response_body);
2037 helper.VerifyDataConsumed();
[email protected]a5566f9702010-05-05 22:25:432038}
2039
[email protected]f9a26d72010-08-03 18:07:132040// The client upon cancellation tries to send a RST_STREAM frame. The mock
2041// socket causes the TCP write to return zero. This test checks that the client
2042// tries to queue up the RST_STREAM frame again.
[email protected]513963e2013-06-15 01:53:042043TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
[email protected]cdf8f7e72013-05-23 10:56:462044 scoped_ptr<SpdyFrame> req(
2045 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]ff98d7f02012-03-22 21:44:192046 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202047 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]f9a26d72010-08-03 18:07:132048 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:062049 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2050 MockWrite(SYNCHRONOUS, 0, 0, 2),
2051 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
[email protected]f9a26d72010-08-03 18:07:132052 };
2053
[email protected]513963e2013-06-15 01:53:042054 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f9a26d72010-08-03 18:07:132055 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:062056 CreateMockRead(*resp.get(), 1, ASYNC),
2057 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:132058 };
2059
[email protected]dd54bd82012-07-19 23:44:572060 DeterministicSocketData data(reads, arraysize(reads),
2061 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362062 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502063 BoundNetLog(), GetParam(), NULL);
[email protected]3b7828432010-08-18 18:33:272064 helper.SetDeterministic();
[email protected]f9a26d72010-08-03 18:07:132065 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572066 helper.AddDeterministicData(&data);
[email protected]f9a26d72010-08-03 18:07:132067 HttpNetworkTransaction* trans = helper.trans();
2068
[email protected]49639fa2011-12-20 23:22:412069 TestCompletionCallback callback;
2070 int rv = trans->Start(
2071 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]f9a26d72010-08-03 18:07:132072 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3b7828432010-08-18 18:33:272073
[email protected]dd54bd82012-07-19 23:44:572074 data.SetStop(2);
2075 data.Run();
[email protected]f9a26d72010-08-03 18:07:132076 helper.ResetTrans();
[email protected]dd54bd82012-07-19 23:44:572077 data.SetStop(20);
2078 data.Run();
[email protected]3b7828432010-08-18 18:33:272079
[email protected]f9a26d72010-08-03 18:07:132080 helper.VerifyDataConsumed();
2081}
2082
[email protected]93300672009-10-24 13:22:512083// Test that the transaction doesn't crash when we don't have a reply.
[email protected]513963e2013-06-15 01:53:042084TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
[email protected]513963e2013-06-15 01:53:042085 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:142086 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522087 CreateMockRead(*body, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]93300672009-10-24 13:22:512088 };
2089
rch08e3aa3e2015-05-16 14:27:522090 scoped_ptr<SpdyFrame> req(
2091 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2092 scoped_ptr<SpdyFrame> rst(
2093 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2094 MockWrite writes[] = {
2095 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
2096 };
2097 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362098 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502099 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572100 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:472101 TransactionHelperResult out = helper.output();
[email protected]2aeef782013-06-21 18:30:562102 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]93300672009-10-24 13:22:512103}
2104
[email protected]d30022352010-06-24 19:17:582105// Test that the transaction doesn't crash when we get two replies on the same
2106// stream ID. See http://crbug.com/45639.
[email protected]513963e2013-06-15 01:53:042107TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
[email protected]cdf8f7e72013-05-23 10:56:462108 scoped_ptr<SpdyFrame> req(
2109 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]2aeef782013-06-21 18:30:562110 scoped_ptr<SpdyFrame> rst(
[email protected]00b29472014-01-16 18:10:242111 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]2aeef782013-06-21 18:30:562112 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522113 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]2aeef782013-06-21 18:30:562114 };
[email protected]d30022352010-06-24 19:17:582115
[email protected]513963e2013-06-15 01:53:042116 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2117 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d30022352010-06-24 19:17:582118 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522119 CreateMockRead(*resp, 1),
2120 CreateMockRead(*resp, 2),
2121 CreateMockRead(*body, 3),
2122 MockRead(ASYNC, 0, 5) // EOF
[email protected]d30022352010-06-24 19:17:582123 };
2124
rch08e3aa3e2015-05-16 14:27:522125 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d30022352010-06-24 19:17:582126
[email protected]262eec82013-03-19 21:01:362127 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502128 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472129 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572130 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472131
2132 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:582133
[email protected]49639fa2011-12-20 23:22:412134 TestCompletionCallback callback;
2135 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]d30022352010-06-24 19:17:582136 EXPECT_EQ(ERR_IO_PENDING, rv);
2137 rv = callback.WaitForResult();
2138 EXPECT_EQ(OK, rv);
2139
2140 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a5c493b92010-08-06 23:04:292141 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:502142 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]d30022352010-06-24 19:17:582143 EXPECT_TRUE(response->was_fetched_via_spdy);
2144 std::string response_data;
[email protected]3caf5542010-07-16 15:19:472145 rv = ReadTransaction(trans, &response_data);
[email protected]d30022352010-06-24 19:17:582146 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
[email protected]3caf5542010-07-16 15:19:472147
2148 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:582149}
2150
[email protected]513963e2013-06-15 01:53:042151TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252152 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462153 scoped_ptr<SpdyFrame> req(
2154 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]5a7bb252013-02-09 00:21:052155 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202156 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252157 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522158 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
[email protected]b3503002012-03-27 04:57:252159 };
2160
2161 const char* const headers[] = {
[email protected]513963e2013-06-15 01:53:042162 "transfer-encoding", "chunked"
[email protected]b3503002012-03-27 04:57:252163 };
[email protected]513963e2013-06-15 01:53:042164 scoped_ptr<SpdyFrame> resp(
2165 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2166 scoped_ptr<SpdyFrame> body(
2167 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b3503002012-03-27 04:57:252168 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522169 CreateMockRead(*resp, 1),
2170 CreateMockRead(*body, 3),
2171 MockRead(ASYNC, 0, 4) // EOF
[email protected]b3503002012-03-27 04:57:252172 };
2173
rch08e3aa3e2015-05-16 14:27:522174 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362175 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502176 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572177 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252178 TransactionHelperResult out = helper.output();
2179 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2180
2181 helper.session()->spdy_session_pool()->CloseAllSessions();
2182 helper.VerifyDataConsumed();
2183}
2184
[email protected]513963e2013-06-15 01:53:042185TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252186 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462187 scoped_ptr<SpdyFrame> req(
2188 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]5a7bb252013-02-09 00:21:052189 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202190 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252191 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522192 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]b3503002012-03-27 04:57:252193 };
2194
[email protected]513963e2013-06-15 01:53:042195 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2196 const char* const headers[] = {
2197 "transfer-encoding", "chunked"
2198 };
2199 scoped_ptr<SpdyFrame> push(
rchebf12982015-04-10 01:15:002200 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2, 2, 1,
2201 GetDefaultUrlWithPath("/1").c_str()));
[email protected]513963e2013-06-15 01:53:042202 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b3503002012-03-27 04:57:252203 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522204 CreateMockRead(*resp, 1),
2205 CreateMockRead(*push, 2),
2206 CreateMockRead(*body, 3),
2207 MockRead(ASYNC, 0, 5) // EOF
[email protected]b3503002012-03-27 04:57:252208 };
2209
rch08e3aa3e2015-05-16 14:27:522210 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362211 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502212 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572213 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252214 TransactionHelperResult out = helper.output();
2215 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:022216 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b3503002012-03-27 04:57:252217 EXPECT_EQ("hello!", out.response_data);
2218
2219 helper.session()->spdy_session_pool()->CloseAllSessions();
2220 helper.VerifyDataConsumed();
2221}
2222
[email protected]513963e2013-06-15 01:53:042223TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:382224 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462225 scoped_ptr<SpdyFrame> req(
2226 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]34437af82009-11-06 02:28:492227 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:132228 CreateMockWrite(*req),
[email protected]34437af82009-11-06 02:28:492229 };
2230
[email protected]513963e2013-06-15 01:53:042231 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]34437af82009-11-06 02:28:492232 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132233 CreateMockRead(*resp),
[email protected]34437af82009-11-06 02:28:492234 // This following read isn't used by the test, except during the
[email protected]b4c62eb2012-11-14 18:36:512235 // RunUntilIdle() call at the end since the SpdySession survives the
[email protected]3caf5542010-07-16 15:19:472236 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
[email protected]34437af82009-11-06 02:28:492237 // MockRead will do here.
[email protected]8ddf8322012-02-23 18:08:062238 MockRead(ASYNC, 0, 0) // EOF
[email protected]34437af82009-11-06 02:28:492239 };
2240
[email protected]31a2bfe2010-02-09 08:03:392241 StaticSocketDataProvider data(reads, arraysize(reads),
2242 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472243
[email protected]262eec82013-03-19 21:01:362244 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502245 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472246 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:582247 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472248 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:492249
[email protected]49639fa2011-12-20 23:22:412250 TestCompletionCallback callback;
2251 int rv = trans->Start(
2252 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]34437af82009-11-06 02:28:492253 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472254 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:492255
[email protected]30c942b2010-07-21 16:59:592256 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:492257 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:172258 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472259 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:492260}
[email protected]72552f02009-10-28 15:25:012261
[email protected]6c6ea172010-07-27 20:04:032262// Verify that the client sends a Rst Frame upon cancelling the stream.
[email protected]513963e2013-06-15 01:53:042263TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
[email protected]cdf8f7e72013-05-23 10:56:462264 scoped_ptr<SpdyFrame> req(
2265 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]ff98d7f02012-03-22 21:44:192266 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202267 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]6c6ea172010-07-27 20:04:032268 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:062269 CreateMockWrite(*req, 0, SYNCHRONOUS),
2270 CreateMockWrite(*rst, 2, SYNCHRONOUS),
[email protected]6c6ea172010-07-27 20:04:032271 };
2272
[email protected]513963e2013-06-15 01:53:042273 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]6c6ea172010-07-27 20:04:032274 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:062275 CreateMockRead(*resp, 1, ASYNC),
2276 MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:032277 };
2278
[email protected]dd54bd82012-07-19 23:44:572279 DeterministicSocketData data(reads, arraysize(reads),
[email protected]513963e2013-06-15 01:53:042280 writes, arraysize(writes));
[email protected]6c6ea172010-07-27 20:04:032281
[email protected]262eec82013-03-19 21:01:362282 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]6c6ea172010-07-27 20:04:032283 BoundNetLog(),
[email protected]61b4efc2012-04-27 18:12:502284 GetParam(), NULL);
[email protected]3b7828432010-08-18 18:33:272285 helper.SetDeterministic();
[email protected]6c6ea172010-07-27 20:04:032286 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572287 helper.AddDeterministicData(&data);
[email protected]6c6ea172010-07-27 20:04:032288 HttpNetworkTransaction* trans = helper.trans();
2289
[email protected]49639fa2011-12-20 23:22:412290 TestCompletionCallback callback;
[email protected]6c6ea172010-07-27 20:04:032291
[email protected]49639fa2011-12-20 23:22:412292 int rv = trans->Start(
2293 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]6c6ea172010-07-27 20:04:032294 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]6c6ea172010-07-27 20:04:032295
[email protected]dd54bd82012-07-19 23:44:572296 data.SetStop(2);
2297 data.Run();
[email protected]3b7828432010-08-18 18:33:272298 helper.ResetTrans();
[email protected]dd54bd82012-07-19 23:44:572299 data.SetStop(20);
2300 data.Run();
[email protected]3b7828432010-08-18 18:33:272301
[email protected]6c6ea172010-07-27 20:04:032302 helper.VerifyDataConsumed();
2303}
2304
[email protected]b278eb72010-07-09 20:17:002305// Verify that the client can correctly deal with the user callback attempting
2306// to start another transaction on a session that is closing down. See
2307// http://crbug.com/47455
[email protected]513963e2013-06-15 01:53:042308TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
[email protected]cdf8f7e72013-05-23 10:56:462309 scoped_ptr<SpdyFrame> req(
2310 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:522311 MockWrite writes[] = {CreateMockWrite(*req)};
2312 MockWrite writes2[] = {CreateMockWrite(*req, 0)};
[email protected]b278eb72010-07-09 20:17:002313
[email protected]cbdd73162013-03-18 23:27:332314 // The indicated length of this frame is longer than its actual length. When
2315 // the session receives an empty frame after this one, it shuts down the
[email protected]b278eb72010-07-09 20:17:002316 // session, and calls the read callback with the incomplete data.
2317 const uint8 kGetBodyFrame2[] = {
2318 0x00, 0x00, 0x00, 0x01,
2319 0x01, 0x00, 0x00, 0x07,
2320 'h', 'e', 'l', 'l', 'o', '!',
2321 };
2322
[email protected]513963e2013-06-15 01:53:042323 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]b278eb72010-07-09 20:17:002324 MockRead reads[] = {
rch32320842015-05-16 15:57:092325 CreateMockRead(*resp, 1),
2326 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2327 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2328 arraysize(kGetBodyFrame2), 3),
2329 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
2330 MockRead(ASYNC, 0, 0, 5), // EOF
[email protected]b278eb72010-07-09 20:17:002331 };
2332 MockRead reads2[] = {
rch08e3aa3e2015-05-16 14:27:522333 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 0, 2), // EOF
[email protected]b278eb72010-07-09 20:17:002334 };
2335
rch32320842015-05-16 15:57:092336 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
rch08e3aa3e2015-05-16 14:27:522337 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2338 arraysize(writes2));
[email protected]3caf5542010-07-16 15:19:472339
[email protected]262eec82013-03-19 21:01:362340 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502341 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582342 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572343 helper.AddData(&data);
2344 helper.AddData(&data2);
[email protected]3caf5542010-07-16 15:19:472345 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002346
2347 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412348 TestCompletionCallback callback;
2349 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]b278eb72010-07-09 20:17:002350 EXPECT_EQ(ERR_IO_PENDING, rv);
2351 rv = callback.WaitForResult();
2352
[email protected]b278eb72010-07-09 20:17:002353 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162354 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412355 rv = trans->Read(
rchebf12982015-04-10 01:15:002356 buf.get(), kSize,
[email protected]513963e2013-06-15 01:53:042357 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
rchebf12982015-04-10 01:15:002358 helper.session(), GURL(GetDefaultUrl())));
rch32320842015-05-16 15:57:092359 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472360 // This forces an err_IO_pending, which sets the callback.
[email protected]dd54bd82012-07-19 23:44:572361 data.CompleteRead();
[email protected]3caf5542010-07-16 15:19:472362 // This finishes the read.
[email protected]dd54bd82012-07-19 23:44:572363 data.CompleteRead();
[email protected]3caf5542010-07-16 15:19:472364 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002365}
2366
[email protected]9be804c82010-06-24 17:59:462367// Verify that the client can correctly deal with the user callback deleting the
2368// transaction. Failures will usually be valgrind errors. See
2369// http://crbug.com/46925
[email protected]513963e2013-06-15 01:53:042370TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
[email protected]cdf8f7e72013-05-23 10:56:462371 scoped_ptr<SpdyFrame> req(
2372 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch32320842015-05-16 15:57:092373 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]9be804c82010-06-24 17:59:462374
[email protected]513963e2013-06-15 01:53:042375 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2376 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462377 MockRead reads[] = {
rch32320842015-05-16 15:57:092378 CreateMockRead(*resp.get(), 1),
2379 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2380 CreateMockRead(*body.get(), 3),
2381 MockRead(ASYNC, 0, 0, 4), // EOF
[email protected]9be804c82010-06-24 17:59:462382 };
2383
rch32320842015-05-16 15:57:092384 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472385
[email protected]262eec82013-03-19 21:01:362386 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502387 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472388 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572389 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472390 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462391
2392 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412393 TestCompletionCallback callback;
2394 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]9be804c82010-06-24 17:59:462395 EXPECT_EQ(ERR_IO_PENDING, rv);
2396 rv = callback.WaitForResult();
2397
2398 // Setup a user callback which will delete the session, and clear out the
2399 // memory holding the stream object. Note that the callback deletes trans.
[email protected]9be804c82010-06-24 17:59:462400 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162401 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412402 rv = trans->Read(
[email protected]90499482013-06-01 00:39:502403 buf.get(),
2404 kSize,
[email protected]513963e2013-06-15 01:53:042405 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
[email protected]49639fa2011-12-20 23:22:412406 base::Unretained(&helper)));
[email protected]9be804c82010-06-24 17:59:462407 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:572408 data.CompleteRead();
[email protected]9be804c82010-06-24 17:59:462409
2410 // Finish running rest of tasks.
[email protected]fc9d88472013-08-14 02:31:172411 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472412 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462413}
2414
bncce36dca22015-04-21 22:11:232415// Send a spdy request to www.example.org that gets redirected to www.foo.com.
rchebf12982015-04-10 01:15:002416TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectGetRequest) {
[email protected]513963e2013-06-15 01:53:042417 scoped_ptr<SpdyHeaderBlock> headers(
rchebf12982015-04-10 01:15:002418 spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
[email protected]513963e2013-06-15 01:53:042419 (*headers)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062420 (*headers)["accept-encoding"] = "gzip, deflate";
[email protected]513963e2013-06-15 01:53:042421 scoped_ptr<SpdyHeaderBlock> headers2(
2422 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2423 (*headers2)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062424 (*headers2)["accept-encoding"] = "gzip, deflate";
[email protected]e3ebba0f2010-08-05 17:59:582425
bncce36dca22015-04-21 22:11:232426 // Setup writes/reads to www.example.org
[email protected]745aa9c2014-06-27 02:21:292427 scoped_ptr<SpdyFrame> req(
2428 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2429 scoped_ptr<SpdyFrame> req2(
2430 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042431 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
[email protected]e3ebba0f2010-08-05 17:59:582432 MockWrite writes[] = {
2433 CreateMockWrite(*req, 1),
2434 };
2435 MockRead reads[] = {
2436 CreateMockRead(*resp, 2),
[email protected]8ddf8322012-02-23 18:08:062437 MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582438 };
2439
2440 // Setup writes/reads to www.foo.com
[email protected]513963e2013-06-15 01:53:042441 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2442 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582443 MockWrite writes2[] = {
2444 CreateMockWrite(*req2, 1),
2445 };
2446 MockRead reads2[] = {
2447 CreateMockRead(*resp2, 2),
2448 CreateMockRead(*body2, 3),
[email protected]8ddf8322012-02-23 18:08:062449 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582450 };
rch08e3aa3e2015-05-16 14:27:522451 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2452 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2453 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582454
2455 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582456 TestDelegate d;
2457 {
rchebf12982015-04-10 01:15:002458 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
davidben151423e2015-03-23 18:48:362459 scoped_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002460 GURL(GetDefaultUrl()), DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092461 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572462 AddSocketDataProvider(&data);
[email protected]ef2bf422012-05-11 03:27:092463 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572464 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582465
2466 d.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192467 r->Start();
[email protected]fc9d88472013-08-14 02:31:172468 base::RunLoop().Run();
[email protected]513963e2013-06-15 01:53:042469
[email protected]e3ebba0f2010-08-05 17:59:582470 EXPECT_EQ(1, d.received_redirect_count());
2471
[email protected]f7022f32014-08-21 16:32:192472 r->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172473 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582474 EXPECT_EQ(1, d.response_started_count());
2475 EXPECT_FALSE(d.received_data_before_response());
bnc301745a2015-03-10 03:22:162476 EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582477 std::string contents("hello!");
2478 EXPECT_EQ(contents, d.data_received());
2479 }
rch37de576c2015-05-17 20:28:172480 EXPECT_TRUE(data.AllReadDataConsumed());
2481 EXPECT_TRUE(data.AllWriteDataConsumed());
2482 EXPECT_TRUE(data2.AllReadDataConsumed());
2483 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582484}
2485
bncce36dca22015-04-21 22:11:232486// Send a spdy request to www.example.org. Get a pushed stream that redirects to
[email protected]e3ebba0f2010-08-05 17:59:582487// www.foo.com.
rchebf12982015-04-10 01:15:002488TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
[email protected]513963e2013-06-15 01:53:042489 scoped_ptr<SpdyHeaderBlock> headers(
rchebf12982015-04-10 01:15:002490 spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
[email protected]513963e2013-06-15 01:53:042491 (*headers)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062492 (*headers)["accept-encoding"] = "gzip, deflate";
[email protected]3a8d6852011-03-11 23:43:442493
bncce36dca22015-04-21 22:11:232494 // Setup writes/reads to www.example.org
[email protected]ff98d7f02012-03-22 21:44:192495 scoped_ptr<SpdyFrame> req(
[email protected]745aa9c2014-06-27 02:21:292496 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042497 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002498 scoped_ptr<SpdyFrame> rep(spdy_util_.ConstructSpdyPush(
2499 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
2500 "301 Moved Permanently", "http://www.foo.com/index.php"));
[email protected]513963e2013-06-15 01:53:042501 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202502 scoped_ptr<SpdyFrame> rst(
2503 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]3a8d6852011-03-11 23:43:442504 MockWrite writes[] = {
2505 CreateMockWrite(*req, 1),
2506 CreateMockWrite(*rst, 6),
2507 };
2508 MockRead reads[] = {
2509 CreateMockRead(*resp, 2),
2510 CreateMockRead(*rep, 3),
2511 CreateMockRead(*body, 4),
[email protected]8ddf8322012-02-23 18:08:062512 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2513 MockRead(ASYNC, 0, 0, 7) // EOF
[email protected]3a8d6852011-03-11 23:43:442514 };
2515
2516 // Setup writes/reads to www.foo.com
[email protected]513963e2013-06-15 01:53:042517 scoped_ptr<SpdyHeaderBlock> headers2(
2518 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2519 (*headers2)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062520 (*headers2)["accept-encoding"] = "gzip, deflate";
[email protected]ff98d7f02012-03-22 21:44:192521 scoped_ptr<SpdyFrame> req2(
[email protected]745aa9c2014-06-27 02:21:292522 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042523 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2524 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582525 MockWrite writes2[] = {
2526 CreateMockWrite(*req2, 1),
2527 };
2528 MockRead reads2[] = {
2529 CreateMockRead(*resp2, 2),
2530 CreateMockRead(*body2, 3),
[email protected]8ddf8322012-02-23 18:08:062531 MockRead(ASYNC, 0, 0, 5) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582532 };
rch08e3aa3e2015-05-16 14:27:522533 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2534 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2535 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582536
2537 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582538 TestDelegate d;
2539 TestDelegate d2;
rchebf12982015-04-10 01:15:002540 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
[email protected]e3ebba0f2010-08-05 17:59:582541 {
davidben151423e2015-03-23 18:48:362542 scoped_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002543 GURL(GetDefaultUrl()), DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092544 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572545 AddSocketDataProvider(&data);
[email protected]e3ebba0f2010-08-05 17:59:582546
[email protected]f7022f32014-08-21 16:32:192547 r->Start();
[email protected]fc9d88472013-08-14 02:31:172548 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582549
2550 EXPECT_EQ(0, d.received_redirect_count());
2551 std::string contents("hello!");
2552 EXPECT_EQ(contents, d.data_received());
2553
davidben151423e2015-03-23 18:48:362554 scoped_ptr<URLRequest> r2(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002555 GURL(GetDefaultUrlWithPath("/foo.dat")), DEFAULT_PRIORITY, &d2));
[email protected]ef2bf422012-05-11 03:27:092556 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572557 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582558
2559 d2.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192560 r2->Start();
[email protected]fc9d88472013-08-14 02:31:172561 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582562 EXPECT_EQ(1, d2.received_redirect_count());
2563
[email protected]f7022f32014-08-21 16:32:192564 r2->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172565 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582566 EXPECT_EQ(1, d2.response_started_count());
2567 EXPECT_FALSE(d2.received_data_before_response());
bnc301745a2015-03-10 03:22:162568 EXPECT_EQ(URLRequestStatus::SUCCESS, r2->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582569 std::string contents2("hello!");
2570 EXPECT_EQ(contents2, d2.data_received());
2571 }
rch08e3aa3e2015-05-16 14:27:522572 EXPECT_TRUE(data.AllReadDataConsumed());
2573 EXPECT_TRUE(data.AllWriteDataConsumed());
2574 EXPECT_TRUE(data2.AllReadDataConsumed());
2575 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582576}
2577
[email protected]513963e2013-06-15 01:53:042578TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
[email protected]cdf8f7e72013-05-23 10:56:462579 scoped_ptr<SpdyFrame> stream1_syn(
2580 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042581 scoped_ptr<SpdyFrame> stream1_body(
2582 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582583 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522584 CreateMockWrite(*stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582585 };
2586
[email protected]ff98d7f02012-03-22 21:44:192587 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042588 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002589 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2590 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432591 const char kPushedData[] = "pushed";
2592 scoped_ptr<SpdyFrame> stream2_body(
2593 spdy_util_.ConstructSpdyBodyFrame(
2594 2, kPushedData, strlen(kPushedData), true));
[email protected]e3ebba0f2010-08-05 17:59:582595 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522596 CreateMockRead(*stream1_reply, 1),
2597 CreateMockRead(*stream2_syn, 2),
2598 CreateMockRead(*stream1_body, 3, SYNCHRONOUS),
2599 CreateMockRead(*stream2_body, 4),
2600 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582601 };
2602
2603 HttpResponseInfo response;
2604 HttpResponseInfo response2;
[email protected]19ec8a72010-08-23 03:38:232605 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522606 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572607 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032608 &response,
2609 &response2,
2610 expected_push_result);
[email protected]e3ebba0f2010-08-05 17:59:582611
2612 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502613 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022614 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582615
2616 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502617 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582618 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2619}
2620
[email protected]513963e2013-06-15 01:53:042621TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
[email protected]cdf8f7e72013-05-23 10:56:462622 scoped_ptr<SpdyFrame> stream1_syn(
2623 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042624 scoped_ptr<SpdyFrame> stream1_body(
2625 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]a5b8eb29d2012-03-06 06:19:462626 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522627 CreateMockWrite(*stream1_syn, 0),
[email protected]a5b8eb29d2012-03-06 06:19:462628 };
2629
[email protected]ff98d7f02012-03-22 21:44:192630 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042631 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002632 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2633 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432634 const char kPushedData[] = "pushed";
2635 scoped_ptr<SpdyFrame> stream2_body(
2636 spdy_util_.ConstructSpdyBodyFrame(
2637 2, kPushedData, strlen(kPushedData), true));
[email protected]a5b8eb29d2012-03-06 06:19:462638 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522639 CreateMockRead(*stream2_syn, 1),
2640 CreateMockRead(*stream1_reply, 2),
2641 CreateMockRead(*stream1_body, 3, SYNCHRONOUS),
2642 CreateMockRead(*stream2_body, 4),
2643 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]a5b8eb29d2012-03-06 06:19:462644 };
2645
2646 HttpResponseInfo response;
2647 HttpResponseInfo response2;
2648 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522649 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572650 RunServerPushTest(&data,
[email protected]a5b8eb29d2012-03-06 06:19:462651 &response,
2652 &response2,
2653 expected_push_result);
2654
2655 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502656 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022657 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]a5b8eb29d2012-03-06 06:19:462658
2659 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502660 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]a5b8eb29d2012-03-06 06:19:462661 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2662}
2663
[email protected]513963e2013-06-15 01:53:042664TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
[email protected]cdf8f7e72013-05-23 10:56:462665 scoped_ptr<SpdyFrame> stream1_syn(
2666 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:522667 MockWrite writes[] = {
2668 CreateMockWrite(*stream1_syn, 0),
2669 };
[email protected]82918cc2010-08-25 17:24:502670
[email protected]ff98d7f02012-03-22 21:44:192671 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042672 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002673 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2674 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432675 const char kPushedData[] = "pushed";
2676 scoped_ptr<SpdyFrame> stream2_body(
2677 spdy_util_.ConstructSpdyBodyFrame(
2678 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:192679 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042680 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]82918cc2010-08-25 17:24:502681 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522682 CreateMockRead(*stream1_reply, 1),
2683 CreateMockRead(*stream2_syn, 2),
2684 CreateMockRead(*stream2_body, 3),
2685 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2686 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]82918cc2010-08-25 17:24:502687 };
2688
2689 HttpResponseInfo response;
2690 HttpResponseInfo response2;
2691 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522692 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572693 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032694 &response,
2695 &response2,
2696 expected_push_result);
[email protected]82918cc2010-08-25 17:24:502697
2698 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502699 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022700 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]82918cc2010-08-25 17:24:502701
2702 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502703 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]82918cc2010-08-25 17:24:502704 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2705}
2706
[email protected]513963e2013-06-15 01:53:042707TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
[email protected]cdf8f7e72013-05-23 10:56:462708 scoped_ptr<SpdyFrame> stream1_syn(
2709 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042710 scoped_ptr<SpdyFrame> stream1_body(
2711 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582712 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522713 CreateMockWrite(*stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582714 };
2715
[email protected]ff98d7f02012-03-22 21:44:192716 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042717 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002718 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2719 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]c10b20852013-05-15 21:29:202720 scoped_ptr<SpdyFrame> stream2_rst(
2721 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582722 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522723 CreateMockRead(*stream1_reply, 1),
2724 CreateMockRead(*stream2_syn, 2),
2725 CreateMockRead(*stream2_rst, 3),
2726 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2727 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582728 };
2729
rch08e3aa3e2015-05-16 14:27:522730 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362731 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502732 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582733
2734 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572735 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582736
2737 HttpNetworkTransaction* trans = helper.trans();
2738
2739 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412740 TestCompletionCallback callback;
2741 int rv = trans->Start(
2742 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:582743 EXPECT_EQ(ERR_IO_PENDING, rv);
2744 rv = callback.WaitForResult();
[email protected]19ec8a72010-08-23 03:38:232745 EXPECT_EQ(OK, rv);
2746
2747 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522748 EXPECT_TRUE(data.AllReadDataConsumed());
2749 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]19ec8a72010-08-23 03:38:232750
2751 // Verify the SYN_REPLY.
2752 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502753 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022754 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232755}
2756
[email protected]8a0fc822013-06-27 20:52:432757// Verify that we don't leak streams and that we properly send a reset
2758// if the server pushes the same stream twice.
[email protected]513963e2013-06-15 01:53:042759TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
[email protected]cdf8f7e72013-05-23 10:56:462760 scoped_ptr<SpdyFrame> stream1_syn(
2761 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042762 scoped_ptr<SpdyFrame> stream1_body(
2763 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202764 scoped_ptr<SpdyFrame> stream3_rst(
2765 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
[email protected]fdc165a2010-09-03 03:51:292766 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522767 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream3_rst, 4),
[email protected]fdc165a2010-09-03 03:51:292768 };
2769
[email protected]ff98d7f02012-03-22 21:44:192770 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042771 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002772 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2773 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432774 const char kPushedData[] = "pushed";
2775 scoped_ptr<SpdyFrame> stream2_body(
2776 spdy_util_.ConstructSpdyBodyFrame(
2777 2, kPushedData, strlen(kPushedData), true));
rchebf12982015-04-10 01:15:002778 scoped_ptr<SpdyFrame> stream3_syn(spdy_util_.ConstructSpdyPush(
2779 NULL, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]fdc165a2010-09-03 03:51:292780 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522781 CreateMockRead(*stream1_reply, 1),
2782 CreateMockRead(*stream2_syn, 2),
2783 CreateMockRead(*stream3_syn, 3),
2784 CreateMockRead(*stream1_body, 5),
2785 CreateMockRead(*stream2_body, 6),
2786 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7), // Force a pause
[email protected]fdc165a2010-09-03 03:51:292787 };
2788
2789 HttpResponseInfo response;
2790 HttpResponseInfo response2;
2791 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522792 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572793 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032794 &response,
2795 &response2,
2796 expected_push_result);
[email protected]fdc165a2010-09-03 03:51:292797
2798 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502799 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022800 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]fdc165a2010-09-03 03:51:292801
2802 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502803 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]fdc165a2010-09-03 03:51:292804 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2805}
2806
[email protected]513963e2013-06-15 01:53:042807TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
[email protected]cdf8f7e72013-05-23 10:56:462808 scoped_ptr<SpdyFrame> stream1_syn(
2809 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042810 scoped_ptr<SpdyFrame> stream1_body(
2811 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232812 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522813 CreateMockWrite(*stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232814 };
2815
[email protected]ff98d7f02012-03-22 21:44:192816 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042817 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002818 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2819 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432820 static const char kPushedData[] = "pushed my darling hello my baby";
2821 scoped_ptr<SpdyFrame> stream2_body_base(
2822 spdy_util_.ConstructSpdyBodyFrame(
2823 2, kPushedData, strlen(kPushedData), true));
2824 const size_t kChunkSize = strlen(kPushedData) / 4;
2825 scoped_ptr<SpdyFrame> stream2_body1(
2826 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2827 scoped_ptr<SpdyFrame> stream2_body2(
2828 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2829 scoped_ptr<SpdyFrame> stream2_body3(
2830 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2831 kChunkSize, false));
2832 scoped_ptr<SpdyFrame> stream2_body4(
2833 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2834 stream2_body_base->size() - 3 * kChunkSize, false));
[email protected]19ec8a72010-08-23 03:38:232835 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522836 CreateMockRead(*stream1_reply, 1),
2837 CreateMockRead(*stream2_syn, 2),
2838 CreateMockRead(*stream2_body1, 3),
2839 CreateMockRead(*stream2_body2, 4),
2840 CreateMockRead(*stream2_body3, 5),
2841 CreateMockRead(*stream2_body4, 6),
2842 CreateMockRead(*stream1_body, 7, SYNCHRONOUS),
2843 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), // Force a pause
[email protected]19ec8a72010-08-23 03:38:232844 };
2845
2846 HttpResponseInfo response;
2847 HttpResponseInfo response2;
2848 std::string expected_push_result("pushed my darling hello my baby");
rch08e3aa3e2015-05-16 14:27:522849 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432850 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232851
2852 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502853 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022854 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232855
2856 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502857 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232858 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2859}
2860
[email protected]513963e2013-06-15 01:53:042861TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
[email protected]cdf8f7e72013-05-23 10:56:462862 scoped_ptr<SpdyFrame> stream1_syn(
2863 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042864 scoped_ptr<SpdyFrame> stream1_body(
2865 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232866 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522867 CreateMockWrite(*stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232868 };
2869
[email protected]ff98d7f02012-03-22 21:44:192870 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042871 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002872 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2873 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432874 static const char kPushedData[] = "pushed my darling hello my baby";
2875 scoped_ptr<SpdyFrame> stream2_body_base(
2876 spdy_util_.ConstructSpdyBodyFrame(
2877 2, kPushedData, strlen(kPushedData), true));
2878 const size_t kChunkSize = strlen(kPushedData) / 4;
2879 scoped_ptr<SpdyFrame> stream2_body1(
2880 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2881 scoped_ptr<SpdyFrame> stream2_body2(
2882 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2883 scoped_ptr<SpdyFrame> stream2_body3(
2884 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2885 kChunkSize, false));
2886 scoped_ptr<SpdyFrame> stream2_body4(
2887 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2888 stream2_body_base->size() - 3 * kChunkSize, false));
[email protected]19ec8a72010-08-23 03:38:232889 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522890 CreateMockRead(*stream1_reply, 1),
2891 CreateMockRead(*stream2_syn, 2),
2892 CreateMockRead(*stream2_body1, 3),
2893 CreateMockRead(*stream2_body2, 4),
2894 CreateMockRead(*stream2_body3, 5),
2895 CreateMockRead(*stream2_body4, 6),
2896 CreateMockRead(*stream1_body.get(), 7, SYNCHRONOUS),
2897 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8) // Force a pause.
[email protected]19ec8a72010-08-23 03:38:232898 };
2899
2900 HttpResponseInfo response;
2901 HttpResponseInfo response2;
rch08e3aa3e2015-05-16 14:27:522902 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432903 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232904
2905 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502906 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022907 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]19ec8a72010-08-23 03:38:232908
2909 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502910 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232911 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2912}
2913
[email protected]513963e2013-06-15 01:53:042914TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
bncacac4f8a2015-06-18 12:24:492915 if (spdy_util_.spdy_version() == HTTP2) {
[email protected]0338bc62014-06-20 17:09:562916 // PUSH_PROMISE with stream id 0 is connection-level error.
2917 // TODO(baranovich): Test session going away.
[email protected]00b29472014-01-16 18:10:242918 return;
2919 }
[email protected]0338bc62014-06-20 17:09:562920
[email protected]cdf8f7e72013-05-23 10:56:462921 scoped_ptr<SpdyFrame> stream1_syn(
2922 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042923 scoped_ptr<SpdyFrame> stream1_body(
2924 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202925 scoped_ptr<SpdyFrame> stream2_rst(
2926 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]19ec8a72010-08-23 03:38:232927 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522928 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]19ec8a72010-08-23 03:38:232929 };
2930
[email protected]ff98d7f02012-03-22 21:44:192931 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042932 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002933 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2934 NULL, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]19ec8a72010-08-23 03:38:232935 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522936 CreateMockRead(*stream1_reply, 1),
2937 CreateMockRead(*stream2_syn, 2),
2938 CreateMockRead(*stream1_body, 4),
2939 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]19ec8a72010-08-23 03:38:232940 };
2941
rch08e3aa3e2015-05-16 14:27:522942 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362943 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502944 BoundNetLog(), GetParam(), NULL);
[email protected]19ec8a72010-08-23 03:38:232945
2946 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572947 helper.AddData(&data);
[email protected]19ec8a72010-08-23 03:38:232948
2949 HttpNetworkTransaction* trans = helper.trans();
2950
2951 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412952 TestCompletionCallback callback;
2953 int rv = trans->Start(
2954 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]19ec8a72010-08-23 03:38:232955 EXPECT_EQ(ERR_IO_PENDING, rv);
2956 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:582957 EXPECT_EQ(OK, rv);
2958
2959 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522960 EXPECT_TRUE(data.AllReadDataConsumed());
2961 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582962
2963 // Verify the SYN_REPLY.
2964 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502965 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:022966 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:582967}
2968
[email protected]513963e2013-06-15 01:53:042969TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
[email protected]cdf8f7e72013-05-23 10:56:462970 scoped_ptr<SpdyFrame> stream1_syn(
2971 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042972 scoped_ptr<SpdyFrame> stream1_body(
2973 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202974 scoped_ptr<SpdyFrame> stream2_rst(
2975 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
[email protected]e3ebba0f2010-08-05 17:59:582976 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522977 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582978 };
2979
[email protected]ff98d7f02012-03-22 21:44:192980 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042981 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002982 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2983 NULL, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]e3ebba0f2010-08-05 17:59:582984 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522985 CreateMockRead(*stream1_reply, 1),
2986 CreateMockRead(*stream2_syn, 2),
2987 CreateMockRead(*stream1_body, 4),
2988 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582989 };
2990
rch08e3aa3e2015-05-16 14:27:522991 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362992 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502993 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582994
2995 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572996 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582997
2998 HttpNetworkTransaction* trans = helper.trans();
2999
3000 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:413001 TestCompletionCallback callback;
3002 int rv = trans->Start(
3003 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:583004 EXPECT_EQ(ERR_IO_PENDING, rv);
3005 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583006 EXPECT_EQ(OK, rv);
3007
3008 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:523009 EXPECT_TRUE(data.AllReadDataConsumed());
3010 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:583011
3012 // Verify the SYN_REPLY.
3013 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503014 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:023015 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:583016}
3017
[email protected]513963e2013-06-15 01:53:043018TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
[email protected]cdf8f7e72013-05-23 10:56:463019 scoped_ptr<SpdyFrame> stream1_syn(
3020 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:043021 scoped_ptr<SpdyFrame> stream1_body(
3022 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:203023 scoped_ptr<SpdyFrame> stream2_rst(
3024 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:583025 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:523026 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:583027 };
3028
[email protected]ff98d7f02012-03-22 21:44:193029 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:043030 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8b9211d2013-06-24 05:54:453031 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
[email protected]8b9211d2013-06-24 05:54:453032 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
3033 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
bnc7ecc1122015-09-28 13:22:493034 (*incomplete_headers)["hello"] = "bye";
[email protected]0338bc62014-06-20 17:09:563035 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
3036 incomplete_headers.Pass(), 2, 1));
[email protected]e3ebba0f2010-08-05 17:59:583037 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523038 CreateMockRead(*stream1_reply, 1),
3039 CreateMockRead(*stream2_syn, 2),
3040 CreateMockRead(*stream1_body, 4),
3041 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:583042 };
3043
rch08e3aa3e2015-05-16 14:27:523044 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363045 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503046 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:583047
3048 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573049 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:583050
3051 HttpNetworkTransaction* trans = helper.trans();
3052
3053 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:413054 TestCompletionCallback callback;
3055 int rv = trans->Start(
3056 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:583057 EXPECT_EQ(ERR_IO_PENDING, rv);
3058 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583059 EXPECT_EQ(OK, rv);
rch08e3aa3e2015-05-16 14:27:523060
[email protected]e3ebba0f2010-08-05 17:59:583061 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:523062 EXPECT_TRUE(data.AllReadDataConsumed());
3063 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:583064
3065 // Verify the SYN_REPLY.
3066 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503067 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:023068 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]e3ebba0f2010-08-05 17:59:583069}
3070
[email protected]8b070372009-11-16 22:01:253071// Verify that various SynReply headers parse correctly through the
3072// HTTP layer.
[email protected]513963e2013-06-15 01:53:043073TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
[email protected]e7f75092010-07-01 22:39:133074 struct SynReplyHeadersTests {
3075 int num_headers;
3076 const char* extra_headers[5];
[email protected]513963e2013-06-15 01:53:043077 SpdyHeaderBlock expected_headers;
[email protected]8b070372009-11-16 22:01:253078 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133079 // This uses a multi-valued cookie header.
3080 { 2,
3081 { "cookie", "val1",
3082 "cookie", "val2", // will get appended separated by NULL
3083 NULL
3084 },
[email protected]8b070372009-11-16 22:01:253085 },
[email protected]e7f75092010-07-01 22:39:133086 // This is the minimalist set of headers.
3087 { 0,
3088 { NULL },
[email protected]8b070372009-11-16 22:01:253089 },
[email protected]e7f75092010-07-01 22:39:133090 // Headers with a comma separated list.
3091 { 1,
3092 { "cookie", "val1,val2",
3093 NULL
3094 },
[email protected]8b070372009-11-16 22:01:253095 }
3096 };
3097
[email protected]513963e2013-06-15 01:53:043098 test_cases[0].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043099 test_cases[1].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043100 test_cases[2].expected_headers["status"] = "200";
[email protected]601e03f12014-04-06 16:26:393101
bnc7ecc1122015-09-28 13:22:493102 // HTTP/2 eliminates use of the :version header.
bncacac4f8a2015-06-18 12:24:493103 if (spdy_util_.spdy_version() < HTTP2) {
[email protected]601e03f12014-04-06 16:26:393104 test_cases[0].expected_headers["version"] = "HTTP/1.1";
3105 test_cases[1].expected_headers["version"] = "HTTP/1.1";
3106 test_cases[2].expected_headers["version"] = "HTTP/1.1";
3107 }
[email protected]513963e2013-06-15 01:53:043108
bnc7ecc1122015-09-28 13:22:493109 test_cases[0].expected_headers["hello"] = "bye";
3110 test_cases[1].expected_headers["hello"] = "bye";
3111 test_cases[2].expected_headers["hello"] = "bye";
3112
3113 test_cases[0].expected_headers["cookie"] = StringPiece("val1\0val2", 9);
3114 test_cases[2].expected_headers["cookie"] = "val1,val2";
3115
viettrungluue4a8b882014-10-16 06:17:383116 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193117 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463118 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523119 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8b070372009-11-16 22:01:253120
[email protected]ff98d7f02012-03-22 21:44:193121 scoped_ptr<SpdyFrame> resp(
[email protected]513963e2013-06-15 01:53:043122 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
[email protected]2bd93022010-07-17 00:58:443123 test_cases[i].num_headers,
3124 1));
[email protected]513963e2013-06-15 01:53:043125 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:383126 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]8b070372009-11-16 22:01:253127 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523128 CreateMockRead(*resp, 1),
3129 CreateMockRead(*body, 2),
3130 MockRead(ASYNC, 0, 3) // EOF
[email protected]8b070372009-11-16 22:01:253131 };
3132
rch08e3aa3e2015-05-16 14:27:523133 SequencedSocketData data(reads, arraysize(reads), writes,
3134 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363135 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503136 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573137 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473138 TransactionHelperResult out = helper.output();
3139
[email protected]8b070372009-11-16 22:01:253140 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023141 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8b070372009-11-16 22:01:253142 EXPECT_EQ("hello!", out.response_data);
3143
3144 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3145 EXPECT_TRUE(headers.get() != NULL);
3146 void* iter = NULL;
[email protected]513963e2013-06-15 01:53:043147 std::string name, value;
3148 SpdyHeaderBlock header_block;
[email protected]8b070372009-11-16 22:01:253149 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
bnc7ecc1122015-09-28 13:22:493150 SpdyHeaderBlock::StringPieceProxy mutable_header_block_value =
3151 header_block[name];
3152 if (static_cast<StringPiece>(mutable_header_block_value).empty()) {
3153 mutable_header_block_value = value;
[email protected]513963e2013-06-15 01:53:043154 } else {
bnc7ecc1122015-09-28 13:22:493155 std::string joint_value = mutable_header_block_value.as_string();
3156 joint_value.append(1, '\0');
3157 joint_value.append(value);
3158 mutable_header_block_value = joint_value;
[email protected]513963e2013-06-15 01:53:043159 }
[email protected]8b070372009-11-16 22:01:253160 }
[email protected]513963e2013-06-15 01:53:043161 EXPECT_EQ(test_cases[i].expected_headers, header_block);
[email protected]8b070372009-11-16 22:01:253162 }
3163}
3164
[email protected]3f662f12010-03-25 19:56:123165// Verify that various SynReply headers parse vary fields correctly
3166// through the HTTP layer, and the response matches the request.
[email protected]513963e2013-06-15 01:53:043167TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
[email protected]3f662f12010-03-25 19:56:123168 // Modify the following data to change/add test cases:
3169 struct SynReplyTests {
[email protected]3f662f12010-03-25 19:56:123170 bool vary_matches;
3171 int num_headers[2];
3172 const char* extra_headers[2][16];
3173 } test_cases[] = {
bnc7ecc1122015-09-28 13:22:493174 // Test the case of a multi-valued cookie. When the value is delimited
3175 // with NUL characters, it needs to be unfolded into multiple headers.
3176 {true,
3177 {1, 4},
3178 {{"cookie", "val1,val2", NULL},
3179 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
3180 "/index.php", spdy_util_.GetVersionKey(), "HTTP/1.1", "vary", "cookie",
3181 NULL}}},
3182 {// Multiple vary fields.
3183 true,
3184 {2, 5},
3185 {{"friend", "barney", "enemy", "snaggletooth", NULL},
3186 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
3187 "/index.php", spdy_util_.GetVersionKey(), "HTTP/1.1", "vary", "friend",
3188 "vary", "enemy", NULL}}},
3189 {// Test a '*' vary field.
3190 false,
3191 {1, 4},
3192 {{"cookie", "val1,val2", NULL},
3193 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
3194 "/index.php", spdy_util_.GetVersionKey(), "HTTP/1.1", "vary", "*",
3195 NULL}}},
3196 {// Multiple comma-separated vary fields.
3197 true,
3198 {2, 4},
3199 {{"friend", "barney", "enemy", "snaggletooth", NULL},
3200 {spdy_util_.GetStatusKey(), "200", spdy_util_.GetPathKey(),
3201 "/index.php", spdy_util_.GetVersionKey(), "HTTP/1.1", "vary",
3202 "friend,enemy", NULL}}}};
[email protected]3f662f12010-03-25 19:56:123203
viettrungluue4a8b882014-10-16 06:17:383204 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]3f662f12010-03-25 19:56:123205 // Construct the request.
[email protected]ff98d7f02012-03-22 21:44:193206 scoped_ptr<SpdyFrame> frame_req(
[email protected]cdf8f7e72013-05-23 10:56:463207 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3208 test_cases[i].num_headers[0],
3209 false, 1, LOWEST, true));
[email protected]3f662f12010-03-25 19:56:123210
3211 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:523212 CreateMockWrite(*frame_req, 0),
[email protected]3f662f12010-03-25 19:56:123213 };
3214
3215 // Construct the reply.
[email protected]745aa9c2014-06-27 02:21:293216 SpdyHeaderBlock reply_headers;
3217 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3218 test_cases[i].num_headers[1],
3219 &reply_headers);
[email protected]ff98d7f02012-03-22 21:44:193220 scoped_ptr<SpdyFrame> frame_reply(
[email protected]745aa9c2014-06-27 02:21:293221 spdy_util_.ConstructSpdyReply(1, reply_headers));
[email protected]3f662f12010-03-25 19:56:123222
[email protected]513963e2013-06-15 01:53:043223 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:383224 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]3f662f12010-03-25 19:56:123225 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523226 CreateMockRead(*frame_reply, 1),
3227 CreateMockRead(*body, 2),
3228 MockRead(ASYNC, 0, 3) // EOF
[email protected]3f662f12010-03-25 19:56:123229 };
3230
[email protected]3f662f12010-03-25 19:56:123231 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:433232 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:123233
[email protected]d3cee19d2010-06-22 18:42:183234 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:433235 for (int ct = 0; ct < header_count; ct++) {
3236 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3237 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3238 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:123239 }
3240
rch08e3aa3e2015-05-16 14:27:523241 SequencedSocketData data(reads, arraysize(reads), writes,
3242 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363243 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503244 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573245 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473246 TransactionHelperResult out = helper.output();
3247
[email protected]3f662f12010-03-25 19:56:123248 EXPECT_EQ(OK, out.rv) << i;
bnc84e7fb52015-12-02 11:50:023249 EXPECT_EQ("HTTP/1.1 200", out.status_line) << i;
[email protected]3f662f12010-03-25 19:56:123250 EXPECT_EQ("hello!", out.response_data) << i;
3251
3252 // Test the response information.
[email protected]3f662f12010-03-25 19:56:123253 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3254 test_cases[i].vary_matches) << i;
3255
3256 // Check the headers.
3257 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3258 ASSERT_TRUE(headers.get() != NULL) << i;
3259 void* iter = NULL;
3260 std::string name, value, lines;
3261 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3262 lines.append(name);
3263 lines.append(": ");
3264 lines.append(value);
3265 lines.append("\n");
3266 }
3267
3268 // Construct the expected header reply string.
[email protected]9aa323192013-05-31 21:38:403269 std::string expected_reply =
3270 spdy_util_.ConstructSpdyReplyString(reply_headers);
3271 EXPECT_EQ(expected_reply, lines) << i;
[email protected]3f662f12010-03-25 19:56:123272 }
3273}
3274
[email protected]dd11b932009-11-30 19:39:483275// Verify that we don't crash on invalid SynReply responses.
[email protected]513963e2013-06-15 01:53:043276TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
[email protected]e7f75092010-07-01 22:39:133277 struct InvalidSynReplyTests {
3278 int num_headers;
3279 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:483280 } test_cases[] = {
bnc7ecc1122015-09-28 13:22:493281 // SYN_REPLY missing status header
3282 {
3283 4,
3284 {spdy_util_.GetPathKey(), "/index.php", spdy_util_.GetVersionKey(),
3285 "HTTP/1.1", "cookie", "val1", "cookie", "val2", NULL},
[email protected]e7f75092010-07-01 22:39:133286 },
bnc7ecc1122015-09-28 13:22:493287 // SYN_REPLY missing version header
3288 {
3289 2, {spdy_util_.GetPathKey(), "/index.php", "status", "200", NULL},
[email protected]e7f75092010-07-01 22:39:133290 },
bnc7ecc1122015-09-28 13:22:493291 // SYN_REPLY with no headers
3292 {
3293 0, {NULL},
3294 },
[email protected]dd11b932009-11-30 19:39:483295 };
3296
viettrungluue4a8b882014-10-16 06:17:383297 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193298 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463299 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:413300 scoped_ptr<SpdyFrame> rst(
3301 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
rdsmithebb50aa2015-11-12 03:44:383302 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dd11b932009-11-30 19:39:483303 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:523304 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
[email protected]dd11b932009-11-30 19:39:483305 };
3306
[email protected]745aa9c2014-06-27 02:21:293307 // Construct the reply.
3308 SpdyHeaderBlock reply_headers;
3309 AppendToHeaderBlock(
3310 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
3311 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
[email protected]dd11b932009-11-30 19:39:483312 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523313 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]dd11b932009-11-30 19:39:483314 };
3315
rch08e3aa3e2015-05-16 14:27:523316 SequencedSocketData data(reads, arraysize(reads), writes,
3317 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363318 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503319 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573320 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473321 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:413322 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]dd11b932009-11-30 19:39:483323 }
3324}
3325
[email protected]94d78132010-01-22 00:53:003326// Verify that we don't crash on some corrupt frames.
bncacac4f8a2015-06-18 12:24:493327// TODO(jgraettinger): HTTP/2 treats a header decompression failure as a
[email protected]e3352df2014-03-19 05:55:423328// connection error. I'd like to backport this behavior to SPDY3 as well.
[email protected]513963e2013-06-15 01:53:043329TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
bncacac4f8a2015-06-18 12:24:493330 if (spdy_util_.spdy_version() >= HTTP2) {
[email protected]e3352df2014-03-19 05:55:423331 return;
3332 }
[email protected]61c83f782011-01-27 21:00:243333 // This is the length field that's too short.
[email protected]ff98d7f02012-03-22 21:44:193334 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
[email protected]513963e2013-06-15 01:53:043335 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:043336 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]8a0fc822013-06-27 20:52:433337 size_t right_size =
bncacac4f8a2015-06-18 12:24:493338 (spdy_util_.spdy_version() < HTTP2)
3339 ? syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize()
3340 : syn_reply_wrong_length->size();
[email protected]8a0fc822013-06-27 20:52:433341 size_t wrong_size = right_size - 4;
[email protected]a4bfdf72013-02-22 04:06:163342 test::SetFrameLength(syn_reply_wrong_length.get(),
[email protected]8a0fc822013-06-27 20:52:433343 wrong_size,
[email protected]513963e2013-06-15 01:53:043344 spdy_util_.spdy_version());
[email protected]94d78132010-01-22 00:53:003345
3346 struct SynReplyTests {
[email protected]ff98d7f02012-03-22 21:44:193347 const SpdyFrame* syn_reply;
[email protected]94d78132010-01-22 00:53:003348 } test_cases[] = {
[email protected]61c83f782011-01-27 21:00:243349 { syn_reply_wrong_length.get(), },
[email protected]94d78132010-01-22 00:53:003350 };
3351
viettrungluue4a8b882014-10-16 06:17:383352 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193353 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463354 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]099bc7e2013-07-18 04:19:163355 scoped_ptr<SpdyFrame> rst(
3356 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3357 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:523358 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
[email protected]94d78132010-01-22 00:53:003359 };
3360
[email protected]513963e2013-06-15 01:53:043361 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003362 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523363 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size, 1),
3364 CreateMockRead(*body, 2),
3365 MockRead(ASYNC, 0, 4) // EOF
[email protected]94d78132010-01-22 00:53:003366 };
3367
rch08e3aa3e2015-05-16 14:27:523368 SequencedSocketData data(reads, arraysize(reads), writes,
3369 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363370 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503371 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573372 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473373 TransactionHelperResult out = helper.output();
[email protected]955fc2e72010-02-08 20:37:303374 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003375 }
3376}
3377
bncacac4f8a2015-06-18 12:24:493378// HTTP/2 treats a header decompression failure as a connection-level error.
[email protected]e3352df2014-03-19 05:55:423379TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
bncacac4f8a2015-06-18 12:24:493380 if (spdy_util_.spdy_version() < HTTP2) {
[email protected]e3352df2014-03-19 05:55:423381 return;
3382 }
3383 // This is the length field that's too short.
3384 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3385 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3386 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3387 size_t right_size =
[email protected]c143f2742014-03-31 00:48:543388 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
[email protected]e3352df2014-03-19 05:55:423389 size_t wrong_size = right_size - 4;
3390 test::SetFrameLength(syn_reply_wrong_length.get(),
3391 wrong_size,
3392 spdy_util_.spdy_version());
3393
[email protected]e3352df2014-03-19 05:55:423394 scoped_ptr<SpdyFrame> req(
3395 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bdd1b222014-06-10 11:08:393396 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3397 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch08e3aa3e2015-05-16 14:27:523398 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]e3352df2014-03-19 05:55:423399
3400 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3401 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523402 MockRead(ASYNC, syn_reply_wrong_length->data(),
3403 syn_reply_wrong_length->size() - 4, 1),
[email protected]e3352df2014-03-19 05:55:423404 };
3405
rch08e3aa3e2015-05-16 14:27:523406 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]e3352df2014-03-19 05:55:423407 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3408 BoundNetLog(), GetParam(), NULL);
3409 helper.RunToCompletion(&data);
3410 TransactionHelperResult out = helper.output();
[email protected]bdd1b222014-06-10 11:08:393411 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3412}
3413
3414TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
bnc9b79a572015-09-02 12:25:033415 if (GetParam().protocol < kProtoHTTP2) {
[email protected]bdd1b222014-06-10 11:08:393416 // Decompression failures are a stream error in SPDY3 and above.
3417 return;
3418 }
3419 scoped_ptr<SpdyFrame> req(
3420 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3421 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3422 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch08e3aa3e2015-05-16 14:27:523423 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393424
3425 // Read HEADERS with corrupted payload.
3426 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3427 memset(resp->data() + 12, 0xff, resp->size() - 12);
rch08e3aa3e2015-05-16 14:27:523428 MockRead reads[] = {CreateMockRead(*resp, 1)};
[email protected]bdd1b222014-06-10 11:08:393429
rch08e3aa3e2015-05-16 14:27:523430 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bdd1b222014-06-10 11:08:393431 NormalSpdyTransactionHelper helper(
3432 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3433 helper.RunToCompletion(&data);
3434 TransactionHelperResult out = helper.output();
3435 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3436}
3437
3438TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3439 scoped_ptr<SpdyFrame> req(
3440 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3441 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3442 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
rch08e3aa3e2015-05-16 14:27:523443 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393444
3445 // Read WINDOW_UPDATE with incorrectly-sized payload.
3446 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3447 // which is mapped to a protocol error, and not a frame size error.
3448 scoped_ptr<SpdyFrame> bad_window_update(
3449 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3450 test::SetFrameLength(bad_window_update.get(),
3451 bad_window_update->size() - 1,
3452 spdy_util_.spdy_version());
rch08e3aa3e2015-05-16 14:27:523453 MockRead reads[] = {CreateMockRead(*bad_window_update, 1)};
[email protected]bdd1b222014-06-10 11:08:393454
rch08e3aa3e2015-05-16 14:27:523455 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bdd1b222014-06-10 11:08:393456 NormalSpdyTransactionHelper helper(
3457 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3458 helper.RunToCompletion(&data);
3459 TransactionHelperResult out = helper.output();
[email protected]e3352df2014-03-19 05:55:423460 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3461}
3462
[email protected]bf2491a92009-11-29 16:39:483463// Test that we shutdown correctly on write errors.
[email protected]513963e2013-06-15 01:53:043464TEST_P(SpdyNetworkTransactionTest, WriteError) {
[email protected]cdf8f7e72013-05-23 10:56:463465 scoped_ptr<SpdyFrame> req(
3466 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483467 MockWrite writes[] = {
[email protected]bdd1b222014-06-10 11:08:393468 // We'll write 10 bytes successfully
3469 MockWrite(ASYNC, req->data(), 10, 0),
3470 // Followed by ERROR!
3471 MockWrite(ASYNC, ERR_FAILED, 1),
3472 // Session drains and attempts to write a GOAWAY: Another ERROR!
3473 MockWrite(ASYNC, ERR_FAILED, 2),
[email protected]bf2491a92009-11-29 16:39:483474 };
3475
[email protected]238002d2013-10-17 02:01:403476 MockRead reads[] = {
[email protected]bdd1b222014-06-10 11:08:393477 MockRead(ASYNC, 0, 3) // EOF
[email protected]238002d2013-10-17 02:01:403478 };
3479
3480 DeterministicSocketData data(reads, arraysize(reads),
3481 writes, arraysize(writes));
3482
[email protected]262eec82013-03-19 21:01:363483 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503484 BoundNetLog(), GetParam(), NULL);
[email protected]238002d2013-10-17 02:01:403485 helper.SetDeterministic();
3486 helper.RunPreTestSetup();
3487 helper.AddDeterministicData(&data);
3488 EXPECT_TRUE(helper.StartDefaultTest());
3489 data.RunFor(2);
3490 helper.FinishDefaultTest();
rch37de576c2015-05-17 20:28:173491 EXPECT_TRUE(data.AllWriteDataConsumed());
3492 EXPECT_TRUE(!data.AllReadDataConsumed());
[email protected]3caf5542010-07-16 15:19:473493 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483494 EXPECT_EQ(ERR_FAILED, out.rv);
3495}
3496
3497// Test that partial writes work.
[email protected]513963e2013-06-15 01:53:043498TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
[email protected]bf2491a92009-11-29 16:39:483499 // Chop the SYN_STREAM frame into 5 chunks.
[email protected]cdf8f7e72013-05-23 10:56:463500 scoped_ptr<SpdyFrame> req(
3501 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483502 const int kChunks = 5;
[email protected]4356f0f2013-04-07 00:58:173503 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
rch08e3aa3e2015-05-16 14:27:523504 for (int i = 0; i < kChunks; ++i) {
3505 writes[i].sequence_number = i;
3506 }
[email protected]bf2491a92009-11-29 16:39:483507
[email protected]513963e2013-06-15 01:53:043508 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3509 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:483510 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523511 CreateMockRead(*resp, kChunks),
3512 CreateMockRead(*body, kChunks + 1),
3513 MockRead(ASYNC, 0, kChunks + 2) // EOF
[email protected]bf2491a92009-11-29 16:39:483514 };
3515
rch08e3aa3e2015-05-16 14:27:523516 SequencedSocketData data(reads, arraysize(reads), writes.get(), kChunks);
[email protected]262eec82013-03-19 21:01:363517 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503518 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573519 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473520 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483521 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023522 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]bf2491a92009-11-29 16:39:483523 EXPECT_EQ("hello!", out.response_data);
3524}
3525
[email protected]94d78132010-01-22 00:53:003526// In this test, we enable compression, but get a uncompressed SynReply from
3527// the server. Verify that teardown is all clean.
[email protected]513963e2013-06-15 01:53:043528TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
bncacac4f8a2015-06-18 12:24:493529 if (spdy_util_.spdy_version() >= HTTP2) {
[email protected]e3352df2014-03-19 05:55:423530 // HPACK doesn't use deflate compression.
3531 return;
3532 }
[email protected]ff98d7f02012-03-22 21:44:193533 scoped_ptr<SpdyFrame> compressed(
[email protected]cdf8f7e72013-05-23 10:56:463534 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
[email protected]bdd1b222014-06-10 11:08:393535 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3536 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch08e3aa3e2015-05-16 14:27:523537 MockWrite writes[] = {CreateMockWrite(*compressed, 0),
3538 CreateMockWrite(*goaway, 2)};
[email protected]94d78132010-01-22 00:53:003539
[email protected]513963e2013-06-15 01:53:043540 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3541 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003542 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523543 CreateMockRead(*resp, 1),
[email protected]94d78132010-01-22 00:53:003544 };
3545
rch08e3aa3e2015-05-16 14:27:523546 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
rdsmith82957ad2015-09-16 19:42:033547 scoped_ptr<SpdySessionDependencies> session_deps =
[email protected]513963e2013-06-15 01:53:043548 CreateSpdySessionDependencies(GetParam());
[email protected]f9cf5572012-12-04 15:52:093549 session_deps->enable_compression = true;
[email protected]262eec82013-03-19 21:01:363550 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
rdsmith82957ad2015-09-16 19:42:033551 BoundNetLog(), GetParam(),
3552 session_deps.Pass());
[email protected]dd54bd82012-07-19 23:44:573553 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473554 TransactionHelperResult out = helper.output();
[email protected]bdd1b222014-06-10 11:08:393555 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003556}
3557
[email protected]9e743cd2010-03-16 07:03:533558// Test that the NetLog contains good data for a simple GET request.
[email protected]513963e2013-06-15 01:53:043559TEST_P(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:403560 static const char* const kExtraHeaders[] = {
3561 "user-agent", "Chrome",
3562 };
[email protected]cdf8f7e72013-05-23 10:56:463563 scoped_ptr<SpdyFrame> req(
3564 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523565 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]dac358042009-12-18 02:07:483566
[email protected]513963e2013-06-15 01:53:043567 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3568 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]dac358042009-12-18 02:07:483569 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523570 CreateMockRead(*resp, 1),
3571 CreateMockRead(*body, 2),
3572 MockRead(ASYNC, 0, 3) // EOF
[email protected]dac358042009-12-18 02:07:483573 };
3574
vishal.b62985ca92015-04-17 08:45:513575 BoundTestNetLog log;
[email protected]dac358042009-12-18 02:07:483576
rch08e3aa3e2015-05-16 14:27:523577 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3deb9a52010-11-11 00:24:403578 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
[email protected]262eec82013-03-19 21:01:363579 DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503580 log.bound(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573581 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473582 TransactionHelperResult out = helper.output();
[email protected]dac358042009-12-18 02:07:483583 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023584 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]dac358042009-12-18 02:07:483585 EXPECT_EQ("hello!", out.response_data);
3586
[email protected]9e743cd2010-03-16 07:03:533587 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:473588 // This test is intentionally non-specific about the exact ordering of the
3589 // log; instead we just check to make sure that certain events exist, and that
3590 // they are in the right order.
mmenke43758e62015-05-04 21:09:463591 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403592 log.GetEntries(&entries);
3593
3594 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:483595 int pos = 0;
bnc301745a2015-03-10 03:22:163596 pos = ExpectLogContainsSomewhere(entries, 0,
3597 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3598 NetLog::PHASE_BEGIN);
3599 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3600 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3601 NetLog::PHASE_END);
3602 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3603 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3604 NetLog::PHASE_BEGIN);
3605 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3606 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3607 NetLog::PHASE_END);
3608 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3609 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3610 NetLog::PHASE_BEGIN);
3611 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3612 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3613 NetLog::PHASE_END);
[email protected]3deb9a52010-11-11 00:24:403614
3615 // Check that we logged all the headers correctly
bnc301745a2015-03-10 03:22:163616 const NetLog::EventType type = (GetParam().protocol <= kProtoSPDY31)
3617 ? NetLog::TYPE_HTTP2_SESSION_SYN_STREAM
3618 : NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS;
3619 pos = ExpectLogContainsSomewhere(entries, 0, type, NetLog::PHASE_NONE);
[email protected]3deb9a52010-11-11 00:24:403620
[email protected]ea5ef4c2013-06-13 22:50:273621 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:573622 ASSERT_TRUE(entries[pos].params.get());
3623 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3624
3625 std::vector<std::string> expected;
bncce36dca22015-04-21 22:11:233626 expected.push_back(std::string(spdy_util_.GetHostKey()) +
3627 ": www.example.org");
[email protected]513963e2013-06-15 01:53:043628 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
rchebf12982015-04-10 01:15:003629 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": " +
3630 spdy_util_.default_url().scheme());
[email protected]513963e2013-06-15 01:53:043631 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
[email protected]f3da152d2012-06-02 01:00:573632 expected.push_back("user-agent: Chrome");
bncacac4f8a2015-06-18 12:24:493633 if (spdy_util_.spdy_version() < HTTP2) {
3634 // HTTP/2 eliminates use of the :version header.
[email protected]601e03f12014-04-06 16:26:393635 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3636 }
[email protected]f3da152d2012-06-02 01:00:573637 EXPECT_EQ(expected.size(), header_list->GetSize());
3638 for (std::vector<std::string>::const_iterator it = expected.begin();
3639 it != expected.end();
3640 ++it) {
3641 base::StringValue header(*it);
3642 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3643 "Header not found: " << *it;
[email protected]3deb9a52010-11-11 00:24:403644 }
[email protected]dac358042009-12-18 02:07:483645}
3646
[email protected]79d84222010-02-26 00:01:443647// Since we buffer the IO from the stream to the renderer, this test verifies
3648// that when we read out the maximum amount of data (e.g. we received 50 bytes
3649// on the network, but issued a Read for only 5 of those bytes) that the data
3650// flow still works correctly.
[email protected]513963e2013-06-15 01:53:043651TEST_P(SpdyNetworkTransactionTest, BufferFull) {
[email protected]513963e2013-06-15 01:53:043652 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433653
[email protected]cdf8f7e72013-05-23 10:56:463654 scoped_ptr<SpdyFrame> req(
3655 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523656 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]79d84222010-02-26 00:01:443657
[email protected]20d005f2010-07-02 19:55:433658 // 2 data frames in a single read.
[email protected]ff98d7f02012-03-22 21:44:193659 scoped_ptr<SpdyFrame> data_frame_1(
3660 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3661 scoped_ptr<SpdyFrame> data_frame_2(
3662 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3663 const SpdyFrame* data_frames[2] = {
[email protected]20d005f2010-07-02 19:55:433664 data_frame_1.get(),
3665 data_frame_2.get(),
[email protected]79d84222010-02-26 00:01:443666 };
[email protected]20d005f2010-07-02 19:55:433667 char combined_data_frames[100];
3668 int combined_data_frames_len =
3669 CombineFrames(data_frames, arraysize(data_frames),
3670 combined_data_frames, arraysize(combined_data_frames));
[email protected]ff98d7f02012-03-22 21:44:193671 scoped_ptr<SpdyFrame> last_frame(
3672 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
[email protected]79d84222010-02-26 00:01:443673
[email protected]513963e2013-06-15 01:53:043674 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]79d84222010-02-26 00:01:443675 MockRead reads[] = {
rch32320842015-05-16 15:57:093676 CreateMockRead(*resp, 1),
3677 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3678 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3679 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
3680 CreateMockRead(*last_frame, 5),
3681 MockRead(ASYNC, 0, 6) // EOF
[email protected]79d84222010-02-26 00:01:443682 };
3683
rch32320842015-05-16 15:57:093684 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]79d84222010-02-26 00:01:443685
[email protected]49639fa2011-12-20 23:22:413686 TestCompletionCallback callback;
[email protected]79d84222010-02-26 00:01:443687
[email protected]262eec82013-03-19 21:01:363688 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503689 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473690 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573691 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473692 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413693 int rv = trans->Start(
3694 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]79d84222010-02-26 00:01:443695 EXPECT_EQ(ERR_IO_PENDING, rv);
3696
[email protected]3caf5542010-07-16 15:19:473697 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:443698 out.rv = callback.WaitForResult();
3699 EXPECT_EQ(out.rv, OK);
3700
3701 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503702 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]79d84222010-02-26 00:01:443703 EXPECT_TRUE(response->was_fetched_via_spdy);
3704 out.status_line = response->headers->GetStatusLine();
3705 out.response_info = *response; // Make a copy so we can verify.
3706
3707 // Read Data
[email protected]49639fa2011-12-20 23:22:413708 TestCompletionCallback read_callback;
[email protected]79d84222010-02-26 00:01:443709
3710 std::string content;
3711 do {
3712 // Read small chunks at a time.
3713 const int kSmallReadSize = 3;
bnc301745a2015-03-10 03:22:163714 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503715 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163716 if (rv == ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573717 data.CompleteRead();
[email protected]79d84222010-02-26 00:01:443718 rv = read_callback.WaitForResult();
3719 }
3720 if (rv > 0) {
3721 content.append(buf->data(), rv);
3722 } else if (rv < 0) {
3723 NOTREACHED();
3724 }
3725 } while (rv > 0);
3726
3727 out.response_data.swap(content);
3728
[email protected]30c942b2010-07-21 16:59:593729 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553730 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173731 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553732
[email protected]79d84222010-02-26 00:01:443733 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473734 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:443735
3736 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023737 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]79d84222010-02-26 00:01:443738 EXPECT_EQ("goodbye world", out.response_data);
3739}
3740
[email protected]8918d282010-03-02 00:57:553741// Verify that basic buffering works; when multiple data frames arrive
3742// at the same time, ensure that we don't notify a read completion for
3743// each data frame individually.
[email protected]513963e2013-06-15 01:53:043744TEST_P(SpdyNetworkTransactionTest, Buffering) {
[email protected]513963e2013-06-15 01:53:043745 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433746
[email protected]cdf8f7e72013-05-23 10:56:463747 scoped_ptr<SpdyFrame> req(
3748 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch32320842015-05-16 15:57:093749 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8918d282010-03-02 00:57:553750
3751 // 4 data frames in a single read.
[email protected]ff98d7f02012-03-22 21:44:193752 scoped_ptr<SpdyFrame> data_frame(
3753 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3754 scoped_ptr<SpdyFrame> data_frame_fin(
3755 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3756 const SpdyFrame* data_frames[4] = {
[email protected]20d005f2010-07-02 19:55:433757 data_frame.get(),
3758 data_frame.get(),
3759 data_frame.get(),
3760 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:553761 };
[email protected]20d005f2010-07-02 19:55:433762 char combined_data_frames[100];
3763 int combined_data_frames_len =
3764 CombineFrames(data_frames, arraysize(data_frames),
3765 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:553766
[email protected]513963e2013-06-15 01:53:043767 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553768 MockRead reads[] = {
rch32320842015-05-16 15:57:093769 CreateMockRead(*resp, 1),
3770 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3771 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3772 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553773 };
3774
rch32320842015-05-16 15:57:093775 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553776
[email protected]262eec82013-03-19 21:01:363777 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503778 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473779 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573780 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473781 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553782
[email protected]49639fa2011-12-20 23:22:413783 TestCompletionCallback callback;
3784 int rv = trans->Start(
3785 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553786 EXPECT_EQ(ERR_IO_PENDING, rv);
3787
[email protected]3caf5542010-07-16 15:19:473788 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553789 out.rv = callback.WaitForResult();
3790 EXPECT_EQ(out.rv, OK);
3791
3792 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503793 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553794 EXPECT_TRUE(response->was_fetched_via_spdy);
3795 out.status_line = response->headers->GetStatusLine();
3796 out.response_info = *response; // Make a copy so we can verify.
3797
3798 // Read Data
[email protected]49639fa2011-12-20 23:22:413799 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553800
3801 std::string content;
3802 int reads_completed = 0;
3803 do {
3804 // Read small chunks at a time.
3805 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163806 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503807 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163808 if (rv == ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573809 data.CompleteRead();
[email protected]8918d282010-03-02 00:57:553810 rv = read_callback.WaitForResult();
3811 }
3812 if (rv > 0) {
3813 EXPECT_EQ(kSmallReadSize, rv);
3814 content.append(buf->data(), rv);
3815 } else if (rv < 0) {
3816 FAIL() << "Unexpected read error: " << rv;
3817 }
3818 reads_completed++;
3819 } while (rv > 0);
3820
3821 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3822
3823 out.response_data.swap(content);
3824
[email protected]30c942b2010-07-21 16:59:593825 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553826 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173827 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553828
3829 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473830 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553831
3832 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023833 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:553834 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3835}
3836
3837// Verify the case where we buffer data but read it after it has been buffered.
[email protected]513963e2013-06-15 01:53:043838TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
[email protected]513963e2013-06-15 01:53:043839 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433840
[email protected]cdf8f7e72013-05-23 10:56:463841 scoped_ptr<SpdyFrame> req(
3842 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523843 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8918d282010-03-02 00:57:553844
[email protected]20d005f2010-07-02 19:55:433845 // 5 data frames in a single read.
[email protected]745aa9c2014-06-27 02:21:293846 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:193847 scoped_ptr<SpdyFrame> data_frame(
3848 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3849 scoped_ptr<SpdyFrame> data_frame_fin(
3850 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
[email protected]745aa9c2014-06-27 02:21:293851 const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
3852 data_frame.get(), data_frame_fin.get()};
[email protected]20d005f2010-07-02 19:55:433853 char combined_frames[200];
3854 int combined_frames_len =
3855 CombineFrames(frames, arraysize(frames),
3856 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:553857
3858 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523859 MockRead(ASYNC, combined_frames, combined_frames_len, 1),
3860 MockRead(ASYNC, 0, 2) // EOF
[email protected]8918d282010-03-02 00:57:553861 };
3862
rch08e3aa3e2015-05-16 14:27:523863 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553864
[email protected]262eec82013-03-19 21:01:363865 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503866 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473867 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573868 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473869 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553870
[email protected]49639fa2011-12-20 23:22:413871 TestCompletionCallback callback;
3872 int rv = trans->Start(
3873 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553874 EXPECT_EQ(ERR_IO_PENDING, rv);
3875
[email protected]3caf5542010-07-16 15:19:473876 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553877 out.rv = callback.WaitForResult();
3878 EXPECT_EQ(out.rv, OK);
3879
3880 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503881 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553882 EXPECT_TRUE(response->was_fetched_via_spdy);
3883 out.status_line = response->headers->GetStatusLine();
3884 out.response_info = *response; // Make a copy so we can verify.
3885
3886 // Read Data
[email protected]49639fa2011-12-20 23:22:413887 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553888
3889 std::string content;
3890 int reads_completed = 0;
3891 do {
3892 // Read small chunks at a time.
3893 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163894 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503895 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:553896 if (rv > 0) {
3897 EXPECT_EQ(kSmallReadSize, rv);
3898 content.append(buf->data(), rv);
3899 } else if (rv < 0) {
3900 FAIL() << "Unexpected read error: " << rv;
3901 }
3902 reads_completed++;
3903 } while (rv > 0);
3904
3905 EXPECT_EQ(3, reads_completed);
3906
3907 out.response_data.swap(content);
3908
[email protected]30c942b2010-07-21 16:59:593909 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553910 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173911 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553912
3913 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473914 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553915
3916 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:023917 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]8918d282010-03-02 00:57:553918 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3919}
3920
3921// Verify the case where we buffer data and close the connection.
[email protected]513963e2013-06-15 01:53:043922TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
[email protected]513963e2013-06-15 01:53:043923 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433924
[email protected]cdf8f7e72013-05-23 10:56:463925 scoped_ptr<SpdyFrame> req(
3926 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch32320842015-05-16 15:57:093927 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8918d282010-03-02 00:57:553928
3929 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:433930 // NOTE: We don't FIN the stream.
[email protected]ff98d7f02012-03-22 21:44:193931 scoped_ptr<SpdyFrame> data_frame(
3932 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3933 const SpdyFrame* data_frames[4] = {
[email protected]20d005f2010-07-02 19:55:433934 data_frame.get(),
3935 data_frame.get(),
3936 data_frame.get(),
3937 data_frame.get()
[email protected]8918d282010-03-02 00:57:553938 };
[email protected]20d005f2010-07-02 19:55:433939 char combined_data_frames[100];
3940 int combined_data_frames_len =
3941 CombineFrames(data_frames, arraysize(data_frames),
3942 combined_data_frames, arraysize(combined_data_frames));
[email protected]513963e2013-06-15 01:53:043943 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553944 MockRead reads[] = {
rch32320842015-05-16 15:57:093945 CreateMockRead(*resp, 1),
3946 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3947 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3948 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553949 };
3950
rch32320842015-05-16 15:57:093951 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553952
[email protected]262eec82013-03-19 21:01:363953 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503954 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473955 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573956 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473957 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553958
[email protected]49639fa2011-12-20 23:22:413959 TestCompletionCallback callback;
[email protected]8918d282010-03-02 00:57:553960
[email protected]49639fa2011-12-20 23:22:413961 int rv = trans->Start(
3962 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553963 EXPECT_EQ(ERR_IO_PENDING, rv);
3964
[email protected]3caf5542010-07-16 15:19:473965 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553966 out.rv = callback.WaitForResult();
3967 EXPECT_EQ(out.rv, OK);
3968
3969 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503970 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553971 EXPECT_TRUE(response->was_fetched_via_spdy);
3972 out.status_line = response->headers->GetStatusLine();
3973 out.response_info = *response; // Make a copy so we can verify.
3974
3975 // Read Data
[email protected]49639fa2011-12-20 23:22:413976 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553977
3978 std::string content;
3979 int reads_completed = 0;
3980 do {
3981 // Read small chunks at a time.
3982 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163983 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503984 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163985 if (rv == ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573986 data.CompleteRead();
[email protected]8918d282010-03-02 00:57:553987 rv = read_callback.WaitForResult();
3988 }
3989 if (rv > 0) {
3990 content.append(buf->data(), rv);
3991 } else if (rv < 0) {
3992 // This test intentionally closes the connection, and will get an error.
3993 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
3994 break;
3995 }
3996 reads_completed++;
3997 } while (rv > 0);
3998
3999 EXPECT_EQ(0, reads_completed);
4000
4001 out.response_data.swap(content);
4002
[email protected]30c942b2010-07-21 16:59:594003 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:554004 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:174005 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:554006
4007 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474008 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:554009}
4010
[email protected]1ed7b3dc2010-03-04 05:41:454011// Verify the case where we buffer data and cancel the transaction.
[email protected]513963e2013-06-15 01:53:044012TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
[email protected]513963e2013-06-15 01:53:044013 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:434014
[email protected]cdf8f7e72013-05-23 10:56:464015 scoped_ptr<SpdyFrame> req(
4016 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]975da41a2014-06-05 03:36:244017 scoped_ptr<SpdyFrame> rst(
4018 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
rch32320842015-05-16 15:57:094019 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
[email protected]1ed7b3dc2010-03-04 05:41:454020
[email protected]20d005f2010-07-02 19:55:434021 // NOTE: We don't FIN the stream.
[email protected]ff98d7f02012-03-22 21:44:194022 scoped_ptr<SpdyFrame> data_frame(
4023 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
[email protected]1ed7b3dc2010-03-04 05:41:454024
[email protected]513963e2013-06-15 01:53:044025 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:454026 MockRead reads[] = {
rch32320842015-05-16 15:57:094027 CreateMockRead(*resp, 1),
4028 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
4029 CreateMockRead(*data_frame, 3),
4030 MockRead(ASYNC, 0, 5) // EOF
[email protected]1ed7b3dc2010-03-04 05:41:454031 };
4032
rch32320842015-05-16 15:57:094033 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1ed7b3dc2010-03-04 05:41:454034
[email protected]262eec82013-03-19 21:01:364035 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504036 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474037 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574038 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474039 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:414040 TestCompletionCallback callback;
[email protected]1ed7b3dc2010-03-04 05:41:454041
[email protected]49639fa2011-12-20 23:22:414042 int rv = trans->Start(
4043 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]1ed7b3dc2010-03-04 05:41:454044 EXPECT_EQ(ERR_IO_PENDING, rv);
4045
[email protected]3caf5542010-07-16 15:19:474046 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:454047 out.rv = callback.WaitForResult();
4048 EXPECT_EQ(out.rv, OK);
4049
4050 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504051 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]1ed7b3dc2010-03-04 05:41:454052 EXPECT_TRUE(response->was_fetched_via_spdy);
4053 out.status_line = response->headers->GetStatusLine();
4054 out.response_info = *response; // Make a copy so we can verify.
4055
4056 // Read Data
[email protected]49639fa2011-12-20 23:22:414057 TestCompletionCallback read_callback;
[email protected]1ed7b3dc2010-03-04 05:41:454058
[email protected]88c7b4be2014-03-19 23:04:014059 const int kReadSize = 256;
bnc301745a2015-03-10 03:22:164060 scoped_refptr<IOBuffer> buf(new IOBuffer(kReadSize));
[email protected]88c7b4be2014-03-19 23:04:014061 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:164062 ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
[email protected]88c7b4be2014-03-19 23:04:014063
4064 // Complete the read now, which causes buffering to start.
4065 data.CompleteRead();
4066 // Destroy the transaction, causing the stream to get cancelled
4067 // and orphaning the buffered IO task.
4068 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:454069
4070 // Flush the MessageLoop; this will cause the buffered IO task
4071 // to run for the final time.
[email protected]fc9d88472013-08-14 02:31:174072 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:474073
4074 // Verify that we consumed all test data.
4075 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:454076}
4077
[email protected]74188f22010-04-09 20:18:504078// Test that if the server requests persistence of settings, that we save
[email protected]18b28ab2012-04-18 02:14:424079// the settings in the HttpServerProperties.
[email protected]513963e2013-06-15 01:53:044080TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
bncacac4f8a2015-06-18 12:24:494081 if (spdy_util_.spdy_version() >= HTTP2) {
4082 // HTTP/2 doesn't support settings persistence.
[email protected]8a7bc7a2014-02-28 21:25:224083 return;
4084 }
[email protected]74188f22010-04-09 20:18:504085 static const SpdyHeaderInfo kSynReplyInfo = {
[email protected]ff98d7f02012-03-22 21:44:194086 SYN_REPLY, // Syn Reply
[email protected]e0935cc2012-03-24 14:12:484087 1, // Stream ID
4088 0, // Associated Stream ID
[email protected]513963e2013-06-15 01:53:044089 ConvertRequestPriorityToSpdyPriority(
4090 LOWEST, spdy_util_.spdy_version()),
[email protected]ff98d7f02012-03-22 21:44:194091 CONTROL_FLAG_NONE, // Control Flags
[email protected]e0935cc2012-03-24 14:12:484092 false, // Compressed
[email protected]5a7bb252013-02-09 00:21:054093 RST_STREAM_INVALID, // Status
[email protected]e0935cc2012-03-24 14:12:484094 NULL, // Data
4095 0, // Data Length
[email protected]ff98d7f02012-03-22 21:44:194096 DATA_FLAG_NONE // Data Flags
[email protected]74188f22010-04-09 20:18:504097 };
[email protected]74188f22010-04-09 20:18:504098
[email protected]c0168822011-12-10 01:24:274099 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364100 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4101 net_log, GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:584102 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504103
4104 // Verify that no settings exist initially.
bncce36dca22015-04-21 22:11:234105 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]102e27c2011-02-23 01:01:314106 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]53bfa31c2011-11-15 19:20:314107 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4108 host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504109
4110 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:464111 scoped_ptr<SpdyFrame> req(
4112 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524113 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]74188f22010-04-09 20:18:504114
4115 // Construct the reply.
[email protected]513963e2013-06-15 01:53:044116 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4117 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4118 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]ff98d7f02012-03-22 21:44:194119 scoped_ptr<SpdyFrame> reply(
[email protected]513963e2013-06-15 01:53:044120 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
[email protected]74188f22010-04-09 20:18:504121
[email protected]e0935cc2012-03-24 14:12:484122 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
[email protected]74188f22010-04-09 20:18:504123 unsigned int kSampleValue1 = 0x0a0a0a0a;
[email protected]e0935cc2012-03-24 14:12:484124 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
[email protected]74188f22010-04-09 20:18:504125 unsigned int kSampleValue2 = 0x0b0b0b0b;
[email protected]e0935cc2012-03-24 14:12:484126 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
[email protected]74188f22010-04-09 20:18:504127 unsigned int kSampleValue3 = 0x0c0c0c0c;
[email protected]ff98d7f02012-03-22 21:44:194128 scoped_ptr<SpdyFrame> settings_frame;
[email protected]74188f22010-04-09 20:18:504129 {
4130 // Construct the SETTINGS frame.
[email protected]18b28ab2012-04-18 02:14:424131 SettingsMap settings;
[email protected]e0935cc2012-03-24 14:12:484132 // First add a persisted setting.
[email protected]18b28ab2012-04-18 02:14:424133 settings[kSampleId1] =
4134 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
[email protected]e0935cc2012-03-24 14:12:484135 // Next add a non-persisted setting.
[email protected]18b28ab2012-04-18 02:14:424136 settings[kSampleId2] =
4137 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
[email protected]e0935cc2012-03-24 14:12:484138 // Next add another persisted setting.
[email protected]18b28ab2012-04-18 02:14:424139 settings[kSampleId3] =
4140 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
[email protected]c10b20852013-05-15 21:29:204141 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
[email protected]74188f22010-04-09 20:18:504142 }
4143
[email protected]513963e2013-06-15 01:53:044144 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504145 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524146 CreateMockRead(*reply, 1),
4147 CreateMockRead(*body, 2),
4148 CreateMockRead(*settings_frame, 3),
4149 MockRead(ASYNC, 0, 4) // EOF
[email protected]74188f22010-04-09 20:18:504150 };
4151
rch08e3aa3e2015-05-16 14:27:524152 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574153 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:584154 helper.RunDefaultTest();
4155 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474156 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504157 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:024158 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]74188f22010-04-09 20:18:504159 EXPECT_EQ("hello!", out.response_data);
4160
4161 {
4162 // Verify we had two persisted settings.
[email protected]e0935cc2012-03-24 14:12:484163 const SettingsMap& settings_map =
[email protected]53bfa31c2011-11-15 19:20:314164 spdy_session_pool->http_server_properties()->GetSpdySettings(
4165 host_port_pair);
[email protected]e0935cc2012-03-24 14:12:484166 ASSERT_EQ(2u, settings_map.size());
[email protected]74188f22010-04-09 20:18:504167
4168 // Verify the first persisted setting.
[email protected]e0935cc2012-03-24 14:12:484169 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4170 EXPECT_TRUE(it1 != settings_map.end());
4171 SettingsFlagsAndValue flags_and_value1 = it1->second;
4172 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4173 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
[email protected]74188f22010-04-09 20:18:504174
4175 // Verify the second persisted setting.
[email protected]e0935cc2012-03-24 14:12:484176 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4177 EXPECT_TRUE(it3 != settings_map.end());
4178 SettingsFlagsAndValue flags_and_value3 = it3->second;
4179 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4180 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
[email protected]74188f22010-04-09 20:18:504181 }
4182}
4183
4184// Test that when there are settings saved that they are sent back to the
4185// server upon session establishment.
[email protected]513963e2013-06-15 01:53:044186TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
bncacac4f8a2015-06-18 12:24:494187 if (spdy_util_.spdy_version() >= HTTP2) {
4188 // HTTP/2 doesn't support settings persistence.
[email protected]745aa9c2014-06-27 02:21:294189 return;
4190 }
[email protected]74188f22010-04-09 20:18:504191 static const SpdyHeaderInfo kSynReplyInfo = {
[email protected]ff98d7f02012-03-22 21:44:194192 SYN_REPLY, // Syn Reply
[email protected]e0935cc2012-03-24 14:12:484193 1, // Stream ID
4194 0, // Associated Stream ID
[email protected]513963e2013-06-15 01:53:044195 ConvertRequestPriorityToSpdyPriority(
4196 LOWEST, spdy_util_.spdy_version()),
[email protected]ff98d7f02012-03-22 21:44:194197 CONTROL_FLAG_NONE, // Control Flags
[email protected]e0935cc2012-03-24 14:12:484198 false, // Compressed
[email protected]5a7bb252013-02-09 00:21:054199 RST_STREAM_INVALID, // Status
[email protected]e0935cc2012-03-24 14:12:484200 NULL, // Data
4201 0, // Data Length
[email protected]ff98d7f02012-03-22 21:44:194202 DATA_FLAG_NONE // Data Flags
[email protected]74188f22010-04-09 20:18:504203 };
[email protected]74188f22010-04-09 20:18:504204
[email protected]c0168822011-12-10 01:24:274205 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364206 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4207 net_log, GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:584208 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504209
[email protected]b40f7fa2013-08-01 16:13:054210 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4211
4212 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4213 pool_peer.SetEnableSendingInitialData(true);
4214
[email protected]74188f22010-04-09 20:18:504215 // Verify that no settings exist initially.
bncce36dca22015-04-21 22:11:234216 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]53bfa31c2011-11-15 19:20:314217 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4218 host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504219
[email protected]c143f2742014-03-31 00:48:544220 const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
[email protected]74188f22010-04-09 20:18:504221 unsigned int kSampleValue1 = 0x0a0a0a0a;
[email protected]c143f2742014-03-31 00:48:544222 const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
[email protected]74188f22010-04-09 20:18:504223 unsigned int kSampleValue2 = 0x0c0c0c0c;
[email protected]74188f22010-04-09 20:18:504224
[email protected]e0935cc2012-03-24 14:12:484225 // First add a persisted setting.
4226 spdy_session_pool->http_server_properties()->SetSpdySetting(
4227 host_port_pair,
4228 kSampleId1,
4229 SETTINGS_FLAG_PLEASE_PERSIST,
4230 kSampleValue1);
4231
4232 // Next add another persisted setting.
4233 spdy_session_pool->http_server_properties()->SetSpdySetting(
4234 host_port_pair,
4235 kSampleId2,
4236 SETTINGS_FLAG_PLEASE_PERSIST,
4237 kSampleValue2);
[email protected]74188f22010-04-09 20:18:504238
[email protected]53bfa31c2011-11-15 19:20:314239 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4240 host_port_pair).size());
[email protected]74188f22010-04-09 20:18:504241
[email protected]b40f7fa2013-08-01 16:13:054242 // Construct the initial SETTINGS frame.
4243 SettingsMap initial_settings;
4244 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4245 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4246 scoped_ptr<SpdyFrame> initial_settings_frame(
4247 spdy_util_.ConstructSpdySettings(initial_settings));
4248
[email protected]b40f7fa2013-08-01 16:13:054249 // Construct the persisted SETTINGS frame.
[email protected]18b28ab2012-04-18 02:14:424250 const SettingsMap& settings =
[email protected]53bfa31c2011-11-15 19:20:314251 spdy_session_pool->http_server_properties()->GetSpdySettings(
4252 host_port_pair);
[email protected]c10b20852013-05-15 21:29:204253 scoped_ptr<SpdyFrame> settings_frame(
4254 spdy_util_.ConstructSpdySettings(settings));
[email protected]74188f22010-04-09 20:18:504255
4256 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:464257 scoped_ptr<SpdyFrame> req(
4258 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]74188f22010-04-09 20:18:504259
rch32320842015-05-16 15:57:094260 MockWrite writes[] = {
4261 CreateMockWrite(*initial_settings_frame, 0),
4262 CreateMockWrite(*settings_frame, 1),
4263 CreateMockWrite(*req, 2),
4264 };
[email protected]74188f22010-04-09 20:18:504265
4266 // Construct the reply.
[email protected]513963e2013-06-15 01:53:044267 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4268 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4269 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]ff98d7f02012-03-22 21:44:194270 scoped_ptr<SpdyFrame> reply(
[email protected]513963e2013-06-15 01:53:044271 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
[email protected]74188f22010-04-09 20:18:504272
[email protected]513963e2013-06-15 01:53:044273 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504274 MockRead reads[] = {
rch32320842015-05-16 15:57:094275 CreateMockRead(*reply, 3),
4276 CreateMockRead(*body, 4),
4277 MockRead(ASYNC, 0, 5) // EOF
[email protected]74188f22010-04-09 20:18:504278 };
4279
rch32320842015-05-16 15:57:094280 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574281 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:584282 helper.RunDefaultTest();
4283 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474284 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504285 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:024286 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]74188f22010-04-09 20:18:504287 EXPECT_EQ("hello!", out.response_data);
4288
4289 {
4290 // Verify we had two persisted settings.
[email protected]e0935cc2012-03-24 14:12:484291 const SettingsMap& settings_map =
[email protected]53bfa31c2011-11-15 19:20:314292 spdy_session_pool->http_server_properties()->GetSpdySettings(
4293 host_port_pair);
[email protected]e0935cc2012-03-24 14:12:484294 ASSERT_EQ(2u, settings_map.size());
[email protected]74188f22010-04-09 20:18:504295
4296 // Verify the first persisted setting.
[email protected]e0935cc2012-03-24 14:12:484297 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4298 EXPECT_TRUE(it1 != settings_map.end());
4299 SettingsFlagsAndValue flags_and_value1 = it1->second;
4300 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4301 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
[email protected]74188f22010-04-09 20:18:504302
4303 // Verify the second persisted setting.
[email protected]e0935cc2012-03-24 14:12:484304 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4305 EXPECT_TRUE(it2 != settings_map.end());
4306 SettingsFlagsAndValue flags_and_value2 = it2->second;
4307 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4308 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
[email protected]74188f22010-04-09 20:18:504309 }
4310}
4311
[email protected]513963e2013-06-15 01:53:044312TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
[email protected]cdf8f7e72013-05-23 10:56:464313 scoped_ptr<SpdyFrame> req(
4314 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524315 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]69d717bd2010-04-21 18:43:214316
[email protected]c10b20852013-05-15 21:29:204317 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:214318 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524319 CreateMockRead(*go_away, 1),
[email protected]58cebf8f2010-07-31 19:20:164320 };
4321
rch08e3aa3e2015-05-16 14:27:524322 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364323 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504324 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574325 helper.AddData(&data);
4326 helper.RunToCompletion(&data);
[email protected]58cebf8f2010-07-31 19:20:164327 TransactionHelperResult out = helper.output();
[email protected]c9336d22010-08-10 00:04:184328 EXPECT_EQ(ERR_ABORTED, out.rv);
[email protected]69d717bd2010-04-21 18:43:214329}
4330
[email protected]513963e2013-06-15 01:53:044331TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
[email protected]cdf8f7e72013-05-23 10:56:464332 scoped_ptr<SpdyFrame> req(
4333 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524334 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]f5ed21552010-05-04 18:39:544335
[email protected]513963e2013-06-15 01:53:044336 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f5ed21552010-05-04 18:39:544337 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524338 CreateMockRead(*resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
[email protected]f5ed21552010-05-04 18:39:544339 };
4340
rch08e3aa3e2015-05-16 14:27:524341 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]f5ed21552010-05-04 18:39:544342 BoundNetLog log;
[email protected]262eec82013-03-19 21:01:364343 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504344 log, GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474345 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574346 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474347 HttpNetworkTransaction* trans = helper.trans();
[email protected]f5ed21552010-05-04 18:39:544348
[email protected]49639fa2011-12-20 23:22:414349 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:474350 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414351 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
[email protected]3caf5542010-07-16 15:19:474352
[email protected]f5ed21552010-05-04 18:39:544353 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4354 out.rv = callback.WaitForResult();
4355 EXPECT_EQ(out.rv, OK);
4356
4357 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504358 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]f5ed21552010-05-04 18:39:544359 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]3caf5542010-07-16 15:19:474360 out.rv = ReadTransaction(trans, &out.response_data);
[email protected]f5ed21552010-05-04 18:39:544361 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4362
4363 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474364 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:544365}
[email protected]58cebf8f2010-07-31 19:20:164366
bnca7f994a2015-01-20 19:39:414367// HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4368TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredError) {
bncacac4f8a2015-06-18 12:24:494369 // HTTP_1_1_REQUIRED is only supported by HTTP/2.
4370 if (spdy_util_.spdy_version() < HTTP2)
bnca7f994a2015-01-20 19:39:414371 return;
4372
4373 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4374 BoundNetLog(), GetParam(), nullptr);
4375
4376 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4377 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4378 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524379 CreateMockRead(*go_away, 0),
bnca7f994a2015-01-20 19:39:414380 };
rch08e3aa3e2015-05-16 14:27:524381 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
bnca7f994a2015-01-20 19:39:414382
4383 helper.RunToCompletion(&data);
4384 TransactionHelperResult out = helper.output();
4385 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED, out.rv);
4386}
4387
bncfacdd852015-01-09 19:22:544388// Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4389// protocol negotiation happens, instead this test forces protocols for both
4390// sockets.
4391TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
bncacac4f8a2015-06-18 12:24:494392 // HTTP_1_1_REQUIRED is only supported by HTTP/2.
4393 if (spdy_util_.spdy_version() < HTTP2)
bncfacdd852015-01-09 19:22:544394 return;
4395 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4396 // only spoken over SSL.
rchebf12982015-04-10 01:15:004397 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
bncfacdd852015-01-09 19:22:544398 return;
4399
4400 HttpRequestInfo request;
4401 request.method = "GET";
bncce36dca22015-04-21 22:11:234402 request.url = GURL("https://www.example.org/");
bncfacdd852015-01-09 19:22:544403 scoped_ptr<SpdySessionDependencies> session_deps(
4404 CreateSpdySessionDependencies(GetParam()));
4405 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:544406 session_deps->next_protos = SpdyNextProtos();
4407 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
rdsmith82957ad2015-09-16 19:42:034408 GetParam(), session_deps.Pass());
bncfacdd852015-01-09 19:22:544409
4410 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
rchebf12982015-04-10 01:15:004411 const char* url = request.url.spec().c_str();
bncfacdd852015-01-09 19:22:544412 scoped_ptr<SpdyHeaderBlock> headers(spdy_util_.ConstructGetHeaderBlock(url));
4413 scoped_ptr<SpdyFrame> req(
4414 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
rch08e3aa3e2015-05-16 14:27:524415 MockWrite writes0[] = {CreateMockWrite(*req, 0)};
bncfacdd852015-01-09 19:22:544416 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4417 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
rch08e3aa3e2015-05-16 14:27:524418 MockRead reads0[] = {CreateMockRead(*go_away, 1)};
4419 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4420 arraysize(writes0));
bncfacdd852015-01-09 19:22:544421
4422 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4423 new SSLSocketDataProvider(ASYNC, OK));
4424 // Expect HTTP/2 protocols too in SSLConfig.
4425 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4426 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
bnc06d22432015-06-29 12:39:434427 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
bncfacdd852015-01-09 19:22:544428 // Force SPDY.
4429 ssl_provider0->SetNextProto(GetParam().protocol);
4430 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4431
4432 // Second socket: falling back to HTTP/1.1.
rch08e3aa3e2015-05-16 14:27:524433 MockWrite writes1[] = {MockWrite(ASYNC, 0,
4434 "GET / HTTP/1.1\r\n"
4435 "Host: www.example.org\r\n"
4436 "Connection: keep-alive\r\n\r\n")};
4437 MockRead reads1[] = {MockRead(ASYNC, 1,
4438 "HTTP/1.1 200 OK\r\n"
4439 "Content-Length: 5\r\n\r\n"
4440 "hello")};
4441 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4442 arraysize(writes1));
bncfacdd852015-01-09 19:22:544443
4444 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4445 new SSLSocketDataProvider(ASYNC, OK));
4446 // Expect only HTTP/1.1 protocol in SSLConfig.
4447 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4448 // Force HTTP/1.1.
4449 ssl_provider1->SetNextProto(kProtoHTTP11);
4450 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4451
4452 base::WeakPtr<HttpServerProperties> http_server_properties =
4453 helper.session()->spdy_session_pool()->http_server_properties();
4454 const HostPortPair host_port_pair = HostPortPair::FromURL(GURL(url));
4455 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair));
4456
4457 helper.RunPreTestSetup();
4458 helper.StartDefaultTest();
4459 helper.FinishDefaultTestWithoutVerification();
4460 helper.VerifyDataConsumed();
4461 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair));
4462
4463 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4464 ASSERT_TRUE(response != nullptr);
4465 ASSERT_TRUE(response->headers.get() != nullptr);
4466 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4467 EXPECT_FALSE(response->was_fetched_via_spdy);
4468 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4469 EXPECT_TRUE(response->was_npn_negotiated);
4470 EXPECT_TRUE(request.url.SchemeIs("https"));
4471 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4472 EXPECT_EQ(443, response->socket_address.port());
4473 std::string response_data;
4474 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4475 EXPECT_EQ("hello", response_data);
4476}
4477
4478// Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4479// proxy. Note that no actual protocol negotiation happens, instead this test
4480// forces protocols for both sockets.
4481TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
bncacac4f8a2015-06-18 12:24:494482 // HTTP_1_1_REQUIRED is only supported by HTTP/2.
4483 if (spdy_util_.spdy_version() < HTTP2)
bncfacdd852015-01-09 19:22:544484 return;
4485 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4486 // only spoken over SSL.
rchebf12982015-04-10 01:15:004487 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
bncfacdd852015-01-09 19:22:544488 return;
4489
4490 HttpRequestInfo request;
4491 request.method = "GET";
bncce36dca22015-04-21 22:11:234492 request.url = GURL("https://www.example.org/");
bncfacdd852015-01-09 19:22:544493 scoped_ptr<SpdySessionDependencies> session_deps(
4494 CreateSpdySessionDependencies(
4495 GetParam(),
4496 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4497 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:544498 session_deps->next_protos = SpdyNextProtos();
4499 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
rdsmith82957ad2015-09-16 19:42:034500 GetParam(), session_deps.Pass());
bncfacdd852015-01-09 19:22:544501
4502 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4503 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234504 nullptr, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
rch08e3aa3e2015-05-16 14:27:524505 MockWrite writes0[] = {CreateMockWrite(*req, 0)};
bncfacdd852015-01-09 19:22:544506 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4507 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
rch08e3aa3e2015-05-16 14:27:524508 MockRead reads0[] = {CreateMockRead(*go_away, 1)};
4509 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4510 arraysize(writes0));
bncfacdd852015-01-09 19:22:544511
4512 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4513 new SSLSocketDataProvider(ASYNC, OK));
4514 // Expect HTTP/2 protocols too in SSLConfig.
4515 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4516 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
bnc06d22432015-06-29 12:39:434517 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
bncfacdd852015-01-09 19:22:544518 // Force SPDY.
4519 ssl_provider0->SetNextProto(GetParam().protocol);
4520 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4521
4522 // Second socket: retry using HTTP/1.1.
4523 MockWrite writes1[] = {
rch08e3aa3e2015-05-16 14:27:524524 MockWrite(ASYNC, 0,
bncce36dca22015-04-21 22:11:234525 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174526 "Host: www.example.org:443\r\n"
bncfacdd852015-01-09 19:22:544527 "Proxy-Connection: keep-alive\r\n\r\n"),
rch08e3aa3e2015-05-16 14:27:524528 MockWrite(ASYNC, 2,
bncfacdd852015-01-09 19:22:544529 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:234530 "Host: www.example.org\r\n"
bncfacdd852015-01-09 19:22:544531 "Connection: keep-alive\r\n\r\n"),
4532 };
4533
4534 MockRead reads1[] = {
rch08e3aa3e2015-05-16 14:27:524535 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4536 MockRead(ASYNC, 3,
bncfacdd852015-01-09 19:22:544537 "HTTP/1.1 200 OK\r\n"
4538 "Content-Length: 5\r\n\r\n"
4539 "hello"),
4540 };
rch08e3aa3e2015-05-16 14:27:524541 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4542 arraysize(writes1));
bncfacdd852015-01-09 19:22:544543
4544 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4545 new SSLSocketDataProvider(ASYNC, OK));
4546 // Expect only HTTP/1.1 protocol in SSLConfig.
4547 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4548 // Force HTTP/1.1.
4549 ssl_provider1->SetNextProto(kProtoHTTP11);
4550 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4551
4552 // A third socket is needed for the tunnelled connection.
4553 scoped_ptr<SSLSocketDataProvider> ssl_provider2(
4554 new SSLSocketDataProvider(ASYNC, OK));
4555 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4556 ssl_provider2.get());
4557
4558 base::WeakPtr<HttpServerProperties> http_server_properties =
4559 helper.session()->spdy_session_pool()->http_server_properties();
4560 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
4561 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4562
4563 helper.RunPreTestSetup();
4564 helper.StartDefaultTest();
4565 helper.FinishDefaultTestWithoutVerification();
4566 helper.VerifyDataConsumed();
4567 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4568
4569 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4570 ASSERT_TRUE(response != nullptr);
4571 ASSERT_TRUE(response->headers.get() != nullptr);
4572 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4573 EXPECT_FALSE(response->was_fetched_via_spdy);
4574 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4575 EXPECT_FALSE(response->was_npn_negotiated);
4576 EXPECT_TRUE(request.url.SchemeIs("https"));
4577 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4578 EXPECT_EQ(70, response->socket_address.port());
4579 std::string response_data;
4580 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4581 EXPECT_EQ("hello", response_data);
4582}
4583
[email protected]b261d0e2010-08-02 19:13:244584// Test to make sure we can correctly connect through a proxy.
[email protected]513963e2013-06-15 01:53:044585TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
[email protected]262eec82013-03-19 21:01:364586 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504587 BoundNetLog(), GetParam(), NULL);
rdsmith82957ad2015-09-16 19:42:034588 helper.session_deps() = CreateSpdySessionDependencies(
4589 GetParam(), ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
mmenkee65e7af2015-10-13 17:16:424590 helper.SetSession(
4591 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get()));
[email protected]b261d0e2010-08-02 19:13:244592 helper.RunPreTestSetup();
4593 HttpNetworkTransaction* trans = helper.trans();
4594
rchebf12982015-04-10 01:15:004595 const char kConnect443[] = {
bncce36dca22015-04-21 22:11:234596 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174597 "Host: www.example.org:443\r\n"
rchcb934f562015-04-07 16:25:124598 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244599 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
[email protected]cdf8f7e72013-05-23 10:56:464600 scoped_ptr<SpdyFrame> req(
4601 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:044602 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4603 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244604
rchebf12982015-04-10 01:15:004605 MockWrite writes[] = {
4606 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4607 CreateMockWrite(*req, 2),
[email protected]b261d0e2010-08-02 19:13:244608 };
rchebf12982015-04-10 01:15:004609 MockRead reads[] = {
4610 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4611 CreateMockRead(*resp, 3),
4612 CreateMockRead(*body.get(), 4),
4613 MockRead(ASYNC, 0, 0, 5),
[email protected]b261d0e2010-08-02 19:13:244614 };
rch08e3aa3e2015-05-16 14:27:524615 scoped_ptr<SequencedSocketData> data(new SequencedSocketData(
rchebf12982015-04-10 01:15:004616 reads, arraysize(reads), writes, arraysize(writes)));
[email protected]b261d0e2010-08-02 19:13:244617
4618 helper.AddData(data.get());
[email protected]49639fa2011-12-20 23:22:414619 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244620
[email protected]49639fa2011-12-20 23:22:414621 int rv = trans->Start(
4622 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244623 EXPECT_EQ(ERR_IO_PENDING, rv);
4624
4625 rv = callback.WaitForResult();
4626 EXPECT_EQ(0, rv);
4627
4628 // Verify the SYN_REPLY.
4629 HttpResponseInfo response = *trans->GetResponseInfo();
rsleevidb16bb02015-11-12 23:47:174630 ASSERT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024631 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:244632
4633 std::string response_data;
4634 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4635 EXPECT_EQ("hello!", response_data);
4636 helper.VerifyDataConsumed();
4637}
4638
bncce36dca22015-04-21 22:11:234639// Test to make sure we can correctly connect through a proxy to
4640// www.example.org, if there already exists a direct spdy connection to
4641// www.example.org. See https://crbug.com/49874.
[email protected]513963e2013-06-15 01:53:044642TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
[email protected]b261d0e2010-08-02 19:13:244643 // When setting up the first transaction, we store the SpdySessionPool so that
4644 // we can use the same pool in the second transaction.
[email protected]262eec82013-03-19 21:01:364645 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504646 BoundNetLog(), GetParam(), NULL);
[email protected]733b7a6d2010-08-25 01:38:434647
4648 // Use a proxy service which returns a proxy fallback list from DIRECT to
4649 // myproxy:70. For this test there will be no fallback, so it is equivalent
4650 // to simply DIRECT. The reason for appending the second proxy is to verify
4651 // that the session pool key used does is just "DIRECT".
rdsmith82957ad2015-09-16 19:42:034652 helper.session_deps() = CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:044653 GetParam(),
rdsmith82957ad2015-09-16 19:42:034654 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70"));
mmenkee65e7af2015-10-13 17:16:424655 helper.SetSession(
4656 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get()));
[email protected]733b7a6d2010-08-25 01:38:434657
[email protected]87bfa3f2010-09-30 14:54:564658 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:244659 helper.RunPreTestSetup();
4660
4661 // Construct and send a simple GET request.
[email protected]cdf8f7e72013-05-23 10:56:464662 scoped_ptr<SpdyFrame> req(
4663 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b261d0e2010-08-02 19:13:244664 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:524665 CreateMockWrite(*req, 0),
[email protected]b261d0e2010-08-02 19:13:244666 };
4667
[email protected]513963e2013-06-15 01:53:044668 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4669 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244670 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524671 CreateMockRead(*resp, 1),
4672 CreateMockRead(*body, 2),
4673 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3), // Force a pause
[email protected]b261d0e2010-08-02 19:13:244674 };
rch08e3aa3e2015-05-16 14:27:524675 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574676 helper.AddData(&data);
[email protected]b261d0e2010-08-02 19:13:244677 HttpNetworkTransaction* trans = helper.trans();
4678
[email protected]49639fa2011-12-20 23:22:414679 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244680 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414681 out.rv = trans->Start(
4682 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244683
4684 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4685 out.rv = callback.WaitForResult();
4686 EXPECT_EQ(out.rv, OK);
4687
4688 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504689 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244690 EXPECT_TRUE(response->was_fetched_via_spdy);
4691 out.rv = ReadTransaction(trans, &out.response_data);
4692 EXPECT_EQ(OK, out.rv);
4693 out.status_line = response->headers->GetStatusLine();
bnc84e7fb52015-12-02 11:50:024694 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]b261d0e2010-08-02 19:13:244695 EXPECT_EQ("hello!", out.response_data);
4696
4697 // Check that the SpdySession is still in the SpdySessionPool.
bncce36dca22015-04-21 22:11:234698 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]e6d017652013-05-17 18:01:404699 SpdySessionKey session_pool_key_direct(
[email protected]314b03992014-04-01 01:28:534700 host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264701 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
[email protected]e6d017652013-05-17 18:01:404702 SpdySessionKey session_pool_key_proxy(
[email protected]31e68d72010-08-25 06:36:584703 host_port_pair,
[email protected]e6d017652013-05-17 18:01:404704 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
[email protected]314b03992014-04-01 01:28:534705 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264706 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:244707
rdsmithebb50aa2015-11-12 03:44:384708 // New SpdyTestUtil instance for the session that will be used for the
4709 // proxy connection.
4710 SpdyTestUtil spdy_util_2(GetParam().protocol,
4711 GetParam().priority_to_dependency);
4712
[email protected]b261d0e2010-08-02 19:13:244713 // Set up data for the proxy connection.
bncce36dca22015-04-21 22:11:234714 const char kConnect443[] = {
4715 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174716 "Host: www.example.org:443\r\n"
bncce36dca22015-04-21 22:11:234717 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244718 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
rdsmithebb50aa2015-11-12 03:44:384719 scoped_ptr<SpdyFrame> req2(spdy_util_2.ConstructSpdyGet(
rchebf12982015-04-10 01:15:004720 GetDefaultUrlWithPath("/foo.dat").c_str(), false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:384721 scoped_ptr<SpdyFrame> resp2(spdy_util_2.ConstructSpdyGetSynReply(NULL, 0, 1));
4722 scoped_ptr<SpdyFrame> body2(spdy_util_2.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244723
rchebf12982015-04-10 01:15:004724 MockWrite writes2[] = {
4725 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4726 CreateMockWrite(*req2, 2),
[email protected]b261d0e2010-08-02 19:13:244727 };
rchebf12982015-04-10 01:15:004728 MockRead reads2[] = {
4729 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4730 CreateMockRead(*resp2, 3),
4731 CreateMockRead(*body2, 4),
4732 MockRead(ASYNC, 0, 5) // EOF
[email protected]b261d0e2010-08-02 19:13:244733 };
4734
rch08e3aa3e2015-05-16 14:27:524735 scoped_ptr<SequencedSocketData> data_proxy(new SequencedSocketData(
rchebf12982015-04-10 01:15:004736 reads2, arraysize(reads2), writes2, arraysize(writes2)));
[email protected]b261d0e2010-08-02 19:13:244737
bncce36dca22015-04-21 22:11:234738 // Create another request to www.example.org, but this time through a proxy.
[email protected]b261d0e2010-08-02 19:13:244739 HttpRequestInfo request_proxy;
4740 request_proxy.method = "GET";
rchebf12982015-04-10 01:15:004741 request_proxy.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
[email protected]b261d0e2010-08-02 19:13:244742 request_proxy.load_flags = 0;
[email protected]bb88e1d32013-05-03 23:11:074743 scoped_ptr<SpdySessionDependencies> ssd_proxy(
[email protected]513963e2013-06-15 01:53:044744 CreateSpdySessionDependencies(GetParam()));
[email protected]b261d0e2010-08-02 19:13:244745 // Ensure that this transaction uses the same SpdySessionPool.
mmenkee65e7af2015-10-13 17:16:424746 scoped_ptr<HttpNetworkSession> session_proxy(
[email protected]ad8e04a2010-11-01 04:16:274747 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
[email protected]262eec82013-03-19 21:01:364748 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504749 BoundNetLog(), GetParam(), NULL);
mmenkee65e7af2015-10-13 17:16:424750 HttpNetworkSessionPeer session_peer(session_proxy.get());
bnc301745a2015-03-10 03:22:164751 scoped_ptr<ProxyService> proxy_service(
4752 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
[email protected]6104ea5d2011-04-27 21:37:124753 session_peer.SetProxyService(proxy_service.get());
[email protected]b261d0e2010-08-02 19:13:244754 helper_proxy.session_deps().swap(ssd_proxy);
mmenkee65e7af2015-10-13 17:16:424755 helper_proxy.SetSession(session_proxy.Pass());
[email protected]b261d0e2010-08-02 19:13:244756 helper_proxy.RunPreTestSetup();
4757 helper_proxy.AddData(data_proxy.get());
4758
4759 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
[email protected]49639fa2011-12-20 23:22:414760 TestCompletionCallback callback_proxy;
4761 int rv = trans_proxy->Start(
4762 &request_proxy, callback_proxy.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244763 EXPECT_EQ(ERR_IO_PENDING, rv);
4764 rv = callback_proxy.WaitForResult();
4765 EXPECT_EQ(0, rv);
4766
4767 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
rsleevidb16bb02015-11-12 23:47:174768 ASSERT_TRUE(response_proxy.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024769 EXPECT_EQ("HTTP/1.1 200", response_proxy.headers->GetStatusLine());
[email protected]b261d0e2010-08-02 19:13:244770
4771 std::string response_data;
4772 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4773 EXPECT_EQ("hello!", response_data);
4774
[email protected]b261d0e2010-08-02 19:13:244775 helper_proxy.VerifyDataConsumed();
4776}
4777
[email protected]58cebf8f2010-07-31 19:20:164778// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4779// on a new connection, if the connection was previously known to be good.
4780// This can happen when a server reboots without saying goodbye, or when
4781// we're behind a NAT that masked the RST.
[email protected]513963e2013-06-15 01:53:044782TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
[email protected]513963e2013-06-15 01:53:044783 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4784 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]58cebf8f2010-07-31 19:20:164785 MockRead reads[] = {
rch32320842015-05-16 15:57:094786 CreateMockRead(*resp, 1),
4787 CreateMockRead(*body, 2),
4788 MockRead(ASYNC, ERR_IO_PENDING, 3),
4789 MockRead(ASYNC, ERR_CONNECTION_RESET, 4),
[email protected]58cebf8f2010-07-31 19:20:164790 };
4791
4792 MockRead reads2[] = {
rch32320842015-05-16 15:57:094793 CreateMockRead(*resp, 1),
4794 CreateMockRead(*body, 2),
4795 MockRead(ASYNC, 0, 3) // EOF
[email protected]58cebf8f2010-07-31 19:20:164796 };
4797
rchacdcbdc2015-05-16 17:16:004798 scoped_ptr<SpdyFrame> req(
4799 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:384800 // In all cases the connection will be reset before req3 can be
4801 // dispatched, destroying both streams.
4802 spdy_util_.UpdateWithStreamDestruction(1);
rchacdcbdc2015-05-16 17:16:004803 scoped_ptr<SpdyFrame> req3(
4804 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
4805 MockWrite writes1[] = {CreateMockWrite(*req, 0), CreateMockWrite(*req3, 5)};
4806 MockWrite writes2[] = {CreateMockWrite(*req, 0)};
4807
[email protected]58cebf8f2010-07-31 19:20:164808 // This test has a couple of variants.
4809 enum {
4810 // Induce the RST while waiting for our transaction to send.
rchacdcbdc2015-05-16 17:16:004811 VARIANT_RST_DURING_SEND_COMPLETION = 0,
[email protected]58cebf8f2010-07-31 19:20:164812 // Induce the RST while waiting for our transaction to read.
4813 // In this case, the send completed - everything copied into the SNDBUF.
rchacdcbdc2015-05-16 17:16:004814 VARIANT_RST_DURING_READ_COMPLETION = 1
[email protected]58cebf8f2010-07-31 19:20:164815 };
4816
4817 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4818 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4819 ++variant) {
rchacdcbdc2015-05-16 17:16:004820 SequencedSocketData data1(reads, arraysize(reads), writes1, 1 + variant);
[email protected]58cebf8f2010-07-31 19:20:164821
rchacdcbdc2015-05-16 17:16:004822 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
4823 arraysize(writes2));
[email protected]58cebf8f2010-07-31 19:20:164824
[email protected]262eec82013-03-19 21:01:364825 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504826 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574827 helper.AddData(&data1);
4828 helper.AddData(&data2);
[email protected]58cebf8f2010-07-31 19:20:164829 helper.RunPreTestSetup();
4830
4831 for (int i = 0; i < 2; ++i) {
4832 scoped_ptr<HttpNetworkTransaction> trans(
mmenkee65e7af2015-10-13 17:16:424833 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]58cebf8f2010-07-31 19:20:164834
[email protected]49639fa2011-12-20 23:22:414835 TestCompletionCallback callback;
4836 int rv = trans->Start(
4837 &helper.request(), callback.callback(), BoundNetLog());
[email protected]58cebf8f2010-07-31 19:20:164838 EXPECT_EQ(ERR_IO_PENDING, rv);
4839 // On the second transaction, we trigger the RST.
4840 if (i == 1) {
4841 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4842 // Writes to the socket complete asynchronously on SPDY by running
4843 // through the message loop. Complete the write here.
[email protected]fc9d88472013-08-14 02:31:174844 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164845 }
4846
4847 // Now schedule the ERR_CONNECTION_RESET.
[email protected]dd54bd82012-07-19 23:44:574848 data1.CompleteRead();
[email protected]58cebf8f2010-07-31 19:20:164849 }
4850 rv = callback.WaitForResult();
4851 EXPECT_EQ(OK, rv);
4852
4853 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]351ab642010-08-05 16:55:314854 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504855 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]58cebf8f2010-07-31 19:20:164856 EXPECT_TRUE(response->was_fetched_via_spdy);
4857 std::string response_data;
4858 rv = ReadTransaction(trans.get(), &response_data);
4859 EXPECT_EQ(OK, rv);
bnc84e7fb52015-12-02 11:50:024860 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]58cebf8f2010-07-31 19:20:164861 EXPECT_EQ("hello!", response_data);
rchacdcbdc2015-05-16 17:16:004862 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164863 }
4864
4865 helper.VerifyDataConsumed();
rchacdcbdc2015-05-16 17:16:004866 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164867 }
4868}
[email protected]1f418ee2010-10-16 19:46:564869
4870// Test that turning SPDY on and off works properly.
[email protected]513963e2013-06-15 01:53:044871TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
[email protected]d7599122014-05-24 03:37:234872 HttpStreamFactory::set_spdy_enabled(true);
[email protected]cdf8f7e72013-05-23 10:56:464873 scoped_ptr<SpdyFrame> req(
4874 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524875 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]1f418ee2010-10-16 19:46:564876
[email protected]513963e2013-06-15 01:53:044877 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4878 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1f418ee2010-10-16 19:46:564879 MockRead spdy_reads[] = {
rch08e3aa3e2015-05-16 14:27:524880 CreateMockRead(*resp, 1),
4881 CreateMockRead(*body, 2),
4882 MockRead(ASYNC, 0, 3) // EOF
[email protected]1f418ee2010-10-16 19:46:564883 };
4884
rch08e3aa3e2015-05-16 14:27:524885 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4886 arraysize(spdy_writes));
[email protected]262eec82013-03-19 21:01:364887 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504888 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574889 helper.RunToCompletion(&data);
[email protected]1f418ee2010-10-16 19:46:564890 TransactionHelperResult out = helper.output();
4891 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:024892 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]1f418ee2010-10-16 19:46:564893 EXPECT_EQ("hello!", out.response_data);
4894
bnc301745a2015-03-10 03:22:164895 HttpStreamFactory::set_spdy_enabled(false);
rch08e3aa3e2015-05-16 14:27:524896 MockWrite http_writes[] = {
4897 MockWrite(SYNCHRONOUS, 0,
4898 "GET / HTTP/1.1\r\n"
4899 "Host: www.example.org\r\n"
4900 "Connection: keep-alive\r\n\r\n"),
rch73e17422015-05-04 19:52:064901 };
rch08e3aa3e2015-05-16 14:27:524902
4903 MockRead http_reads[] = {
4904 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4905 MockRead(SYNCHRONOUS, 2, "hello from http"),
4906 MockRead(SYNCHRONOUS, OK, 3),
4907 };
4908 SequencedSocketData data2(http_reads, arraysize(http_reads), http_writes,
4909 arraysize(http_writes));
[email protected]262eec82013-03-19 21:01:364910 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504911 BoundNetLog(), GetParam(), NULL);
[email protected]1f418ee2010-10-16 19:46:564912 helper2.SetSpdyDisabled();
[email protected]dd54bd82012-07-19 23:44:574913 helper2.RunToCompletion(&data2);
[email protected]1f418ee2010-10-16 19:46:564914 TransactionHelperResult out2 = helper2.output();
4915 EXPECT_EQ(OK, out2.rv);
4916 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4917 EXPECT_EQ("hello from http", out2.response_data);
4918
bnc301745a2015-03-10 03:22:164919 HttpStreamFactory::set_spdy_enabled(true);
[email protected]1f418ee2010-10-16 19:46:564920}
[email protected]018aabc2010-10-29 16:16:594921
4922// Tests that Basic authentication works over SPDY
[email protected]513963e2013-06-15 01:53:044923TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
bnc301745a2015-03-10 03:22:164924 HttpStreamFactory::set_spdy_enabled(true);
[email protected]018aabc2010-10-29 16:16:594925
4926 // The first request will be a bare GET, the second request will be a
4927 // GET with an Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194928 scoped_ptr<SpdyFrame> req_get(
[email protected]cdf8f7e72013-05-23 10:56:464929 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:384930 // Will be refused for lack of auth.
4931 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]018aabc2010-10-29 16:16:594932 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464933 "authorization", "Basic Zm9vOmJhcg=="
[email protected]018aabc2010-10-29 16:16:594934 };
[email protected]ff98d7f02012-03-22 21:44:194935 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464936 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4937 arraysize(kExtraAuthorizationHeaders) / 2,
4938 false, 3, LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594939 MockWrite spdy_writes[] = {
rch08e3aa3e2015-05-16 14:27:524940 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
[email protected]018aabc2010-10-29 16:16:594941 };
4942
4943 // The first response is a 401 authentication challenge, and the second
4944 // response will be a 200 response since the second request includes a valid
4945 // Authorization header.
4946 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:264947 "www-authenticate",
[email protected]018aabc2010-10-29 16:16:594948 "Basic realm=\"MyRealm\""
4949 };
[email protected]ff98d7f02012-03-22 21:44:194950 scoped_ptr<SpdyFrame> resp_authentication(
[email protected]513963e2013-06-15 01:53:044951 spdy_util_.ConstructSpdySynReplyError(
[email protected]018aabc2010-10-29 16:16:594952 "401 Authentication Required",
[email protected]d08358502010-12-03 22:04:034953 kExtraAuthenticationHeaders,
4954 arraysize(kExtraAuthenticationHeaders) / 2,
[email protected]018aabc2010-10-29 16:16:594955 1));
[email protected]ff98d7f02012-03-22 21:44:194956 scoped_ptr<SpdyFrame> body_authentication(
[email protected]513963e2013-06-15 01:53:044957 spdy_util_.ConstructSpdyBodyFrame(1, true));
4958 scoped_ptr<SpdyFrame> resp_data(
4959 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4960 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]018aabc2010-10-29 16:16:594961 MockRead spdy_reads[] = {
rch08e3aa3e2015-05-16 14:27:524962 CreateMockRead(*resp_authentication, 1),
4963 CreateMockRead(*body_authentication, 2),
4964 CreateMockRead(*resp_data, 4),
4965 CreateMockRead(*body_data, 5),
4966 MockRead(ASYNC, 0, 6),
[email protected]018aabc2010-10-29 16:16:594967 };
4968
rch08e3aa3e2015-05-16 14:27:524969 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4970 arraysize(spdy_writes));
[email protected]018aabc2010-10-29 16:16:594971 HttpRequestInfo request(CreateGetRequest());
4972 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364973 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
4974 net_log, GetParam(), NULL);
[email protected]018aabc2010-10-29 16:16:594975
4976 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574977 helper.AddData(&data);
[email protected]018aabc2010-10-29 16:16:594978 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:414979 TestCompletionCallback callback;
4980 const int rv_start = trans->Start(&request, callback.callback(), net_log);
[email protected]018aabc2010-10-29 16:16:594981 EXPECT_EQ(ERR_IO_PENDING, rv_start);
[email protected]49639fa2011-12-20 23:22:414982 const int rv_start_complete = callback.WaitForResult();
[email protected]018aabc2010-10-29 16:16:594983 EXPECT_EQ(OK, rv_start_complete);
4984
4985 // Make sure the response has an auth challenge.
4986 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4987 ASSERT_TRUE(response_start != NULL);
[email protected]90499482013-06-01 00:39:504988 ASSERT_TRUE(response_start->headers.get() != NULL);
[email protected]018aabc2010-10-29 16:16:594989 EXPECT_EQ(401, response_start->headers->response_code());
4990 EXPECT_TRUE(response_start->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044991 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
4992 ASSERT_TRUE(auth_challenge != NULL);
4993 EXPECT_FALSE(auth_challenge->is_proxy);
aberentbba302d2015-12-03 10:20:194994 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:044995 EXPECT_EQ("MyRealm", auth_challenge->realm);
[email protected]018aabc2010-10-29 16:16:594996
4997 // Restart with a username/password.
[email protected]ad65a3e2013-12-25 18:18:014998 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
4999 base::ASCIIToUTF16("bar"));
[email protected]49639fa2011-12-20 23:22:415000 TestCompletionCallback callback_restart;
5001 const int rv_restart = trans->RestartWithAuth(
5002 credentials, callback_restart.callback());
[email protected]018aabc2010-10-29 16:16:595003 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
5004 const int rv_restart_complete = callback_restart.WaitForResult();
5005 EXPECT_EQ(OK, rv_restart_complete);
5006 // TODO(cbentzel): This is actually the same response object as before, but
5007 // data has changed.
5008 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5009 ASSERT_TRUE(response_restart != NULL);
[email protected]90499482013-06-01 00:39:505010 ASSERT_TRUE(response_restart->headers.get() != NULL);
[email protected]018aabc2010-10-29 16:16:595011 EXPECT_EQ(200, response_restart->headers->response_code());
5012 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
5013}
5014
[email protected]513963e2013-06-15 01:53:045015TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:465016 scoped_ptr<SpdyFrame> stream1_syn(
5017 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045018 scoped_ptr<SpdyFrame> stream1_body(
5019 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035020 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525021 CreateMockWrite(*stream1_syn, 0),
[email protected]d08358502010-12-03 22:04:035022 };
5023
[email protected]513963e2013-06-15 01:53:045024 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005025 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5026 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235027 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565028 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045029
5030 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
[email protected]513963e2013-06-15 01:53:045031 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5032 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
bnc7ecc1122015-09-28 13:22:495033 (*late_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235034 scoped_ptr<SpdyFrame> stream2_headers(
[email protected]513963e2013-06-15 01:53:045035 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235036 false,
5037 2,
5038 LOWEST,
5039 HEADERS,
5040 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235041 0));
[email protected]d08358502010-12-03 22:04:035042
[email protected]ff98d7f02012-03-22 21:44:195043 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045044 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435045 const char kPushedData[] = "pushed";
5046 scoped_ptr<SpdyFrame> stream2_body(
5047 spdy_util_.ConstructSpdyBodyFrame(
5048 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035049 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525050 CreateMockRead(*stream1_reply, 1),
5051 CreateMockRead(*stream2_syn, 2),
5052 CreateMockRead(*stream2_headers, 3),
5053 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
5054 CreateMockRead(*stream2_body, 5),
5055 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]d08358502010-12-03 22:04:035056 };
5057
5058 HttpResponseInfo response;
5059 HttpResponseInfo response2;
5060 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:525061 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:575062 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:035063 &response,
5064 &response2,
5065 expected_push_result);
5066
5067 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505068 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025069 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:035070
5071 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505072 EXPECT_TRUE(response2.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025073 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:035074}
5075
[email protected]513963e2013-06-15 01:53:045076TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
[email protected]d08358502010-12-03 22:04:035077 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465078 scoped_ptr<SpdyFrame> stream1_syn(
5079 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045080 scoped_ptr<SpdyFrame> stream1_body(
5081 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035082 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:065083 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:035084 };
5085
[email protected]513963e2013-06-15 01:53:045086 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005087 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5088 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235089 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565090 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045091
5092 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
[email protected]513963e2013-06-15 01:53:045093 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5094 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
bnc7ecc1122015-09-28 13:22:495095 (*late_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235096 scoped_ptr<SpdyFrame> stream2_headers(
[email protected]513963e2013-06-15 01:53:045097 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235098 false,
5099 2,
5100 LOWEST,
5101 HEADERS,
5102 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235103 0));
[email protected]d08358502010-12-03 22:04:035104
[email protected]ff98d7f02012-03-22 21:44:195105 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045106 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435107 const char kPushedData[] = "pushed";
5108 scoped_ptr<SpdyFrame> stream2_body(
5109 spdy_util_.ConstructSpdyBodyFrame(
5110 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035111 MockRead reads[] = {
5112 CreateMockRead(*stream1_reply, 1),
5113 CreateMockRead(*stream2_syn, 2),
5114 CreateMockRead(*stream1_body, 3),
5115 CreateMockRead(*stream2_headers, 4),
[email protected]8a0fc822013-06-27 20:52:435116 CreateMockRead(*stream2_body, 5),
[email protected]d55b30a2012-07-21 00:35:395117 MockRead(ASYNC, 0, 6), // EOF
[email protected]d08358502010-12-03 22:04:035118 };
5119
5120 HttpResponseInfo response;
5121 HttpResponseInfo response2;
5122 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:575123 DeterministicSocketData data(reads, arraysize(reads),
5124 writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:035125
[email protected]262eec82013-03-19 21:01:365126 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505127 BoundNetLog(), GetParam(), NULL);
[email protected]d08358502010-12-03 22:04:035128 helper.SetDeterministic();
[email protected]dd54bd82012-07-19 23:44:575129 helper.AddDeterministicData(&data);
[email protected]d08358502010-12-03 22:04:035130 helper.RunPreTestSetup();
5131
5132 HttpNetworkTransaction* trans = helper.trans();
5133
5134 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5135 // and the body of the primary stream, but before we've received the HEADERS
5136 // for the pushed stream.
[email protected]dd54bd82012-07-19 23:44:575137 data.SetStop(3);
[email protected]d08358502010-12-03 22:04:035138
5139 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:415140 TestCompletionCallback callback;
5141 int rv = trans->Start(
5142 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035143 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575144 data.Run();
[email protected]d08358502010-12-03 22:04:035145 rv = callback.WaitForResult();
5146 EXPECT_EQ(0, rv);
5147
5148 // Request the pushed path. At this point, we've received the push, but the
5149 // headers are not yet complete.
5150 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:425151 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]49639fa2011-12-20 23:22:415152 rv = trans2->Start(
5153 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035154 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575155 data.RunFor(3);
[email protected]fc9d88472013-08-14 02:31:175156 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:035157
5158 // Read the server push body.
5159 std::string result2;
rch0aecfd82015-05-19 17:22:325160 ReadResult(trans2.get(), &result2);
[email protected]d08358502010-12-03 22:04:035161 // Read the response body.
5162 std::string result;
rch0aecfd82015-05-19 17:22:325163 ReadResult(trans, &result);
[email protected]d08358502010-12-03 22:04:035164
[email protected]d08358502010-12-03 22:04:035165 // Verify that the received push data is same as the expected push data.
5166 EXPECT_EQ(result2.compare(expected_push_result), 0)
5167 << "Received data: "
5168 << result2
5169 << "||||| Expected data: "
5170 << expected_push_result;
5171
5172 // Verify the SYN_REPLY.
5173 // Copy the response info, because trans goes away.
5174 response = *trans->GetResponseInfo();
5175 response2 = *trans2->GetResponseInfo();
5176
5177 VerifyStreamsClosed(helper);
5178
5179 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505180 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025181 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:035182
5183 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505184 EXPECT_TRUE(response2.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025185 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d55b30a2012-07-21 00:35:395186
5187 // Read the final EOF (which will close the session)
5188 data.RunFor(1);
5189
5190 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:175191 EXPECT_TRUE(data.AllReadDataConsumed());
5192 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:035193}
5194
[email protected]6cd63ba2014-06-12 16:14:565195// TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
[email protected]513963e2013-06-15 01:53:045196TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
[email protected]d08358502010-12-03 22:04:035197 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465198 scoped_ptr<SpdyFrame> stream1_syn(
5199 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045200 scoped_ptr<SpdyFrame> stream1_body(
5201 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035202 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:065203 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:035204 };
5205
[email protected]513963e2013-06-15 01:53:045206 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
bncacac4f8a2015-06-18 12:24:495207 if (spdy_util_.spdy_version() < HTTP2) {
5208 // In HTTP/2 PUSH_PROMISE headers won't show up in the response headers.
[email protected]0338bc62014-06-20 17:09:565209 (*initial_headers)["alpha"] = "beta";
5210 }
rchebf12982015-04-10 01:15:005211 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5212 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235213 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565214 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045215
5216 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5217 (*middle_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235218 scoped_ptr<SpdyFrame> stream2_headers1(
[email protected]513963e2013-06-15 01:53:045219 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235220 false,
5221 2,
5222 LOWEST,
5223 HEADERS,
5224 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235225 0));
[email protected]513963e2013-06-15 01:53:045226
5227 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5228 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
bncacac4f8a2015-06-18 12:24:495229 if (spdy_util_.spdy_version() < HTTP2) {
5230 // HTTP/2 eliminates use of the :version header.
[email protected]601e03f12014-04-06 16:26:395231 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5232 }
[email protected]4bd46222013-05-14 19:32:235233 scoped_ptr<SpdyFrame> stream2_headers2(
[email protected]513963e2013-06-15 01:53:045234 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235235 false,
5236 2,
5237 LOWEST,
5238 HEADERS,
5239 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235240 0));
[email protected]d08358502010-12-03 22:04:035241
[email protected]ff98d7f02012-03-22 21:44:195242 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045243 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435244 const char kPushedData[] = "pushed";
5245 scoped_ptr<SpdyFrame> stream2_body(
5246 spdy_util_.ConstructSpdyBodyFrame(
5247 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035248 MockRead reads[] = {
5249 CreateMockRead(*stream1_reply, 1),
5250 CreateMockRead(*stream2_syn, 2),
5251 CreateMockRead(*stream1_body, 3),
5252 CreateMockRead(*stream2_headers1, 4),
5253 CreateMockRead(*stream2_headers2, 5),
[email protected]8a0fc822013-06-27 20:52:435254 CreateMockRead(*stream2_body, 6),
[email protected]d55b30a2012-07-21 00:35:395255 MockRead(ASYNC, 0, 7), // EOF
[email protected]d08358502010-12-03 22:04:035256 };
5257
5258 HttpResponseInfo response;
5259 HttpResponseInfo response2;
5260 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:575261 DeterministicSocketData data(reads, arraysize(reads),
5262 writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:035263
[email protected]262eec82013-03-19 21:01:365264 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505265 BoundNetLog(), GetParam(), NULL);
[email protected]d08358502010-12-03 22:04:035266 helper.SetDeterministic();
[email protected]dd54bd82012-07-19 23:44:575267 helper.AddDeterministicData(&data);
[email protected]d08358502010-12-03 22:04:035268 helper.RunPreTestSetup();
5269
5270 HttpNetworkTransaction* trans = helper.trans();
5271
5272 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5273 // the first HEADERS frame, and the body of the primary stream, but before
5274 // we've received the final HEADERS for the pushed stream.
[email protected]dd54bd82012-07-19 23:44:575275 data.SetStop(4);
[email protected]d08358502010-12-03 22:04:035276
5277 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:415278 TestCompletionCallback callback;
5279 int rv = trans->Start(
5280 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035281 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575282 data.Run();
[email protected]d08358502010-12-03 22:04:035283 rv = callback.WaitForResult();
5284 EXPECT_EQ(0, rv);
5285
5286 // Request the pushed path. At this point, we've received the push, but the
5287 // headers are not yet complete.
5288 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:425289 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]49639fa2011-12-20 23:22:415290 rv = trans2->Start(
5291 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035292 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575293 data.RunFor(3);
[email protected]fc9d88472013-08-14 02:31:175294 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:035295
5296 // Read the server push body.
5297 std::string result2;
rch0aecfd82015-05-19 17:22:325298 ReadResult(trans2.get(), &result2);
[email protected]d08358502010-12-03 22:04:035299 // Read the response body.
5300 std::string result;
rch0aecfd82015-05-19 17:22:325301 ReadResult(trans, &result);
[email protected]d08358502010-12-03 22:04:035302
[email protected]d08358502010-12-03 22:04:035303 // Verify that the received push data is same as the expected push data.
[email protected]6d116e1a2013-06-24 07:42:155304 EXPECT_EQ(expected_push_result, result2);
[email protected]d08358502010-12-03 22:04:035305
5306 // Verify the SYN_REPLY.
5307 // Copy the response info, because trans goes away.
5308 response = *trans->GetResponseInfo();
5309 response2 = *trans2->GetResponseInfo();
5310
5311 VerifyStreamsClosed(helper);
5312
5313 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505314 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025315 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:035316
5317 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505318 EXPECT_TRUE(response2.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025319 EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
[email protected]d08358502010-12-03 22:04:035320
[email protected]6cd63ba2014-06-12 16:14:565321 // Verify we got all the headers from all header blocks.
bncacac4f8a2015-06-18 12:24:495322 if (spdy_util_.spdy_version() < HTTP2)
[email protected]0338bc62014-06-20 17:09:565323 EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
[email protected]d08358502010-12-03 22:04:035324 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5325 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
[email protected]d55b30a2012-07-21 00:35:395326
5327 // Read the final EOF (which will close the session)
5328 data.RunFor(1);
5329
5330 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:175331 EXPECT_TRUE(data.AllReadDataConsumed());
5332 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:035333}
5334
[email protected]513963e2013-06-15 01:53:045335TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
[email protected]5c6908e2012-08-06 18:53:475336 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465337 scoped_ptr<SpdyFrame> stream1_syn(
5338 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045339 scoped_ptr<SpdyFrame> stream1_body(
5340 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]5c6908e2012-08-06 18:53:475341 MockWrite writes[] = {
5342 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5343 };
5344
[email protected]513963e2013-06-15 01:53:045345 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005346 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5347 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235348 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565349 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045350
5351 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5352 (*middle_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235353 scoped_ptr<SpdyFrame> stream2_headers1(
[email protected]513963e2013-06-15 01:53:045354 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235355 false,
5356 2,
5357 LOWEST,
5358 HEADERS,
5359 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235360 0));
[email protected]5c6908e2012-08-06 18:53:475361
5362 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045363 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435364 const char kPushedData[] = "pushed";
5365 scoped_ptr<SpdyFrame> stream2_body(
5366 spdy_util_.ConstructSpdyBodyFrame(
5367 2, kPushedData, strlen(kPushedData), true));
[email protected]5c6908e2012-08-06 18:53:475368 MockRead reads[] = {
5369 CreateMockRead(*stream1_reply, 1),
5370 CreateMockRead(*stream2_syn, 2),
5371 CreateMockRead(*stream1_body, 3),
5372 CreateMockRead(*stream2_headers1, 4),
[email protected]8a0fc822013-06-27 20:52:435373 CreateMockRead(*stream2_body, 5),
[email protected]5c6908e2012-08-06 18:53:475374 MockRead(ASYNC, 0, 6), // EOF
5375 };
5376
5377 DeterministicSocketData data(reads, arraysize(reads),
5378 writes, arraysize(writes));
5379
[email protected]262eec82013-03-19 21:01:365380 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]5c6908e2012-08-06 18:53:475381 BoundNetLog(), GetParam(), NULL);
5382 helper.SetDeterministic();
5383 helper.AddDeterministicData(&data);
5384 helper.RunPreTestSetup();
5385
5386 HttpNetworkTransaction* trans = helper.trans();
5387
5388 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5389 // the first HEADERS frame, and the body of the primary stream, but before
5390 // we've received the final HEADERS for the pushed stream.
5391 data.SetStop(4);
5392
5393 // Start the transaction.
5394 TestCompletionCallback callback;
5395 int rv = trans->Start(
5396 &CreateGetRequest(), callback.callback(), BoundNetLog());
5397 EXPECT_EQ(ERR_IO_PENDING, rv);
5398 data.Run();
5399 rv = callback.WaitForResult();
5400 EXPECT_EQ(0, rv);
5401
5402 // Request the pushed path. At this point, we've received the push, but the
5403 // headers are not yet complete.
5404 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:425405 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
[email protected]5c6908e2012-08-06 18:53:475406 rv = trans2->Start(
5407 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5408 EXPECT_EQ(ERR_IO_PENDING, rv);
5409 data.RunFor(2);
[email protected]fc9d88472013-08-14 02:31:175410 base::RunLoop().RunUntilIdle();
[email protected]5c6908e2012-08-06 18:53:475411
5412 // Read the server push body.
5413 std::string result2;
rch0aecfd82015-05-19 17:22:325414 ReadResult(trans2.get(), &result2);
[email protected]5c6908e2012-08-06 18:53:475415 // Read the response body.
5416 std::string result;
rch0aecfd82015-05-19 17:22:325417 ReadResult(trans, &result);
[email protected]5c6908e2012-08-06 18:53:475418 EXPECT_EQ("hello!", result);
5419
5420 // Verify that we haven't received any push data.
5421 EXPECT_EQ("", result2);
5422
5423 // Verify the SYN_REPLY.
5424 // Copy the response info, because trans goes away.
5425 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]5c6908e2012-08-06 18:53:475426
5427 VerifyStreamsClosed(helper);
5428
5429 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505430 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025431 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]5c6908e2012-08-06 18:53:475432
5433 // Read the final EOF (which will close the session).
5434 data.RunFor(1);
5435
5436 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:175437 EXPECT_TRUE(data.AllReadDataConsumed());
5438 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]5c6908e2012-08-06 18:53:475439}
5440
[email protected]513963e2013-06-15 01:53:045441TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:465442 scoped_ptr<SpdyFrame> req(
5443 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:415444 scoped_ptr<SpdyFrame> rst(
5445 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5446 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525447 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]745aa9c2014-06-27 02:21:295448 };
[email protected]d08358502010-12-03 22:04:035449
[email protected]4bd46222013-05-14 19:32:235450 scoped_ptr<SpdyFrame> stream1_reply(
[email protected]745aa9c2014-06-27 02:21:295451 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:045452
5453 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5454 (*late_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235455 scoped_ptr<SpdyFrame> stream1_headers(
[email protected]513963e2013-06-15 01:53:045456 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235457 false,
5458 1,
5459 LOWEST,
5460 HEADERS,
5461 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235462 0));
[email protected]513963e2013-06-15 01:53:045463 scoped_ptr<SpdyFrame> stream1_body(
5464 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035465 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525466 CreateMockRead(*stream1_reply, 1),
5467 CreateMockRead(*stream1_headers, 2),
5468 CreateMockRead(*stream1_body, 3),
5469 MockRead(ASYNC, 0, 5) // EOF
[email protected]d08358502010-12-03 22:04:035470 };
5471
rch08e3aa3e2015-05-16 14:27:525472 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365473 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505474 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:575475 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035476 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:415477 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]d08358502010-12-03 22:04:035478}
5479
xunjieli294da722015-08-11 19:15:025480// Tests that receiving HEADERS, DATA, HEADERS, and DATA in that sequence will
5481// trigger a ERR_SPDY_PROTOCOL_ERROR because trailing HEADERS must not be
5482// followed by any DATA frames.
5483TEST_P(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) {
[email protected]cdf8f7e72013-05-23 10:56:465484 scoped_ptr<SpdyFrame> req(
5485 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:415486 scoped_ptr<SpdyFrame> rst(
5487 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5488 MockWrite writes[] = {
xunjieli294da722015-08-11 19:15:025489 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
[email protected]b771bb72013-06-24 09:55:415490 };
[email protected]d08358502010-12-03 22:04:035491
[email protected]4bd46222013-05-14 19:32:235492 scoped_ptr<SpdyFrame> stream1_reply(
[email protected]745aa9c2014-06-27 02:21:295493 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:045494
5495 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5496 (*late_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235497 scoped_ptr<SpdyFrame> stream1_headers(
[email protected]513963e2013-06-15 01:53:045498 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235499 false,
5500 1,
5501 LOWEST,
5502 HEADERS,
5503 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235504 0));
[email protected]513963e2013-06-15 01:53:045505 scoped_ptr<SpdyFrame> stream1_body(
5506 spdy_util_.ConstructSpdyBodyFrame(1, false));
5507 scoped_ptr<SpdyFrame> stream1_body2(
5508 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035509 MockRead reads[] = {
xunjieli294da722015-08-11 19:15:025510 CreateMockRead(*stream1_reply, 1), CreateMockRead(*stream1_body, 2),
5511 CreateMockRead(*stream1_headers, 3), CreateMockRead(*stream1_body2, 4),
rch08e3aa3e2015-05-16 14:27:525512 MockRead(ASYNC, 0, 6) // EOF
[email protected]d08358502010-12-03 22:04:035513 };
5514
rch32320842015-05-16 15:57:095515 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365516 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505517 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:575518 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035519 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:415520 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]d08358502010-12-03 22:04:035521}
5522
[email protected]513963e2013-06-15 01:53:045523TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
rchebf12982015-04-10 01:15:005524 // Running these tests via Alt-Svc is too complicated to be worthwhile.
5525 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
5526 return;
5527
[email protected]a7a265ef2010-12-08 18:05:575528 // In this test we want to verify that we can't accidentally push content
5529 // which can't be pushed by this content server.
5530 // This test assumes that:
5531 // - if we're requesting http://www.foo.com/barbaz
5532 // - the browser has made a connection to "www.foo.com".
5533
5534 // A list of the URL to fetch, followed by the URL being pushed.
5535 static const char* const kTestCases[] = {
bncce36dca22015-04-21 22:11:235536 "https://www.example.org/foo.html",
5537 "https://www.example.org:81/foo.js", // Bad port
[email protected]a7a265ef2010-12-08 18:05:575538
bncce36dca22015-04-21 22:11:235539 "https://www.example.org/foo.html",
5540 "http://www.example.org/foo.js", // Bad protocol
[email protected]a7a265ef2010-12-08 18:05:575541
bncce36dca22015-04-21 22:11:235542 "https://www.example.org/foo.html",
5543 "ftp://www.example.org/foo.js", // Invalid Protocol
[email protected]a7a265ef2010-12-08 18:05:575544
bncce36dca22015-04-21 22:11:235545 "https://www.example.org/foo.html",
5546 "https://blat.www.example.org/foo.js", // Cross subdomain
[email protected]a7a265ef2010-12-08 18:05:575547
bncce36dca22015-04-21 22:11:235548 "https://www.example.org/foo.html",
rchebf12982015-04-10 01:15:005549 "https://www.foo.com/foo.js", // Cross domain
[email protected]a7a265ef2010-12-08 18:05:575550 };
5551
[email protected]b3f899332010-12-08 18:20:445552 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
[email protected]a7a265ef2010-12-08 18:05:575553 const char* url_to_fetch = kTestCases[index];
5554 const char* url_to_push = kTestCases[index + 1];
5555
[email protected]cdf8f7e72013-05-23 10:56:465556 scoped_ptr<SpdyFrame> stream1_syn(
5557 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
[email protected]513963e2013-06-15 01:53:045558 scoped_ptr<SpdyFrame> stream1_body(
5559 spdy_util_.ConstructSpdyBodyFrame(1, true));
rdsmithebb50aa2015-11-12 03:44:385560 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]ff98d7f02012-03-22 21:44:195561 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:205562 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]a7a265ef2010-12-08 18:05:575563 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525564 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*push_rst, 3),
[email protected]a7a265ef2010-12-08 18:05:575565 };
5566
[email protected]ff98d7f02012-03-22 21:44:195567 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045568 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:195569 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045570 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5571 0,
5572 2,
5573 1,
5574 url_to_push));
[email protected]8a0fc822013-06-27 20:52:435575 const char kPushedData[] = "pushed";
5576 scoped_ptr<SpdyFrame> stream2_body(
5577 spdy_util_.ConstructSpdyBodyFrame(
5578 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:195579 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:205580 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]a7a265ef2010-12-08 18:05:575581
5582 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525583 CreateMockRead(*stream1_reply, 1),
5584 CreateMockRead(*stream2_syn, 2),
5585 CreateMockRead(*stream1_body, 4),
5586 CreateMockRead(*stream2_body, 5),
5587 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]a7a265ef2010-12-08 18:05:575588 };
5589
5590 HttpResponseInfo response;
rch08e3aa3e2015-05-16 14:27:525591 SequencedSocketData data(reads, arraysize(reads), writes,
5592 arraysize(writes));
[email protected]a7a265ef2010-12-08 18:05:575593
5594 HttpRequestInfo request;
5595 request.method = "GET";
5596 request.url = GURL(url_to_fetch);
5597 request.load_flags = 0;
[email protected]a7a265ef2010-12-08 18:05:575598
[email protected]7c6f7ba2012-04-03 04:09:295599 // Enable cross-origin push. Since we are not using a proxy, this should
5600 // not actually enable cross-origin SPDY push.
[email protected]61b4efc2012-04-27 18:12:505601 scoped_ptr<SpdySessionDependencies> session_deps(
[email protected]513963e2013-06-15 01:53:045602 CreateSpdySessionDependencies(GetParam()));
[email protected]61b4efc2012-04-27 18:12:505603 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
rdsmith82957ad2015-09-16 19:42:035604 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
5605 GetParam(), session_deps.Pass());
[email protected]61b4efc2012-04-27 18:12:505606 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575607 helper.AddData(&data);
[email protected]7c6f7ba2012-04-03 04:09:295608
[email protected]a7a265ef2010-12-08 18:05:575609 HttpNetworkTransaction* trans = helper.trans();
5610
5611 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415612 TestCompletionCallback callback;
[email protected]a7a265ef2010-12-08 18:05:575613
[email protected]49639fa2011-12-20 23:22:415614 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]a7a265ef2010-12-08 18:05:575615 EXPECT_EQ(ERR_IO_PENDING, rv);
5616 rv = callback.WaitForResult();
5617
5618 // Read the response body.
5619 std::string result;
rch0aecfd82015-05-19 17:22:325620 ReadResult(trans, &result);
[email protected]a7a265ef2010-12-08 18:05:575621
5622 // Verify that we consumed all test data.
rch37de576c2015-05-17 20:28:175623 EXPECT_TRUE(data.AllReadDataConsumed());
5624 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]a7a265ef2010-12-08 18:05:575625
5626 // Verify the SYN_REPLY.
5627 // Copy the response info, because trans goes away.
5628 response = *trans->GetResponseInfo();
5629
5630 VerifyStreamsClosed(helper);
5631
5632 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505633 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025634 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]a7a265ef2010-12-08 18:05:575635 }
5636}
5637
[email protected]513963e2013-06-15 01:53:045638TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
[email protected]721c0ce2011-10-13 02:41:005639 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:465640 scoped_ptr<SpdyFrame> req(
5641 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rdsmithebb50aa2015-11-12 03:44:385642 // Will be destroyed by the RST before stream 3 starts.
5643 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:465644 scoped_ptr<SpdyFrame> req2(
5645 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]721c0ce2011-10-13 02:41:005646 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525647 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 2),
[email protected]721c0ce2011-10-13 02:41:005648 };
5649
[email protected]ff98d7f02012-03-22 21:44:195650 scoped_ptr<SpdyFrame> refused(
[email protected]c10b20852013-05-15 21:29:205651 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
[email protected]513963e2013-06-15 01:53:045652 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5653 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]721c0ce2011-10-13 02:41:005654 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525655 CreateMockRead(*refused, 1),
5656 CreateMockRead(*resp, 3),
5657 CreateMockRead(*body, 4),
5658 MockRead(ASYNC, 0, 5) // EOF
[email protected]721c0ce2011-10-13 02:41:005659 };
5660
rch08e3aa3e2015-05-16 14:27:525661 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365662 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505663 BoundNetLog(), GetParam(), NULL);
[email protected]721c0ce2011-10-13 02:41:005664
5665 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575666 helper.AddData(&data);
[email protected]721c0ce2011-10-13 02:41:005667
5668 HttpNetworkTransaction* trans = helper.trans();
5669
5670 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415671 TestCompletionCallback callback;
5672 int rv = trans->Start(
5673 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]721c0ce2011-10-13 02:41:005674 EXPECT_EQ(ERR_IO_PENDING, rv);
5675 rv = callback.WaitForResult();
5676 EXPECT_EQ(OK, rv);
5677
5678 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:525679 EXPECT_TRUE(data.AllReadDataConsumed());
5680 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]721c0ce2011-10-13 02:41:005681
5682 // Verify the SYN_REPLY.
5683 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:505684 EXPECT_TRUE(response.headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025685 EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
[email protected]721c0ce2011-10-13 02:41:005686}
5687
[email protected]513963e2013-06-15 01:53:045688TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
[email protected]e1f58efa2012-05-15 18:23:405689 // This first request will start to establish the SpdySession.
5690 // Then we will start the second (MEDIUM priority) and then third
5691 // (HIGHEST priority) request in such a way that the third will actually
[email protected]c92f4b4542012-07-26 23:53:215692 // start before the second, causing the second to be numbered differently
[email protected]513963e2013-06-15 01:53:045693 // than the order they were created.
rdsmithebb50aa2015-11-12 03:44:385694 //
5695 // Note that the requests and responses created below are expectations
5696 // of what the above will produce on the wire, and hence are in the
5697 // initial->HIGHEST->LOWEST priority.
5698 //
5699 // Frames are created by SpdySession just before the write associated
5700 // with the frame is attempted, so stream dependencies will be based
5701 // on the streams alive at the point of the request write attempt. Thus
5702 // req1 is alive when req2 is attempted (during but not after the
5703 // |data.RunFor(2);| statement below) but not when req3 is attempted.
5704 // The call to spdy_util_.UpdateWithStreamDestruction() reflects this.
[email protected]cdf8f7e72013-05-23 10:56:465705 scoped_ptr<SpdyFrame> req1(
5706 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5707 scoped_ptr<SpdyFrame> req2(
5708 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
rdsmithebb50aa2015-11-12 03:44:385709 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:465710 scoped_ptr<SpdyFrame> req3(
5711 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
[email protected]e1f58efa2012-05-15 18:23:405712 MockWrite writes[] = {
5713 CreateMockWrite(*req1, 0),
5714 CreateMockWrite(*req2, 3),
5715 CreateMockWrite(*req3, 4),
5716 };
5717
[email protected]513963e2013-06-15 01:53:045718 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5719 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5720 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5721 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5722 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5723 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]e1f58efa2012-05-15 18:23:405724 MockRead reads[] = {
5725 CreateMockRead(*resp1, 1),
5726 CreateMockRead(*body1, 2),
5727 CreateMockRead(*resp2, 5),
5728 CreateMockRead(*body2, 6),
5729 CreateMockRead(*resp3, 7),
5730 CreateMockRead(*body3, 8),
5731 MockRead(ASYNC, 0, 9) // EOF
5732 };
5733
[email protected]dd54bd82012-07-19 23:44:575734 DeterministicSocketData data(reads, arraysize(reads),
[email protected]513963e2013-06-15 01:53:045735 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365736 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
[email protected]e1f58efa2012-05-15 18:23:405737 BoundNetLog(), GetParam(), NULL);
5738 helper.SetDeterministic();
5739 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575740 helper.AddDeterministicData(&data);
[email protected]e1f58efa2012-05-15 18:23:405741
5742 // Start the first transaction to set up the SpdySession
5743 HttpNetworkTransaction* trans = helper.trans();
5744 TestCompletionCallback callback;
5745 HttpRequestInfo info1 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405746 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
5747 EXPECT_EQ(ERR_IO_PENDING, rv);
5748
5749 // Run the message loop, but do not allow the write to complete.
5750 // This leaves the SpdySession with a write pending, which prevents
5751 // SpdySession from attempting subsequent writes until this write completes.
[email protected]fc9d88472013-08-14 02:31:175752 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405753
5754 // Now, start both new transactions
5755 HttpRequestInfo info2 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405756 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:505757 scoped_ptr<HttpNetworkTransaction> trans2(
mmenkee65e7af2015-10-13 17:16:425758 new HttpNetworkTransaction(MEDIUM, helper.session()));
[email protected]e1f58efa2012-05-15 18:23:405759 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
5760 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:175761 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405762
5763 HttpRequestInfo info3 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405764 TestCompletionCallback callback3;
5765 scoped_ptr<HttpNetworkTransaction> trans3(
mmenkee65e7af2015-10-13 17:16:425766 new HttpNetworkTransaction(HIGHEST, helper.session()));
[email protected]e1f58efa2012-05-15 18:23:405767 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5768 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:175769 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405770
5771 // We now have two SYN_STREAM frames queued up which will be
5772 // dequeued only once the first write completes, which we
5773 // now allow to happen.
[email protected]dd54bd82012-07-19 23:44:575774 data.RunFor(2);
[email protected]e1f58efa2012-05-15 18:23:405775 EXPECT_EQ(OK, callback.WaitForResult());
5776
5777 // And now we can allow everything else to run to completion.
[email protected]dd54bd82012-07-19 23:44:575778 data.SetStop(10);
5779 data.Run();
[email protected]e1f58efa2012-05-15 18:23:405780 EXPECT_EQ(OK, callback2.WaitForResult());
5781 EXPECT_EQ(OK, callback3.WaitForResult());
5782
5783 helper.VerifyDataConsumed();
5784}
5785
[email protected]d11b6912013-06-27 23:07:325786// The tests below are only for SPDY/3 and above.
5787
5788// Test that sent data frames and received WINDOW_UPDATE frames change
5789// the send_window_size_ correctly.
5790
5791// WINDOW_UPDATE is different than most other frames in that it can arrive
5792// while the client is still sending the request body. In order to enforce
5793// this scenario, we feed a couple of dummy frames and give a delay of 0 to
5794// socket data provider, so that initial read that is done as soon as the
5795// stream is created, succeeds and schedules another read. This way reads
5796// and writes are interleaved; after doing a full frame write, SpdyStream
5797// will break out of DoLoop and will read and process a WINDOW_UPDATE.
5798// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5799// since request has not been completely written, therefore we feed
5800// enough number of WINDOW_UPDATEs to finish the first read and cause a
5801// write, leading to a complete write of request body; after that we send
5802// a reply with a body, to cause a graceful shutdown.
5803
5804// TODO(agayev): develop a socket data provider where both, reads and
5805// writes are ordered so that writing tests like these are easy and rewrite
5806// all these tests using it. Right now we are working around the
5807// limitations as described above and it's not deterministic, tests may
5808// fail under specific circumstances.
5809TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
[email protected]d11b6912013-06-27 23:07:325810 static int kFrameCount = 2;
5811 scoped_ptr<std::string> content(
5812 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5813 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:005814 GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL,
5815 0));
[email protected]d11b6912013-06-27 23:07:325816 scoped_ptr<SpdyFrame> body(
5817 spdy_util_.ConstructSpdyBodyFrame(
5818 1, content->c_str(), content->size(), false));
5819 scoped_ptr<SpdyFrame> body_end(
5820 spdy_util_.ConstructSpdyBodyFrame(
5821 1, content->c_str(), content->size(), true));
5822
5823 MockWrite writes[] = {
5824 CreateMockWrite(*req, 0),
5825 CreateMockWrite(*body, 1),
5826 CreateMockWrite(*body_end, 2),
5827 };
5828
5829 static const int32 kDeltaWindowSize = 0xff;
5830 static const int kDeltaCount = 4;
5831 scoped_ptr<SpdyFrame> window_update(
5832 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5833 scoped_ptr<SpdyFrame> window_update_dummy(
5834 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5835 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
5836 MockRead reads[] = {
5837 CreateMockRead(*window_update_dummy, 3),
5838 CreateMockRead(*window_update_dummy, 4),
5839 CreateMockRead(*window_update_dummy, 5),
5840 CreateMockRead(*window_update, 6), // Four updates, therefore window
5841 CreateMockRead(*window_update, 7), // size should increase by
5842 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
5843 CreateMockRead(*window_update, 9),
5844 CreateMockRead(*resp, 10),
5845 CreateMockRead(*body_end, 11),
5846 MockRead(ASYNC, 0, 0, 12) // EOF
5847 };
5848
5849 DeterministicSocketData data(reads, arraysize(reads),
5850 writes, arraysize(writes));
5851
olli.raula6df48b2a2015-11-26 07:40:225852 std::vector<scoped_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:325853 for (int i = 0; i < kFrameCount; ++i) {
olli.raula6df48b2a2015-11-26 07:40:225854 element_readers.push_back(make_scoped_ptr(
5855 new UploadBytesElementReader(content->c_str(), content->size())));
[email protected]d11b6912013-06-27 23:07:325856 }
olli.raula6df48b2a2015-11-26 07:40:225857 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:325858
5859 // Setup the request
5860 HttpRequestInfo request;
5861 request.method = "POST";
rchebf12982015-04-10 01:15:005862 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:325863 request.upload_data_stream = &upload_data_stream;
5864
5865 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5866 BoundNetLog(), GetParam(), NULL);
5867 helper.SetDeterministic();
5868 helper.AddDeterministicData(&data);
5869 helper.RunPreTestSetup();
5870
5871 HttpNetworkTransaction* trans = helper.trans();
5872
5873 TestCompletionCallback callback;
5874 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5875
5876 EXPECT_EQ(ERR_IO_PENDING, rv);
5877
5878 data.RunFor(11);
5879
5880 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5881 ASSERT_TRUE(stream != NULL);
5882 ASSERT_TRUE(stream->stream() != NULL);
bnc638c4702015-04-09 18:01:185883 EXPECT_EQ(static_cast<int>(
5884 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol)) +
5885 kDeltaWindowSize * kDeltaCount -
5886 kMaxSpdyFrameChunkSize * kFrameCount,
5887 stream->stream()->send_window_size());
[email protected]d11b6912013-06-27 23:07:325888
5889 data.RunFor(1);
5890
5891 rv = callback.WaitForResult();
5892 EXPECT_EQ(OK, rv);
5893
5894 helper.VerifyDataConsumed();
5895}
5896
5897// Test that received data frames and sent WINDOW_UPDATE frames change
5898// the recv_window_size_ correctly.
5899TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
bnc8f0f3b62015-04-08 04:37:235900 const int32 default_initial_window_size =
bnc638c4702015-04-09 18:01:185901 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
bnc8f0f3b62015-04-08 04:37:235902 // Session level maximum window size that is more than twice the default
5903 // initial window size so that an initial window update is sent.
5904 const int32 session_max_recv_window_size = 5 * 64 * 1024;
5905 ASSERT_LT(2 * default_initial_window_size, session_max_recv_window_size);
5906 // Stream level maximum window size that is less than the session level
5907 // maximum window size so that we test for confusion between the two.
5908 const int32 stream_max_recv_window_size = 4 * 64 * 1024;
5909 ASSERT_GT(session_max_recv_window_size, stream_max_recv_window_size);
5910 // Size of body to be sent. Has to be less than or equal to both window sizes
5911 // so that we do not run out of receiving window. Also has to be greater than
5912 // half of them so that it triggers both a session level and a stream level
5913 // window update frame.
5914 const int32 kTargetSize = 3 * 64 * 1024;
5915 ASSERT_GE(session_max_recv_window_size, kTargetSize);
5916 ASSERT_GE(stream_max_recv_window_size, kTargetSize);
5917 ASSERT_LT(session_max_recv_window_size / 2, kTargetSize);
5918 ASSERT_LT(stream_max_recv_window_size / 2, kTargetSize);
5919 // Size of each DATA frame.
5920 const int32 kChunkSize = 4096;
5921 // Size of window updates.
5922 ASSERT_EQ(0, session_max_recv_window_size / 2 % kChunkSize);
5923 const int32 session_window_update_delta =
5924 session_max_recv_window_size / 2 + kChunkSize;
5925 ASSERT_EQ(0, stream_max_recv_window_size / 2 % kChunkSize);
5926 const int32 stream_window_update_delta =
5927 stream_max_recv_window_size / 2 + kChunkSize;
[email protected]d11b6912013-06-27 23:07:325928
bnc8f0f3b62015-04-08 04:37:235929 SettingsMap initial_settings;
5930 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
5931 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
5932 initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
5933 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size);
5934 scoped_ptr<SpdyFrame> initial_settings_frame(
5935 spdy_util_.ConstructSpdySettings(initial_settings));
5936 scoped_ptr<SpdyFrame> initial_window_update(
5937 spdy_util_.ConstructSpdyWindowUpdate(
5938 kSessionFlowControlStreamId,
5939 session_max_recv_window_size - default_initial_window_size));
[email protected]d11b6912013-06-27 23:07:325940 scoped_ptr<SpdyFrame> req(
5941 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5942 scoped_ptr<SpdyFrame> session_window_update(
bnc8f0f3b62015-04-08 04:37:235943 spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta));
5944 scoped_ptr<SpdyFrame> stream_window_update(
5945 spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta));
[email protected]d11b6912013-06-27 23:07:325946
5947 std::vector<MockWrite> writes;
bnc9b79a572015-09-02 12:25:035948 if (GetParam().protocol == kProtoHTTP2) {
bnc8f0f3b62015-04-08 04:37:235949 writes.push_back(MockWrite(ASYNC, kHttp2ConnectionHeaderPrefix,
5950 kHttp2ConnectionHeaderPrefixSize, 0));
5951 }
rchacdcbdc2015-05-16 17:16:005952 writes.push_back(CreateMockWrite(*initial_settings_frame, writes.size()));
5953 writes.push_back(CreateMockWrite(*initial_window_update, writes.size()));
5954 writes.push_back(CreateMockWrite(*req, writes.size()));
[email protected]d11b6912013-06-27 23:07:325955
[email protected]251029e2014-03-19 06:04:405956 std::vector<MockRead> reads;
[email protected]d11b6912013-06-27 23:07:325957 scoped_ptr<SpdyFrame> resp(
5958 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchacdcbdc2015-05-16 17:16:005959 reads.push_back(CreateMockRead(*resp, writes.size() + reads.size()));
[email protected]d11b6912013-06-27 23:07:325960
[email protected]251029e2014-03-19 06:04:405961 ScopedVector<SpdyFrame> body_frames;
bnc8f0f3b62015-04-08 04:37:235962 const std::string body_data(kChunkSize, 'x');
[email protected]251029e2014-03-19 06:04:405963 for (size_t remaining = kTargetSize; remaining != 0;) {
5964 size_t frame_size = std::min(remaining, body_data.size());
5965 body_frames.push_back(spdy_util_.ConstructSpdyBodyFrame(
5966 1, body_data.data(), frame_size, false));
rchacdcbdc2015-05-16 17:16:005967 reads.push_back(
5968 CreateMockRead(*body_frames.back(), writes.size() + reads.size()));
[email protected]251029e2014-03-19 06:04:405969 remaining -= frame_size;
5970 }
rchacdcbdc2015-05-16 17:16:005971 reads.push_back(
5972 MockRead(ASYNC, ERR_IO_PENDING, writes.size() + reads.size())); // Yield.
[email protected]251029e2014-03-19 06:04:405973
rchacdcbdc2015-05-16 17:16:005974 writes.push_back(
5975 CreateMockWrite(*session_window_update, writes.size() + reads.size()));
5976 writes.push_back(
5977 CreateMockWrite(*stream_window_update, writes.size() + reads.size()));
5978
davidben5f8b6bc2015-11-25 03:19:545979 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
5980 writes.size());
[email protected]d11b6912013-06-27 23:07:325981
5982 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5983 BoundNetLog(), GetParam(), NULL);
5984 helper.AddData(&data);
5985 helper.RunPreTestSetup();
[email protected]d11b6912013-06-27 23:07:325986
bnc8f0f3b62015-04-08 04:37:235987 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5988 SpdySessionPoolPeer pool_peer(spdy_session_pool);
5989 pool_peer.SetEnableSendingInitialData(true);
5990 pool_peer.SetSessionMaxRecvWindowSize(session_max_recv_window_size);
5991 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
5992
5993 HttpNetworkTransaction* trans = helper.trans();
[email protected]d11b6912013-06-27 23:07:325994 TestCompletionCallback callback;
5995 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5996
5997 EXPECT_EQ(ERR_IO_PENDING, rv);
5998 rv = callback.WaitForResult();
5999 EXPECT_EQ(OK, rv);
6000
6001 SpdyHttpStream* stream =
6002 static_cast<SpdyHttpStream*>(trans->stream_.get());
6003 ASSERT_TRUE(stream != NULL);
6004 ASSERT_TRUE(stream->stream() != NULL);
6005
[email protected]251029e2014-03-19 06:04:406006 // All data has been read, but not consumed. The window reflects this.
bnc8f0f3b62015-04-08 04:37:236007 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size - kTargetSize),
[email protected]251029e2014-03-19 06:04:406008 stream->stream()->recv_window_size());
[email protected]d11b6912013-06-27 23:07:326009
6010 const HttpResponseInfo* response = trans->GetResponseInfo();
6011 ASSERT_TRUE(response != NULL);
6012 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:026013 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d11b6912013-06-27 23:07:326014 EXPECT_TRUE(response->was_fetched_via_spdy);
6015
6016 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6017 // size increased to default.
bnc301745a2015-03-10 03:22:166018 scoped_refptr<IOBuffer> buf(new IOBuffer(kTargetSize));
[email protected]251029e2014-03-19 06:04:406019 EXPECT_EQ(static_cast<int>(kTargetSize),
6020 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
bnc8f0f3b62015-04-08 04:37:236021 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size),
[email protected]251029e2014-03-19 06:04:406022 stream->stream()->recv_window_size());
6023 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
[email protected]d11b6912013-06-27 23:07:326024
[email protected]251029e2014-03-19 06:04:406025 // Allow scheduled WINDOW_UPDATE frames to write.
[email protected]fc9d88472013-08-14 02:31:176026 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326027 helper.VerifyDataConsumed();
6028}
6029
6030// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6031TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]d11b6912013-06-27 23:07:326032 // Number of full frames we hope to write (but will not, used to
6033 // set content-length header correctly)
6034 static int kFrameCount = 3;
6035
6036 scoped_ptr<std::string> content(
6037 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6038 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006039 GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL,
6040 0));
[email protected]d11b6912013-06-27 23:07:326041 scoped_ptr<SpdyFrame> body(
6042 spdy_util_.ConstructSpdyBodyFrame(
6043 1, content->c_str(), content->size(), false));
6044 scoped_ptr<SpdyFrame> rst(
6045 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
6046
6047 // We're not going to write a data frame with FIN, we'll receive a bad
6048 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6049 MockWrite writes[] = {
6050 CreateMockWrite(*req, 0),
6051 CreateMockWrite(*body, 2),
6052 CreateMockWrite(*rst, 3),
6053 };
6054
6055 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
6056 scoped_ptr<SpdyFrame> window_update(
6057 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6058 MockRead reads[] = {
6059 CreateMockRead(*window_update, 1),
6060 MockRead(ASYNC, 0, 4) // EOF
6061 };
6062
6063 DeterministicSocketData data(reads, arraysize(reads),
6064 writes, arraysize(writes));
6065
olli.raula6df48b2a2015-11-26 07:40:226066 std::vector<scoped_ptr<UploadElementReader>> element_readers;
[email protected]d11b6912013-06-27 23:07:326067 for (int i = 0; i < kFrameCount; ++i) {
olli.raula6df48b2a2015-11-26 07:40:226068 element_readers.push_back(make_scoped_ptr(
6069 new UploadBytesElementReader(content->c_str(), content->size())));
[email protected]d11b6912013-06-27 23:07:326070 }
olli.raula6df48b2a2015-11-26 07:40:226071 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326072
6073 // Setup the request
6074 HttpRequestInfo request;
6075 request.method = "POST";
rchebf12982015-04-10 01:15:006076 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326077 request.upload_data_stream = &upload_data_stream;
6078
6079 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6080 BoundNetLog(), GetParam(), NULL);
6081 helper.SetDeterministic();
6082 helper.RunPreTestSetup();
6083 helper.AddDeterministicData(&data);
6084 HttpNetworkTransaction* trans = helper.trans();
6085
6086 TestCompletionCallback callback;
6087 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6088 ASSERT_EQ(ERR_IO_PENDING, rv);
6089
6090 data.RunFor(5);
6091 ASSERT_TRUE(callback.have_result());
6092 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6093 helper.VerifyDataConsumed();
6094}
6095
6096// Test that after hitting a send window size of 0, the write process
6097// stalls and upon receiving WINDOW_UPDATE frame write resumes.
6098
6099// This test constructs a POST request followed by enough data frames
6100// containing 'a' that would make the window size 0, followed by another
6101// data frame containing default content (which is "hello!") and this frame
rchacdcbdc2015-05-16 17:16:006102// also contains a FIN flag. SequencedSocketData is used to enforce all
6103// writes, save the last, go through before a read could happen. The last frame
6104// ("hello!") is not permitted to go through since by the time its turn
[email protected]d11b6912013-06-27 23:07:326105// arrives, window size is 0. At this point MessageLoop::Run() called via
6106// callback would block. Therefore we call MessageLoop::RunUntilIdle()
6107// which returns after performing all possible writes. We use DCHECKS to
6108// ensure that last data frame is still there and stream has stalled.
6109// After that, next read is artifically enforced, which causes a
6110// WINDOW_UPDATE to be read and I/O process resumes.
6111TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
bnc2f54c832014-12-01 13:31:196112 const int32 initial_window_size =
bnc638c4702015-04-09 18:01:186113 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
[email protected]d11b6912013-06-27 23:07:326114 // Number of frames we need to send to zero out the window size: data
6115 // frames plus SYN_STREAM plus the last data frame; also we need another
6116 // data frame that we will send once the WINDOW_UPDATE is received,
6117 // therefore +3.
bnc2f54c832014-12-01 13:31:196118 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326119
6120 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196121 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326122
6123 // Construct content for a data frame of maximum size.
6124 std::string content(kMaxSpdyFrameChunkSize, 'a');
6125
6126 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006127 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6128 0));
[email protected]d11b6912013-06-27 23:07:326129
6130 // Full frames.
6131 scoped_ptr<SpdyFrame> body1(
6132 spdy_util_.ConstructSpdyBodyFrame(
6133 1, content.c_str(), content.size(), false));
6134
6135 // Last frame to zero out the window size.
6136 scoped_ptr<SpdyFrame> body2(
6137 spdy_util_.ConstructSpdyBodyFrame(
6138 1, content.c_str(), last_frame_size, false));
6139
6140 // Data frame to be sent once WINDOW_UPDATE frame is received.
6141 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6142
6143 // Fill in mock writes.
6144 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6145 size_t i = 0;
rchacdcbdc2015-05-16 17:16:006146 writes[i] = CreateMockWrite(*req, i);
[email protected]d11b6912013-06-27 23:07:326147 for (i = 1; i < num_writes - 2; i++)
rchacdcbdc2015-05-16 17:16:006148 writes[i] = CreateMockWrite(*body1, i);
6149 writes[i] = CreateMockWrite(*body2, i);
6150 // The last write must not be attempted until after the WINDOW_UPDATES
6151 // have been received.
6152 writes[i + 1] = CreateMockWrite(*body3, i + 4, SYNCHRONOUS);
[email protected]d11b6912013-06-27 23:07:326153
6154 // Construct read frame, give enough space to upload the rest of the
6155 // data.
6156 scoped_ptr<SpdyFrame> session_window_update(
6157 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6158 scoped_ptr<SpdyFrame> window_update(
6159 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6160 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6161 MockRead reads[] = {
rchacdcbdc2015-05-16 17:16:006162 MockRead(ASYNC, ERR_IO_PENDING, i + 1), // Force a pause
6163 CreateMockRead(*session_window_update, i + 2),
6164 CreateMockRead(*window_update, i + 3),
6165 // Now the last write will occur.
6166 CreateMockRead(*reply, i + 5),
6167 CreateMockRead(*body2, i + 6),
6168 CreateMockRead(*body3, i + 7),
6169 MockRead(ASYNC, 0, i + 8) // EOF
[email protected]d11b6912013-06-27 23:07:326170 };
6171
rchacdcbdc2015-05-16 17:16:006172 SequencedSocketData data(reads, arraysize(reads), writes.get(), num_writes);
[email protected]d11b6912013-06-27 23:07:326173
olli.raula6df48b2a2015-11-26 07:40:226174 std::vector<scoped_ptr<UploadElementReader>> element_readers;
bnc2f54c832014-12-01 13:31:196175 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326176 upload_data_string.append(kUploadData, kUploadDataSize);
olli.raula6df48b2a2015-11-26 07:40:226177 element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader(
6178 upload_data_string.c_str(), upload_data_string.size())));
6179 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326180
6181 HttpRequestInfo request;
6182 request.method = "POST";
rchebf12982015-04-10 01:15:006183 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326184 request.upload_data_stream = &upload_data_stream;
6185 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6186 BoundNetLog(), GetParam(), NULL);
6187 helper.AddData(&data);
6188 helper.RunPreTestSetup();
6189
6190 HttpNetworkTransaction* trans = helper.trans();
6191
6192 TestCompletionCallback callback;
6193 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6194 EXPECT_EQ(ERR_IO_PENDING, rv);
6195
[email protected]fc9d88472013-08-14 02:31:176196 base::RunLoop().RunUntilIdle(); // Write as much as we can.
[email protected]d11b6912013-06-27 23:07:326197
6198 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6199 ASSERT_TRUE(stream != NULL);
6200 ASSERT_TRUE(stream->stream() != NULL);
6201 EXPECT_EQ(0, stream->stream()->send_window_size());
6202 // All the body data should have been read.
6203 // TODO(satorux): This is because of the weirdness in reading the request
6204 // body in OnSendBodyComplete(). See crbug.com/113107.
6205 EXPECT_TRUE(upload_data_stream.IsEOF());
6206 // But the body is not yet fully sent (kUploadData is not yet sent)
6207 // since we're send-stalled.
6208 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6209
rchacdcbdc2015-05-16 17:16:006210 data.CompleteRead(); // Read in WINDOW_UPDATE frame.
[email protected]d11b6912013-06-27 23:07:326211 rv = callback.WaitForResult();
6212 helper.VerifyDataConsumed();
6213}
6214
6215// Test we correctly handle the case where the SETTINGS frame results in
6216// unstalling the send window.
6217TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
bnc2f54c832014-12-01 13:31:196218 const int32 initial_window_size =
bnc638c4702015-04-09 18:01:186219 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
bnc2f54c832014-12-01 13:31:196220
[email protected]d11b6912013-06-27 23:07:326221 // Number of frames we need to send to zero out the window size: data
6222 // frames plus SYN_STREAM plus the last data frame; also we need another
6223 // data frame that we will send once the SETTING is received, therefore +3.
bnc2f54c832014-12-01 13:31:196224 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326225
6226 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196227 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326228
6229 // Construct content for a data frame of maximum size.
6230 std::string content(kMaxSpdyFrameChunkSize, 'a');
6231
6232 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006233 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6234 0));
[email protected]d11b6912013-06-27 23:07:326235
6236 // Full frames.
6237 scoped_ptr<SpdyFrame> body1(
6238 spdy_util_.ConstructSpdyBodyFrame(
6239 1, content.c_str(), content.size(), false));
6240
6241 // Last frame to zero out the window size.
6242 scoped_ptr<SpdyFrame> body2(
6243 spdy_util_.ConstructSpdyBodyFrame(
6244 1, content.c_str(), last_frame_size, false));
6245
6246 // Data frame to be sent once SETTINGS frame is received.
6247 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6248
6249 // Fill in mock reads/writes.
6250 std::vector<MockRead> reads;
6251 std::vector<MockWrite> writes;
6252 size_t i = 0;
6253 writes.push_back(CreateMockWrite(*req, i++));
6254 while (i < num_writes - 2)
6255 writes.push_back(CreateMockWrite(*body1, i++));
6256 writes.push_back(CreateMockWrite(*body2, i++));
6257
6258 // Construct read frame for SETTINGS that gives enough space to upload the
6259 // rest of the data.
6260 SettingsMap settings;
6261 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:196262 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
[email protected]d11b6912013-06-27 23:07:326263 scoped_ptr<SpdyFrame> settings_frame_large(
6264 spdy_util_.ConstructSpdySettings(settings));
6265
6266 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6267
6268 scoped_ptr<SpdyFrame> session_window_update(
6269 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6270 if (GetParam().protocol >= kProtoSPDY31)
6271 reads.push_back(CreateMockRead(*session_window_update, i++));
6272
[email protected]d4a77c12014-05-15 20:45:216273 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6274 writes.push_back(CreateMockWrite(*settings_ack, i++));
6275
[email protected]d11b6912013-06-27 23:07:326276 writes.push_back(CreateMockWrite(*body3, i++));
6277
6278 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6279 reads.push_back(CreateMockRead(*reply, i++));
6280 reads.push_back(CreateMockRead(*body2, i++));
6281 reads.push_back(CreateMockRead(*body3, i++));
6282 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6283
6284 // Force all writes to happen before any read, last write will not
6285 // actually queue a frame, due to window size being 0.
davidben5f8b6bc2015-11-25 03:19:546286 DeterministicSocketData data(reads.data(), reads.size(), writes.data(),
6287 writes.size());
[email protected]d11b6912013-06-27 23:07:326288
olli.raula6df48b2a2015-11-26 07:40:226289 std::vector<scoped_ptr<UploadElementReader>> element_readers;
bnc2f54c832014-12-01 13:31:196290 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326291 upload_data_string.append(kUploadData, kUploadDataSize);
olli.raula6df48b2a2015-11-26 07:40:226292 element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader(
6293 upload_data_string.c_str(), upload_data_string.size())));
6294 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326295
6296 HttpRequestInfo request;
6297 request.method = "POST";
rchebf12982015-04-10 01:15:006298 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326299 request.upload_data_stream = &upload_data_stream;
6300 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6301 BoundNetLog(), GetParam(), NULL);
6302 helper.SetDeterministic();
6303 helper.RunPreTestSetup();
6304 helper.AddDeterministicData(&data);
6305
6306 HttpNetworkTransaction* trans = helper.trans();
6307
6308 TestCompletionCallback callback;
6309 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6310 EXPECT_EQ(ERR_IO_PENDING, rv);
6311
6312 data.RunFor(num_writes - 1); // Write as much as we can.
6313
6314 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6315 ASSERT_TRUE(stream != NULL);
6316 ASSERT_TRUE(stream->stream() != NULL);
6317 EXPECT_EQ(0, stream->stream()->send_window_size());
6318
6319 // All the body data should have been read.
6320 // TODO(satorux): This is because of the weirdness in reading the request
6321 // body in OnSendBodyComplete(). See crbug.com/113107.
6322 EXPECT_TRUE(upload_data_stream.IsEOF());
6323 // But the body is not yet fully sent (kUploadData is not yet sent)
6324 // since we're send-stalled.
6325 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6326
[email protected]d4a77c12014-05-15 20:45:216327 data.RunFor(7); // Read in SETTINGS frame to unstall.
[email protected]d11b6912013-06-27 23:07:326328 rv = callback.WaitForResult();
6329 helper.VerifyDataConsumed();
6330 // If stream is NULL, that means it was unstalled and closed.
6331 EXPECT_TRUE(stream->stream() == NULL);
6332}
6333
6334// Test we correctly handle the case where the SETTINGS frame results in a
6335// negative send window size.
6336TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
bnc2f54c832014-12-01 13:31:196337 const int32 initial_window_size =
bnc638c4702015-04-09 18:01:186338 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
[email protected]d11b6912013-06-27 23:07:326339 // Number of frames we need to send to zero out the window size: data
6340 // frames plus SYN_STREAM plus the last data frame; also we need another
6341 // data frame that we will send once the SETTING is received, therefore +3.
bnc2f54c832014-12-01 13:31:196342 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326343
6344 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196345 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326346
6347 // Construct content for a data frame of maximum size.
6348 std::string content(kMaxSpdyFrameChunkSize, 'a');
6349
6350 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006351 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6352 0));
[email protected]d11b6912013-06-27 23:07:326353
6354 // Full frames.
6355 scoped_ptr<SpdyFrame> body1(
6356 spdy_util_.ConstructSpdyBodyFrame(
6357 1, content.c_str(), content.size(), false));
6358
6359 // Last frame to zero out the window size.
6360 scoped_ptr<SpdyFrame> body2(
6361 spdy_util_.ConstructSpdyBodyFrame(
6362 1, content.c_str(), last_frame_size, false));
6363
6364 // Data frame to be sent once SETTINGS frame is received.
6365 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6366
6367 // Fill in mock reads/writes.
6368 std::vector<MockRead> reads;
6369 std::vector<MockWrite> writes;
6370 size_t i = 0;
6371 writes.push_back(CreateMockWrite(*req, i++));
6372 while (i < num_writes - 2)
6373 writes.push_back(CreateMockWrite(*body1, i++));
6374 writes.push_back(CreateMockWrite(*body2, i++));
6375
6376 // Construct read frame for SETTINGS that makes the send_window_size
6377 // negative.
6378 SettingsMap new_settings;
6379 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:196380 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
[email protected]d11b6912013-06-27 23:07:326381 scoped_ptr<SpdyFrame> settings_frame_small(
6382 spdy_util_.ConstructSpdySettings(new_settings));
6383 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6384 // positive.
6385 scoped_ptr<SpdyFrame> session_window_update_init_size(
bnc2f54c832014-12-01 13:31:196386 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
[email protected]d11b6912013-06-27 23:07:326387 scoped_ptr<SpdyFrame> window_update_init_size(
bnc2f54c832014-12-01 13:31:196388 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
[email protected]d11b6912013-06-27 23:07:326389
6390 reads.push_back(CreateMockRead(*settings_frame_small, i++));
bnc33b8cef42014-11-19 17:30:386391 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
[email protected]d11b6912013-06-27 23:07:326392 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6393
[email protected]d4a77c12014-05-15 20:45:216394 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6395 writes.push_back(CreateMockWrite(*settings_ack, i++));
6396
[email protected]d11b6912013-06-27 23:07:326397 writes.push_back(CreateMockWrite(*body3, i++));
6398
6399 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6400 reads.push_back(CreateMockRead(*reply, i++));
6401 reads.push_back(CreateMockRead(*body2, i++));
6402 reads.push_back(CreateMockRead(*body3, i++));
6403 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6404
6405 // Force all writes to happen before any read, last write will not
6406 // actually queue a frame, due to window size being 0.
davidben5f8b6bc2015-11-25 03:19:546407 DeterministicSocketData data(reads.data(), reads.size(), writes.data(),
6408 writes.size());
[email protected]d11b6912013-06-27 23:07:326409
olli.raula6df48b2a2015-11-26 07:40:226410 std::vector<scoped_ptr<UploadElementReader>> element_readers;
bnc2f54c832014-12-01 13:31:196411 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326412 upload_data_string.append(kUploadData, kUploadDataSize);
olli.raula6df48b2a2015-11-26 07:40:226413 element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader(
6414 upload_data_string.c_str(), upload_data_string.size())));
6415 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]d11b6912013-06-27 23:07:326416
6417 HttpRequestInfo request;
6418 request.method = "POST";
rchebf12982015-04-10 01:15:006419 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326420 request.upload_data_stream = &upload_data_stream;
6421 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6422 BoundNetLog(), GetParam(), NULL);
6423 helper.SetDeterministic();
6424 helper.RunPreTestSetup();
6425 helper.AddDeterministicData(&data);
6426
6427 HttpNetworkTransaction* trans = helper.trans();
6428
6429 TestCompletionCallback callback;
6430 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6431 EXPECT_EQ(ERR_IO_PENDING, rv);
6432
6433 data.RunFor(num_writes - 1); // Write as much as we can.
6434
6435 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6436 ASSERT_TRUE(stream != NULL);
6437 ASSERT_TRUE(stream->stream() != NULL);
6438 EXPECT_EQ(0, stream->stream()->send_window_size());
6439
6440 // All the body data should have been read.
6441 // TODO(satorux): This is because of the weirdness in reading the request
6442 // body in OnSendBodyComplete(). See crbug.com/113107.
6443 EXPECT_TRUE(upload_data_stream.IsEOF());
6444 // But the body is not yet fully sent (kUploadData is not yet sent)
6445 // since we're send-stalled.
6446 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6447
6448 // Read in WINDOW_UPDATE or SETTINGS frame.
[email protected]d4a77c12014-05-15 20:45:216449 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 9 : 8);
[email protected]d11b6912013-06-27 23:07:326450 rv = callback.WaitForResult();
6451 helper.VerifyDataConsumed();
6452}
6453
baranovich212a1292014-09-02 21:45:316454TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
6455 if (spdy_util_.spdy_version() < SPDY3)
6456 return;
6457
6458 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
bncce36dca22015-04-21 22:11:236459 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat",
baranovich212a1292014-09-02 21:45:316460 push_headers.get());
6461 scoped_ptr<SpdyFrame> push(
6462 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 3, 1));
6463 MockRead reads[] = {CreateMockRead(*push, 1)};
6464
6465 scoped_ptr<SpdyFrame> req(
6466 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6467 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6468 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6469 MockWrite writes[] = {
6470 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
6471 };
6472
rch08e3aa3e2015-05-16 14:27:526473 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
baranovich212a1292014-09-02 21:45:316474 NormalSpdyTransactionHelper helper(
6475 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6476 helper.RunToCompletion(&data);
6477 TransactionHelperResult out = helper.output();
6478 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6479}
6480
6481TEST_P(SpdyNetworkTransactionTest,
6482 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
6483 if (spdy_util_.spdy_version() < SPDY3)
6484 return;
6485
6486 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:006487 NULL, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
baranovich212a1292014-09-02 21:45:316488 scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
rchebf12982015-04-10 01:15:006489 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/b.dat"),
baranovich212a1292014-09-02 21:45:316490 push_b_headers.get());
6491 scoped_ptr<SpdyFrame> push_b(
6492 spdy_util_.ConstructInitialSpdyPushFrame(push_b_headers.Pass(), 2, 1));
6493 MockRead reads[] = {
6494 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
6495 };
6496
6497 scoped_ptr<SpdyFrame> req(
6498 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6499 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6500 4,
6501 GOAWAY_PROTOCOL_ERROR,
6502 "New push stream id must be greater than the last accepted."));
6503 MockWrite writes[] = {
6504 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
6505 };
6506
rch08e3aa3e2015-05-16 14:27:526507 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
baranovich212a1292014-09-02 21:45:316508 NormalSpdyTransactionHelper helper(
6509 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6510 helper.RunToCompletion(&data);
6511 TransactionHelperResult out = helper.output();
6512 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6513}
6514
bnc76598ab2015-06-29 12:43:076515// Regression test for https://crbug.com/493348: request header exceeds 16 kB
6516// and thus sent in multiple frames when using HTTP/2.
6517TEST_P(SpdyNetworkTransactionTest, LargeRequest) {
6518 const std::string kKey("foo");
6519 const std::string kValue(1 << 15, 'z');
6520
6521 HttpRequestInfo request;
6522 request.method = "GET";
6523 request.url = GURL(GetDefaultUrl());
6524 request.extra_headers.SetHeader(kKey, kValue);
6525
6526 scoped_ptr<SpdyHeaderBlock> headers(
6527 spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
6528 (*headers)[kKey] = kValue;
6529 scoped_ptr<SpdyFrame> req(
6530 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
6531 MockWrite writes[] = {
6532 CreateMockWrite(*req, 0),
6533 };
6534
6535 scoped_ptr<SpdyFrame> resp(
6536 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
6537 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6538 MockRead reads[] = {
6539 CreateMockRead(*resp, 1),
6540 CreateMockRead(*body, 2),
6541 MockRead(ASYNC, 0, 3) // EOF
6542 };
6543
6544 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
6545 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
6546 GetParam(), nullptr);
6547 helper.RunToCompletion(&data);
6548 TransactionHelperResult out = helper.output();
6549
6550 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:026551 EXPECT_EQ("HTTP/1.1 200", out.status_line);
bnc76598ab2015-06-29 12:43:076552 EXPECT_EQ("hello!", out.response_data);
6553}
6554
[email protected]514aeaf2014-05-23 10:31:516555class SpdyNetworkTransactionNoTLSUsageCheckTest
6556 : public SpdyNetworkTransactionTest {
6557 protected:
6558 void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6559 // Construct the request.
rchebf12982015-04-10 01:15:006560 scoped_ptr<SpdyFrame> req(
6561 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:526562 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]514aeaf2014-05-23 10:31:516563
6564 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6565 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6566 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:526567 CreateMockRead(*resp, 1),
6568 CreateMockRead(*body, 2),
6569 MockRead(ASYNC, 0, 3) // EOF
[email protected]514aeaf2014-05-23 10:31:516570 };
6571
rch08e3aa3e2015-05-16 14:27:526572 SequencedSocketData data(reads, arraysize(reads), writes,
6573 arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516574 HttpRequestInfo request;
6575 request.method = "GET";
bncce36dca22015-04-21 22:11:236576 request.url = GURL("https://www.example.org/");
[email protected]514aeaf2014-05-23 10:31:516577 NormalSpdyTransactionHelper helper(
6578 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6579 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6580 TransactionHelperResult out = helper.output();
6581 EXPECT_EQ(OK, out.rv);
bnc84e7fb52015-12-02 11:50:026582 EXPECT_EQ("HTTP/1.1 200", out.status_line);
[email protected]514aeaf2014-05-23 10:31:516583 EXPECT_EQ("hello!", out.response_data);
6584 }
6585};
6586
6587//-----------------------------------------------------------------------------
6588// All tests are run with three different connection types: SPDY after NPN
6589// negotiation, SPDY without SSL, and SPDY with SSL.
6590//
6591// TODO(akalin): Use ::testing::Combine() when we are able to use
6592// <tr1/tuple>.
6593INSTANTIATE_TEST_CASE_P(
6594 Spdy,
6595 SpdyNetworkTransactionNoTLSUsageCheckTest,
rchebf12982015-04-10 01:15:006596 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31,
rdsmithebb50aa2015-11-12 03:44:386597 HTTPS_SPDY_VIA_NPN,
6598 false)));
[email protected]514aeaf2014-05-23 10:31:516599
6600TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6601 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6602 new SSLSocketDataProvider(ASYNC, OK));
6603 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6604 &ssl_provider->connection_status);
6605
6606 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6607}
6608
6609TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6610 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6611 new SSLSocketDataProvider(ASYNC, OK));
6612 // Set to TLS_RSA_WITH_NULL_MD5
6613 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6614
6615 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6616}
6617
6618class SpdyNetworkTransactionTLSUsageCheckTest
6619 : public SpdyNetworkTransactionTest {
6620 protected:
6621 void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]bdd1b222014-06-10 11:08:396622 scoped_ptr<SpdyFrame> goaway(
6623 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6624 MockWrite writes[] = {CreateMockWrite(*goaway)};
[email protected]514aeaf2014-05-23 10:31:516625
rch08e3aa3e2015-05-16 14:27:526626 StaticSocketDataProvider data(NULL, 0, writes, arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516627 HttpRequestInfo request;
6628 request.method = "GET";
bncce36dca22015-04-21 22:11:236629 request.url = GURL("https://www.example.org/");
[email protected]514aeaf2014-05-23 10:31:516630 NormalSpdyTransactionHelper helper(
6631 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6632 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6633 TransactionHelperResult out = helper.output();
6634 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6635 }
6636};
6637
6638INSTANTIATE_TEST_CASE_P(
6639 Spdy,
6640 SpdyNetworkTransactionTLSUsageCheckTest,
rdsmithebb50aa2015-11-12 03:44:386641 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoHTTP2,
6642 HTTPS_SPDY_VIA_NPN,
6643 false),
6644 SpdyNetworkTransactionTestParams(kProtoHTTP2,
6645 HTTPS_SPDY_VIA_NPN,
6646 true)));
[email protected]514aeaf2014-05-23 10:31:516647
6648TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6649 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6650 new SSLSocketDataProvider(ASYNC, OK));
6651 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6652 &ssl_provider->connection_status);
6653
6654 RunTLSUsageCheckTest(ssl_provider.Pass());
6655}
6656
6657TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6658 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6659 new SSLSocketDataProvider(ASYNC, OK));
6660 // Set to TLS_RSA_WITH_NULL_MD5
6661 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6662
6663 RunTLSUsageCheckTest(ssl_provider.Pass());
6664}
6665
[email protected]aea80602009-09-18 00:55:086666} // namespace net