blob: 5002dc8c58b0122d34daff1c5f369a4b5b2951bf [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"
[email protected]69e6b4a2012-10-18 08:03:0112#include "base/memory/scoped_vector.h"
[email protected]fc9d88472013-08-14 02:31:1713#include "base/run_loop.h"
[email protected]b771bb72013-06-24 09:55:4114#include "base/stl_util.h"
[email protected]251029e2014-03-19 06:04:4015#include "base/strings/string_piece.h"
[email protected]999dd8c2013-11-12 06:45:5416#include "base/test/test_file_util.h"
[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"
[email protected]87bfa3f2010-09-30 14:54:5624#include "net/http/http_network_session_peer.h"
[email protected]513963e2013-06-15 01:53:0425#include "net/http/http_network_transaction.h"
26#include "net/http/http_server_properties.h"
[email protected]c41737d2014-05-14 07:47:1927#include "net/http/http_transaction_test_util.h"
mmenke16a7cbdd2015-04-24 23:00:5628#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4629#include "net/log/test_net_log_entry.h"
30#include "net/log/test_net_log_util.h"
[email protected]2d6728692011-03-12 01:39:5531#include "net/socket/client_socket_pool_base.h"
[email protected]bb88e1d32013-05-03 23:11:0732#include "net/socket/next_proto.h"
[email protected]f54c85792012-03-08 19:06:4133#include "net/spdy/buffered_spdy_framer.h"
[email protected]9be804c82010-06-24 17:59:4634#include "net/spdy/spdy_http_stream.h"
[email protected]9e1bdd32011-02-03 21:48:3435#include "net/spdy/spdy_http_utils.h"
[email protected]bdebd1b2010-08-09 20:18:0836#include "net/spdy/spdy_session.h"
[email protected]19ec8a72010-08-23 03:38:2337#include "net/spdy/spdy_session_pool.h"
[email protected]86aa87b2013-02-15 01:10:0338#include "net/spdy/spdy_test_util_common.h"
[email protected]a4bfdf72013-02-22 04:06:1639#include "net/spdy/spdy_test_utils.h"
[email protected]514aeaf2014-05-23 10:31:5140#include "net/ssl/ssl_connection_status_flags.h"
bncce36dca22015-04-21 22:11:2341#include "net/test/cert_test_util.h"
[email protected]d2db0292011-01-26 20:23:4442#include "net/url_request/url_request_test_util.h"
[email protected]251029e2014-03-19 06:04:4043#include "testing/gmock/include/gmock/gmock.h"
[email protected]aea80602009-09-18 00:55:0844#include "testing/platform_test.h"
45
46//-----------------------------------------------------------------------------
47
[email protected]d1eda932009-11-04 01:03:1048namespace net {
[email protected]dae22c52010-07-30 02:16:3549
[email protected]cbdd73162013-03-18 23:27:3350namespace {
[email protected]251029e2014-03-19 06:04:4051
52using testing::Each;
53using testing::Eq;
54
[email protected]513963e2013-06-15 01:53:0455enum SpdyNetworkTransactionTestSSLType {
rchebf12982015-04-10 01:15:0056 // Request an https:// URL and use NPN (or ALPN) to negotiate SPDY during
57 // the TLS handshake.
58 HTTPS_SPDY_VIA_NPN,
59 // Request and http:// URL to a server that supports SPDY via Alternative
60 // Service on port 443.
61 // See: https//tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html
62 HTTP_SPDY_VIA_ALT_SVC,
[email protected]9e9e842e2010-07-23 23:09:1563};
[email protected]ca6459f862012-04-11 19:43:2064
[email protected]513963e2013-06-15 01:53:0465struct SpdyNetworkTransactionTestParams {
66 SpdyNetworkTransactionTestParams()
rchebf12982015-04-10 01:15:0067 : protocol(kProtoSPDY31), ssl_type(HTTPS_SPDY_VIA_NPN) {}
[email protected]513963e2013-06-15 01:53:0468
rchebf12982015-04-10 01:15:0069 SpdyNetworkTransactionTestParams(NextProto protocol,
70 SpdyNetworkTransactionTestSSLType ssl_type)
71 : protocol(protocol), ssl_type(ssl_type) {}
72
73 friend std::ostream& operator<<(std::ostream& os,
74 const SpdyNetworkTransactionTestParams& p) {
75 std::string type_str;
76 switch (p.ssl_type) {
77 case HTTP_SPDY_VIA_ALT_SVC:
78 type_str = "HTTP_SPDY_VIA_ALT_SVC";
79 break;
80 case HTTPS_SPDY_VIA_NPN:
81 type_str = "HTTPS_SPDY_VIA_NPN";
82 break;
83 }
84 os << "{ protocol: " << SSLClientSocket::NextProtoToString(p.protocol)
85 << ", ssl_type: " << type_str << " }";
86 return os;
87 }
[email protected]513963e2013-06-15 01:53:0488
89 NextProto protocol;
90 SpdyNetworkTransactionTestSSLType ssl_type;
91};
92
rchebf12982015-04-10 01:15:0093void UpdateSpdySessionDependencies(SpdyNetworkTransactionTestParams test_params,
94 SpdySessionDependencies* session_deps) {
95 session_deps->use_alternate_protocols = true;
96 session_deps->next_protos = SpdyNextProtos();
97 if (test_params.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
98 session_deps->http_server_properties.SetAlternativeService(
bncce36dca22015-04-21 22:11:2399 HostPortPair("www.example.org", 80),
rchebf12982015-04-10 01:15:00100 AlternativeService(AlternateProtocolFromNextProto(test_params.protocol),
bncce36dca22015-04-21 22:11:23101 "www.example.org", 443),
rchebf12982015-04-10 01:15:00102 1);
[email protected]d7599122014-05-24 03:37:23103 }
104}
105
[email protected]513963e2013-06-15 01:53:04106SpdySessionDependencies* CreateSpdySessionDependencies(
107 SpdyNetworkTransactionTestParams test_params) {
[email protected]d7599122014-05-24 03:37:23108 SpdySessionDependencies* session_deps =
109 new SpdySessionDependencies(test_params.protocol);
110 UpdateSpdySessionDependencies(test_params, session_deps);
111 return session_deps;
[email protected]513963e2013-06-15 01:53:04112}
113
114SpdySessionDependencies* CreateSpdySessionDependencies(
115 SpdyNetworkTransactionTestParams test_params,
[email protected]bb88e1d32013-05-03 23:11:07116 ProxyService* proxy_service) {
[email protected]d7599122014-05-24 03:37:23117 SpdySessionDependencies* session_deps =
118 new SpdySessionDependencies(test_params.protocol, proxy_service);
119 UpdateSpdySessionDependencies(test_params, session_deps);
120 return session_deps;
[email protected]bb88e1d32013-05-03 23:11:07121}
122
[email protected]513963e2013-06-15 01:53:04123} // namespace
124
125class SpdyNetworkTransactionTest
126 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
[email protected]34437af82009-11-06 02:28:49127 protected:
[email protected]513963e2013-06-15 01:53:04128 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
rchebf12982015-04-10 01:15:00129 spdy_util_.set_default_url(GURL(GetDefaultUrl()));
[email protected]9ec54f82013-05-10 02:53:05130 }
[email protected]2d6728692011-03-12 01:39:55131
[email protected]fc9d88472013-08-14 02:31:17132 virtual ~SpdyNetworkTransactionTest() {
mmenkecbc2b712014-10-09 20:29:07133 // UploadDataStream may post a deletion tasks back to the message loop on
[email protected]fc9d88472013-08-14 02:31:17134 // destruction.
135 upload_data_stream_.reset();
136 base::RunLoop().RunUntilIdle();
137 }
138
dcheng67be2b1f2014-10-27 21:47:29139 void SetUp() override {
bncce36dca22015-04-21 22:11:23140 get_request_initialized_ = false;
141 post_request_initialized_ = false;
142 chunked_post_request_initialized_ = false;
[email protected]69e6b4a2012-10-18 08:03:01143 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]aea80602009-09-18 00:55:08144 }
145
[email protected]72552f02009-10-28 15:25:01146 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:08147 int rv;
148 std::string status_line;
149 std::string response_data;
[email protected]8b070372009-11-16 22:01:25150 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:08151 };
152
[email protected]3caf5542010-07-16 15:19:47153 // A helper class that handles all the initial npn/ssl setup.
154 class NormalSpdyTransactionHelper {
155 public:
156 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
[email protected]262eec82013-03-19 21:01:36157 RequestPriority priority,
[email protected]9e9e842e2010-07-23 23:09:15158 const BoundNetLog& log,
[email protected]513963e2013-06-15 01:53:04159 SpdyNetworkTransactionTestParams test_params,
[email protected]61b4efc2012-04-27 18:12:50160 SpdySessionDependencies* session_deps)
[email protected]30c942b2010-07-21 16:59:59161 : request_(request),
[email protected]262eec82013-03-19 21:01:36162 priority_(priority),
rchebf12982015-04-10 01:15:00163 session_deps_(session_deps == NULL
164 ? CreateSpdySessionDependencies(test_params)
165 : session_deps),
166 session_(
167 SpdySessionDependencies::SpdyCreateSession(session_deps_.get())),
[email protected]9e9e842e2010-07-23 23:09:15168 log_(log),
[email protected]513963e2013-06-15 01:53:04169 test_params_(test_params),
rchebf12982015-04-10 01:15:00170 port_(443),
[email protected]1f418ee2010-10-16 19:46:56171 deterministic_(false),
rchebf12982015-04-10 01:15:00172 spdy_enabled_(true) {}
[email protected]61b4efc2012-04-27 18:12:50173
[email protected]19ec8a72010-08-23 03:38:23174 ~NormalSpdyTransactionHelper() {
175 // Any test which doesn't close the socket by sending it an EOF will
176 // have a valid session left open, which leaks the entire session pool.
177 // This is just fine - in fact, some of our tests intentionally do this
178 // so that we can check consistency of the SpdySessionPool as the test
179 // finishes. If we had put an EOF on the socket, the SpdySession would
180 // have closed and we wouldn't be able to check the consistency.
181
182 // Forcefully close existing sessions here.
183 session()->spdy_session_pool()->CloseAllSessions();
184 }
185
[email protected]3b7828432010-08-18 18:33:27186 void SetDeterministic() {
187 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
188 session_deps_.get());
189 deterministic_ = true;
190 }
191
[email protected]1f418ee2010-10-16 19:46:56192 void SetSpdyDisabled() {
193 spdy_enabled_ = false;
rchebf12982015-04-10 01:15:00194 port_ = test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC ? 80 : 443;
[email protected]1f418ee2010-10-16 19:46:56195 }
196
[email protected]3caf5542010-07-16 15:19:47197 void RunPreTestSetup() {
[email protected]b261d0e2010-08-02 19:13:24198 if (!session_deps_.get())
[email protected]513963e2013-06-15 01:53:04199 session_deps_.reset(CreateSpdySessionDependencies(test_params_));
[email protected]d7599122014-05-24 03:37:23200 if (!session_.get()) {
[email protected]b261d0e2010-08-02 19:13:24201 session_ = SpdySessionDependencies::SpdyCreateSession(
202 session_deps_.get());
[email protected]3caf5542010-07-16 15:19:47203 }
[email protected]aea80602009-09-18 00:55:08204
[email protected]3caf5542010-07-16 15:19:47205 // We're now ready to use SSL-npn SPDY.
[email protected]90499482013-06-01 00:39:50206 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
[email protected]cb54b3b22010-06-03 16:28:55207 }
[email protected]aea80602009-09-18 00:55:08208
[email protected]3caf5542010-07-16 15:19:47209 // Start the transaction, read some data, finish.
210 void RunDefaultTest() {
[email protected]34b345f92013-02-22 03:27:26211 if (!StartDefaultTest())
212 return;
213 FinishDefaultTest();
214 }
215
216 bool StartDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51217 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
[email protected]aea80602009-09-18 00:55:08218
[email protected]3caf5542010-07-16 15:19:47219 // We expect an IO Pending or some sort of error.
220 EXPECT_LT(output_.rv, 0);
[email protected]34b345f92013-02-22 03:27:26221 return output_.rv == ERR_IO_PENDING;
222 }
[email protected]aea80602009-09-18 00:55:08223
[email protected]34b345f92013-02-22 03:27:26224 void FinishDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51225 output_.rv = callback_.WaitForResult();
[email protected]3caf5542010-07-16 15:19:47226 if (output_.rv != OK) {
bnc301745a2015-03-10 03:22:16227 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
[email protected]3caf5542010-07-16 15:19:47228 return;
229 }
[email protected]ff57bb82009-11-12 06:52:14230
[email protected]3caf5542010-07-16 15:19:47231 // Verify responses.
232 const HttpResponseInfo* response = trans_->GetResponseInfo();
233 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:50234 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]3caf5542010-07-16 15:19:47235 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]1f418ee2010-10-16 19:46:56236 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
[email protected]808957c2013-03-13 03:51:27237 if (HttpStreamFactory::spdy_enabled()) {
[email protected]88a332622013-07-30 07:13:32238 EXPECT_EQ(
239 HttpResponseInfo::ConnectionInfoFromNextProto(
240 test_params_.protocol),
241 response->connection_info);
[email protected]808957c2013-03-13 03:51:27242 } else {
243 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
244 response->connection_info);
245 }
rchebf12982015-04-10 01:15:00246 if (spdy_enabled_) {
[email protected]9e9e842e2010-07-23 23:09:15247 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]a33cad2b62010-07-30 22:24:39248 } else {
rchebf12982015-04-10 01:15:00249 // If SPDY is disabled, an HTTP request should not be diverted
250 // over an SSL session.
[email protected]1f418ee2010-10-16 19:46:56251 EXPECT_EQ(request_.url.SchemeIs("https"),
252 response->was_npn_negotiated);
253 }
[email protected]80a09a82012-11-16 17:40:06254 EXPECT_EQ("127.0.0.1", response->socket_address.host());
255 EXPECT_EQ(port_, response->socket_address.port());
[email protected]3caf5542010-07-16 15:19:47256 output_.status_line = response->headers->GetStatusLine();
257 output_.response_info = *response; // Make a copy so we can verify.
258 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
[email protected]3caf5542010-07-16 15:19:47259 }
260
bncfacdd852015-01-09 19:22:54261 void FinishDefaultTestWithoutVerification() {
262 output_.rv = callback_.WaitForResult();
263 if (output_.rv != OK)
bnc301745a2015-03-10 03:22:16264 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
bncfacdd852015-01-09 19:22:54265 }
266
[email protected]3caf5542010-07-16 15:19:47267 // Most tests will want to call this function. In particular, the MockReads
268 // should end with an empty read, and that read needs to be processed to
269 // ensure proper deletion of the spdy_session_pool.
270 void VerifyDataConsumed() {
rch08e3aa3e2015-05-16 14:27:52271 for (const SocketDataProvider* provider : data_vector_) {
272 EXPECT_TRUE(provider->AllReadDataConsumed());
273 EXPECT_TRUE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47274 }
275 }
276
277 // Occasionally a test will expect to error out before certain reads are
278 // processed. In that case we want to explicitly ensure that the reads were
279 // not processed.
280 void VerifyDataNotConsumed() {
rch08e3aa3e2015-05-16 14:27:52281 for (const SocketDataProvider* provider : data_vector_) {
282 EXPECT_FALSE(provider->AllReadDataConsumed());
283 EXPECT_FALSE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47284 }
285 }
286
rch08e3aa3e2015-05-16 14:27:52287 void RunToCompletion(SocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47288 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58289 AddData(data);
[email protected]3caf5542010-07-16 15:19:47290 RunDefaultTest();
291 VerifyDataConsumed();
292 }
[email protected]e6b06862010-07-20 16:32:58293
[email protected]514aeaf2014-05-23 10:31:51294 void RunToCompletionWithSSLData(
rch08e3aa3e2015-05-16 14:27:52295 SocketDataProvider* data,
[email protected]514aeaf2014-05-23 10:31:51296 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
297 RunPreTestSetup();
298 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
299 RunDefaultTest();
300 VerifyDataConsumed();
301 }
302
rch08e3aa3e2015-05-16 14:27:52303 void AddData(SocketDataProvider* data) {
[email protected]514aeaf2014-05-23 10:31:51304 scoped_ptr<SSLSocketDataProvider> ssl_provider(
305 new SSLSocketDataProvider(ASYNC, OK));
bncce36dca22015-04-21 22:11:23306 ssl_provider->cert =
307 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
[email protected]514aeaf2014-05-23 10:31:51308 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
309 }
310
311 void AddDataWithSSLSocketDataProvider(
rch08e3aa3e2015-05-16 14:27:52312 SocketDataProvider* data,
[email protected]514aeaf2014-05-23 10:31:51313 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]3b7828432010-08-18 18:33:27314 DCHECK(!deterministic_);
[email protected]3caf5542010-07-16 15:19:47315 data_vector_.push_back(data);
rchebf12982015-04-10 01:15:00316 if (ssl_provider->next_proto_status ==
317 SSLClientSocket::kNextProtoUnsupported) {
[email protected]513963e2013-06-15 01:53:04318 ssl_provider->SetNextProto(test_params_.protocol);
[email protected]514aeaf2014-05-23 10:31:51319 }
rchebf12982015-04-10 01:15:00320
321 session_deps_->socket_factory->AddSSLSocketDataProvider(
322 ssl_provider.get());
[email protected]514aeaf2014-05-23 10:31:51323 ssl_vector_.push_back(ssl_provider.release());
[email protected]d4f00222012-07-10 06:24:51324
[email protected]3b7828432010-08-18 18:33:27325 session_deps_->socket_factory->AddSocketDataProvider(data);
rchebf12982015-04-10 01:15:00326 if (test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
327 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
328 StaticSocketDataProvider* hanging_non_alt_svc_socket =
[email protected]513963e2013-06-15 01:53:04329 new StaticSocketDataProvider(NULL, 0, NULL, 0);
rchebf12982015-04-10 01:15:00330 hanging_non_alt_svc_socket->set_connect_data(hanging_connect);
[email protected]2d6728692011-03-12 01:39:55331 session_deps_->socket_factory->AddSocketDataProvider(
rchebf12982015-04-10 01:15:00332 hanging_non_alt_svc_socket);
333 alternate_vector_.push_back(hanging_non_alt_svc_socket);
[email protected]2d6728692011-03-12 01:39:55334 }
[email protected]3b7828432010-08-18 18:33:27335 }
336
337 void AddDeterministicData(DeterministicSocketData* data) {
338 DCHECK(deterministic_);
339 data_vector_.push_back(data);
[email protected]d4f00222012-07-10 06:24:51340 SSLSocketDataProvider* ssl_provider =
341 new SSLSocketDataProvider(ASYNC, OK);
rchebf12982015-04-10 01:15:00342 ssl_provider->SetNextProto(test_params_.protocol);
bncce36dca22015-04-21 22:11:23343 ssl_provider->cert =
344 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
[email protected]d4f00222012-07-10 06:24:51345 ssl_vector_.push_back(ssl_provider);
rchebf12982015-04-10 01:15:00346 session_deps_->deterministic_socket_factory->AddSSLSocketDataProvider(
347 ssl_provider);
348
[email protected]3b7828432010-08-18 18:33:27349 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
rchebf12982015-04-10 01:15:00350 if (test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
351 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
352 DeterministicSocketData* hanging_non_alt_svc_socket =
[email protected]d4f00222012-07-10 06:24:51353 new DeterministicSocketData(NULL, 0, NULL, 0);
rchebf12982015-04-10 01:15:00354 hanging_non_alt_svc_socket->set_connect_data(hanging_connect);
[email protected]2d6728692011-03-12 01:39:55355 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
rchebf12982015-04-10 01:15:00356 hanging_non_alt_svc_socket);
357 alternate_vector_.push_back(hanging_non_alt_svc_socket);
[email protected]2d6728692011-03-12 01:39:55358 }
[email protected]3caf5542010-07-16 15:19:47359 }
360
[email protected]a33cad2b62010-07-30 22:24:39361 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
[email protected]3caf5542010-07-16 15:19:47362 session_ = session;
363 }
364 HttpNetworkTransaction* trans() { return trans_.get(); }
365 void ResetTrans() { trans_.reset(); }
366 TransactionHelperResult& output() { return output_; }
[email protected]19ec8a72010-08-23 03:38:23367 const HttpRequestInfo& request() const { return request_; }
368 const scoped_refptr<HttpNetworkSession>& session() const {
369 return session_;
370 }
[email protected]b261d0e2010-08-02 19:13:24371 scoped_ptr<SpdySessionDependencies>& session_deps() {
372 return session_deps_;
373 }
[email protected]19ec8a72010-08-23 03:38:23374 int port() const { return port_; }
[email protected]513963e2013-06-15 01:53:04375 SpdyNetworkTransactionTestParams test_params() const {
376 return test_params_;
[email protected]448d4ca52012-03-04 04:12:23377 }
[email protected]3caf5542010-07-16 15:19:47378
379 private:
rch08e3aa3e2015-05-16 14:27:52380 typedef std::vector<SocketDataProvider*> DataVector;
[email protected]d4f00222012-07-10 06:24:51381 typedef ScopedVector<SSLSocketDataProvider> SSLVector;
rch08e3aa3e2015-05-16 14:27:52382 typedef ScopedVector<SocketDataProvider> AlternateVector;
[email protected]d4f00222012-07-10 06:24:51383 typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
[email protected]3caf5542010-07-16 15:19:47384 HttpRequestInfo request_;
[email protected]262eec82013-03-19 21:01:36385 RequestPriority priority_;
[email protected]b261d0e2010-08-02 19:13:24386 scoped_ptr<SpdySessionDependencies> session_deps_;
[email protected]3caf5542010-07-16 15:19:47387 scoped_refptr<HttpNetworkSession> session_;
388 TransactionHelperResult output_;
rch08e3aa3e2015-05-16 14:27:52389 scoped_ptr<SocketDataProvider> first_transaction_;
[email protected]3caf5542010-07-16 15:19:47390 SSLVector ssl_vector_;
[email protected]514aeaf2014-05-23 10:31:51391 TestCompletionCallback callback_;
[email protected]3caf5542010-07-16 15:19:47392 scoped_ptr<HttpNetworkTransaction> trans_;
393 scoped_ptr<HttpNetworkTransaction> trans_http_;
394 DataVector data_vector_;
[email protected]2d6728692011-03-12 01:39:55395 AlternateVector alternate_vector_;
396 AlternateDeterministicVector alternate_deterministic_vector_;
bnc29b1f072015-01-14 20:37:49397 const BoundNetLog log_;
[email protected]513963e2013-06-15 01:53:04398 SpdyNetworkTransactionTestParams test_params_;
[email protected]9e9e842e2010-07-23 23:09:15399 int port_;
[email protected]3b7828432010-08-18 18:33:27400 bool deterministic_;
[email protected]1f418ee2010-10-16 19:46:56401 bool spdy_enabled_;
[email protected]3caf5542010-07-16 15:19:47402 };
[email protected]aea80602009-09-18 00:55:08403
404 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
405 int expected_status);
406
407 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18408
[email protected]e3ebba0f2010-08-05 17:59:58409 const HttpRequestInfo& CreateGetPushRequest() {
bncce36dca22015-04-21 22:11:23410 get_push_request_.method = "GET";
411 get_push_request_.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
412 get_push_request_.load_flags = 0;
413 return get_push_request_;
[email protected]e3ebba0f2010-08-05 17:59:58414 }
415
[email protected]d3cee19d2010-06-22 18:42:18416 const HttpRequestInfo& CreateGetRequest() {
bncce36dca22015-04-21 22:11:23417 if (!get_request_initialized_) {
418 get_request_.method = "GET";
419 get_request_.url = GURL(GetDefaultUrl());
420 get_request_.load_flags = 0;
421 get_request_initialized_ = true;
[email protected]d3cee19d2010-06-22 18:42:18422 }
bncce36dca22015-04-21 22:11:23423 return get_request_;
[email protected]d3cee19d2010-06-22 18:42:18424 }
425
[email protected]3deb9a52010-11-11 00:24:40426 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
bncce36dca22015-04-21 22:11:23427 if (!get_request_initialized_) {
428 get_request_.method = "GET";
429 get_request_.url = GURL(GetDefaultUrl());
430 get_request_.load_flags = 0;
431 get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
432 get_request_initialized_ = true;
[email protected]3deb9a52010-11-11 00:24:40433 }
bncce36dca22015-04-21 22:11:23434 return get_request_;
[email protected]3deb9a52010-11-11 00:24:40435 }
436
[email protected]310240592010-08-05 21:04:19437 const HttpRequestInfo& CreatePostRequest() {
bncce36dca22015-04-21 22:11:23438 if (!post_request_initialized_) {
[email protected]b2d26cfd2012-12-11 10:36:06439 ScopedVector<UploadElementReader> element_readers;
440 element_readers.push_back(
441 new UploadBytesElementReader(kUploadData, kUploadDataSize));
[email protected]96c77a72013-09-24 09:49:20442 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07443 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]329b68b2012-11-14 17:54:27444
bncce36dca22015-04-21 22:11:23445 post_request_.method = "POST";
446 post_request_.url = GURL(GetDefaultUrl());
447 post_request_.upload_data_stream = upload_data_stream_.get();
448 post_request_initialized_ = true;
[email protected]310240592010-08-05 21:04:19449 }
bncce36dca22015-04-21 22:11:23450 return post_request_;
[email protected]310240592010-08-05 21:04:19451 }
452
[email protected]69e6b4a2012-10-18 08:03:01453 const HttpRequestInfo& CreateFilePostRequest() {
bncce36dca22015-04-21 22:11:23454 if (!post_request_initialized_) {
[email protected]6cdfd7f2013-02-08 20:40:15455 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52456 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01457 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30458 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01459
[email protected]b2d26cfd2012-12-11 10:36:06460 ScopedVector<UploadElementReader> element_readers;
[email protected]cadac622013-06-11 16:46:36461 element_readers.push_back(
462 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
463 file_path,
464 0,
465 kUploadDataSize,
466 base::Time()));
[email protected]96c77a72013-09-24 09:49:20467 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07468 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]329b68b2012-11-14 17:54:27469
bncce36dca22015-04-21 22:11:23470 post_request_.method = "POST";
471 post_request_.url = GURL(GetDefaultUrl());
472 post_request_.upload_data_stream = upload_data_stream_.get();
473 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01474 }
bncce36dca22015-04-21 22:11:23475 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01476 }
477
[email protected]999dd8c2013-11-12 06:45:54478 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
bncce36dca22015-04-21 22:11:23479 if (post_request_initialized_)
480 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54481
482 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52483 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]999dd8c2013-11-12 06:45:54484 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30485 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]92be8eb2014-08-07 22:57:11486 CHECK(base::MakeFileUnreadable(file_path));
[email protected]999dd8c2013-11-12 06:45:54487
488 ScopedVector<UploadElementReader> element_readers;
489 element_readers.push_back(
490 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
491 file_path,
492 0,
493 kUploadDataSize,
494 base::Time()));
495 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07496 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]999dd8c2013-11-12 06:45:54497
bncce36dca22015-04-21 22:11:23498 post_request_.method = "POST";
499 post_request_.url = GURL(GetDefaultUrl());
500 post_request_.upload_data_stream = upload_data_stream_.get();
501 post_request_initialized_ = true;
502 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54503 }
504
[email protected]69e6b4a2012-10-18 08:03:01505 const HttpRequestInfo& CreateComplexPostRequest() {
bncce36dca22015-04-21 22:11:23506 if (!post_request_initialized_) {
[email protected]69e6b4a2012-10-18 08:03:01507 const int kFileRangeOffset = 1;
508 const int kFileRangeLength = 3;
509 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
510
[email protected]6cdfd7f2013-02-08 20:40:15511 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52512 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01513 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30514 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01515
[email protected]b2d26cfd2012-12-11 10:36:06516 ScopedVector<UploadElementReader> element_readers;
517 element_readers.push_back(
518 new UploadBytesElementReader(kUploadData, kFileRangeOffset));
[email protected]cadac622013-06-11 16:46:36519 element_readers.push_back(
520 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
521 file_path,
522 kFileRangeOffset,
523 kFileRangeLength,
524 base::Time()));
[email protected]b2d26cfd2012-12-11 10:36:06525 element_readers.push_back(new UploadBytesElementReader(
[email protected]69e6b4a2012-10-18 08:03:01526 kUploadData + kFileRangeOffset + kFileRangeLength,
[email protected]b2d26cfd2012-12-11 10:36:06527 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
[email protected]96c77a72013-09-24 09:49:20528 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07529 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]329b68b2012-11-14 17:54:27530
bncce36dca22015-04-21 22:11:23531 post_request_.method = "POST";
532 post_request_.url = GURL(GetDefaultUrl());
533 post_request_.upload_data_stream = upload_data_stream_.get();
534 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01535 }
bncce36dca22015-04-21 22:11:23536 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01537 }
538
[email protected]0c9bf872011-03-04 17:53:22539 const HttpRequestInfo& CreateChunkedPostRequest() {
bncce36dca22015-04-21 22:11:23540 if (!chunked_post_request_initialized_) {
mmenkecbc2b712014-10-09 20:29:07541 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
bncce36dca22015-04-21 22:11:23542 chunked_post_request_.method = "POST";
543 chunked_post_request_.url = GURL(GetDefaultUrl());
544 chunked_post_request_.upload_data_stream =
mmenkecbc2b712014-10-09 20:29:07545 upload_chunked_data_stream_.get();
bncce36dca22015-04-21 22:11:23546 chunked_post_request_initialized_ = true;
[email protected]0c9bf872011-03-04 17:53:22547 }
bncce36dca22015-04-21 22:11:23548 return chunked_post_request_;
[email protected]0c9bf872011-03-04 17:53:22549 }
550
[email protected]19ec8a72010-08-23 03:38:23551 // Read the result of a particular transaction, knowing that we've got
552 // multiple transactions in the read pipeline; so as we read, we may have
553 // to skip over data destined for other transactions while we consume
554 // the data for |trans|.
555 int ReadResult(HttpNetworkTransaction* trans,
rch08e3aa3e2015-05-16 14:27:52556 SocketDataProvider* data,
[email protected]19ec8a72010-08-23 03:38:23557 std::string* result) {
558 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58559
[email protected]19ec8a72010-08-23 03:38:23560 int bytes_read = 0;
bnc301745a2015-03-10 03:22:16561 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(kSize));
[email protected]49639fa2011-12-20 23:22:41562 TestCompletionCallback callback;
[email protected]19ec8a72010-08-23 03:38:23563 while (true) {
[email protected]90499482013-06-01 00:39:50564 int rv = trans->Read(buf.get(), kSize, callback.callback());
[email protected]19ec8a72010-08-23 03:38:23565 if (rv == ERR_IO_PENDING) {
[email protected]19ec8a72010-08-23 03:38:23566 rv = callback.WaitForResult();
567 } else if (rv <= 0) {
568 break;
569 }
570 result->append(buf->data(), rv);
571 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58572 }
[email protected]19ec8a72010-08-23 03:38:23573 return bytes_read;
574 }
[email protected]e3ebba0f2010-08-05 17:59:58575
[email protected]19ec8a72010-08-23 03:38:23576 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
577 // This lengthy block is reaching into the pool to dig out the active
578 // session. Once we have the session, we verify that the streams are
579 // all closed and not leaked at this point.
580 const GURL& url = helper.request().url;
rchebf12982015-04-10 01:15:00581 HostPortPair host_port_pair(url.host(), 443);
[email protected]e6d017652013-05-17 18:01:40582 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:53583 PRIVACY_MODE_DISABLED);
[email protected]19ec8a72010-08-23 03:38:23584 BoundNetLog log;
585 const scoped_refptr<HttpNetworkSession>& session = helper.session();
[email protected]795cbf82013-07-22 09:37:27586 base::WeakPtr<SpdySession> spdy_session =
[email protected]04644d42013-07-08 04:29:59587 session->spdy_session_pool()->FindAvailableSession(key, log);
[email protected]41d64e82013-07-03 22:44:26588 ASSERT_TRUE(spdy_session != NULL);
[email protected]19ec8a72010-08-23 03:38:23589 EXPECT_EQ(0u, spdy_session->num_active_streams());
590 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
591 }
[email protected]e3ebba0f2010-08-05 17:59:58592
rch08e3aa3e2015-05-16 14:27:52593 void RunServerPushTest(SequencedSocketData* data,
[email protected]e3ebba0f2010-08-05 17:59:58594 HttpResponseInfo* response,
[email protected]a7a265ef2010-12-08 18:05:57595 HttpResponseInfo* push_response,
[email protected]8a0fc822013-06-27 20:52:43596 const std::string& expected) {
[email protected]262eec82013-03-19 21:01:36597 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50598 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:58599 helper.RunPreTestSetup();
[email protected]d08358502010-12-03 22:04:03600 helper.AddData(data);
[email protected]e3ebba0f2010-08-05 17:59:58601
602 HttpNetworkTransaction* trans = helper.trans();
603
604 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:41605 TestCompletionCallback callback;
606 int rv = trans->Start(
607 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:58608 EXPECT_EQ(ERR_IO_PENDING, rv);
609 rv = callback.WaitForResult();
610
611 // Request the pushed path.
[email protected]e3ebba0f2010-08-05 17:59:58612 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:50613 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]49639fa2011-12-20 23:22:41614 rv = trans2->Start(
615 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:58616 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:17617 base::RunLoop().RunUntilIdle();
[email protected]e3ebba0f2010-08-05 17:59:58618
[email protected]513963e2013-06-15 01:53:04619 // The data for the pushed path may be coming in more than 1 frame. Compile
[email protected]e3ebba0f2010-08-05 17:59:58620 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23621
622 // Read the server push body.
623 std::string result2;
624 ReadResult(trans2.get(), data, &result2);
625 // Read the response body.
[email protected]e3ebba0f2010-08-05 17:59:58626 std::string result;
[email protected]19ec8a72010-08-23 03:38:23627 ReadResult(trans, data, &result);
[email protected]e3ebba0f2010-08-05 17:59:58628
629 // Verify that we consumed all test data.
rchb6dc73572015-05-08 04:01:07630 EXPECT_TRUE(data->at_read_eof());
631 EXPECT_TRUE(data->at_write_eof());
[email protected]e3ebba0f2010-08-05 17:59:58632
633 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23634 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
635 << result2
636 << "||||| Expected data: "
637 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58638
639 // Verify the SYN_REPLY.
640 // Copy the response info, because trans goes away.
641 *response = *trans->GetResponseInfo();
[email protected]a7a265ef2010-12-08 18:05:57642 *push_response = *trans2->GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23643
644 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58645 }
646
[email protected]49639fa2011-12-20 23:22:41647 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
648 int result) {
649 helper->ResetTrans();
650 }
651
652 static void StartTransactionCallback(
653 const scoped_refptr<HttpNetworkSession>& session,
rchebf12982015-04-10 01:15:00654 GURL url,
[email protected]49639fa2011-12-20 23:22:41655 int result) {
656 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:50657 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:41658 TestCompletionCallback callback;
659 HttpRequestInfo request;
660 request.method = "GET";
rchebf12982015-04-10 01:15:00661 request.url = url;
[email protected]49639fa2011-12-20 23:22:41662 request.load_flags = 0;
663 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
664 EXPECT_EQ(ERR_IO_PENDING, rv);
665 callback.WaitForResult();
666 }
667
mmenkecbc2b712014-10-09 20:29:07668 ChunkedUploadDataStream* upload_chunked_data_stream() const {
669 return upload_chunked_data_stream_.get();
670 }
671
rchebf12982015-04-10 01:15:00672 const char* GetDefaultUrl() {
673 switch (GetParam().ssl_type) {
674 case HTTP_SPDY_VIA_ALT_SVC:
bncce36dca22015-04-21 22:11:23675 return "http://www.example.org";
rchebf12982015-04-10 01:15:00676 case HTTPS_SPDY_VIA_NPN:
bncce36dca22015-04-21 22:11:23677 return "https://www.example.org";
rchebf12982015-04-10 01:15:00678 default:
679 NOTREACHED();
680 return "";
681 }
682 }
683
684 std::string GetDefaultUrlWithPath(const char* path) {
685 return std::string(GetDefaultUrl()) + path;
686 }
687
[email protected]9ec54f82013-05-10 02:53:05688 SpdyTestUtil spdy_util_;
689
[email protected]d3cee19d2010-06-22 18:42:18690 private:
mmenkecbc2b712014-10-09 20:29:07691 scoped_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
[email protected]329b68b2012-11-14 17:54:27692 scoped_ptr<UploadDataStream> upload_data_stream_;
bncce36dca22015-04-21 22:11:23693 bool get_request_initialized_;
694 bool post_request_initialized_;
695 bool chunked_post_request_initialized_;
696 HttpRequestInfo get_request_;
697 HttpRequestInfo post_request_;
698 HttpRequestInfo chunked_post_request_;
699 HttpRequestInfo get_push_request_;
[email protected]ea1a3f62012-11-16 20:34:23700 base::ScopedTempDir temp_dir_;
[email protected]aea80602009-09-18 00:55:08701};
702
703//-----------------------------------------------------------------------------
[email protected]9e9e842e2010-07-23 23:09:15704// All tests are run with three different connection types: SPDY after NPN
705// negotiation, SPDY without SSL, and SPDY with SSL.
[email protected]513963e2013-06-15 01:53:04706//
707// TODO(akalin): Use ::testing::Combine() when we are able to use
708// <tr1/tuple>.
709INSTANTIATE_TEST_CASE_P(
710 Spdy,
711 SpdyNetworkTransactionTest,
712 ::testing::Values(
rchebf12982015-04-10 01:15:00713 SpdyNetworkTransactionTestParams(kProtoSPDY31, HTTPS_SPDY_VIA_NPN),
714 SpdyNetworkTransactionTestParams(kProtoSPDY31, HTTP_SPDY_VIA_ALT_SVC),
715 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, HTTPS_SPDY_VIA_NPN),
716 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, HTTP_SPDY_VIA_ALT_SVC),
717 SpdyNetworkTransactionTestParams(kProtoSPDY4, HTTPS_SPDY_VIA_NPN),
718 SpdyNetworkTransactionTestParams(kProtoSPDY4, HTTP_SPDY_VIA_ALT_SVC)));
[email protected]aea80602009-09-18 00:55:08719
[email protected]3caf5542010-07-16 15:19:47720// Verify HttpNetworkTransaction constructor.
[email protected]513963e2013-06-15 01:53:04721TEST_P(SpdyNetworkTransactionTest, Constructor) {
[email protected]bb88e1d32013-05-03 23:11:07722 scoped_ptr<SpdySessionDependencies> session_deps(
[email protected]513963e2013-06-15 01:53:04723 CreateSpdySessionDependencies(GetParam()));
[email protected]ad8e04a2010-11-01 04:16:27724 scoped_refptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:07725 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
[email protected]262eec82013-03-19 21:01:36726 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:50727 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]aea80602009-09-18 00:55:08728}
729
[email protected]513963e2013-06-15 01:53:04730TEST_P(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38731 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:46732 scoped_ptr<SpdyFrame> req(
733 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:52734 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]72552f02009-10-28 15:25:01735
[email protected]513963e2013-06-15 01:53:04736 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
737 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]72552f02009-10-28 15:25:01738 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52739 CreateMockRead(*resp, 1),
740 CreateMockRead(*body, 2),
741 MockRead(ASYNC, 0, 3) // EOF
[email protected]72552f02009-10-28 15:25:01742 };
743
rch08e3aa3e2015-05-16 14:27:52744 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:36745 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50746 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:57747 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:47748 TransactionHelperResult out = helper.output();
[email protected]72552f02009-10-28 15:25:01749 EXPECT_EQ(OK, out.rv);
750 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
751 EXPECT_EQ("hello!", out.response_data);
752}
753
[email protected]513963e2013-06-15 01:53:04754TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
[email protected]3d08dd382013-10-19 00:13:11755 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
[email protected]31ae7ab2012-04-24 21:09:05756 p = RequestPriority(p + 1)) {
[email protected]c9c6f5c2010-07-31 01:30:03757 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:46758 scoped_ptr<SpdyFrame> req(
759 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
rch08e3aa3e2015-05-16 14:27:52760 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]c9c6f5c2010-07-31 01:30:03761
[email protected]86aa87b2013-02-15 01:10:03762 SpdyPriority spdy_prio = 0;
[email protected]513963e2013-06-15 01:53:04763 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
[email protected]c9c6f5c2010-07-31 01:30:03764 // this repeats the RequestPriority-->SpdyPriority mapping from
765 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
766 // sure it's being done right.
[email protected]513963e2013-06-15 01:53:04767 if (spdy_util_.spdy_version() < SPDY3) {
mmenkecbc2b712014-10-09 20:29:07768 switch (p) {
[email protected]513963e2013-06-15 01:53:04769 case HIGHEST:
770 EXPECT_EQ(0, spdy_prio);
771 break;
772 case MEDIUM:
773 EXPECT_EQ(1, spdy_prio);
774 break;
775 case LOW:
776 case LOWEST:
777 EXPECT_EQ(2, spdy_prio);
778 break;
779 case IDLE:
780 EXPECT_EQ(3, spdy_prio);
781 break;
782 default:
783 FAIL();
784 }
785 } else {
786 switch(p) {
787 case HIGHEST:
788 EXPECT_EQ(0, spdy_prio);
789 break;
790 case MEDIUM:
791 EXPECT_EQ(1, spdy_prio);
792 break;
793 case LOW:
794 EXPECT_EQ(2, spdy_prio);
795 break;
796 case LOWEST:
797 EXPECT_EQ(3, spdy_prio);
798 break;
799 case IDLE:
800 EXPECT_EQ(4, spdy_prio);
801 break;
802 default:
803 FAIL();
804 }
[email protected]c9c6f5c2010-07-31 01:30:03805 }
806
[email protected]513963e2013-06-15 01:53:04807 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
808 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c9c6f5c2010-07-31 01:30:03809 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52810 CreateMockRead(*resp, 1),
811 CreateMockRead(*body, 2),
812 MockRead(ASYNC, 0, 3) // EOF
[email protected]c9c6f5c2010-07-31 01:30:03813 };
814
rch08e3aa3e2015-05-16 14:27:52815 SequencedSocketData data(reads, arraysize(reads), writes,
816 arraysize(writes));
[email protected]c9c6f5c2010-07-31 01:30:03817 HttpRequestInfo http_req = CreateGetRequest();
[email protected]c9c6f5c2010-07-31 01:30:03818
[email protected]262eec82013-03-19 21:01:36819 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
[email protected]61b4efc2012-04-27 18:12:50820 GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:57821 helper.RunToCompletion(&data);
[email protected]c9c6f5c2010-07-31 01:30:03822 TransactionHelperResult out = helper.output();
823 EXPECT_EQ(OK, out.rv);
824 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
825 EXPECT_EQ("hello!", out.response_data);
826 }
827}
828
[email protected]2bd93022010-07-17 00:58:44829// Start three gets simultaniously; making sure that multiplexed
830// streams work properly.
831
832// This can't use the TransactionHelper method, since it only
833// handles a single transaction, and finishes them as soon
834// as it launches them.
835
836// TODO(gavinp): create a working generalized TransactionHelper that
837// can allow multiple streams in flight.
838
[email protected]513963e2013-06-15 01:53:04839TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
[email protected]cdf8f7e72013-05-23 10:56:46840 scoped_ptr<SpdyFrame> req(
841 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04842 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
843 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
844 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:44845
[email protected]cdf8f7e72013-05-23 10:56:46846 scoped_ptr<SpdyFrame> req2(
847 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04848 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
849 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
850 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:44851
[email protected]cdf8f7e72013-05-23 10:56:46852 scoped_ptr<SpdyFrame> req3(
853 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04854 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
855 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
856 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44857
[email protected]1b323172011-03-01 17:50:17858 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:52859 CreateMockWrite(*req, 0),
860 CreateMockWrite(*req2, 3),
861 CreateMockWrite(*req3, 6),
[email protected]2bd93022010-07-17 00:58:44862 };
863 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52864 CreateMockRead(*resp, 1),
865 CreateMockRead(*body, 2),
866 CreateMockRead(*resp2, 4),
867 CreateMockRead(*body2, 5),
868 CreateMockRead(*resp3, 7),
869 CreateMockRead(*body3, 8),
[email protected]2bd93022010-07-17 00:58:44870
rch08e3aa3e2015-05-16 14:27:52871 CreateMockRead(*fbody, 9),
872 CreateMockRead(*fbody2, 10),
873 CreateMockRead(*fbody3, 11),
[email protected]2bd93022010-07-17 00:58:44874
rch08e3aa3e2015-05-16 14:27:52875 MockRead(ASYNC, 0, 12), // EOF
[email protected]2bd93022010-07-17 00:58:44876 };
rch08e3aa3e2015-05-16 14:27:52877 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
878 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]2bd93022010-07-17 00:58:44879
880 BoundNetLog log;
881 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36882 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50883 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:08884 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57885 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49886 // We require placeholder data because three get requests are sent out at
887 // the same time which results in three sockets being connected. The first
888 // on will negotiate SPDY and will be used for all requests.
[email protected]dd54bd82012-07-19 23:44:57889 helper.AddData(&data_placeholder);
890 helper.AddData(&data_placeholder);
[email protected]bdebd1b2010-08-09 20:18:08891 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:50892 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:08893 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:50894 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:08895 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:50896 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:44897
[email protected]49639fa2011-12-20 23:22:41898 TestCompletionCallback callback1;
899 TestCompletionCallback callback2;
900 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44901
[email protected]bdebd1b2010-08-09 20:18:08902 HttpRequestInfo httpreq1 = CreateGetRequest();
903 HttpRequestInfo httpreq2 = CreateGetRequest();
904 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:44905
[email protected]49639fa2011-12-20 23:22:41906 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08907 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41908 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08909 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41910 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08911 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:44912
[email protected]bdebd1b2010-08-09 20:18:08913 out.rv = callback1.WaitForResult();
914 ASSERT_EQ(OK, out.rv);
915 out.rv = callback3.WaitForResult();
916 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44917
[email protected]bdebd1b2010-08-09 20:18:08918 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:50919 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:08920 EXPECT_TRUE(response1->was_fetched_via_spdy);
921 out.status_line = response1->headers->GetStatusLine();
922 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:44923
[email protected]bdebd1b2010-08-09 20:18:08924 trans2->GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:44925
[email protected]bdebd1b2010-08-09 20:18:08926 out.rv = ReadTransaction(trans1.get(), &out.response_data);
927 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:44928 EXPECT_EQ(OK, out.rv);
929
[email protected]2bd93022010-07-17 00:58:44930 EXPECT_EQ(OK, out.rv);
931 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
932 EXPECT_EQ("hello!hello!", out.response_data);
933}
934
[email protected]513963e2013-06-15 01:53:04935TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
[email protected]cdf8f7e72013-05-23 10:56:46936 scoped_ptr<SpdyFrame> req(
937 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04938 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
939 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
940 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1b323172011-03-01 17:50:17941
[email protected]cdf8f7e72013-05-23 10:56:46942 scoped_ptr<SpdyFrame> req2(
943 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04944 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
945 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
946 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]1b323172011-03-01 17:50:17947
948 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:52949 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 3),
[email protected]1b323172011-03-01 17:50:17950 };
951 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:52952 CreateMockRead(*resp, 1),
953 CreateMockRead(*body, 2),
954 CreateMockRead(*resp2, 4),
955 CreateMockRead(*body2, 5),
956 CreateMockRead(*fbody, 6),
957 CreateMockRead(*fbody2, 7),
958 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:17959 };
rch08e3aa3e2015-05-16 14:27:52960 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1b323172011-03-01 17:50:17961
[email protected]d973e99a2012-02-17 21:02:36962 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
rch08e3aa3e2015-05-16 14:27:52963 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:57964 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17965
966 BoundNetLog log;
967 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36968 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50969 BoundNetLog(), GetParam(), NULL);
[email protected]1b323172011-03-01 17:50:17970 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57971 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49972 // We require placeholder data because two requests are sent out at
973 // the same time which results in two sockets being connected. The first
974 // on will negotiate SPDY and will be used for all requests.
[email protected]dd54bd82012-07-19 23:44:57975 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:17976 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:50977 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:17978 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:50979 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:17980
[email protected]49639fa2011-12-20 23:22:41981 TestCompletionCallback callback1;
982 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:17983
984 HttpRequestInfo httpreq1 = CreateGetRequest();
985 HttpRequestInfo httpreq2 = CreateGetRequest();
986
[email protected]49639fa2011-12-20 23:22:41987 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]1b323172011-03-01 17:50:17988 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41989 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]1b323172011-03-01 17:50:17990 ASSERT_EQ(ERR_IO_PENDING, out.rv);
991
992 out.rv = callback1.WaitForResult();
993 ASSERT_EQ(OK, out.rv);
994 out.rv = callback2.WaitForResult();
995 ASSERT_EQ(OK, out.rv);
996
997 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:50998 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:17999 EXPECT_TRUE(response1->was_fetched_via_spdy);
1000 out.status_line = response1->headers->GetStatusLine();
1001 out.response_info = *response1;
1002 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1003 EXPECT_EQ(OK, out.rv);
1004 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1005 EXPECT_EQ("hello!hello!", out.response_data);
1006
1007 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501008 EXPECT_TRUE(response2->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171009 EXPECT_TRUE(response2->was_fetched_via_spdy);
1010 out.status_line = response2->headers->GetStatusLine();
1011 out.response_info = *response2;
1012 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1013 EXPECT_EQ(OK, out.rv);
1014 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1015 EXPECT_EQ("hello!hello!", out.response_data);
1016
1017 helper.VerifyDataConsumed();
1018}
1019
[email protected]513963e2013-06-15 01:53:041020TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
[email protected]cdf8f7e72013-05-23 10:56:461021 scoped_ptr<SpdyFrame> req(
1022 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041023 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1024 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1025 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1b323172011-03-01 17:50:171026
[email protected]cdf8f7e72013-05-23 10:56:461027 scoped_ptr<SpdyFrame> req2(
1028 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041029 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1030 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1031 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]1b323172011-03-01 17:50:171032
1033 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521034 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 3),
[email protected]1b323172011-03-01 17:50:171035 };
1036 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521037 CreateMockRead(*resp, 1),
1038 CreateMockRead(*body, 2),
1039 CreateMockRead(*resp2, 4),
1040 CreateMockRead(*body2, 5),
1041 CreateMockRead(*fbody, 6),
1042 CreateMockRead(*fbody2, 7),
1043 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:171044 };
rch08e3aa3e2015-05-16 14:27:521045 SequencedSocketData preconnect_data(reads, arraysize(reads), writes,
1046 arraysize(writes));
[email protected]1b323172011-03-01 17:50:171047
[email protected]d973e99a2012-02-17 21:02:361048 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
[email protected]1b323172011-03-01 17:50:171049
rch08e3aa3e2015-05-16 14:27:521050 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:571051 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:171052
1053 BoundNetLog log;
1054 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361055 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501056 BoundNetLog(), GetParam(), NULL);
[email protected]1b323172011-03-01 17:50:171057 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571058 helper.AddData(&preconnect_data);
[email protected]1b323172011-03-01 17:50:171059 // We require placeholder data because 3 connections are attempted (first is
1060 // the preconnect, 2nd and 3rd are the never finished connections.
[email protected]dd54bd82012-07-19 23:44:571061 helper.AddData(&data_placeholder);
1062 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:171063
1064 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501065 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:171066 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501067 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:171068
[email protected]49639fa2011-12-20 23:22:411069 TestCompletionCallback callback1;
1070 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:171071
1072 HttpRequestInfo httpreq = CreateGetRequest();
1073
1074 // Preconnect the first.
1075 SSLConfig preconnect_ssl_config;
1076 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1077 HttpStreamFactory* http_stream_factory =
1078 helper.session()->http_stream_factory();
[email protected]d7599122014-05-24 03:37:231079 helper.session()->GetNextProtos(&preconnect_ssl_config.next_protos);
[email protected]1b323172011-03-01 17:50:171080
1081 http_stream_factory->PreconnectStreams(
[email protected]262eec82013-03-19 21:01:361082 1, httpreq, DEFAULT_PRIORITY,
1083 preconnect_ssl_config, preconnect_ssl_config);
[email protected]1b323172011-03-01 17:50:171084
[email protected]49639fa2011-12-20 23:22:411085 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
[email protected]1b323172011-03-01 17:50:171086 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411087 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
[email protected]1b323172011-03-01 17:50:171088 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1089
1090 out.rv = callback1.WaitForResult();
1091 ASSERT_EQ(OK, out.rv);
1092 out.rv = callback2.WaitForResult();
1093 ASSERT_EQ(OK, out.rv);
1094
1095 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501096 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171097 EXPECT_TRUE(response1->was_fetched_via_spdy);
1098 out.status_line = response1->headers->GetStatusLine();
1099 out.response_info = *response1;
1100 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1101 EXPECT_EQ(OK, out.rv);
1102 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1103 EXPECT_EQ("hello!hello!", out.response_data);
1104
1105 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501106 EXPECT_TRUE(response2->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171107 EXPECT_TRUE(response2->was_fetched_via_spdy);
1108 out.status_line = response2->headers->GetStatusLine();
1109 out.response_info = *response2;
1110 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1111 EXPECT_EQ(OK, out.rv);
1112 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1113 EXPECT_EQ("hello!hello!", out.response_data);
1114
1115 helper.VerifyDataConsumed();
1116}
1117
[email protected]2bd93022010-07-17 00:58:441118// Similar to ThreeGets above, however this test adds a SETTINGS
1119// frame. The SETTINGS frame is read during the IO loop waiting on
1120// the first transaction completion, and sets a maximum concurrent
1121// stream limit of 1. This means that our IO loop exists after the
1122// second transaction completes, so we can assert on read_index().
[email protected]513963e2013-06-15 01:53:041123TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:441124 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461125 scoped_ptr<SpdyFrame> req(
1126 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041127 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1128 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1129 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:441130
[email protected]cdf8f7e72013-05-23 10:56:461131 scoped_ptr<SpdyFrame> req2(
1132 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041133 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1134 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1135 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441136
[email protected]cdf8f7e72013-05-23 10:56:461137 scoped_ptr<SpdyFrame> req3(
1138 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041139 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1140 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1141 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:441142
[email protected]18b28ab2012-04-18 02:14:421143 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281144 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421145 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1146 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201147 scoped_ptr<SpdyFrame> settings_frame(
1148 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211149 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441150
[email protected]2d6728692011-03-12 01:39:551151 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521152 CreateMockWrite(*req, 0),
1153 CreateMockWrite(*settings_ack, 5),
1154 CreateMockWrite(*req2, 6),
1155 CreateMockWrite(*req3, 10),
[email protected]2bd93022010-07-17 00:58:441156 };
[email protected]2d6728692011-03-12 01:39:551157
[email protected]2bd93022010-07-17 00:58:441158 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521159 CreateMockRead(*settings_frame, 1),
1160 CreateMockRead(*resp, 2),
1161 CreateMockRead(*body, 3),
1162 CreateMockRead(*fbody, 4),
1163 CreateMockRead(*resp2, 7),
1164 CreateMockRead(*body2, 8),
1165 CreateMockRead(*fbody2, 9),
1166 CreateMockRead(*resp3, 11),
1167 CreateMockRead(*body3, 12),
1168 CreateMockRead(*fbody3, 13),
[email protected]2bd93022010-07-17 00:58:441169
rch08e3aa3e2015-05-16 14:27:521170 MockRead(ASYNC, 0, 14), // EOF
[email protected]2bd93022010-07-17 00:58:441171 };
1172
rch08e3aa3e2015-05-16 14:27:521173 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441174
1175 BoundNetLog log;
1176 TransactionHelperResult out;
1177 {
[email protected]262eec82013-03-19 21:01:361178 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501179 BoundNetLog(), GetParam(), NULL);
[email protected]2d6728692011-03-12 01:39:551180 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571181 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:081182 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501183 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081184 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501185 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081186 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:501187 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:441188
[email protected]49639fa2011-12-20 23:22:411189 TestCompletionCallback callback1;
1190 TestCompletionCallback callback2;
1191 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441192
1193 HttpRequestInfo httpreq1 = CreateGetRequest();
1194 HttpRequestInfo httpreq2 = CreateGetRequest();
1195 HttpRequestInfo httpreq3 = CreateGetRequest();
1196
[email protected]49639fa2011-12-20 23:22:411197 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]2bd93022010-07-17 00:58:441198 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]513963e2013-06-15 01:53:041199 // Run transaction 1 through quickly to force a read of our SETTINGS
1200 // frame.
[email protected]2bd93022010-07-17 00:58:441201 out.rv = callback1.WaitForResult();
[email protected]bdebd1b2010-08-09 20:18:081202 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441203
[email protected]49639fa2011-12-20 23:22:411204 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]2bd93022010-07-17 00:58:441205 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411206 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]2bd93022010-07-17 00:58:441207 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1208 out.rv = callback2.WaitForResult();
1209 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441210
1211 out.rv = callback3.WaitForResult();
1212 ASSERT_EQ(OK, out.rv);
1213
1214 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081215 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501216 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]2bd93022010-07-17 00:58:441217 EXPECT_TRUE(response1->was_fetched_via_spdy);
1218 out.status_line = response1->headers->GetStatusLine();
1219 out.response_info = *response1;
1220 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1221 EXPECT_EQ(OK, out.rv);
1222 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1223 EXPECT_EQ("hello!hello!", out.response_data);
1224
1225 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1226 out.status_line = response2->headers->GetStatusLine();
1227 out.response_info = *response2;
1228 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1229 EXPECT_EQ(OK, out.rv);
1230 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1231 EXPECT_EQ("hello!hello!", out.response_data);
1232
1233 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1234 out.status_line = response3->headers->GetStatusLine();
1235 out.response_info = *response3;
1236 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1237 EXPECT_EQ(OK, out.rv);
1238 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1239 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:261240
1241 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441242 }
1243 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441244}
1245
1246// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1247// a fourth transaction. The third and fourth transactions have
1248// different data ("hello!" vs "hello!hello!") and because of the
1249// user specified priority, we expect to see them inverted in
1250// the response from the server.
[email protected]513963e2013-06-15 01:53:041251TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:441252 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461253 scoped_ptr<SpdyFrame> req(
1254 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041255 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1256 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1257 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:441258
[email protected]cdf8f7e72013-05-23 10:56:461259 scoped_ptr<SpdyFrame> req2(
1260 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041261 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1262 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1263 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441264
[email protected]ff98d7f02012-03-22 21:44:191265 scoped_ptr<SpdyFrame> req4(
[email protected]cdf8f7e72013-05-23 10:56:461266 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
[email protected]513963e2013-06-15 01:53:041267 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1268 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:441269
[email protected]cdf8f7e72013-05-23 10:56:461270 scoped_ptr<SpdyFrame> req3(
1271 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041272 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1273 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1274 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
[email protected]2bd93022010-07-17 00:58:441275
[email protected]18b28ab2012-04-18 02:14:421276 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281277 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421278 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1279 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201280 scoped_ptr<SpdyFrame> settings_frame(
1281 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211282 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
rch08e3aa3e2015-05-16 14:27:521283 MockWrite writes[] = {
1284 CreateMockWrite(*req, 0),
1285 CreateMockWrite(*settings_ack, 5),
1286 // By making these synchronous, it guarantees that they are not *started*
1287 // before their sequence number, which in turn verifies that only a single
1288 // request is in-flight at a time.
1289 CreateMockWrite(*req2, 6, SYNCHRONOUS),
1290 CreateMockWrite(*req4, 10, SYNCHRONOUS),
1291 CreateMockWrite(*req3, 13, SYNCHRONOUS),
[email protected]2bd93022010-07-17 00:58:441292 };
1293 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521294 CreateMockRead(*settings_frame, 1),
1295 CreateMockRead(*resp, 2),
1296 CreateMockRead(*body, 3),
1297 CreateMockRead(*fbody, 4),
1298 CreateMockRead(*resp2, 7),
1299 CreateMockRead(*body2, 8),
1300 CreateMockRead(*fbody2, 9),
1301 CreateMockRead(*resp4, 11),
1302 CreateMockRead(*fbody4, 12),
1303 CreateMockRead(*resp3, 14),
1304 CreateMockRead(*body3, 15),
1305 CreateMockRead(*fbody3, 16),
[email protected]2bd93022010-07-17 00:58:441306
rch08e3aa3e2015-05-16 14:27:521307 MockRead(ASYNC, 0, 17), // EOF
[email protected]2bd93022010-07-17 00:58:441308 };
rch08e3aa3e2015-05-16 14:27:521309 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441310 BoundNetLog log;
1311 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361312 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1313 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081314 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571315 helper.AddData(&data);
rch08e3aa3e2015-05-16 14:27:521316
[email protected]bdebd1b2010-08-09 20:18:081317 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501318 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081319 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501320 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081321 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:501322 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081323 scoped_ptr<HttpNetworkTransaction> trans4(
[email protected]90499482013-06-01 00:39:501324 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:441325
[email protected]49639fa2011-12-20 23:22:411326 TestCompletionCallback callback1;
1327 TestCompletionCallback callback2;
1328 TestCompletionCallback callback3;
1329 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:441330
[email protected]bdebd1b2010-08-09 20:18:081331 HttpRequestInfo httpreq1 = CreateGetRequest();
1332 HttpRequestInfo httpreq2 = CreateGetRequest();
1333 HttpRequestInfo httpreq3 = CreateGetRequest();
1334 HttpRequestInfo httpreq4 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441335
[email protected]49639fa2011-12-20 23:22:411336 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081337 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]e0935cc2012-03-24 14:12:481338 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081339 out.rv = callback1.WaitForResult();
1340 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441341
[email protected]49639fa2011-12-20 23:22:411342 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081343 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411344 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081345 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411346 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081347 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:441348
[email protected]bdebd1b2010-08-09 20:18:081349 out.rv = callback2.WaitForResult();
1350 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441351
[email protected]bdebd1b2010-08-09 20:18:081352 out.rv = callback3.WaitForResult();
1353 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441354
[email protected]bdebd1b2010-08-09 20:18:081355 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501356 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:081357 EXPECT_TRUE(response1->was_fetched_via_spdy);
1358 out.status_line = response1->headers->GetStatusLine();
1359 out.response_info = *response1;
1360 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1361 EXPECT_EQ(OK, out.rv);
1362 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1363 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441364
[email protected]bdebd1b2010-08-09 20:18:081365 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1366 out.status_line = response2->headers->GetStatusLine();
1367 out.response_info = *response2;
1368 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1369 EXPECT_EQ(OK, out.rv);
1370 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1371 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441372
[email protected]bdebd1b2010-08-09 20:18:081373 // notice: response3 gets two hellos, response4 gets one
1374 // hello, so we know dequeuing priority was respected.
1375 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1376 out.status_line = response3->headers->GetStatusLine();
1377 out.response_info = *response3;
1378 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1379 EXPECT_EQ(OK, out.rv);
1380 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1381 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441382
[email protected]bdebd1b2010-08-09 20:18:081383 out.rv = callback4.WaitForResult();
1384 EXPECT_EQ(OK, out.rv);
1385 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1386 out.status_line = response4->headers->GetStatusLine();
1387 out.response_info = *response4;
1388 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1389 EXPECT_EQ(OK, out.rv);
1390 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1391 EXPECT_EQ("hello!", out.response_data);
1392 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441393 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441394}
1395
1396// Similar to ThreeGetsMaxConcurrrent above, however, this test
rch08e3aa3e2015-05-16 14:27:521397// deletes a session in the middle of the transaction to ensure
[email protected]2bd93022010-07-17 00:58:441398// that we properly remove pendingcreatestream objects from
1399// the spdy_session
[email protected]513963e2013-06-15 01:53:041400TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:441401 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461402 scoped_ptr<SpdyFrame> req(
1403 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041404 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1405 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1406 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:441407
[email protected]cdf8f7e72013-05-23 10:56:461408 scoped_ptr<SpdyFrame> req2(
1409 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041410 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1411 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1412 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441413
[email protected]18b28ab2012-04-18 02:14:421414 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281415 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421416 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1417 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201418 scoped_ptr<SpdyFrame> settings_frame(
1419 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211420 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441421
[email protected]d4a77c12014-05-15 20:45:211422 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521423 CreateMockWrite(*req, 0),
1424 CreateMockWrite(*settings_ack, 5),
1425 CreateMockWrite(*req2, 6),
[email protected]2bd93022010-07-17 00:58:441426 };
1427 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521428 CreateMockRead(*settings_frame, 1),
1429 CreateMockRead(*resp, 2),
1430 CreateMockRead(*body, 3),
1431 CreateMockRead(*fbody, 4),
1432 CreateMockRead(*resp2, 7),
1433 CreateMockRead(*body2, 8),
1434 CreateMockRead(*fbody2, 9),
1435 MockRead(ASYNC, 0, 10), // EOF
[email protected]2bd93022010-07-17 00:58:441436 };
1437
rch08e3aa3e2015-05-16 14:27:521438 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441439
1440 BoundNetLog log;
1441 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361442 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1443 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081444 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571445 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:081446 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501447 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081448 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501449 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081450 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:501451 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:441452
[email protected]49639fa2011-12-20 23:22:411453 TestCompletionCallback callback1;
1454 TestCompletionCallback callback2;
1455 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441456
[email protected]bdebd1b2010-08-09 20:18:081457 HttpRequestInfo httpreq1 = CreateGetRequest();
1458 HttpRequestInfo httpreq2 = CreateGetRequest();
1459 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441460
[email protected]49639fa2011-12-20 23:22:411461 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081462 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481463 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081464 out.rv = callback1.WaitForResult();
1465 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441466
[email protected]49639fa2011-12-20 23:22:411467 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081468 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411469 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081470 delete trans3.release();
1471 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1472 out.rv = callback2.WaitForResult();
1473 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441474
[email protected]bdebd1b2010-08-09 20:18:081475 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1476 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501477 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:081478 EXPECT_TRUE(response1->was_fetched_via_spdy);
1479 out.status_line = response1->headers->GetStatusLine();
1480 out.response_info = *response1;
1481 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1482 EXPECT_EQ(OK, out.rv);
1483 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1484 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441485
[email protected]bdebd1b2010-08-09 20:18:081486 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1487 ASSERT_TRUE(response2 != NULL);
1488 out.status_line = response2->headers->GetStatusLine();
1489 out.response_info = *response2;
1490 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1491 EXPECT_EQ(OK, out.rv);
1492 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1493 EXPECT_EQ("hello!hello!", out.response_data);
1494 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441495 EXPECT_EQ(OK, out.rv);
[email protected]044dcc52010-09-17 15:44:261496}
[email protected]2bd93022010-07-17 00:58:441497
[email protected]448d4ca52012-03-04 04:12:231498namespace {
1499
[email protected]044dcc52010-09-17 15:44:261500// The KillerCallback will delete the transaction on error as part of the
1501// callback.
[email protected]49639fa2011-12-20 23:22:411502class KillerCallback : public TestCompletionCallbackBase {
[email protected]044dcc52010-09-17 15:44:261503 public:
1504 explicit KillerCallback(HttpNetworkTransaction* transaction)
[email protected]49639fa2011-12-20 23:22:411505 : transaction_(transaction),
[email protected]aa249b52013-04-30 01:04:321506 callback_(base::Bind(&KillerCallback::OnComplete,
1507 base::Unretained(this))) {
[email protected]044dcc52010-09-17 15:44:261508 }
1509
dchengb03027d2014-10-21 12:00:201510 ~KillerCallback() override {}
[email protected]49639fa2011-12-20 23:22:411511
1512 const CompletionCallback& callback() const { return callback_; }
1513
[email protected]044dcc52010-09-17 15:44:261514 private:
[email protected]49639fa2011-12-20 23:22:411515 void OnComplete(int result) {
1516 if (result < 0)
1517 delete transaction_;
1518
1519 SetResult(result);
1520 }
1521
[email protected]044dcc52010-09-17 15:44:261522 HttpNetworkTransaction* transaction_;
[email protected]49639fa2011-12-20 23:22:411523 CompletionCallback callback_;
[email protected]044dcc52010-09-17 15:44:261524};
1525
[email protected]448d4ca52012-03-04 04:12:231526} // namespace
1527
[email protected]044dcc52010-09-17 15:44:261528// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1529// closes the socket while we have a pending transaction waiting for
1530// a pending stream creation. http://crbug.com/52901
[email protected]513963e2013-06-15 01:53:041531TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
[email protected]044dcc52010-09-17 15:44:261532 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461533 scoped_ptr<SpdyFrame> req(
1534 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041535 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1536 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1537 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]044dcc52010-09-17 15:44:261538
[email protected]cdf8f7e72013-05-23 10:56:461539 scoped_ptr<SpdyFrame> req2(
1540 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041541 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]044dcc52010-09-17 15:44:261542
[email protected]18b28ab2012-04-18 02:14:421543 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281544 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421545 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1546 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201547 scoped_ptr<SpdyFrame> settings_frame(
1548 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211549 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]044dcc52010-09-17 15:44:261550
[email protected]d4a77c12014-05-15 20:45:211551 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521552 CreateMockWrite(*req, 0),
1553 CreateMockWrite(*settings_ack, 5),
1554 CreateMockWrite(*req2, 6),
[email protected]044dcc52010-09-17 15:44:261555 };
1556 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521557 CreateMockRead(*settings_frame, 1),
1558 CreateMockRead(*resp, 2),
1559 CreateMockRead(*body, 3),
1560 CreateMockRead(*fin_body, 4),
1561 CreateMockRead(*resp2, 7),
1562 MockRead(ASYNC, ERR_CONNECTION_RESET, 8), // Abort!
[email protected]044dcc52010-09-17 15:44:261563 };
1564
rch08e3aa3e2015-05-16 14:27:521565 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1566 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]044dcc52010-09-17 15:44:261567
1568 BoundNetLog log;
1569 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361570 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1571 BoundNetLog(), GetParam(), NULL);
[email protected]044dcc52010-09-17 15:44:261572 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571573 helper.AddData(&data);
[email protected]044dcc52010-09-17 15:44:261574 // We require placeholder data because three get requests are sent out, so
1575 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571576 helper.AddData(&data_placeholder);
1577 helper.AddData(&data_placeholder);
[email protected]90499482013-06-01 00:39:501578 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1579 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
[email protected]262eec82013-03-19 21:01:361580 HttpNetworkTransaction* trans3(
[email protected]90499482013-06-01 00:39:501581 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]044dcc52010-09-17 15:44:261582
[email protected]49639fa2011-12-20 23:22:411583 TestCompletionCallback callback1;
1584 TestCompletionCallback callback2;
[email protected]044dcc52010-09-17 15:44:261585 KillerCallback callback3(trans3);
1586
1587 HttpRequestInfo httpreq1 = CreateGetRequest();
1588 HttpRequestInfo httpreq2 = CreateGetRequest();
1589 HttpRequestInfo httpreq3 = CreateGetRequest();
1590
[email protected]49639fa2011-12-20 23:22:411591 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]044dcc52010-09-17 15:44:261592 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481593 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]044dcc52010-09-17 15:44:261594 out.rv = callback1.WaitForResult();
1595 ASSERT_EQ(OK, out.rv);
1596
[email protected]49639fa2011-12-20 23:22:411597 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]044dcc52010-09-17 15:44:261598 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411599 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]044dcc52010-09-17 15:44:261600 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1601 out.rv = callback3.WaitForResult();
1602 ASSERT_EQ(ERR_ABORTED, out.rv);
1603
[email protected]044dcc52010-09-17 15:44:261604 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1605 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501606 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]044dcc52010-09-17 15:44:261607 EXPECT_TRUE(response1->was_fetched_via_spdy);
1608 out.status_line = response1->headers->GetStatusLine();
1609 out.response_info = *response1;
1610 out.rv = ReadTransaction(&trans1, &out.response_data);
1611 EXPECT_EQ(OK, out.rv);
1612
1613 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1614 ASSERT_TRUE(response2 != NULL);
1615 out.status_line = response2->headers->GetStatusLine();
1616 out.response_info = *response2;
1617 out.rv = ReadTransaction(&trans2, &out.response_data);
1618 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1619
1620 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441621}
1622
[email protected]d8ef27b2010-08-06 17:34:391623// Test that a simple PUT request works.
[email protected]513963e2013-06-15 01:53:041624TEST_P(SpdyNetworkTransactionTest, Put) {
[email protected]d8ef27b2010-08-06 17:34:391625 // Setup the request
1626 HttpRequestInfo request;
1627 request.method = "PUT";
rchebf12982015-04-10 01:15:001628 request.url = GURL(GetDefaultUrl());
[email protected]d8ef27b2010-08-06 17:34:391629
[email protected]513963e2013-06-15 01:53:041630 scoped_ptr<SpdyHeaderBlock> put_headers(
rchebf12982015-04-10 01:15:001631 spdy_util_.ConstructPutHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291632 scoped_ptr<SpdyFrame> req(
1633 spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
[email protected]d8ef27b2010-08-06 17:34:391634 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521635 CreateMockWrite(*req, 0),
[email protected]d8ef27b2010-08-06 17:34:391636 };
1637
[email protected]745aa9c2014-06-27 02:21:291638 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041639 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391640 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521641 CreateMockRead(*resp, 1),
1642 CreateMockRead(*body, 2),
1643 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391644 };
1645
rch08e3aa3e2015-05-16 14:27:521646 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361647 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501648 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571649 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391650 TransactionHelperResult out = helper.output();
1651
1652 EXPECT_EQ(OK, out.rv);
1653 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1654}
1655
1656// Test that a simple HEAD request works.
[email protected]513963e2013-06-15 01:53:041657TEST_P(SpdyNetworkTransactionTest, Head) {
[email protected]d8ef27b2010-08-06 17:34:391658 // Setup the request
1659 HttpRequestInfo request;
1660 request.method = "HEAD";
rchebf12982015-04-10 01:15:001661 request.url = GURL(GetDefaultUrl());
[email protected]d8ef27b2010-08-06 17:34:391662
[email protected]513963e2013-06-15 01:53:041663 scoped_ptr<SpdyHeaderBlock> head_headers(
rchebf12982015-04-10 01:15:001664 spdy_util_.ConstructHeadHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291665 scoped_ptr<SpdyFrame> req(
1666 spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
[email protected]d8ef27b2010-08-06 17:34:391667 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521668 CreateMockWrite(*req, 0),
[email protected]d8ef27b2010-08-06 17:34:391669 };
1670
[email protected]745aa9c2014-06-27 02:21:291671 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041672 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391673 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521674 CreateMockRead(*resp, 1),
1675 CreateMockRead(*body, 2),
1676 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391677 };
1678
rch08e3aa3e2015-05-16 14:27:521679 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361680 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501681 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571682 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391683 TransactionHelperResult out = helper.output();
1684
1685 EXPECT_EQ(OK, out.rv);
1686 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1687}
1688
[email protected]72552f02009-10-28 15:25:011689// Test that a simple POST works.
[email protected]513963e2013-06-15 01:53:041690TEST_P(SpdyNetworkTransactionTest, Post) {
rchebf12982015-04-10 01:15:001691 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1692 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041693 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141694 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521695 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141696 };
[email protected]72552f02009-10-28 15:25:011697
[email protected]513963e2013-06-15 01:53:041698 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]ff57bb82009-11-12 06:52:141699 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521700 CreateMockRead(*resp, 2),
1701 CreateMockRead(*body, 3),
1702 MockRead(ASYNC, 0, 4) // EOF
[email protected]aea80602009-09-18 00:55:081703 };
1704
rch08e3aa3e2015-05-16 14:27:521705 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361706 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501707 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571708 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471709 TransactionHelperResult out = helper.output();
[email protected]aea80602009-09-18 00:55:081710 EXPECT_EQ(OK, out.rv);
1711 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1712 EXPECT_EQ("hello!", out.response_data);
1713}
1714
[email protected]69e6b4a2012-10-18 08:03:011715// Test that a POST with a file works.
[email protected]513963e2013-06-15 01:53:041716TEST_P(SpdyNetworkTransactionTest, FilePost) {
rchebf12982015-04-10 01:15:001717 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1718 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041719 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011720 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521721 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011722 };
1723
[email protected]513963e2013-06-15 01:53:041724 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011725 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521726 CreateMockRead(*resp, 2),
1727 CreateMockRead(*body, 3),
1728 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011729 };
1730
rch08e3aa3e2015-05-16 14:27:521731 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361732 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
[email protected]69e6b4a2012-10-18 08:03:011733 BoundNetLog(), GetParam(), NULL);
1734 helper.RunToCompletion(&data);
1735 TransactionHelperResult out = helper.output();
1736 EXPECT_EQ(OK, out.rv);
1737 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1738 EXPECT_EQ("hello!", out.response_data);
1739}
1740
[email protected]999dd8c2013-11-12 06:45:541741// Test that a POST with a unreadable file fails.
1742TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1743 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521744 MockWrite(ASYNC, 0, 0) // EOF
[email protected]999dd8c2013-11-12 06:45:541745 };
1746 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521747 MockRead(ASYNC, 0, 1) // EOF
[email protected]999dd8c2013-11-12 06:45:541748 };
1749
rch08e3aa3e2015-05-16 14:27:521750 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]999dd8c2013-11-12 06:45:541751 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1752 DEFAULT_PRIORITY,
1753 BoundNetLog(), GetParam(), NULL);
1754 helper.RunPreTestSetup();
1755 helper.AddData(&data);
1756 helper.RunDefaultTest();
1757
1758 base::RunLoop().RunUntilIdle();
1759 helper.VerifyDataNotConsumed();
1760 EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1761}
1762
[email protected]69e6b4a2012-10-18 08:03:011763// Test that a complex POST works.
[email protected]513963e2013-06-15 01:53:041764TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
rchebf12982015-04-10 01:15:001765 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1766 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041767 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011768 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521769 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011770 };
1771
[email protected]513963e2013-06-15 01:53:041772 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011773 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521774 CreateMockRead(*resp, 2),
1775 CreateMockRead(*body, 3),
1776 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011777 };
1778
rch08e3aa3e2015-05-16 14:27:521779 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]69e6b4a2012-10-18 08:03:011780 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
[email protected]262eec82013-03-19 21:01:361781 DEFAULT_PRIORITY,
[email protected]69e6b4a2012-10-18 08:03:011782 BoundNetLog(), GetParam(), NULL);
1783 helper.RunToCompletion(&data);
1784 TransactionHelperResult out = helper.output();
1785 EXPECT_EQ(OK, out.rv);
1786 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1787 EXPECT_EQ("hello!", out.response_data);
1788}
1789
[email protected]0c9bf872011-03-04 17:53:221790// Test that a chunked POST works.
[email protected]513963e2013-06-15 01:53:041791TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
[email protected]513963e2013-06-15 01:53:041792 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1793 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]0c9bf872011-03-04 17:53:221794 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521795 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1),
[email protected]0c9bf872011-03-04 17:53:221796 };
1797
[email protected]513963e2013-06-15 01:53:041798 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]0c9bf872011-03-04 17:53:221799 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521800 CreateMockRead(*resp, 2),
1801 CreateMockRead(*body, 3),
1802 MockRead(ASYNC, 0, 4) // EOF
[email protected]0c9bf872011-03-04 17:53:221803 };
1804
rch08e3aa3e2015-05-16 14:27:521805 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]0c9bf872011-03-04 17:53:221806 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
[email protected]262eec82013-03-19 21:01:361807 DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501808 BoundNetLog(), GetParam(), NULL);
[email protected]34b345f92013-02-22 03:27:261809
1810 // These chunks get merged into a single frame when being sent.
1811 const int kFirstChunkSize = kUploadDataSize/2;
mmenkecbc2b712014-10-09 20:29:071812 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1813 upload_chunked_data_stream()->AppendData(
[email protected]34b345f92013-02-22 03:27:261814 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1815
[email protected]dd54bd82012-07-19 23:44:571816 helper.RunToCompletion(&data);
[email protected]0c9bf872011-03-04 17:53:221817 TransactionHelperResult out = helper.output();
1818 EXPECT_EQ(OK, out.rv);
1819 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
[email protected]34b345f92013-02-22 03:27:261820 EXPECT_EQ(kUploadData, out.response_data);
1821}
1822
1823// Test that a chunked POST works with chunks appended after transaction starts.
[email protected]513963e2013-06-15 01:53:041824TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
[email protected]513963e2013-06-15 01:53:041825 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1826 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1827 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1828 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]34b345f92013-02-22 03:27:261829 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521830 CreateMockWrite(*req, 0),
1831 CreateMockWrite(*chunk1, 1),
1832 CreateMockWrite(*chunk2, 2),
1833 CreateMockWrite(*chunk3, 3),
[email protected]34b345f92013-02-22 03:27:261834 };
1835
[email protected]513963e2013-06-15 01:53:041836 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]34b345f92013-02-22 03:27:261837 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521838 CreateMockRead(*resp, 4),
1839 CreateMockRead(*chunk1, 5),
1840 CreateMockRead(*chunk2, 6),
1841 CreateMockRead(*chunk3, 7),
1842 MockRead(ASYNC, 0, 8) // EOF
[email protected]34b345f92013-02-22 03:27:261843 };
1844
rch08e3aa3e2015-05-16 14:27:521845 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]34b345f92013-02-22 03:27:261846 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
[email protected]262eec82013-03-19 21:01:361847 DEFAULT_PRIORITY,
[email protected]34b345f92013-02-22 03:27:261848 BoundNetLog(), GetParam(), NULL);
1849
mmenkecbc2b712014-10-09 20:29:071850 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]34b345f92013-02-22 03:27:261851
1852 helper.RunPreTestSetup();
1853 helper.AddData(&data);
1854 ASSERT_TRUE(helper.StartDefaultTest());
1855
[email protected]fc9d88472013-08-14 02:31:171856 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071857 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]fc9d88472013-08-14 02:31:171858 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071859 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]34b345f92013-02-22 03:27:261860
1861 helper.FinishDefaultTest();
1862 helper.VerifyDataConsumed();
1863
1864 std::string expected_response;
1865 expected_response += kUploadData;
1866 expected_response += kUploadData;
1867 expected_response += kUploadData;
1868
1869 TransactionHelperResult out = helper.output();
1870 EXPECT_EQ(OK, out.rv);
1871 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1872 EXPECT_EQ(expected_response, out.response_data);
[email protected]0c9bf872011-03-04 17:53:221873}
1874
[email protected]a33cad2b62010-07-30 22:24:391875// Test that a POST without any post data works.
[email protected]513963e2013-06-15 01:53:041876TEST_P(SpdyNetworkTransactionTest, NullPost) {
[email protected]d2c1a97b2014-03-03 19:25:091877 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]a33cad2b62010-07-30 22:24:391878 // Setup the request
1879 HttpRequestInfo request;
1880 request.method = "POST";
rchebf12982015-04-10 01:15:001881 request.url = GURL(GetDefaultUrl());
[email protected]a33cad2b62010-07-30 22:24:391882 // Create an empty UploadData.
[email protected]329b68b2012-11-14 17:54:271883 request.upload_data_stream = NULL;
[email protected]a33cad2b62010-07-30 22:24:391884
[email protected]329b68b2012-11-14 17:54:271885 // When request.upload_data_stream is NULL for post, content-length is
[email protected]a33cad2b62010-07-30 22:24:391886 // expected to be 0.
[email protected]745aa9c2014-06-27 02:21:291887 scoped_ptr<SpdyHeaderBlock> req_block(
rchebf12982015-04-10 01:15:001888 spdy_util_.ConstructPostHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291889 scoped_ptr<SpdyFrame> req(
1890 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
[email protected]d2c1a97b2014-03-03 19:25:091891
[email protected]a33cad2b62010-07-30 22:24:391892 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521893 CreateMockWrite(*req, 0),
[email protected]a33cad2b62010-07-30 22:24:391894 };
1895
[email protected]513963e2013-06-15 01:53:041896 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1897 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]a33cad2b62010-07-30 22:24:391898 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521899 CreateMockRead(*resp, 1),
1900 CreateMockRead(*body, 2),
1901 MockRead(ASYNC, 0, 3) // EOF
[email protected]a33cad2b62010-07-30 22:24:391902 };
1903
rch08e3aa3e2015-05-16 14:27:521904 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]a33cad2b62010-07-30 22:24:391905
[email protected]262eec82013-03-19 21:01:361906 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501907 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571908 helper.RunToCompletion(&data);
[email protected]a33cad2b62010-07-30 22:24:391909 TransactionHelperResult out = helper.output();
1910 EXPECT_EQ(OK, out.rv);
1911 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1912 EXPECT_EQ("hello!", out.response_data);
1913}
1914
[email protected]edd3b0a52009-11-24 18:56:361915// Test that a simple POST works.
[email protected]513963e2013-06-15 01:53:041916TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]d2c1a97b2014-03-03 19:25:091917 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]329b68b2012-11-14 17:54:271918 // Create an empty UploadDataStream.
[email protected]b2d26cfd2012-12-11 10:36:061919 ScopedVector<UploadElementReader> element_readers;
mmenkecbc2b712014-10-09 20:29:071920 ElementsUploadDataStream stream(element_readers.Pass(), 0);
[email protected]329b68b2012-11-14 17:54:271921
[email protected]edd3b0a52009-11-24 18:56:361922 // Setup the request
1923 HttpRequestInfo request;
1924 request.method = "POST";
rchebf12982015-04-10 01:15:001925 request.url = GURL(GetDefaultUrl());
[email protected]329b68b2012-11-14 17:54:271926 request.upload_data_stream = &stream;
[email protected]edd3b0a52009-11-24 18:56:361927
[email protected]ad91dc52012-09-01 03:46:061928 const uint64 kContentLength = 0;
[email protected]d2c1a97b2014-03-03 19:25:091929
[email protected]745aa9c2014-06-27 02:21:291930 scoped_ptr<SpdyHeaderBlock> req_block(
rchebf12982015-04-10 01:15:001931 spdy_util_.ConstructPostHeaderBlock(GetDefaultUrl(), kContentLength));
[email protected]745aa9c2014-06-27 02:21:291932 scoped_ptr<SpdyFrame> req(
1933 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
[email protected]d2c1a97b2014-03-03 19:25:091934
[email protected]edd3b0a52009-11-24 18:56:361935 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:521936 CreateMockWrite(*req, 0),
[email protected]edd3b0a52009-11-24 18:56:361937 };
1938
[email protected]513963e2013-06-15 01:53:041939 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1940 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361941 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:521942 CreateMockRead(*resp, 1),
1943 CreateMockRead(*body, 2),
1944 MockRead(ASYNC, 0, 3) // EOF
[email protected]edd3b0a52009-11-24 18:56:361945 };
1946
rch08e3aa3e2015-05-16 14:27:521947 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bf2491a92009-11-29 16:39:481948
[email protected]262eec82013-03-19 21:01:361949 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1950 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571951 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471952 TransactionHelperResult out = helper.output();
[email protected]edd3b0a52009-11-24 18:56:361953 EXPECT_EQ(OK, out.rv);
1954 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1955 EXPECT_EQ("hello!", out.response_data);
1956}
1957
[email protected]35c3fc732014-02-15 00:16:071958// While we're doing a post, the server sends the reply before upload completes.
1959TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
1960 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1961 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1962 MockWrite writes[] = {
1963 CreateMockWrite(*req, 0),
1964 CreateMockWrite(*body, 3),
1965 };
1966 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]a5566f9702010-05-05 22:25:431967 MockRead reads[] = {
[email protected]35c3fc732014-02-15 00:16:071968 CreateMockRead(*resp, 1),
1969 CreateMockRead(*body, 2),
[email protected]099bc7e2013-07-18 04:19:161970 MockRead(ASYNC, 0, 4) // EOF
[email protected]a5566f9702010-05-05 22:25:431971 };
1972
[email protected]35c3fc732014-02-15 00:16:071973 // Write the request headers, and read the complete response
1974 // while still waiting for chunked request data.
[email protected]c92f4b4542012-07-26 23:53:211975 DeterministicSocketData data(reads, arraysize(reads),
1976 writes, arraysize(writes));
[email protected]35c3fc732014-02-15 00:16:071977 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1978 DEFAULT_PRIORITY,
[email protected]c92f4b4542012-07-26 23:53:211979 BoundNetLog(), GetParam(), NULL);
1980 helper.SetDeterministic();
1981 helper.RunPreTestSetup();
1982 helper.AddDeterministicData(&data);
[email protected]c92f4b4542012-07-26 23:53:211983
[email protected]35c3fc732014-02-15 00:16:071984 ASSERT_TRUE(helper.StartDefaultTest());
[email protected]c92f4b4542012-07-26 23:53:211985
[email protected]35c3fc732014-02-15 00:16:071986 // Process the request headers, SYN_REPLY, and response body.
1987 // The request body is still in flight.
1988 data.RunFor(3);
1989
1990 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
1991 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1992
1993 // Finish sending the request body.
mmenkecbc2b712014-10-09 20:29:071994 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]35c3fc732014-02-15 00:16:071995 data.RunFor(2);
1996
1997 std::string response_body;
1998 EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
1999 EXPECT_EQ(kUploadData, response_body);
2000 helper.VerifyDataConsumed();
[email protected]a5566f9702010-05-05 22:25:432001}
2002
[email protected]f9a26d72010-08-03 18:07:132003// The client upon cancellation tries to send a RST_STREAM frame. The mock
2004// socket causes the TCP write to return zero. This test checks that the client
2005// tries to queue up the RST_STREAM frame again.
[email protected]513963e2013-06-15 01:53:042006TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
[email protected]cdf8f7e72013-05-23 10:56:462007 scoped_ptr<SpdyFrame> req(
2008 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]ff98d7f02012-03-22 21:44:192009 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202010 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]f9a26d72010-08-03 18:07:132011 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:062012 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2013 MockWrite(SYNCHRONOUS, 0, 0, 2),
2014 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
[email protected]f9a26d72010-08-03 18:07:132015 };
2016
[email protected]513963e2013-06-15 01:53:042017 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f9a26d72010-08-03 18:07:132018 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:062019 CreateMockRead(*resp.get(), 1, ASYNC),
2020 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:132021 };
2022
[email protected]dd54bd82012-07-19 23:44:572023 DeterministicSocketData data(reads, arraysize(reads),
2024 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362025 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502026 BoundNetLog(), GetParam(), NULL);
[email protected]3b7828432010-08-18 18:33:272027 helper.SetDeterministic();
[email protected]f9a26d72010-08-03 18:07:132028 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572029 helper.AddDeterministicData(&data);
[email protected]f9a26d72010-08-03 18:07:132030 HttpNetworkTransaction* trans = helper.trans();
2031
[email protected]49639fa2011-12-20 23:22:412032 TestCompletionCallback callback;
2033 int rv = trans->Start(
2034 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]f9a26d72010-08-03 18:07:132035 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3b7828432010-08-18 18:33:272036
[email protected]dd54bd82012-07-19 23:44:572037 data.SetStop(2);
2038 data.Run();
[email protected]f9a26d72010-08-03 18:07:132039 helper.ResetTrans();
[email protected]dd54bd82012-07-19 23:44:572040 data.SetStop(20);
2041 data.Run();
[email protected]3b7828432010-08-18 18:33:272042
[email protected]f9a26d72010-08-03 18:07:132043 helper.VerifyDataConsumed();
2044}
2045
[email protected]93300672009-10-24 13:22:512046// Test that the transaction doesn't crash when we don't have a reply.
[email protected]513963e2013-06-15 01:53:042047TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
[email protected]513963e2013-06-15 01:53:042048 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:142049 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522050 CreateMockRead(*body, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]93300672009-10-24 13:22:512051 };
2052
rch08e3aa3e2015-05-16 14:27:522053 scoped_ptr<SpdyFrame> req(
2054 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2055 scoped_ptr<SpdyFrame> rst(
2056 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2057 MockWrite writes[] = {
2058 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
2059 };
2060 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362061 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502062 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572063 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:472064 TransactionHelperResult out = helper.output();
[email protected]2aeef782013-06-21 18:30:562065 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]93300672009-10-24 13:22:512066}
2067
[email protected]d30022352010-06-24 19:17:582068// Test that the transaction doesn't crash when we get two replies on the same
2069// stream ID. See http://crbug.com/45639.
[email protected]513963e2013-06-15 01:53:042070TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
[email protected]cdf8f7e72013-05-23 10:56:462071 scoped_ptr<SpdyFrame> req(
2072 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]2aeef782013-06-21 18:30:562073 scoped_ptr<SpdyFrame> rst(
[email protected]00b29472014-01-16 18:10:242074 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]2aeef782013-06-21 18:30:562075 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522076 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]2aeef782013-06-21 18:30:562077 };
[email protected]d30022352010-06-24 19:17:582078
[email protected]513963e2013-06-15 01:53:042079 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2080 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d30022352010-06-24 19:17:582081 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522082 CreateMockRead(*resp, 1),
2083 CreateMockRead(*resp, 2),
2084 CreateMockRead(*body, 3),
2085 MockRead(ASYNC, 0, 5) // EOF
[email protected]d30022352010-06-24 19:17:582086 };
2087
rch08e3aa3e2015-05-16 14:27:522088 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d30022352010-06-24 19:17:582089
[email protected]262eec82013-03-19 21:01:362090 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502091 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472092 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572093 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472094
2095 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:582096
[email protected]49639fa2011-12-20 23:22:412097 TestCompletionCallback callback;
2098 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]d30022352010-06-24 19:17:582099 EXPECT_EQ(ERR_IO_PENDING, rv);
2100 rv = callback.WaitForResult();
2101 EXPECT_EQ(OK, rv);
2102
2103 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a5c493b92010-08-06 23:04:292104 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:502105 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]d30022352010-06-24 19:17:582106 EXPECT_TRUE(response->was_fetched_via_spdy);
2107 std::string response_data;
[email protected]3caf5542010-07-16 15:19:472108 rv = ReadTransaction(trans, &response_data);
[email protected]d30022352010-06-24 19:17:582109 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
[email protected]3caf5542010-07-16 15:19:472110
2111 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:582112}
2113
[email protected]513963e2013-06-15 01:53:042114TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252115 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462116 scoped_ptr<SpdyFrame> req(
2117 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]5a7bb252013-02-09 00:21:052118 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202119 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252120 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522121 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
[email protected]b3503002012-03-27 04:57:252122 };
2123
2124 const char* const headers[] = {
[email protected]513963e2013-06-15 01:53:042125 "transfer-encoding", "chunked"
[email protected]b3503002012-03-27 04:57:252126 };
[email protected]513963e2013-06-15 01:53:042127 scoped_ptr<SpdyFrame> resp(
2128 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2129 scoped_ptr<SpdyFrame> body(
2130 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b3503002012-03-27 04:57:252131 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522132 CreateMockRead(*resp, 1),
2133 CreateMockRead(*body, 3),
2134 MockRead(ASYNC, 0, 4) // EOF
[email protected]b3503002012-03-27 04:57:252135 };
2136
rch08e3aa3e2015-05-16 14:27:522137 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362138 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502139 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572140 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252141 TransactionHelperResult out = helper.output();
2142 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2143
2144 helper.session()->spdy_session_pool()->CloseAllSessions();
2145 helper.VerifyDataConsumed();
2146}
2147
[email protected]513963e2013-06-15 01:53:042148TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252149 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462150 scoped_ptr<SpdyFrame> req(
2151 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]5a7bb252013-02-09 00:21:052152 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202153 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252154 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522155 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]b3503002012-03-27 04:57:252156 };
2157
[email protected]513963e2013-06-15 01:53:042158 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2159 const char* const headers[] = {
2160 "transfer-encoding", "chunked"
2161 };
2162 scoped_ptr<SpdyFrame> push(
rchebf12982015-04-10 01:15:002163 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2, 2, 1,
2164 GetDefaultUrlWithPath("/1").c_str()));
[email protected]513963e2013-06-15 01:53:042165 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b3503002012-03-27 04:57:252166 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522167 CreateMockRead(*resp, 1),
2168 CreateMockRead(*push, 2),
2169 CreateMockRead(*body, 3),
2170 MockRead(ASYNC, 0, 5) // EOF
[email protected]b3503002012-03-27 04:57:252171 };
2172
rch08e3aa3e2015-05-16 14:27:522173 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362174 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502175 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572176 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252177 TransactionHelperResult out = helper.output();
2178 EXPECT_EQ(OK, out.rv);
2179 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2180 EXPECT_EQ("hello!", out.response_data);
2181
2182 helper.session()->spdy_session_pool()->CloseAllSessions();
2183 helper.VerifyDataConsumed();
2184}
2185
[email protected]513963e2013-06-15 01:53:042186TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:382187 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462188 scoped_ptr<SpdyFrame> req(
2189 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]34437af82009-11-06 02:28:492190 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:132191 CreateMockWrite(*req),
[email protected]34437af82009-11-06 02:28:492192 };
2193
[email protected]513963e2013-06-15 01:53:042194 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]34437af82009-11-06 02:28:492195 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132196 CreateMockRead(*resp),
[email protected]34437af82009-11-06 02:28:492197 // This following read isn't used by the test, except during the
[email protected]b4c62eb2012-11-14 18:36:512198 // RunUntilIdle() call at the end since the SpdySession survives the
[email protected]3caf5542010-07-16 15:19:472199 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
[email protected]34437af82009-11-06 02:28:492200 // MockRead will do here.
[email protected]8ddf8322012-02-23 18:08:062201 MockRead(ASYNC, 0, 0) // EOF
[email protected]34437af82009-11-06 02:28:492202 };
2203
[email protected]31a2bfe2010-02-09 08:03:392204 StaticSocketDataProvider data(reads, arraysize(reads),
2205 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472206
[email protected]262eec82013-03-19 21:01:362207 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502208 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472209 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:582210 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472211 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:492212
[email protected]49639fa2011-12-20 23:22:412213 TestCompletionCallback callback;
2214 int rv = trans->Start(
2215 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]34437af82009-11-06 02:28:492216 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472217 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:492218
[email protected]30c942b2010-07-21 16:59:592219 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:492220 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:172221 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472222 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:492223}
[email protected]72552f02009-10-28 15:25:012224
[email protected]6c6ea172010-07-27 20:04:032225// Verify that the client sends a Rst Frame upon cancelling the stream.
[email protected]513963e2013-06-15 01:53:042226TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
[email protected]cdf8f7e72013-05-23 10:56:462227 scoped_ptr<SpdyFrame> req(
2228 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]ff98d7f02012-03-22 21:44:192229 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202230 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]6c6ea172010-07-27 20:04:032231 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:062232 CreateMockWrite(*req, 0, SYNCHRONOUS),
2233 CreateMockWrite(*rst, 2, SYNCHRONOUS),
[email protected]6c6ea172010-07-27 20:04:032234 };
2235
[email protected]513963e2013-06-15 01:53:042236 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]6c6ea172010-07-27 20:04:032237 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:062238 CreateMockRead(*resp, 1, ASYNC),
2239 MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:032240 };
2241
[email protected]dd54bd82012-07-19 23:44:572242 DeterministicSocketData data(reads, arraysize(reads),
[email protected]513963e2013-06-15 01:53:042243 writes, arraysize(writes));
[email protected]6c6ea172010-07-27 20:04:032244
[email protected]262eec82013-03-19 21:01:362245 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]6c6ea172010-07-27 20:04:032246 BoundNetLog(),
[email protected]61b4efc2012-04-27 18:12:502247 GetParam(), NULL);
[email protected]3b7828432010-08-18 18:33:272248 helper.SetDeterministic();
[email protected]6c6ea172010-07-27 20:04:032249 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572250 helper.AddDeterministicData(&data);
[email protected]6c6ea172010-07-27 20:04:032251 HttpNetworkTransaction* trans = helper.trans();
2252
[email protected]49639fa2011-12-20 23:22:412253 TestCompletionCallback callback;
[email protected]6c6ea172010-07-27 20:04:032254
[email protected]49639fa2011-12-20 23:22:412255 int rv = trans->Start(
2256 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]6c6ea172010-07-27 20:04:032257 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]6c6ea172010-07-27 20:04:032258
[email protected]dd54bd82012-07-19 23:44:572259 data.SetStop(2);
2260 data.Run();
[email protected]3b7828432010-08-18 18:33:272261 helper.ResetTrans();
[email protected]dd54bd82012-07-19 23:44:572262 data.SetStop(20);
2263 data.Run();
[email protected]3b7828432010-08-18 18:33:272264
[email protected]6c6ea172010-07-27 20:04:032265 helper.VerifyDataConsumed();
2266}
2267
[email protected]b278eb72010-07-09 20:17:002268// Verify that the client can correctly deal with the user callback attempting
2269// to start another transaction on a session that is closing down. See
2270// http://crbug.com/47455
[email protected]513963e2013-06-15 01:53:042271TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
[email protected]cdf8f7e72013-05-23 10:56:462272 scoped_ptr<SpdyFrame> req(
2273 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:522274 MockWrite writes[] = {CreateMockWrite(*req)};
2275 MockWrite writes2[] = {CreateMockWrite(*req, 0)};
[email protected]b278eb72010-07-09 20:17:002276
[email protected]cbdd73162013-03-18 23:27:332277 // The indicated length of this frame is longer than its actual length. When
2278 // the session receives an empty frame after this one, it shuts down the
[email protected]b278eb72010-07-09 20:17:002279 // session, and calls the read callback with the incomplete data.
2280 const uint8 kGetBodyFrame2[] = {
2281 0x00, 0x00, 0x00, 0x01,
2282 0x01, 0x00, 0x00, 0x07,
2283 'h', 'e', 'l', 'l', 'o', '!',
2284 };
2285
[email protected]513963e2013-06-15 01:53:042286 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]b278eb72010-07-09 20:17:002287 MockRead reads[] = {
rch32320842015-05-16 15:57:092288 CreateMockRead(*resp, 1),
2289 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2290 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2291 arraysize(kGetBodyFrame2), 3),
2292 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
2293 MockRead(ASYNC, 0, 0, 5), // EOF
[email protected]b278eb72010-07-09 20:17:002294 };
2295 MockRead reads2[] = {
rch08e3aa3e2015-05-16 14:27:522296 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 0, 2), // EOF
[email protected]b278eb72010-07-09 20:17:002297 };
2298
rch32320842015-05-16 15:57:092299 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
rch08e3aa3e2015-05-16 14:27:522300 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2301 arraysize(writes2));
[email protected]3caf5542010-07-16 15:19:472302
[email protected]262eec82013-03-19 21:01:362303 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502304 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582305 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572306 helper.AddData(&data);
2307 helper.AddData(&data2);
[email protected]3caf5542010-07-16 15:19:472308 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002309
2310 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412311 TestCompletionCallback callback;
2312 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]b278eb72010-07-09 20:17:002313 EXPECT_EQ(ERR_IO_PENDING, rv);
2314 rv = callback.WaitForResult();
2315
[email protected]b278eb72010-07-09 20:17:002316 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162317 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412318 rv = trans->Read(
rchebf12982015-04-10 01:15:002319 buf.get(), kSize,
[email protected]513963e2013-06-15 01:53:042320 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
rchebf12982015-04-10 01:15:002321 helper.session(), GURL(GetDefaultUrl())));
rch32320842015-05-16 15:57:092322 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472323 // This forces an err_IO_pending, which sets the callback.
[email protected]dd54bd82012-07-19 23:44:572324 data.CompleteRead();
[email protected]3caf5542010-07-16 15:19:472325 // This finishes the read.
[email protected]dd54bd82012-07-19 23:44:572326 data.CompleteRead();
[email protected]3caf5542010-07-16 15:19:472327 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002328}
2329
[email protected]9be804c82010-06-24 17:59:462330// Verify that the client can correctly deal with the user callback deleting the
2331// transaction. Failures will usually be valgrind errors. See
2332// http://crbug.com/46925
[email protected]513963e2013-06-15 01:53:042333TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
[email protected]cdf8f7e72013-05-23 10:56:462334 scoped_ptr<SpdyFrame> req(
2335 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch32320842015-05-16 15:57:092336 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]9be804c82010-06-24 17:59:462337
[email protected]513963e2013-06-15 01:53:042338 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2339 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462340 MockRead reads[] = {
rch32320842015-05-16 15:57:092341 CreateMockRead(*resp.get(), 1),
2342 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
2343 CreateMockRead(*body.get(), 3),
2344 MockRead(ASYNC, 0, 0, 4), // EOF
[email protected]9be804c82010-06-24 17:59:462345 };
2346
rch32320842015-05-16 15:57:092347 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472348
[email protected]262eec82013-03-19 21:01:362349 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502350 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472351 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572352 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472353 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462354
2355 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412356 TestCompletionCallback callback;
2357 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]9be804c82010-06-24 17:59:462358 EXPECT_EQ(ERR_IO_PENDING, rv);
2359 rv = callback.WaitForResult();
2360
2361 // Setup a user callback which will delete the session, and clear out the
2362 // memory holding the stream object. Note that the callback deletes trans.
[email protected]9be804c82010-06-24 17:59:462363 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162364 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412365 rv = trans->Read(
[email protected]90499482013-06-01 00:39:502366 buf.get(),
2367 kSize,
[email protected]513963e2013-06-15 01:53:042368 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
[email protected]49639fa2011-12-20 23:22:412369 base::Unretained(&helper)));
[email protected]9be804c82010-06-24 17:59:462370 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:572371 data.CompleteRead();
[email protected]9be804c82010-06-24 17:59:462372
2373 // Finish running rest of tasks.
[email protected]fc9d88472013-08-14 02:31:172374 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472375 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462376}
2377
bncce36dca22015-04-21 22:11:232378// Send a spdy request to www.example.org that gets redirected to www.foo.com.
rchebf12982015-04-10 01:15:002379TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectGetRequest) {
[email protected]513963e2013-06-15 01:53:042380 scoped_ptr<SpdyHeaderBlock> headers(
rchebf12982015-04-10 01:15:002381 spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
[email protected]513963e2013-06-15 01:53:042382 (*headers)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062383 (*headers)["accept-encoding"] = "gzip, deflate";
[email protected]513963e2013-06-15 01:53:042384 scoped_ptr<SpdyHeaderBlock> headers2(
2385 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2386 (*headers2)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062387 (*headers2)["accept-encoding"] = "gzip, deflate";
[email protected]e3ebba0f2010-08-05 17:59:582388
bncce36dca22015-04-21 22:11:232389 // Setup writes/reads to www.example.org
[email protected]745aa9c2014-06-27 02:21:292390 scoped_ptr<SpdyFrame> req(
2391 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2392 scoped_ptr<SpdyFrame> req2(
2393 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042394 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
[email protected]e3ebba0f2010-08-05 17:59:582395 MockWrite writes[] = {
2396 CreateMockWrite(*req, 1),
2397 };
2398 MockRead reads[] = {
2399 CreateMockRead(*resp, 2),
[email protected]8ddf8322012-02-23 18:08:062400 MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582401 };
2402
2403 // Setup writes/reads to www.foo.com
[email protected]513963e2013-06-15 01:53:042404 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2405 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582406 MockWrite writes2[] = {
2407 CreateMockWrite(*req2, 1),
2408 };
2409 MockRead reads2[] = {
2410 CreateMockRead(*resp2, 2),
2411 CreateMockRead(*body2, 3),
[email protected]8ddf8322012-02-23 18:08:062412 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582413 };
rch08e3aa3e2015-05-16 14:27:522414 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2415 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2416 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582417
2418 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582419 TestDelegate d;
2420 {
rchebf12982015-04-10 01:15:002421 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
davidben151423e2015-03-23 18:48:362422 scoped_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002423 GURL(GetDefaultUrl()), DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092424 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572425 AddSocketDataProvider(&data);
[email protected]ef2bf422012-05-11 03:27:092426 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572427 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582428
2429 d.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192430 r->Start();
[email protected]fc9d88472013-08-14 02:31:172431 base::RunLoop().Run();
[email protected]513963e2013-06-15 01:53:042432
[email protected]e3ebba0f2010-08-05 17:59:582433 EXPECT_EQ(1, d.received_redirect_count());
2434
[email protected]f7022f32014-08-21 16:32:192435 r->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172436 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582437 EXPECT_EQ(1, d.response_started_count());
2438 EXPECT_FALSE(d.received_data_before_response());
bnc301745a2015-03-10 03:22:162439 EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582440 std::string contents("hello!");
2441 EXPECT_EQ(contents, d.data_received());
2442 }
rchb6dc73572015-05-08 04:01:072443 EXPECT_TRUE(data.at_read_eof());
2444 EXPECT_TRUE(data.at_write_eof());
2445 EXPECT_TRUE(data2.at_read_eof());
2446 EXPECT_TRUE(data2.at_write_eof());
[email protected]e3ebba0f2010-08-05 17:59:582447}
2448
bncce36dca22015-04-21 22:11:232449// Send a spdy request to www.example.org. Get a pushed stream that redirects to
[email protected]e3ebba0f2010-08-05 17:59:582450// www.foo.com.
rchebf12982015-04-10 01:15:002451TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
[email protected]513963e2013-06-15 01:53:042452 scoped_ptr<SpdyHeaderBlock> headers(
rchebf12982015-04-10 01:15:002453 spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
[email protected]513963e2013-06-15 01:53:042454 (*headers)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062455 (*headers)["accept-encoding"] = "gzip, deflate";
[email protected]3a8d6852011-03-11 23:43:442456
bncce36dca22015-04-21 22:11:232457 // Setup writes/reads to www.example.org
[email protected]ff98d7f02012-03-22 21:44:192458 scoped_ptr<SpdyFrame> req(
[email protected]745aa9c2014-06-27 02:21:292459 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042460 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002461 scoped_ptr<SpdyFrame> rep(spdy_util_.ConstructSpdyPush(
2462 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
2463 "301 Moved Permanently", "http://www.foo.com/index.php"));
[email protected]513963e2013-06-15 01:53:042464 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202465 scoped_ptr<SpdyFrame> rst(
2466 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]3a8d6852011-03-11 23:43:442467 MockWrite writes[] = {
2468 CreateMockWrite(*req, 1),
2469 CreateMockWrite(*rst, 6),
2470 };
2471 MockRead reads[] = {
2472 CreateMockRead(*resp, 2),
2473 CreateMockRead(*rep, 3),
2474 CreateMockRead(*body, 4),
[email protected]8ddf8322012-02-23 18:08:062475 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2476 MockRead(ASYNC, 0, 0, 7) // EOF
[email protected]3a8d6852011-03-11 23:43:442477 };
2478
2479 // Setup writes/reads to www.foo.com
[email protected]513963e2013-06-15 01:53:042480 scoped_ptr<SpdyHeaderBlock> headers2(
2481 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2482 (*headers2)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062483 (*headers2)["accept-encoding"] = "gzip, deflate";
[email protected]ff98d7f02012-03-22 21:44:192484 scoped_ptr<SpdyFrame> req2(
[email protected]745aa9c2014-06-27 02:21:292485 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042486 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2487 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582488 MockWrite writes2[] = {
2489 CreateMockWrite(*req2, 1),
2490 };
2491 MockRead reads2[] = {
2492 CreateMockRead(*resp2, 2),
2493 CreateMockRead(*body2, 3),
[email protected]8ddf8322012-02-23 18:08:062494 MockRead(ASYNC, 0, 0, 5) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582495 };
rch08e3aa3e2015-05-16 14:27:522496 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2497 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2498 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582499
2500 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582501 TestDelegate d;
2502 TestDelegate d2;
rchebf12982015-04-10 01:15:002503 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
[email protected]e3ebba0f2010-08-05 17:59:582504 {
davidben151423e2015-03-23 18:48:362505 scoped_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002506 GURL(GetDefaultUrl()), DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092507 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572508 AddSocketDataProvider(&data);
[email protected]e3ebba0f2010-08-05 17:59:582509
[email protected]f7022f32014-08-21 16:32:192510 r->Start();
[email protected]fc9d88472013-08-14 02:31:172511 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582512
2513 EXPECT_EQ(0, d.received_redirect_count());
2514 std::string contents("hello!");
2515 EXPECT_EQ(contents, d.data_received());
2516
davidben151423e2015-03-23 18:48:362517 scoped_ptr<URLRequest> r2(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002518 GURL(GetDefaultUrlWithPath("/foo.dat")), DEFAULT_PRIORITY, &d2));
[email protected]ef2bf422012-05-11 03:27:092519 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572520 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582521
2522 d2.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192523 r2->Start();
[email protected]fc9d88472013-08-14 02:31:172524 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582525 EXPECT_EQ(1, d2.received_redirect_count());
2526
[email protected]f7022f32014-08-21 16:32:192527 r2->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172528 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582529 EXPECT_EQ(1, d2.response_started_count());
2530 EXPECT_FALSE(d2.received_data_before_response());
bnc301745a2015-03-10 03:22:162531 EXPECT_EQ(URLRequestStatus::SUCCESS, r2->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582532 std::string contents2("hello!");
2533 EXPECT_EQ(contents2, d2.data_received());
2534 }
rch08e3aa3e2015-05-16 14:27:522535 EXPECT_TRUE(data.AllReadDataConsumed());
2536 EXPECT_TRUE(data.AllWriteDataConsumed());
2537 EXPECT_TRUE(data2.AllReadDataConsumed());
2538 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582539}
2540
[email protected]513963e2013-06-15 01:53:042541TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
[email protected]cdf8f7e72013-05-23 10:56:462542 scoped_ptr<SpdyFrame> stream1_syn(
2543 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042544 scoped_ptr<SpdyFrame> stream1_body(
2545 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582546 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522547 CreateMockWrite(*stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582548 };
2549
[email protected]ff98d7f02012-03-22 21:44:192550 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042551 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002552 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2553 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432554 const char kPushedData[] = "pushed";
2555 scoped_ptr<SpdyFrame> stream2_body(
2556 spdy_util_.ConstructSpdyBodyFrame(
2557 2, kPushedData, strlen(kPushedData), true));
[email protected]e3ebba0f2010-08-05 17:59:582558 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522559 CreateMockRead(*stream1_reply, 1),
2560 CreateMockRead(*stream2_syn, 2),
2561 CreateMockRead(*stream1_body, 3, SYNCHRONOUS),
2562 CreateMockRead(*stream2_body, 4),
2563 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582564 };
2565
2566 HttpResponseInfo response;
2567 HttpResponseInfo response2;
[email protected]19ec8a72010-08-23 03:38:232568 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522569 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572570 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032571 &response,
2572 &response2,
2573 expected_push_result);
[email protected]e3ebba0f2010-08-05 17:59:582574
2575 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502576 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582577 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2578
2579 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502580 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582581 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2582}
2583
[email protected]513963e2013-06-15 01:53:042584TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
[email protected]cdf8f7e72013-05-23 10:56:462585 scoped_ptr<SpdyFrame> stream1_syn(
2586 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042587 scoped_ptr<SpdyFrame> stream1_body(
2588 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]a5b8eb29d2012-03-06 06:19:462589 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522590 CreateMockWrite(*stream1_syn, 0),
[email protected]a5b8eb29d2012-03-06 06:19:462591 };
2592
[email protected]ff98d7f02012-03-22 21:44:192593 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042594 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002595 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2596 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432597 const char kPushedData[] = "pushed";
2598 scoped_ptr<SpdyFrame> stream2_body(
2599 spdy_util_.ConstructSpdyBodyFrame(
2600 2, kPushedData, strlen(kPushedData), true));
[email protected]a5b8eb29d2012-03-06 06:19:462601 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522602 CreateMockRead(*stream2_syn, 1),
2603 CreateMockRead(*stream1_reply, 2),
2604 CreateMockRead(*stream1_body, 3, SYNCHRONOUS),
2605 CreateMockRead(*stream2_body, 4),
2606 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]a5b8eb29d2012-03-06 06:19:462607 };
2608
2609 HttpResponseInfo response;
2610 HttpResponseInfo response2;
2611 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522612 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572613 RunServerPushTest(&data,
[email protected]a5b8eb29d2012-03-06 06:19:462614 &response,
2615 &response2,
2616 expected_push_result);
2617
2618 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502619 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]a5b8eb29d2012-03-06 06:19:462620 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2621
2622 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502623 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]a5b8eb29d2012-03-06 06:19:462624 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2625}
2626
[email protected]513963e2013-06-15 01:53:042627TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
[email protected]cdf8f7e72013-05-23 10:56:462628 scoped_ptr<SpdyFrame> stream1_syn(
2629 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:522630 MockWrite writes[] = {
2631 CreateMockWrite(*stream1_syn, 0),
2632 };
[email protected]82918cc2010-08-25 17:24:502633
[email protected]ff98d7f02012-03-22 21:44:192634 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042635 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002636 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2637 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432638 const char kPushedData[] = "pushed";
2639 scoped_ptr<SpdyFrame> stream2_body(
2640 spdy_util_.ConstructSpdyBodyFrame(
2641 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:192642 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042643 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]82918cc2010-08-25 17:24:502644 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522645 CreateMockRead(*stream1_reply, 1),
2646 CreateMockRead(*stream2_syn, 2),
2647 CreateMockRead(*stream2_body, 3),
2648 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2649 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]82918cc2010-08-25 17:24:502650 };
2651
2652 HttpResponseInfo response;
2653 HttpResponseInfo response2;
2654 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522655 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572656 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032657 &response,
2658 &response2,
2659 expected_push_result);
[email protected]82918cc2010-08-25 17:24:502660
2661 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502662 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]82918cc2010-08-25 17:24:502663 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2664
2665 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502666 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]82918cc2010-08-25 17:24:502667 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2668}
2669
[email protected]513963e2013-06-15 01:53:042670TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
[email protected]cdf8f7e72013-05-23 10:56:462671 scoped_ptr<SpdyFrame> stream1_syn(
2672 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042673 scoped_ptr<SpdyFrame> stream1_body(
2674 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582675 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522676 CreateMockWrite(*stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582677 };
2678
[email protected]ff98d7f02012-03-22 21:44:192679 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042680 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002681 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2682 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]c10b20852013-05-15 21:29:202683 scoped_ptr<SpdyFrame> stream2_rst(
2684 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582685 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522686 CreateMockRead(*stream1_reply, 1),
2687 CreateMockRead(*stream2_syn, 2),
2688 CreateMockRead(*stream2_rst, 3),
2689 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2690 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582691 };
2692
rch08e3aa3e2015-05-16 14:27:522693 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362694 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502695 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582696
2697 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572698 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582699
2700 HttpNetworkTransaction* trans = helper.trans();
2701
2702 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412703 TestCompletionCallback callback;
2704 int rv = trans->Start(
2705 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:582706 EXPECT_EQ(ERR_IO_PENDING, rv);
2707 rv = callback.WaitForResult();
[email protected]19ec8a72010-08-23 03:38:232708 EXPECT_EQ(OK, rv);
2709
2710 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522711 EXPECT_TRUE(data.AllReadDataConsumed());
2712 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]19ec8a72010-08-23 03:38:232713
2714 // Verify the SYN_REPLY.
2715 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502716 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232717 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2718}
2719
[email protected]8a0fc822013-06-27 20:52:432720// Verify that we don't leak streams and that we properly send a reset
2721// if the server pushes the same stream twice.
[email protected]513963e2013-06-15 01:53:042722TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
[email protected]cdf8f7e72013-05-23 10:56:462723 scoped_ptr<SpdyFrame> stream1_syn(
2724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042725 scoped_ptr<SpdyFrame> stream1_body(
2726 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202727 scoped_ptr<SpdyFrame> stream3_rst(
2728 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
[email protected]fdc165a2010-09-03 03:51:292729 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522730 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream3_rst, 4),
[email protected]fdc165a2010-09-03 03:51:292731 };
2732
[email protected]ff98d7f02012-03-22 21:44:192733 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042734 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002735 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2736 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432737 const char kPushedData[] = "pushed";
2738 scoped_ptr<SpdyFrame> stream2_body(
2739 spdy_util_.ConstructSpdyBodyFrame(
2740 2, kPushedData, strlen(kPushedData), true));
rchebf12982015-04-10 01:15:002741 scoped_ptr<SpdyFrame> stream3_syn(spdy_util_.ConstructSpdyPush(
2742 NULL, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]fdc165a2010-09-03 03:51:292743 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522744 CreateMockRead(*stream1_reply, 1),
2745 CreateMockRead(*stream2_syn, 2),
2746 CreateMockRead(*stream3_syn, 3),
2747 CreateMockRead(*stream1_body, 5),
2748 CreateMockRead(*stream2_body, 6),
2749 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7), // Force a pause
[email protected]fdc165a2010-09-03 03:51:292750 };
2751
2752 HttpResponseInfo response;
2753 HttpResponseInfo response2;
2754 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:522755 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572756 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032757 &response,
2758 &response2,
2759 expected_push_result);
[email protected]fdc165a2010-09-03 03:51:292760
2761 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502762 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]fdc165a2010-09-03 03:51:292763 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2764
2765 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502766 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]fdc165a2010-09-03 03:51:292767 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2768}
2769
[email protected]513963e2013-06-15 01:53:042770TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
[email protected]cdf8f7e72013-05-23 10:56:462771 scoped_ptr<SpdyFrame> stream1_syn(
2772 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042773 scoped_ptr<SpdyFrame> stream1_body(
2774 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232775 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522776 CreateMockWrite(*stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232777 };
2778
[email protected]ff98d7f02012-03-22 21:44:192779 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042780 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002781 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2782 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432783 static const char kPushedData[] = "pushed my darling hello my baby";
2784 scoped_ptr<SpdyFrame> stream2_body_base(
2785 spdy_util_.ConstructSpdyBodyFrame(
2786 2, kPushedData, strlen(kPushedData), true));
2787 const size_t kChunkSize = strlen(kPushedData) / 4;
2788 scoped_ptr<SpdyFrame> stream2_body1(
2789 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2790 scoped_ptr<SpdyFrame> stream2_body2(
2791 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2792 scoped_ptr<SpdyFrame> stream2_body3(
2793 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2794 kChunkSize, false));
2795 scoped_ptr<SpdyFrame> stream2_body4(
2796 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2797 stream2_body_base->size() - 3 * kChunkSize, false));
[email protected]19ec8a72010-08-23 03:38:232798 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522799 CreateMockRead(*stream1_reply, 1),
2800 CreateMockRead(*stream2_syn, 2),
2801 CreateMockRead(*stream2_body1, 3),
2802 CreateMockRead(*stream2_body2, 4),
2803 CreateMockRead(*stream2_body3, 5),
2804 CreateMockRead(*stream2_body4, 6),
2805 CreateMockRead(*stream1_body, 7, SYNCHRONOUS),
2806 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), // Force a pause
[email protected]19ec8a72010-08-23 03:38:232807 };
2808
2809 HttpResponseInfo response;
2810 HttpResponseInfo response2;
2811 std::string expected_push_result("pushed my darling hello my baby");
rch08e3aa3e2015-05-16 14:27:522812 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432813 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232814
2815 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502816 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232817 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2818
2819 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502820 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232821 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2822}
2823
[email protected]513963e2013-06-15 01:53:042824TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
[email protected]cdf8f7e72013-05-23 10:56:462825 scoped_ptr<SpdyFrame> stream1_syn(
2826 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042827 scoped_ptr<SpdyFrame> stream1_body(
2828 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232829 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522830 CreateMockWrite(*stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232831 };
2832
[email protected]ff98d7f02012-03-22 21:44:192833 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042834 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002835 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2836 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432837 static const char kPushedData[] = "pushed my darling hello my baby";
2838 scoped_ptr<SpdyFrame> stream2_body_base(
2839 spdy_util_.ConstructSpdyBodyFrame(
2840 2, kPushedData, strlen(kPushedData), true));
2841 const size_t kChunkSize = strlen(kPushedData) / 4;
2842 scoped_ptr<SpdyFrame> stream2_body1(
2843 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2844 scoped_ptr<SpdyFrame> stream2_body2(
2845 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2846 scoped_ptr<SpdyFrame> stream2_body3(
2847 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2848 kChunkSize, false));
2849 scoped_ptr<SpdyFrame> stream2_body4(
2850 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2851 stream2_body_base->size() - 3 * kChunkSize, false));
[email protected]19ec8a72010-08-23 03:38:232852 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522853 CreateMockRead(*stream1_reply, 1),
2854 CreateMockRead(*stream2_syn, 2),
2855 CreateMockRead(*stream2_body1, 3),
2856 CreateMockRead(*stream2_body2, 4),
2857 CreateMockRead(*stream2_body3, 5),
2858 CreateMockRead(*stream2_body4, 6),
2859 CreateMockRead(*stream1_body.get(), 7, SYNCHRONOUS),
2860 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8) // Force a pause.
[email protected]19ec8a72010-08-23 03:38:232861 };
2862
2863 HttpResponseInfo response;
2864 HttpResponseInfo response2;
rch08e3aa3e2015-05-16 14:27:522865 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432866 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232867
2868 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502869 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232870 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2871
2872 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502873 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232874 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2875}
2876
[email protected]513963e2013-06-15 01:53:042877TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
[email protected]00b29472014-01-16 18:10:242878 if (spdy_util_.spdy_version() == SPDY4) {
[email protected]0338bc62014-06-20 17:09:562879 // PUSH_PROMISE with stream id 0 is connection-level error.
2880 // TODO(baranovich): Test session going away.
[email protected]00b29472014-01-16 18:10:242881 return;
2882 }
[email protected]0338bc62014-06-20 17:09:562883
[email protected]cdf8f7e72013-05-23 10:56:462884 scoped_ptr<SpdyFrame> stream1_syn(
2885 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042886 scoped_ptr<SpdyFrame> stream1_body(
2887 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202888 scoped_ptr<SpdyFrame> stream2_rst(
2889 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]19ec8a72010-08-23 03:38:232890 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522891 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]19ec8a72010-08-23 03:38:232892 };
2893
[email protected]ff98d7f02012-03-22 21:44:192894 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042895 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002896 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2897 NULL, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]19ec8a72010-08-23 03:38:232898 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522899 CreateMockRead(*stream1_reply, 1),
2900 CreateMockRead(*stream2_syn, 2),
2901 CreateMockRead(*stream1_body, 4),
2902 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]19ec8a72010-08-23 03:38:232903 };
2904
rch08e3aa3e2015-05-16 14:27:522905 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362906 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502907 BoundNetLog(), GetParam(), NULL);
[email protected]19ec8a72010-08-23 03:38:232908
2909 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572910 helper.AddData(&data);
[email protected]19ec8a72010-08-23 03:38:232911
2912 HttpNetworkTransaction* trans = helper.trans();
2913
2914 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412915 TestCompletionCallback callback;
2916 int rv = trans->Start(
2917 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]19ec8a72010-08-23 03:38:232918 EXPECT_EQ(ERR_IO_PENDING, rv);
2919 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:582920 EXPECT_EQ(OK, rv);
2921
2922 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522923 EXPECT_TRUE(data.AllReadDataConsumed());
2924 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582925
2926 // Verify the SYN_REPLY.
2927 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502928 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582929 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2930}
2931
[email protected]513963e2013-06-15 01:53:042932TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
[email protected]cdf8f7e72013-05-23 10:56:462933 scoped_ptr<SpdyFrame> stream1_syn(
2934 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042935 scoped_ptr<SpdyFrame> stream1_body(
2936 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202937 scoped_ptr<SpdyFrame> stream2_rst(
2938 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
[email protected]e3ebba0f2010-08-05 17:59:582939 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522940 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582941 };
2942
[email protected]ff98d7f02012-03-22 21:44:192943 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042944 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002945 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2946 NULL, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]e3ebba0f2010-08-05 17:59:582947 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:522948 CreateMockRead(*stream1_reply, 1),
2949 CreateMockRead(*stream2_syn, 2),
2950 CreateMockRead(*stream1_body, 4),
2951 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582952 };
2953
rch08e3aa3e2015-05-16 14:27:522954 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362955 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502956 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582957
2958 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572959 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582960
2961 HttpNetworkTransaction* trans = helper.trans();
2962
2963 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412964 TestCompletionCallback callback;
2965 int rv = trans->Start(
2966 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:582967 EXPECT_EQ(ERR_IO_PENDING, rv);
2968 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:582969 EXPECT_EQ(OK, rv);
2970
2971 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:522972 EXPECT_TRUE(data.AllReadDataConsumed());
2973 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582974
2975 // Verify the SYN_REPLY.
2976 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502977 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582978 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2979}
2980
[email protected]513963e2013-06-15 01:53:042981TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
[email protected]cdf8f7e72013-05-23 10:56:462982 scoped_ptr<SpdyFrame> stream1_syn(
2983 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042984 scoped_ptr<SpdyFrame> stream1_body(
2985 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202986 scoped_ptr<SpdyFrame> stream2_rst(
2987 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582988 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:522989 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582990 };
2991
[email protected]ff98d7f02012-03-22 21:44:192992 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042993 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8b9211d2013-06-24 05:54:452994 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
2995 (*incomplete_headers)["hello"] = "bye";
2996 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
2997 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]0338bc62014-06-20 17:09:562998 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
2999 incomplete_headers.Pass(), 2, 1));
[email protected]e3ebba0f2010-08-05 17:59:583000 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523001 CreateMockRead(*stream1_reply, 1),
3002 CreateMockRead(*stream2_syn, 2),
3003 CreateMockRead(*stream1_body, 4),
3004 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:583005 };
3006
rch08e3aa3e2015-05-16 14:27:523007 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363008 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503009 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:583010
3011 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573012 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:583013
3014 HttpNetworkTransaction* trans = helper.trans();
3015
3016 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:413017 TestCompletionCallback callback;
3018 int rv = trans->Start(
3019 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:583020 EXPECT_EQ(ERR_IO_PENDING, rv);
3021 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583022 EXPECT_EQ(OK, rv);
rch08e3aa3e2015-05-16 14:27:523023
[email protected]e3ebba0f2010-08-05 17:59:583024 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:523025 EXPECT_TRUE(data.AllReadDataConsumed());
3026 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:583027
3028 // Verify the SYN_REPLY.
3029 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503030 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:583031 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3032}
3033
[email protected]8b070372009-11-16 22:01:253034// Verify that various SynReply headers parse correctly through the
3035// HTTP layer.
[email protected]513963e2013-06-15 01:53:043036TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
[email protected]e7f75092010-07-01 22:39:133037 struct SynReplyHeadersTests {
3038 int num_headers;
3039 const char* extra_headers[5];
[email protected]513963e2013-06-15 01:53:043040 SpdyHeaderBlock expected_headers;
[email protected]8b070372009-11-16 22:01:253041 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133042 // This uses a multi-valued cookie header.
3043 { 2,
3044 { "cookie", "val1",
3045 "cookie", "val2", // will get appended separated by NULL
3046 NULL
3047 },
[email protected]8b070372009-11-16 22:01:253048 },
[email protected]e7f75092010-07-01 22:39:133049 // This is the minimalist set of headers.
3050 { 0,
3051 { NULL },
[email protected]8b070372009-11-16 22:01:253052 },
[email protected]e7f75092010-07-01 22:39:133053 // Headers with a comma separated list.
3054 { 1,
3055 { "cookie", "val1,val2",
3056 NULL
3057 },
[email protected]8b070372009-11-16 22:01:253058 }
3059 };
3060
[email protected]513963e2013-06-15 01:53:043061 test_cases[0].expected_headers["cookie"] = "val1";
3062 test_cases[0].expected_headers["cookie"] += '\0';
3063 test_cases[0].expected_headers["cookie"] += "val2";
3064 test_cases[0].expected_headers["hello"] = "bye";
3065 test_cases[0].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043066
3067 test_cases[1].expected_headers["hello"] = "bye";
3068 test_cases[1].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043069
3070 test_cases[2].expected_headers["cookie"] = "val1,val2";
3071 test_cases[2].expected_headers["hello"] = "bye";
3072 test_cases[2].expected_headers["status"] = "200";
[email protected]601e03f12014-04-06 16:26:393073
3074 if (spdy_util_.spdy_version() < SPDY4) {
3075 // SPDY4/HTTP2 eliminates use of the :version header.
3076 test_cases[0].expected_headers["version"] = "HTTP/1.1";
3077 test_cases[1].expected_headers["version"] = "HTTP/1.1";
3078 test_cases[2].expected_headers["version"] = "HTTP/1.1";
3079 }
[email protected]513963e2013-06-15 01:53:043080
viettrungluue4a8b882014-10-16 06:17:383081 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193082 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463083 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523084 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8b070372009-11-16 22:01:253085
[email protected]ff98d7f02012-03-22 21:44:193086 scoped_ptr<SpdyFrame> resp(
[email protected]513963e2013-06-15 01:53:043087 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
[email protected]2bd93022010-07-17 00:58:443088 test_cases[i].num_headers,
3089 1));
[email protected]513963e2013-06-15 01:53:043090 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8b070372009-11-16 22:01:253091 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523092 CreateMockRead(*resp, 1),
3093 CreateMockRead(*body, 2),
3094 MockRead(ASYNC, 0, 3) // EOF
[email protected]8b070372009-11-16 22:01:253095 };
3096
rch08e3aa3e2015-05-16 14:27:523097 SequencedSocketData data(reads, arraysize(reads), writes,
3098 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363099 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503100 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573101 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473102 TransactionHelperResult out = helper.output();
3103
[email protected]8b070372009-11-16 22:01:253104 EXPECT_EQ(OK, out.rv);
3105 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3106 EXPECT_EQ("hello!", out.response_data);
3107
3108 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3109 EXPECT_TRUE(headers.get() != NULL);
3110 void* iter = NULL;
[email protected]513963e2013-06-15 01:53:043111 std::string name, value;
3112 SpdyHeaderBlock header_block;
[email protected]8b070372009-11-16 22:01:253113 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
[email protected]513963e2013-06-15 01:53:043114 if (header_block[name].empty()) {
3115 header_block[name] = value;
3116 } else {
3117 header_block[name] += '\0';
3118 header_block[name] += value;
3119 }
[email protected]8b070372009-11-16 22:01:253120 }
[email protected]513963e2013-06-15 01:53:043121 EXPECT_EQ(test_cases[i].expected_headers, header_block);
[email protected]8b070372009-11-16 22:01:253122 }
3123}
3124
[email protected]3f662f12010-03-25 19:56:123125// Verify that various SynReply headers parse vary fields correctly
3126// through the HTTP layer, and the response matches the request.
[email protected]513963e2013-06-15 01:53:043127TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
[email protected]3f662f12010-03-25 19:56:123128 // Modify the following data to change/add test cases:
3129 struct SynReplyTests {
[email protected]3f662f12010-03-25 19:56:123130 bool vary_matches;
3131 int num_headers[2];
3132 const char* extra_headers[2][16];
3133 } test_cases[] = {
3134 // Test the case of a multi-valued cookie. When the value is delimited
3135 // with NUL characters, it needs to be unfolded into multiple headers.
3136 {
[email protected]3f662f12010-03-25 19:56:123137 true,
[email protected]8c76ae22010-04-20 22:15:433138 { 1, 4 },
3139 { { "cookie", "val1,val2",
[email protected]3f662f12010-03-25 19:56:123140 NULL
3141 },
[email protected]513963e2013-06-15 01:53:043142 { "vary", "cookie",
3143 spdy_util_.GetStatusKey(), "200",
3144 spdy_util_.GetPathKey(), "/index.php",
3145 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123146 NULL
3147 }
3148 }
3149 }, { // Multiple vary fields.
[email protected]3f662f12010-03-25 19:56:123150 true,
3151 { 2, 5 },
3152 { { "friend", "barney",
3153 "enemy", "snaggletooth",
3154 NULL
3155 },
[email protected]513963e2013-06-15 01:53:043156 { "vary", "friend",
[email protected]3f662f12010-03-25 19:56:123157 "vary", "enemy",
[email protected]513963e2013-06-15 01:53:043158 spdy_util_.GetStatusKey(), "200",
3159 spdy_util_.GetPathKey(), "/index.php",
3160 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123161 NULL
3162 }
3163 }
3164 }, { // Test a '*' vary field.
[email protected]3f662f12010-03-25 19:56:123165 false,
3166 { 1, 4 },
3167 { { "cookie", "val1,val2",
3168 NULL
3169 },
[email protected]513963e2013-06-15 01:53:043170 { "vary", "*",
3171 spdy_util_.GetStatusKey(), "200",
3172 spdy_util_.GetPathKey(), "/index.php",
3173 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123174 NULL
3175 }
3176 }
3177 }, { // Multiple comma-separated vary fields.
[email protected]3f662f12010-03-25 19:56:123178 true,
3179 { 2, 4 },
3180 { { "friend", "barney",
3181 "enemy", "snaggletooth",
3182 NULL
3183 },
[email protected]513963e2013-06-15 01:53:043184 { "vary", "friend,enemy",
3185 spdy_util_.GetStatusKey(), "200",
3186 spdy_util_.GetPathKey(), "/index.php",
3187 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123188 NULL
3189 }
3190 }
3191 }
3192 };
3193
viettrungluue4a8b882014-10-16 06:17:383194 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]3f662f12010-03-25 19:56:123195 // Construct the request.
[email protected]ff98d7f02012-03-22 21:44:193196 scoped_ptr<SpdyFrame> frame_req(
[email protected]cdf8f7e72013-05-23 10:56:463197 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3198 test_cases[i].num_headers[0],
3199 false, 1, LOWEST, true));
[email protected]3f662f12010-03-25 19:56:123200
3201 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:523202 CreateMockWrite(*frame_req, 0),
[email protected]3f662f12010-03-25 19:56:123203 };
3204
3205 // Construct the reply.
[email protected]745aa9c2014-06-27 02:21:293206 SpdyHeaderBlock reply_headers;
3207 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3208 test_cases[i].num_headers[1],
3209 &reply_headers);
[email protected]ff98d7f02012-03-22 21:44:193210 scoped_ptr<SpdyFrame> frame_reply(
[email protected]745aa9c2014-06-27 02:21:293211 spdy_util_.ConstructSpdyReply(1, reply_headers));
[email protected]3f662f12010-03-25 19:56:123212
[email protected]513963e2013-06-15 01:53:043213 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]3f662f12010-03-25 19:56:123214 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523215 CreateMockRead(*frame_reply, 1),
3216 CreateMockRead(*body, 2),
3217 MockRead(ASYNC, 0, 3) // EOF
[email protected]3f662f12010-03-25 19:56:123218 };
3219
[email protected]3f662f12010-03-25 19:56:123220 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:433221 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:123222
[email protected]d3cee19d2010-06-22 18:42:183223 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:433224 for (int ct = 0; ct < header_count; ct++) {
3225 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3226 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3227 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:123228 }
3229
rch08e3aa3e2015-05-16 14:27:523230 SequencedSocketData data(reads, arraysize(reads), writes,
3231 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363232 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503233 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573234 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473235 TransactionHelperResult out = helper.output();
3236
[email protected]3f662f12010-03-25 19:56:123237 EXPECT_EQ(OK, out.rv) << i;
3238 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3239 EXPECT_EQ("hello!", out.response_data) << i;
3240
3241 // Test the response information.
[email protected]3f662f12010-03-25 19:56:123242 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3243 test_cases[i].vary_matches) << i;
3244
3245 // Check the headers.
3246 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3247 ASSERT_TRUE(headers.get() != NULL) << i;
3248 void* iter = NULL;
3249 std::string name, value, lines;
3250 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3251 lines.append(name);
3252 lines.append(": ");
3253 lines.append(value);
3254 lines.append("\n");
3255 }
3256
3257 // Construct the expected header reply string.
[email protected]9aa323192013-05-31 21:38:403258 std::string expected_reply =
3259 spdy_util_.ConstructSpdyReplyString(reply_headers);
3260 EXPECT_EQ(expected_reply, lines) << i;
[email protected]3f662f12010-03-25 19:56:123261 }
3262}
3263
[email protected]dd11b932009-11-30 19:39:483264// Verify that we don't crash on invalid SynReply responses.
[email protected]513963e2013-06-15 01:53:043265TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
[email protected]e7f75092010-07-01 22:39:133266 struct InvalidSynReplyTests {
3267 int num_headers;
3268 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:483269 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133270 // SYN_REPLY missing status header
3271 { 4,
3272 { "cookie", "val1",
3273 "cookie", "val2",
[email protected]513963e2013-06-15 01:53:043274 spdy_util_.GetPathKey(), "/index.php",
3275 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]e7f75092010-07-01 22:39:133276 NULL
3277 },
3278 },
3279 // SYN_REPLY missing version header
3280 { 2,
[email protected]513963e2013-06-15 01:53:043281 { "status", "200",
3282 spdy_util_.GetPathKey(), "/index.php",
[email protected]e7f75092010-07-01 22:39:133283 NULL
3284 },
3285 },
[email protected]0d384bb2010-07-14 01:51:123286 // SYN_REPLY with no headers
3287 { 0, { NULL }, },
[email protected]dd11b932009-11-30 19:39:483288 };
3289
viettrungluue4a8b882014-10-16 06:17:383290 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193291 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463292 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:413293 scoped_ptr<SpdyFrame> rst(
3294 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:483295 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:523296 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
[email protected]dd11b932009-11-30 19:39:483297 };
3298
[email protected]745aa9c2014-06-27 02:21:293299 // Construct the reply.
3300 SpdyHeaderBlock reply_headers;
3301 AppendToHeaderBlock(
3302 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
3303 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
[email protected]dd11b932009-11-30 19:39:483304 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523305 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]dd11b932009-11-30 19:39:483306 };
3307
rch08e3aa3e2015-05-16 14:27:523308 SequencedSocketData data(reads, arraysize(reads), writes,
3309 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363310 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503311 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573312 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473313 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:413314 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]dd11b932009-11-30 19:39:483315 }
3316}
3317
[email protected]94d78132010-01-22 00:53:003318// Verify that we don't crash on some corrupt frames.
[email protected]e3352df2014-03-19 05:55:423319// TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3320// connection error. I'd like to backport this behavior to SPDY3 as well.
[email protected]513963e2013-06-15 01:53:043321TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
[email protected]e3352df2014-03-19 05:55:423322 if (spdy_util_.spdy_version() >= SPDY4) {
3323 return;
3324 }
[email protected]61c83f782011-01-27 21:00:243325 // This is the length field that's too short.
[email protected]ff98d7f02012-03-22 21:44:193326 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
[email protected]513963e2013-06-15 01:53:043327 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:043328 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]8a0fc822013-06-27 20:52:433329 size_t right_size =
3330 (spdy_util_.spdy_version() < SPDY4) ?
3331 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3332 syn_reply_wrong_length->size();
3333 size_t wrong_size = right_size - 4;
[email protected]a4bfdf72013-02-22 04:06:163334 test::SetFrameLength(syn_reply_wrong_length.get(),
[email protected]8a0fc822013-06-27 20:52:433335 wrong_size,
[email protected]513963e2013-06-15 01:53:043336 spdy_util_.spdy_version());
[email protected]94d78132010-01-22 00:53:003337
3338 struct SynReplyTests {
[email protected]ff98d7f02012-03-22 21:44:193339 const SpdyFrame* syn_reply;
[email protected]94d78132010-01-22 00:53:003340 } test_cases[] = {
[email protected]61c83f782011-01-27 21:00:243341 { syn_reply_wrong_length.get(), },
[email protected]94d78132010-01-22 00:53:003342 };
3343
viettrungluue4a8b882014-10-16 06:17:383344 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193345 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463346 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]099bc7e2013-07-18 04:19:163347 scoped_ptr<SpdyFrame> rst(
3348 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3349 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:523350 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
[email protected]94d78132010-01-22 00:53:003351 };
3352
[email protected]513963e2013-06-15 01:53:043353 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003354 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523355 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size, 1),
3356 CreateMockRead(*body, 2),
3357 MockRead(ASYNC, 0, 4) // EOF
[email protected]94d78132010-01-22 00:53:003358 };
3359
rch08e3aa3e2015-05-16 14:27:523360 SequencedSocketData data(reads, arraysize(reads), writes,
3361 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363362 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503363 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573364 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473365 TransactionHelperResult out = helper.output();
[email protected]955fc2e72010-02-08 20:37:303366 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003367 }
3368}
3369
[email protected]e3352df2014-03-19 05:55:423370// SPDY4 treats a header decompression failure as a connection-level error.
3371TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
3372 if (spdy_util_.spdy_version() < SPDY4) {
3373 return;
3374 }
3375 // This is the length field that's too short.
3376 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3377 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3378 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3379 size_t right_size =
[email protected]c143f2742014-03-31 00:48:543380 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
[email protected]e3352df2014-03-19 05:55:423381 size_t wrong_size = right_size - 4;
3382 test::SetFrameLength(syn_reply_wrong_length.get(),
3383 wrong_size,
3384 spdy_util_.spdy_version());
3385
[email protected]e3352df2014-03-19 05:55:423386 scoped_ptr<SpdyFrame> req(
3387 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bdd1b222014-06-10 11:08:393388 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3389 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch08e3aa3e2015-05-16 14:27:523390 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]e3352df2014-03-19 05:55:423391
3392 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3393 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523394 MockRead(ASYNC, syn_reply_wrong_length->data(),
3395 syn_reply_wrong_length->size() - 4, 1),
[email protected]e3352df2014-03-19 05:55:423396 };
3397
rch08e3aa3e2015-05-16 14:27:523398 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]e3352df2014-03-19 05:55:423399 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3400 BoundNetLog(), GetParam(), NULL);
3401 helper.RunToCompletion(&data);
3402 TransactionHelperResult out = helper.output();
[email protected]bdd1b222014-06-10 11:08:393403 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3404}
3405
3406TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
bnc5b3dce0d2014-11-13 19:57:463407 if (GetParam().protocol < kProtoSPDY4MinimumVersion) {
[email protected]bdd1b222014-06-10 11:08:393408 // Decompression failures are a stream error in SPDY3 and above.
3409 return;
3410 }
3411 scoped_ptr<SpdyFrame> req(
3412 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3413 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3414 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch08e3aa3e2015-05-16 14:27:523415 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393416
3417 // Read HEADERS with corrupted payload.
3418 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3419 memset(resp->data() + 12, 0xff, resp->size() - 12);
rch08e3aa3e2015-05-16 14:27:523420 MockRead reads[] = {CreateMockRead(*resp, 1)};
[email protected]bdd1b222014-06-10 11:08:393421
rch08e3aa3e2015-05-16 14:27:523422 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bdd1b222014-06-10 11:08:393423 NormalSpdyTransactionHelper helper(
3424 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3425 helper.RunToCompletion(&data);
3426 TransactionHelperResult out = helper.output();
3427 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3428}
3429
3430TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3431 scoped_ptr<SpdyFrame> req(
3432 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3433 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3434 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
rch08e3aa3e2015-05-16 14:27:523435 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393436
3437 // Read WINDOW_UPDATE with incorrectly-sized payload.
3438 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3439 // which is mapped to a protocol error, and not a frame size error.
3440 scoped_ptr<SpdyFrame> bad_window_update(
3441 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3442 test::SetFrameLength(bad_window_update.get(),
3443 bad_window_update->size() - 1,
3444 spdy_util_.spdy_version());
rch08e3aa3e2015-05-16 14:27:523445 MockRead reads[] = {CreateMockRead(*bad_window_update, 1)};
[email protected]bdd1b222014-06-10 11:08:393446
rch08e3aa3e2015-05-16 14:27:523447 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bdd1b222014-06-10 11:08:393448 NormalSpdyTransactionHelper helper(
3449 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3450 helper.RunToCompletion(&data);
3451 TransactionHelperResult out = helper.output();
[email protected]e3352df2014-03-19 05:55:423452 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3453}
3454
[email protected]bf2491a92009-11-29 16:39:483455// Test that we shutdown correctly on write errors.
[email protected]513963e2013-06-15 01:53:043456TEST_P(SpdyNetworkTransactionTest, WriteError) {
[email protected]cdf8f7e72013-05-23 10:56:463457 scoped_ptr<SpdyFrame> req(
3458 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483459 MockWrite writes[] = {
[email protected]bdd1b222014-06-10 11:08:393460 // We'll write 10 bytes successfully
3461 MockWrite(ASYNC, req->data(), 10, 0),
3462 // Followed by ERROR!
3463 MockWrite(ASYNC, ERR_FAILED, 1),
3464 // Session drains and attempts to write a GOAWAY: Another ERROR!
3465 MockWrite(ASYNC, ERR_FAILED, 2),
[email protected]bf2491a92009-11-29 16:39:483466 };
3467
[email protected]238002d2013-10-17 02:01:403468 MockRead reads[] = {
[email protected]bdd1b222014-06-10 11:08:393469 MockRead(ASYNC, 0, 3) // EOF
[email protected]238002d2013-10-17 02:01:403470 };
3471
3472 DeterministicSocketData data(reads, arraysize(reads),
3473 writes, arraysize(writes));
3474
[email protected]262eec82013-03-19 21:01:363475 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503476 BoundNetLog(), GetParam(), NULL);
[email protected]238002d2013-10-17 02:01:403477 helper.SetDeterministic();
3478 helper.RunPreTestSetup();
3479 helper.AddDeterministicData(&data);
3480 EXPECT_TRUE(helper.StartDefaultTest());
3481 data.RunFor(2);
3482 helper.FinishDefaultTest();
rchb6dc73572015-05-08 04:01:073483 EXPECT_TRUE(data.at_write_eof());
3484 EXPECT_TRUE(!data.at_read_eof());
[email protected]3caf5542010-07-16 15:19:473485 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483486 EXPECT_EQ(ERR_FAILED, out.rv);
3487}
3488
3489// Test that partial writes work.
[email protected]513963e2013-06-15 01:53:043490TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
[email protected]bf2491a92009-11-29 16:39:483491 // Chop the SYN_STREAM frame into 5 chunks.
[email protected]cdf8f7e72013-05-23 10:56:463492 scoped_ptr<SpdyFrame> req(
3493 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483494 const int kChunks = 5;
[email protected]4356f0f2013-04-07 00:58:173495 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
rch08e3aa3e2015-05-16 14:27:523496 for (int i = 0; i < kChunks; ++i) {
3497 writes[i].sequence_number = i;
3498 }
[email protected]bf2491a92009-11-29 16:39:483499
[email protected]513963e2013-06-15 01:53:043500 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3501 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:483502 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523503 CreateMockRead(*resp, kChunks),
3504 CreateMockRead(*body, kChunks + 1),
3505 MockRead(ASYNC, 0, kChunks + 2) // EOF
[email protected]bf2491a92009-11-29 16:39:483506 };
3507
rch08e3aa3e2015-05-16 14:27:523508 SequencedSocketData data(reads, arraysize(reads), writes.get(), kChunks);
[email protected]262eec82013-03-19 21:01:363509 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503510 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573511 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473512 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483513 EXPECT_EQ(OK, out.rv);
3514 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3515 EXPECT_EQ("hello!", out.response_data);
3516}
3517
[email protected]94d78132010-01-22 00:53:003518// In this test, we enable compression, but get a uncompressed SynReply from
3519// the server. Verify that teardown is all clean.
[email protected]513963e2013-06-15 01:53:043520TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
[email protected]e3352df2014-03-19 05:55:423521 if (spdy_util_.spdy_version() >= SPDY4) {
3522 // HPACK doesn't use deflate compression.
3523 return;
3524 }
[email protected]ff98d7f02012-03-22 21:44:193525 scoped_ptr<SpdyFrame> compressed(
[email protected]cdf8f7e72013-05-23 10:56:463526 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
[email protected]bdd1b222014-06-10 11:08:393527 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3528 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch08e3aa3e2015-05-16 14:27:523529 MockWrite writes[] = {CreateMockWrite(*compressed, 0),
3530 CreateMockWrite(*goaway, 2)};
[email protected]94d78132010-01-22 00:53:003531
[email protected]513963e2013-06-15 01:53:043532 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3533 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003534 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523535 CreateMockRead(*resp, 1),
[email protected]94d78132010-01-22 00:53:003536 };
3537
rch08e3aa3e2015-05-16 14:27:523538 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]513963e2013-06-15 01:53:043539 SpdySessionDependencies* session_deps =
3540 CreateSpdySessionDependencies(GetParam());
[email protected]f9cf5572012-12-04 15:52:093541 session_deps->enable_compression = true;
[email protected]262eec82013-03-19 21:01:363542 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]f9cf5572012-12-04 15:52:093543 BoundNetLog(), GetParam(), session_deps);
[email protected]dd54bd82012-07-19 23:44:573544 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473545 TransactionHelperResult out = helper.output();
[email protected]bdd1b222014-06-10 11:08:393546 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
[email protected]dd54bd82012-07-19 23:44:573547 data.Reset();
[email protected]94d78132010-01-22 00:53:003548}
3549
[email protected]9e743cd2010-03-16 07:03:533550// Test that the NetLog contains good data for a simple GET request.
[email protected]513963e2013-06-15 01:53:043551TEST_P(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:403552 static const char* const kExtraHeaders[] = {
3553 "user-agent", "Chrome",
3554 };
[email protected]cdf8f7e72013-05-23 10:56:463555 scoped_ptr<SpdyFrame> req(
3556 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523557 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]dac358042009-12-18 02:07:483558
[email protected]513963e2013-06-15 01:53:043559 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3560 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]dac358042009-12-18 02:07:483561 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523562 CreateMockRead(*resp, 1),
3563 CreateMockRead(*body, 2),
3564 MockRead(ASYNC, 0, 3) // EOF
[email protected]dac358042009-12-18 02:07:483565 };
3566
vishal.b62985ca92015-04-17 08:45:513567 BoundTestNetLog log;
[email protected]dac358042009-12-18 02:07:483568
rch08e3aa3e2015-05-16 14:27:523569 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3deb9a52010-11-11 00:24:403570 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
[email protected]262eec82013-03-19 21:01:363571 DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503572 log.bound(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573573 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473574 TransactionHelperResult out = helper.output();
[email protected]dac358042009-12-18 02:07:483575 EXPECT_EQ(OK, out.rv);
3576 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3577 EXPECT_EQ("hello!", out.response_data);
3578
[email protected]9e743cd2010-03-16 07:03:533579 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:473580 // This test is intentionally non-specific about the exact ordering of the
3581 // log; instead we just check to make sure that certain events exist, and that
3582 // they are in the right order.
mmenke43758e62015-05-04 21:09:463583 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403584 log.GetEntries(&entries);
3585
3586 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:483587 int pos = 0;
bnc301745a2015-03-10 03:22:163588 pos = ExpectLogContainsSomewhere(entries, 0,
3589 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3590 NetLog::PHASE_BEGIN);
3591 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3592 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3593 NetLog::PHASE_END);
3594 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3595 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3596 NetLog::PHASE_BEGIN);
3597 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3598 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3599 NetLog::PHASE_END);
3600 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3601 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3602 NetLog::PHASE_BEGIN);
3603 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3604 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3605 NetLog::PHASE_END);
[email protected]3deb9a52010-11-11 00:24:403606
3607 // Check that we logged all the headers correctly
bnc301745a2015-03-10 03:22:163608 const NetLog::EventType type = (GetParam().protocol <= kProtoSPDY31)
3609 ? NetLog::TYPE_HTTP2_SESSION_SYN_STREAM
3610 : NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS;
3611 pos = ExpectLogContainsSomewhere(entries, 0, type, NetLog::PHASE_NONE);
[email protected]3deb9a52010-11-11 00:24:403612
[email protected]ea5ef4c2013-06-13 22:50:273613 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:573614 ASSERT_TRUE(entries[pos].params.get());
3615 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3616
3617 std::vector<std::string> expected;
bncce36dca22015-04-21 22:11:233618 expected.push_back(std::string(spdy_util_.GetHostKey()) +
3619 ": www.example.org");
[email protected]513963e2013-06-15 01:53:043620 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
rchebf12982015-04-10 01:15:003621 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": " +
3622 spdy_util_.default_url().scheme());
[email protected]513963e2013-06-15 01:53:043623 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
[email protected]f3da152d2012-06-02 01:00:573624 expected.push_back("user-agent: Chrome");
[email protected]601e03f12014-04-06 16:26:393625 if (spdy_util_.spdy_version() < SPDY4) {
3626 // SPDY4/HTTP2 eliminates use of the :version header.
3627 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3628 }
[email protected]f3da152d2012-06-02 01:00:573629 EXPECT_EQ(expected.size(), header_list->GetSize());
3630 for (std::vector<std::string>::const_iterator it = expected.begin();
3631 it != expected.end();
3632 ++it) {
3633 base::StringValue header(*it);
3634 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3635 "Header not found: " << *it;
[email protected]3deb9a52010-11-11 00:24:403636 }
[email protected]dac358042009-12-18 02:07:483637}
3638
[email protected]79d84222010-02-26 00:01:443639// Since we buffer the IO from the stream to the renderer, this test verifies
3640// that when we read out the maximum amount of data (e.g. we received 50 bytes
3641// on the network, but issued a Read for only 5 of those bytes) that the data
3642// flow still works correctly.
[email protected]513963e2013-06-15 01:53:043643TEST_P(SpdyNetworkTransactionTest, BufferFull) {
[email protected]513963e2013-06-15 01:53:043644 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433645
[email protected]cdf8f7e72013-05-23 10:56:463646 scoped_ptr<SpdyFrame> req(
3647 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523648 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]79d84222010-02-26 00:01:443649
[email protected]20d005f2010-07-02 19:55:433650 // 2 data frames in a single read.
[email protected]ff98d7f02012-03-22 21:44:193651 scoped_ptr<SpdyFrame> data_frame_1(
3652 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3653 scoped_ptr<SpdyFrame> data_frame_2(
3654 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3655 const SpdyFrame* data_frames[2] = {
[email protected]20d005f2010-07-02 19:55:433656 data_frame_1.get(),
3657 data_frame_2.get(),
[email protected]79d84222010-02-26 00:01:443658 };
[email protected]20d005f2010-07-02 19:55:433659 char combined_data_frames[100];
3660 int combined_data_frames_len =
3661 CombineFrames(data_frames, arraysize(data_frames),
3662 combined_data_frames, arraysize(combined_data_frames));
[email protected]ff98d7f02012-03-22 21:44:193663 scoped_ptr<SpdyFrame> last_frame(
3664 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
[email protected]79d84222010-02-26 00:01:443665
[email protected]513963e2013-06-15 01:53:043666 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]79d84222010-02-26 00:01:443667 MockRead reads[] = {
rch32320842015-05-16 15:57:093668 CreateMockRead(*resp, 1),
3669 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3670 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3671 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
3672 CreateMockRead(*last_frame, 5),
3673 MockRead(ASYNC, 0, 6) // EOF
[email protected]79d84222010-02-26 00:01:443674 };
3675
rch32320842015-05-16 15:57:093676 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]79d84222010-02-26 00:01:443677
[email protected]49639fa2011-12-20 23:22:413678 TestCompletionCallback callback;
[email protected]79d84222010-02-26 00:01:443679
[email protected]262eec82013-03-19 21:01:363680 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503681 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473682 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573683 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473684 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413685 int rv = trans->Start(
3686 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]79d84222010-02-26 00:01:443687 EXPECT_EQ(ERR_IO_PENDING, rv);
3688
[email protected]3caf5542010-07-16 15:19:473689 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:443690 out.rv = callback.WaitForResult();
3691 EXPECT_EQ(out.rv, OK);
3692
3693 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503694 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]79d84222010-02-26 00:01:443695 EXPECT_TRUE(response->was_fetched_via_spdy);
3696 out.status_line = response->headers->GetStatusLine();
3697 out.response_info = *response; // Make a copy so we can verify.
3698
3699 // Read Data
[email protected]49639fa2011-12-20 23:22:413700 TestCompletionCallback read_callback;
[email protected]79d84222010-02-26 00:01:443701
3702 std::string content;
3703 do {
3704 // Read small chunks at a time.
3705 const int kSmallReadSize = 3;
bnc301745a2015-03-10 03:22:163706 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503707 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163708 if (rv == ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573709 data.CompleteRead();
[email protected]79d84222010-02-26 00:01:443710 rv = read_callback.WaitForResult();
3711 }
3712 if (rv > 0) {
3713 content.append(buf->data(), rv);
3714 } else if (rv < 0) {
3715 NOTREACHED();
3716 }
3717 } while (rv > 0);
3718
3719 out.response_data.swap(content);
3720
[email protected]30c942b2010-07-21 16:59:593721 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553722 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173723 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553724
[email protected]79d84222010-02-26 00:01:443725 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473726 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:443727
3728 EXPECT_EQ(OK, out.rv);
3729 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3730 EXPECT_EQ("goodbye world", out.response_data);
3731}
3732
[email protected]8918d282010-03-02 00:57:553733// Verify that basic buffering works; when multiple data frames arrive
3734// at the same time, ensure that we don't notify a read completion for
3735// each data frame individually.
[email protected]513963e2013-06-15 01:53:043736TEST_P(SpdyNetworkTransactionTest, Buffering) {
[email protected]513963e2013-06-15 01:53:043737 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433738
[email protected]cdf8f7e72013-05-23 10:56:463739 scoped_ptr<SpdyFrame> req(
3740 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch32320842015-05-16 15:57:093741 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8918d282010-03-02 00:57:553742
3743 // 4 data frames in a single read.
[email protected]ff98d7f02012-03-22 21:44:193744 scoped_ptr<SpdyFrame> data_frame(
3745 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3746 scoped_ptr<SpdyFrame> data_frame_fin(
3747 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3748 const SpdyFrame* data_frames[4] = {
[email protected]20d005f2010-07-02 19:55:433749 data_frame.get(),
3750 data_frame.get(),
3751 data_frame.get(),
3752 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:553753 };
[email protected]20d005f2010-07-02 19:55:433754 char combined_data_frames[100];
3755 int combined_data_frames_len =
3756 CombineFrames(data_frames, arraysize(data_frames),
3757 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:553758
[email protected]513963e2013-06-15 01:53:043759 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553760 MockRead reads[] = {
rch32320842015-05-16 15:57:093761 CreateMockRead(*resp, 1),
3762 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
3763 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3764 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553765 };
3766
rch32320842015-05-16 15:57:093767 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553768
[email protected]262eec82013-03-19 21:01:363769 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503770 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473771 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573772 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473773 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553774
[email protected]49639fa2011-12-20 23:22:413775 TestCompletionCallback callback;
3776 int rv = trans->Start(
3777 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553778 EXPECT_EQ(ERR_IO_PENDING, rv);
3779
[email protected]3caf5542010-07-16 15:19:473780 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553781 out.rv = callback.WaitForResult();
3782 EXPECT_EQ(out.rv, OK);
3783
3784 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503785 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553786 EXPECT_TRUE(response->was_fetched_via_spdy);
3787 out.status_line = response->headers->GetStatusLine();
3788 out.response_info = *response; // Make a copy so we can verify.
3789
3790 // Read Data
[email protected]49639fa2011-12-20 23:22:413791 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553792
3793 std::string content;
3794 int reads_completed = 0;
3795 do {
3796 // Read small chunks at a time.
3797 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163798 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503799 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163800 if (rv == ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573801 data.CompleteRead();
[email protected]8918d282010-03-02 00:57:553802 rv = read_callback.WaitForResult();
3803 }
3804 if (rv > 0) {
3805 EXPECT_EQ(kSmallReadSize, rv);
3806 content.append(buf->data(), rv);
3807 } else if (rv < 0) {
3808 FAIL() << "Unexpected read error: " << rv;
3809 }
3810 reads_completed++;
3811 } while (rv > 0);
3812
3813 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3814
3815 out.response_data.swap(content);
3816
[email protected]30c942b2010-07-21 16:59:593817 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553818 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173819 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553820
3821 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473822 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553823
3824 EXPECT_EQ(OK, out.rv);
3825 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3826 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3827}
3828
3829// Verify the case where we buffer data but read it after it has been buffered.
[email protected]513963e2013-06-15 01:53:043830TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
[email protected]513963e2013-06-15 01:53:043831 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433832
[email protected]cdf8f7e72013-05-23 10:56:463833 scoped_ptr<SpdyFrame> req(
3834 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:523835 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8918d282010-03-02 00:57:553836
[email protected]20d005f2010-07-02 19:55:433837 // 5 data frames in a single read.
[email protected]745aa9c2014-06-27 02:21:293838 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:193839 scoped_ptr<SpdyFrame> data_frame(
3840 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3841 scoped_ptr<SpdyFrame> data_frame_fin(
3842 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
[email protected]745aa9c2014-06-27 02:21:293843 const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
3844 data_frame.get(), data_frame_fin.get()};
[email protected]20d005f2010-07-02 19:55:433845 char combined_frames[200];
3846 int combined_frames_len =
3847 CombineFrames(frames, arraysize(frames),
3848 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:553849
3850 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:523851 MockRead(ASYNC, combined_frames, combined_frames_len, 1),
3852 MockRead(ASYNC, 0, 2) // EOF
[email protected]8918d282010-03-02 00:57:553853 };
3854
rch08e3aa3e2015-05-16 14:27:523855 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553856
[email protected]262eec82013-03-19 21:01:363857 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503858 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473859 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573860 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473861 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553862
[email protected]49639fa2011-12-20 23:22:413863 TestCompletionCallback callback;
3864 int rv = trans->Start(
3865 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553866 EXPECT_EQ(ERR_IO_PENDING, rv);
3867
[email protected]3caf5542010-07-16 15:19:473868 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553869 out.rv = callback.WaitForResult();
3870 EXPECT_EQ(out.rv, OK);
3871
3872 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503873 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553874 EXPECT_TRUE(response->was_fetched_via_spdy);
3875 out.status_line = response->headers->GetStatusLine();
3876 out.response_info = *response; // Make a copy so we can verify.
3877
3878 // Read Data
[email protected]49639fa2011-12-20 23:22:413879 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553880
3881 std::string content;
3882 int reads_completed = 0;
3883 do {
3884 // Read small chunks at a time.
3885 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163886 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503887 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:553888 if (rv > 0) {
3889 EXPECT_EQ(kSmallReadSize, rv);
3890 content.append(buf->data(), rv);
3891 } else if (rv < 0) {
3892 FAIL() << "Unexpected read error: " << rv;
3893 }
3894 reads_completed++;
3895 } while (rv > 0);
3896
3897 EXPECT_EQ(3, reads_completed);
3898
3899 out.response_data.swap(content);
3900
[email protected]30c942b2010-07-21 16:59:593901 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553902 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173903 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553904
3905 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473906 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553907
3908 EXPECT_EQ(OK, out.rv);
3909 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3910 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3911}
3912
3913// Verify the case where we buffer data and close the connection.
[email protected]513963e2013-06-15 01:53:043914TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
[email protected]513963e2013-06-15 01:53:043915 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433916
[email protected]cdf8f7e72013-05-23 10:56:463917 scoped_ptr<SpdyFrame> req(
3918 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch32320842015-05-16 15:57:093919 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8918d282010-03-02 00:57:553920
3921 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:433922 // NOTE: We don't FIN the stream.
[email protected]ff98d7f02012-03-22 21:44:193923 scoped_ptr<SpdyFrame> data_frame(
3924 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3925 const SpdyFrame* data_frames[4] = {
[email protected]20d005f2010-07-02 19:55:433926 data_frame.get(),
3927 data_frame.get(),
3928 data_frame.get(),
3929 data_frame.get()
[email protected]8918d282010-03-02 00:57:553930 };
[email protected]20d005f2010-07-02 19:55:433931 char combined_data_frames[100];
3932 int combined_data_frames_len =
3933 CombineFrames(data_frames, arraysize(data_frames),
3934 combined_data_frames, arraysize(combined_data_frames));
[email protected]513963e2013-06-15 01:53:043935 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553936 MockRead reads[] = {
rch32320842015-05-16 15:57:093937 CreateMockRead(*resp, 1),
3938 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
3939 MockRead(ASYNC, combined_data_frames, combined_data_frames_len, 3),
3940 MockRead(ASYNC, 0, 4) // EOF
[email protected]8918d282010-03-02 00:57:553941 };
3942
rch32320842015-05-16 15:57:093943 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553944
[email protected]262eec82013-03-19 21:01:363945 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503946 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473947 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573948 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473949 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553950
[email protected]49639fa2011-12-20 23:22:413951 TestCompletionCallback callback;
[email protected]8918d282010-03-02 00:57:553952
[email protected]49639fa2011-12-20 23:22:413953 int rv = trans->Start(
3954 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553955 EXPECT_EQ(ERR_IO_PENDING, rv);
3956
[email protected]3caf5542010-07-16 15:19:473957 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553958 out.rv = callback.WaitForResult();
3959 EXPECT_EQ(out.rv, OK);
3960
3961 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503962 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553963 EXPECT_TRUE(response->was_fetched_via_spdy);
3964 out.status_line = response->headers->GetStatusLine();
3965 out.response_info = *response; // Make a copy so we can verify.
3966
3967 // Read Data
[email protected]49639fa2011-12-20 23:22:413968 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553969
3970 std::string content;
3971 int reads_completed = 0;
3972 do {
3973 // Read small chunks at a time.
3974 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163975 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503976 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163977 if (rv == ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573978 data.CompleteRead();
[email protected]8918d282010-03-02 00:57:553979 rv = read_callback.WaitForResult();
3980 }
3981 if (rv > 0) {
3982 content.append(buf->data(), rv);
3983 } else if (rv < 0) {
3984 // This test intentionally closes the connection, and will get an error.
3985 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
3986 break;
3987 }
3988 reads_completed++;
3989 } while (rv > 0);
3990
3991 EXPECT_EQ(0, reads_completed);
3992
3993 out.response_data.swap(content);
3994
[email protected]30c942b2010-07-21 16:59:593995 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553996 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173997 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553998
3999 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474000 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:554001}
4002
[email protected]1ed7b3dc2010-03-04 05:41:454003// Verify the case where we buffer data and cancel the transaction.
[email protected]513963e2013-06-15 01:53:044004TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
[email protected]513963e2013-06-15 01:53:044005 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:434006
[email protected]cdf8f7e72013-05-23 10:56:464007 scoped_ptr<SpdyFrame> req(
4008 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]975da41a2014-06-05 03:36:244009 scoped_ptr<SpdyFrame> rst(
4010 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
rch32320842015-05-16 15:57:094011 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
[email protected]1ed7b3dc2010-03-04 05:41:454012
[email protected]20d005f2010-07-02 19:55:434013 // NOTE: We don't FIN the stream.
[email protected]ff98d7f02012-03-22 21:44:194014 scoped_ptr<SpdyFrame> data_frame(
4015 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
[email protected]1ed7b3dc2010-03-04 05:41:454016
[email protected]513963e2013-06-15 01:53:044017 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:454018 MockRead reads[] = {
rch32320842015-05-16 15:57:094019 CreateMockRead(*resp, 1),
4020 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
4021 CreateMockRead(*data_frame, 3),
4022 MockRead(ASYNC, 0, 5) // EOF
[email protected]1ed7b3dc2010-03-04 05:41:454023 };
4024
rch32320842015-05-16 15:57:094025 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1ed7b3dc2010-03-04 05:41:454026
[email protected]262eec82013-03-19 21:01:364027 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504028 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474029 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574030 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474031 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:414032 TestCompletionCallback callback;
[email protected]1ed7b3dc2010-03-04 05:41:454033
[email protected]49639fa2011-12-20 23:22:414034 int rv = trans->Start(
4035 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]1ed7b3dc2010-03-04 05:41:454036 EXPECT_EQ(ERR_IO_PENDING, rv);
4037
[email protected]3caf5542010-07-16 15:19:474038 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:454039 out.rv = callback.WaitForResult();
4040 EXPECT_EQ(out.rv, OK);
4041
4042 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504043 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]1ed7b3dc2010-03-04 05:41:454044 EXPECT_TRUE(response->was_fetched_via_spdy);
4045 out.status_line = response->headers->GetStatusLine();
4046 out.response_info = *response; // Make a copy so we can verify.
4047
4048 // Read Data
[email protected]49639fa2011-12-20 23:22:414049 TestCompletionCallback read_callback;
[email protected]1ed7b3dc2010-03-04 05:41:454050
[email protected]88c7b4be2014-03-19 23:04:014051 const int kReadSize = 256;
bnc301745a2015-03-10 03:22:164052 scoped_refptr<IOBuffer> buf(new IOBuffer(kReadSize));
[email protected]88c7b4be2014-03-19 23:04:014053 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:164054 ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
[email protected]88c7b4be2014-03-19 23:04:014055
4056 // Complete the read now, which causes buffering to start.
4057 data.CompleteRead();
4058 // Destroy the transaction, causing the stream to get cancelled
4059 // and orphaning the buffered IO task.
4060 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:454061
4062 // Flush the MessageLoop; this will cause the buffered IO task
4063 // to run for the final time.
[email protected]fc9d88472013-08-14 02:31:174064 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:474065
4066 // Verify that we consumed all test data.
4067 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:454068}
4069
[email protected]74188f22010-04-09 20:18:504070// Test that if the server requests persistence of settings, that we save
[email protected]18b28ab2012-04-18 02:14:424071// the settings in the HttpServerProperties.
[email protected]513963e2013-06-15 01:53:044072TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
[email protected]8a7bc7a2014-02-28 21:25:224073 if (spdy_util_.spdy_version() >= SPDY4) {
[email protected]745aa9c2014-06-27 02:21:294074 // SPDY4 doesn't support settings persistence.
[email protected]8a7bc7a2014-02-28 21:25:224075 return;
4076 }
[email protected]74188f22010-04-09 20:18:504077 static const SpdyHeaderInfo kSynReplyInfo = {
[email protected]ff98d7f02012-03-22 21:44:194078 SYN_REPLY, // Syn Reply
[email protected]e0935cc2012-03-24 14:12:484079 1, // Stream ID
4080 0, // Associated Stream ID
[email protected]513963e2013-06-15 01:53:044081 ConvertRequestPriorityToSpdyPriority(
4082 LOWEST, spdy_util_.spdy_version()),
4083 kSpdyCredentialSlotUnused,
[email protected]ff98d7f02012-03-22 21:44:194084 CONTROL_FLAG_NONE, // Control Flags
[email protected]e0935cc2012-03-24 14:12:484085 false, // Compressed
[email protected]5a7bb252013-02-09 00:21:054086 RST_STREAM_INVALID, // Status
[email protected]e0935cc2012-03-24 14:12:484087 NULL, // Data
4088 0, // Data Length
[email protected]ff98d7f02012-03-22 21:44:194089 DATA_FLAG_NONE // Data Flags
[email protected]74188f22010-04-09 20:18:504090 };
[email protected]74188f22010-04-09 20:18:504091
[email protected]c0168822011-12-10 01:24:274092 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364093 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4094 net_log, GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:584095 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504096
4097 // Verify that no settings exist initially.
bncce36dca22015-04-21 22:11:234098 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]102e27c2011-02-23 01:01:314099 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]53bfa31c2011-11-15 19:20:314100 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4101 host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504102
4103 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:464104 scoped_ptr<SpdyFrame> req(
4105 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524106 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]74188f22010-04-09 20:18:504107
4108 // Construct the reply.
[email protected]513963e2013-06-15 01:53:044109 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4110 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4111 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]ff98d7f02012-03-22 21:44:194112 scoped_ptr<SpdyFrame> reply(
[email protected]513963e2013-06-15 01:53:044113 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
[email protected]74188f22010-04-09 20:18:504114
[email protected]e0935cc2012-03-24 14:12:484115 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
[email protected]74188f22010-04-09 20:18:504116 unsigned int kSampleValue1 = 0x0a0a0a0a;
[email protected]e0935cc2012-03-24 14:12:484117 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
[email protected]74188f22010-04-09 20:18:504118 unsigned int kSampleValue2 = 0x0b0b0b0b;
[email protected]e0935cc2012-03-24 14:12:484119 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
[email protected]74188f22010-04-09 20:18:504120 unsigned int kSampleValue3 = 0x0c0c0c0c;
[email protected]ff98d7f02012-03-22 21:44:194121 scoped_ptr<SpdyFrame> settings_frame;
[email protected]74188f22010-04-09 20:18:504122 {
4123 // Construct the SETTINGS frame.
[email protected]18b28ab2012-04-18 02:14:424124 SettingsMap settings;
[email protected]e0935cc2012-03-24 14:12:484125 // First add a persisted setting.
[email protected]18b28ab2012-04-18 02:14:424126 settings[kSampleId1] =
4127 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
[email protected]e0935cc2012-03-24 14:12:484128 // Next add a non-persisted setting.
[email protected]18b28ab2012-04-18 02:14:424129 settings[kSampleId2] =
4130 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
[email protected]e0935cc2012-03-24 14:12:484131 // Next add another persisted setting.
[email protected]18b28ab2012-04-18 02:14:424132 settings[kSampleId3] =
4133 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
[email protected]c10b20852013-05-15 21:29:204134 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
[email protected]74188f22010-04-09 20:18:504135 }
4136
[email protected]513963e2013-06-15 01:53:044137 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504138 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524139 CreateMockRead(*reply, 1),
4140 CreateMockRead(*body, 2),
4141 CreateMockRead(*settings_frame, 3),
4142 MockRead(ASYNC, 0, 4) // EOF
[email protected]74188f22010-04-09 20:18:504143 };
4144
rch08e3aa3e2015-05-16 14:27:524145 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574146 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:584147 helper.RunDefaultTest();
4148 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474149 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504150 EXPECT_EQ(OK, out.rv);
4151 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4152 EXPECT_EQ("hello!", out.response_data);
4153
4154 {
4155 // Verify we had two persisted settings.
[email protected]e0935cc2012-03-24 14:12:484156 const SettingsMap& settings_map =
[email protected]53bfa31c2011-11-15 19:20:314157 spdy_session_pool->http_server_properties()->GetSpdySettings(
4158 host_port_pair);
[email protected]e0935cc2012-03-24 14:12:484159 ASSERT_EQ(2u, settings_map.size());
[email protected]74188f22010-04-09 20:18:504160
4161 // Verify the first persisted setting.
[email protected]e0935cc2012-03-24 14:12:484162 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4163 EXPECT_TRUE(it1 != settings_map.end());
4164 SettingsFlagsAndValue flags_and_value1 = it1->second;
4165 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4166 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
[email protected]74188f22010-04-09 20:18:504167
4168 // Verify the second persisted setting.
[email protected]e0935cc2012-03-24 14:12:484169 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4170 EXPECT_TRUE(it3 != settings_map.end());
4171 SettingsFlagsAndValue flags_and_value3 = it3->second;
4172 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4173 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
[email protected]74188f22010-04-09 20:18:504174 }
4175}
4176
4177// Test that when there are settings saved that they are sent back to the
4178// server upon session establishment.
[email protected]513963e2013-06-15 01:53:044179TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
[email protected]745aa9c2014-06-27 02:21:294180 if (spdy_util_.spdy_version() >= SPDY4) {
4181 // SPDY4 doesn't support settings persistence.
4182 return;
4183 }
[email protected]74188f22010-04-09 20:18:504184 static const SpdyHeaderInfo kSynReplyInfo = {
[email protected]ff98d7f02012-03-22 21:44:194185 SYN_REPLY, // Syn Reply
[email protected]e0935cc2012-03-24 14:12:484186 1, // Stream ID
4187 0, // Associated Stream ID
[email protected]513963e2013-06-15 01:53:044188 ConvertRequestPriorityToSpdyPriority(
4189 LOWEST, spdy_util_.spdy_version()),
4190 kSpdyCredentialSlotUnused,
[email protected]ff98d7f02012-03-22 21:44:194191 CONTROL_FLAG_NONE, // Control Flags
[email protected]e0935cc2012-03-24 14:12:484192 false, // Compressed
[email protected]5a7bb252013-02-09 00:21:054193 RST_STREAM_INVALID, // Status
[email protected]e0935cc2012-03-24 14:12:484194 NULL, // Data
4195 0, // Data Length
[email protected]ff98d7f02012-03-22 21:44:194196 DATA_FLAG_NONE // Data Flags
[email protected]74188f22010-04-09 20:18:504197 };
[email protected]74188f22010-04-09 20:18:504198
[email protected]c0168822011-12-10 01:24:274199 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364200 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4201 net_log, GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:584202 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504203
[email protected]b40f7fa2013-08-01 16:13:054204 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4205
4206 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4207 pool_peer.SetEnableSendingInitialData(true);
4208
[email protected]74188f22010-04-09 20:18:504209 // Verify that no settings exist initially.
bncce36dca22015-04-21 22:11:234210 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]53bfa31c2011-11-15 19:20:314211 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4212 host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504213
[email protected]c143f2742014-03-31 00:48:544214 const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
[email protected]74188f22010-04-09 20:18:504215 unsigned int kSampleValue1 = 0x0a0a0a0a;
[email protected]c143f2742014-03-31 00:48:544216 const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
[email protected]74188f22010-04-09 20:18:504217 unsigned int kSampleValue2 = 0x0c0c0c0c;
[email protected]74188f22010-04-09 20:18:504218
[email protected]e0935cc2012-03-24 14:12:484219 // First add a persisted setting.
4220 spdy_session_pool->http_server_properties()->SetSpdySetting(
4221 host_port_pair,
4222 kSampleId1,
4223 SETTINGS_FLAG_PLEASE_PERSIST,
4224 kSampleValue1);
4225
4226 // Next add another persisted setting.
4227 spdy_session_pool->http_server_properties()->SetSpdySetting(
4228 host_port_pair,
4229 kSampleId2,
4230 SETTINGS_FLAG_PLEASE_PERSIST,
4231 kSampleValue2);
[email protected]74188f22010-04-09 20:18:504232
[email protected]53bfa31c2011-11-15 19:20:314233 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4234 host_port_pair).size());
[email protected]74188f22010-04-09 20:18:504235
[email protected]b40f7fa2013-08-01 16:13:054236 // Construct the initial SETTINGS frame.
4237 SettingsMap initial_settings;
4238 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4239 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4240 scoped_ptr<SpdyFrame> initial_settings_frame(
4241 spdy_util_.ConstructSpdySettings(initial_settings));
4242
[email protected]b40f7fa2013-08-01 16:13:054243 // Construct the persisted SETTINGS frame.
[email protected]18b28ab2012-04-18 02:14:424244 const SettingsMap& settings =
[email protected]53bfa31c2011-11-15 19:20:314245 spdy_session_pool->http_server_properties()->GetSpdySettings(
4246 host_port_pair);
[email protected]c10b20852013-05-15 21:29:204247 scoped_ptr<SpdyFrame> settings_frame(
4248 spdy_util_.ConstructSpdySettings(settings));
[email protected]74188f22010-04-09 20:18:504249
4250 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:464251 scoped_ptr<SpdyFrame> req(
4252 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]74188f22010-04-09 20:18:504253
rch32320842015-05-16 15:57:094254 MockWrite writes[] = {
4255 CreateMockWrite(*initial_settings_frame, 0),
4256 CreateMockWrite(*settings_frame, 1),
4257 CreateMockWrite(*req, 2),
4258 };
[email protected]74188f22010-04-09 20:18:504259
4260 // Construct the reply.
[email protected]513963e2013-06-15 01:53:044261 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4262 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4263 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]ff98d7f02012-03-22 21:44:194264 scoped_ptr<SpdyFrame> reply(
[email protected]513963e2013-06-15 01:53:044265 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
[email protected]74188f22010-04-09 20:18:504266
[email protected]513963e2013-06-15 01:53:044267 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504268 MockRead reads[] = {
rch32320842015-05-16 15:57:094269 CreateMockRead(*reply, 3),
4270 CreateMockRead(*body, 4),
4271 MockRead(ASYNC, 0, 5) // EOF
[email protected]74188f22010-04-09 20:18:504272 };
4273
rch32320842015-05-16 15:57:094274 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574275 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:584276 helper.RunDefaultTest();
4277 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474278 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504279 EXPECT_EQ(OK, out.rv);
4280 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4281 EXPECT_EQ("hello!", out.response_data);
4282
4283 {
4284 // Verify we had two persisted settings.
[email protected]e0935cc2012-03-24 14:12:484285 const SettingsMap& settings_map =
[email protected]53bfa31c2011-11-15 19:20:314286 spdy_session_pool->http_server_properties()->GetSpdySettings(
4287 host_port_pair);
[email protected]e0935cc2012-03-24 14:12:484288 ASSERT_EQ(2u, settings_map.size());
[email protected]74188f22010-04-09 20:18:504289
4290 // Verify the first persisted setting.
[email protected]e0935cc2012-03-24 14:12:484291 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4292 EXPECT_TRUE(it1 != settings_map.end());
4293 SettingsFlagsAndValue flags_and_value1 = it1->second;
4294 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4295 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
[email protected]74188f22010-04-09 20:18:504296
4297 // Verify the second persisted setting.
[email protected]e0935cc2012-03-24 14:12:484298 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4299 EXPECT_TRUE(it2 != settings_map.end());
4300 SettingsFlagsAndValue flags_and_value2 = it2->second;
4301 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4302 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
[email protected]74188f22010-04-09 20:18:504303 }
4304}
4305
[email protected]513963e2013-06-15 01:53:044306TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
[email protected]cdf8f7e72013-05-23 10:56:464307 scoped_ptr<SpdyFrame> req(
4308 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524309 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]69d717bd2010-04-21 18:43:214310
[email protected]c10b20852013-05-15 21:29:204311 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:214312 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524313 CreateMockRead(*go_away, 1),
[email protected]58cebf8f2010-07-31 19:20:164314 };
4315
rch08e3aa3e2015-05-16 14:27:524316 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364317 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504318 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574319 helper.AddData(&data);
4320 helper.RunToCompletion(&data);
[email protected]58cebf8f2010-07-31 19:20:164321 TransactionHelperResult out = helper.output();
[email protected]c9336d22010-08-10 00:04:184322 EXPECT_EQ(ERR_ABORTED, out.rv);
[email protected]69d717bd2010-04-21 18:43:214323}
4324
[email protected]513963e2013-06-15 01:53:044325TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
[email protected]cdf8f7e72013-05-23 10:56:464326 scoped_ptr<SpdyFrame> req(
4327 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524328 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]f5ed21552010-05-04 18:39:544329
[email protected]513963e2013-06-15 01:53:044330 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f5ed21552010-05-04 18:39:544331 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524332 CreateMockRead(*resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
[email protected]f5ed21552010-05-04 18:39:544333 };
4334
rch08e3aa3e2015-05-16 14:27:524335 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]f5ed21552010-05-04 18:39:544336 BoundNetLog log;
[email protected]262eec82013-03-19 21:01:364337 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504338 log, GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474339 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574340 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474341 HttpNetworkTransaction* trans = helper.trans();
[email protected]f5ed21552010-05-04 18:39:544342
[email protected]49639fa2011-12-20 23:22:414343 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:474344 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414345 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
[email protected]3caf5542010-07-16 15:19:474346
[email protected]f5ed21552010-05-04 18:39:544347 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4348 out.rv = callback.WaitForResult();
4349 EXPECT_EQ(out.rv, OK);
4350
4351 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504352 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]f5ed21552010-05-04 18:39:544353 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]3caf5542010-07-16 15:19:474354 out.rv = ReadTransaction(trans, &out.response_data);
[email protected]f5ed21552010-05-04 18:39:544355 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4356
4357 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474358 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:544359}
[email protected]58cebf8f2010-07-31 19:20:164360
bnca7f994a2015-01-20 19:39:414361// HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4362TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredError) {
4363 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4364 if (spdy_util_.spdy_version() < SPDY4)
4365 return;
4366
4367 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4368 BoundNetLog(), GetParam(), nullptr);
4369
4370 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4371 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4372 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524373 CreateMockRead(*go_away, 0),
bnca7f994a2015-01-20 19:39:414374 };
rch08e3aa3e2015-05-16 14:27:524375 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
bnca7f994a2015-01-20 19:39:414376
4377 helper.RunToCompletion(&data);
4378 TransactionHelperResult out = helper.output();
4379 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED, out.rv);
4380}
4381
bncfacdd852015-01-09 19:22:544382// Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4383// protocol negotiation happens, instead this test forces protocols for both
4384// sockets.
4385TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
4386 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4387 if (spdy_util_.spdy_version() < SPDY4)
4388 return;
4389 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4390 // only spoken over SSL.
rchebf12982015-04-10 01:15:004391 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
bncfacdd852015-01-09 19:22:544392 return;
4393
4394 HttpRequestInfo request;
4395 request.method = "GET";
bncce36dca22015-04-21 22:11:234396 request.url = GURL("https://www.example.org/");
bncfacdd852015-01-09 19:22:544397 scoped_ptr<SpdySessionDependencies> session_deps(
4398 CreateSpdySessionDependencies(GetParam()));
4399 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:544400 session_deps->next_protos = SpdyNextProtos();
4401 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4402 GetParam(), session_deps.release());
4403
4404 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
rchebf12982015-04-10 01:15:004405 const char* url = request.url.spec().c_str();
bncfacdd852015-01-09 19:22:544406 scoped_ptr<SpdyHeaderBlock> headers(spdy_util_.ConstructGetHeaderBlock(url));
4407 scoped_ptr<SpdyFrame> req(
4408 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
rch08e3aa3e2015-05-16 14:27:524409 MockWrite writes0[] = {CreateMockWrite(*req, 0)};
bncfacdd852015-01-09 19:22:544410 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4411 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
rch08e3aa3e2015-05-16 14:27:524412 MockRead reads0[] = {CreateMockRead(*go_away, 1)};
4413 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4414 arraysize(writes0));
bncfacdd852015-01-09 19:22:544415
4416 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4417 new SSLSocketDataProvider(ASYNC, OK));
4418 // Expect HTTP/2 protocols too in SSLConfig.
4419 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4420 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
4421 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_14);
bncbfa20e62015-03-09 23:29:224422 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4);
bncfacdd852015-01-09 19:22:544423 // Force SPDY.
4424 ssl_provider0->SetNextProto(GetParam().protocol);
4425 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4426
4427 // Second socket: falling back to HTTP/1.1.
rch08e3aa3e2015-05-16 14:27:524428 MockWrite writes1[] = {MockWrite(ASYNC, 0,
4429 "GET / HTTP/1.1\r\n"
4430 "Host: www.example.org\r\n"
4431 "Connection: keep-alive\r\n\r\n")};
4432 MockRead reads1[] = {MockRead(ASYNC, 1,
4433 "HTTP/1.1 200 OK\r\n"
4434 "Content-Length: 5\r\n\r\n"
4435 "hello")};
4436 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4437 arraysize(writes1));
bncfacdd852015-01-09 19:22:544438
4439 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4440 new SSLSocketDataProvider(ASYNC, OK));
4441 // Expect only HTTP/1.1 protocol in SSLConfig.
4442 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4443 // Force HTTP/1.1.
4444 ssl_provider1->SetNextProto(kProtoHTTP11);
4445 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4446
4447 base::WeakPtr<HttpServerProperties> http_server_properties =
4448 helper.session()->spdy_session_pool()->http_server_properties();
4449 const HostPortPair host_port_pair = HostPortPair::FromURL(GURL(url));
4450 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair));
4451
4452 helper.RunPreTestSetup();
4453 helper.StartDefaultTest();
4454 helper.FinishDefaultTestWithoutVerification();
4455 helper.VerifyDataConsumed();
4456 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair));
4457
4458 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4459 ASSERT_TRUE(response != nullptr);
4460 ASSERT_TRUE(response->headers.get() != nullptr);
4461 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4462 EXPECT_FALSE(response->was_fetched_via_spdy);
4463 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4464 EXPECT_TRUE(response->was_npn_negotiated);
4465 EXPECT_TRUE(request.url.SchemeIs("https"));
4466 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4467 EXPECT_EQ(443, response->socket_address.port());
4468 std::string response_data;
4469 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4470 EXPECT_EQ("hello", response_data);
4471}
4472
4473// Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4474// proxy. Note that no actual protocol negotiation happens, instead this test
4475// forces protocols for both sockets.
4476TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
4477 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4478 if (spdy_util_.spdy_version() < SPDY4)
4479 return;
4480 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4481 // only spoken over SSL.
rchebf12982015-04-10 01:15:004482 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
bncfacdd852015-01-09 19:22:544483 return;
4484
4485 HttpRequestInfo request;
4486 request.method = "GET";
bncce36dca22015-04-21 22:11:234487 request.url = GURL("https://www.example.org/");
bncfacdd852015-01-09 19:22:544488 scoped_ptr<SpdySessionDependencies> session_deps(
4489 CreateSpdySessionDependencies(
4490 GetParam(),
4491 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4492 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:544493 session_deps->next_protos = SpdyNextProtos();
4494 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4495 GetParam(), session_deps.release());
4496
4497 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4498 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234499 nullptr, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
rch08e3aa3e2015-05-16 14:27:524500 MockWrite writes0[] = {CreateMockWrite(*req, 0)};
bncfacdd852015-01-09 19:22:544501 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4502 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
rch08e3aa3e2015-05-16 14:27:524503 MockRead reads0[] = {CreateMockRead(*go_away, 1)};
4504 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4505 arraysize(writes0));
bncfacdd852015-01-09 19:22:544506
4507 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4508 new SSLSocketDataProvider(ASYNC, OK));
4509 // Expect HTTP/2 protocols too in SSLConfig.
4510 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4511 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
4512 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_14);
bncbfa20e62015-03-09 23:29:224513 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4);
bncfacdd852015-01-09 19:22:544514 // Force SPDY.
4515 ssl_provider0->SetNextProto(GetParam().protocol);
4516 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4517
4518 // Second socket: retry using HTTP/1.1.
4519 MockWrite writes1[] = {
rch08e3aa3e2015-05-16 14:27:524520 MockWrite(ASYNC, 0,
bncce36dca22015-04-21 22:11:234521 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4522 "Host: www.example.org\r\n"
bncfacdd852015-01-09 19:22:544523 "Proxy-Connection: keep-alive\r\n\r\n"),
rch08e3aa3e2015-05-16 14:27:524524 MockWrite(ASYNC, 2,
bncfacdd852015-01-09 19:22:544525 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:234526 "Host: www.example.org\r\n"
bncfacdd852015-01-09 19:22:544527 "Connection: keep-alive\r\n\r\n"),
4528 };
4529
4530 MockRead reads1[] = {
rch08e3aa3e2015-05-16 14:27:524531 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4532 MockRead(ASYNC, 3,
bncfacdd852015-01-09 19:22:544533 "HTTP/1.1 200 OK\r\n"
4534 "Content-Length: 5\r\n\r\n"
4535 "hello"),
4536 };
rch08e3aa3e2015-05-16 14:27:524537 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4538 arraysize(writes1));
bncfacdd852015-01-09 19:22:544539
4540 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4541 new SSLSocketDataProvider(ASYNC, OK));
4542 // Expect only HTTP/1.1 protocol in SSLConfig.
4543 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4544 // Force HTTP/1.1.
4545 ssl_provider1->SetNextProto(kProtoHTTP11);
4546 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4547
4548 // A third socket is needed for the tunnelled connection.
4549 scoped_ptr<SSLSocketDataProvider> ssl_provider2(
4550 new SSLSocketDataProvider(ASYNC, OK));
4551 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4552 ssl_provider2.get());
4553
4554 base::WeakPtr<HttpServerProperties> http_server_properties =
4555 helper.session()->spdy_session_pool()->http_server_properties();
4556 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
4557 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4558
4559 helper.RunPreTestSetup();
4560 helper.StartDefaultTest();
4561 helper.FinishDefaultTestWithoutVerification();
4562 helper.VerifyDataConsumed();
4563 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4564
4565 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4566 ASSERT_TRUE(response != nullptr);
4567 ASSERT_TRUE(response->headers.get() != nullptr);
4568 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4569 EXPECT_FALSE(response->was_fetched_via_spdy);
4570 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4571 EXPECT_FALSE(response->was_npn_negotiated);
4572 EXPECT_TRUE(request.url.SchemeIs("https"));
4573 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4574 EXPECT_EQ(70, response->socket_address.port());
4575 std::string response_data;
4576 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4577 EXPECT_EQ("hello", response_data);
4578}
4579
[email protected]b261d0e2010-08-02 19:13:244580// Test to make sure we can correctly connect through a proxy.
[email protected]513963e2013-06-15 01:53:044581TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
[email protected]262eec82013-03-19 21:01:364582 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504583 BoundNetLog(), GetParam(), NULL);
[email protected]bb88e1d32013-05-03 23:11:074584 helper.session_deps().reset(CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:044585 GetParam(),
[email protected]733b7a6d2010-08-25 01:38:434586 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
[email protected]00cd9c42010-11-02 20:15:574587 helper.SetSession(make_scoped_refptr(
4588 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
[email protected]b261d0e2010-08-02 19:13:244589 helper.RunPreTestSetup();
4590 HttpNetworkTransaction* trans = helper.trans();
4591
rchebf12982015-04-10 01:15:004592 const char kConnect443[] = {
bncce36dca22015-04-21 22:11:234593 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4594 "Host: www.example.org\r\n"
rchcb934f562015-04-07 16:25:124595 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244596 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
[email protected]cdf8f7e72013-05-23 10:56:464597 scoped_ptr<SpdyFrame> req(
4598 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:044599 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4600 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244601
rchebf12982015-04-10 01:15:004602 MockWrite writes[] = {
4603 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4604 CreateMockWrite(*req, 2),
[email protected]b261d0e2010-08-02 19:13:244605 };
rchebf12982015-04-10 01:15:004606 MockRead reads[] = {
4607 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4608 CreateMockRead(*resp, 3),
4609 CreateMockRead(*body.get(), 4),
4610 MockRead(ASYNC, 0, 0, 5),
[email protected]b261d0e2010-08-02 19:13:244611 };
rch08e3aa3e2015-05-16 14:27:524612 scoped_ptr<SequencedSocketData> data(new SequencedSocketData(
rchebf12982015-04-10 01:15:004613 reads, arraysize(reads), writes, arraysize(writes)));
[email protected]b261d0e2010-08-02 19:13:244614
4615 helper.AddData(data.get());
[email protected]49639fa2011-12-20 23:22:414616 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244617
[email protected]49639fa2011-12-20 23:22:414618 int rv = trans->Start(
4619 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244620 EXPECT_EQ(ERR_IO_PENDING, rv);
4621
4622 rv = callback.WaitForResult();
4623 EXPECT_EQ(0, rv);
4624
4625 // Verify the SYN_REPLY.
4626 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504627 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244628 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4629
4630 std::string response_data;
4631 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4632 EXPECT_EQ("hello!", response_data);
4633 helper.VerifyDataConsumed();
4634}
4635
bncce36dca22015-04-21 22:11:234636// Test to make sure we can correctly connect through a proxy to
4637// www.example.org, if there already exists a direct spdy connection to
4638// www.example.org. See https://crbug.com/49874.
[email protected]513963e2013-06-15 01:53:044639TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
[email protected]b261d0e2010-08-02 19:13:244640 // When setting up the first transaction, we store the SpdySessionPool so that
4641 // we can use the same pool in the second transaction.
[email protected]262eec82013-03-19 21:01:364642 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504643 BoundNetLog(), GetParam(), NULL);
[email protected]733b7a6d2010-08-25 01:38:434644
4645 // Use a proxy service which returns a proxy fallback list from DIRECT to
4646 // myproxy:70. For this test there will be no fallback, so it is equivalent
4647 // to simply DIRECT. The reason for appending the second proxy is to verify
4648 // that the session pool key used does is just "DIRECT".
[email protected]bb88e1d32013-05-03 23:11:074649 helper.session_deps().reset(CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:044650 GetParam(),
[email protected]733b7a6d2010-08-25 01:38:434651 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
[email protected]00cd9c42010-11-02 20:15:574652 helper.SetSession(make_scoped_refptr(
4653 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
[email protected]733b7a6d2010-08-25 01:38:434654
[email protected]87bfa3f2010-09-30 14:54:564655 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:244656 helper.RunPreTestSetup();
4657
4658 // Construct and send a simple GET request.
[email protected]cdf8f7e72013-05-23 10:56:464659 scoped_ptr<SpdyFrame> req(
4660 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b261d0e2010-08-02 19:13:244661 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:524662 CreateMockWrite(*req, 0),
[email protected]b261d0e2010-08-02 19:13:244663 };
4664
[email protected]513963e2013-06-15 01:53:044665 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4666 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244667 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:524668 CreateMockRead(*resp, 1),
4669 CreateMockRead(*body, 2),
4670 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3), // Force a pause
[email protected]b261d0e2010-08-02 19:13:244671 };
rch08e3aa3e2015-05-16 14:27:524672 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574673 helper.AddData(&data);
[email protected]b261d0e2010-08-02 19:13:244674 HttpNetworkTransaction* trans = helper.trans();
4675
[email protected]49639fa2011-12-20 23:22:414676 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244677 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414678 out.rv = trans->Start(
4679 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244680
4681 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4682 out.rv = callback.WaitForResult();
4683 EXPECT_EQ(out.rv, OK);
4684
4685 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504686 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244687 EXPECT_TRUE(response->was_fetched_via_spdy);
4688 out.rv = ReadTransaction(trans, &out.response_data);
4689 EXPECT_EQ(OK, out.rv);
4690 out.status_line = response->headers->GetStatusLine();
4691 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4692 EXPECT_EQ("hello!", out.response_data);
4693
4694 // Check that the SpdySession is still in the SpdySessionPool.
bncce36dca22015-04-21 22:11:234695 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]e6d017652013-05-17 18:01:404696 SpdySessionKey session_pool_key_direct(
[email protected]314b03992014-04-01 01:28:534697 host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264698 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
[email protected]e6d017652013-05-17 18:01:404699 SpdySessionKey session_pool_key_proxy(
[email protected]31e68d72010-08-25 06:36:584700 host_port_pair,
[email protected]e6d017652013-05-17 18:01:404701 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
[email protected]314b03992014-04-01 01:28:534702 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264703 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:244704
4705 // Set up data for the proxy connection.
bncce36dca22015-04-21 22:11:234706 const char kConnect443[] = {
4707 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4708 "Host: www.example.org\r\n"
4709 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244710 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
[email protected]cdf8f7e72013-05-23 10:56:464711 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
rchebf12982015-04-10 01:15:004712 GetDefaultUrlWithPath("/foo.dat").c_str(), false, 1, LOWEST));
[email protected]513963e2013-06-15 01:53:044713 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4714 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244715
rchebf12982015-04-10 01:15:004716 MockWrite writes2[] = {
4717 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4718 CreateMockWrite(*req2, 2),
[email protected]b261d0e2010-08-02 19:13:244719 };
rchebf12982015-04-10 01:15:004720 MockRead reads2[] = {
4721 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4722 CreateMockRead(*resp2, 3),
4723 CreateMockRead(*body2, 4),
4724 MockRead(ASYNC, 0, 5) // EOF
[email protected]b261d0e2010-08-02 19:13:244725 };
4726
rch08e3aa3e2015-05-16 14:27:524727 scoped_ptr<SequencedSocketData> data_proxy(new SequencedSocketData(
rchebf12982015-04-10 01:15:004728 reads2, arraysize(reads2), writes2, arraysize(writes2)));
[email protected]b261d0e2010-08-02 19:13:244729
bncce36dca22015-04-21 22:11:234730 // Create another request to www.example.org, but this time through a proxy.
[email protected]b261d0e2010-08-02 19:13:244731 HttpRequestInfo request_proxy;
4732 request_proxy.method = "GET";
rchebf12982015-04-10 01:15:004733 request_proxy.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
[email protected]b261d0e2010-08-02 19:13:244734 request_proxy.load_flags = 0;
[email protected]bb88e1d32013-05-03 23:11:074735 scoped_ptr<SpdySessionDependencies> ssd_proxy(
[email protected]513963e2013-06-15 01:53:044736 CreateSpdySessionDependencies(GetParam()));
[email protected]b261d0e2010-08-02 19:13:244737 // Ensure that this transaction uses the same SpdySessionPool.
[email protected]ad8e04a2010-11-01 04:16:274738 scoped_refptr<HttpNetworkSession> session_proxy(
4739 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
[email protected]262eec82013-03-19 21:01:364740 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504741 BoundNetLog(), GetParam(), NULL);
[email protected]87bfa3f2010-09-30 14:54:564742 HttpNetworkSessionPeer session_peer(session_proxy);
bnc301745a2015-03-10 03:22:164743 scoped_ptr<ProxyService> proxy_service(
4744 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
[email protected]6104ea5d2011-04-27 21:37:124745 session_peer.SetProxyService(proxy_service.get());
[email protected]b261d0e2010-08-02 19:13:244746 helper_proxy.session_deps().swap(ssd_proxy);
[email protected]19ec8a72010-08-23 03:38:234747 helper_proxy.SetSession(session_proxy);
[email protected]b261d0e2010-08-02 19:13:244748 helper_proxy.RunPreTestSetup();
4749 helper_proxy.AddData(data_proxy.get());
4750
4751 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
[email protected]49639fa2011-12-20 23:22:414752 TestCompletionCallback callback_proxy;
4753 int rv = trans_proxy->Start(
4754 &request_proxy, callback_proxy.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244755 EXPECT_EQ(ERR_IO_PENDING, rv);
4756 rv = callback_proxy.WaitForResult();
4757 EXPECT_EQ(0, rv);
4758
4759 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504760 EXPECT_TRUE(response_proxy.headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244761 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
4762
4763 std::string response_data;
4764 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4765 EXPECT_EQ("hello!", response_data);
4766
[email protected]b261d0e2010-08-02 19:13:244767 helper_proxy.VerifyDataConsumed();
4768}
4769
[email protected]58cebf8f2010-07-31 19:20:164770// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4771// on a new connection, if the connection was previously known to be good.
4772// This can happen when a server reboots without saying goodbye, or when
4773// we're behind a NAT that masked the RST.
[email protected]513963e2013-06-15 01:53:044774TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
[email protected]513963e2013-06-15 01:53:044775 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4776 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]58cebf8f2010-07-31 19:20:164777 MockRead reads[] = {
rch32320842015-05-16 15:57:094778 CreateMockRead(*resp, 1),
4779 CreateMockRead(*body, 2),
4780 MockRead(ASYNC, ERR_IO_PENDING, 3),
4781 MockRead(ASYNC, ERR_CONNECTION_RESET, 4),
[email protected]58cebf8f2010-07-31 19:20:164782 };
4783
4784 MockRead reads2[] = {
rch32320842015-05-16 15:57:094785 CreateMockRead(*resp, 1),
4786 CreateMockRead(*body, 2),
4787 MockRead(ASYNC, 0, 3) // EOF
[email protected]58cebf8f2010-07-31 19:20:164788 };
4789
4790 // This test has a couple of variants.
4791 enum {
4792 // Induce the RST while waiting for our transaction to send.
4793 VARIANT_RST_DURING_SEND_COMPLETION,
4794 // Induce the RST while waiting for our transaction to read.
4795 // In this case, the send completed - everything copied into the SNDBUF.
4796 VARIANT_RST_DURING_READ_COMPLETION
4797 };
4798
4799 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4800 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4801 ++variant) {
[email protected]dd54bd82012-07-19 23:44:574802 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
[email protected]58cebf8f2010-07-31 19:20:164803
[email protected]dd54bd82012-07-19 23:44:574804 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
[email protected]58cebf8f2010-07-31 19:20:164805
[email protected]262eec82013-03-19 21:01:364806 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504807 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574808 helper.AddData(&data1);
4809 helper.AddData(&data2);
[email protected]58cebf8f2010-07-31 19:20:164810 helper.RunPreTestSetup();
4811
4812 for (int i = 0; i < 2; ++i) {
4813 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:504814 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]58cebf8f2010-07-31 19:20:164815
[email protected]49639fa2011-12-20 23:22:414816 TestCompletionCallback callback;
4817 int rv = trans->Start(
4818 &helper.request(), callback.callback(), BoundNetLog());
[email protected]58cebf8f2010-07-31 19:20:164819 EXPECT_EQ(ERR_IO_PENDING, rv);
4820 // On the second transaction, we trigger the RST.
4821 if (i == 1) {
4822 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4823 // Writes to the socket complete asynchronously on SPDY by running
4824 // through the message loop. Complete the write here.
[email protected]fc9d88472013-08-14 02:31:174825 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164826 }
4827
4828 // Now schedule the ERR_CONNECTION_RESET.
[email protected]dd54bd82012-07-19 23:44:574829 EXPECT_EQ(3u, data1.read_index());
4830 data1.CompleteRead();
4831 EXPECT_EQ(4u, data1.read_index());
[email protected]58cebf8f2010-07-31 19:20:164832 }
4833 rv = callback.WaitForResult();
4834 EXPECT_EQ(OK, rv);
4835
4836 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]351ab642010-08-05 16:55:314837 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504838 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]58cebf8f2010-07-31 19:20:164839 EXPECT_TRUE(response->was_fetched_via_spdy);
4840 std::string response_data;
4841 rv = ReadTransaction(trans.get(), &response_data);
4842 EXPECT_EQ(OK, rv);
4843 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4844 EXPECT_EQ("hello!", response_data);
4845 }
4846
4847 helper.VerifyDataConsumed();
4848 }
4849}
[email protected]1f418ee2010-10-16 19:46:564850
4851// Test that turning SPDY on and off works properly.
[email protected]513963e2013-06-15 01:53:044852TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
[email protected]d7599122014-05-24 03:37:234853 HttpStreamFactory::set_spdy_enabled(true);
[email protected]cdf8f7e72013-05-23 10:56:464854 scoped_ptr<SpdyFrame> req(
4855 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:524856 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]1f418ee2010-10-16 19:46:564857
[email protected]513963e2013-06-15 01:53:044858 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4859 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1f418ee2010-10-16 19:46:564860 MockRead spdy_reads[] = {
rch08e3aa3e2015-05-16 14:27:524861 CreateMockRead(*resp, 1),
4862 CreateMockRead(*body, 2),
4863 MockRead(ASYNC, 0, 3) // EOF
[email protected]1f418ee2010-10-16 19:46:564864 };
4865
rch08e3aa3e2015-05-16 14:27:524866 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4867 arraysize(spdy_writes));
[email protected]262eec82013-03-19 21:01:364868 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504869 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574870 helper.RunToCompletion(&data);
[email protected]1f418ee2010-10-16 19:46:564871 TransactionHelperResult out = helper.output();
4872 EXPECT_EQ(OK, out.rv);
4873 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4874 EXPECT_EQ("hello!", out.response_data);
4875
bnc301745a2015-03-10 03:22:164876 HttpStreamFactory::set_spdy_enabled(false);
rch08e3aa3e2015-05-16 14:27:524877 MockWrite http_writes[] = {
4878 MockWrite(SYNCHRONOUS, 0,
4879 "GET / HTTP/1.1\r\n"
4880 "Host: www.example.org\r\n"
4881 "Connection: keep-alive\r\n\r\n"),
rch73e17422015-05-04 19:52:064882 };
rch08e3aa3e2015-05-16 14:27:524883
4884 MockRead http_reads[] = {
4885 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4886 MockRead(SYNCHRONOUS, 2, "hello from http"),
4887 MockRead(SYNCHRONOUS, OK, 3),
4888 };
4889 SequencedSocketData data2(http_reads, arraysize(http_reads), http_writes,
4890 arraysize(http_writes));
[email protected]262eec82013-03-19 21:01:364891 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504892 BoundNetLog(), GetParam(), NULL);
[email protected]1f418ee2010-10-16 19:46:564893 helper2.SetSpdyDisabled();
[email protected]dd54bd82012-07-19 23:44:574894 helper2.RunToCompletion(&data2);
[email protected]1f418ee2010-10-16 19:46:564895 TransactionHelperResult out2 = helper2.output();
4896 EXPECT_EQ(OK, out2.rv);
4897 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4898 EXPECT_EQ("hello from http", out2.response_data);
4899
bnc301745a2015-03-10 03:22:164900 HttpStreamFactory::set_spdy_enabled(true);
[email protected]1f418ee2010-10-16 19:46:564901}
[email protected]018aabc2010-10-29 16:16:594902
4903// Tests that Basic authentication works over SPDY
[email protected]513963e2013-06-15 01:53:044904TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
bnc301745a2015-03-10 03:22:164905 HttpStreamFactory::set_spdy_enabled(true);
[email protected]018aabc2010-10-29 16:16:594906
4907 // The first request will be a bare GET, the second request will be a
4908 // GET with an Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194909 scoped_ptr<SpdyFrame> req_get(
[email protected]cdf8f7e72013-05-23 10:56:464910 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594911 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464912 "authorization", "Basic Zm9vOmJhcg=="
[email protected]018aabc2010-10-29 16:16:594913 };
[email protected]ff98d7f02012-03-22 21:44:194914 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464915 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4916 arraysize(kExtraAuthorizationHeaders) / 2,
4917 false, 3, LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594918 MockWrite spdy_writes[] = {
rch08e3aa3e2015-05-16 14:27:524919 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
[email protected]018aabc2010-10-29 16:16:594920 };
4921
4922 // The first response is a 401 authentication challenge, and the second
4923 // response will be a 200 response since the second request includes a valid
4924 // Authorization header.
4925 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:264926 "www-authenticate",
[email protected]018aabc2010-10-29 16:16:594927 "Basic realm=\"MyRealm\""
4928 };
[email protected]ff98d7f02012-03-22 21:44:194929 scoped_ptr<SpdyFrame> resp_authentication(
[email protected]513963e2013-06-15 01:53:044930 spdy_util_.ConstructSpdySynReplyError(
[email protected]018aabc2010-10-29 16:16:594931 "401 Authentication Required",
[email protected]d08358502010-12-03 22:04:034932 kExtraAuthenticationHeaders,
4933 arraysize(kExtraAuthenticationHeaders) / 2,
[email protected]018aabc2010-10-29 16:16:594934 1));
[email protected]ff98d7f02012-03-22 21:44:194935 scoped_ptr<SpdyFrame> body_authentication(
[email protected]513963e2013-06-15 01:53:044936 spdy_util_.ConstructSpdyBodyFrame(1, true));
4937 scoped_ptr<SpdyFrame> resp_data(
4938 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4939 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]018aabc2010-10-29 16:16:594940 MockRead spdy_reads[] = {
rch08e3aa3e2015-05-16 14:27:524941 CreateMockRead(*resp_authentication, 1),
4942 CreateMockRead(*body_authentication, 2),
4943 CreateMockRead(*resp_data, 4),
4944 CreateMockRead(*body_data, 5),
4945 MockRead(ASYNC, 0, 6),
[email protected]018aabc2010-10-29 16:16:594946 };
4947
rch08e3aa3e2015-05-16 14:27:524948 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4949 arraysize(spdy_writes));
[email protected]018aabc2010-10-29 16:16:594950 HttpRequestInfo request(CreateGetRequest());
4951 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364952 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
4953 net_log, GetParam(), NULL);
[email protected]018aabc2010-10-29 16:16:594954
4955 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574956 helper.AddData(&data);
[email protected]018aabc2010-10-29 16:16:594957 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:414958 TestCompletionCallback callback;
4959 const int rv_start = trans->Start(&request, callback.callback(), net_log);
[email protected]018aabc2010-10-29 16:16:594960 EXPECT_EQ(ERR_IO_PENDING, rv_start);
[email protected]49639fa2011-12-20 23:22:414961 const int rv_start_complete = callback.WaitForResult();
[email protected]018aabc2010-10-29 16:16:594962 EXPECT_EQ(OK, rv_start_complete);
4963
4964 // Make sure the response has an auth challenge.
4965 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4966 ASSERT_TRUE(response_start != NULL);
[email protected]90499482013-06-01 00:39:504967 ASSERT_TRUE(response_start->headers.get() != NULL);
[email protected]018aabc2010-10-29 16:16:594968 EXPECT_EQ(401, response_start->headers->response_code());
4969 EXPECT_TRUE(response_start->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044970 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
4971 ASSERT_TRUE(auth_challenge != NULL);
4972 EXPECT_FALSE(auth_challenge->is_proxy);
4973 EXPECT_EQ("basic", auth_challenge->scheme);
4974 EXPECT_EQ("MyRealm", auth_challenge->realm);
[email protected]018aabc2010-10-29 16:16:594975
4976 // Restart with a username/password.
[email protected]ad65a3e2013-12-25 18:18:014977 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
4978 base::ASCIIToUTF16("bar"));
[email protected]49639fa2011-12-20 23:22:414979 TestCompletionCallback callback_restart;
4980 const int rv_restart = trans->RestartWithAuth(
4981 credentials, callback_restart.callback());
[email protected]018aabc2010-10-29 16:16:594982 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
4983 const int rv_restart_complete = callback_restart.WaitForResult();
4984 EXPECT_EQ(OK, rv_restart_complete);
4985 // TODO(cbentzel): This is actually the same response object as before, but
4986 // data has changed.
4987 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4988 ASSERT_TRUE(response_restart != NULL);
[email protected]90499482013-06-01 00:39:504989 ASSERT_TRUE(response_restart->headers.get() != NULL);
[email protected]018aabc2010-10-29 16:16:594990 EXPECT_EQ(200, response_restart->headers->response_code());
4991 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4992}
4993
[email protected]513963e2013-06-15 01:53:044994TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:464995 scoped_ptr<SpdyFrame> stream1_syn(
4996 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:044997 scoped_ptr<SpdyFrame> stream1_body(
4998 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:034999 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525000 CreateMockWrite(*stream1_syn, 0),
[email protected]d08358502010-12-03 22:04:035001 };
5002
[email protected]513963e2013-06-15 01:53:045003 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005004 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5005 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235006 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565007 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045008
5009 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5010 (*late_headers)["hello"] = "bye";
5011 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5012 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]4bd46222013-05-14 19:32:235013 scoped_ptr<SpdyFrame> stream2_headers(
[email protected]513963e2013-06-15 01:53:045014 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235015 false,
5016 2,
5017 LOWEST,
5018 HEADERS,
5019 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235020 0));
[email protected]d08358502010-12-03 22:04:035021
[email protected]ff98d7f02012-03-22 21:44:195022 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045023 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435024 const char kPushedData[] = "pushed";
5025 scoped_ptr<SpdyFrame> stream2_body(
5026 spdy_util_.ConstructSpdyBodyFrame(
5027 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035028 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525029 CreateMockRead(*stream1_reply, 1),
5030 CreateMockRead(*stream2_syn, 2),
5031 CreateMockRead(*stream2_headers, 3),
5032 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
5033 CreateMockRead(*stream2_body, 5),
5034 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]d08358502010-12-03 22:04:035035 };
5036
5037 HttpResponseInfo response;
5038 HttpResponseInfo response2;
5039 std::string expected_push_result("pushed");
rch08e3aa3e2015-05-16 14:27:525040 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:575041 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:035042 &response,
5043 &response2,
5044 expected_push_result);
5045
5046 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505047 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035048 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5049
5050 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505051 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035052 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5053}
5054
[email protected]513963e2013-06-15 01:53:045055TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
[email protected]d08358502010-12-03 22:04:035056 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465057 scoped_ptr<SpdyFrame> stream1_syn(
5058 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045059 scoped_ptr<SpdyFrame> stream1_body(
5060 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035061 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:065062 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:035063 };
5064
[email protected]513963e2013-06-15 01:53:045065 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005066 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5067 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235068 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565069 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045070
5071 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5072 (*late_headers)["hello"] = "bye";
5073 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5074 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]4bd46222013-05-14 19:32:235075 scoped_ptr<SpdyFrame> stream2_headers(
[email protected]513963e2013-06-15 01:53:045076 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235077 false,
5078 2,
5079 LOWEST,
5080 HEADERS,
5081 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235082 0));
[email protected]d08358502010-12-03 22:04:035083
[email protected]ff98d7f02012-03-22 21:44:195084 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045085 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435086 const char kPushedData[] = "pushed";
5087 scoped_ptr<SpdyFrame> stream2_body(
5088 spdy_util_.ConstructSpdyBodyFrame(
5089 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035090 MockRead reads[] = {
5091 CreateMockRead(*stream1_reply, 1),
5092 CreateMockRead(*stream2_syn, 2),
5093 CreateMockRead(*stream1_body, 3),
5094 CreateMockRead(*stream2_headers, 4),
[email protected]8a0fc822013-06-27 20:52:435095 CreateMockRead(*stream2_body, 5),
[email protected]d55b30a2012-07-21 00:35:395096 MockRead(ASYNC, 0, 6), // EOF
[email protected]d08358502010-12-03 22:04:035097 };
5098
5099 HttpResponseInfo response;
5100 HttpResponseInfo response2;
5101 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:575102 DeterministicSocketData data(reads, arraysize(reads),
5103 writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:035104
[email protected]262eec82013-03-19 21:01:365105 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505106 BoundNetLog(), GetParam(), NULL);
[email protected]d08358502010-12-03 22:04:035107 helper.SetDeterministic();
[email protected]dd54bd82012-07-19 23:44:575108 helper.AddDeterministicData(&data);
[email protected]d08358502010-12-03 22:04:035109 helper.RunPreTestSetup();
5110
5111 HttpNetworkTransaction* trans = helper.trans();
5112
5113 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5114 // and the body of the primary stream, but before we've received the HEADERS
5115 // for the pushed stream.
[email protected]dd54bd82012-07-19 23:44:575116 data.SetStop(3);
[email protected]d08358502010-12-03 22:04:035117
5118 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:415119 TestCompletionCallback callback;
5120 int rv = trans->Start(
5121 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035122 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575123 data.Run();
[email protected]d08358502010-12-03 22:04:035124 rv = callback.WaitForResult();
5125 EXPECT_EQ(0, rv);
5126
5127 // Request the pushed path. At this point, we've received the push, but the
5128 // headers are not yet complete.
5129 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:505130 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]49639fa2011-12-20 23:22:415131 rv = trans2->Start(
5132 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035133 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575134 data.RunFor(3);
[email protected]fc9d88472013-08-14 02:31:175135 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:035136
5137 // Read the server push body.
5138 std::string result2;
[email protected]dd54bd82012-07-19 23:44:575139 ReadResult(trans2.get(), &data, &result2);
[email protected]d08358502010-12-03 22:04:035140 // Read the response body.
5141 std::string result;
[email protected]dd54bd82012-07-19 23:44:575142 ReadResult(trans, &data, &result);
[email protected]d08358502010-12-03 22:04:035143
[email protected]d08358502010-12-03 22:04:035144 // Verify that the received push data is same as the expected push data.
5145 EXPECT_EQ(result2.compare(expected_push_result), 0)
5146 << "Received data: "
5147 << result2
5148 << "||||| Expected data: "
5149 << expected_push_result;
5150
5151 // Verify the SYN_REPLY.
5152 // Copy the response info, because trans goes away.
5153 response = *trans->GetResponseInfo();
5154 response2 = *trans2->GetResponseInfo();
5155
5156 VerifyStreamsClosed(helper);
5157
5158 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505159 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035160 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5161
5162 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505163 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035164 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
[email protected]d55b30a2012-07-21 00:35:395165
5166 // Read the final EOF (which will close the session)
5167 data.RunFor(1);
5168
5169 // Verify that we consumed all test data.
rchb6dc73572015-05-08 04:01:075170 EXPECT_TRUE(data.at_read_eof());
5171 EXPECT_TRUE(data.at_write_eof());
[email protected]d08358502010-12-03 22:04:035172}
5173
[email protected]6cd63ba2014-06-12 16:14:565174// TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
[email protected]513963e2013-06-15 01:53:045175TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
[email protected]d08358502010-12-03 22:04:035176 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465177 scoped_ptr<SpdyFrame> stream1_syn(
5178 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045179 scoped_ptr<SpdyFrame> stream1_body(
5180 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035181 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:065182 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:035183 };
5184
[email protected]513963e2013-06-15 01:53:045185 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
[email protected]0338bc62014-06-20 17:09:565186 if (spdy_util_.spdy_version() < SPDY4) {
5187 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5188 (*initial_headers)["alpha"] = "beta";
5189 }
rchebf12982015-04-10 01:15:005190 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5191 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235192 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565193 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045194
5195 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5196 (*middle_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235197 scoped_ptr<SpdyFrame> stream2_headers1(
[email protected]513963e2013-06-15 01:53:045198 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235199 false,
5200 2,
5201 LOWEST,
5202 HEADERS,
5203 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235204 0));
[email protected]513963e2013-06-15 01:53:045205
5206 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5207 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
[email protected]601e03f12014-04-06 16:26:395208 if (spdy_util_.spdy_version() < SPDY4) {
5209 // SPDY4/HTTP2 eliminates use of the :version header.
5210 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5211 }
[email protected]4bd46222013-05-14 19:32:235212 scoped_ptr<SpdyFrame> stream2_headers2(
[email protected]513963e2013-06-15 01:53:045213 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235214 false,
5215 2,
5216 LOWEST,
5217 HEADERS,
5218 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235219 0));
[email protected]d08358502010-12-03 22:04:035220
[email protected]ff98d7f02012-03-22 21:44:195221 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045222 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435223 const char kPushedData[] = "pushed";
5224 scoped_ptr<SpdyFrame> stream2_body(
5225 spdy_util_.ConstructSpdyBodyFrame(
5226 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035227 MockRead reads[] = {
5228 CreateMockRead(*stream1_reply, 1),
5229 CreateMockRead(*stream2_syn, 2),
5230 CreateMockRead(*stream1_body, 3),
5231 CreateMockRead(*stream2_headers1, 4),
5232 CreateMockRead(*stream2_headers2, 5),
[email protected]8a0fc822013-06-27 20:52:435233 CreateMockRead(*stream2_body, 6),
[email protected]d55b30a2012-07-21 00:35:395234 MockRead(ASYNC, 0, 7), // EOF
[email protected]d08358502010-12-03 22:04:035235 };
5236
5237 HttpResponseInfo response;
5238 HttpResponseInfo response2;
5239 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:575240 DeterministicSocketData data(reads, arraysize(reads),
5241 writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:035242
[email protected]262eec82013-03-19 21:01:365243 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505244 BoundNetLog(), GetParam(), NULL);
[email protected]d08358502010-12-03 22:04:035245 helper.SetDeterministic();
[email protected]dd54bd82012-07-19 23:44:575246 helper.AddDeterministicData(&data);
[email protected]d08358502010-12-03 22:04:035247 helper.RunPreTestSetup();
5248
5249 HttpNetworkTransaction* trans = helper.trans();
5250
5251 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5252 // the first HEADERS frame, and the body of the primary stream, but before
5253 // we've received the final HEADERS for the pushed stream.
[email protected]dd54bd82012-07-19 23:44:575254 data.SetStop(4);
[email protected]d08358502010-12-03 22:04:035255
5256 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:415257 TestCompletionCallback callback;
5258 int rv = trans->Start(
5259 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035260 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575261 data.Run();
[email protected]d08358502010-12-03 22:04:035262 rv = callback.WaitForResult();
5263 EXPECT_EQ(0, rv);
5264
5265 // Request the pushed path. At this point, we've received the push, but the
5266 // headers are not yet complete.
5267 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:505268 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]49639fa2011-12-20 23:22:415269 rv = trans2->Start(
5270 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035271 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575272 data.RunFor(3);
[email protected]fc9d88472013-08-14 02:31:175273 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:035274
5275 // Read the server push body.
5276 std::string result2;
[email protected]dd54bd82012-07-19 23:44:575277 ReadResult(trans2.get(), &data, &result2);
[email protected]d08358502010-12-03 22:04:035278 // Read the response body.
5279 std::string result;
[email protected]dd54bd82012-07-19 23:44:575280 ReadResult(trans, &data, &result);
[email protected]d08358502010-12-03 22:04:035281
[email protected]d08358502010-12-03 22:04:035282 // Verify that the received push data is same as the expected push data.
[email protected]6d116e1a2013-06-24 07:42:155283 EXPECT_EQ(expected_push_result, result2);
[email protected]d08358502010-12-03 22:04:035284
5285 // Verify the SYN_REPLY.
5286 // Copy the response info, because trans goes away.
5287 response = *trans->GetResponseInfo();
5288 response2 = *trans2->GetResponseInfo();
5289
5290 VerifyStreamsClosed(helper);
5291
5292 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505293 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035294 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5295
5296 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505297 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035298 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5299
[email protected]6cd63ba2014-06-12 16:14:565300 // Verify we got all the headers from all header blocks.
[email protected]0338bc62014-06-20 17:09:565301 if (spdy_util_.spdy_version() < SPDY4)
5302 EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
[email protected]d08358502010-12-03 22:04:035303 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5304 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
[email protected]d55b30a2012-07-21 00:35:395305
5306 // Read the final EOF (which will close the session)
5307 data.RunFor(1);
5308
5309 // Verify that we consumed all test data.
rchb6dc73572015-05-08 04:01:075310 EXPECT_TRUE(data.at_read_eof());
5311 EXPECT_TRUE(data.at_write_eof());
[email protected]d08358502010-12-03 22:04:035312}
5313
[email protected]513963e2013-06-15 01:53:045314TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
[email protected]5c6908e2012-08-06 18:53:475315 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465316 scoped_ptr<SpdyFrame> stream1_syn(
5317 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045318 scoped_ptr<SpdyFrame> stream1_body(
5319 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]5c6908e2012-08-06 18:53:475320 MockWrite writes[] = {
5321 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5322 };
5323
[email protected]513963e2013-06-15 01:53:045324 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005325 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5326 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235327 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565328 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045329
5330 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5331 (*middle_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235332 scoped_ptr<SpdyFrame> stream2_headers1(
[email protected]513963e2013-06-15 01:53:045333 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235334 false,
5335 2,
5336 LOWEST,
5337 HEADERS,
5338 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235339 0));
[email protected]5c6908e2012-08-06 18:53:475340
5341 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045342 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435343 const char kPushedData[] = "pushed";
5344 scoped_ptr<SpdyFrame> stream2_body(
5345 spdy_util_.ConstructSpdyBodyFrame(
5346 2, kPushedData, strlen(kPushedData), true));
[email protected]5c6908e2012-08-06 18:53:475347 MockRead reads[] = {
5348 CreateMockRead(*stream1_reply, 1),
5349 CreateMockRead(*stream2_syn, 2),
5350 CreateMockRead(*stream1_body, 3),
5351 CreateMockRead(*stream2_headers1, 4),
[email protected]8a0fc822013-06-27 20:52:435352 CreateMockRead(*stream2_body, 5),
[email protected]5c6908e2012-08-06 18:53:475353 MockRead(ASYNC, 0, 6), // EOF
5354 };
5355
5356 DeterministicSocketData data(reads, arraysize(reads),
5357 writes, arraysize(writes));
5358
[email protected]262eec82013-03-19 21:01:365359 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]5c6908e2012-08-06 18:53:475360 BoundNetLog(), GetParam(), NULL);
5361 helper.SetDeterministic();
5362 helper.AddDeterministicData(&data);
5363 helper.RunPreTestSetup();
5364
5365 HttpNetworkTransaction* trans = helper.trans();
5366
5367 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5368 // the first HEADERS frame, and the body of the primary stream, but before
5369 // we've received the final HEADERS for the pushed stream.
5370 data.SetStop(4);
5371
5372 // Start the transaction.
5373 TestCompletionCallback callback;
5374 int rv = trans->Start(
5375 &CreateGetRequest(), callback.callback(), BoundNetLog());
5376 EXPECT_EQ(ERR_IO_PENDING, rv);
5377 data.Run();
5378 rv = callback.WaitForResult();
5379 EXPECT_EQ(0, rv);
5380
5381 // Request the pushed path. At this point, we've received the push, but the
5382 // headers are not yet complete.
5383 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:505384 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]5c6908e2012-08-06 18:53:475385 rv = trans2->Start(
5386 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5387 EXPECT_EQ(ERR_IO_PENDING, rv);
5388 data.RunFor(2);
[email protected]fc9d88472013-08-14 02:31:175389 base::RunLoop().RunUntilIdle();
[email protected]5c6908e2012-08-06 18:53:475390
5391 // Read the server push body.
5392 std::string result2;
5393 ReadResult(trans2.get(), &data, &result2);
5394 // Read the response body.
5395 std::string result;
5396 ReadResult(trans, &data, &result);
5397 EXPECT_EQ("hello!", result);
5398
5399 // Verify that we haven't received any push data.
5400 EXPECT_EQ("", result2);
5401
5402 // Verify the SYN_REPLY.
5403 // Copy the response info, because trans goes away.
5404 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]5c6908e2012-08-06 18:53:475405
5406 VerifyStreamsClosed(helper);
5407
5408 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505409 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]5c6908e2012-08-06 18:53:475410 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5411
5412 // Read the final EOF (which will close the session).
5413 data.RunFor(1);
5414
5415 // Verify that we consumed all test data.
rchb6dc73572015-05-08 04:01:075416 EXPECT_TRUE(data.at_read_eof());
5417 EXPECT_TRUE(data.at_write_eof());
[email protected]5c6908e2012-08-06 18:53:475418}
5419
[email protected]513963e2013-06-15 01:53:045420TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:465421 scoped_ptr<SpdyFrame> req(
5422 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:415423 scoped_ptr<SpdyFrame> rst(
5424 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5425 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525426 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]745aa9c2014-06-27 02:21:295427 };
[email protected]d08358502010-12-03 22:04:035428
[email protected]4bd46222013-05-14 19:32:235429 scoped_ptr<SpdyFrame> stream1_reply(
[email protected]745aa9c2014-06-27 02:21:295430 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:045431
5432 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5433 (*late_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235434 scoped_ptr<SpdyFrame> stream1_headers(
[email protected]513963e2013-06-15 01:53:045435 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235436 false,
5437 1,
5438 LOWEST,
5439 HEADERS,
5440 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235441 0));
[email protected]513963e2013-06-15 01:53:045442 scoped_ptr<SpdyFrame> stream1_body(
5443 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035444 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525445 CreateMockRead(*stream1_reply, 1),
5446 CreateMockRead(*stream1_headers, 2),
5447 CreateMockRead(*stream1_body, 3),
5448 MockRead(ASYNC, 0, 5) // EOF
[email protected]d08358502010-12-03 22:04:035449 };
5450
rch08e3aa3e2015-05-16 14:27:525451 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365452 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505453 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:575454 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035455 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:415456 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]d08358502010-12-03 22:04:035457}
5458
[email protected]513963e2013-06-15 01:53:045459TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:465460 scoped_ptr<SpdyFrame> req(
5461 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:415462 scoped_ptr<SpdyFrame> rst(
5463 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5464 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525465 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]b771bb72013-06-24 09:55:415466 };
[email protected]d08358502010-12-03 22:04:035467
[email protected]4bd46222013-05-14 19:32:235468 scoped_ptr<SpdyFrame> stream1_reply(
[email protected]745aa9c2014-06-27 02:21:295469 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:045470
5471 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5472 (*late_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235473 scoped_ptr<SpdyFrame> stream1_headers(
[email protected]513963e2013-06-15 01:53:045474 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235475 false,
5476 1,
5477 LOWEST,
5478 HEADERS,
5479 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235480 0));
[email protected]513963e2013-06-15 01:53:045481 scoped_ptr<SpdyFrame> stream1_body(
5482 spdy_util_.ConstructSpdyBodyFrame(1, false));
5483 scoped_ptr<SpdyFrame> stream1_body2(
5484 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035485 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525486 CreateMockRead(*stream1_reply, 1),
5487 CreateMockRead(*stream1_body, 2),
5488 CreateMockRead(*stream1_headers, 3),
5489 CreateMockRead(*stream1_body2, 5),
5490 MockRead(ASYNC, 0, 6) // EOF
[email protected]d08358502010-12-03 22:04:035491 };
5492
rch32320842015-05-16 15:57:095493 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365494 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505495 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:575496 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035497 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:415498 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]d08358502010-12-03 22:04:035499}
5500
[email protected]513963e2013-06-15 01:53:045501TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
rchebf12982015-04-10 01:15:005502 // Running these tests via Alt-Svc is too complicated to be worthwhile.
5503 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
5504 return;
5505
[email protected]a7a265ef2010-12-08 18:05:575506 // In this test we want to verify that we can't accidentally push content
5507 // which can't be pushed by this content server.
5508 // This test assumes that:
5509 // - if we're requesting http://www.foo.com/barbaz
5510 // - the browser has made a connection to "www.foo.com".
5511
5512 // A list of the URL to fetch, followed by the URL being pushed.
5513 static const char* const kTestCases[] = {
bncce36dca22015-04-21 22:11:235514 "https://www.example.org/foo.html",
5515 "https://www.example.org:81/foo.js", // Bad port
[email protected]a7a265ef2010-12-08 18:05:575516
bncce36dca22015-04-21 22:11:235517 "https://www.example.org/foo.html",
5518 "http://www.example.org/foo.js", // Bad protocol
[email protected]a7a265ef2010-12-08 18:05:575519
bncce36dca22015-04-21 22:11:235520 "https://www.example.org/foo.html",
5521 "ftp://www.example.org/foo.js", // Invalid Protocol
[email protected]a7a265ef2010-12-08 18:05:575522
bncce36dca22015-04-21 22:11:235523 "https://www.example.org/foo.html",
5524 "https://blat.www.example.org/foo.js", // Cross subdomain
[email protected]a7a265ef2010-12-08 18:05:575525
bncce36dca22015-04-21 22:11:235526 "https://www.example.org/foo.html",
rchebf12982015-04-10 01:15:005527 "https://www.foo.com/foo.js", // Cross domain
[email protected]a7a265ef2010-12-08 18:05:575528 };
5529
[email protected]b3f899332010-12-08 18:20:445530 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
[email protected]a7a265ef2010-12-08 18:05:575531 const char* url_to_fetch = kTestCases[index];
5532 const char* url_to_push = kTestCases[index + 1];
5533
[email protected]cdf8f7e72013-05-23 10:56:465534 scoped_ptr<SpdyFrame> stream1_syn(
5535 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
[email protected]513963e2013-06-15 01:53:045536 scoped_ptr<SpdyFrame> stream1_body(
5537 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff98d7f02012-03-22 21:44:195538 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:205539 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]a7a265ef2010-12-08 18:05:575540 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525541 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*push_rst, 3),
[email protected]a7a265ef2010-12-08 18:05:575542 };
5543
[email protected]ff98d7f02012-03-22 21:44:195544 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045545 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:195546 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045547 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5548 0,
5549 2,
5550 1,
5551 url_to_push));
[email protected]8a0fc822013-06-27 20:52:435552 const char kPushedData[] = "pushed";
5553 scoped_ptr<SpdyFrame> stream2_body(
5554 spdy_util_.ConstructSpdyBodyFrame(
5555 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:195556 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:205557 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]a7a265ef2010-12-08 18:05:575558
5559 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525560 CreateMockRead(*stream1_reply, 1),
5561 CreateMockRead(*stream2_syn, 2),
5562 CreateMockRead(*stream1_body, 4),
5563 CreateMockRead(*stream2_body, 5),
5564 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]a7a265ef2010-12-08 18:05:575565 };
5566
5567 HttpResponseInfo response;
rch08e3aa3e2015-05-16 14:27:525568 SequencedSocketData data(reads, arraysize(reads), writes,
5569 arraysize(writes));
[email protected]a7a265ef2010-12-08 18:05:575570
5571 HttpRequestInfo request;
5572 request.method = "GET";
5573 request.url = GURL(url_to_fetch);
5574 request.load_flags = 0;
[email protected]a7a265ef2010-12-08 18:05:575575
[email protected]7c6f7ba2012-04-03 04:09:295576 // Enable cross-origin push. Since we are not using a proxy, this should
5577 // not actually enable cross-origin SPDY push.
[email protected]61b4efc2012-04-27 18:12:505578 scoped_ptr<SpdySessionDependencies> session_deps(
[email protected]513963e2013-06-15 01:53:045579 CreateSpdySessionDependencies(GetParam()));
[email protected]61b4efc2012-04-27 18:12:505580 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
[email protected]262eec82013-03-19 21:01:365581 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505582 BoundNetLog(), GetParam(),
5583 session_deps.release());
5584 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575585 helper.AddData(&data);
[email protected]7c6f7ba2012-04-03 04:09:295586
[email protected]a7a265ef2010-12-08 18:05:575587 HttpNetworkTransaction* trans = helper.trans();
5588
5589 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415590 TestCompletionCallback callback;
[email protected]a7a265ef2010-12-08 18:05:575591
[email protected]49639fa2011-12-20 23:22:415592 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]a7a265ef2010-12-08 18:05:575593 EXPECT_EQ(ERR_IO_PENDING, rv);
5594 rv = callback.WaitForResult();
5595
5596 // Read the response body.
5597 std::string result;
[email protected]dd54bd82012-07-19 23:44:575598 ReadResult(trans, &data, &result);
[email protected]a7a265ef2010-12-08 18:05:575599
5600 // Verify that we consumed all test data.
rchb6dc73572015-05-08 04:01:075601 EXPECT_TRUE(data.at_read_eof());
5602 EXPECT_TRUE(data.at_write_eof());
[email protected]a7a265ef2010-12-08 18:05:575603
5604 // Verify the SYN_REPLY.
5605 // Copy the response info, because trans goes away.
5606 response = *trans->GetResponseInfo();
5607
5608 VerifyStreamsClosed(helper);
5609
5610 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505611 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]a7a265ef2010-12-08 18:05:575612 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5613 }
5614}
5615
[email protected]513963e2013-06-15 01:53:045616TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
[email protected]721c0ce2011-10-13 02:41:005617 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:465618 scoped_ptr<SpdyFrame> req(
5619 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5620 scoped_ptr<SpdyFrame> req2(
5621 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]721c0ce2011-10-13 02:41:005622 MockWrite writes[] = {
rch08e3aa3e2015-05-16 14:27:525623 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 2),
[email protected]721c0ce2011-10-13 02:41:005624 };
5625
[email protected]ff98d7f02012-03-22 21:44:195626 scoped_ptr<SpdyFrame> refused(
[email protected]c10b20852013-05-15 21:29:205627 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
[email protected]513963e2013-06-15 01:53:045628 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5629 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]721c0ce2011-10-13 02:41:005630 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:525631 CreateMockRead(*refused, 1),
5632 CreateMockRead(*resp, 3),
5633 CreateMockRead(*body, 4),
5634 MockRead(ASYNC, 0, 5) // EOF
[email protected]721c0ce2011-10-13 02:41:005635 };
5636
rch08e3aa3e2015-05-16 14:27:525637 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365638 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505639 BoundNetLog(), GetParam(), NULL);
[email protected]721c0ce2011-10-13 02:41:005640
5641 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575642 helper.AddData(&data);
[email protected]721c0ce2011-10-13 02:41:005643
5644 HttpNetworkTransaction* trans = helper.trans();
5645
5646 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415647 TestCompletionCallback callback;
5648 int rv = trans->Start(
5649 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]721c0ce2011-10-13 02:41:005650 EXPECT_EQ(ERR_IO_PENDING, rv);
5651 rv = callback.WaitForResult();
5652 EXPECT_EQ(OK, rv);
5653
5654 // Verify that we consumed all test data.
rch08e3aa3e2015-05-16 14:27:525655 EXPECT_TRUE(data.AllReadDataConsumed());
5656 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]721c0ce2011-10-13 02:41:005657
5658 // Verify the SYN_REPLY.
5659 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:505660 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]721c0ce2011-10-13 02:41:005661 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5662}
5663
[email protected]513963e2013-06-15 01:53:045664TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
[email protected]e1f58efa2012-05-15 18:23:405665 // This first request will start to establish the SpdySession.
5666 // Then we will start the second (MEDIUM priority) and then third
5667 // (HIGHEST priority) request in such a way that the third will actually
[email protected]c92f4b4542012-07-26 23:53:215668 // start before the second, causing the second to be numbered differently
[email protected]513963e2013-06-15 01:53:045669 // than the order they were created.
[email protected]cdf8f7e72013-05-23 10:56:465670 scoped_ptr<SpdyFrame> req1(
5671 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5672 scoped_ptr<SpdyFrame> req2(
5673 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5674 scoped_ptr<SpdyFrame> req3(
5675 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
[email protected]e1f58efa2012-05-15 18:23:405676 MockWrite writes[] = {
5677 CreateMockWrite(*req1, 0),
5678 CreateMockWrite(*req2, 3),
5679 CreateMockWrite(*req3, 4),
5680 };
5681
[email protected]513963e2013-06-15 01:53:045682 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5683 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5684 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5685 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5686 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5687 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]e1f58efa2012-05-15 18:23:405688 MockRead reads[] = {
5689 CreateMockRead(*resp1, 1),
5690 CreateMockRead(*body1, 2),
5691 CreateMockRead(*resp2, 5),
5692 CreateMockRead(*body2, 6),
5693 CreateMockRead(*resp3, 7),
5694 CreateMockRead(*body3, 8),
5695 MockRead(ASYNC, 0, 9) // EOF
5696 };
5697
[email protected]dd54bd82012-07-19 23:44:575698 DeterministicSocketData data(reads, arraysize(reads),
[email protected]513963e2013-06-15 01:53:045699 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365700 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
[email protected]e1f58efa2012-05-15 18:23:405701 BoundNetLog(), GetParam(), NULL);
5702 helper.SetDeterministic();
5703 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575704 helper.AddDeterministicData(&data);
[email protected]e1f58efa2012-05-15 18:23:405705
5706 // Start the first transaction to set up the SpdySession
5707 HttpNetworkTransaction* trans = helper.trans();
5708 TestCompletionCallback callback;
5709 HttpRequestInfo info1 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405710 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
5711 EXPECT_EQ(ERR_IO_PENDING, rv);
5712
5713 // Run the message loop, but do not allow the write to complete.
5714 // This leaves the SpdySession with a write pending, which prevents
5715 // SpdySession from attempting subsequent writes until this write completes.
[email protected]fc9d88472013-08-14 02:31:175716 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405717
5718 // Now, start both new transactions
5719 HttpRequestInfo info2 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405720 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:505721 scoped_ptr<HttpNetworkTransaction> trans2(
5722 new HttpNetworkTransaction(MEDIUM, helper.session().get()));
[email protected]e1f58efa2012-05-15 18:23:405723 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
5724 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:175725 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405726
5727 HttpRequestInfo info3 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405728 TestCompletionCallback callback3;
5729 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:505730 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
[email protected]e1f58efa2012-05-15 18:23:405731 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5732 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:175733 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405734
5735 // We now have two SYN_STREAM frames queued up which will be
5736 // dequeued only once the first write completes, which we
5737 // now allow to happen.
[email protected]dd54bd82012-07-19 23:44:575738 data.RunFor(2);
[email protected]e1f58efa2012-05-15 18:23:405739 EXPECT_EQ(OK, callback.WaitForResult());
5740
5741 // And now we can allow everything else to run to completion.
[email protected]dd54bd82012-07-19 23:44:575742 data.SetStop(10);
5743 data.Run();
[email protected]e1f58efa2012-05-15 18:23:405744 EXPECT_EQ(OK, callback2.WaitForResult());
5745 EXPECT_EQ(OK, callback3.WaitForResult());
5746
5747 helper.VerifyDataConsumed();
5748}
5749
[email protected]d11b6912013-06-27 23:07:325750// The tests below are only for SPDY/3 and above.
5751
5752// Test that sent data frames and received WINDOW_UPDATE frames change
5753// the send_window_size_ correctly.
5754
5755// WINDOW_UPDATE is different than most other frames in that it can arrive
5756// while the client is still sending the request body. In order to enforce
5757// this scenario, we feed a couple of dummy frames and give a delay of 0 to
5758// socket data provider, so that initial read that is done as soon as the
5759// stream is created, succeeds and schedules another read. This way reads
5760// and writes are interleaved; after doing a full frame write, SpdyStream
5761// will break out of DoLoop and will read and process a WINDOW_UPDATE.
5762// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5763// since request has not been completely written, therefore we feed
5764// enough number of WINDOW_UPDATEs to finish the first read and cause a
5765// write, leading to a complete write of request body; after that we send
5766// a reply with a body, to cause a graceful shutdown.
5767
5768// TODO(agayev): develop a socket data provider where both, reads and
5769// writes are ordered so that writing tests like these are easy and rewrite
5770// all these tests using it. Right now we are working around the
5771// limitations as described above and it's not deterministic, tests may
5772// fail under specific circumstances.
5773TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
[email protected]d11b6912013-06-27 23:07:325774 static int kFrameCount = 2;
5775 scoped_ptr<std::string> content(
5776 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5777 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:005778 GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL,
5779 0));
[email protected]d11b6912013-06-27 23:07:325780 scoped_ptr<SpdyFrame> body(
5781 spdy_util_.ConstructSpdyBodyFrame(
5782 1, content->c_str(), content->size(), false));
5783 scoped_ptr<SpdyFrame> body_end(
5784 spdy_util_.ConstructSpdyBodyFrame(
5785 1, content->c_str(), content->size(), true));
5786
5787 MockWrite writes[] = {
5788 CreateMockWrite(*req, 0),
5789 CreateMockWrite(*body, 1),
5790 CreateMockWrite(*body_end, 2),
5791 };
5792
5793 static const int32 kDeltaWindowSize = 0xff;
5794 static const int kDeltaCount = 4;
5795 scoped_ptr<SpdyFrame> window_update(
5796 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5797 scoped_ptr<SpdyFrame> window_update_dummy(
5798 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5799 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
5800 MockRead reads[] = {
5801 CreateMockRead(*window_update_dummy, 3),
5802 CreateMockRead(*window_update_dummy, 4),
5803 CreateMockRead(*window_update_dummy, 5),
5804 CreateMockRead(*window_update, 6), // Four updates, therefore window
5805 CreateMockRead(*window_update, 7), // size should increase by
5806 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
5807 CreateMockRead(*window_update, 9),
5808 CreateMockRead(*resp, 10),
5809 CreateMockRead(*body_end, 11),
5810 MockRead(ASYNC, 0, 0, 12) // EOF
5811 };
5812
5813 DeterministicSocketData data(reads, arraysize(reads),
5814 writes, arraysize(writes));
5815
5816 ScopedVector<UploadElementReader> element_readers;
5817 for (int i = 0; i < kFrameCount; ++i) {
5818 element_readers.push_back(
5819 new UploadBytesElementReader(content->c_str(), content->size()));
5820 }
mmenkecbc2b712014-10-09 20:29:075821 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:325822
5823 // Setup the request
5824 HttpRequestInfo request;
5825 request.method = "POST";
rchebf12982015-04-10 01:15:005826 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:325827 request.upload_data_stream = &upload_data_stream;
5828
5829 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5830 BoundNetLog(), GetParam(), NULL);
5831 helper.SetDeterministic();
5832 helper.AddDeterministicData(&data);
5833 helper.RunPreTestSetup();
5834
5835 HttpNetworkTransaction* trans = helper.trans();
5836
5837 TestCompletionCallback callback;
5838 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5839
5840 EXPECT_EQ(ERR_IO_PENDING, rv);
5841
5842 data.RunFor(11);
5843
5844 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5845 ASSERT_TRUE(stream != NULL);
5846 ASSERT_TRUE(stream->stream() != NULL);
bnc638c4702015-04-09 18:01:185847 EXPECT_EQ(static_cast<int>(
5848 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol)) +
5849 kDeltaWindowSize * kDeltaCount -
5850 kMaxSpdyFrameChunkSize * kFrameCount,
5851 stream->stream()->send_window_size());
[email protected]d11b6912013-06-27 23:07:325852
5853 data.RunFor(1);
5854
5855 rv = callback.WaitForResult();
5856 EXPECT_EQ(OK, rv);
5857
5858 helper.VerifyDataConsumed();
5859}
5860
5861// Test that received data frames and sent WINDOW_UPDATE frames change
5862// the recv_window_size_ correctly.
5863TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
bnc8f0f3b62015-04-08 04:37:235864 const int32 default_initial_window_size =
bnc638c4702015-04-09 18:01:185865 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
bnc8f0f3b62015-04-08 04:37:235866 // Session level maximum window size that is more than twice the default
5867 // initial window size so that an initial window update is sent.
5868 const int32 session_max_recv_window_size = 5 * 64 * 1024;
5869 ASSERT_LT(2 * default_initial_window_size, session_max_recv_window_size);
5870 // Stream level maximum window size that is less than the session level
5871 // maximum window size so that we test for confusion between the two.
5872 const int32 stream_max_recv_window_size = 4 * 64 * 1024;
5873 ASSERT_GT(session_max_recv_window_size, stream_max_recv_window_size);
5874 // Size of body to be sent. Has to be less than or equal to both window sizes
5875 // so that we do not run out of receiving window. Also has to be greater than
5876 // half of them so that it triggers both a session level and a stream level
5877 // window update frame.
5878 const int32 kTargetSize = 3 * 64 * 1024;
5879 ASSERT_GE(session_max_recv_window_size, kTargetSize);
5880 ASSERT_GE(stream_max_recv_window_size, kTargetSize);
5881 ASSERT_LT(session_max_recv_window_size / 2, kTargetSize);
5882 ASSERT_LT(stream_max_recv_window_size / 2, kTargetSize);
5883 // Size of each DATA frame.
5884 const int32 kChunkSize = 4096;
5885 // Size of window updates.
5886 ASSERT_EQ(0, session_max_recv_window_size / 2 % kChunkSize);
5887 const int32 session_window_update_delta =
5888 session_max_recv_window_size / 2 + kChunkSize;
5889 ASSERT_EQ(0, stream_max_recv_window_size / 2 % kChunkSize);
5890 const int32 stream_window_update_delta =
5891 stream_max_recv_window_size / 2 + kChunkSize;
[email protected]d11b6912013-06-27 23:07:325892
bnc8f0f3b62015-04-08 04:37:235893 SettingsMap initial_settings;
5894 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
5895 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
5896 initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
5897 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size);
5898 scoped_ptr<SpdyFrame> initial_settings_frame(
5899 spdy_util_.ConstructSpdySettings(initial_settings));
5900 scoped_ptr<SpdyFrame> initial_window_update(
5901 spdy_util_.ConstructSpdyWindowUpdate(
5902 kSessionFlowControlStreamId,
5903 session_max_recv_window_size - default_initial_window_size));
[email protected]d11b6912013-06-27 23:07:325904 scoped_ptr<SpdyFrame> req(
5905 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5906 scoped_ptr<SpdyFrame> session_window_update(
bnc8f0f3b62015-04-08 04:37:235907 spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta));
5908 scoped_ptr<SpdyFrame> stream_window_update(
5909 spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta));
[email protected]d11b6912013-06-27 23:07:325910
5911 std::vector<MockWrite> writes;
bnc8f0f3b62015-04-08 04:37:235912 if ((GetParam().protocol >= kProtoSPDY4MinimumVersion) &&
5913 (GetParam().protocol <= kProtoSPDY4MaximumVersion)) {
5914 writes.push_back(MockWrite(ASYNC, kHttp2ConnectionHeaderPrefix,
5915 kHttp2ConnectionHeaderPrefixSize, 0));
5916 }
5917 writes.push_back(CreateMockWrite(*initial_settings_frame));
5918 writes.push_back(CreateMockWrite(*initial_window_update));
[email protected]d11b6912013-06-27 23:07:325919 writes.push_back(CreateMockWrite(*req));
bnc8f0f3b62015-04-08 04:37:235920 writes.push_back(CreateMockWrite(*session_window_update));
5921 writes.push_back(CreateMockWrite(*stream_window_update));
[email protected]d11b6912013-06-27 23:07:325922
[email protected]251029e2014-03-19 06:04:405923 std::vector<MockRead> reads;
[email protected]d11b6912013-06-27 23:07:325924 scoped_ptr<SpdyFrame> resp(
5925 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]251029e2014-03-19 06:04:405926 reads.push_back(CreateMockRead(*resp));
[email protected]d11b6912013-06-27 23:07:325927
[email protected]251029e2014-03-19 06:04:405928 ScopedVector<SpdyFrame> body_frames;
bnc8f0f3b62015-04-08 04:37:235929 const std::string body_data(kChunkSize, 'x');
[email protected]251029e2014-03-19 06:04:405930 for (size_t remaining = kTargetSize; remaining != 0;) {
5931 size_t frame_size = std::min(remaining, body_data.size());
5932 body_frames.push_back(spdy_util_.ConstructSpdyBodyFrame(
5933 1, body_data.data(), frame_size, false));
5934 reads.push_back(CreateMockRead(*body_frames.back()));
5935 remaining -= frame_size;
5936 }
bnc2f54c832014-12-01 13:31:195937 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 0)); // Yield.
[email protected]251029e2014-03-19 06:04:405938
bnc8f0f3b62015-04-08 04:37:235939 DelayedSocketData data(2, vector_as_array(&reads), reads.size(),
[email protected]d11b6912013-06-27 23:07:325940 vector_as_array(&writes), writes.size());
5941
5942 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5943 BoundNetLog(), GetParam(), NULL);
5944 helper.AddData(&data);
5945 helper.RunPreTestSetup();
[email protected]d11b6912013-06-27 23:07:325946
bnc8f0f3b62015-04-08 04:37:235947 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5948 SpdySessionPoolPeer pool_peer(spdy_session_pool);
5949 pool_peer.SetEnableSendingInitialData(true);
5950 pool_peer.SetSessionMaxRecvWindowSize(session_max_recv_window_size);
5951 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
5952
5953 HttpNetworkTransaction* trans = helper.trans();
[email protected]d11b6912013-06-27 23:07:325954 TestCompletionCallback callback;
5955 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5956
5957 EXPECT_EQ(ERR_IO_PENDING, rv);
5958 rv = callback.WaitForResult();
5959 EXPECT_EQ(OK, rv);
5960
5961 SpdyHttpStream* stream =
5962 static_cast<SpdyHttpStream*>(trans->stream_.get());
5963 ASSERT_TRUE(stream != NULL);
5964 ASSERT_TRUE(stream->stream() != NULL);
5965
[email protected]251029e2014-03-19 06:04:405966 // All data has been read, but not consumed. The window reflects this.
bnc8f0f3b62015-04-08 04:37:235967 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size - kTargetSize),
[email protected]251029e2014-03-19 06:04:405968 stream->stream()->recv_window_size());
[email protected]d11b6912013-06-27 23:07:325969
5970 const HttpResponseInfo* response = trans->GetResponseInfo();
5971 ASSERT_TRUE(response != NULL);
5972 ASSERT_TRUE(response->headers.get() != NULL);
5973 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5974 EXPECT_TRUE(response->was_fetched_via_spdy);
5975
5976 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5977 // size increased to default.
bnc301745a2015-03-10 03:22:165978 scoped_refptr<IOBuffer> buf(new IOBuffer(kTargetSize));
[email protected]251029e2014-03-19 06:04:405979 EXPECT_EQ(static_cast<int>(kTargetSize),
5980 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
bnc8f0f3b62015-04-08 04:37:235981 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size),
[email protected]251029e2014-03-19 06:04:405982 stream->stream()->recv_window_size());
5983 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
[email protected]d11b6912013-06-27 23:07:325984
[email protected]251029e2014-03-19 06:04:405985 // Allow scheduled WINDOW_UPDATE frames to write.
[email protected]fc9d88472013-08-14 02:31:175986 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:325987 helper.VerifyDataConsumed();
5988}
5989
5990// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
5991TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]d11b6912013-06-27 23:07:325992 // Number of full frames we hope to write (but will not, used to
5993 // set content-length header correctly)
5994 static int kFrameCount = 3;
5995
5996 scoped_ptr<std::string> content(
5997 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5998 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:005999 GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL,
6000 0));
[email protected]d11b6912013-06-27 23:07:326001 scoped_ptr<SpdyFrame> body(
6002 spdy_util_.ConstructSpdyBodyFrame(
6003 1, content->c_str(), content->size(), false));
6004 scoped_ptr<SpdyFrame> rst(
6005 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
6006
6007 // We're not going to write a data frame with FIN, we'll receive a bad
6008 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6009 MockWrite writes[] = {
6010 CreateMockWrite(*req, 0),
6011 CreateMockWrite(*body, 2),
6012 CreateMockWrite(*rst, 3),
6013 };
6014
6015 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
6016 scoped_ptr<SpdyFrame> window_update(
6017 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6018 MockRead reads[] = {
6019 CreateMockRead(*window_update, 1),
6020 MockRead(ASYNC, 0, 4) // EOF
6021 };
6022
6023 DeterministicSocketData data(reads, arraysize(reads),
6024 writes, arraysize(writes));
6025
6026 ScopedVector<UploadElementReader> element_readers;
6027 for (int i = 0; i < kFrameCount; ++i) {
6028 element_readers.push_back(
6029 new UploadBytesElementReader(content->c_str(), content->size()));
6030 }
mmenkecbc2b712014-10-09 20:29:076031 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326032
6033 // Setup the request
6034 HttpRequestInfo request;
6035 request.method = "POST";
rchebf12982015-04-10 01:15:006036 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326037 request.upload_data_stream = &upload_data_stream;
6038
6039 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6040 BoundNetLog(), GetParam(), NULL);
6041 helper.SetDeterministic();
6042 helper.RunPreTestSetup();
6043 helper.AddDeterministicData(&data);
6044 HttpNetworkTransaction* trans = helper.trans();
6045
6046 TestCompletionCallback callback;
6047 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6048 ASSERT_EQ(ERR_IO_PENDING, rv);
6049
6050 data.RunFor(5);
6051 ASSERT_TRUE(callback.have_result());
6052 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6053 helper.VerifyDataConsumed();
6054}
6055
6056// Test that after hitting a send window size of 0, the write process
6057// stalls and upon receiving WINDOW_UPDATE frame write resumes.
6058
6059// This test constructs a POST request followed by enough data frames
6060// containing 'a' that would make the window size 0, followed by another
6061// data frame containing default content (which is "hello!") and this frame
6062// also contains a FIN flag. DelayedSocketData is used to enforce all
6063// writes go through before a read could happen. However, the last frame
6064// ("hello!") is not supposed to go through since by the time its turn
6065// arrives, window size is 0. At this point MessageLoop::Run() called via
6066// callback would block. Therefore we call MessageLoop::RunUntilIdle()
6067// which returns after performing all possible writes. We use DCHECKS to
6068// ensure that last data frame is still there and stream has stalled.
6069// After that, next read is artifically enforced, which causes a
6070// WINDOW_UPDATE to be read and I/O process resumes.
6071TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
bnc2f54c832014-12-01 13:31:196072 const int32 initial_window_size =
bnc638c4702015-04-09 18:01:186073 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
[email protected]d11b6912013-06-27 23:07:326074 // Number of frames we need to send to zero out the window size: data
6075 // frames plus SYN_STREAM plus the last data frame; also we need another
6076 // data frame that we will send once the WINDOW_UPDATE is received,
6077 // therefore +3.
bnc2f54c832014-12-01 13:31:196078 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326079
6080 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196081 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326082
6083 // Construct content for a data frame of maximum size.
6084 std::string content(kMaxSpdyFrameChunkSize, 'a');
6085
6086 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006087 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6088 0));
[email protected]d11b6912013-06-27 23:07:326089
6090 // Full frames.
6091 scoped_ptr<SpdyFrame> body1(
6092 spdy_util_.ConstructSpdyBodyFrame(
6093 1, content.c_str(), content.size(), false));
6094
6095 // Last frame to zero out the window size.
6096 scoped_ptr<SpdyFrame> body2(
6097 spdy_util_.ConstructSpdyBodyFrame(
6098 1, content.c_str(), last_frame_size, false));
6099
6100 // Data frame to be sent once WINDOW_UPDATE frame is received.
6101 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6102
6103 // Fill in mock writes.
6104 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6105 size_t i = 0;
6106 writes[i] = CreateMockWrite(*req);
6107 for (i = 1; i < num_writes - 2; i++)
6108 writes[i] = CreateMockWrite(*body1);
6109 writes[i++] = CreateMockWrite(*body2);
6110 writes[i] = CreateMockWrite(*body3);
6111
6112 // Construct read frame, give enough space to upload the rest of the
6113 // data.
6114 scoped_ptr<SpdyFrame> session_window_update(
6115 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6116 scoped_ptr<SpdyFrame> window_update(
6117 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6118 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6119 MockRead reads[] = {
6120 CreateMockRead(*session_window_update),
6121 CreateMockRead(*session_window_update),
6122 CreateMockRead(*window_update),
6123 CreateMockRead(*window_update),
6124 CreateMockRead(*reply),
6125 CreateMockRead(*body2),
6126 CreateMockRead(*body3),
6127 MockRead(ASYNC, 0, 0) // EOF
6128 };
6129
6130 // Skip the session window updates unless we're using SPDY/3.1 and
6131 // above.
6132 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6133 size_t num_reads = arraysize(reads) - read_offset;
6134
6135 // Force all writes to happen before any read, last write will not
6136 // actually queue a frame, due to window size being 0.
6137 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6138 writes.get(), num_writes);
6139
6140 ScopedVector<UploadElementReader> element_readers;
bnc2f54c832014-12-01 13:31:196141 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326142 upload_data_string.append(kUploadData, kUploadDataSize);
6143 element_readers.push_back(new UploadBytesElementReader(
6144 upload_data_string.c_str(), upload_data_string.size()));
mmenkecbc2b712014-10-09 20:29:076145 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326146
6147 HttpRequestInfo request;
6148 request.method = "POST";
rchebf12982015-04-10 01:15:006149 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326150 request.upload_data_stream = &upload_data_stream;
6151 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6152 BoundNetLog(), GetParam(), NULL);
6153 helper.AddData(&data);
6154 helper.RunPreTestSetup();
6155
6156 HttpNetworkTransaction* trans = helper.trans();
6157
6158 TestCompletionCallback callback;
6159 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6160 EXPECT_EQ(ERR_IO_PENDING, rv);
6161
[email protected]fc9d88472013-08-14 02:31:176162 base::RunLoop().RunUntilIdle(); // Write as much as we can.
[email protected]d11b6912013-06-27 23:07:326163
6164 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6165 ASSERT_TRUE(stream != NULL);
6166 ASSERT_TRUE(stream->stream() != NULL);
6167 EXPECT_EQ(0, stream->stream()->send_window_size());
6168 // All the body data should have been read.
6169 // TODO(satorux): This is because of the weirdness in reading the request
6170 // body in OnSendBodyComplete(). See crbug.com/113107.
6171 EXPECT_TRUE(upload_data_stream.IsEOF());
6172 // But the body is not yet fully sent (kUploadData is not yet sent)
6173 // since we're send-stalled.
6174 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6175
6176 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6177 rv = callback.WaitForResult();
6178 helper.VerifyDataConsumed();
6179}
6180
6181// Test we correctly handle the case where the SETTINGS frame results in
6182// unstalling the send window.
6183TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
bnc2f54c832014-12-01 13:31:196184 const int32 initial_window_size =
bnc638c4702015-04-09 18:01:186185 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
bnc2f54c832014-12-01 13:31:196186
[email protected]d11b6912013-06-27 23:07:326187 // Number of frames we need to send to zero out the window size: data
6188 // frames plus SYN_STREAM plus the last data frame; also we need another
6189 // data frame that we will send once the SETTING is received, therefore +3.
bnc2f54c832014-12-01 13:31:196190 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326191
6192 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196193 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326194
6195 // Construct content for a data frame of maximum size.
6196 std::string content(kMaxSpdyFrameChunkSize, 'a');
6197
6198 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006199 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6200 0));
[email protected]d11b6912013-06-27 23:07:326201
6202 // Full frames.
6203 scoped_ptr<SpdyFrame> body1(
6204 spdy_util_.ConstructSpdyBodyFrame(
6205 1, content.c_str(), content.size(), false));
6206
6207 // Last frame to zero out the window size.
6208 scoped_ptr<SpdyFrame> body2(
6209 spdy_util_.ConstructSpdyBodyFrame(
6210 1, content.c_str(), last_frame_size, false));
6211
6212 // Data frame to be sent once SETTINGS frame is received.
6213 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6214
6215 // Fill in mock reads/writes.
6216 std::vector<MockRead> reads;
6217 std::vector<MockWrite> writes;
6218 size_t i = 0;
6219 writes.push_back(CreateMockWrite(*req, i++));
6220 while (i < num_writes - 2)
6221 writes.push_back(CreateMockWrite(*body1, i++));
6222 writes.push_back(CreateMockWrite(*body2, i++));
6223
6224 // Construct read frame for SETTINGS that gives enough space to upload the
6225 // rest of the data.
6226 SettingsMap settings;
6227 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:196228 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
[email protected]d11b6912013-06-27 23:07:326229 scoped_ptr<SpdyFrame> settings_frame_large(
6230 spdy_util_.ConstructSpdySettings(settings));
6231
6232 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6233
6234 scoped_ptr<SpdyFrame> session_window_update(
6235 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6236 if (GetParam().protocol >= kProtoSPDY31)
6237 reads.push_back(CreateMockRead(*session_window_update, i++));
6238
[email protected]d4a77c12014-05-15 20:45:216239 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6240 writes.push_back(CreateMockWrite(*settings_ack, i++));
6241
[email protected]d11b6912013-06-27 23:07:326242 writes.push_back(CreateMockWrite(*body3, i++));
6243
6244 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6245 reads.push_back(CreateMockRead(*reply, i++));
6246 reads.push_back(CreateMockRead(*body2, i++));
6247 reads.push_back(CreateMockRead(*body3, i++));
6248 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6249
6250 // Force all writes to happen before any read, last write will not
6251 // actually queue a frame, due to window size being 0.
6252 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6253 vector_as_array(&writes), writes.size());
6254
6255 ScopedVector<UploadElementReader> element_readers;
bnc2f54c832014-12-01 13:31:196256 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326257 upload_data_string.append(kUploadData, kUploadDataSize);
6258 element_readers.push_back(new UploadBytesElementReader(
6259 upload_data_string.c_str(), upload_data_string.size()));
mmenkecbc2b712014-10-09 20:29:076260 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326261
6262 HttpRequestInfo request;
6263 request.method = "POST";
rchebf12982015-04-10 01:15:006264 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326265 request.upload_data_stream = &upload_data_stream;
6266 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6267 BoundNetLog(), GetParam(), NULL);
6268 helper.SetDeterministic();
6269 helper.RunPreTestSetup();
6270 helper.AddDeterministicData(&data);
6271
6272 HttpNetworkTransaction* trans = helper.trans();
6273
6274 TestCompletionCallback callback;
6275 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6276 EXPECT_EQ(ERR_IO_PENDING, rv);
6277
6278 data.RunFor(num_writes - 1); // Write as much as we can.
6279
6280 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6281 ASSERT_TRUE(stream != NULL);
6282 ASSERT_TRUE(stream->stream() != NULL);
6283 EXPECT_EQ(0, stream->stream()->send_window_size());
6284
6285 // All the body data should have been read.
6286 // TODO(satorux): This is because of the weirdness in reading the request
6287 // body in OnSendBodyComplete(). See crbug.com/113107.
6288 EXPECT_TRUE(upload_data_stream.IsEOF());
6289 // But the body is not yet fully sent (kUploadData is not yet sent)
6290 // since we're send-stalled.
6291 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6292
[email protected]d4a77c12014-05-15 20:45:216293 data.RunFor(7); // Read in SETTINGS frame to unstall.
[email protected]d11b6912013-06-27 23:07:326294 rv = callback.WaitForResult();
6295 helper.VerifyDataConsumed();
6296 // If stream is NULL, that means it was unstalled and closed.
6297 EXPECT_TRUE(stream->stream() == NULL);
6298}
6299
6300// Test we correctly handle the case where the SETTINGS frame results in a
6301// negative send window size.
6302TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
bnc2f54c832014-12-01 13:31:196303 const int32 initial_window_size =
bnc638c4702015-04-09 18:01:186304 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
[email protected]d11b6912013-06-27 23:07:326305 // Number of frames we need to send to zero out the window size: data
6306 // frames plus SYN_STREAM plus the last data frame; also we need another
6307 // data frame that we will send once the SETTING is received, therefore +3.
bnc2f54c832014-12-01 13:31:196308 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326309
6310 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196311 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326312
6313 // Construct content for a data frame of maximum size.
6314 std::string content(kMaxSpdyFrameChunkSize, 'a');
6315
6316 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006317 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6318 0));
[email protected]d11b6912013-06-27 23:07:326319
6320 // Full frames.
6321 scoped_ptr<SpdyFrame> body1(
6322 spdy_util_.ConstructSpdyBodyFrame(
6323 1, content.c_str(), content.size(), false));
6324
6325 // Last frame to zero out the window size.
6326 scoped_ptr<SpdyFrame> body2(
6327 spdy_util_.ConstructSpdyBodyFrame(
6328 1, content.c_str(), last_frame_size, false));
6329
6330 // Data frame to be sent once SETTINGS frame is received.
6331 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6332
6333 // Fill in mock reads/writes.
6334 std::vector<MockRead> reads;
6335 std::vector<MockWrite> writes;
6336 size_t i = 0;
6337 writes.push_back(CreateMockWrite(*req, i++));
6338 while (i < num_writes - 2)
6339 writes.push_back(CreateMockWrite(*body1, i++));
6340 writes.push_back(CreateMockWrite(*body2, i++));
6341
6342 // Construct read frame for SETTINGS that makes the send_window_size
6343 // negative.
6344 SettingsMap new_settings;
6345 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:196346 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
[email protected]d11b6912013-06-27 23:07:326347 scoped_ptr<SpdyFrame> settings_frame_small(
6348 spdy_util_.ConstructSpdySettings(new_settings));
6349 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6350 // positive.
6351 scoped_ptr<SpdyFrame> session_window_update_init_size(
bnc2f54c832014-12-01 13:31:196352 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
[email protected]d11b6912013-06-27 23:07:326353 scoped_ptr<SpdyFrame> window_update_init_size(
bnc2f54c832014-12-01 13:31:196354 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
[email protected]d11b6912013-06-27 23:07:326355
6356 reads.push_back(CreateMockRead(*settings_frame_small, i++));
bnc33b8cef42014-11-19 17:30:386357 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
[email protected]d11b6912013-06-27 23:07:326358 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6359
[email protected]d4a77c12014-05-15 20:45:216360 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6361 writes.push_back(CreateMockWrite(*settings_ack, i++));
6362
[email protected]d11b6912013-06-27 23:07:326363 writes.push_back(CreateMockWrite(*body3, i++));
6364
6365 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6366 reads.push_back(CreateMockRead(*reply, i++));
6367 reads.push_back(CreateMockRead(*body2, i++));
6368 reads.push_back(CreateMockRead(*body3, i++));
6369 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6370
6371 // Force all writes to happen before any read, last write will not
6372 // actually queue a frame, due to window size being 0.
6373 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6374 vector_as_array(&writes), writes.size());
6375
6376 ScopedVector<UploadElementReader> element_readers;
bnc2f54c832014-12-01 13:31:196377 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326378 upload_data_string.append(kUploadData, kUploadDataSize);
6379 element_readers.push_back(new UploadBytesElementReader(
6380 upload_data_string.c_str(), upload_data_string.size()));
mmenkecbc2b712014-10-09 20:29:076381 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326382
6383 HttpRequestInfo request;
6384 request.method = "POST";
rchebf12982015-04-10 01:15:006385 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326386 request.upload_data_stream = &upload_data_stream;
6387 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6388 BoundNetLog(), GetParam(), NULL);
6389 helper.SetDeterministic();
6390 helper.RunPreTestSetup();
6391 helper.AddDeterministicData(&data);
6392
6393 HttpNetworkTransaction* trans = helper.trans();
6394
6395 TestCompletionCallback callback;
6396 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6397 EXPECT_EQ(ERR_IO_PENDING, rv);
6398
6399 data.RunFor(num_writes - 1); // Write as much as we can.
6400
6401 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6402 ASSERT_TRUE(stream != NULL);
6403 ASSERT_TRUE(stream->stream() != NULL);
6404 EXPECT_EQ(0, stream->stream()->send_window_size());
6405
6406 // All the body data should have been read.
6407 // TODO(satorux): This is because of the weirdness in reading the request
6408 // body in OnSendBodyComplete(). See crbug.com/113107.
6409 EXPECT_TRUE(upload_data_stream.IsEOF());
6410 // But the body is not yet fully sent (kUploadData is not yet sent)
6411 // since we're send-stalled.
6412 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6413
6414 // Read in WINDOW_UPDATE or SETTINGS frame.
[email protected]d4a77c12014-05-15 20:45:216415 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 9 : 8);
[email protected]d11b6912013-06-27 23:07:326416 rv = callback.WaitForResult();
6417 helper.VerifyDataConsumed();
6418}
6419
baranovich212a1292014-09-02 21:45:316420TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
6421 if (spdy_util_.spdy_version() < SPDY3)
6422 return;
6423
6424 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
bncce36dca22015-04-21 22:11:236425 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat",
baranovich212a1292014-09-02 21:45:316426 push_headers.get());
6427 scoped_ptr<SpdyFrame> push(
6428 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 3, 1));
6429 MockRead reads[] = {CreateMockRead(*push, 1)};
6430
6431 scoped_ptr<SpdyFrame> req(
6432 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6433 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6434 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6435 MockWrite writes[] = {
6436 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
6437 };
6438
rch08e3aa3e2015-05-16 14:27:526439 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
baranovich212a1292014-09-02 21:45:316440 NormalSpdyTransactionHelper helper(
6441 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6442 helper.RunToCompletion(&data);
6443 TransactionHelperResult out = helper.output();
6444 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6445}
6446
6447TEST_P(SpdyNetworkTransactionTest,
6448 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
6449 if (spdy_util_.spdy_version() < SPDY3)
6450 return;
6451
6452 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:006453 NULL, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
baranovich212a1292014-09-02 21:45:316454 scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
rchebf12982015-04-10 01:15:006455 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/b.dat"),
baranovich212a1292014-09-02 21:45:316456 push_b_headers.get());
6457 scoped_ptr<SpdyFrame> push_b(
6458 spdy_util_.ConstructInitialSpdyPushFrame(push_b_headers.Pass(), 2, 1));
6459 MockRead reads[] = {
6460 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
6461 };
6462
6463 scoped_ptr<SpdyFrame> req(
6464 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6465 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6466 4,
6467 GOAWAY_PROTOCOL_ERROR,
6468 "New push stream id must be greater than the last accepted."));
6469 MockWrite writes[] = {
6470 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
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
[email protected]514aeaf2014-05-23 10:31:516481class SpdyNetworkTransactionNoTLSUsageCheckTest
6482 : public SpdyNetworkTransactionTest {
6483 protected:
6484 void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6485 // Construct the request.
rchebf12982015-04-10 01:15:006486 scoped_ptr<SpdyFrame> req(
6487 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch08e3aa3e2015-05-16 14:27:526488 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]514aeaf2014-05-23 10:31:516489
6490 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6491 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6492 MockRead reads[] = {
rch08e3aa3e2015-05-16 14:27:526493 CreateMockRead(*resp, 1),
6494 CreateMockRead(*body, 2),
6495 MockRead(ASYNC, 0, 3) // EOF
[email protected]514aeaf2014-05-23 10:31:516496 };
6497
rch08e3aa3e2015-05-16 14:27:526498 SequencedSocketData data(reads, arraysize(reads), writes,
6499 arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516500 HttpRequestInfo request;
6501 request.method = "GET";
bncce36dca22015-04-21 22:11:236502 request.url = GURL("https://www.example.org/");
[email protected]514aeaf2014-05-23 10:31:516503 NormalSpdyTransactionHelper helper(
6504 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6505 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6506 TransactionHelperResult out = helper.output();
6507 EXPECT_EQ(OK, out.rv);
6508 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
6509 EXPECT_EQ("hello!", out.response_data);
6510 }
6511};
6512
6513//-----------------------------------------------------------------------------
6514// All tests are run with three different connection types: SPDY after NPN
6515// negotiation, SPDY without SSL, and SPDY with SSL.
6516//
6517// TODO(akalin): Use ::testing::Combine() when we are able to use
6518// <tr1/tuple>.
6519INSTANTIATE_TEST_CASE_P(
6520 Spdy,
6521 SpdyNetworkTransactionNoTLSUsageCheckTest,
rchebf12982015-04-10 01:15:006522 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31,
6523 HTTPS_SPDY_VIA_NPN)));
[email protected]514aeaf2014-05-23 10:31:516524
6525TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6526 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6527 new SSLSocketDataProvider(ASYNC, OK));
6528 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6529 &ssl_provider->connection_status);
6530
6531 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6532}
6533
6534TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6535 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6536 new SSLSocketDataProvider(ASYNC, OK));
6537 // Set to TLS_RSA_WITH_NULL_MD5
6538 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6539
6540 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6541}
6542
6543class SpdyNetworkTransactionTLSUsageCheckTest
6544 : public SpdyNetworkTransactionTest {
6545 protected:
6546 void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]bdd1b222014-06-10 11:08:396547 scoped_ptr<SpdyFrame> goaway(
6548 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6549 MockWrite writes[] = {CreateMockWrite(*goaway)};
[email protected]514aeaf2014-05-23 10:31:516550
rch08e3aa3e2015-05-16 14:27:526551 StaticSocketDataProvider data(NULL, 0, writes, arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516552 HttpRequestInfo request;
6553 request.method = "GET";
bncce36dca22015-04-21 22:11:236554 request.url = GURL("https://www.example.org/");
[email protected]514aeaf2014-05-23 10:31:516555 NormalSpdyTransactionHelper helper(
6556 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6557 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6558 TransactionHelperResult out = helper.output();
6559 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6560 }
6561};
6562
6563INSTANTIATE_TEST_CASE_P(
6564 Spdy,
6565 SpdyNetworkTransactionTLSUsageCheckTest,
rchebf12982015-04-10 01:15:006566 ::testing::Values(
6567 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, HTTPS_SPDY_VIA_NPN),
6568 SpdyNetworkTransactionTestParams(kProtoSPDY4, HTTPS_SPDY_VIA_NPN)));
[email protected]514aeaf2014-05-23 10:31:516569
6570TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6571 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6572 new SSLSocketDataProvider(ASYNC, OK));
6573 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6574 &ssl_provider->connection_status);
6575
6576 RunTLSUsageCheckTest(ssl_provider.Pass());
6577}
6578
6579TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6580 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6581 new SSLSocketDataProvider(ASYNC, OK));
6582 // Set to TLS_RSA_WITH_NULL_MD5
6583 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6584
6585 RunTLSUsageCheckTest(ssl_provider.Pass());
6586}
6587
[email protected]aea80602009-09-18 00:55:086588} // namespace net