blob: 94ef61d718c00f2f29126e28bd56002ca6042f35 [file] [log] [blame]
[email protected]f90bf0d92011-01-13 02:12:441// Copyright (c) 2011 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]9e1bdd32011-02-03 21:48:345#include "net/http/http_network_transaction.h"
6
[email protected]d8ef27b2010-08-06 17:34:397#include <string>
[email protected]a33cad2b62010-07-30 22:24:398#include <vector>
9
[email protected]018aabc2010-10-29 16:16:5910#include "net/base/auth.h"
[email protected]9e743cd2010-03-16 07:03:5311#include "net/base/net_log_unittest.h"
[email protected]87bfa3f2010-09-30 14:54:5612#include "net/http/http_network_session_peer.h"
[email protected]aea80602009-09-18 00:55:0813#include "net/http/http_transaction_unittest.h"
[email protected]9be804c82010-06-24 17:59:4614#include "net/spdy/spdy_http_stream.h"
[email protected]9e1bdd32011-02-03 21:48:3415#include "net/spdy/spdy_http_utils.h"
[email protected]bdebd1b2010-08-09 20:18:0816#include "net/spdy/spdy_session.h"
[email protected]19ec8a72010-08-23 03:38:2317#include "net/spdy/spdy_session_pool.h"
[email protected]2ff8b312010-04-26 22:20:5418#include "net/spdy/spdy_test_util.h"
[email protected]d2db0292011-01-26 20:23:4419#include "net/url_request/url_request_test_util.h"
[email protected]aea80602009-09-18 00:55:0820#include "testing/platform_test.h"
21
22//-----------------------------------------------------------------------------
23
[email protected]d1eda932009-11-04 01:03:1024namespace net {
[email protected]dae22c52010-07-30 02:16:3525
26// This is the expected list of advertised protocols from the browser's NPN
27// list.
28static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
29
[email protected]9e9e842e2010-07-23 23:09:1530enum SpdyNetworkTransactionTestTypes {
31 SPDYNPN,
32 SPDYNOSSL,
[email protected]1f418ee2010-10-16 19:46:5633 SPDYSSL,
[email protected]9e9e842e2010-07-23 23:09:1534};
35class SpdyNetworkTransactionTest
36 : public ::testing::TestWithParam<SpdyNetworkTransactionTestTypes> {
[email protected]34437af82009-11-06 02:28:4937 protected:
[email protected]aea80602009-09-18 00:55:0838 virtual void SetUp() {
[email protected]94d78132010-01-22 00:53:0039 // By default, all tests turn off compression.
40 EnableCompression(false);
[email protected]d3cee19d2010-06-22 18:42:1841 google_get_request_initialized_ = false;
[email protected]310240592010-08-05 21:04:1942 google_post_request_initialized_ = false;
[email protected]0c9bf872011-03-04 17:53:2243 google_chunked_post_request_initialized_ = false;
[email protected]aea80602009-09-18 00:55:0844 }
45
46 virtual void TearDown() {
47 // Empty the current queue.
48 MessageLoop::current()->RunAllPending();
[email protected]aea80602009-09-18 00:55:0849 }
50
[email protected]72552f02009-10-28 15:25:0151 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:0852 int rv;
53 std::string status_line;
54 std::string response_data;
[email protected]8b070372009-11-16 22:01:2555 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:0856 };
57
[email protected]94d78132010-01-22 00:53:0058 void EnableCompression(bool enabled) {
[email protected]955fc2e72010-02-08 20:37:3059 spdy::SpdyFramer::set_enable_compression_default(enabled);
[email protected]94d78132010-01-22 00:53:0060 }
61
[email protected]3caf5542010-07-16 15:19:4762 class StartTransactionCallback;
63 class DeleteSessionCallback;
[email protected]74188f22010-04-09 20:18:5064
[email protected]3caf5542010-07-16 15:19:4765 // A helper class that handles all the initial npn/ssl setup.
66 class NormalSpdyTransactionHelper {
67 public:
68 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
[email protected]9e9e842e2010-07-23 23:09:1569 const BoundNetLog& log,
70 SpdyNetworkTransactionTestTypes test_type)
[email protected]30c942b2010-07-21 16:59:5971 : request_(request),
[email protected]b261d0e2010-08-02 19:13:2472 session_deps_(new SpdySessionDependencies()),
73 session_(SpdySessionDependencies::SpdyCreateSession(
74 session_deps_.get())),
[email protected]9e9e842e2010-07-23 23:09:1575 log_(log),
[email protected]3b7828432010-08-18 18:33:2776 test_type_(test_type),
[email protected]1f418ee2010-10-16 19:46:5677 deterministic_(false),
78 spdy_enabled_(true) {
[email protected]a33cad2b62010-07-30 22:24:3979 switch (test_type_) {
[email protected]9e9e842e2010-07-23 23:09:1580 case SPDYNOSSL:
81 case SPDYSSL:
82 port_ = 80;
83 break;
84 case SPDYNPN:
85 port_ = 443;
86 break;
87 default:
88 NOTREACHED();
89 }
90 }
[email protected]74188f22010-04-09 20:18:5091
[email protected]19ec8a72010-08-23 03:38:2392 ~NormalSpdyTransactionHelper() {
93 // Any test which doesn't close the socket by sending it an EOF will
94 // have a valid session left open, which leaks the entire session pool.
95 // This is just fine - in fact, some of our tests intentionally do this
96 // so that we can check consistency of the SpdySessionPool as the test
97 // finishes. If we had put an EOF on the socket, the SpdySession would
98 // have closed and we wouldn't be able to check the consistency.
99
100 // Forcefully close existing sessions here.
101 session()->spdy_session_pool()->CloseAllSessions();
102 }
103
[email protected]3b7828432010-08-18 18:33:27104 void SetDeterministic() {
105 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
106 session_deps_.get());
107 deterministic_ = true;
108 }
109
[email protected]1f418ee2010-10-16 19:46:56110 void SetSpdyDisabled() {
111 spdy_enabled_ = false;
112 }
113
[email protected]3caf5542010-07-16 15:19:47114 void RunPreTestSetup() {
[email protected]b261d0e2010-08-02 19:13:24115 if (!session_deps_.get())
116 session_deps_.reset(new SpdySessionDependencies());
117 if (!session_.get())
118 session_ = SpdySessionDependencies::SpdyCreateSession(
119 session_deps_.get());
[email protected]8e6441ca2010-08-19 05:56:38120 HttpStreamFactory::set_use_alternate_protocols(false);
121 HttpStreamFactory::set_force_spdy_over_ssl(false);
122 HttpStreamFactory::set_force_spdy_always(false);
[email protected]a33cad2b62010-07-30 22:24:39123 switch (test_type_) {
[email protected]9e9e842e2010-07-23 23:09:15124 case SPDYNPN:
125 session_->mutable_alternate_protocols()->SetAlternateProtocolFor(
126 HostPortPair("www.google.com", 80), 443,
[email protected]dae22c52010-07-30 02:16:35127 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]8e6441ca2010-08-19 05:56:38128 HttpStreamFactory::set_use_alternate_protocols(true);
129 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]9e9e842e2010-07-23 23:09:15130 break;
131 case SPDYNOSSL:
[email protected]8e6441ca2010-08-19 05:56:38132 HttpStreamFactory::set_force_spdy_over_ssl(false);
133 HttpStreamFactory::set_force_spdy_always(true);
[email protected]9e9e842e2010-07-23 23:09:15134 break;
135 case SPDYSSL:
[email protected]8e6441ca2010-08-19 05:56:38136 HttpStreamFactory::set_force_spdy_over_ssl(true);
137 HttpStreamFactory::set_force_spdy_always(true);
[email protected]9e9e842e2010-07-23 23:09:15138 break;
139 default:
140 NOTREACHED();
[email protected]3caf5542010-07-16 15:19:47141 }
[email protected]aea80602009-09-18 00:55:08142
[email protected]3caf5542010-07-16 15:19:47143 // We're now ready to use SSL-npn SPDY.
144 trans_.reset(new HttpNetworkTransaction(session_));
[email protected]cb54b3b22010-06-03 16:28:55145 }
[email protected]aea80602009-09-18 00:55:08146
[email protected]3caf5542010-07-16 15:19:47147 // Start the transaction, read some data, finish.
148 void RunDefaultTest() {
149 output_.rv = trans_->Start(&request_, &callback, log_);
[email protected]aea80602009-09-18 00:55:08150
[email protected]3caf5542010-07-16 15:19:47151 // We expect an IO Pending or some sort of error.
152 EXPECT_LT(output_.rv, 0);
153 if (output_.rv != ERR_IO_PENDING)
154 return;
[email protected]aea80602009-09-18 00:55:08155
[email protected]3caf5542010-07-16 15:19:47156 output_.rv = callback.WaitForResult();
157 if (output_.rv != OK) {
[email protected]a01ea222010-08-19 16:50:53158 session_->spdy_session_pool()->CloseCurrentSessions();
[email protected]3caf5542010-07-16 15:19:47159 return;
160 }
[email protected]ff57bb82009-11-12 06:52:14161
[email protected]3caf5542010-07-16 15:19:47162 // Verify responses.
163 const HttpResponseInfo* response = trans_->GetResponseInfo();
164 ASSERT_TRUE(response != NULL);
165 ASSERT_TRUE(response->headers != NULL);
166 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]1f418ee2010-10-16 19:46:56167 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
168 if (test_type_ == SPDYNPN && spdy_enabled_) {
[email protected]9e9e842e2010-07-23 23:09:15169 EXPECT_TRUE(response->was_npn_negotiated);
170 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]a33cad2b62010-07-30 22:24:39171 } else {
[email protected]9e9e842e2010-07-23 23:09:15172 EXPECT_TRUE(!response->was_npn_negotiated);
173 EXPECT_TRUE(!response->was_alternate_protocol_available);
174 }
[email protected]1f418ee2010-10-16 19:46:56175 // If SPDY is not enabled, a HTTP request should not be diverted
176 // over a SSL session.
177 if (!spdy_enabled_) {
178 EXPECT_EQ(request_.url.SchemeIs("https"),
179 response->was_npn_negotiated);
180 }
[email protected]6d81b482011-02-22 19:47:19181 EXPECT_EQ("192.0.2.33", response->socket_address.host());
182 EXPECT_EQ(0, response->socket_address.port());
[email protected]3caf5542010-07-16 15:19:47183 output_.status_line = response->headers->GetStatusLine();
184 output_.response_info = *response; // Make a copy so we can verify.
185 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
[email protected]3caf5542010-07-16 15:19:47186 }
187
188 // Most tests will want to call this function. In particular, the MockReads
189 // should end with an empty read, and that read needs to be processed to
190 // ensure proper deletion of the spdy_session_pool.
191 void VerifyDataConsumed() {
[email protected]a33cad2b62010-07-30 22:24:39192 for (DataVector::iterator it = data_vector_.begin();
[email protected]3caf5542010-07-16 15:19:47193 it != data_vector_.end(); ++it) {
194 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
195 << (*it)->read_count()
196 << " Read index: "
197 << (*it)->read_index();
198 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
199 << (*it)->write_count()
200 << " Write index: "
201 << (*it)->write_index();
202 }
203 }
204
205 // Occasionally a test will expect to error out before certain reads are
206 // processed. In that case we want to explicitly ensure that the reads were
207 // not processed.
208 void VerifyDataNotConsumed() {
[email protected]a33cad2b62010-07-30 22:24:39209 for (DataVector::iterator it = data_vector_.begin();
[email protected]3caf5542010-07-16 15:19:47210 it != data_vector_.end(); ++it) {
211 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
212 << (*it)->read_count()
213 << " Read index: "
214 << (*it)->read_index();
215 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
216 << (*it)->write_count()
217 << " Write index: "
218 << (*it)->write_index();
[email protected]3caf5542010-07-16 15:19:47219 }
220 }
221
222 void RunToCompletion(StaticSocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47223 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58224 AddData(data);
[email protected]3caf5542010-07-16 15:19:47225 RunDefaultTest();
226 VerifyDataConsumed();
227 }
[email protected]e6b06862010-07-20 16:32:58228
[email protected]3caf5542010-07-16 15:19:47229 void AddData(StaticSocketDataProvider* data) {
[email protected]3b7828432010-08-18 18:33:27230 DCHECK(!deterministic_);
[email protected]3caf5542010-07-16 15:19:47231 data_vector_.push_back(data);
[email protected]9e9e842e2010-07-23 23:09:15232 linked_ptr<SSLSocketDataProvider> ssl_(
233 new SSLSocketDataProvider(true, OK));
[email protected]a33cad2b62010-07-30 22:24:39234 if (test_type_ == SPDYNPN) {
[email protected]9e9e842e2010-07-23 23:09:15235 ssl_->next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:35236 ssl_->next_proto = "spdy/2";
[email protected]9e9e842e2010-07-23 23:09:15237 ssl_->was_npn_negotiated = true;
238 }
239 ssl_vector_.push_back(ssl_);
[email protected]b261d0e2010-08-02 19:13:24240 if(test_type_ == SPDYNPN || test_type_ == SPDYSSL)
[email protected]3b7828432010-08-18 18:33:27241 session_deps_->socket_factory->AddSSLSocketDataProvider(ssl_.get());
242 session_deps_->socket_factory->AddSocketDataProvider(data);
243 }
244
245 void AddDeterministicData(DeterministicSocketData* data) {
246 DCHECK(deterministic_);
247 data_vector_.push_back(data);
248 linked_ptr<SSLSocketDataProvider> ssl_(
249 new SSLSocketDataProvider(true, OK));
250 if (test_type_ == SPDYNPN) {
251 ssl_->next_proto_status = SSLClientSocket::kNextProtoNegotiated;
252 ssl_->next_proto = "spdy/2";
253 ssl_->was_npn_negotiated = true;
254 }
255 ssl_vector_.push_back(ssl_);
256 if(test_type_ == SPDYNPN || test_type_ == SPDYSSL)
257 session_deps_->deterministic_socket_factory->
258 AddSSLSocketDataProvider(ssl_.get());
259 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
[email protected]3caf5542010-07-16 15:19:47260 }
261
[email protected]e6b06862010-07-20 16:32:58262 // This can only be called after RunPreTestSetup. It adds a Data Provider,
263 // but not a corresponding SSL data provider
264 void AddDataNoSSL(StaticSocketDataProvider* data) {
[email protected]3b7828432010-08-18 18:33:27265 DCHECK(!deterministic_);
266 session_deps_->socket_factory->AddSocketDataProvider(data);
267 }
268 void AddDataNoSSL(DeterministicSocketData* data) {
269 DCHECK(deterministic_);
270 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
[email protected]e6b06862010-07-20 16:32:58271 }
272
[email protected]a33cad2b62010-07-30 22:24:39273 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
[email protected]3caf5542010-07-16 15:19:47274 session_ = session;
275 }
276 HttpNetworkTransaction* trans() { return trans_.get(); }
277 void ResetTrans() { trans_.reset(); }
278 TransactionHelperResult& output() { return output_; }
[email protected]19ec8a72010-08-23 03:38:23279 const HttpRequestInfo& request() const { return request_; }
280 const scoped_refptr<HttpNetworkSession>& session() const {
281 return session_;
282 }
[email protected]b261d0e2010-08-02 19:13:24283 scoped_ptr<SpdySessionDependencies>& session_deps() {
284 return session_deps_;
285 }
[email protected]19ec8a72010-08-23 03:38:23286 int port() const { return port_; }
287 SpdyNetworkTransactionTestTypes test_type() const { return test_type_; }
[email protected]3caf5542010-07-16 15:19:47288
289 private:
290 typedef std::vector<StaticSocketDataProvider*> DataVector;
291 typedef std::vector<linked_ptr<SSLSocketDataProvider> > SSLVector;
292 HttpRequestInfo request_;
[email protected]b261d0e2010-08-02 19:13:24293 scoped_ptr<SpdySessionDependencies> session_deps_;
[email protected]3caf5542010-07-16 15:19:47294 scoped_refptr<HttpNetworkSession> session_;
295 TransactionHelperResult output_;
296 scoped_ptr<StaticSocketDataProvider> first_transaction_;
297 SSLVector ssl_vector_;
298 TestCompletionCallback callback;
299 scoped_ptr<HttpNetworkTransaction> trans_;
300 scoped_ptr<HttpNetworkTransaction> trans_http_;
301 DataVector data_vector_;
302 const BoundNetLog& log_;
[email protected]9e9e842e2010-07-23 23:09:15303 SpdyNetworkTransactionTestTypes test_type_;
304 int port_;
[email protected]3b7828432010-08-18 18:33:27305 bool deterministic_;
[email protected]1f418ee2010-10-16 19:46:56306 bool spdy_enabled_;
[email protected]3caf5542010-07-16 15:19:47307 };
[email protected]aea80602009-09-18 00:55:08308
309 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
310 int expected_status);
311
312 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18313
[email protected]e3ebba0f2010-08-05 17:59:58314 const HttpRequestInfo& CreateGetPushRequest() {
315 google_get_push_request_.method = "GET";
316 google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
317 google_get_push_request_.load_flags = 0;
318 return google_get_push_request_;
319 }
320
[email protected]d3cee19d2010-06-22 18:42:18321 const HttpRequestInfo& CreateGetRequest() {
322 if (!google_get_request_initialized_) {
323 google_get_request_.method = "GET";
[email protected]310240592010-08-05 21:04:19324 google_get_request_.url = GURL(kDefaultURL);
[email protected]d3cee19d2010-06-22 18:42:18325 google_get_request_.load_flags = 0;
326 google_get_request_initialized_ = true;
327 }
328 return google_get_request_;
329 }
330
[email protected]3deb9a52010-11-11 00:24:40331 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
332 if (!google_get_request_initialized_) {
333 google_get_request_.method = "GET";
334 google_get_request_.url = GURL(kDefaultURL);
335 google_get_request_.load_flags = 0;
336 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
337 google_get_request_initialized_ = true;
338 }
339 return google_get_request_;
340 }
341
[email protected]310240592010-08-05 21:04:19342 const HttpRequestInfo& CreatePostRequest() {
343 if (!google_post_request_initialized_) {
344 google_post_request_.method = "POST";
345 google_post_request_.url = GURL(kDefaultURL);
346 google_post_request_.upload_data = new UploadData();
347 google_post_request_.upload_data->AppendBytes(kUploadData,
348 kUploadDataSize);
349 google_post_request_initialized_ = true;
350 }
351 return google_post_request_;
352 }
353
[email protected]0c9bf872011-03-04 17:53:22354 const HttpRequestInfo& CreateChunkedPostRequest() {
355 if (!google_chunked_post_request_initialized_) {
356 google_chunked_post_request_.method = "POST";
357 google_chunked_post_request_.url = GURL(kDefaultURL);
358 google_chunked_post_request_.upload_data = new UploadData();
359 google_chunked_post_request_.upload_data->set_is_chunked(true);
360 google_chunked_post_request_.upload_data->AppendChunk(
361 kUploadData, kUploadDataSize, false);
362 google_chunked_post_request_.upload_data->AppendChunk(
363 kUploadData, kUploadDataSize, true);
364 google_chunked_post_request_initialized_ = true;
365 }
366 return google_chunked_post_request_;
367 }
368
[email protected]19ec8a72010-08-23 03:38:23369 // Read the result of a particular transaction, knowing that we've got
370 // multiple transactions in the read pipeline; so as we read, we may have
371 // to skip over data destined for other transactions while we consume
372 // the data for |trans|.
373 int ReadResult(HttpNetworkTransaction* trans,
[email protected]d08358502010-12-03 22:04:03374 StaticSocketDataProvider* data,
[email protected]19ec8a72010-08-23 03:38:23375 std::string* result) {
376 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58377
[email protected]19ec8a72010-08-23 03:38:23378 int bytes_read = 0;
[email protected]ad8e04a2010-11-01 04:16:27379 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
[email protected]19ec8a72010-08-23 03:38:23380 TestCompletionCallback callback;
381 while (true) {
382 int rv = trans->Read(buf, kSize, &callback);
383 if (rv == ERR_IO_PENDING) {
384 // Multiple transactions may be in the data set. Keep pulling off
385 // reads until we complete our callback.
386 while (!callback.have_result()) {
387 data->CompleteRead();
388 MessageLoop::current()->RunAllPending();
389 }
390 rv = callback.WaitForResult();
391 } else if (rv <= 0) {
392 break;
393 }
394 result->append(buf->data(), rv);
395 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58396 }
[email protected]19ec8a72010-08-23 03:38:23397 return bytes_read;
398 }
[email protected]e3ebba0f2010-08-05 17:59:58399
[email protected]19ec8a72010-08-23 03:38:23400 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
401 // This lengthy block is reaching into the pool to dig out the active
402 // session. Once we have the session, we verify that the streams are
403 // all closed and not leaked at this point.
404 const GURL& url = helper.request().url;
405 int port = helper.test_type() == SPDYNPN ? 443 : 80;
406 HostPortPair host_port_pair(url.host(), port);
[email protected]31e68d72010-08-25 06:36:58407 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]19ec8a72010-08-23 03:38:23408 BoundNetLog log;
409 const scoped_refptr<HttpNetworkSession>& session = helper.session();
[email protected]87bfa3f2010-09-30 14:54:56410 SpdySessionPool* pool(session->spdy_session_pool());
[email protected]19ec8a72010-08-23 03:38:23411 EXPECT_TRUE(pool->HasSession(pair));
[email protected]102e27c2011-02-23 01:01:31412 scoped_refptr<SpdySession> spdy_session(pool->Get(pair, log));
[email protected]19ec8a72010-08-23 03:38:23413 ASSERT_TRUE(spdy_session.get() != NULL);
414 EXPECT_EQ(0u, spdy_session->num_active_streams());
415 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
416 }
[email protected]e3ebba0f2010-08-05 17:59:58417
[email protected]d08358502010-12-03 22:04:03418 void RunServerPushTest(OrderedSocketData* data,
[email protected]e3ebba0f2010-08-05 17:59:58419 HttpResponseInfo* response,
[email protected]a7a265ef2010-12-08 18:05:57420 HttpResponseInfo* push_response,
[email protected]e3ebba0f2010-08-05 17:59:58421 std::string& expected) {
[email protected]e3ebba0f2010-08-05 17:59:58422 NormalSpdyTransactionHelper helper(CreateGetRequest(),
423 BoundNetLog(), GetParam());
[email protected]e3ebba0f2010-08-05 17:59:58424 helper.RunPreTestSetup();
[email protected]d08358502010-12-03 22:04:03425 helper.AddData(data);
[email protected]e3ebba0f2010-08-05 17:59:58426
427 HttpNetworkTransaction* trans = helper.trans();
428
429 // Start the transaction with basic parameters.
430 TestCompletionCallback callback;
431 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
432 EXPECT_EQ(ERR_IO_PENDING, rv);
433 rv = callback.WaitForResult();
434
435 // Request the pushed path.
[email protected]e3ebba0f2010-08-05 17:59:58436 scoped_ptr<HttpNetworkTransaction> trans2(
437 new HttpNetworkTransaction(helper.session()));
438 rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog());
439 EXPECT_EQ(ERR_IO_PENDING, rv);
440 MessageLoop::current()->RunAllPending();
441
442 // The data for the pushed path may be coming in more than 1 packet. Compile
443 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23444
445 // Read the server push body.
446 std::string result2;
447 ReadResult(trans2.get(), data, &result2);
448 // Read the response body.
[email protected]e3ebba0f2010-08-05 17:59:58449 std::string result;
[email protected]19ec8a72010-08-23 03:38:23450 ReadResult(trans, data, &result);
[email protected]e3ebba0f2010-08-05 17:59:58451
452 // Verify that we consumed all test data.
453 EXPECT_TRUE(data->at_read_eof());
454 EXPECT_TRUE(data->at_write_eof());
455
456 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23457 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
458 << result2
459 << "||||| Expected data: "
460 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58461
462 // Verify the SYN_REPLY.
463 // Copy the response info, because trans goes away.
464 *response = *trans->GetResponseInfo();
[email protected]a7a265ef2010-12-08 18:05:57465 *push_response = *trans2->GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23466
467 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58468 }
469
[email protected]d3cee19d2010-06-22 18:42:18470 private:
471 bool google_get_request_initialized_;
[email protected]310240592010-08-05 21:04:19472 bool google_post_request_initialized_;
[email protected]0c9bf872011-03-04 17:53:22473 bool google_chunked_post_request_initialized_;
[email protected]d3cee19d2010-06-22 18:42:18474 HttpRequestInfo google_get_request_;
[email protected]310240592010-08-05 21:04:19475 HttpRequestInfo google_post_request_;
[email protected]0c9bf872011-03-04 17:53:22476 HttpRequestInfo google_chunked_post_request_;
[email protected]e3ebba0f2010-08-05 17:59:58477 HttpRequestInfo google_get_push_request_;
[email protected]aea80602009-09-18 00:55:08478};
479
480//-----------------------------------------------------------------------------
[email protected]9e9e842e2010-07-23 23:09:15481// All tests are run with three different connection types: SPDY after NPN
482// negotiation, SPDY without SSL, and SPDY with SSL.
[email protected]5cd9d7f2010-09-03 22:06:24483INSTANTIATE_TEST_CASE_P(Spdy,
[email protected]9e9e842e2010-07-23 23:09:15484 SpdyNetworkTransactionTest,
[email protected]e3ebba0f2010-08-05 17:59:58485 ::testing::Values(SPDYNOSSL, SPDYSSL, SPDYNPN));
[email protected]9e9e842e2010-07-23 23:09:15486
[email protected]aea80602009-09-18 00:55:08487
[email protected]3caf5542010-07-16 15:19:47488// Verify HttpNetworkTransaction constructor.
[email protected]9e9e842e2010-07-23 23:09:15489TEST_P(SpdyNetworkTransactionTest, Constructor) {
[email protected]30c942b2010-07-21 16:59:59490 SpdySessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27491 scoped_refptr<HttpNetworkSession> session(
492 SpdySessionDependencies::SpdyCreateSession(&session_deps));
[email protected]3caf5542010-07-16 15:19:47493 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]aea80602009-09-18 00:55:08494}
495
[email protected]9e9e842e2010-07-23 23:09:15496TEST_P(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38497 // Construct the request.
[email protected]2bd93022010-07-17 00:58:44498 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:13499 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]72552f02009-10-28 15:25:01500
[email protected]2bd93022010-07-17 00:58:44501 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
502 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]72552f02009-10-28 15:25:01503 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:13504 CreateMockRead(*resp),
505 CreateMockRead(*body),
[email protected]72552f02009-10-28 15:25:01506 MockRead(true, 0, 0) // EOF
507 };
508
[email protected]bf2491a92009-11-29 16:39:48509 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:39510 new DelayedSocketData(1, reads, arraysize(reads),
511 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:47512 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:15513 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:47514 helper.RunToCompletion(data.get());
515 TransactionHelperResult out = helper.output();
[email protected]72552f02009-10-28 15:25:01516 EXPECT_EQ(OK, out.rv);
517 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
518 EXPECT_EQ("hello!", out.response_data);
519}
520
[email protected]c9c6f5c2010-07-31 01:30:03521TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
522 for (RequestPriority p = HIGHEST; p < NUM_PRIORITIES;
523 p = RequestPriority(p+1)) {
524 // Construct the request.
525 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, p));
526 MockWrite writes[] = { CreateMockWrite(*req) };
527
528 const int spdy_prio = reinterpret_cast<spdy::SpdySynStreamControlFrame*>(
529 req.get())->priority();
530 // this repeats the RequestPriority-->SpdyPriority mapping from
531 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
532 // sure it's being done right.
533 switch(p) {
534 case HIGHEST:
535 EXPECT_EQ(0, spdy_prio);
536 break;
537 case MEDIUM:
538 EXPECT_EQ(1, spdy_prio);
539 break;
540 case LOW:
541 case LOWEST:
542 EXPECT_EQ(2, spdy_prio);
543 break;
544 case IDLE:
545 EXPECT_EQ(3, spdy_prio);
546 break;
547 default:
548 FAIL();
549 }
550
551 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
552 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
553 MockRead reads[] = {
554 CreateMockRead(*resp),
555 CreateMockRead(*body),
556 MockRead(true, 0, 0) // EOF
557 };
558
559 scoped_refptr<DelayedSocketData> data(
560 new DelayedSocketData(1, reads, arraysize(reads),
561 writes, arraysize(writes)));
562 HttpRequestInfo http_req = CreateGetRequest();
563 http_req.priority = p;
564
565 NormalSpdyTransactionHelper helper(http_req, BoundNetLog(), GetParam());
566 helper.RunToCompletion(data.get());
567 TransactionHelperResult out = helper.output();
568 EXPECT_EQ(OK, out.rv);
569 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
570 EXPECT_EQ("hello!", out.response_data);
571 }
572}
573
[email protected]2bd93022010-07-17 00:58:44574// Start three gets simultaniously; making sure that multiplexed
575// streams work properly.
576
577// This can't use the TransactionHelper method, since it only
578// handles a single transaction, and finishes them as soon
579// as it launches them.
580
581// TODO(gavinp): create a working generalized TransactionHelper that
582// can allow multiple streams in flight.
583
[email protected]9e9e842e2010-07-23 23:09:15584TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
[email protected]2bd93022010-07-17 00:58:44585 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
586 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
587 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
588 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
589
590 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
591 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
592 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
593 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
594
595 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
596 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
597 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
598 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
599
[email protected]1b323172011-03-01 17:50:17600 MockWrite writes[] = {
601 CreateMockWrite(*req),
602 CreateMockWrite(*req2),
603 CreateMockWrite(*req3),
[email protected]2bd93022010-07-17 00:58:44604 };
605 MockRead reads[] = {
606 CreateMockRead(*resp, 1),
607 CreateMockRead(*body),
608 CreateMockRead(*resp2, 4),
609 CreateMockRead(*body2),
610 CreateMockRead(*resp3, 7),
611 CreateMockRead(*body3),
612
613 CreateMockRead(*fbody),
614 CreateMockRead(*fbody2),
615 CreateMockRead(*fbody3),
616
617 MockRead(true, 0, 0), // EOF
618 };
[email protected]2bd93022010-07-17 00:58:44619 scoped_refptr<OrderedSocketData> data(
620 new OrderedSocketData(reads, arraysize(reads),
621 writes, arraysize(writes)));
[email protected]bdebd1b2010-08-09 20:18:08622 scoped_refptr<OrderedSocketData> data_placeholder(
623 new OrderedSocketData(NULL, 0, NULL, 0));
[email protected]2bd93022010-07-17 00:58:44624
625 BoundNetLog log;
626 TransactionHelperResult out;
[email protected]bdebd1b2010-08-09 20:18:08627 NormalSpdyTransactionHelper helper(CreateGetRequest(),
628 BoundNetLog(), GetParam());
629 helper.RunPreTestSetup();
630 helper.AddData(data.get());
631 // We require placeholder data because three get requests are sent out, so
632 // there needs to be three sets of SSL connection data.
633 helper.AddData(data_placeholder.get());
634 helper.AddData(data_placeholder.get());
635 scoped_ptr<HttpNetworkTransaction> trans1(
636 new HttpNetworkTransaction(helper.session()));
637 scoped_ptr<HttpNetworkTransaction> trans2(
638 new HttpNetworkTransaction(helper.session()));
639 scoped_ptr<HttpNetworkTransaction> trans3(
640 new HttpNetworkTransaction(helper.session()));
[email protected]2bd93022010-07-17 00:58:44641
[email protected]bdebd1b2010-08-09 20:18:08642 TestCompletionCallback callback1;
643 TestCompletionCallback callback2;
644 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44645
[email protected]bdebd1b2010-08-09 20:18:08646 HttpRequestInfo httpreq1 = CreateGetRequest();
647 HttpRequestInfo httpreq2 = CreateGetRequest();
648 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:44649
[email protected]bdebd1b2010-08-09 20:18:08650 out.rv = trans1->Start(&httpreq1, &callback1, log);
651 ASSERT_EQ(ERR_IO_PENDING, out.rv);
652 out.rv = trans2->Start(&httpreq2, &callback2, log);
653 ASSERT_EQ(ERR_IO_PENDING, out.rv);
654 out.rv = trans3->Start(&httpreq3, &callback3, log);
655 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:44656
[email protected]bdebd1b2010-08-09 20:18:08657 out.rv = callback1.WaitForResult();
658 ASSERT_EQ(OK, out.rv);
659 out.rv = callback3.WaitForResult();
660 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44661
[email protected]bdebd1b2010-08-09 20:18:08662 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
663 EXPECT_TRUE(response1->headers != NULL);
664 EXPECT_TRUE(response1->was_fetched_via_spdy);
665 out.status_line = response1->headers->GetStatusLine();
666 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:44667
[email protected]bdebd1b2010-08-09 20:18:08668 trans2->GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:44669
[email protected]bdebd1b2010-08-09 20:18:08670 out.rv = ReadTransaction(trans1.get(), &out.response_data);
671 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:44672 EXPECT_EQ(OK, out.rv);
673
[email protected]2bd93022010-07-17 00:58:44674 EXPECT_EQ(OK, out.rv);
675 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
676 EXPECT_EQ("hello!hello!", out.response_data);
677}
678
[email protected]1b323172011-03-01 17:50:17679TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
680 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
681 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
682 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
683 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
684
685 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
686 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
687 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
688 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
689
690 MockWrite writes[] = {
691 CreateMockWrite(*req),
692 CreateMockWrite(*req2),
693 };
694 MockRead reads[] = {
695 CreateMockRead(*resp, 1),
696 CreateMockRead(*body),
697 CreateMockRead(*resp2, 4),
698 CreateMockRead(*body2),
699 CreateMockRead(*fbody),
700 CreateMockRead(*fbody2),
701 MockRead(true, 0, 0), // EOF
702 };
703 scoped_refptr<OrderedSocketData> data(
704 new OrderedSocketData(reads, arraysize(reads),
705 writes, arraysize(writes)));
706
707 MockConnect never_finishing_connect(true, ERR_IO_PENDING);
708
709 scoped_refptr<OrderedSocketData> data_placeholder(
710 new OrderedSocketData(NULL, 0, NULL, 0));
711 data_placeholder->set_connect_data(never_finishing_connect);
712
713 BoundNetLog log;
714 TransactionHelperResult out;
715 NormalSpdyTransactionHelper helper(CreateGetRequest(),
716 BoundNetLog(), GetParam());
717 helper.RunPreTestSetup();
718 helper.AddData(data.get());
719 // We require placeholder data because two get requests are sent out, so
720 // there needs to be two sets of SSL connection data.
721 helper.AddData(data_placeholder.get());
722 scoped_ptr<HttpNetworkTransaction> trans1(
723 new HttpNetworkTransaction(helper.session()));
724 scoped_ptr<HttpNetworkTransaction> trans2(
725 new HttpNetworkTransaction(helper.session()));
726
727 TestCompletionCallback callback1;
728 TestCompletionCallback callback2;
729
730 HttpRequestInfo httpreq1 = CreateGetRequest();
731 HttpRequestInfo httpreq2 = CreateGetRequest();
732
733 out.rv = trans1->Start(&httpreq1, &callback1, log);
734 ASSERT_EQ(ERR_IO_PENDING, out.rv);
735 out.rv = trans2->Start(&httpreq2, &callback2, log);
736 ASSERT_EQ(ERR_IO_PENDING, out.rv);
737
738 out.rv = callback1.WaitForResult();
739 ASSERT_EQ(OK, out.rv);
740 out.rv = callback2.WaitForResult();
741 ASSERT_EQ(OK, out.rv);
742
743 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
744 EXPECT_TRUE(response1->headers != NULL);
745 EXPECT_TRUE(response1->was_fetched_via_spdy);
746 out.status_line = response1->headers->GetStatusLine();
747 out.response_info = *response1;
748 out.rv = ReadTransaction(trans1.get(), &out.response_data);
749 EXPECT_EQ(OK, out.rv);
750 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
751 EXPECT_EQ("hello!hello!", out.response_data);
752
753 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
754 EXPECT_TRUE(response2->headers != NULL);
755 EXPECT_TRUE(response2->was_fetched_via_spdy);
756 out.status_line = response2->headers->GetStatusLine();
757 out.response_info = *response2;
758 out.rv = ReadTransaction(trans2.get(), &out.response_data);
759 EXPECT_EQ(OK, out.rv);
760 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
761 EXPECT_EQ("hello!hello!", out.response_data);
762
763 helper.VerifyDataConsumed();
764}
765
766TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
767 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
768 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
769 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
770 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
771
772 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
773 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
774 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
775 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
776
777 MockWrite writes[] = {
778 CreateMockWrite(*req),
779 CreateMockWrite(*req2),
780 };
781 MockRead reads[] = {
782 CreateMockRead(*resp, 1),
783 CreateMockRead(*body),
784 CreateMockRead(*resp2, 4),
785 CreateMockRead(*body2),
786 CreateMockRead(*fbody),
787 CreateMockRead(*fbody2),
788 MockRead(true, 0, 0), // EOF
789 };
790 scoped_refptr<OrderedSocketData> preconnect_data(
791 new OrderedSocketData(reads, arraysize(reads),
792 writes, arraysize(writes)));
793
794 MockConnect never_finishing_connect(true, ERR_IO_PENDING);
795
796 scoped_refptr<OrderedSocketData> data_placeholder(
797 new OrderedSocketData(NULL, 0, NULL, 0));
798 data_placeholder->set_connect_data(never_finishing_connect);
799
800 BoundNetLog log;
801 TransactionHelperResult out;
802 NormalSpdyTransactionHelper helper(CreateGetRequest(),
803 BoundNetLog(), GetParam());
804 helper.RunPreTestSetup();
805 helper.AddData(preconnect_data.get());
806 // We require placeholder data because 3 connections are attempted (first is
807 // the preconnect, 2nd and 3rd are the never finished connections.
808 helper.AddData(data_placeholder.get());
809 helper.AddData(data_placeholder.get());
810
811 scoped_ptr<HttpNetworkTransaction> trans1(
812 new HttpNetworkTransaction(helper.session()));
813 scoped_ptr<HttpNetworkTransaction> trans2(
814 new HttpNetworkTransaction(helper.session()));
815
816 TestCompletionCallback callback1;
817 TestCompletionCallback callback2;
818
819 HttpRequestInfo httpreq = CreateGetRequest();
820
821 // Preconnect the first.
822 SSLConfig preconnect_ssl_config;
823 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
824 HttpStreamFactory* http_stream_factory =
825 helper.session()->http_stream_factory();
826 if (http_stream_factory->next_protos()) {
827 preconnect_ssl_config.next_protos = *http_stream_factory->next_protos();
828 }
829
830 http_stream_factory->PreconnectStreams(
831 1, httpreq, preconnect_ssl_config, log);
832
833 out.rv = trans1->Start(&httpreq, &callback1, log);
834 ASSERT_EQ(ERR_IO_PENDING, out.rv);
835 out.rv = trans2->Start(&httpreq, &callback2, log);
836 ASSERT_EQ(ERR_IO_PENDING, out.rv);
837
838 out.rv = callback1.WaitForResult();
839 ASSERT_EQ(OK, out.rv);
840 out.rv = callback2.WaitForResult();
841 ASSERT_EQ(OK, out.rv);
842
843 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
844 EXPECT_TRUE(response1->headers != NULL);
845 EXPECT_TRUE(response1->was_fetched_via_spdy);
846 out.status_line = response1->headers->GetStatusLine();
847 out.response_info = *response1;
848 out.rv = ReadTransaction(trans1.get(), &out.response_data);
849 EXPECT_EQ(OK, out.rv);
850 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
851 EXPECT_EQ("hello!hello!", out.response_data);
852
853 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
854 EXPECT_TRUE(response2->headers != NULL);
855 EXPECT_TRUE(response2->was_fetched_via_spdy);
856 out.status_line = response2->headers->GetStatusLine();
857 out.response_info = *response2;
858 out.rv = ReadTransaction(trans2.get(), &out.response_data);
859 EXPECT_EQ(OK, out.rv);
860 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
861 EXPECT_EQ("hello!hello!", out.response_data);
862
863 helper.VerifyDataConsumed();
864}
865
[email protected]2bd93022010-07-17 00:58:44866// Similar to ThreeGets above, however this test adds a SETTINGS
867// frame. The SETTINGS frame is read during the IO loop waiting on
868// the first transaction completion, and sets a maximum concurrent
869// stream limit of 1. This means that our IO loop exists after the
870// second transaction completes, so we can assert on read_index().
[email protected]9e9e842e2010-07-23 23:09:15871TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:44872 // Construct the request.
873 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
874 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
875 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
876 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
877
878 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
879 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
880 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
881 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
882
883 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
884 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
885 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
886 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
887
888 spdy::SpdySettings settings;
889 spdy::SettingsFlagsAndId id(0);
890 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
891 const size_t max_concurrent_streams = 1;
892
893 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
894 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
895
896 MockWrite writes[] = { CreateMockWrite(*req),
897 CreateMockWrite(*req2),
898 CreateMockWrite(*req3),
899 };
900 MockRead reads[] = {
[email protected]bdebd1b2010-08-09 20:18:08901 CreateMockRead(*settings_frame, 1),
[email protected]2bd93022010-07-17 00:58:44902 CreateMockRead(*resp),
903 CreateMockRead(*body),
904 CreateMockRead(*fbody),
[email protected]bdebd1b2010-08-09 20:18:08905 CreateMockRead(*resp2, 7),
[email protected]2bd93022010-07-17 00:58:44906 CreateMockRead(*body2),
907 CreateMockRead(*fbody2),
[email protected]bdebd1b2010-08-09 20:18:08908 CreateMockRead(*resp3, 12),
[email protected]2bd93022010-07-17 00:58:44909 CreateMockRead(*body3),
910 CreateMockRead(*fbody3),
911
912 MockRead(true, 0, 0), // EOF
913 };
914
915 scoped_refptr<OrderedSocketData> data(
916 new OrderedSocketData(reads, arraysize(reads),
917 writes, arraysize(writes)));
[email protected]bdebd1b2010-08-09 20:18:08918 scoped_refptr<OrderedSocketData> data_placeholder(
919 new OrderedSocketData(NULL, 0, NULL, 0));
[email protected]2bd93022010-07-17 00:58:44920
921 BoundNetLog log;
922 TransactionHelperResult out;
923 {
[email protected]bdebd1b2010-08-09 20:18:08924 NormalSpdyTransactionHelper helper(CreateGetRequest(),
925 BoundNetLog(), GetParam());
926 helper.RunPreTestSetup();
927 helper.AddData(data.get());
928 // We require placeholder data because three get requests are sent out, so
929 // there needs to be three sets of SSL connection data.
930 helper.AddData(data_placeholder.get());
931 helper.AddData(data_placeholder.get());
932 scoped_ptr<HttpNetworkTransaction> trans1(
933 new HttpNetworkTransaction(helper.session()));
934 scoped_ptr<HttpNetworkTransaction> trans2(
935 new HttpNetworkTransaction(helper.session()));
936 scoped_ptr<HttpNetworkTransaction> trans3(
937 new HttpNetworkTransaction(helper.session()));
[email protected]2bd93022010-07-17 00:58:44938
939 TestCompletionCallback callback1;
940 TestCompletionCallback callback2;
941 TestCompletionCallback callback3;
942
943 HttpRequestInfo httpreq1 = CreateGetRequest();
944 HttpRequestInfo httpreq2 = CreateGetRequest();
945 HttpRequestInfo httpreq3 = CreateGetRequest();
946
947 out.rv = trans1->Start(&httpreq1, &callback1, log);
948 ASSERT_EQ(out.rv, ERR_IO_PENDING);
949 // run transaction 1 through quickly to force a read of our SETTINGS
950 // frame
951 out.rv = callback1.WaitForResult();
[email protected]bdebd1b2010-08-09 20:18:08952 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44953
954 out.rv = trans2->Start(&httpreq2, &callback2, log);
955 ASSERT_EQ(out.rv, ERR_IO_PENDING);
956 out.rv = trans3->Start(&httpreq3, &callback3, log);
957 ASSERT_EQ(out.rv, ERR_IO_PENDING);
958 out.rv = callback2.WaitForResult();
959 ASSERT_EQ(OK, out.rv);
960 EXPECT_EQ(7U, data->read_index()); // i.e. the third trans was queued
961
962 out.rv = callback3.WaitForResult();
963 ASSERT_EQ(OK, out.rv);
964
965 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:08966 ASSERT_TRUE(response1 != NULL);
[email protected]2bd93022010-07-17 00:58:44967 EXPECT_TRUE(response1->headers != NULL);
968 EXPECT_TRUE(response1->was_fetched_via_spdy);
969 out.status_line = response1->headers->GetStatusLine();
970 out.response_info = *response1;
971 out.rv = ReadTransaction(trans1.get(), &out.response_data);
972 EXPECT_EQ(OK, out.rv);
973 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
974 EXPECT_EQ("hello!hello!", out.response_data);
975
976 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
977 out.status_line = response2->headers->GetStatusLine();
978 out.response_info = *response2;
979 out.rv = ReadTransaction(trans2.get(), &out.response_data);
980 EXPECT_EQ(OK, out.rv);
981 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
982 EXPECT_EQ("hello!hello!", out.response_data);
983
984 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
985 out.status_line = response3->headers->GetStatusLine();
986 out.response_info = *response3;
987 out.rv = ReadTransaction(trans3.get(), &out.response_data);
988 EXPECT_EQ(OK, out.rv);
989 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
990 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:26991
992 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:44993 }
994 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44995}
996
997// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
998// a fourth transaction. The third and fourth transactions have
999// different data ("hello!" vs "hello!hello!") and because of the
1000// user specified priority, we expect to see them inverted in
1001// the response from the server.
[email protected]9e9e842e2010-07-23 23:09:151002TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:441003 // Construct the request.
1004 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1005 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1006 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1007 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
1008
1009 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1010 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1011 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
1012 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
1013
1014 scoped_ptr<spdy::SpdyFrame> req4(
1015 ConstructSpdyGet(NULL, 0, false, 5, HIGHEST));
1016 scoped_ptr<spdy::SpdyFrame> resp4(ConstructSpdyGetSynReply(NULL, 0, 5));
1017 scoped_ptr<spdy::SpdyFrame> fbody4(ConstructSpdyBodyFrame(5, true));
1018
1019 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 7, LOWEST));
1020 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 7));
1021 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(7, false));
1022 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(7, true));
1023
1024
1025 spdy::SpdySettings settings;
1026 spdy::SettingsFlagsAndId id(0);
1027 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1028 const size_t max_concurrent_streams = 1;
1029
1030 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1031 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1032
1033 MockWrite writes[] = { CreateMockWrite(*req),
[email protected]bdebd1b2010-08-09 20:18:081034 CreateMockWrite(*req2),
1035 CreateMockWrite(*req4),
1036 CreateMockWrite(*req3),
[email protected]2bd93022010-07-17 00:58:441037 };
1038 MockRead reads[] = {
[email protected]bdebd1b2010-08-09 20:18:081039 CreateMockRead(*settings_frame, 1),
[email protected]2bd93022010-07-17 00:58:441040 CreateMockRead(*resp),
1041 CreateMockRead(*body),
1042 CreateMockRead(*fbody),
[email protected]bdebd1b2010-08-09 20:18:081043 CreateMockRead(*resp2, 7),
[email protected]2bd93022010-07-17 00:58:441044 CreateMockRead(*body2),
1045 CreateMockRead(*fbody2),
[email protected]bdebd1b2010-08-09 20:18:081046 CreateMockRead(*resp4, 13),
[email protected]2bd93022010-07-17 00:58:441047 CreateMockRead(*fbody4),
[email protected]bdebd1b2010-08-09 20:18:081048 CreateMockRead(*resp3, 16),
[email protected]2bd93022010-07-17 00:58:441049 CreateMockRead(*body3),
1050 CreateMockRead(*fbody3),
1051
1052 MockRead(true, 0, 0), // EOF
1053 };
1054
1055 scoped_refptr<OrderedSocketData> data(
1056 new OrderedSocketData(reads, arraysize(reads),
[email protected]bdebd1b2010-08-09 20:18:081057 writes, arraysize(writes)));
1058 scoped_refptr<OrderedSocketData> data_placeholder(
1059 new OrderedSocketData(NULL, 0, NULL, 0));
[email protected]2bd93022010-07-17 00:58:441060
1061 BoundNetLog log;
1062 TransactionHelperResult out;
[email protected]bdebd1b2010-08-09 20:18:081063 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1064 BoundNetLog(), GetParam());
1065 helper.RunPreTestSetup();
1066 helper.AddData(data.get());
1067 // We require placeholder data because four get requests are sent out, so
1068 // there needs to be four sets of SSL connection data.
1069 helper.AddData(data_placeholder.get());
1070 helper.AddData(data_placeholder.get());
1071 helper.AddData(data_placeholder.get());
1072 scoped_ptr<HttpNetworkTransaction> trans1(
1073 new HttpNetworkTransaction(helper.session()));
1074 scoped_ptr<HttpNetworkTransaction> trans2(
1075 new HttpNetworkTransaction(helper.session()));
1076 scoped_ptr<HttpNetworkTransaction> trans3(
1077 new HttpNetworkTransaction(helper.session()));
1078 scoped_ptr<HttpNetworkTransaction> trans4(
1079 new HttpNetworkTransaction(helper.session()));
[email protected]2bd93022010-07-17 00:58:441080
[email protected]bdebd1b2010-08-09 20:18:081081 TestCompletionCallback callback1;
1082 TestCompletionCallback callback2;
1083 TestCompletionCallback callback3;
1084 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:441085
[email protected]bdebd1b2010-08-09 20:18:081086 HttpRequestInfo httpreq1 = CreateGetRequest();
1087 HttpRequestInfo httpreq2 = CreateGetRequest();
1088 HttpRequestInfo httpreq3 = CreateGetRequest();
1089 HttpRequestInfo httpreq4 = CreateGetRequest();
1090 httpreq4.priority = HIGHEST;
[email protected]2bd93022010-07-17 00:58:441091
[email protected]bdebd1b2010-08-09 20:18:081092 out.rv = trans1->Start(&httpreq1, &callback1, log);
1093 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1094 // run transaction 1 through quickly to force a read of our SETTINGS
1095 // frame
1096 out.rv = callback1.WaitForResult();
1097 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441098
[email protected]bdebd1b2010-08-09 20:18:081099 out.rv = trans2->Start(&httpreq2, &callback2, log);
1100 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1101 out.rv = trans3->Start(&httpreq3, &callback3, log);
1102 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1103 out.rv = trans4->Start(&httpreq4, &callback4, log);
1104 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:441105
[email protected]bdebd1b2010-08-09 20:18:081106 out.rv = callback2.WaitForResult();
1107 ASSERT_EQ(OK, out.rv);
1108 EXPECT_EQ(data->read_index(), 7U); // i.e. the third & fourth trans queued
[email protected]2bd93022010-07-17 00:58:441109
[email protected]bdebd1b2010-08-09 20:18:081110 out.rv = callback3.WaitForResult();
1111 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441112
[email protected]bdebd1b2010-08-09 20:18:081113 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1114 EXPECT_TRUE(response1->headers != NULL);
1115 EXPECT_TRUE(response1->was_fetched_via_spdy);
1116 out.status_line = response1->headers->GetStatusLine();
1117 out.response_info = *response1;
1118 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1119 EXPECT_EQ(OK, out.rv);
1120 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1121 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441122
[email protected]bdebd1b2010-08-09 20:18:081123 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1124 out.status_line = response2->headers->GetStatusLine();
1125 out.response_info = *response2;
1126 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1127 EXPECT_EQ(OK, out.rv);
1128 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1129 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441130
[email protected]bdebd1b2010-08-09 20:18:081131 // notice: response3 gets two hellos, response4 gets one
1132 // hello, so we know dequeuing priority was respected.
1133 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1134 out.status_line = response3->headers->GetStatusLine();
1135 out.response_info = *response3;
1136 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1137 EXPECT_EQ(OK, out.rv);
1138 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1139 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441140
[email protected]bdebd1b2010-08-09 20:18:081141 out.rv = callback4.WaitForResult();
1142 EXPECT_EQ(OK, out.rv);
1143 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1144 out.status_line = response4->headers->GetStatusLine();
1145 out.response_info = *response4;
1146 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1147 EXPECT_EQ(OK, out.rv);
1148 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1149 EXPECT_EQ("hello!", out.response_data);
1150 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441151 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441152}
1153
1154// Similar to ThreeGetsMaxConcurrrent above, however, this test
1155// deletes a session in the middle of the transaction to insure
1156// that we properly remove pendingcreatestream objects from
1157// the spdy_session
[email protected]9e9e842e2010-07-23 23:09:151158TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:441159 // Construct the request.
1160 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1161 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1162 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1163 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
1164
1165 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1166 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1167 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
1168 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
1169
[email protected]2bd93022010-07-17 00:58:441170 spdy::SpdySettings settings;
1171 spdy::SettingsFlagsAndId id(0);
1172 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1173 const size_t max_concurrent_streams = 1;
1174
1175 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1176 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1177
1178 MockWrite writes[] = { CreateMockWrite(*req),
[email protected]bdebd1b2010-08-09 20:18:081179 CreateMockWrite(*req2),
[email protected]2bd93022010-07-17 00:58:441180 };
1181 MockRead reads[] = {
[email protected]bdebd1b2010-08-09 20:18:081182 CreateMockRead(*settings_frame, 1),
[email protected]2bd93022010-07-17 00:58:441183 CreateMockRead(*resp),
1184 CreateMockRead(*body),
1185 CreateMockRead(*fbody),
[email protected]bdebd1b2010-08-09 20:18:081186 CreateMockRead(*resp2, 7),
[email protected]2bd93022010-07-17 00:58:441187 CreateMockRead(*body2),
1188 CreateMockRead(*fbody2),
1189 MockRead(true, 0, 0), // EOF
1190 };
1191
1192 scoped_refptr<OrderedSocketData> data(
1193 new OrderedSocketData(reads, arraysize(reads),
[email protected]bdebd1b2010-08-09 20:18:081194 writes, arraysize(writes)));
1195 scoped_refptr<OrderedSocketData> data_placeholder(
1196 new OrderedSocketData(NULL, 0, NULL, 0));
[email protected]2bd93022010-07-17 00:58:441197
1198 BoundNetLog log;
1199 TransactionHelperResult out;
[email protected]bdebd1b2010-08-09 20:18:081200 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1201 BoundNetLog(), GetParam());
1202 helper.RunPreTestSetup();
1203 helper.AddData(data.get());
1204 // We require placeholder data because three get requests are sent out, so
1205 // there needs to be three sets of SSL connection data.
1206 helper.AddData(data_placeholder.get());
1207 helper.AddData(data_placeholder.get());
1208 scoped_ptr<HttpNetworkTransaction> trans1(
1209 new HttpNetworkTransaction(helper.session()));
1210 scoped_ptr<HttpNetworkTransaction> trans2(
1211 new HttpNetworkTransaction(helper.session()));
1212 scoped_ptr<HttpNetworkTransaction> trans3(
1213 new HttpNetworkTransaction(helper.session()));
[email protected]2bd93022010-07-17 00:58:441214
[email protected]bdebd1b2010-08-09 20:18:081215 TestCompletionCallback callback1;
1216 TestCompletionCallback callback2;
1217 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441218
[email protected]bdebd1b2010-08-09 20:18:081219 HttpRequestInfo httpreq1 = CreateGetRequest();
1220 HttpRequestInfo httpreq2 = CreateGetRequest();
1221 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441222
[email protected]bdebd1b2010-08-09 20:18:081223 out.rv = trans1->Start(&httpreq1, &callback1, log);
1224 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1225 // run transaction 1 through quickly to force a read of our SETTINGS
1226 // frame
1227 out.rv = callback1.WaitForResult();
1228 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441229
[email protected]bdebd1b2010-08-09 20:18:081230 out.rv = trans2->Start(&httpreq2, &callback2, log);
1231 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1232 out.rv = trans3->Start(&httpreq3, &callback3, log);
1233 delete trans3.release();
1234 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1235 out.rv = callback2.WaitForResult();
1236 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441237
[email protected]bdebd1b2010-08-09 20:18:081238 EXPECT_EQ(8U, data->read_index());
[email protected]2bd93022010-07-17 00:58:441239
[email protected]bdebd1b2010-08-09 20:18:081240 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1241 ASSERT_TRUE(response1 != NULL);
1242 EXPECT_TRUE(response1->headers != NULL);
1243 EXPECT_TRUE(response1->was_fetched_via_spdy);
1244 out.status_line = response1->headers->GetStatusLine();
1245 out.response_info = *response1;
1246 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1247 EXPECT_EQ(OK, out.rv);
1248 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1249 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441250
[email protected]bdebd1b2010-08-09 20:18:081251 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1252 ASSERT_TRUE(response2 != NULL);
1253 out.status_line = response2->headers->GetStatusLine();
1254 out.response_info = *response2;
1255 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1256 EXPECT_EQ(OK, out.rv);
1257 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1258 EXPECT_EQ("hello!hello!", out.response_data);
1259 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441260 EXPECT_EQ(OK, out.rv);
[email protected]044dcc52010-09-17 15:44:261261}
[email protected]2bd93022010-07-17 00:58:441262
[email protected]044dcc52010-09-17 15:44:261263// The KillerCallback will delete the transaction on error as part of the
1264// callback.
1265class KillerCallback : public TestCompletionCallback {
1266 public:
1267 explicit KillerCallback(HttpNetworkTransaction* transaction)
1268 : transaction_(transaction) {}
1269
1270 virtual void RunWithParams(const Tuple1<int>& params) {
1271 if (params.a < 0)
1272 delete transaction_;
1273 TestCompletionCallback::RunWithParams(params);
1274 }
1275
1276 private:
1277 HttpNetworkTransaction* transaction_;
1278};
1279
1280// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1281// closes the socket while we have a pending transaction waiting for
1282// a pending stream creation. http://crbug.com/52901
1283TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1284 // Construct the request.
1285 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1286 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1287 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1288 scoped_ptr<spdy::SpdyFrame> fin_body(ConstructSpdyBodyFrame(1, true));
1289
1290 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1291 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1292
1293 spdy::SpdySettings settings;
1294 spdy::SettingsFlagsAndId id(0);
1295 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1296 const size_t max_concurrent_streams = 1;
1297
1298 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1299 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1300
1301 MockWrite writes[] = { CreateMockWrite(*req),
1302 CreateMockWrite(*req2),
1303 };
1304 MockRead reads[] = {
1305 CreateMockRead(*settings_frame, 1),
1306 CreateMockRead(*resp),
1307 CreateMockRead(*body),
1308 CreateMockRead(*fin_body),
1309 CreateMockRead(*resp2, 7),
1310 MockRead(true, ERR_CONNECTION_RESET, 0), // Abort!
1311 };
1312
1313 scoped_refptr<OrderedSocketData> data(
1314 new OrderedSocketData(reads, arraysize(reads),
1315 writes, arraysize(writes)));
1316 scoped_refptr<OrderedSocketData> data_placeholder(
1317 new OrderedSocketData(NULL, 0, NULL, 0));
1318
1319 BoundNetLog log;
1320 TransactionHelperResult out;
1321 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1322 BoundNetLog(), GetParam());
1323 helper.RunPreTestSetup();
1324 helper.AddData(data.get());
1325 // We require placeholder data because three get requests are sent out, so
1326 // there needs to be three sets of SSL connection data.
1327 helper.AddData(data_placeholder.get());
1328 helper.AddData(data_placeholder.get());
1329 HttpNetworkTransaction trans1(helper.session());
1330 HttpNetworkTransaction trans2(helper.session());
1331 HttpNetworkTransaction* trans3(new HttpNetworkTransaction(helper.session()));
1332
1333 TestCompletionCallback callback1;
1334 TestCompletionCallback callback2;
1335 KillerCallback callback3(trans3);
1336
1337 HttpRequestInfo httpreq1 = CreateGetRequest();
1338 HttpRequestInfo httpreq2 = CreateGetRequest();
1339 HttpRequestInfo httpreq3 = CreateGetRequest();
1340
1341 out.rv = trans1.Start(&httpreq1, &callback1, log);
1342 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1343 // run transaction 1 through quickly to force a read of our SETTINGS
1344 // frame
1345 out.rv = callback1.WaitForResult();
1346 ASSERT_EQ(OK, out.rv);
1347
1348 out.rv = trans2.Start(&httpreq2, &callback2, log);
1349 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1350 out.rv = trans3->Start(&httpreq3, &callback3, log);
1351 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1352 out.rv = callback3.WaitForResult();
1353 ASSERT_EQ(ERR_ABORTED, out.rv);
1354
1355 EXPECT_EQ(6U, data->read_index());
1356
1357 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1358 ASSERT_TRUE(response1 != NULL);
1359 EXPECT_TRUE(response1->headers != NULL);
1360 EXPECT_TRUE(response1->was_fetched_via_spdy);
1361 out.status_line = response1->headers->GetStatusLine();
1362 out.response_info = *response1;
1363 out.rv = ReadTransaction(&trans1, &out.response_data);
1364 EXPECT_EQ(OK, out.rv);
1365
1366 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1367 ASSERT_TRUE(response2 != NULL);
1368 out.status_line = response2->headers->GetStatusLine();
1369 out.response_info = *response2;
1370 out.rv = ReadTransaction(&trans2, &out.response_data);
1371 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1372
1373 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441374}
1375
[email protected]d8ef27b2010-08-06 17:34:391376// Test that a simple PUT request works.
1377TEST_P(SpdyNetworkTransactionTest, Put) {
1378 // Setup the request
1379 HttpRequestInfo request;
1380 request.method = "PUT";
1381 request.url = GURL("http://www.google.com/");
1382
1383 const SpdyHeaderInfo kSynStartHeader = {
1384 spdy::SYN_STREAM, // Kind = Syn
1385 1, // Stream ID
1386 0, // Associated stream ID
1387 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1388 spdy::CONTROL_FLAG_FIN, // Control Flags
1389 false, // Compressed
1390 spdy::INVALID, // Status
1391 NULL, // Data
1392 0, // Length
1393 spdy::DATA_FLAG_NONE // Data Flags
1394 };
1395 const char* const kPutHeaders[] = {
1396 "method", "PUT",
1397 "url", "/",
1398 "host", "www.google.com",
1399 "scheme", "http",
1400 "version", "HTTP/1.1",
1401 "content-length", "0"
1402 };
1403 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
[email protected]d08358502010-12-03 22:04:031404 kPutHeaders, arraysize(kPutHeaders) / 2));
[email protected]d8ef27b2010-08-06 17:34:391405 MockWrite writes[] = {
1406 CreateMockWrite(*req)
1407 };
1408
1409 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1410 const SpdyHeaderInfo kSynReplyHeader = {
1411 spdy::SYN_REPLY, // Kind = SynReply
1412 1, // Stream ID
1413 0, // Associated stream ID
1414 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1415 spdy::CONTROL_FLAG_NONE, // Control Flags
1416 false, // Compressed
1417 spdy::INVALID, // Status
1418 NULL, // Data
1419 0, // Length
1420 spdy::DATA_FLAG_NONE // Data Flags
1421 };
1422 static const char* const kStandardGetHeaders[] = {
1423 "status", "200",
1424 "version", "HTTP/1.1"
1425 "content-length", "1234"
1426 };
1427 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
[email protected]d08358502010-12-03 22:04:031428 NULL, 0, kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
[email protected]d8ef27b2010-08-06 17:34:391429 MockRead reads[] = {
1430 CreateMockRead(*resp),
1431 CreateMockRead(*body),
1432 MockRead(true, 0, 0) // EOF
1433 };
1434
1435 scoped_refptr<DelayedSocketData> data(
1436 new DelayedSocketData(1, reads, arraysize(reads),
1437 writes, arraysize(writes)));
1438 NormalSpdyTransactionHelper helper(request,
1439 BoundNetLog(), GetParam());
1440 helper.RunToCompletion(data.get());
1441 TransactionHelperResult out = helper.output();
1442
1443 EXPECT_EQ(OK, out.rv);
1444 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1445}
1446
1447// Test that a simple HEAD request works.
1448TEST_P(SpdyNetworkTransactionTest, Head) {
1449 // Setup the request
1450 HttpRequestInfo request;
1451 request.method = "HEAD";
1452 request.url = GURL("http://www.google.com/");
1453
1454 const SpdyHeaderInfo kSynStartHeader = {
1455 spdy::SYN_STREAM, // Kind = Syn
1456 1, // Stream ID
1457 0, // Associated stream ID
1458 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1459 spdy::CONTROL_FLAG_FIN, // Control Flags
1460 false, // Compressed
1461 spdy::INVALID, // Status
1462 NULL, // Data
1463 0, // Length
1464 spdy::DATA_FLAG_NONE // Data Flags
1465 };
1466 const char* const kHeadHeaders[] = {
1467 "method", "HEAD",
1468 "url", "/",
1469 "host", "www.google.com",
1470 "scheme", "http",
1471 "version", "HTTP/1.1",
1472 "content-length", "0"
1473 };
1474 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
[email protected]d08358502010-12-03 22:04:031475 kHeadHeaders, arraysize(kHeadHeaders) / 2));
[email protected]d8ef27b2010-08-06 17:34:391476 MockWrite writes[] = {
1477 CreateMockWrite(*req)
1478 };
1479
1480 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1481 const SpdyHeaderInfo kSynReplyHeader = {
1482 spdy::SYN_REPLY, // Kind = SynReply
1483 1, // Stream ID
1484 0, // Associated stream ID
1485 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1486 spdy::CONTROL_FLAG_NONE, // Control Flags
1487 false, // Compressed
1488 spdy::INVALID, // Status
1489 NULL, // Data
1490 0, // Length
1491 spdy::DATA_FLAG_NONE // Data Flags
1492 };
1493 static const char* const kStandardGetHeaders[] = {
1494 "status", "200",
1495 "version", "HTTP/1.1"
1496 "content-length", "1234"
1497 };
1498 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
[email protected]d08358502010-12-03 22:04:031499 NULL, 0, kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
[email protected]d8ef27b2010-08-06 17:34:391500 MockRead reads[] = {
1501 CreateMockRead(*resp),
1502 CreateMockRead(*body),
1503 MockRead(true, 0, 0) // EOF
1504 };
1505
1506 scoped_refptr<DelayedSocketData> data(
1507 new DelayedSocketData(1, reads, arraysize(reads),
1508 writes, arraysize(writes)));
1509 NormalSpdyTransactionHelper helper(request,
1510 BoundNetLog(), GetParam());
1511 helper.RunToCompletion(data.get());
1512 TransactionHelperResult out = helper.output();
1513
1514 EXPECT_EQ(OK, out.rv);
1515 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1516}
1517
[email protected]72552f02009-10-28 15:25:011518// Test that a simple POST works.
[email protected]9e9e842e2010-07-23 23:09:151519TEST_P(SpdyNetworkTransactionTest, Post) {
[email protected]310240592010-08-05 21:04:191520 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(kUploadDataSize, NULL, 0));
[email protected]2bd93022010-07-17 00:58:441521 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141522 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131523 CreateMockWrite(*req),
1524 CreateMockWrite(*body), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141525 };
[email protected]72552f02009-10-28 15:25:011526
[email protected]a4aeaf42010-06-30 19:57:281527 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
[email protected]ff57bb82009-11-12 06:52:141528 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131529 CreateMockRead(*resp),
1530 CreateMockRead(*body),
[email protected]72552f02009-10-28 15:25:011531 MockRead(true, 0, 0) // EOF
[email protected]aea80602009-09-18 00:55:081532 };
1533
[email protected]bf2491a92009-11-29 16:39:481534 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:391535 new DelayedSocketData(2, reads, arraysize(reads),
1536 writes, arraysize(writes)));
[email protected]310240592010-08-05 21:04:191537 NormalSpdyTransactionHelper helper(CreatePostRequest(),
[email protected]9e9e842e2010-07-23 23:09:151538 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471539 helper.RunToCompletion(data.get());
1540 TransactionHelperResult out = helper.output();
[email protected]aea80602009-09-18 00:55:081541 EXPECT_EQ(OK, out.rv);
1542 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1543 EXPECT_EQ("hello!", out.response_data);
1544}
1545
[email protected]0c9bf872011-03-04 17:53:221546// Test that a chunked POST works.
1547TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1548 UploadDataStream::set_merge_chunks(false);
1549 scoped_ptr<spdy::SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
1550 scoped_ptr<spdy::SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
1551 scoped_ptr<spdy::SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
1552 MockWrite writes[] = {
1553 CreateMockWrite(*req),
1554 CreateMockWrite(*chunk1),
1555 CreateMockWrite(*chunk2),
1556 };
1557
1558 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1559 MockRead reads[] = {
1560 CreateMockRead(*resp),
1561 CreateMockRead(*chunk1),
1562 CreateMockRead(*chunk2),
1563 MockRead(true, 0, 0) // EOF
1564 };
1565
1566 scoped_refptr<DelayedSocketData> data(
1567 new DelayedSocketData(2, reads, arraysize(reads),
1568 writes, arraysize(writes)));
1569 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1570 BoundNetLog(), GetParam());
1571 helper.RunToCompletion(data.get());
1572 TransactionHelperResult out = helper.output();
1573 EXPECT_EQ(OK, out.rv);
1574 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1575 EXPECT_EQ("hello!hello!", out.response_data);
1576}
1577
[email protected]a33cad2b62010-07-30 22:24:391578// Test that a POST without any post data works.
1579TEST_P(SpdyNetworkTransactionTest, NullPost) {
1580 // Setup the request
1581 HttpRequestInfo request;
1582 request.method = "POST";
1583 request.url = GURL("http://www.google.com/");
1584 // Create an empty UploadData.
1585 request.upload_data = NULL;
1586
1587 // When request.upload_data is NULL for post, content-length is
1588 // expected to be 0.
1589 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(0, NULL, 0));
1590 // Set the FIN bit since there will be no body.
1591 req->set_flags(spdy::CONTROL_FLAG_FIN);
1592 MockWrite writes[] = {
1593 CreateMockWrite(*req),
1594 };
1595
1596 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1597 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1598 MockRead reads[] = {
1599 CreateMockRead(*resp),
1600 CreateMockRead(*body),
1601 MockRead(true, 0, 0) // EOF
1602 };
1603
1604 scoped_refptr<DelayedSocketData> data(
1605 new DelayedSocketData(1, reads, arraysize(reads),
1606 writes, arraysize(writes)));
1607
1608 NormalSpdyTransactionHelper helper(request,
1609 BoundNetLog(), GetParam());
1610 helper.RunToCompletion(data.get());
1611 TransactionHelperResult out = helper.output();
1612 EXPECT_EQ(OK, out.rv);
1613 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1614 EXPECT_EQ("hello!", out.response_data);
1615}
1616
[email protected]edd3b0a52009-11-24 18:56:361617// Test that a simple POST works.
[email protected]9e9e842e2010-07-23 23:09:151618TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]edd3b0a52009-11-24 18:56:361619 // Setup the request
1620 HttpRequestInfo request;
1621 request.method = "POST";
1622 request.url = GURL("http://www.google.com/");
1623 // Create an empty UploadData.
1624 request.upload_data = new UploadData();
1625
[email protected]a33cad2b62010-07-30 22:24:391626 // Http POST Content-Length is using UploadDataStream::size().
1627 // It is the same as request.upload_data->GetContentLength().
[email protected]219ba8cb2010-07-31 04:51:461628 scoped_ptr<UploadDataStream> stream(UploadDataStream::Create(
1629 request.upload_data, NULL));
1630 ASSERT_EQ(request.upload_data->GetContentLength(), stream->size());
[email protected]a33cad2b62010-07-30 22:24:391631
1632 scoped_ptr<spdy::SpdyFrame>
1633 req(ConstructSpdyPost(request.upload_data->GetContentLength(), NULL, 0));
[email protected]a4aeaf42010-06-30 19:57:281634 // Set the FIN bit since there will be no body.
1635 req->set_flags(spdy::CONTROL_FLAG_FIN);
[email protected]edd3b0a52009-11-24 18:56:361636 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131637 CreateMockWrite(*req),
[email protected]edd3b0a52009-11-24 18:56:361638 };
1639
[email protected]a4aeaf42010-06-30 19:57:281640 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
[email protected]2bd93022010-07-17 00:58:441641 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361642 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131643 CreateMockRead(*resp),
1644 CreateMockRead(*body),
[email protected]edd3b0a52009-11-24 18:56:361645 MockRead(true, 0, 0) // EOF
1646 };
1647
[email protected]bf2491a92009-11-29 16:39:481648 scoped_refptr<DelayedSocketData> data(
[email protected]3f662f12010-03-25 19:56:121649 new DelayedSocketData(1, reads, arraysize(reads),
1650 writes, arraysize(writes)));
[email protected]bf2491a92009-11-29 16:39:481651
[email protected]3caf5542010-07-16 15:19:471652 NormalSpdyTransactionHelper helper(request,
[email protected]9e9e842e2010-07-23 23:09:151653 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471654 helper.RunToCompletion(data.get());
1655 TransactionHelperResult out = helper.output();
[email protected]edd3b0a52009-11-24 18:56:361656 EXPECT_EQ(OK, out.rv);
1657 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1658 EXPECT_EQ("hello!", out.response_data);
1659}
1660
[email protected]a5566f9702010-05-05 22:25:431661// While we're doing a post, the server sends back a SYN_REPLY.
[email protected]9e9e842e2010-07-23 23:09:151662TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) {
[email protected]a4aeaf42010-06-30 19:57:281663 static const char upload[] = { "hello!" };
[email protected]a5566f9702010-05-05 22:25:431664
1665 // Setup the request
1666 HttpRequestInfo request;
1667 request.method = "POST";
1668 request.url = GURL("http://www.google.com/");
1669 request.upload_data = new UploadData();
1670 request.upload_data->AppendBytes(upload, sizeof(upload));
1671
[email protected]a33cad2b62010-07-30 22:24:391672 // Http POST Content-Length is using UploadDataStream::size().
1673 // It is the same as request.upload_data->GetContentLength().
[email protected]219ba8cb2010-07-31 04:51:461674 scoped_ptr<UploadDataStream> stream(UploadDataStream::Create(
1675 request.upload_data, NULL));
1676 ASSERT_EQ(request.upload_data->GetContentLength(), stream->size());
[email protected]82918cc2010-08-25 17:24:501677 scoped_ptr<spdy::SpdyFrame> stream_reply(ConstructSpdyPostSynReply(NULL, 0));
1678 scoped_ptr<spdy::SpdyFrame> stream_body(ConstructSpdyBodyFrame(1, true));
[email protected]a5566f9702010-05-05 22:25:431679 MockRead reads[] = {
[email protected]82918cc2010-08-25 17:24:501680 CreateMockRead(*stream_reply, 2),
1681 CreateMockRead(*stream_body, 3),
[email protected]a5566f9702010-05-05 22:25:431682 MockRead(false, 0, 0) // EOF
1683 };
1684
1685 scoped_refptr<DelayedSocketData> data(
[email protected]8e6441ca2010-08-19 05:56:381686 new DelayedSocketData(0, reads, arraysize(reads), NULL, 0));
[email protected]3caf5542010-07-16 15:19:471687 NormalSpdyTransactionHelper helper(request,
[email protected]9e9e842e2010-07-23 23:09:151688 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471689 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:581690 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:471691 helper.RunDefaultTest();
[email protected]310240592010-08-05 21:04:191692 helper.VerifyDataConsumed();
1693
[email protected]3caf5542010-07-16 15:19:471694 TransactionHelperResult out = helper.output();
[email protected]82918cc2010-08-25 17:24:501695 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
[email protected]a5566f9702010-05-05 22:25:431696}
1697
[email protected]f9a26d72010-08-03 18:07:131698// The client upon cancellation tries to send a RST_STREAM frame. The mock
1699// socket causes the TCP write to return zero. This test checks that the client
1700// tries to queue up the RST_STREAM frame again.
[email protected]3b7828432010-08-18 18:33:271701TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
[email protected]f9a26d72010-08-03 18:07:131702 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1703 scoped_ptr<spdy::SpdyFrame> rst(
1704 ConstructSpdyRstStream(1, spdy::CANCEL));
1705 MockWrite writes[] = {
[email protected]3b7828432010-08-18 18:33:271706 CreateMockWrite(*req.get(), 0, false),
1707 MockWrite(false, 0, 0, 2),
1708 CreateMockWrite(*rst.get(), 3, false),
[email protected]f9a26d72010-08-03 18:07:131709 };
1710
1711 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1712 MockRead reads[] = {
[email protected]5e6609582010-10-05 18:14:201713 CreateMockRead(*resp.get(), 1, true),
1714 MockRead(true, 0, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:131715 };
1716
[email protected]3b7828432010-08-18 18:33:271717 scoped_refptr<DeterministicSocketData> data(
1718 new DeterministicSocketData(reads, arraysize(reads),
[email protected]f9a26d72010-08-03 18:07:131719 writes, arraysize(writes)));
1720 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1721 BoundNetLog(), GetParam());
[email protected]3b7828432010-08-18 18:33:271722 helper.SetDeterministic();
[email protected]f9a26d72010-08-03 18:07:131723 helper.RunPreTestSetup();
[email protected]3b7828432010-08-18 18:33:271724 helper.AddDeterministicData(data.get());
[email protected]f9a26d72010-08-03 18:07:131725 HttpNetworkTransaction* trans = helper.trans();
1726
1727 TestCompletionCallback callback;
1728 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
1729 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3b7828432010-08-18 18:33:271730
1731 data->SetStop(2);
1732 data->Run();
[email protected]f9a26d72010-08-03 18:07:131733 helper.ResetTrans();
[email protected]3b7828432010-08-18 18:33:271734 data->SetStop(20);
1735 data->Run();
1736
[email protected]f9a26d72010-08-03 18:07:131737 helper.VerifyDataConsumed();
1738}
1739
[email protected]93300672009-10-24 13:22:511740// Test that the transaction doesn't crash when we don't have a reply.
[email protected]9e9e842e2010-07-23 23:09:151741TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
[email protected]2bd93022010-07-17 00:58:441742 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141743 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131744 CreateMockRead(*body),
[email protected]72552f02009-10-28 15:25:011745 MockRead(true, 0, 0) // EOF
[email protected]93300672009-10-24 13:22:511746 };
1747
[email protected]bf2491a92009-11-29 16:39:481748 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:391749 new DelayedSocketData(1, reads, arraysize(reads), NULL, 0));
[email protected]3caf5542010-07-16 15:19:471750 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151751 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471752 helper.RunToCompletion(data.get());
1753 TransactionHelperResult out = helper.output();
[email protected]93300672009-10-24 13:22:511754 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
1755}
1756
[email protected]d30022352010-06-24 19:17:581757// Test that the transaction doesn't crash when we get two replies on the same
1758// stream ID. See http://crbug.com/45639.
[email protected]9e9e842e2010-07-23 23:09:151759TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
[email protected]2bd93022010-07-17 00:58:441760 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:131761 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]d30022352010-06-24 19:17:581762
[email protected]2bd93022010-07-17 00:58:441763 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1764 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]d30022352010-06-24 19:17:581765 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131766 CreateMockRead(*resp),
1767 CreateMockRead(*resp),
1768 CreateMockRead(*body),
[email protected]d30022352010-06-24 19:17:581769 MockRead(true, 0, 0) // EOF
1770 };
1771
[email protected]d30022352010-06-24 19:17:581772 scoped_refptr<DelayedSocketData> data(
1773 new DelayedSocketData(1, reads, arraysize(reads),
1774 writes, arraysize(writes)));
[email protected]d30022352010-06-24 19:17:581775
[email protected]3caf5542010-07-16 15:19:471776 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151777 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471778 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:581779 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:471780
1781 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:581782
1783 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:471784 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]d30022352010-06-24 19:17:581785 EXPECT_EQ(ERR_IO_PENDING, rv);
1786 rv = callback.WaitForResult();
1787 EXPECT_EQ(OK, rv);
1788
1789 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a5c493b92010-08-06 23:04:291790 ASSERT_TRUE(response != NULL);
[email protected]d30022352010-06-24 19:17:581791 EXPECT_TRUE(response->headers != NULL);
1792 EXPECT_TRUE(response->was_fetched_via_spdy);
1793 std::string response_data;
[email protected]3caf5542010-07-16 15:19:471794 rv = ReadTransaction(trans, &response_data);
[email protected]d30022352010-06-24 19:17:581795 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
[email protected]3caf5542010-07-16 15:19:471796
1797 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:581798}
1799
[email protected]7349c6b12010-07-22 02:29:161800// Test that sent data frames and received WINDOW_UPDATE frames change
1801// the send_window_size_ correctly.
[email protected]6abf5372010-08-17 15:44:251802
1803// WINDOW_UPDATE is different than most other frames in that it can arrive
1804// while the client is still sending the request body. In order to enforce
1805// this scenario, we feed a couple of dummy frames and give a delay of 0 to
1806// socket data provider, so that initial read that is done as soon as the
1807// stream is created, succeeds and schedules another read. This way reads
1808// and writes are interleaved; after doing a full frame write, SpdyStream
1809// will break out of DoLoop and will read and process a WINDOW_UPDATE.
1810// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
1811// since request has not been completely written, therefore we feed
1812// enough number of WINDOW_UPDATEs to finish the first read and cause a
1813// write, leading to a complete write of request body; after that we send
1814// a reply with a body, to cause a graceful shutdown.
1815
1816// TODO(agayev): develop a socket data provider where both, reads and
[email protected]450c5022010-08-26 02:38:281817// writes are ordered so that writing tests like these are easy and rewrite
1818// all these tests using it. Right now we are working around the
1819// limitations as described above and it's not deterministic, tests may
1820// fail under specific circumstances.
1821TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
1822 SpdySession::set_flow_control(true);
[email protected]5af3c572010-07-20 14:16:271823
[email protected]6abf5372010-08-17 15:44:251824 static int kFrameCount = 2;
1825 scoped_ptr<std::string> content(
1826 new std::string(kMaxSpdyFrameChunkSize, 'a'));
1827 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
1828 kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
1829 scoped_ptr<spdy::SpdyFrame> body(
1830 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
1831 scoped_ptr<spdy::SpdyFrame> body_end(
1832 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), true));
1833
[email protected]5af3c572010-07-20 14:16:271834 MockWrite writes[] = {
1835 CreateMockWrite(*req),
1836 CreateMockWrite(*body),
[email protected]6abf5372010-08-17 15:44:251837 CreateMockWrite(*body_end),
[email protected]5af3c572010-07-20 14:16:271838 };
1839
[email protected]5af3c572010-07-20 14:16:271840 static const int kDeltaWindowSize = 0xff;
[email protected]6abf5372010-08-17 15:44:251841 static const int kDeltaCount = 4;
[email protected]5af3c572010-07-20 14:16:271842 scoped_ptr<spdy::SpdyFrame> window_update(
1843 ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
[email protected]6abf5372010-08-17 15:44:251844 scoped_ptr<spdy::SpdyFrame> window_update_dummy(
1845 ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
1846 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
[email protected]5af3c572010-07-20 14:16:271847 MockRead reads[] = {
[email protected]6abf5372010-08-17 15:44:251848 CreateMockRead(*window_update_dummy),
1849 CreateMockRead(*window_update_dummy),
[email protected]450c5022010-08-26 02:38:281850 CreateMockRead(*window_update_dummy),
[email protected]6abf5372010-08-17 15:44:251851 CreateMockRead(*window_update), // Four updates, therefore window
1852 CreateMockRead(*window_update), // size should increase by
1853 CreateMockRead(*window_update), // kDeltaWindowSize * 4
[email protected]5af3c572010-07-20 14:16:271854 CreateMockRead(*window_update),
[email protected]6abf5372010-08-17 15:44:251855 CreateMockRead(*resp),
1856 CreateMockRead(*body_end),
[email protected]5af3c572010-07-20 14:16:271857 MockRead(true, 0, 0) // EOF
1858 };
1859
1860 scoped_refptr<DelayedSocketData> data(
[email protected]6abf5372010-08-17 15:44:251861 new DelayedSocketData(0, reads, arraysize(reads),
[email protected]5af3c572010-07-20 14:16:271862 writes, arraysize(writes)));
[email protected]5af3c572010-07-20 14:16:271863
[email protected]6abf5372010-08-17 15:44:251864 // Setup the request
1865 HttpRequestInfo request;
1866 request.method = "POST";
1867 request.url = GURL(kDefaultURL);
1868 request.upload_data = new UploadData();
1869 for (int i = 0; i < kFrameCount; ++i)
1870 request.upload_data->AppendBytes(content->c_str(), content->size());
1871
1872 NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam());
[email protected]310240592010-08-05 21:04:191873 helper.AddData(data.get());
1874 helper.RunPreTestSetup();
1875
1876 HttpNetworkTransaction* trans = helper.trans();
[email protected]5af3c572010-07-20 14:16:271877
1878 TestCompletionCallback callback;
[email protected]310240592010-08-05 21:04:191879 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]5af3c572010-07-20 14:16:271880
1881 EXPECT_EQ(ERR_IO_PENDING, rv);
1882 rv = callback.WaitForResult();
1883 EXPECT_EQ(OK, rv);
1884
[email protected]4d4a5162010-09-21 22:44:041885 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
[email protected]6abf5372010-08-17 15:44:251886 ASSERT_TRUE(stream != NULL);
1887 ASSERT_TRUE(stream->stream() != NULL);
[email protected]d08358502010-12-03 22:04:031888 EXPECT_EQ(static_cast<int>(spdy::kSpdyStreamInitialWindowSize) +
[email protected]6abf5372010-08-17 15:44:251889 kDeltaWindowSize * kDeltaCount -
1890 kMaxSpdyFrameChunkSize * kFrameCount,
1891 stream->stream()->send_window_size());
[email protected]310240592010-08-05 21:04:191892 helper.VerifyDataConsumed();
[email protected]450c5022010-08-26 02:38:281893 SpdySession::set_flow_control(false);
1894}
1895
1896// Test that received data frames and sent WINDOW_UPDATE frames change
1897// the recv_window_size_ correctly.
1898TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
1899 SpdySession::set_flow_control(true);
1900
1901 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1902 scoped_ptr<spdy::SpdyFrame> window_update(
1903 ConstructSpdyWindowUpdate(1, kUploadDataSize));
1904
1905 MockWrite writes[] = {
1906 CreateMockWrite(*req),
1907 CreateMockWrite(*window_update),
1908 };
1909
1910 scoped_ptr<spdy::SpdyFrame> resp(
1911 ConstructSpdyGetSynReply(NULL, 0, 1));
1912 scoped_ptr<spdy::SpdyFrame> body_no_fin(
1913 ConstructSpdyBodyFrame(1, false));
1914 scoped_ptr<spdy::SpdyFrame> body_fin(
1915 ConstructSpdyBodyFrame(1, NULL, 0, true));
1916 MockRead reads[] = {
1917 CreateMockRead(*resp),
1918 CreateMockRead(*body_no_fin),
1919 MockRead(true, ERR_IO_PENDING, 0), // Force a pause
1920 CreateMockRead(*body_fin),
1921 MockRead(true, ERR_IO_PENDING, 0), // Force a pause
1922 MockRead(true, 0, 0) // EOF
1923 };
1924
1925 scoped_refptr<DelayedSocketData> data(
1926 new DelayedSocketData(1, reads, arraysize(reads),
1927 writes, arraysize(writes)));
1928
1929 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1930 BoundNetLog(), GetParam());
1931 helper.AddData(data.get());
1932 helper.RunPreTestSetup();
1933 HttpNetworkTransaction* trans = helper.trans();
1934
1935 TestCompletionCallback callback;
1936 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
1937
1938 EXPECT_EQ(ERR_IO_PENDING, rv);
1939 rv = callback.WaitForResult();
1940 EXPECT_EQ(OK, rv);
1941
1942 SpdyHttpStream* stream =
[email protected]4d4a5162010-09-21 22:44:041943 static_cast<SpdyHttpStream*>(trans->stream_.get());
[email protected]450c5022010-08-26 02:38:281944 ASSERT_TRUE(stream != NULL);
1945 ASSERT_TRUE(stream->stream() != NULL);
1946
[email protected]d08358502010-12-03 22:04:031947 EXPECT_EQ(
1948 static_cast<int>(spdy::kSpdyStreamInitialWindowSize) - kUploadDataSize,
1949 stream->stream()->recv_window_size());
[email protected]450c5022010-08-26 02:38:281950
1951 const HttpResponseInfo* response = trans->GetResponseInfo();
1952 ASSERT_TRUE(response != NULL);
1953 ASSERT_TRUE(response->headers != NULL);
1954 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1955 EXPECT_TRUE(response->was_fetched_via_spdy);
1956
1957 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
1958 // size increased to default.
[email protected]ad8e04a2010-11-01 04:16:271959 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kUploadDataSize));
[email protected]450c5022010-08-26 02:38:281960 rv = trans->Read(buf, kUploadDataSize, NULL);
1961 EXPECT_EQ(kUploadDataSize, rv);
1962 std::string content(buf->data(), buf->data()+kUploadDataSize);
1963 EXPECT_STREQ(kUploadData, content.c_str());
1964
1965 // Schedule the reading of empty data frame with FIN
1966 data->CompleteRead();
1967
1968 // Force write of WINDOW_UPDATE which was scheduled during the above
1969 // read.
1970 MessageLoop::current()->RunAllPending();
1971
1972 // Read EOF.
1973 data->CompleteRead();
1974
1975 helper.VerifyDataConsumed();
1976 SpdySession::set_flow_control(false);
[email protected]5af3c572010-07-20 14:16:271977}
1978
[email protected]6abf5372010-08-17 15:44:251979// Test that WINDOW_UPDATE frame causing overflow is handled correctly. We
1980// use the same trick as in the above test to enforce our scenario.
[email protected]9e9e842e2010-07-23 23:09:151981TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]450c5022010-08-26 02:38:281982 SpdySession::set_flow_control(true);
[email protected]5af3c572010-07-20 14:16:271983
[email protected]310240592010-08-05 21:04:191984 // number of full frames we hope to write (but will not, used to
1985 // set content-length header correctly)
1986 static int kFrameCount = 3;
[email protected]5af3c572010-07-20 14:16:271987
[email protected]310240592010-08-05 21:04:191988 scoped_ptr<std::string> content(
1989 new std::string(kMaxSpdyFrameChunkSize, 'a'));
[email protected]310240592010-08-05 21:04:191990 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
1991 kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
[email protected]310240592010-08-05 21:04:191992 scoped_ptr<spdy::SpdyFrame> body(
1993 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
[email protected]5af3c572010-07-20 14:16:271994 scoped_ptr<spdy::SpdyFrame> rst(
1995 ConstructSpdyRstStream(1, spdy::FLOW_CONTROL_ERROR));
[email protected]310240592010-08-05 21:04:191996
1997 // We're not going to write a data frame with FIN, we'll receive a bad
1998 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
[email protected]5af3c572010-07-20 14:16:271999 MockWrite writes[] = {
2000 CreateMockWrite(*req),
2001 CreateMockWrite(*body),
2002 CreateMockWrite(*rst),
2003 };
2004
[email protected]a33cad2b62010-07-30 22:24:392005 static const int kDeltaWindowSize = 0x7fffffff; // cause an overflow
[email protected]5af3c572010-07-20 14:16:272006 scoped_ptr<spdy::SpdyFrame> window_update(
2007 ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
[email protected]310240592010-08-05 21:04:192008 scoped_ptr<spdy::SpdyFrame> window_update2(
2009 ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
[email protected]5af3c572010-07-20 14:16:272010 scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
[email protected]310240592010-08-05 21:04:192011
[email protected]5af3c572010-07-20 14:16:272012 MockRead reads[] = {
[email protected]310240592010-08-05 21:04:192013 CreateMockRead(*window_update2),
2014 CreateMockRead(*window_update2),
[email protected]5af3c572010-07-20 14:16:272015 CreateMockRead(*window_update),
[email protected]310240592010-08-05 21:04:192016 CreateMockRead(*window_update),
2017 CreateMockRead(*window_update),
[email protected]8e6441ca2010-08-19 05:56:382018 MockRead(true, ERR_IO_PENDING, 0), // Wait for the RST to be written.
[email protected]5af3c572010-07-20 14:16:272019 MockRead(true, 0, 0) // EOF
2020 };
2021
2022 scoped_refptr<DelayedSocketData> data(
[email protected]310240592010-08-05 21:04:192023 new DelayedSocketData(0, reads, arraysize(reads),
[email protected]5af3c572010-07-20 14:16:272024 writes, arraysize(writes)));
[email protected]5af3c572010-07-20 14:16:272025
[email protected]310240592010-08-05 21:04:192026 // Setup the request
2027 HttpRequestInfo request;
2028 request.method = "POST";
2029 request.url = GURL("http://www.google.com/");
2030 request.upload_data = new UploadData();
2031 for (int i = 0; i < kFrameCount; ++i)
2032 request.upload_data->AppendBytes(content->c_str(), content->size());
2033
2034 NormalSpdyTransactionHelper helper(request,
2035 BoundNetLog(), GetParam());
2036 helper.AddData(data.get());
2037 helper.RunPreTestSetup();
2038
2039 HttpNetworkTransaction* trans = helper.trans();
[email protected]5af3c572010-07-20 14:16:272040
2041 TestCompletionCallback callback;
[email protected]310240592010-08-05 21:04:192042 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]5af3c572010-07-20 14:16:272043
2044 EXPECT_EQ(ERR_IO_PENDING, rv);
2045 rv = callback.WaitForResult();
2046 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2047
[email protected]8e6441ca2010-08-19 05:56:382048 data->CompleteRead();
2049
[email protected]310240592010-08-05 21:04:192050 ASSERT_TRUE(helper.session() != NULL);
2051 ASSERT_TRUE(helper.session()->spdy_session_pool() != NULL);
[email protected]a01ea222010-08-19 16:50:532052 helper.session()->spdy_session_pool()->CloseAllSessions();
[email protected]310240592010-08-05 21:04:192053 helper.VerifyDataConsumed();
[email protected]5af3c572010-07-20 14:16:272054
[email protected]450c5022010-08-26 02:38:282055 SpdySession::set_flow_control(false);
[email protected]310240592010-08-05 21:04:192056}
2057
2058// Test that after hitting a send window size of 0, the write process
2059// stalls and upon receiving WINDOW_UPDATE frame write resumes.
[email protected]6abf5372010-08-17 15:44:252060
[email protected]310240592010-08-05 21:04:192061// This test constructs a POST request followed by enough data frames
2062// containing 'a' that would make the window size 0, followed by another
2063// data frame containing default content (which is "hello!") and this frame
2064// also contains a FIN flag. DelayedSocketData is used to enforce all
2065// writes go through before a read could happen. However, the last frame
2066// ("hello!") is not supposed to go through since by the time its turn
2067// arrives, window size is 0. At this point MessageLoop::Run() called via
2068// callback would block. Therefore we call MessageLoop::RunAllPending()
2069// which returns after performing all possible writes. We use DCHECKS to
2070// ensure that last data frame is still there and stream has stalled.
2071// After that, next read is artifically enforced, which causes a
2072// WINDOW_UPDATE to be read and I/O process resumes.
2073TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
[email protected]450c5022010-08-26 02:38:282074 SpdySession::set_flow_control(true);
[email protected]310240592010-08-05 21:04:192075
2076 // Number of frames we need to send to zero out the window size: data
2077 // frames plus SYN_STREAM plus the last data frame; also we need another
2078 // data frame that we will send once the WINDOW_UPDATE is received,
2079 // therefore +3.
[email protected]d08358502010-12-03 22:04:032080 size_t nwrites =
2081 spdy::kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
[email protected]310240592010-08-05 21:04:192082
2083 // Calculate last frame's size; 0 size data frame is legal.
[email protected]d08358502010-12-03 22:04:032084 size_t last_frame_size =
2085 spdy::kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
[email protected]310240592010-08-05 21:04:192086
2087 // Construct content for a data frame of maximum size.
2088 scoped_ptr<std::string> content(
2089 new std::string(kMaxSpdyFrameChunkSize, 'a'));
2090
2091 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
[email protected]d08358502010-12-03 22:04:032092 spdy::kSpdyStreamInitialWindowSize + kUploadDataSize, NULL, 0));
[email protected]310240592010-08-05 21:04:192093
2094 // Full frames.
2095 scoped_ptr<spdy::SpdyFrame> body1(
2096 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
2097
2098 // Last frame to zero out the window size.
2099 scoped_ptr<spdy::SpdyFrame> body2(
2100 ConstructSpdyBodyFrame(1, content->c_str(), last_frame_size, false));
2101
2102 // Data frame to be sent once WINDOW_UPDATE frame is received.
2103 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(1, true));
2104
2105 // Fill in mock writes.
2106 scoped_array<MockWrite> writes(new MockWrite[nwrites]);
2107 size_t i = 0;
2108 writes[i] = CreateMockWrite(*req);
2109 for (i = 1; i < nwrites-2; i++)
2110 writes[i] = CreateMockWrite(*body1);
2111 writes[i++] = CreateMockWrite(*body2);
2112 writes[i] = CreateMockWrite(*body3);
2113
[email protected]6abf5372010-08-17 15:44:252114 // Construct read frame, give enough space to upload the rest of the
[email protected]310240592010-08-05 21:04:192115 // data.
2116 scoped_ptr<spdy::SpdyFrame> window_update(
2117 ConstructSpdyWindowUpdate(1, kUploadDataSize));
2118 scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
2119 MockRead reads[] = {
2120 CreateMockRead(*window_update),
2121 CreateMockRead(*window_update),
2122 CreateMockRead(*reply),
2123 CreateMockRead(*body2),
2124 CreateMockRead(*body3),
2125 MockRead(true, 0, 0) // EOF
2126 };
2127
2128 // Force all writes to happen before any read, last write will not
2129 // actually queue a frame, due to window size being 0.
2130 scoped_refptr<DelayedSocketData> data(
2131 new DelayedSocketData(nwrites, reads, arraysize(reads),
2132 writes.get(), nwrites));
2133
2134 HttpRequestInfo request;
2135 request.method = "POST";
2136 request.url = GURL("http://www.google.com/");
2137 request.upload_data = new UploadData();
2138 scoped_ptr<std::string> upload_data(
[email protected]d08358502010-12-03 22:04:032139 new std::string(spdy::kSpdyStreamInitialWindowSize, 'a'));
[email protected]310240592010-08-05 21:04:192140 upload_data->append(kUploadData, kUploadDataSize);
2141 request.upload_data->AppendBytes(upload_data->c_str(), upload_data->size());
2142 NormalSpdyTransactionHelper helper(request,
2143 BoundNetLog(), GetParam());
2144 helper.AddData(data.get());
2145 helper.RunPreTestSetup();
2146
2147 HttpNetworkTransaction* trans = helper.trans();
2148
2149 TestCompletionCallback callback;
2150 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
2151 EXPECT_EQ(ERR_IO_PENDING, rv);
2152
2153 MessageLoop::current()->RunAllPending(); // Write as much as we can.
[email protected]6abf5372010-08-17 15:44:252154
[email protected]4d4a5162010-09-21 22:44:042155 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
[email protected]6abf5372010-08-17 15:44:252156 ASSERT_TRUE(stream != NULL);
2157 ASSERT_TRUE(stream->stream() != NULL);
2158 EXPECT_EQ(0, stream->stream()->send_window_size());
2159 EXPECT_FALSE(stream->request_body_stream_->eof());
[email protected]310240592010-08-05 21:04:192160
2161 data->ForceNextRead(); // Read in WINDOW_UPDATE frame.
2162 rv = callback.WaitForResult();
2163 helper.VerifyDataConsumed();
[email protected]7349c6b12010-07-22 02:29:162164
[email protected]450c5022010-08-26 02:38:282165 SpdySession::set_flow_control(false);
[email protected]5af3c572010-07-20 14:16:272166}
2167
[email protected]9e9e842e2010-07-23 23:09:152168TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:382169 // Construct the request.
[email protected]2bd93022010-07-17 00:58:442170 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]34437af82009-11-06 02:28:492171 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:132172 CreateMockWrite(*req),
[email protected]34437af82009-11-06 02:28:492173 };
2174
[email protected]2bd93022010-07-17 00:58:442175 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]34437af82009-11-06 02:28:492176 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132177 CreateMockRead(*resp),
[email protected]34437af82009-11-06 02:28:492178 // This following read isn't used by the test, except during the
[email protected]955fc2e72010-02-08 20:37:302179 // RunAllPending() call at the end since the SpdySession survives the
[email protected]3caf5542010-07-16 15:19:472180 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
[email protected]34437af82009-11-06 02:28:492181 // MockRead will do here.
2182 MockRead(true, 0, 0) // EOF
2183 };
2184
[email protected]31a2bfe2010-02-09 08:03:392185 StaticSocketDataProvider data(reads, arraysize(reads),
2186 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472187
2188 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152189 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:472190 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:582191 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472192 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:492193
2194 TestCompletionCallback callback;
[email protected]d3cee19d2010-06-22 18:42:182195 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]34437af82009-11-06 02:28:492196 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472197 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:492198
[email protected]30c942b2010-07-21 16:59:592199 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:492200 // MockClientSocketFactory) are still alive.
2201 MessageLoop::current()->RunAllPending();
[email protected]3caf5542010-07-16 15:19:472202 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:492203}
[email protected]72552f02009-10-28 15:25:012204
[email protected]6c6ea172010-07-27 20:04:032205// Verify that the client sends a Rst Frame upon cancelling the stream.
[email protected]3b7828432010-08-18 18:33:272206TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
[email protected]6c6ea172010-07-27 20:04:032207 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2208 scoped_ptr<spdy::SpdyFrame> rst(
2209 ConstructSpdyRstStream(1, spdy::CANCEL));
2210 MockWrite writes[] = {
[email protected]3b7828432010-08-18 18:33:272211 CreateMockWrite(*req, 0, false),
2212 CreateMockWrite(*rst, 2, false),
[email protected]6c6ea172010-07-27 20:04:032213 };
2214
2215 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2216 MockRead reads[] = {
[email protected]5e6609582010-10-05 18:14:202217 CreateMockRead(*resp, 1, true),
2218 MockRead(true, 0, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:032219 };
2220
[email protected]3b7828432010-08-18 18:33:272221 scoped_refptr<DeterministicSocketData> data(
2222 new DeterministicSocketData(reads, arraysize(reads),
[email protected]6c6ea172010-07-27 20:04:032223 writes, arraysize(writes)));
2224
2225 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2226 BoundNetLog(),
2227 GetParam());
[email protected]3b7828432010-08-18 18:33:272228 helper.SetDeterministic();
[email protected]6c6ea172010-07-27 20:04:032229 helper.RunPreTestSetup();
[email protected]3b7828432010-08-18 18:33:272230 helper.AddDeterministicData(data.get());
[email protected]6c6ea172010-07-27 20:04:032231 HttpNetworkTransaction* trans = helper.trans();
2232
2233 TestCompletionCallback callback;
2234
2235 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
2236 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]6c6ea172010-07-27 20:04:032237
[email protected]3b7828432010-08-18 18:33:272238 data->SetStop(2);
2239 data->Run();
2240 helper.ResetTrans();
2241 data->SetStop(20);
2242 data->Run();
2243
[email protected]6c6ea172010-07-27 20:04:032244 helper.VerifyDataConsumed();
2245}
2246
[email protected]3caf5542010-07-16 15:19:472247class SpdyNetworkTransactionTest::StartTransactionCallback
2248 : public CallbackRunner< Tuple1<int> > {
[email protected]b278eb72010-07-09 20:17:002249 public:
2250 explicit StartTransactionCallback(
[email protected]19ec8a72010-08-23 03:38:232251 const scoped_refptr<HttpNetworkSession>& session,
[email protected]3caf5542010-07-16 15:19:472252 NormalSpdyTransactionHelper& helper)
2253 : session_(session), helper_(helper) {}
[email protected]b278eb72010-07-09 20:17:002254
2255 // We try to start another transaction, which should succeed.
2256 virtual void RunWithParams(const Tuple1<int>& params) {
[email protected]3caf5542010-07-16 15:19:472257 scoped_ptr<HttpNetworkTransaction> trans(
2258 new HttpNetworkTransaction(session_));
[email protected]b278eb72010-07-09 20:17:002259 TestCompletionCallback callback;
2260 HttpRequestInfo request;
2261 request.method = "GET";
2262 request.url = GURL("http://www.google.com/");
2263 request.load_flags = 0;
2264 int rv = trans->Start(&request, &callback, BoundNetLog());
2265 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472266 rv = callback.WaitForResult();
[email protected]b278eb72010-07-09 20:17:002267 }
2268
2269 private:
[email protected]19ec8a72010-08-23 03:38:232270 const scoped_refptr<HttpNetworkSession>& session_;
[email protected]3caf5542010-07-16 15:19:472271 NormalSpdyTransactionHelper& helper_;
[email protected]b278eb72010-07-09 20:17:002272};
2273
2274// Verify that the client can correctly deal with the user callback attempting
2275// to start another transaction on a session that is closing down. See
2276// http://crbug.com/47455
[email protected]9e9e842e2010-07-23 23:09:152277TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
[email protected]2bd93022010-07-17 00:58:442278 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]b278eb72010-07-09 20:17:002279 MockWrite writes[] = { CreateMockWrite(*req) };
2280 MockWrite writes2[] = { CreateMockWrite(*req) };
2281
2282 // The indicated length of this packet is longer than its actual length. When
2283 // the session receives an empty packet after this one, it shuts down the
2284 // session, and calls the read callback with the incomplete data.
2285 const uint8 kGetBodyFrame2[] = {
2286 0x00, 0x00, 0x00, 0x01,
2287 0x01, 0x00, 0x00, 0x07,
2288 'h', 'e', 'l', 'l', 'o', '!',
2289 };
2290
[email protected]2bd93022010-07-17 00:58:442291 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]b278eb72010-07-09 20:17:002292 MockRead reads[] = {
2293 CreateMockRead(*resp, 2),
2294 MockRead(true, ERR_IO_PENDING, 3), // Force a pause
2295 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame2),
2296 arraysize(kGetBodyFrame2), 4),
[email protected]3caf5542010-07-16 15:19:472297 MockRead(true, ERR_IO_PENDING, 5), // Force a pause
2298 MockRead(true, 0, 0, 6), // EOF
[email protected]b278eb72010-07-09 20:17:002299 };
2300 MockRead reads2[] = {
2301 CreateMockRead(*resp, 2),
2302 MockRead(true, 0, 0, 3), // EOF
2303 };
2304
[email protected]b278eb72010-07-09 20:17:002305 scoped_refptr<OrderedSocketData> data(
2306 new OrderedSocketData(reads, arraysize(reads),
2307 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:472308 scoped_refptr<DelayedSocketData> data2(
[email protected]8e6441ca2010-08-19 05:56:382309 new DelayedSocketData(1, reads2, arraysize(reads2),
[email protected]b278eb72010-07-09 20:17:002310 writes2, arraysize(writes2)));
[email protected]3caf5542010-07-16 15:19:472311
2312 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152313 BoundNetLog(), GetParam());
[email protected]e3ebba0f2010-08-05 17:59:582314 helper.RunPreTestSetup();
[email protected]3caf5542010-07-16 15:19:472315 helper.AddData(data.get());
2316 helper.AddData(data2.get());
[email protected]3caf5542010-07-16 15:19:472317 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002318
2319 // Start the transaction with basic parameters.
2320 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:472321 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]b278eb72010-07-09 20:17:002322 EXPECT_EQ(ERR_IO_PENDING, rv);
2323 rv = callback.WaitForResult();
2324
[email protected]3caf5542010-07-16 15:19:472325 StartTransactionCallback callback2(helper.session(), helper);
[email protected]b278eb72010-07-09 20:17:002326 const int kSize = 3000;
[email protected]ad8e04a2010-11-01 04:16:272327 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
[email protected]b278eb72010-07-09 20:17:002328 rv = trans->Read(buf, kSize, &callback2);
[email protected]3caf5542010-07-16 15:19:472329 // This forces an err_IO_pending, which sets the callback.
[email protected]b278eb72010-07-09 20:17:002330 data->CompleteRead();
[email protected]3caf5542010-07-16 15:19:472331 // This finishes the read.
2332 data->CompleteRead();
2333 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002334}
2335
[email protected]3caf5542010-07-16 15:19:472336class SpdyNetworkTransactionTest::DeleteSessionCallback
2337 : public CallbackRunner< Tuple1<int> > {
[email protected]9be804c82010-06-24 17:59:462338 public:
[email protected]3caf5542010-07-16 15:19:472339 explicit DeleteSessionCallback(NormalSpdyTransactionHelper& helper) :
2340 helper_(helper) {}
[email protected]9be804c82010-06-24 17:59:462341
[email protected]b278eb72010-07-09 20:17:002342 // We kill the transaction, which deletes the session and stream.
[email protected]9be804c82010-06-24 17:59:462343 virtual void RunWithParams(const Tuple1<int>& params) {
[email protected]3caf5542010-07-16 15:19:472344 helper_.ResetTrans();
[email protected]9be804c82010-06-24 17:59:462345 }
2346
2347 private:
[email protected]3caf5542010-07-16 15:19:472348 NormalSpdyTransactionHelper& helper_;
[email protected]9be804c82010-06-24 17:59:462349};
2350
2351// Verify that the client can correctly deal with the user callback deleting the
2352// transaction. Failures will usually be valgrind errors. See
2353// http://crbug.com/46925
[email protected]9e9e842e2010-07-23 23:09:152354TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
[email protected]2bd93022010-07-17 00:58:442355 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:132356 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]9be804c82010-06-24 17:59:462357
[email protected]2bd93022010-07-17 00:58:442358 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2359 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462360 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132361 CreateMockRead(*resp.get(), 2),
[email protected]9be804c82010-06-24 17:59:462362 MockRead(true, ERR_IO_PENDING, 3), // Force a pause
[email protected]e7f75092010-07-01 22:39:132363 CreateMockRead(*body.get(), 4),
[email protected]9be804c82010-06-24 17:59:462364 MockRead(true, 0, 0, 5), // EOF
2365 };
2366
[email protected]9be804c82010-06-24 17:59:462367 scoped_refptr<OrderedSocketData> data(
2368 new OrderedSocketData(reads, arraysize(reads),
2369 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:472370
2371 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152372 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:472373 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:582374 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:472375 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462376
2377 // Start the transaction with basic parameters.
2378 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:472379 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]9be804c82010-06-24 17:59:462380 EXPECT_EQ(ERR_IO_PENDING, rv);
2381 rv = callback.WaitForResult();
2382
2383 // Setup a user callback which will delete the session, and clear out the
2384 // memory holding the stream object. Note that the callback deletes trans.
[email protected]3caf5542010-07-16 15:19:472385 DeleteSessionCallback callback2(helper);
[email protected]9be804c82010-06-24 17:59:462386 const int kSize = 3000;
[email protected]ad8e04a2010-11-01 04:16:272387 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
[email protected]9be804c82010-06-24 17:59:462388 rv = trans->Read(buf, kSize, &callback2);
2389 ASSERT_EQ(ERR_IO_PENDING, rv);
2390 data->CompleteRead();
2391
2392 // Finish running rest of tasks.
2393 MessageLoop::current()->RunAllPending();
[email protected]3caf5542010-07-16 15:19:472394 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462395}
2396
[email protected]e3ebba0f2010-08-05 17:59:582397// Send a spdy request to www.google.com that gets redirected to www.foo.com.
2398TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
[email protected]6981d9632010-11-30 21:34:022399 // These are headers which the net::URLRequest tacks on.
[email protected]e3ebba0f2010-08-05 17:59:582400 const char* const kExtraHeaders[] = {
2401 "accept-charset",
2402 "",
2403 "accept-encoding",
2404 "gzip,deflate",
2405 "accept-language",
2406 "",
2407 };
2408 const SpdyHeaderInfo kSynStartHeader = make_spdy_header(spdy::SYN_STREAM);
2409 const char* const kStandardGetHeaders[] = {
2410 "host",
2411 "www.google.com",
2412 "method",
2413 "GET",
2414 "scheme",
2415 "http",
2416 "url",
2417 "/",
2418 "user-agent",
2419 "",
2420 "version",
2421 "HTTP/1.1"
2422 };
2423 const char* const kStandardGetHeaders2[] = {
2424 "host",
2425 "www.foo.com",
2426 "method",
2427 "GET",
2428 "scheme",
2429 "http",
2430 "url",
2431 "/index.php",
2432 "user-agent",
2433 "",
2434 "version",
2435 "HTTP/1.1"
2436 };
2437
2438 // Setup writes/reads to www.google.com
2439 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(
[email protected]d08358502010-12-03 22:04:032440 kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2,
2441 kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
[email protected]e3ebba0f2010-08-05 17:59:582442 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyPacket(
[email protected]d08358502010-12-03 22:04:032443 kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2,
2444 kStandardGetHeaders2, arraysize(kStandardGetHeaders2) / 2));
[email protected]e3ebba0f2010-08-05 17:59:582445 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReplyRedirect(1));
2446 MockWrite writes[] = {
2447 CreateMockWrite(*req, 1),
2448 };
2449 MockRead reads[] = {
2450 CreateMockRead(*resp, 2),
2451 MockRead(true, 0, 0, 3) // EOF
2452 };
2453
2454 // Setup writes/reads to www.foo.com
2455 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
2456 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
2457 MockWrite writes2[] = {
2458 CreateMockWrite(*req2, 1),
2459 };
2460 MockRead reads2[] = {
2461 CreateMockRead(*resp2, 2),
2462 CreateMockRead(*body2, 3),
2463 MockRead(true, 0, 0, 4) // EOF
2464 };
2465 scoped_refptr<OrderedSocketData> data(
2466 new OrderedSocketData(reads, arraysize(reads),
2467 writes, arraysize(writes)));
2468 scoped_refptr<OrderedSocketData> data2(
2469 new OrderedSocketData(reads2, arraysize(reads2),
2470 writes2, arraysize(writes2)));
2471
2472 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]8e6441ca2010-08-19 05:56:382473 HttpStreamFactory::set_force_spdy_over_ssl(false);
2474 HttpStreamFactory::set_force_spdy_always(true);
[email protected]e3ebba0f2010-08-05 17:59:582475 TestDelegate d;
2476 {
[email protected]6981d9632010-11-30 21:34:022477 net::URLRequest r(GURL("http://www.google.com/"), &d);
[email protected]e3ebba0f2010-08-05 17:59:582478 SpdyURLRequestContext* spdy_url_request_context =
2479 new SpdyURLRequestContext();
2480 r.set_context(spdy_url_request_context);
2481 spdy_url_request_context->socket_factory().
2482 AddSocketDataProvider(data.get());
2483 spdy_url_request_context->socket_factory().
2484 AddSocketDataProvider(data2.get());
2485
2486 d.set_quit_on_redirect(true);
2487 r.Start();
2488 MessageLoop::current()->Run();
2489
2490 EXPECT_EQ(1, d.received_redirect_count());
2491
2492 r.FollowDeferredRedirect();
2493 MessageLoop::current()->Run();
2494 EXPECT_EQ(1, d.response_started_count());
2495 EXPECT_FALSE(d.received_data_before_response());
[email protected]f90bf0d92011-01-13 02:12:442496 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
[email protected]e3ebba0f2010-08-05 17:59:582497 std::string contents("hello!");
2498 EXPECT_EQ(contents, d.data_received());
2499 }
2500 EXPECT_TRUE(data->at_read_eof());
2501 EXPECT_TRUE(data->at_write_eof());
2502 EXPECT_TRUE(data2->at_read_eof());
2503 EXPECT_TRUE(data2->at_write_eof());
2504}
2505
2506// Send a spdy request to www.google.com. Get a pushed stream that redirects to
2507// www.foo.com.
2508TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
[email protected]6981d9632010-11-30 21:34:022509 // These are headers which the net::URLRequest tacks on.
[email protected]e3ebba0f2010-08-05 17:59:582510 const char* const kExtraHeaders[] = {
2511 "accept-charset",
2512 "",
2513 "accept-encoding",
2514 "gzip,deflate",
2515 "accept-language",
2516 "",
2517 };
2518 const SpdyHeaderInfo kSynStartHeader = make_spdy_header(spdy::SYN_STREAM);
2519 const char* const kStandardGetHeaders[] = {
2520 "host",
2521 "www.google.com",
2522 "method",
2523 "GET",
2524 "scheme",
2525 "http",
2526 "url",
2527 "/",
2528 "user-agent",
2529 "",
2530 "version",
2531 "HTTP/1.1"
2532 };
2533 const char* const kStandardGetHeaders2[] = {
2534 "host",
2535 "www.foo.com",
2536 "method",
2537 "GET",
2538 "scheme",
2539 "http",
2540 "url",
2541 "/index.php",
2542 "user-agent",
2543 "",
2544 "version",
2545 "HTTP/1.1"
2546 };
2547
2548 // Setup writes/reads to www.google.com
[email protected]d08358502010-12-03 22:04:032549 scoped_ptr<spdy::SpdyFrame> req(
2550 ConstructSpdyPacket(kSynStartHeader,
2551 kExtraHeaders,
2552 arraysize(kExtraHeaders) / 2,
2553 kStandardGetHeaders,
2554 arraysize(kStandardGetHeaders) / 2));
2555 scoped_ptr<spdy::SpdyFrame> req2(
2556 ConstructSpdyPacket(kSynStartHeader,
2557 kExtraHeaders,
2558 arraysize(kExtraHeaders) / 2,
2559 kStandardGetHeaders2,
2560 arraysize(kStandardGetHeaders2) / 2));
[email protected]e3ebba0f2010-08-05 17:59:582561 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]d08358502010-12-03 22:04:032562 scoped_ptr<spdy::SpdyFrame> rep(
2563 ConstructSpdyPush(NULL,
2564 0,
2565 2,
2566 1,
2567 "http://www.google.com/foo.dat",
2568 "301 Moved Permanently",
2569 "http://www.foo.com/index.php"));
[email protected]e3ebba0f2010-08-05 17:59:582570 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582571 MockWrite writes[] = {
2572 CreateMockWrite(*req, 1),
[email protected]e3ebba0f2010-08-05 17:59:582573 };
2574 MockRead reads[] = {
2575 CreateMockRead(*resp, 2),
2576 CreateMockRead(*rep, 3),
2577 CreateMockRead(*body, 4),
2578 MockRead(true, ERR_IO_PENDING, 5), // Force a pause
[email protected]0b0bf032010-09-21 18:08:502579 MockRead(true, 0, 0, 6) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582580 };
2581
2582 // Setup writes/reads to www.foo.com
2583 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
2584 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
2585 MockWrite writes2[] = {
2586 CreateMockWrite(*req2, 1),
2587 };
2588 MockRead reads2[] = {
2589 CreateMockRead(*resp2, 2),
2590 CreateMockRead(*body2, 3),
2591 MockRead(true, 0, 0, 5) // EOF
2592 };
2593 scoped_refptr<OrderedSocketData> data(
2594 new OrderedSocketData(reads, arraysize(reads),
2595 writes, arraysize(writes)));
2596 scoped_refptr<OrderedSocketData> data2(
2597 new OrderedSocketData(reads2, arraysize(reads2),
2598 writes2, arraysize(writes2)));
2599
2600 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]8e6441ca2010-08-19 05:56:382601 HttpStreamFactory::set_force_spdy_over_ssl(false);
2602 HttpStreamFactory::set_force_spdy_always(true);
[email protected]e3ebba0f2010-08-05 17:59:582603 TestDelegate d;
2604 TestDelegate d2;
[email protected]2431756e2010-09-29 20:26:132605 scoped_refptr<SpdyURLRequestContext> spdy_url_request_context(
2606 new SpdyURLRequestContext());
[email protected]e3ebba0f2010-08-05 17:59:582607 {
[email protected]6981d9632010-11-30 21:34:022608 net::URLRequest r(GURL("http://www.google.com/"), &d);
[email protected]e3ebba0f2010-08-05 17:59:582609 r.set_context(spdy_url_request_context);
2610 spdy_url_request_context->socket_factory().
2611 AddSocketDataProvider(data.get());
2612
2613 r.Start();
2614 MessageLoop::current()->Run();
2615
2616 EXPECT_EQ(0, d.received_redirect_count());
2617 std::string contents("hello!");
2618 EXPECT_EQ(contents, d.data_received());
2619
[email protected]6981d9632010-11-30 21:34:022620 net::URLRequest r2(GURL("http://www.google.com/foo.dat"), &d2);
[email protected]e3ebba0f2010-08-05 17:59:582621 r2.set_context(spdy_url_request_context);
2622 spdy_url_request_context->socket_factory().
2623 AddSocketDataProvider(data2.get());
2624
2625 d2.set_quit_on_redirect(true);
2626 r2.Start();
2627 MessageLoop::current()->Run();
2628 EXPECT_EQ(1, d2.received_redirect_count());
2629
2630 r2.FollowDeferredRedirect();
2631 MessageLoop::current()->Run();
2632 EXPECT_EQ(1, d2.response_started_count());
2633 EXPECT_FALSE(d2.received_data_before_response());
[email protected]f90bf0d92011-01-13 02:12:442634 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status());
[email protected]e3ebba0f2010-08-05 17:59:582635 std::string contents2("hello!");
2636 EXPECT_EQ(contents2, d2.data_received());
2637 }
2638 data->CompleteRead();
2639 data2->CompleteRead();
2640 EXPECT_TRUE(data->at_read_eof());
2641 EXPECT_TRUE(data->at_write_eof());
2642 EXPECT_TRUE(data2->at_read_eof());
2643 EXPECT_TRUE(data2->at_write_eof());
2644}
2645
2646TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2647 static const unsigned char kPushBodyFrame[] = {
2648 0x00, 0x00, 0x00, 0x02, // header, ID
[email protected]19ec8a72010-08-23 03:38:232649 0x01, 0x00, 0x00, 0x06, // FIN, length
2650 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
[email protected]e3ebba0f2010-08-05 17:59:582651 };
[email protected]19ec8a72010-08-23 03:38:232652 scoped_ptr<spdy::SpdyFrame>
2653 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2654 scoped_ptr<spdy::SpdyFrame>
2655 stream1_body(ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582656 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:232657 CreateMockWrite(*stream1_syn, 1),
[email protected]e3ebba0f2010-08-05 17:59:582658 };
2659
[email protected]19ec8a72010-08-23 03:38:232660 scoped_ptr<spdy::SpdyFrame>
2661 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2662 scoped_ptr<spdy::SpdyFrame>
[email protected]d08358502010-12-03 22:04:032663 stream2_syn(ConstructSpdyPush(NULL,
2664 0,
2665 2,
2666 1,
2667 "http://www.google.com/foo.dat"));
[email protected]e3ebba0f2010-08-05 17:59:582668 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:232669 CreateMockRead(*stream1_reply, 2),
2670 CreateMockRead(*stream2_syn, 3),
2671 CreateMockRead(*stream1_body, 4, false),
[email protected]e3ebba0f2010-08-05 17:59:582672 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
[email protected]19ec8a72010-08-23 03:38:232673 arraysize(kPushBodyFrame), 5),
[email protected]e3ebba0f2010-08-05 17:59:582674 MockRead(true, ERR_IO_PENDING, 6), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582675 };
2676
2677 HttpResponseInfo response;
2678 HttpResponseInfo response2;
[email protected]19ec8a72010-08-23 03:38:232679 std::string expected_push_result("pushed");
[email protected]d08358502010-12-03 22:04:032680 scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2681 reads,
2682 arraysize(reads),
2683 writes,
2684 arraysize(writes)));
2685 RunServerPushTest(data.get(),
2686 &response,
2687 &response2,
2688 expected_push_result);
[email protected]e3ebba0f2010-08-05 17:59:582689
2690 // Verify the SYN_REPLY.
2691 EXPECT_TRUE(response.headers != NULL);
2692 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2693
2694 // Verify the pushed stream.
2695 EXPECT_TRUE(response2.headers != NULL);
2696 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2697}
2698
[email protected]82918cc2010-08-25 17:24:502699TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2700 static const unsigned char kPushBodyFrame[] = {
2701 0x00, 0x00, 0x00, 0x02, // header, ID
2702 0x01, 0x00, 0x00, 0x06, // FIN, length
2703 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2704 };
2705 scoped_ptr<spdy::SpdyFrame>
2706 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2707 MockWrite writes[] = {
2708 CreateMockWrite(*stream1_syn, 1),
2709 };
2710
2711 scoped_ptr<spdy::SpdyFrame>
2712 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2713 scoped_ptr<spdy::SpdyFrame>
[email protected]d08358502010-12-03 22:04:032714 stream2_syn(ConstructSpdyPush(NULL,
2715 0,
2716 2,
2717 1,
2718 "http://www.google.com/foo.dat"));
[email protected]82918cc2010-08-25 17:24:502719 scoped_ptr<spdy::SpdyFrame>
2720 stream1_body(ConstructSpdyBodyFrame(1, true));
2721 MockRead reads[] = {
2722 CreateMockRead(*stream1_reply, 2),
2723 CreateMockRead(*stream2_syn, 3),
2724 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
2725 arraysize(kPushBodyFrame), 5),
2726 CreateMockRead(*stream1_body, 4, false),
2727 MockRead(true, ERR_IO_PENDING, 6), // Force a pause
2728 };
2729
2730 HttpResponseInfo response;
2731 HttpResponseInfo response2;
2732 std::string expected_push_result("pushed");
[email protected]d08358502010-12-03 22:04:032733 scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2734 reads,
2735 arraysize(reads),
2736 writes,
2737 arraysize(writes)));
2738 RunServerPushTest(data.get(),
2739 &response,
2740 &response2,
2741 expected_push_result);
[email protected]82918cc2010-08-25 17:24:502742
2743 // Verify the SYN_REPLY.
2744 EXPECT_TRUE(response.headers != NULL);
2745 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2746
2747 // Verify the pushed stream.
2748 EXPECT_TRUE(response2.headers != NULL);
2749 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2750}
2751
[email protected]19ec8a72010-08-23 03:38:232752TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2753 scoped_ptr<spdy::SpdyFrame>
2754 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2755 scoped_ptr<spdy::SpdyFrame>
2756 stream1_body(ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582757 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:232758 CreateMockWrite(*stream1_syn, 1),
[email protected]e3ebba0f2010-08-05 17:59:582759 };
2760
[email protected]19ec8a72010-08-23 03:38:232761 scoped_ptr<spdy::SpdyFrame>
2762 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2763 scoped_ptr<spdy::SpdyFrame>
[email protected]d08358502010-12-03 22:04:032764 stream2_syn(ConstructSpdyPush(NULL,
2765 0,
2766 2,
2767 1,
2768 "http://www.google.com/foo.dat"));
[email protected]19ec8a72010-08-23 03:38:232769 scoped_ptr<spdy::SpdyFrame>
2770 stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582771 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:232772 CreateMockRead(*stream1_reply, 2),
2773 CreateMockRead(*stream2_syn, 3),
2774 CreateMockRead(*stream2_rst, 4),
2775 CreateMockRead(*stream1_body, 5, false),
2776 MockRead(true, ERR_IO_PENDING, 6), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582777 };
2778
2779 scoped_refptr<OrderedSocketData> data(
2780 new OrderedSocketData(reads, arraysize(reads),
2781 writes, arraysize(writes)));
2782 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2783 BoundNetLog(), GetParam());
2784
2785 helper.RunPreTestSetup();
2786 helper.AddData(data.get());
2787
2788 HttpNetworkTransaction* trans = helper.trans();
2789
2790 // Start the transaction with basic parameters.
2791 TestCompletionCallback callback;
2792 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
2793 EXPECT_EQ(ERR_IO_PENDING, rv);
2794 rv = callback.WaitForResult();
[email protected]19ec8a72010-08-23 03:38:232795 EXPECT_EQ(OK, rv);
2796
2797 // Verify that we consumed all test data.
2798 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
2799 << data->read_count()
2800 << " Read index: "
2801 << data->read_index();
2802 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
2803 << data->write_count()
2804 << " Write index: "
2805 << data->write_index();
2806
2807 // Verify the SYN_REPLY.
2808 HttpResponseInfo response = *trans->GetResponseInfo();
2809 EXPECT_TRUE(response.headers != NULL);
2810 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2811}
2812
[email protected]fdc165a2010-09-03 03:51:292813TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2814 // Verify that we don't leak streams and that we properly send a reset
2815 // if the server pushes the same stream twice.
2816 static const unsigned char kPushBodyFrame[] = {
2817 0x00, 0x00, 0x00, 0x02, // header, ID
2818 0x01, 0x00, 0x00, 0x06, // FIN, length
2819 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2820 };
2821
2822 scoped_ptr<spdy::SpdyFrame>
2823 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2824 scoped_ptr<spdy::SpdyFrame>
2825 stream1_body(ConstructSpdyBodyFrame(1, true));
2826 scoped_ptr<spdy::SpdyFrame>
2827 stream3_rst(ConstructSpdyRstStream(4, spdy::PROTOCOL_ERROR));
2828 MockWrite writes[] = {
2829 CreateMockWrite(*stream1_syn, 1),
2830 CreateMockWrite(*stream3_rst, 5),
2831 };
2832
2833 scoped_ptr<spdy::SpdyFrame>
2834 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2835 scoped_ptr<spdy::SpdyFrame>
[email protected]d08358502010-12-03 22:04:032836 stream2_syn(ConstructSpdyPush(NULL,
2837 0,
2838 2,
2839 1,
2840 "http://www.google.com/foo.dat"));
[email protected]fdc165a2010-09-03 03:51:292841 scoped_ptr<spdy::SpdyFrame>
[email protected]d08358502010-12-03 22:04:032842 stream3_syn(ConstructSpdyPush(NULL,
2843 0,
2844 4,
2845 1,
2846 "http://www.google.com/foo.dat"));
[email protected]fdc165a2010-09-03 03:51:292847 MockRead reads[] = {
2848 CreateMockRead(*stream1_reply, 2),
2849 CreateMockRead(*stream2_syn, 3),
2850 CreateMockRead(*stream3_syn, 4),
2851 CreateMockRead(*stream1_body, 6, false),
2852 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
2853 arraysize(kPushBodyFrame), 7),
2854 MockRead(true, ERR_IO_PENDING, 8), // Force a pause
2855 };
2856
2857 HttpResponseInfo response;
2858 HttpResponseInfo response2;
2859 std::string expected_push_result("pushed");
[email protected]d08358502010-12-03 22:04:032860 scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2861 reads,
2862 arraysize(reads),
2863 writes,
2864 arraysize(writes)));
2865 RunServerPushTest(data.get(),
2866 &response,
2867 &response2,
2868 expected_push_result);
[email protected]fdc165a2010-09-03 03:51:292869
2870 // Verify the SYN_REPLY.
2871 EXPECT_TRUE(response.headers != NULL);
2872 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2873
2874 // Verify the pushed stream.
2875 EXPECT_TRUE(response2.headers != NULL);
2876 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2877}
2878
[email protected]19ec8a72010-08-23 03:38:232879TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2880 static const unsigned char kPushBodyFrame1[] = {
2881 0x00, 0x00, 0x00, 0x02, // header, ID
2882 0x01, 0x00, 0x00, 0x1F, // FIN, length
2883 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2884 };
2885 static const char kPushBodyFrame2[] = " my darling";
2886 static const char kPushBodyFrame3[] = " hello";
2887 static const char kPushBodyFrame4[] = " my baby";
2888
2889 scoped_ptr<spdy::SpdyFrame>
2890 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2891 scoped_ptr<spdy::SpdyFrame>
2892 stream1_body(ConstructSpdyBodyFrame(1, true));
2893 MockWrite writes[] = {
2894 CreateMockWrite(*stream1_syn, 1),
2895 };
2896
2897 scoped_ptr<spdy::SpdyFrame>
2898 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2899 scoped_ptr<spdy::SpdyFrame>
[email protected]d08358502010-12-03 22:04:032900 stream2_syn(ConstructSpdyPush(NULL,
2901 0,
2902 2,
2903 1,
2904 "http://www.google.com/foo.dat"));
[email protected]19ec8a72010-08-23 03:38:232905 MockRead reads[] = {
2906 CreateMockRead(*stream1_reply, 2),
2907 CreateMockRead(*stream2_syn, 3),
2908 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame1),
2909 arraysize(kPushBodyFrame1), 4),
2910 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame2),
2911 arraysize(kPushBodyFrame2) - 1, 5),
2912 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame3),
2913 arraysize(kPushBodyFrame3) - 1, 6),
2914 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame4),
2915 arraysize(kPushBodyFrame4) - 1, 7),
2916 CreateMockRead(*stream1_body, 8, false),
2917 MockRead(true, ERR_IO_PENDING, 9), // Force a pause
2918 };
2919
2920 HttpResponseInfo response;
2921 HttpResponseInfo response2;
2922 std::string expected_push_result("pushed my darling hello my baby");
[email protected]d08358502010-12-03 22:04:032923 scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2924 reads,
2925 arraysize(reads),
2926 writes,
2927 arraysize(writes)));
2928 RunServerPushTest(data.get(),
2929 &response,
2930 &response2,
2931 expected_push_result);
[email protected]19ec8a72010-08-23 03:38:232932
2933 // Verify the SYN_REPLY.
2934 EXPECT_TRUE(response.headers != NULL);
2935 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2936
2937 // Verify the pushed stream.
2938 EXPECT_TRUE(response2.headers != NULL);
2939 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2940}
2941
2942TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2943 static const unsigned char kPushBodyFrame1[] = {
2944 0x00, 0x00, 0x00, 0x02, // header, ID
2945 0x01, 0x00, 0x00, 0x1F, // FIN, length
2946 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2947 };
2948 static const char kPushBodyFrame2[] = " my darling";
2949 static const char kPushBodyFrame3[] = " hello";
2950 static const char kPushBodyFrame4[] = " my baby";
2951
2952 scoped_ptr<spdy::SpdyFrame>
2953 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2954 scoped_ptr<spdy::SpdyFrame>
2955 stream1_body(ConstructSpdyBodyFrame(1, true));
2956 MockWrite writes[] = {
2957 CreateMockWrite(*stream1_syn, 1),
2958 };
2959
2960 scoped_ptr<spdy::SpdyFrame>
2961 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2962 scoped_ptr<spdy::SpdyFrame>
[email protected]d08358502010-12-03 22:04:032963 stream2_syn(ConstructSpdyPush(NULL,
2964 0,
2965 2,
2966 1,
2967 "http://www.google.com/foo.dat"));
[email protected]19ec8a72010-08-23 03:38:232968 MockRead reads[] = {
2969 CreateMockRead(*stream1_reply, 2),
2970 CreateMockRead(*stream2_syn, 3),
2971 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame1),
2972 arraysize(kPushBodyFrame1), 4),
2973 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame2),
2974 arraysize(kPushBodyFrame2) - 1, 5),
2975 MockRead(true, ERR_IO_PENDING, 6), // Force a pause
2976 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame3),
2977 arraysize(kPushBodyFrame3) - 1, 7),
2978 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame4),
2979 arraysize(kPushBodyFrame4) - 1, 8),
2980 CreateMockRead(*stream1_body.get(), 9, false),
2981 MockRead(true, ERR_IO_PENDING, 10) // Force a pause.
2982 };
2983
2984 HttpResponseInfo response;
2985 HttpResponseInfo response2;
2986 std::string expected_push_result("pushed my darling hello my baby");
[email protected]d08358502010-12-03 22:04:032987 scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2988 reads,
2989 arraysize(reads),
2990 writes,
2991 arraysize(writes)));
2992 RunServerPushTest(data.get(),
2993 &response,
2994 &response2,
2995 expected_push_result);
[email protected]19ec8a72010-08-23 03:38:232996
2997 // Verify the SYN_REPLY.
2998 EXPECT_TRUE(response.headers != NULL);
2999 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3000
3001 // Verify the pushed stream.
3002 EXPECT_TRUE(response2.headers != NULL);
3003 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3004}
3005
3006TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
3007 scoped_ptr<spdy::SpdyFrame>
3008 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3009 scoped_ptr<spdy::SpdyFrame>
3010 stream1_body(ConstructSpdyBodyFrame(1, true));
3011 scoped_ptr<spdy::SpdyFrame>
3012 stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_STREAM));
3013 MockWrite writes[] = {
3014 CreateMockWrite(*stream1_syn, 1),
3015 CreateMockWrite(*stream2_rst, 4),
3016 };
3017
3018 scoped_ptr<spdy::SpdyFrame>
3019 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3020 scoped_ptr<spdy::SpdyFrame>
[email protected]d08358502010-12-03 22:04:033021 stream2_syn(ConstructSpdyPush(NULL,
3022 0,
3023 2,
3024 0,
3025 "http://www.google.com/foo.dat"));
[email protected]19ec8a72010-08-23 03:38:233026 MockRead reads[] = {
3027 CreateMockRead(*stream1_reply, 2),
3028 CreateMockRead(*stream2_syn, 3),
3029 CreateMockRead(*stream1_body, 4),
3030 MockRead(true, ERR_IO_PENDING, 5) // Force a pause
3031 };
3032
3033 scoped_refptr<OrderedSocketData> data(
3034 new OrderedSocketData(reads, arraysize(reads),
3035 writes, arraysize(writes)));
3036 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3037 BoundNetLog(), GetParam());
3038
3039 helper.RunPreTestSetup();
3040 helper.AddData(data.get());
3041
3042 HttpNetworkTransaction* trans = helper.trans();
3043
3044 // Start the transaction with basic parameters.
3045 TestCompletionCallback callback;
3046 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3047 EXPECT_EQ(ERR_IO_PENDING, rv);
3048 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583049 EXPECT_EQ(OK, rv);
3050
3051 // Verify that we consumed all test data.
3052 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
3053 << data->read_count()
3054 << " Read index: "
3055 << data->read_index();
3056 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
3057 << data->write_count()
3058 << " Write index: "
3059 << data->write_index();
3060
3061 // Verify the SYN_REPLY.
3062 HttpResponseInfo response = *trans->GetResponseInfo();
3063 EXPECT_TRUE(response.headers != NULL);
3064 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3065}
3066
3067TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
[email protected]19ec8a72010-08-23 03:38:233068 scoped_ptr<spdy::SpdyFrame>
3069 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3070 scoped_ptr<spdy::SpdyFrame>
3071 stream1_body(ConstructSpdyBodyFrame(1, true));
3072 scoped_ptr<spdy::SpdyFrame>
3073 stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_ASSOCIATED_STREAM));
[email protected]e3ebba0f2010-08-05 17:59:583074 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:233075 CreateMockWrite(*stream1_syn, 1),
3076 CreateMockWrite(*stream2_rst, 4),
[email protected]e3ebba0f2010-08-05 17:59:583077 };
3078
[email protected]19ec8a72010-08-23 03:38:233079 scoped_ptr<spdy::SpdyFrame>
3080 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3081 scoped_ptr<spdy::SpdyFrame>
[email protected]d08358502010-12-03 22:04:033082 stream2_syn(ConstructSpdyPush(NULL,
3083 0,
3084 2,
3085 9,
3086 "http://www.google.com/foo.dat"));
[email protected]e3ebba0f2010-08-05 17:59:583087 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:233088 CreateMockRead(*stream1_reply, 2),
3089 CreateMockRead(*stream2_syn, 3),
3090 CreateMockRead(*stream1_body, 4),
3091 MockRead(true, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:583092 };
3093
3094 scoped_refptr<OrderedSocketData> data(
3095 new OrderedSocketData(reads, arraysize(reads),
3096 writes, arraysize(writes)));
3097 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3098 BoundNetLog(), GetParam());
3099
3100 helper.RunPreTestSetup();
3101 helper.AddData(data.get());
3102
3103 HttpNetworkTransaction* trans = helper.trans();
3104
3105 // Start the transaction with basic parameters.
3106 TestCompletionCallback callback;
3107 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3108 EXPECT_EQ(ERR_IO_PENDING, rv);
3109 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583110 EXPECT_EQ(OK, rv);
3111
3112 // Verify that we consumed all test data.
3113 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
3114 << data->read_count()
3115 << " Read index: "
3116 << data->read_index();
3117 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
3118 << data->write_count()
3119 << " Write index: "
3120 << data->write_index();
3121
3122 // Verify the SYN_REPLY.
3123 HttpResponseInfo response = *trans->GetResponseInfo();
3124 EXPECT_TRUE(response.headers != NULL);
3125 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3126}
3127
3128TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
[email protected]19ec8a72010-08-23 03:38:233129 scoped_ptr<spdy::SpdyFrame>
3130 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3131 scoped_ptr<spdy::SpdyFrame>
3132 stream1_body(ConstructSpdyBodyFrame(1, true));
3133 scoped_ptr<spdy::SpdyFrame>
3134 stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:583135 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:233136 CreateMockWrite(*stream1_syn, 1),
3137 CreateMockWrite(*stream2_rst, 4),
[email protected]e3ebba0f2010-08-05 17:59:583138 };
3139
[email protected]19ec8a72010-08-23 03:38:233140 scoped_ptr<spdy::SpdyFrame>
3141 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3142 scoped_ptr<spdy::SpdyFrame>
3143 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1));
[email protected]e3ebba0f2010-08-05 17:59:583144 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:233145 CreateMockRead(*stream1_reply, 2),
3146 CreateMockRead(*stream2_syn, 3),
3147 CreateMockRead(*stream1_body, 4),
3148 MockRead(true, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:583149 };
3150
3151 scoped_refptr<OrderedSocketData> data(
3152 new OrderedSocketData(reads, arraysize(reads),
3153 writes, arraysize(writes)));
3154 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3155 BoundNetLog(), GetParam());
3156
3157 helper.RunPreTestSetup();
3158 helper.AddData(data.get());
3159
3160 HttpNetworkTransaction* trans = helper.trans();
3161
3162 // Start the transaction with basic parameters.
3163 TestCompletionCallback callback;
3164 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3165 EXPECT_EQ(ERR_IO_PENDING, rv);
3166 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583167 EXPECT_EQ(OK, rv);
3168 // Verify that we consumed all test data.
3169 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
3170 << data->read_count()
3171 << " Read index: "
3172 << data->read_index();
3173 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
3174 << data->write_count()
3175 << " Write index: "
3176 << data->write_index();
3177
3178 // Verify the SYN_REPLY.
3179 HttpResponseInfo response = *trans->GetResponseInfo();
3180 EXPECT_TRUE(response.headers != NULL);
3181 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3182}
3183
[email protected]8b070372009-11-16 22:01:253184// Verify that various SynReply headers parse correctly through the
3185// HTTP layer.
[email protected]9e9e842e2010-07-23 23:09:153186TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
[email protected]e7f75092010-07-01 22:39:133187 struct SynReplyHeadersTests {
3188 int num_headers;
3189 const char* extra_headers[5];
[email protected]8b070372009-11-16 22:01:253190 const char* expected_headers;
3191 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133192 // This uses a multi-valued cookie header.
3193 { 2,
3194 { "cookie", "val1",
3195 "cookie", "val2", // will get appended separated by NULL
3196 NULL
3197 },
[email protected]8b070372009-11-16 22:01:253198 "cookie: val1\n"
3199 "cookie: val2\n"
[email protected]e7f75092010-07-01 22:39:133200 "hello: bye\n"
[email protected]8b070372009-11-16 22:01:253201 "status: 200\n"
[email protected]8b070372009-11-16 22:01:253202 "version: HTTP/1.1\n"
3203 },
[email protected]e7f75092010-07-01 22:39:133204 // This is the minimalist set of headers.
3205 { 0,
3206 { NULL },
3207 "hello: bye\n"
[email protected]8b070372009-11-16 22:01:253208 "status: 200\n"
[email protected]8b070372009-11-16 22:01:253209 "version: HTTP/1.1\n"
3210 },
[email protected]e7f75092010-07-01 22:39:133211 // Headers with a comma separated list.
3212 { 1,
3213 { "cookie", "val1,val2",
3214 NULL
3215 },
[email protected]8b070372009-11-16 22:01:253216 "cookie: val1,val2\n"
[email protected]e7f75092010-07-01 22:39:133217 "hello: bye\n"
[email protected]8b070372009-11-16 22:01:253218 "status: 200\n"
[email protected]8b070372009-11-16 22:01:253219 "version: HTTP/1.1\n"
3220 }
3221 };
3222
3223 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]2bd93022010-07-17 00:58:443224 scoped_ptr<spdy::SpdyFrame> req(
3225 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:133226 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8b070372009-11-16 22:01:253227
[email protected]e7f75092010-07-01 22:39:133228 scoped_ptr<spdy::SpdyFrame> resp(
3229 ConstructSpdyGetSynReply(test_cases[i].extra_headers,
[email protected]2bd93022010-07-17 00:58:443230 test_cases[i].num_headers,
3231 1));
3232 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]8b070372009-11-16 22:01:253233 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133234 CreateMockRead(*resp),
3235 CreateMockRead(*body),
[email protected]8b070372009-11-16 22:01:253236 MockRead(true, 0, 0) // EOF
3237 };
3238
[email protected]bf2491a92009-11-29 16:39:483239 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393240 new DelayedSocketData(1, reads, arraysize(reads),
3241 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473242 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153243 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473244 helper.RunToCompletion(data.get());
3245 TransactionHelperResult out = helper.output();
3246
[email protected]8b070372009-11-16 22:01:253247 EXPECT_EQ(OK, out.rv);
3248 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3249 EXPECT_EQ("hello!", out.response_data);
3250
3251 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3252 EXPECT_TRUE(headers.get() != NULL);
3253 void* iter = NULL;
3254 std::string name, value, lines;
3255 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3256 lines.append(name);
3257 lines.append(": ");
3258 lines.append(value);
3259 lines.append("\n");
3260 }
3261 EXPECT_EQ(std::string(test_cases[i].expected_headers), lines);
3262 }
3263}
3264
[email protected]3f662f12010-03-25 19:56:123265// Verify that various SynReply headers parse vary fields correctly
3266// through the HTTP layer, and the response matches the request.
[email protected]9e9e842e2010-07-23 23:09:153267TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
[email protected]3f662f12010-03-25 19:56:123268 static const SpdyHeaderInfo syn_reply_info = {
3269 spdy::SYN_REPLY, // Syn Reply
3270 1, // Stream ID
3271 0, // Associated Stream ID
[email protected]c9c6f5c2010-07-31 01:30:033272 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
3273 // Priority
[email protected]3f662f12010-03-25 19:56:123274 spdy::CONTROL_FLAG_NONE, // Control Flags
3275 false, // Compressed
[email protected]75f30cc22010-06-28 21:41:383276 spdy::INVALID, // Status
[email protected]3f662f12010-03-25 19:56:123277 NULL, // Data
3278 0, // Data Length
3279 spdy::DATA_FLAG_NONE // Data Flags
3280 };
3281 // Modify the following data to change/add test cases:
3282 struct SynReplyTests {
3283 const SpdyHeaderInfo* syn_reply;
3284 bool vary_matches;
3285 int num_headers[2];
3286 const char* extra_headers[2][16];
3287 } test_cases[] = {
3288 // Test the case of a multi-valued cookie. When the value is delimited
3289 // with NUL characters, it needs to be unfolded into multiple headers.
3290 {
3291 &syn_reply_info,
3292 true,
[email protected]8c76ae22010-04-20 22:15:433293 { 1, 4 },
3294 { { "cookie", "val1,val2",
[email protected]3f662f12010-03-25 19:56:123295 NULL
3296 },
3297 { "vary", "cookie",
3298 "status", "200",
3299 "url", "/index.php",
3300 "version", "HTTP/1.1",
3301 NULL
3302 }
3303 }
3304 }, { // Multiple vary fields.
3305 &syn_reply_info,
3306 true,
3307 { 2, 5 },
3308 { { "friend", "barney",
3309 "enemy", "snaggletooth",
3310 NULL
3311 },
3312 { "vary", "friend",
3313 "vary", "enemy",
3314 "status", "200",
3315 "url", "/index.php",
3316 "version", "HTTP/1.1",
3317 NULL
3318 }
3319 }
3320 }, { // Test a '*' vary field.
3321 &syn_reply_info,
3322 false,
3323 { 1, 4 },
3324 { { "cookie", "val1,val2",
3325 NULL
3326 },
3327 { "vary", "*",
3328 "status", "200",
3329 "url", "/index.php",
3330 "version", "HTTP/1.1",
3331 NULL
3332 }
3333 }
3334 }, { // Multiple comma-separated vary fields.
3335 &syn_reply_info,
3336 true,
3337 { 2, 4 },
3338 { { "friend", "barney",
3339 "enemy", "snaggletooth",
3340 NULL
3341 },
3342 { "vary", "friend,enemy",
3343 "status", "200",
3344 "url", "/index.php",
3345 "version", "HTTP/1.1",
3346 NULL
3347 }
3348 }
3349 }
3350 };
3351
3352 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]3f662f12010-03-25 19:56:123353 // Construct the request.
3354 scoped_ptr<spdy::SpdyFrame> frame_req(
3355 ConstructSpdyGet(test_cases[i].extra_headers[0],
[email protected]2bd93022010-07-17 00:58:443356 test_cases[i].num_headers[0],
3357 false, 1, LOWEST));
[email protected]3f662f12010-03-25 19:56:123358
3359 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:133360 CreateMockWrite(*frame_req),
[email protected]3f662f12010-03-25 19:56:123361 };
3362
3363 // Construct the reply.
3364 scoped_ptr<spdy::SpdyFrame> frame_reply(
[email protected]a4aeaf42010-06-30 19:57:283365 ConstructSpdyPacket(*test_cases[i].syn_reply,
[email protected]3f662f12010-03-25 19:56:123366 test_cases[i].extra_headers[1],
3367 test_cases[i].num_headers[1],
3368 NULL,
3369 0));
3370
[email protected]2bd93022010-07-17 00:58:443371 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]3f662f12010-03-25 19:56:123372 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133373 CreateMockRead(*frame_reply),
3374 CreateMockRead(*body),
[email protected]3f662f12010-03-25 19:56:123375 MockRead(true, 0, 0) // EOF
3376 };
3377
[email protected]3f662f12010-03-25 19:56:123378 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:433379 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:123380
[email protected]d3cee19d2010-06-22 18:42:183381 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:433382 for (int ct = 0; ct < header_count; ct++) {
3383 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3384 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3385 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:123386 }
3387
3388 scoped_refptr<DelayedSocketData> data(
3389 new DelayedSocketData(1, reads, arraysize(reads),
3390 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473391 NormalSpdyTransactionHelper helper(request,
[email protected]9e9e842e2010-07-23 23:09:153392 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473393 helper.RunToCompletion(data.get());
3394 TransactionHelperResult out = helper.output();
3395
[email protected]3f662f12010-03-25 19:56:123396 EXPECT_EQ(OK, out.rv) << i;
3397 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3398 EXPECT_EQ("hello!", out.response_data) << i;
3399
3400 // Test the response information.
3401 EXPECT_TRUE(out.response_info.response_time >
3402 out.response_info.request_time) << i;
3403 base::TimeDelta test_delay = out.response_info.response_time -
3404 out.response_info.request_time;
3405 base::TimeDelta min_expected_delay;
3406 min_expected_delay.FromMilliseconds(10);
3407 EXPECT_GT(test_delay.InMillisecondsF(),
3408 min_expected_delay.InMillisecondsF()) << i;
3409 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3410 test_cases[i].vary_matches) << i;
3411
3412 // Check the headers.
3413 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3414 ASSERT_TRUE(headers.get() != NULL) << i;
3415 void* iter = NULL;
3416 std::string name, value, lines;
3417 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3418 lines.append(name);
3419 lines.append(": ");
3420 lines.append(value);
3421 lines.append("\n");
3422 }
3423
3424 // Construct the expected header reply string.
3425 char reply_buffer[256] = "";
[email protected]75f30cc22010-06-28 21:41:383426 ConstructSpdyReplyString(test_cases[i].extra_headers[1],
3427 test_cases[i].num_headers[1],
3428 reply_buffer,
3429 256);
[email protected]3f662f12010-03-25 19:56:123430
3431 EXPECT_EQ(std::string(reply_buffer), lines) << i;
3432 }
3433}
3434
[email protected]dd11b932009-11-30 19:39:483435// Verify that we don't crash on invalid SynReply responses.
[email protected]9e9e842e2010-07-23 23:09:153436TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
[email protected]e7f75092010-07-01 22:39:133437 const SpdyHeaderInfo kSynStartHeader = {
3438 spdy::SYN_REPLY, // Kind = SynReply
3439 1, // Stream ID
3440 0, // Associated stream ID
[email protected]c9c6f5c2010-07-31 01:30:033441 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
3442 // Priority
[email protected]e7f75092010-07-01 22:39:133443 spdy::CONTROL_FLAG_NONE, // Control Flags
3444 false, // Compressed
3445 spdy::INVALID, // Status
3446 NULL, // Data
3447 0, // Length
3448 spdy::DATA_FLAG_NONE // Data Flags
[email protected]dd11b932009-11-30 19:39:483449 };
3450
[email protected]e7f75092010-07-01 22:39:133451 struct InvalidSynReplyTests {
3452 int num_headers;
3453 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:483454 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133455 // SYN_REPLY missing status header
3456 { 4,
3457 { "cookie", "val1",
3458 "cookie", "val2",
3459 "url", "/index.php",
3460 "version", "HTTP/1.1",
3461 NULL
3462 },
3463 },
3464 // SYN_REPLY missing version header
3465 { 2,
3466 { "status", "200",
3467 "url", "/index.php",
3468 NULL
3469 },
3470 },
[email protected]0d384bb2010-07-14 01:51:123471 // SYN_REPLY with no headers
3472 { 0, { NULL }, },
[email protected]dd11b932009-11-30 19:39:483473 };
3474
3475 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]2bd93022010-07-17 00:58:443476 scoped_ptr<spdy::SpdyFrame> req(
3477 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]dd11b932009-11-30 19:39:483478 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:133479 CreateMockWrite(*req),
[email protected]dd11b932009-11-30 19:39:483480 };
3481
[email protected]e7f75092010-07-01 22:39:133482 scoped_ptr<spdy::SpdyFrame> resp(
3483 ConstructSpdyPacket(kSynStartHeader,
3484 NULL, 0,
3485 test_cases[i].headers,
3486 test_cases[i].num_headers));
[email protected]2bd93022010-07-17 00:58:443487 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]dd11b932009-11-30 19:39:483488 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133489 CreateMockRead(*resp),
3490 CreateMockRead(*body),
[email protected]dd11b932009-11-30 19:39:483491 MockRead(true, 0, 0) // EOF
3492 };
3493
[email protected]dd11b932009-11-30 19:39:483494 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393495 new DelayedSocketData(1, reads, arraysize(reads),
3496 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473497 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153498 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473499 helper.RunToCompletion(data.get());
3500 TransactionHelperResult out = helper.output();
[email protected]d08358502010-12-03 22:04:033501 EXPECT_EQ(ERR_INCOMPLETE_SPDY_HEADERS, out.rv);
[email protected]dd11b932009-11-30 19:39:483502 }
3503}
3504
[email protected]94d78132010-01-22 00:53:003505// Verify that we don't crash on some corrupt frames.
[email protected]61c83f782011-01-27 21:00:243506TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3507 // This is the length field that's too short.
3508 scoped_ptr<spdy::SpdyFrame> syn_reply_wrong_length(
[email protected]2bd93022010-07-17 00:58:443509 ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]61c83f782011-01-27 21:00:243510 syn_reply_wrong_length->set_length(syn_reply_wrong_length->length() - 4);
[email protected]94d78132010-01-22 00:53:003511
3512 struct SynReplyTests {
[email protected]e7f75092010-07-01 22:39:133513 const spdy::SpdyFrame* syn_reply;
[email protected]94d78132010-01-22 00:53:003514 } test_cases[] = {
[email protected]61c83f782011-01-27 21:00:243515 { syn_reply_wrong_length.get(), },
[email protected]94d78132010-01-22 00:53:003516 };
3517
3518 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]2bd93022010-07-17 00:58:443519 scoped_ptr<spdy::SpdyFrame> req(
3520 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]94d78132010-01-22 00:53:003521 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:133522 CreateMockWrite(*req),
[email protected]94d78132010-01-22 00:53:003523 MockWrite(true, 0, 0) // EOF
3524 };
3525
[email protected]2bd93022010-07-17 00:58:443526 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003527 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133528 CreateMockRead(*test_cases[i].syn_reply),
3529 CreateMockRead(*body),
[email protected]94d78132010-01-22 00:53:003530 MockRead(true, 0, 0) // EOF
3531 };
3532
[email protected]94d78132010-01-22 00:53:003533 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393534 new DelayedSocketData(1, reads, arraysize(reads),
3535 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473536 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153537 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473538 helper.RunToCompletion(data.get());
3539 TransactionHelperResult out = helper.output();
[email protected]955fc2e72010-02-08 20:37:303540 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003541 }
3542}
3543
[email protected]bf2491a92009-11-29 16:39:483544// Test that we shutdown correctly on write errors.
[email protected]b2776002010-09-10 23:08:493545TEST_P(SpdyNetworkTransactionTest, WriteError) {
[email protected]2bd93022010-07-17 00:58:443546 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]bf2491a92009-11-29 16:39:483547 MockWrite writes[] = {
3548 // We'll write 10 bytes successfully
[email protected]75f30cc22010-06-28 21:41:383549 MockWrite(true, req->data(), 10),
[email protected]bf2491a92009-11-29 16:39:483550 // Followed by ERROR!
3551 MockWrite(true, ERR_FAILED),
[email protected]bf2491a92009-11-29 16:39:483552 };
3553
[email protected]bf2491a92009-11-29 16:39:483554 scoped_refptr<DelayedSocketData> data(
[email protected]3caf5542010-07-16 15:19:473555 new DelayedSocketData(2, NULL, 0,
[email protected]31a2bfe2010-02-09 08:03:393556 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473557 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153558 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473559 helper.RunToCompletion(data.get());
3560 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483561 EXPECT_EQ(ERR_FAILED, out.rv);
[email protected]32100cb2009-11-30 18:24:463562 data->Reset();
[email protected]bf2491a92009-11-29 16:39:483563}
3564
3565// Test that partial writes work.
[email protected]9e9e842e2010-07-23 23:09:153566TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
[email protected]bf2491a92009-11-29 16:39:483567 // Chop the SYN_STREAM frame into 5 chunks.
[email protected]2bd93022010-07-17 00:58:443568 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]bf2491a92009-11-29 16:39:483569 const int kChunks = 5;
[email protected]e7f75092010-07-01 22:39:133570 scoped_array<MockWrite> writes(ChopWriteFrame(*req.get(), kChunks));
[email protected]bf2491a92009-11-29 16:39:483571
[email protected]2bd93022010-07-17 00:58:443572 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3573 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:483574 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133575 CreateMockRead(*resp),
3576 CreateMockRead(*body),
[email protected]bf2491a92009-11-29 16:39:483577 MockRead(true, 0, 0) // EOF
3578 };
3579
[email protected]bf2491a92009-11-29 16:39:483580 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393581 new DelayedSocketData(kChunks, reads, arraysize(reads),
3582 writes.get(), kChunks));
[email protected]3caf5542010-07-16 15:19:473583 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153584 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473585 helper.RunToCompletion(data.get());
3586 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483587 EXPECT_EQ(OK, out.rv);
3588 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3589 EXPECT_EQ("hello!", out.response_data);
3590}
3591
[email protected]94d78132010-01-22 00:53:003592// In this test, we enable compression, but get a uncompressed SynReply from
3593// the server. Verify that teardown is all clean.
[email protected]9e9e842e2010-07-23 23:09:153594TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
[email protected]a4aeaf42010-06-30 19:57:283595 // For this test, we turn on the normal compression.
3596 EnableCompression(true);
3597
[email protected]2bd93022010-07-17 00:58:443598 scoped_ptr<spdy::SpdyFrame> compressed(
3599 ConstructSpdyGet(NULL, 0, true, 1, LOWEST));
[email protected]6c6ea172010-07-27 20:04:033600 scoped_ptr<spdy::SpdyFrame> rst(
3601 ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR));
[email protected]94d78132010-01-22 00:53:003602 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:133603 CreateMockWrite(*compressed),
[email protected]6c6ea172010-07-27 20:04:033604 CreateMockWrite(*rst),
[email protected]94d78132010-01-22 00:53:003605 };
3606
[email protected]2bd93022010-07-17 00:58:443607 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3608 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003609 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133610 CreateMockRead(*resp),
3611 CreateMockRead(*body),
[email protected]58cebf8f2010-07-31 19:20:163612 MockRead(true, 0, 0)
[email protected]94d78132010-01-22 00:53:003613 };
3614
[email protected]94d78132010-01-22 00:53:003615 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393616 new DelayedSocketData(1, reads, arraysize(reads),
3617 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473618 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153619 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473620 helper.RunToCompletion(data.get());
3621 TransactionHelperResult out = helper.output();
[email protected]6c6ea172010-07-27 20:04:033622 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003623 data->Reset();
3624
3625 EnableCompression(false);
3626}
3627
[email protected]9e743cd2010-03-16 07:03:533628// Test that the NetLog contains good data for a simple GET request.
[email protected]9e9e842e2010-07-23 23:09:153629TEST_P(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:403630 static const char* const kExtraHeaders[] = {
3631 "user-agent", "Chrome",
3632 };
3633 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(kExtraHeaders, 1, false, 1,
3634 LOWEST));
[email protected]e7f75092010-07-01 22:39:133635 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]dac358042009-12-18 02:07:483636
[email protected]2bd93022010-07-17 00:58:443637 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3638 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]dac358042009-12-18 02:07:483639 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133640 CreateMockRead(*resp),
3641 CreateMockRead(*body),
[email protected]dac358042009-12-18 02:07:483642 MockRead(true, 0, 0) // EOF
3643 };
3644
[email protected]9e743cd2010-03-16 07:03:533645 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded);
[email protected]dac358042009-12-18 02:07:483646
[email protected]dac358042009-12-18 02:07:483647 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393648 new DelayedSocketData(1, reads, arraysize(reads),
3649 writes, arraysize(writes)));
[email protected]3deb9a52010-11-11 00:24:403650 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
[email protected]9e9e842e2010-07-23 23:09:153651 log.bound(), GetParam());
[email protected]3caf5542010-07-16 15:19:473652 helper.RunToCompletion(data.get());
3653 TransactionHelperResult out = helper.output();
[email protected]dac358042009-12-18 02:07:483654 EXPECT_EQ(OK, out.rv);
3655 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3656 EXPECT_EQ("hello!", out.response_data);
3657
[email protected]9e743cd2010-03-16 07:03:533658 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:473659 // This test is intentionally non-specific about the exact ordering of the
3660 // log; instead we just check to make sure that certain events exist, and that
3661 // they are in the right order.
[email protected]b2fcd0e2010-12-01 15:19:403662 net::CapturingNetLog::EntryList entries;
3663 log.GetEntries(&entries);
3664
3665 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:483666 int pos = 0;
[email protected]b2fcd0e2010-12-01 15:19:403667 pos = net::ExpectLogContainsSomewhere(entries, 0,
[email protected]351ab642010-08-05 16:55:313668 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
[email protected]9e743cd2010-03-16 07:03:533669 net::NetLog::PHASE_BEGIN);
[email protected]b2fcd0e2010-12-01 15:19:403670 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313671 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
[email protected]9e743cd2010-03-16 07:03:533672 net::NetLog::PHASE_END);
[email protected]b2fcd0e2010-12-01 15:19:403673 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313674 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
[email protected]9e743cd2010-03-16 07:03:533675 net::NetLog::PHASE_BEGIN);
[email protected]b2fcd0e2010-12-01 15:19:403676 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313677 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
[email protected]9e743cd2010-03-16 07:03:533678 net::NetLog::PHASE_END);
[email protected]b2fcd0e2010-12-01 15:19:403679 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313680 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
[email protected]9e743cd2010-03-16 07:03:533681 net::NetLog::PHASE_BEGIN);
[email protected]b2fcd0e2010-12-01 15:19:403682 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313683 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
[email protected]9e743cd2010-03-16 07:03:533684 net::NetLog::PHASE_END);
[email protected]3deb9a52010-11-11 00:24:403685
3686 // Check that we logged all the headers correctly
3687 pos = net::ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403688 entries, 0,
[email protected]3deb9a52010-11-11 00:24:403689 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3690 net::NetLog::PHASE_NONE);
[email protected]b2fcd0e2010-12-01 15:19:403691 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:403692 NetLogSpdySynParameter* request_params =
3693 static_cast<NetLogSpdySynParameter*>(entry.extra_parameters.get());
3694 spdy::SpdyHeaderBlock* headers =
3695 request_params->GetHeaders().get();
3696
3697 spdy::SpdyHeaderBlock expected;
3698 expected["host"] = "www.google.com";
3699 expected["url"] = "/";
3700 expected["scheme"] = "http";
3701 expected["version"] = "HTTP/1.1";
3702 expected["method"] = "GET";
3703 expected["user-agent"] = "Chrome";
3704 EXPECT_EQ(expected.size(), headers->size());
3705 spdy::SpdyHeaderBlock::const_iterator end = expected.end();
3706 for (spdy::SpdyHeaderBlock::const_iterator it = expected.begin();
3707 it != end;
3708 ++it) {
3709 EXPECT_EQ(it->second, (*headers)[it->first]);
3710 }
[email protected]dac358042009-12-18 02:07:483711}
3712
[email protected]79d84222010-02-26 00:01:443713// Since we buffer the IO from the stream to the renderer, this test verifies
3714// that when we read out the maximum amount of data (e.g. we received 50 bytes
3715// on the network, but issued a Read for only 5 of those bytes) that the data
3716// flow still works correctly.
[email protected]9e9e842e2010-07-23 23:09:153717TEST_P(SpdyNetworkTransactionTest, BufferFull) {
[email protected]20d005f2010-07-02 19:55:433718 spdy::SpdyFramer framer;
3719
[email protected]2bd93022010-07-17 00:58:443720 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:133721 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]79d84222010-02-26 00:01:443722
[email protected]20d005f2010-07-02 19:55:433723 // 2 data frames in a single read.
3724 scoped_ptr<spdy::SpdyFrame> data_frame_1(
3725 framer.CreateDataFrame(1, "goodby", 6, spdy::DATA_FLAG_NONE));
3726 scoped_ptr<spdy::SpdyFrame> data_frame_2(
3727 framer.CreateDataFrame(1, "e worl", 6, spdy::DATA_FLAG_NONE));
3728 const spdy::SpdyFrame* data_frames[2] = {
3729 data_frame_1.get(),
3730 data_frame_2.get(),
[email protected]79d84222010-02-26 00:01:443731 };
[email protected]20d005f2010-07-02 19:55:433732 char combined_data_frames[100];
3733 int combined_data_frames_len =
3734 CombineFrames(data_frames, arraysize(data_frames),
3735 combined_data_frames, arraysize(combined_data_frames));
3736 scoped_ptr<spdy::SpdyFrame> last_frame(
3737 framer.CreateDataFrame(1, "d", 1, spdy::DATA_FLAG_FIN));
[email protected]79d84222010-02-26 00:01:443738
[email protected]2bd93022010-07-17 00:58:443739 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]79d84222010-02-26 00:01:443740 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133741 CreateMockRead(*resp),
[email protected]79d84222010-02-26 00:01:443742 MockRead(true, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:433743 MockRead(true, combined_data_frames, combined_data_frames_len),
[email protected]79d84222010-02-26 00:01:443744 MockRead(true, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:433745 CreateMockRead(*last_frame),
[email protected]79d84222010-02-26 00:01:443746 MockRead(true, 0, 0) // EOF
3747 };
3748
[email protected]79d84222010-02-26 00:01:443749 scoped_refptr<DelayedSocketData> data(
3750 new DelayedSocketData(1, reads, arraysize(reads),
3751 writes, arraysize(writes)));
3752
[email protected]79d84222010-02-26 00:01:443753
3754 TestCompletionCallback callback;
3755
[email protected]3caf5542010-07-16 15:19:473756 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153757 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473758 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:583759 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:473760 HttpNetworkTransaction* trans = helper.trans();
[email protected]d3cee19d2010-06-22 18:42:183761 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]79d84222010-02-26 00:01:443762 EXPECT_EQ(ERR_IO_PENDING, rv);
3763
[email protected]3caf5542010-07-16 15:19:473764 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:443765 out.rv = callback.WaitForResult();
3766 EXPECT_EQ(out.rv, OK);
3767
3768 const HttpResponseInfo* response = trans->GetResponseInfo();
3769 EXPECT_TRUE(response->headers != NULL);
3770 EXPECT_TRUE(response->was_fetched_via_spdy);
3771 out.status_line = response->headers->GetStatusLine();
3772 out.response_info = *response; // Make a copy so we can verify.
3773
3774 // Read Data
3775 TestCompletionCallback read_callback;
3776
3777 std::string content;
3778 do {
3779 // Read small chunks at a time.
3780 const int kSmallReadSize = 3;
[email protected]ad8e04a2010-11-01 04:16:273781 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]79d84222010-02-26 00:01:443782 rv = trans->Read(buf, kSmallReadSize, &read_callback);
3783 if (rv == net::ERR_IO_PENDING) {
3784 data->CompleteRead();
3785 rv = read_callback.WaitForResult();
3786 }
3787 if (rv > 0) {
3788 content.append(buf->data(), rv);
3789 } else if (rv < 0) {
3790 NOTREACHED();
3791 }
3792 } while (rv > 0);
3793
3794 out.response_data.swap(content);
3795
[email protected]30c942b2010-07-21 16:59:593796 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553797 // MockClientSocketFactory) are still alive.
3798 MessageLoop::current()->RunAllPending();
3799
[email protected]79d84222010-02-26 00:01:443800 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473801 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:443802
3803 EXPECT_EQ(OK, out.rv);
3804 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3805 EXPECT_EQ("goodbye world", out.response_data);
3806}
3807
[email protected]9e9e842e2010-07-23 23:09:153808TEST_P(SpdyNetworkTransactionTest, ConnectFailureFallbackToHttp) {
[email protected]e6b06862010-07-20 16:32:583809 MockConnect connects[] = {
3810 MockConnect(true, ERR_NAME_NOT_RESOLVED),
3811 MockConnect(false, ERR_NAME_NOT_RESOLVED),
3812 MockConnect(true, ERR_INTERNET_DISCONNECTED),
3813 MockConnect(false, ERR_INTERNET_DISCONNECTED)
3814 };
3815
3816 for (size_t index = 0; index < arraysize(connects); ++index) {
3817 scoped_ptr<spdy::SpdyFrame> req(
3818 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3819 MockWrite writes[] = {
3820 CreateMockWrite(*req),
3821 MockWrite(true, 0, 0) // EOF
3822 };
3823
3824 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3825 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3826 MockRead reads[] = {
3827 CreateMockRead(*resp),
3828 CreateMockRead(*body),
3829 MockRead(true, 0, 0) // EOF
3830 };
3831
3832 scoped_refptr<DelayedSocketData> data(
3833 new DelayedSocketData(connects[index], 1, reads, arraysize(reads),
3834 writes, arraysize(writes)));
3835 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153836 BoundNetLog(), GetParam());
[email protected]e6b06862010-07-20 16:32:583837 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:583838 helper.AddData(data.get());
[email protected]e6b06862010-07-20 16:32:583839
3840 // Set up http fallback data.
3841 MockRead http_fallback_data[] = {
3842 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
3843 MockRead("hello world!!!"),
3844 MockRead(true, OK),
3845 };
3846
3847 scoped_ptr<StaticSocketDataProvider> http_fallback(
3848 new StaticSocketDataProvider(http_fallback_data,
3849 arraysize(http_fallback_data),
3850 NULL, 0));
3851 helper.AddDataNoSSL(http_fallback.get());
3852 HttpNetworkTransaction* trans = helper.trans();
3853 TestCompletionCallback callback;
3854
3855 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
3856 EXPECT_EQ(rv, ERR_IO_PENDING);
3857 rv = callback.WaitForResult();
3858 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]9e9e842e2010-07-23 23:09:153859 if (GetParam() == SPDYNOSSL || GetParam() == SPDYSSL) {
3860 ASSERT_TRUE(response == NULL);
3861 return;
3862 }
3863 if (GetParam() != SPDYNPN)
3864 NOTREACHED();
[email protected]e6b06862010-07-20 16:32:583865 ASSERT_TRUE(response != NULL);
3866 ASSERT_TRUE(response->headers != NULL);
3867 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3868 std::string response_data;
3869 rv = ReadTransaction(trans, &response_data);
3870 EXPECT_EQ(OK, rv);
3871
3872 EXPECT_TRUE(!response->was_fetched_via_spdy);
3873 EXPECT_TRUE(!response->was_npn_negotiated);
3874 EXPECT_TRUE(response->was_alternate_protocol_available);
3875 EXPECT_TRUE(http_fallback->at_read_eof());
3876 EXPECT_EQ(0u, data->read_index());
3877 EXPECT_EQ(0u, data->write_index());
3878 EXPECT_EQ("hello world!!!", response_data);
3879 }
3880}
3881
[email protected]8918d282010-03-02 00:57:553882// Verify that basic buffering works; when multiple data frames arrive
3883// at the same time, ensure that we don't notify a read completion for
3884// each data frame individually.
[email protected]9e9e842e2010-07-23 23:09:153885TEST_P(SpdyNetworkTransactionTest, Buffering) {
[email protected]20d005f2010-07-02 19:55:433886 spdy::SpdyFramer framer;
3887
[email protected]2bd93022010-07-17 00:58:443888 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:133889 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:553890
3891 // 4 data frames in a single read.
[email protected]20d005f2010-07-02 19:55:433892 scoped_ptr<spdy::SpdyFrame> data_frame(
3893 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
3894 scoped_ptr<spdy::SpdyFrame> data_frame_fin(
3895 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
3896 const spdy::SpdyFrame* data_frames[4] = {
3897 data_frame.get(),
3898 data_frame.get(),
3899 data_frame.get(),
3900 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:553901 };
[email protected]20d005f2010-07-02 19:55:433902 char combined_data_frames[100];
3903 int combined_data_frames_len =
3904 CombineFrames(data_frames, arraysize(data_frames),
3905 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:553906
[email protected]2bd93022010-07-17 00:58:443907 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553908 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133909 CreateMockRead(*resp),
[email protected]8918d282010-03-02 00:57:553910 MockRead(true, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:433911 MockRead(true, combined_data_frames, combined_data_frames_len),
[email protected]8918d282010-03-02 00:57:553912 MockRead(true, 0, 0) // EOF
3913 };
3914
[email protected]8918d282010-03-02 00:57:553915 scoped_refptr<DelayedSocketData> data(
3916 new DelayedSocketData(1, reads, arraysize(reads),
3917 writes, arraysize(writes)));
3918
[email protected]3caf5542010-07-16 15:19:473919 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153920 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473921 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:583922 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:473923 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553924
3925 TestCompletionCallback callback;
[email protected]d3cee19d2010-06-22 18:42:183926 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]8918d282010-03-02 00:57:553927 EXPECT_EQ(ERR_IO_PENDING, rv);
3928
[email protected]3caf5542010-07-16 15:19:473929 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553930 out.rv = callback.WaitForResult();
3931 EXPECT_EQ(out.rv, OK);
3932
3933 const HttpResponseInfo* response = trans->GetResponseInfo();
3934 EXPECT_TRUE(response->headers != NULL);
3935 EXPECT_TRUE(response->was_fetched_via_spdy);
3936 out.status_line = response->headers->GetStatusLine();
3937 out.response_info = *response; // Make a copy so we can verify.
3938
3939 // Read Data
3940 TestCompletionCallback read_callback;
3941
3942 std::string content;
3943 int reads_completed = 0;
3944 do {
3945 // Read small chunks at a time.
3946 const int kSmallReadSize = 14;
[email protected]ad8e04a2010-11-01 04:16:273947 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]8918d282010-03-02 00:57:553948 rv = trans->Read(buf, kSmallReadSize, &read_callback);
3949 if (rv == net::ERR_IO_PENDING) {
3950 data->CompleteRead();
3951 rv = read_callback.WaitForResult();
3952 }
3953 if (rv > 0) {
3954 EXPECT_EQ(kSmallReadSize, rv);
3955 content.append(buf->data(), rv);
3956 } else if (rv < 0) {
3957 FAIL() << "Unexpected read error: " << rv;
3958 }
3959 reads_completed++;
3960 } while (rv > 0);
3961
3962 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3963
3964 out.response_data.swap(content);
3965
[email protected]30c942b2010-07-21 16:59:593966 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553967 // MockClientSocketFactory) are still alive.
3968 MessageLoop::current()->RunAllPending();
3969
3970 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473971 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553972
3973 EXPECT_EQ(OK, out.rv);
3974 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3975 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3976}
3977
3978// Verify the case where we buffer data but read it after it has been buffered.
[email protected]9e9e842e2010-07-23 23:09:153979TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
[email protected]20d005f2010-07-02 19:55:433980 spdy::SpdyFramer framer;
3981
[email protected]2bd93022010-07-17 00:58:443982 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:133983 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:553984
[email protected]20d005f2010-07-02 19:55:433985 // 5 data frames in a single read.
3986 scoped_ptr<spdy::SpdyFrame> syn_reply(
[email protected]2bd93022010-07-17 00:58:443987 ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]20d005f2010-07-02 19:55:433988 syn_reply->set_flags(spdy::CONTROL_FLAG_NONE); // turn off FIN bit
3989 scoped_ptr<spdy::SpdyFrame> data_frame(
3990 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
3991 scoped_ptr<spdy::SpdyFrame> data_frame_fin(
3992 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
3993 const spdy::SpdyFrame* frames[5] = {
3994 syn_reply.get(),
3995 data_frame.get(),
3996 data_frame.get(),
3997 data_frame.get(),
3998 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:553999 };
[email protected]20d005f2010-07-02 19:55:434000 char combined_frames[200];
4001 int combined_frames_len =
4002 CombineFrames(frames, arraysize(frames),
4003 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:554004
4005 MockRead reads[] = {
[email protected]20d005f2010-07-02 19:55:434006 MockRead(true, combined_frames, combined_frames_len),
[email protected]8918d282010-03-02 00:57:554007 MockRead(true, 0, 0) // EOF
4008 };
4009
[email protected]8918d282010-03-02 00:57:554010 scoped_refptr<DelayedSocketData> data(
4011 new DelayedSocketData(1, reads, arraysize(reads),
4012 writes, arraysize(writes)));
4013
[email protected]3caf5542010-07-16 15:19:474014 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:154015 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:474016 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:584017 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:474018 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:554019
4020 TestCompletionCallback callback;
[email protected]d3cee19d2010-06-22 18:42:184021 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]8918d282010-03-02 00:57:554022 EXPECT_EQ(ERR_IO_PENDING, rv);
4023
[email protected]3caf5542010-07-16 15:19:474024 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:554025 out.rv = callback.WaitForResult();
4026 EXPECT_EQ(out.rv, OK);
4027
4028 const HttpResponseInfo* response = trans->GetResponseInfo();
4029 EXPECT_TRUE(response->headers != NULL);
4030 EXPECT_TRUE(response->was_fetched_via_spdy);
4031 out.status_line = response->headers->GetStatusLine();
4032 out.response_info = *response; // Make a copy so we can verify.
4033
4034 // Read Data
4035 TestCompletionCallback read_callback;
4036
4037 std::string content;
4038 int reads_completed = 0;
4039 do {
4040 // Read small chunks at a time.
4041 const int kSmallReadSize = 14;
[email protected]ad8e04a2010-11-01 04:16:274042 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]8918d282010-03-02 00:57:554043 rv = trans->Read(buf, kSmallReadSize, &read_callback);
4044 if (rv > 0) {
4045 EXPECT_EQ(kSmallReadSize, rv);
4046 content.append(buf->data(), rv);
4047 } else if (rv < 0) {
4048 FAIL() << "Unexpected read error: " << rv;
4049 }
4050 reads_completed++;
4051 } while (rv > 0);
4052
4053 EXPECT_EQ(3, reads_completed);
4054
4055 out.response_data.swap(content);
4056
[email protected]30c942b2010-07-21 16:59:594057 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:554058 // MockClientSocketFactory) are still alive.
4059 MessageLoop::current()->RunAllPending();
4060
4061 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474062 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:554063
4064 EXPECT_EQ(OK, out.rv);
4065 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4066 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4067}
4068
4069// Verify the case where we buffer data and close the connection.
[email protected]9e9e842e2010-07-23 23:09:154070TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
[email protected]20d005f2010-07-02 19:55:434071 spdy::SpdyFramer framer;
4072
[email protected]2bd93022010-07-17 00:58:444073 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:134074 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:554075
4076 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:434077 // NOTE: We don't FIN the stream.
4078 scoped_ptr<spdy::SpdyFrame> data_frame(
4079 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
4080 const spdy::SpdyFrame* data_frames[4] = {
4081 data_frame.get(),
4082 data_frame.get(),
4083 data_frame.get(),
4084 data_frame.get()
[email protected]8918d282010-03-02 00:57:554085 };
[email protected]20d005f2010-07-02 19:55:434086 char combined_data_frames[100];
4087 int combined_data_frames_len =
4088 CombineFrames(data_frames, arraysize(data_frames),
4089 combined_data_frames, arraysize(combined_data_frames));
[email protected]2bd93022010-07-17 00:58:444090 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:554091 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134092 CreateMockRead(*resp),
[email protected]8918d282010-03-02 00:57:554093 MockRead(true, ERR_IO_PENDING), // Force a wait
[email protected]20d005f2010-07-02 19:55:434094 MockRead(true, combined_data_frames, combined_data_frames_len),
[email protected]8918d282010-03-02 00:57:554095 MockRead(true, 0, 0) // EOF
4096 };
4097
[email protected]8918d282010-03-02 00:57:554098 scoped_refptr<DelayedSocketData> data(
4099 new DelayedSocketData(1, reads, arraysize(reads),
4100 writes, arraysize(writes)));
4101
[email protected]3caf5542010-07-16 15:19:474102 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:154103 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:474104 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:584105 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:474106 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:554107
4108 TestCompletionCallback callback;
4109
[email protected]d3cee19d2010-06-22 18:42:184110 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]8918d282010-03-02 00:57:554111 EXPECT_EQ(ERR_IO_PENDING, rv);
4112
[email protected]3caf5542010-07-16 15:19:474113 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:554114 out.rv = callback.WaitForResult();
4115 EXPECT_EQ(out.rv, OK);
4116
4117 const HttpResponseInfo* response = trans->GetResponseInfo();
4118 EXPECT_TRUE(response->headers != NULL);
4119 EXPECT_TRUE(response->was_fetched_via_spdy);
4120 out.status_line = response->headers->GetStatusLine();
4121 out.response_info = *response; // Make a copy so we can verify.
4122
4123 // Read Data
4124 TestCompletionCallback read_callback;
4125
4126 std::string content;
4127 int reads_completed = 0;
4128 do {
4129 // Read small chunks at a time.
4130 const int kSmallReadSize = 14;
[email protected]ad8e04a2010-11-01 04:16:274131 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]8918d282010-03-02 00:57:554132 rv = trans->Read(buf, kSmallReadSize, &read_callback);
4133 if (rv == net::ERR_IO_PENDING) {
4134 data->CompleteRead();
4135 rv = read_callback.WaitForResult();
4136 }
4137 if (rv > 0) {
4138 content.append(buf->data(), rv);
4139 } else if (rv < 0) {
4140 // This test intentionally closes the connection, and will get an error.
4141 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4142 break;
4143 }
4144 reads_completed++;
4145 } while (rv > 0);
4146
4147 EXPECT_EQ(0, reads_completed);
4148
4149 out.response_data.swap(content);
4150
[email protected]30c942b2010-07-21 16:59:594151 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:554152 // MockClientSocketFactory) are still alive.
4153 MessageLoop::current()->RunAllPending();
4154
4155 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474156 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:554157}
4158
[email protected]1ed7b3dc2010-03-04 05:41:454159// Verify the case where we buffer data and cancel the transaction.
[email protected]9e9e842e2010-07-23 23:09:154160TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
[email protected]20d005f2010-07-02 19:55:434161 spdy::SpdyFramer framer;
4162
[email protected]2bd93022010-07-17 00:58:444163 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:134164 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]1ed7b3dc2010-03-04 05:41:454165
[email protected]20d005f2010-07-02 19:55:434166 // NOTE: We don't FIN the stream.
4167 scoped_ptr<spdy::SpdyFrame> data_frame(
4168 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
[email protected]1ed7b3dc2010-03-04 05:41:454169
[email protected]2bd93022010-07-17 00:58:444170 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:454171 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134172 CreateMockRead(*resp),
[email protected]1ed7b3dc2010-03-04 05:41:454173 MockRead(true, ERR_IO_PENDING), // Force a wait
[email protected]20d005f2010-07-02 19:55:434174 CreateMockRead(*data_frame),
[email protected]1ed7b3dc2010-03-04 05:41:454175 MockRead(true, 0, 0) // EOF
4176 };
4177
[email protected]1ed7b3dc2010-03-04 05:41:454178 scoped_refptr<DelayedSocketData> data(
4179 new DelayedSocketData(1, reads, arraysize(reads),
4180 writes, arraysize(writes)));
4181
[email protected]3caf5542010-07-16 15:19:474182 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:154183 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:474184 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:584185 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:474186 HttpNetworkTransaction* trans = helper.trans();
[email protected]1ed7b3dc2010-03-04 05:41:454187 TestCompletionCallback callback;
4188
[email protected]d3cee19d2010-06-22 18:42:184189 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]1ed7b3dc2010-03-04 05:41:454190 EXPECT_EQ(ERR_IO_PENDING, rv);
4191
[email protected]3caf5542010-07-16 15:19:474192 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:454193 out.rv = callback.WaitForResult();
4194 EXPECT_EQ(out.rv, OK);
4195
4196 const HttpResponseInfo* response = trans->GetResponseInfo();
4197 EXPECT_TRUE(response->headers != NULL);
4198 EXPECT_TRUE(response->was_fetched_via_spdy);
4199 out.status_line = response->headers->GetStatusLine();
4200 out.response_info = *response; // Make a copy so we can verify.
4201
4202 // Read Data
4203 TestCompletionCallback read_callback;
4204
4205 do {
4206 const int kReadSize = 256;
[email protected]ad8e04a2010-11-01 04:16:274207 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
[email protected]1ed7b3dc2010-03-04 05:41:454208 rv = trans->Read(buf, kReadSize, &read_callback);
4209 if (rv == net::ERR_IO_PENDING) {
4210 // Complete the read now, which causes buffering to start.
4211 data->CompleteRead();
4212 // Destroy the transaction, causing the stream to get cancelled
4213 // and orphaning the buffered IO task.
[email protected]3caf5542010-07-16 15:19:474214 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:454215 break;
4216 }
4217 // We shouldn't get here in this test.
4218 FAIL() << "Unexpected read: " << rv;
4219 } while (rv > 0);
4220
4221 // Flush the MessageLoop; this will cause the buffered IO task
4222 // to run for the final time.
4223 MessageLoop::current()->RunAllPending();
[email protected]3caf5542010-07-16 15:19:474224
4225 // Verify that we consumed all test data.
4226 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:454227}
4228
[email protected]74188f22010-04-09 20:18:504229// Test that if the server requests persistence of settings, that we save
4230// the settings in the SpdySettingsStorage.
[email protected]9e9e842e2010-07-23 23:09:154231TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
[email protected]74188f22010-04-09 20:18:504232 static const SpdyHeaderInfo kSynReplyInfo = {
4233 spdy::SYN_REPLY, // Syn Reply
4234 1, // Stream ID
4235 0, // Associated Stream ID
[email protected]c9c6f5c2010-07-31 01:30:034236 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
4237 // Priority
[email protected]74188f22010-04-09 20:18:504238 spdy::CONTROL_FLAG_NONE, // Control Flags
4239 false, // Compressed
[email protected]75f30cc22010-06-28 21:41:384240 spdy::INVALID, // Status
[email protected]74188f22010-04-09 20:18:504241 NULL, // Data
4242 0, // Data Length
4243 spdy::DATA_FLAG_NONE // Data Flags
4244 };
4245 static const char* const kExtraHeaders[] = {
4246 "status", "200",
4247 "version", "HTTP/1.1"
4248 };
4249
[email protected]3caf5542010-07-16 15:19:474250 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:154251 BoundNetLog(), GetParam());
[email protected]e3ebba0f2010-08-05 17:59:584252 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504253
4254 // Verify that no settings exist initially.
[email protected]9e9e842e2010-07-23 23:09:154255 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]102e27c2011-02-23 01:01:314256 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4257 EXPECT_TRUE(spdy_session_pool->spdy_settings().Get(host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504258
4259 // Construct the request.
[email protected]2bd93022010-07-17 00:58:444260 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:134261 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]74188f22010-04-09 20:18:504262
4263 // Construct the reply.
4264 scoped_ptr<spdy::SpdyFrame> reply(
[email protected]a4aeaf42010-06-30 19:57:284265 ConstructSpdyPacket(kSynReplyInfo,
[email protected]74188f22010-04-09 20:18:504266 kExtraHeaders,
4267 arraysize(kExtraHeaders) / 2,
4268 NULL,
4269 0));
4270
4271 unsigned int kSampleId1 = 0x1;
4272 unsigned int kSampleValue1 = 0x0a0a0a0a;
4273 unsigned int kSampleId2 = 0x2;
4274 unsigned int kSampleValue2 = 0x0b0b0b0b;
4275 unsigned int kSampleId3 = 0xababab;
4276 unsigned int kSampleValue3 = 0x0c0c0c0c;
4277 scoped_ptr<spdy::SpdyFrame> settings_frame;
4278 {
4279 // Construct the SETTINGS frame.
4280 spdy::SpdySettings settings;
4281 spdy::SettingsFlagsAndId setting(0);
4282 // First add a persisted setting
4283 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4284 setting.set_id(kSampleId1);
4285 settings.push_back(std::make_pair(setting, kSampleValue1));
4286 // Next add a non-persisted setting
4287 setting.set_flags(0);
4288 setting.set_id(kSampleId2);
4289 settings.push_back(std::make_pair(setting, kSampleValue2));
4290 // Next add another persisted setting
4291 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4292 setting.set_id(kSampleId3);
4293 settings.push_back(std::make_pair(setting, kSampleValue3));
4294 settings_frame.reset(ConstructSpdySettings(settings));
4295 }
4296
[email protected]2bd93022010-07-17 00:58:444297 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504298 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134299 CreateMockRead(*reply),
4300 CreateMockRead(*body),
4301 CreateMockRead(*settings_frame),
[email protected]74188f22010-04-09 20:18:504302 MockRead(true, 0, 0) // EOF
4303 };
4304
[email protected]74188f22010-04-09 20:18:504305 scoped_refptr<DelayedSocketData> data(
4306 new DelayedSocketData(1, reads, arraysize(reads),
4307 writes, arraysize(writes)));
[email protected]e3ebba0f2010-08-05 17:59:584308 helper.AddData(data.get());
4309 helper.RunDefaultTest();
4310 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474311 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504312 EXPECT_EQ(OK, out.rv);
4313 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4314 EXPECT_EQ("hello!", out.response_data);
4315
4316 {
4317 // Verify we had two persisted settings.
4318 spdy::SpdySettings saved_settings =
[email protected]102e27c2011-02-23 01:01:314319 spdy_session_pool->spdy_settings().Get(host_port_pair);
[email protected]74188f22010-04-09 20:18:504320 ASSERT_EQ(2u, saved_settings.size());
4321
4322 // Verify the first persisted setting.
4323 spdy::SpdySetting setting = saved_settings.front();
4324 saved_settings.pop_front();
4325 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4326 EXPECT_EQ(kSampleId1, setting.first.id());
4327 EXPECT_EQ(kSampleValue1, setting.second);
4328
4329 // Verify the second persisted setting.
4330 setting = saved_settings.front();
4331 saved_settings.pop_front();
4332 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4333 EXPECT_EQ(kSampleId3, setting.first.id());
4334 EXPECT_EQ(kSampleValue3, setting.second);
4335 }
4336}
4337
4338// Test that when there are settings saved that they are sent back to the
4339// server upon session establishment.
[email protected]9e9e842e2010-07-23 23:09:154340TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
[email protected]74188f22010-04-09 20:18:504341 static const SpdyHeaderInfo kSynReplyInfo = {
4342 spdy::SYN_REPLY, // Syn Reply
4343 1, // Stream ID
4344 0, // Associated Stream ID
[email protected]c9c6f5c2010-07-31 01:30:034345 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
4346 // Priority
[email protected]74188f22010-04-09 20:18:504347 spdy::CONTROL_FLAG_NONE, // Control Flags
4348 false, // Compressed
[email protected]75f30cc22010-06-28 21:41:384349 spdy::INVALID, // Status
[email protected]74188f22010-04-09 20:18:504350 NULL, // Data
4351 0, // Data Length
4352 spdy::DATA_FLAG_NONE // Data Flags
4353 };
4354 static const char* kExtraHeaders[] = {
4355 "status", "200",
4356 "version", "HTTP/1.1"
4357 };
4358
[email protected]3caf5542010-07-16 15:19:474359 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:154360 BoundNetLog(), GetParam());
[email protected]e3ebba0f2010-08-05 17:59:584361 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504362
4363 // Verify that no settings exist initially.
[email protected]9e9e842e2010-07-23 23:09:154364 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]102e27c2011-02-23 01:01:314365 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4366 EXPECT_TRUE(spdy_session_pool->spdy_settings().Get(host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504367
4368 unsigned int kSampleId1 = 0x1;
4369 unsigned int kSampleValue1 = 0x0a0a0a0a;
4370 unsigned int kSampleId2 = 0xababab;
4371 unsigned int kSampleValue2 = 0x0c0c0c0c;
4372 // Manually insert settings into the SpdySettingsStorage here.
4373 {
4374 spdy::SpdySettings settings;
4375 spdy::SettingsFlagsAndId setting(0);
4376 // First add a persisted setting
4377 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4378 setting.set_id(kSampleId1);
4379 settings.push_back(std::make_pair(setting, kSampleValue1));
4380 // Next add another persisted setting
4381 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4382 setting.set_id(kSampleId2);
4383 settings.push_back(std::make_pair(setting, kSampleValue2));
4384
[email protected]102e27c2011-02-23 01:01:314385 spdy_session_pool->mutable_spdy_settings()->Set(host_port_pair, settings);
[email protected]74188f22010-04-09 20:18:504386 }
4387
[email protected]102e27c2011-02-23 01:01:314388 EXPECT_EQ(2u, spdy_session_pool->spdy_settings().Get(host_port_pair).size());
[email protected]74188f22010-04-09 20:18:504389
4390 // Construct the SETTINGS frame.
4391 const spdy::SpdySettings& settings =
[email protected]102e27c2011-02-23 01:01:314392 spdy_session_pool->spdy_settings().Get(host_port_pair);
[email protected]74188f22010-04-09 20:18:504393 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
4394
4395 // Construct the request.
[email protected]2bd93022010-07-17 00:58:444396 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]74188f22010-04-09 20:18:504397
4398 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:134399 CreateMockWrite(*settings_frame),
4400 CreateMockWrite(*req),
[email protected]74188f22010-04-09 20:18:504401 };
4402
4403 // Construct the reply.
4404 scoped_ptr<spdy::SpdyFrame> reply(
[email protected]a4aeaf42010-06-30 19:57:284405 ConstructSpdyPacket(kSynReplyInfo,
[email protected]74188f22010-04-09 20:18:504406 kExtraHeaders,
4407 arraysize(kExtraHeaders) / 2,
4408 NULL,
4409 0));
4410
[email protected]2bd93022010-07-17 00:58:444411 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504412 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134413 CreateMockRead(*reply),
4414 CreateMockRead(*body),
[email protected]74188f22010-04-09 20:18:504415 MockRead(true, 0, 0) // EOF
4416 };
4417
[email protected]74188f22010-04-09 20:18:504418 scoped_refptr<DelayedSocketData> data(
4419 new DelayedSocketData(2, reads, arraysize(reads),
4420 writes, arraysize(writes)));
[email protected]e3ebba0f2010-08-05 17:59:584421 helper.AddData(data.get());
4422 helper.RunDefaultTest();
4423 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474424 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504425 EXPECT_EQ(OK, out.rv);
4426 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4427 EXPECT_EQ("hello!", out.response_data);
4428
4429 {
4430 // Verify we had two persisted settings.
4431 spdy::SpdySettings saved_settings =
[email protected]102e27c2011-02-23 01:01:314432 spdy_session_pool->spdy_settings().Get(host_port_pair);
[email protected]74188f22010-04-09 20:18:504433 ASSERT_EQ(2u, saved_settings.size());
4434
4435 // Verify the first persisted setting.
4436 spdy::SpdySetting setting = saved_settings.front();
4437 saved_settings.pop_front();
4438 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4439 EXPECT_EQ(kSampleId1, setting.first.id());
4440 EXPECT_EQ(kSampleValue1, setting.second);
4441
4442 // Verify the second persisted setting.
4443 setting = saved_settings.front();
4444 saved_settings.pop_front();
4445 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4446 EXPECT_EQ(kSampleId2, setting.first.id());
4447 EXPECT_EQ(kSampleValue2, setting.second);
4448 }
4449}
4450
[email protected]9e9e842e2010-07-23 23:09:154451TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
[email protected]2bd93022010-07-17 00:58:444452 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:134453 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]69d717bd2010-04-21 18:43:214454
[email protected]a4aeaf42010-06-30 19:57:284455 scoped_ptr<spdy::SpdyFrame> go_away(ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:214456 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134457 CreateMockRead(*go_away),
[email protected]58cebf8f2010-07-31 19:20:164458 MockRead(true, 0, 0), // EOF
4459 };
4460
[email protected]69d717bd2010-04-21 18:43:214461 scoped_refptr<DelayedSocketData> data(
4462 new DelayedSocketData(1, reads, arraysize(reads),
4463 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:474464 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:154465 BoundNetLog(), GetParam());
[email protected]58cebf8f2010-07-31 19:20:164466 helper.AddData(data);
[email protected]58cebf8f2010-07-31 19:20:164467 helper.RunToCompletion(data.get());
4468 TransactionHelperResult out = helper.output();
[email protected]c9336d22010-08-10 00:04:184469 EXPECT_EQ(ERR_ABORTED, out.rv);
[email protected]69d717bd2010-04-21 18:43:214470}
4471
[email protected]9e9e842e2010-07-23 23:09:154472TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
[email protected]2bd93022010-07-17 00:58:444473 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:134474 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]f5ed21552010-05-04 18:39:544475
[email protected]2bd93022010-07-17 00:58:444476 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f5ed21552010-05-04 18:39:544477 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134478 CreateMockRead(*resp),
[email protected]f5ed21552010-05-04 18:39:544479 MockRead(false, 0, 0) // EOF
4480 };
4481
[email protected]f5ed21552010-05-04 18:39:544482 scoped_refptr<DelayedSocketData> data(
4483 new DelayedSocketData(1, reads, arraysize(reads),
4484 writes, arraysize(writes)));
[email protected]f5ed21552010-05-04 18:39:544485 BoundNetLog log;
[email protected]3caf5542010-07-16 15:19:474486 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:154487 log, GetParam());
[email protected]3caf5542010-07-16 15:19:474488 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:584489 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:474490 HttpNetworkTransaction* trans = helper.trans();
[email protected]f5ed21552010-05-04 18:39:544491
4492 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:474493 TransactionHelperResult out;
[email protected]d3cee19d2010-06-22 18:42:184494 out.rv = trans->Start(&CreateGetRequest(), &callback, log);
[email protected]3caf5542010-07-16 15:19:474495
[email protected]f5ed21552010-05-04 18:39:544496 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4497 out.rv = callback.WaitForResult();
4498 EXPECT_EQ(out.rv, OK);
4499
4500 const HttpResponseInfo* response = trans->GetResponseInfo();
4501 EXPECT_TRUE(response->headers != NULL);
4502 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]3caf5542010-07-16 15:19:474503 out.rv = ReadTransaction(trans, &out.response_data);
[email protected]f5ed21552010-05-04 18:39:544504 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4505
4506 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474507 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:544508}
[email protected]58cebf8f2010-07-31 19:20:164509
[email protected]b261d0e2010-08-02 19:13:244510// Test to make sure we can correctly connect through a proxy.
4511TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4512 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4513 BoundNetLog(), GetParam());
4514 helper.session_deps().reset(new SpdySessionDependencies(
[email protected]733b7a6d2010-08-25 01:38:434515 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
[email protected]00cd9c42010-11-02 20:15:574516 helper.SetSession(make_scoped_refptr(
4517 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
[email protected]b261d0e2010-08-02 19:13:244518 helper.RunPreTestSetup();
4519 HttpNetworkTransaction* trans = helper.trans();
4520
4521 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4522 "Host: www.google.com\r\n"
4523 "Proxy-Connection: keep-alive\r\n\r\n"};
4524 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4525 "Host: www.google.com\r\n"
4526 "Proxy-Connection: keep-alive\r\n\r\n"};
4527 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4528 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4529 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4530 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4531
4532 MockWrite writes_SPDYNPN[] = {
4533 MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0),
4534 CreateMockWrite(*req, 2),
4535 };
4536 MockRead reads_SPDYNPN[] = {
4537 MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
4538 CreateMockRead(*resp, 3),
4539 CreateMockRead(*body.get(), 4),
4540 MockRead(true, 0, 0, 5),
4541 };
4542
4543 MockWrite writes_SPDYSSL[] = {
4544 MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0),
4545 CreateMockWrite(*req, 2),
4546 };
4547 MockRead reads_SPDYSSL[] = {
4548 MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
4549 CreateMockRead(*resp, 3),
4550 CreateMockRead(*body.get(), 4),
4551 MockRead(true, 0, 0, 5),
4552 };
4553
4554 MockWrite writes_SPDYNOSSL[] = {
4555 CreateMockWrite(*req, 0),
4556 };
4557
4558 MockRead reads_SPDYNOSSL[] = {
4559 CreateMockRead(*resp, 1),
4560 CreateMockRead(*body.get(), 2),
4561 MockRead(true, 0, 0, 3),
4562 };
4563
4564 scoped_refptr<OrderedSocketData> data;
4565 switch(GetParam()) {
4566 case SPDYNOSSL:
4567 data = new OrderedSocketData(reads_SPDYNOSSL,
4568 arraysize(reads_SPDYNOSSL),
4569 writes_SPDYNOSSL,
4570 arraysize(writes_SPDYNOSSL));
4571 break;
4572 case SPDYSSL:
4573 data = new OrderedSocketData(reads_SPDYSSL, arraysize(reads_SPDYSSL),
4574 writes_SPDYSSL, arraysize(writes_SPDYSSL));
4575 break;
4576 case SPDYNPN:
4577 data = new OrderedSocketData(reads_SPDYNPN, arraysize(reads_SPDYNPN),
4578 writes_SPDYNPN, arraysize(writes_SPDYNPN));
4579 break;
4580 default:
4581 NOTREACHED();
4582 }
4583
4584 helper.AddData(data.get());
4585 TestCompletionCallback callback;
4586
4587 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4588 EXPECT_EQ(ERR_IO_PENDING, rv);
4589
4590 rv = callback.WaitForResult();
4591 EXPECT_EQ(0, rv);
4592
4593 // Verify the SYN_REPLY.
4594 HttpResponseInfo response = *trans->GetResponseInfo();
4595 EXPECT_TRUE(response.headers != NULL);
4596 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4597
4598 std::string response_data;
4599 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4600 EXPECT_EQ("hello!", response_data);
4601 helper.VerifyDataConsumed();
4602}
4603
4604// Test to make sure we can correctly connect through a proxy to www.google.com,
4605// if there already exists a direct spdy connection to www.google.com. See
4606// http://crbug.com/49874
4607TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4608 // When setting up the first transaction, we store the SpdySessionPool so that
4609 // we can use the same pool in the second transaction.
4610 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4611 BoundNetLog(), GetParam());
[email protected]733b7a6d2010-08-25 01:38:434612
4613 // Use a proxy service which returns a proxy fallback list from DIRECT to
4614 // myproxy:70. For this test there will be no fallback, so it is equivalent
4615 // to simply DIRECT. The reason for appending the second proxy is to verify
4616 // that the session pool key used does is just "DIRECT".
4617 helper.session_deps().reset(new SpdySessionDependencies(
4618 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
[email protected]00cd9c42010-11-02 20:15:574619 helper.SetSession(make_scoped_refptr(
4620 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
[email protected]733b7a6d2010-08-25 01:38:434621
[email protected]87bfa3f2010-09-30 14:54:564622 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:244623 helper.RunPreTestSetup();
4624
4625 // Construct and send a simple GET request.
4626 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4627 MockWrite writes[] = {
4628 CreateMockWrite(*req, 1),
4629 };
4630
4631 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4632 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4633 MockRead reads[] = {
4634 CreateMockRead(*resp, 2),
4635 CreateMockRead(*body, 3),
4636 MockRead(true, ERR_IO_PENDING, 4), // Force a pause
4637 MockRead(true, 0, 5) // EOF
4638 };
4639 scoped_refptr<OrderedSocketData> data(
4640 new OrderedSocketData(reads, arraysize(reads),
4641 writes, arraysize(writes)));
4642 helper.AddData(data.get());
4643 HttpNetworkTransaction* trans = helper.trans();
4644
4645 TestCompletionCallback callback;
4646 TransactionHelperResult out;
4647 out.rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4648
4649 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4650 out.rv = callback.WaitForResult();
4651 EXPECT_EQ(out.rv, OK);
4652
4653 const HttpResponseInfo* response = trans->GetResponseInfo();
4654 EXPECT_TRUE(response->headers != NULL);
4655 EXPECT_TRUE(response->was_fetched_via_spdy);
4656 out.rv = ReadTransaction(trans, &out.response_data);
4657 EXPECT_EQ(OK, out.rv);
4658 out.status_line = response->headers->GetStatusLine();
4659 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4660 EXPECT_EQ("hello!", out.response_data);
4661
4662 // Check that the SpdySession is still in the SpdySessionPool.
4663 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]31e68d72010-08-25 06:36:584664 HostPortProxyPair session_pool_key_direct(
4665 host_port_pair, ProxyServer::Direct());
[email protected]733b7a6d2010-08-25 01:38:434666 EXPECT_TRUE(spdy_session_pool->HasSession(session_pool_key_direct));
[email protected]31e68d72010-08-25 06:36:584667 HostPortProxyPair session_pool_key_proxy(
4668 host_port_pair,
4669 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP));
[email protected]733b7a6d2010-08-25 01:38:434670 EXPECT_FALSE(spdy_session_pool->HasSession(session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:244671
4672 // Set up data for the proxy connection.
4673 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4674 "Host: www.google.com\r\n"
4675 "Proxy-Connection: keep-alive\r\n\r\n"};
4676 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4677 "Host: www.google.com\r\n"
4678 "Proxy-Connection: keep-alive\r\n\r\n"};
4679 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4680 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(
4681 "http://www.google.com/foo.dat", false, 1, LOWEST));
4682 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
4683 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
4684
4685 MockWrite writes_SPDYNPN[] = {
4686 MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0),
4687 CreateMockWrite(*req2, 2),
4688 };
4689 MockRead reads_SPDYNPN[] = {
4690 MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
4691 CreateMockRead(*resp2, 3),
4692 CreateMockRead(*body2, 4),
4693 MockRead(true, 0, 5) // EOF
4694 };
4695
4696 MockWrite writes_SPDYNOSSL[] = {
4697 CreateMockWrite(*req2, 0),
4698 };
4699 MockRead reads_SPDYNOSSL[] = {
4700 CreateMockRead(*resp2, 1),
4701 CreateMockRead(*body2, 2),
4702 MockRead(true, 0, 3) // EOF
4703 };
4704
4705 MockWrite writes_SPDYSSL[] = {
4706 MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0),
4707 CreateMockWrite(*req2, 2),
4708 };
4709 MockRead reads_SPDYSSL[] = {
4710 MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
4711 CreateMockRead(*resp2, 3),
4712 CreateMockRead(*body2, 4),
4713 MockRead(true, 0, 0, 5),
4714 };
4715
4716 scoped_refptr<OrderedSocketData> data_proxy;
4717 switch(GetParam()) {
4718 case SPDYNPN:
4719 data_proxy = new OrderedSocketData(reads_SPDYNPN,
4720 arraysize(reads_SPDYNPN),
4721 writes_SPDYNPN,
4722 arraysize(writes_SPDYNPN));
4723 break;
4724 case SPDYNOSSL:
4725 data_proxy = new OrderedSocketData(reads_SPDYNOSSL,
4726 arraysize(reads_SPDYNOSSL),
4727 writes_SPDYNOSSL,
4728 arraysize(writes_SPDYNOSSL));
4729 break;
4730 case SPDYSSL:
4731 data_proxy = new OrderedSocketData(reads_SPDYSSL,
4732 arraysize(reads_SPDYSSL),
4733 writes_SPDYSSL,
4734 arraysize(writes_SPDYSSL));
4735 break;
4736 default:
4737 NOTREACHED();
4738 }
4739
4740 // Create another request to www.google.com, but this time through a proxy.
4741 HttpRequestInfo request_proxy;
4742 request_proxy.method = "GET";
4743 request_proxy.url = GURL("http://www.google.com/foo.dat");
4744 request_proxy.load_flags = 0;
[email protected]87bfa3f2010-09-30 14:54:564745 scoped_ptr<SpdySessionDependencies> ssd_proxy(new SpdySessionDependencies());
[email protected]b261d0e2010-08-02 19:13:244746 // Ensure that this transaction uses the same SpdySessionPool.
[email protected]ad8e04a2010-11-01 04:16:274747 scoped_refptr<HttpNetworkSession> session_proxy(
4748 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
[email protected]b261d0e2010-08-02 19:13:244749 NormalSpdyTransactionHelper helper_proxy(request_proxy,
4750 BoundNetLog(), GetParam());
[email protected]87bfa3f2010-09-30 14:54:564751 HttpNetworkSessionPeer session_peer(session_proxy);
4752 session_peer.SetProxyService(
4753 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
[email protected]b261d0e2010-08-02 19:13:244754 helper_proxy.session_deps().swap(ssd_proxy);
[email protected]19ec8a72010-08-23 03:38:234755 helper_proxy.SetSession(session_proxy);
[email protected]b261d0e2010-08-02 19:13:244756 helper_proxy.RunPreTestSetup();
4757 helper_proxy.AddData(data_proxy.get());
4758
4759 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
4760 TestCompletionCallback callback_proxy;
4761 int rv = trans_proxy->Start(&request_proxy, &callback_proxy, BoundNetLog());
4762 EXPECT_EQ(ERR_IO_PENDING, rv);
4763 rv = callback_proxy.WaitForResult();
4764 EXPECT_EQ(0, rv);
4765
4766 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
4767 EXPECT_TRUE(response_proxy.headers != NULL);
4768 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
4769
4770 std::string response_data;
4771 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4772 EXPECT_EQ("hello!", response_data);
4773
4774 data->CompleteRead();
4775 helper_proxy.VerifyDataConsumed();
4776}
4777
[email protected]58cebf8f2010-07-31 19:20:164778// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4779// on a new connection, if the connection was previously known to be good.
4780// This can happen when a server reboots without saying goodbye, or when
4781// we're behind a NAT that masked the RST.
4782TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
4783 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4784 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4785 MockRead reads[] = {
4786 CreateMockRead(*resp),
4787 CreateMockRead(*body),
4788 MockRead(true, ERR_IO_PENDING),
4789 MockRead(true, ERR_CONNECTION_RESET),
4790 };
4791
4792 MockRead reads2[] = {
4793 CreateMockRead(*resp),
4794 CreateMockRead(*body),
4795 MockRead(true, 0, 0) // EOF
4796 };
4797
4798 // This test has a couple of variants.
4799 enum {
4800 // Induce the RST while waiting for our transaction to send.
4801 VARIANT_RST_DURING_SEND_COMPLETION,
4802 // Induce the RST while waiting for our transaction to read.
4803 // In this case, the send completed - everything copied into the SNDBUF.
4804 VARIANT_RST_DURING_READ_COMPLETION
4805 };
4806
4807 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4808 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4809 ++variant) {
4810 scoped_refptr<DelayedSocketData> data1(
4811 new DelayedSocketData(1, reads, arraysize(reads),
4812 NULL, 0));
4813
4814 scoped_refptr<DelayedSocketData> data2(
4815 new DelayedSocketData(1, reads2, arraysize(reads2),
4816 NULL, 0));
4817
4818 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4819 BoundNetLog(), GetParam());
4820 helper.AddData(data1.get());
4821 helper.AddData(data2.get());
4822 helper.RunPreTestSetup();
4823
4824 for (int i = 0; i < 2; ++i) {
4825 scoped_ptr<HttpNetworkTransaction> trans(
4826 new HttpNetworkTransaction(helper.session()));
4827
4828 TestCompletionCallback callback;
4829 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
4830 EXPECT_EQ(ERR_IO_PENDING, rv);
4831 // On the second transaction, we trigger the RST.
4832 if (i == 1) {
4833 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4834 // Writes to the socket complete asynchronously on SPDY by running
4835 // through the message loop. Complete the write here.
4836 MessageLoop::current()->RunAllPending();
4837 }
4838
4839 // Now schedule the ERR_CONNECTION_RESET.
4840 EXPECT_EQ(3u, data1->read_index());
4841 data1->CompleteRead();
4842 EXPECT_EQ(4u, data1->read_index());
4843 }
4844 rv = callback.WaitForResult();
4845 EXPECT_EQ(OK, rv);
4846
4847 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]351ab642010-08-05 16:55:314848 ASSERT_TRUE(response != NULL);
[email protected]58cebf8f2010-07-31 19:20:164849 EXPECT_TRUE(response->headers != NULL);
4850 EXPECT_TRUE(response->was_fetched_via_spdy);
4851 std::string response_data;
4852 rv = ReadTransaction(trans.get(), &response_data);
4853 EXPECT_EQ(OK, rv);
4854 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4855 EXPECT_EQ("hello!", response_data);
4856 }
4857
4858 helper.VerifyDataConsumed();
4859 }
4860}
[email protected]1f418ee2010-10-16 19:46:564861
4862// Test that turning SPDY on and off works properly.
4863TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4864 net::HttpStreamFactory::set_spdy_enabled(true);
4865 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4866 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
4867
4868 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4869 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4870 MockRead spdy_reads[] = {
4871 CreateMockRead(*resp),
4872 CreateMockRead(*body),
4873 MockRead(true, 0, 0) // EOF
4874 };
4875
4876 scoped_refptr<DelayedSocketData> data(
[email protected]018aabc2010-10-29 16:16:594877 new DelayedSocketData(1,
4878 spdy_reads, arraysize(spdy_reads),
[email protected]1f418ee2010-10-16 19:46:564879 spdy_writes, arraysize(spdy_writes)));
4880 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4881 BoundNetLog(), GetParam());
4882 helper.RunToCompletion(data.get());
4883 TransactionHelperResult out = helper.output();
4884 EXPECT_EQ(OK, out.rv);
4885 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4886 EXPECT_EQ("hello!", out.response_data);
4887
4888 net::HttpStreamFactory::set_spdy_enabled(false);
4889 MockRead http_reads[] = {
4890 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4891 MockRead("hello from http"),
4892 MockRead(false, OK),
4893 };
4894 scoped_refptr<DelayedSocketData> data2(
4895 new DelayedSocketData(1, http_reads, arraysize(http_reads),
4896 NULL, 0));
4897 NormalSpdyTransactionHelper helper2(CreateGetRequest(),
4898 BoundNetLog(), GetParam());
4899 helper2.SetSpdyDisabled();
4900 helper2.RunToCompletion(data2.get());
4901 TransactionHelperResult out2 = helper2.output();
4902 EXPECT_EQ(OK, out2.rv);
4903 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4904 EXPECT_EQ("hello from http", out2.response_data);
4905
4906 net::HttpStreamFactory::set_spdy_enabled(true);
4907}
[email protected]018aabc2010-10-29 16:16:594908
4909// Tests that Basic authentication works over SPDY
4910TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
4911 net::HttpStreamFactory::set_spdy_enabled(true);
4912
4913 // The first request will be a bare GET, the second request will be a
4914 // GET with an Authorization header.
4915 scoped_ptr<spdy::SpdyFrame> req_get(
4916 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4917 const char* const kExtraAuthorizationHeaders[] = {
4918 "authorization",
4919 "Basic Zm9vOmJhcg==",
4920 };
4921 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
4922 ConstructSpdyGet(
[email protected]d08358502010-12-03 22:04:034923 kExtraAuthorizationHeaders,
4924 arraysize(kExtraAuthorizationHeaders) / 2,
[email protected]018aabc2010-10-29 16:16:594925 false, 3, LOWEST));
4926 MockWrite spdy_writes[] = {
4927 CreateMockWrite(*req_get, 1),
4928 CreateMockWrite(*req_get_authorization, 4),
4929 };
4930
4931 // The first response is a 401 authentication challenge, and the second
4932 // response will be a 200 response since the second request includes a valid
4933 // Authorization header.
4934 const char* const kExtraAuthenticationHeaders[] = {
4935 "WWW-Authenticate",
4936 "Basic realm=\"MyRealm\""
4937 };
4938 scoped_ptr<spdy::SpdyFrame> resp_authentication(
4939 ConstructSpdySynReplyError(
4940 "401 Authentication Required",
[email protected]d08358502010-12-03 22:04:034941 kExtraAuthenticationHeaders,
4942 arraysize(kExtraAuthenticationHeaders) / 2,
[email protected]018aabc2010-10-29 16:16:594943 1));
4944 scoped_ptr<spdy::SpdyFrame> body_authentication(
4945 ConstructSpdyBodyFrame(1, true));
4946 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
4947 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
4948 MockRead spdy_reads[] = {
4949 CreateMockRead(*resp_authentication, 2),
4950 CreateMockRead(*body_authentication, 3),
4951 CreateMockRead(*resp_data, 5),
4952 CreateMockRead(*body_data, 6),
4953 MockRead(true, 0, 7),
4954 };
4955
4956 scoped_refptr<OrderedSocketData> data(
4957 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
4958 spdy_writes, arraysize(spdy_writes)));
4959 HttpRequestInfo request(CreateGetRequest());
4960 BoundNetLog net_log;
4961 NormalSpdyTransactionHelper helper(request, net_log, GetParam());
4962
4963 helper.RunPreTestSetup();
4964 helper.AddData(data.get());
4965 HttpNetworkTransaction* trans = helper.trans();
4966 TestCompletionCallback callback_start;
4967 const int rv_start = trans->Start(&request, &callback_start, net_log);
4968 EXPECT_EQ(ERR_IO_PENDING, rv_start);
4969 const int rv_start_complete = callback_start.WaitForResult();
4970 EXPECT_EQ(OK, rv_start_complete);
4971
4972 // Make sure the response has an auth challenge.
4973 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4974 ASSERT_TRUE(response_start != NULL);
4975 ASSERT_TRUE(response_start->headers != NULL);
4976 EXPECT_EQ(401, response_start->headers->response_code());
4977 EXPECT_TRUE(response_start->was_fetched_via_spdy);
4978 ASSERT_TRUE(response_start->auth_challenge.get() != NULL);
4979 EXPECT_FALSE(response_start->auth_challenge->is_proxy);
4980 EXPECT_EQ(L"basic", response_start->auth_challenge->scheme);
4981 EXPECT_EQ(L"MyRealm", response_start->auth_challenge->realm);
4982
4983 // Restart with a username/password.
4984 const string16 kFoo(ASCIIToUTF16("foo"));
4985 const string16 kBar(ASCIIToUTF16("bar"));
4986 TestCompletionCallback callback_restart;
4987 const int rv_restart = trans->RestartWithAuth(kFoo, kBar, &callback_restart);
4988 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
4989 const int rv_restart_complete = callback_restart.WaitForResult();
4990 EXPECT_EQ(OK, rv_restart_complete);
4991 // TODO(cbentzel): This is actually the same response object as before, but
4992 // data has changed.
4993 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4994 ASSERT_TRUE(response_restart != NULL);
4995 ASSERT_TRUE(response_restart->headers != NULL);
4996 EXPECT_EQ(200, response_restart->headers->response_code());
4997 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4998}
4999
[email protected]d08358502010-12-03 22:04:035000TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
5001 static const unsigned char kPushBodyFrame[] = {
5002 0x00, 0x00, 0x00, 0x02, // header, ID
5003 0x01, 0x00, 0x00, 0x06, // FIN, length
5004 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5005 };
5006 scoped_ptr<spdy::SpdyFrame>
5007 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5008 scoped_ptr<spdy::SpdyFrame>
5009 stream1_body(ConstructSpdyBodyFrame(1, true));
5010 MockWrite writes[] = {
5011 CreateMockWrite(*stream1_syn, 1),
5012 };
5013
5014 static const char* const kInitialHeaders[] = {
5015 "url",
5016 "http://www.google.com/foo.dat",
5017 };
5018 static const char* const kLateHeaders[] = {
5019 "hello",
5020 "bye",
5021 "status",
5022 "200",
5023 "version",
5024 "HTTP/1.1"
5025 };
5026 scoped_ptr<spdy::SpdyFrame>
5027 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5028 arraysize(kInitialHeaders) / 2,
5029 false,
5030 2,
5031 LOWEST,
5032 spdy::SYN_STREAM,
5033 spdy::CONTROL_FLAG_NONE,
5034 NULL,
5035 0,
5036 1));
5037 scoped_ptr<spdy::SpdyFrame>
5038 stream2_headers(ConstructSpdyControlFrame(kLateHeaders,
5039 arraysize(kLateHeaders) / 2,
5040 false,
5041 2,
5042 LOWEST,
5043 spdy::HEADERS,
5044 spdy::CONTROL_FLAG_NONE,
5045 NULL,
5046 0,
5047 0));
5048
5049 scoped_ptr<spdy::SpdyFrame>
5050 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5051 MockRead reads[] = {
5052 CreateMockRead(*stream1_reply, 2),
5053 CreateMockRead(*stream2_syn, 3),
5054 CreateMockRead(*stream2_headers, 4),
5055 CreateMockRead(*stream1_body, 5, false),
5056 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5057 arraysize(kPushBodyFrame), 6),
5058 MockRead(true, ERR_IO_PENDING, 7), // Force a pause
5059 };
5060
5061 HttpResponseInfo response;
5062 HttpResponseInfo response2;
5063 std::string expected_push_result("pushed");
5064 scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
5065 reads,
5066 arraysize(reads),
5067 writes,
5068 arraysize(writes)));
5069 RunServerPushTest(data.get(),
5070 &response,
5071 &response2,
5072 expected_push_result);
5073
5074 // Verify the SYN_REPLY.
5075 EXPECT_TRUE(response.headers != NULL);
5076 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5077
5078 // Verify the pushed stream.
5079 EXPECT_TRUE(response2.headers != NULL);
5080 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5081}
5082
5083TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5084 // We push a stream and attempt to claim it before the headers come down.
5085 static const unsigned char kPushBodyFrame[] = {
5086 0x00, 0x00, 0x00, 0x02, // header, ID
5087 0x01, 0x00, 0x00, 0x06, // FIN, length
5088 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5089 };
5090 scoped_ptr<spdy::SpdyFrame>
5091 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5092 scoped_ptr<spdy::SpdyFrame>
5093 stream1_body(ConstructSpdyBodyFrame(1, true));
5094 MockWrite writes[] = {
5095 CreateMockWrite(*stream1_syn, 0, false),
5096 };
5097
5098 static const char* const kInitialHeaders[] = {
5099 "url",
5100 "http://www.google.com/foo.dat",
5101 };
5102 static const char* const kLateHeaders[] = {
5103 "hello",
5104 "bye",
5105 "status",
5106 "200",
5107 "version",
5108 "HTTP/1.1"
5109 };
5110 scoped_ptr<spdy::SpdyFrame>
5111 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5112 arraysize(kInitialHeaders) / 2,
5113 false,
5114 2,
5115 LOWEST,
5116 spdy::SYN_STREAM,
5117 spdy::CONTROL_FLAG_NONE,
5118 NULL,
5119 0,
5120 1));
5121 scoped_ptr<spdy::SpdyFrame>
5122 stream2_headers(ConstructSpdyControlFrame(kLateHeaders,
5123 arraysize(kLateHeaders) / 2,
5124 false,
5125 2,
5126 LOWEST,
5127 spdy::HEADERS,
5128 spdy::CONTROL_FLAG_NONE,
5129 NULL,
5130 0,
5131 0));
5132
5133 scoped_ptr<spdy::SpdyFrame>
5134 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5135 MockRead reads[] = {
5136 CreateMockRead(*stream1_reply, 1),
5137 CreateMockRead(*stream2_syn, 2),
5138 CreateMockRead(*stream1_body, 3),
5139 CreateMockRead(*stream2_headers, 4),
5140 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5141 arraysize(kPushBodyFrame), 5),
5142 MockRead(true, 0, 5), // EOF
5143 };
5144
5145 HttpResponseInfo response;
5146 HttpResponseInfo response2;
5147 std::string expected_push_result("pushed");
5148 scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData(
5149 reads,
5150 arraysize(reads),
5151 writes,
5152 arraysize(writes)));
5153
5154 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5155 BoundNetLog(), GetParam());
5156 helper.SetDeterministic();
5157 helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data));
5158 helper.RunPreTestSetup();
5159
5160 HttpNetworkTransaction* trans = helper.trans();
5161
5162 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5163 // and the body of the primary stream, but before we've received the HEADERS
5164 // for the pushed stream.
5165 data->SetStop(3);
5166
5167 // Start the transaction.
5168 TestCompletionCallback callback;
5169 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
5170 EXPECT_EQ(ERR_IO_PENDING, rv);
5171 data->Run();
5172 rv = callback.WaitForResult();
5173 EXPECT_EQ(0, rv);
5174
5175 // Request the pushed path. At this point, we've received the push, but the
5176 // headers are not yet complete.
5177 scoped_ptr<HttpNetworkTransaction> trans2(
5178 new HttpNetworkTransaction(helper.session()));
5179 rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog());
5180 EXPECT_EQ(ERR_IO_PENDING, rv);
5181 data->RunFor(3);
5182 MessageLoop::current()->RunAllPending();
5183
5184 // Read the server push body.
5185 std::string result2;
5186 ReadResult(trans2.get(), data.get(), &result2);
5187 // Read the response body.
5188 std::string result;
5189 ReadResult(trans, data, &result);
5190
5191 // Verify that we consumed all test data.
5192 EXPECT_TRUE(data->at_read_eof());
5193 EXPECT_TRUE(data->at_write_eof());
5194
5195 // Verify that the received push data is same as the expected push data.
5196 EXPECT_EQ(result2.compare(expected_push_result), 0)
5197 << "Received data: "
5198 << result2
5199 << "||||| Expected data: "
5200 << expected_push_result;
5201
5202 // Verify the SYN_REPLY.
5203 // Copy the response info, because trans goes away.
5204 response = *trans->GetResponseInfo();
5205 response2 = *trans2->GetResponseInfo();
5206
5207 VerifyStreamsClosed(helper);
5208
5209 // Verify the SYN_REPLY.
5210 EXPECT_TRUE(response.headers != NULL);
5211 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5212
5213 // Verify the pushed stream.
5214 EXPECT_TRUE(response2.headers != NULL);
5215 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5216}
5217
5218TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5219 // We push a stream and attempt to claim it before the headers come down.
5220 static const unsigned char kPushBodyFrame[] = {
5221 0x00, 0x00, 0x00, 0x02, // header, ID
5222 0x01, 0x00, 0x00, 0x06, // FIN, length
5223 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5224 };
5225 scoped_ptr<spdy::SpdyFrame>
5226 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5227 scoped_ptr<spdy::SpdyFrame>
5228 stream1_body(ConstructSpdyBodyFrame(1, true));
5229 MockWrite writes[] = {
5230 CreateMockWrite(*stream1_syn, 0, false),
5231 };
5232
5233 static const char* const kInitialHeaders[] = {
5234 "url",
5235 "http://www.google.com/foo.dat",
5236 };
5237 static const char* const kMiddleHeaders[] = {
5238 "hello",
5239 "bye",
5240 };
5241 static const char* const kLateHeaders[] = {
5242 "status",
5243 "200",
5244 "version",
5245 "HTTP/1.1"
5246 };
5247 scoped_ptr<spdy::SpdyFrame>
5248 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5249 arraysize(kInitialHeaders) / 2,
5250 false,
5251 2,
5252 LOWEST,
5253 spdy::SYN_STREAM,
5254 spdy::CONTROL_FLAG_NONE,
5255 NULL,
5256 0,
5257 1));
5258 scoped_ptr<spdy::SpdyFrame>
5259 stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders,
5260 arraysize(kMiddleHeaders) / 2,
5261 false,
5262 2,
5263 LOWEST,
5264 spdy::HEADERS,
5265 spdy::CONTROL_FLAG_NONE,
5266 NULL,
5267 0,
5268 0));
5269 scoped_ptr<spdy::SpdyFrame>
5270 stream2_headers2(ConstructSpdyControlFrame(kLateHeaders,
5271 arraysize(kLateHeaders) / 2,
5272 false,
5273 2,
5274 LOWEST,
5275 spdy::HEADERS,
5276 spdy::CONTROL_FLAG_NONE,
5277 NULL,
5278 0,
5279 0));
5280
5281 scoped_ptr<spdy::SpdyFrame>
5282 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5283 MockRead reads[] = {
5284 CreateMockRead(*stream1_reply, 1),
5285 CreateMockRead(*stream2_syn, 2),
5286 CreateMockRead(*stream1_body, 3),
5287 CreateMockRead(*stream2_headers1, 4),
5288 CreateMockRead(*stream2_headers2, 5),
5289 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5290 arraysize(kPushBodyFrame), 6),
5291 MockRead(true, 0, 6), // EOF
5292 };
5293
5294 HttpResponseInfo response;
5295 HttpResponseInfo response2;
5296 std::string expected_push_result("pushed");
5297 scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData(
5298 reads,
5299 arraysize(reads),
5300 writes,
5301 arraysize(writes)));
5302
5303 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5304 BoundNetLog(), GetParam());
5305 helper.SetDeterministic();
5306 helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data));
5307 helper.RunPreTestSetup();
5308
5309 HttpNetworkTransaction* trans = helper.trans();
5310
5311 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5312 // the first HEADERS frame, and the body of the primary stream, but before
5313 // we've received the final HEADERS for the pushed stream.
5314 data->SetStop(4);
5315
5316 // Start the transaction.
5317 TestCompletionCallback callback;
5318 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
5319 EXPECT_EQ(ERR_IO_PENDING, rv);
5320 data->Run();
5321 rv = callback.WaitForResult();
5322 EXPECT_EQ(0, rv);
5323
5324 // Request the pushed path. At this point, we've received the push, but the
5325 // headers are not yet complete.
5326 scoped_ptr<HttpNetworkTransaction> trans2(
5327 new HttpNetworkTransaction(helper.session()));
5328 rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog());
5329 EXPECT_EQ(ERR_IO_PENDING, rv);
5330 data->RunFor(3);
5331 MessageLoop::current()->RunAllPending();
5332
5333 // Read the server push body.
5334 std::string result2;
5335 ReadResult(trans2.get(), data, &result2);
5336 // Read the response body.
5337 std::string result;
5338 ReadResult(trans, data, &result);
5339
5340 // Verify that we consumed all test data.
5341 EXPECT_TRUE(data->at_read_eof());
5342 EXPECT_TRUE(data->at_write_eof());
5343
5344 // Verify that the received push data is same as the expected push data.
5345 EXPECT_EQ(result2.compare(expected_push_result), 0)
5346 << "Received data: "
5347 << result2
5348 << "||||| Expected data: "
5349 << expected_push_result;
5350
5351 // Verify the SYN_REPLY.
5352 // Copy the response info, because trans goes away.
5353 response = *trans->GetResponseInfo();
5354 response2 = *trans2->GetResponseInfo();
5355
5356 VerifyStreamsClosed(helper);
5357
5358 // Verify the SYN_REPLY.
5359 EXPECT_TRUE(response.headers != NULL);
5360 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5361
5362 // Verify the pushed stream.
5363 EXPECT_TRUE(response2.headers != NULL);
5364 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5365
5366 // Verify we got all the headers
5367 EXPECT_TRUE(response2.headers->HasHeaderValue(
5368 "url",
5369 "http://www.google.com/foo.dat"));
5370 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5371 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5372 EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1"));
5373}
5374
5375TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5376 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5377 MockWrite writes[] = { CreateMockWrite(*req) };
5378
5379 static const char* const kInitialHeaders[] = {
5380 "status",
5381 "200 OK",
5382 "version",
5383 "HTTP/1.1"
5384 };
5385 static const char* const kLateHeaders[] = {
5386 "hello",
5387 "bye",
5388 };
5389 scoped_ptr<spdy::SpdyFrame>
5390 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5391 arraysize(kInitialHeaders) / 2,
5392 false,
5393 1,
5394 LOWEST,
5395 spdy::SYN_REPLY,
5396 spdy::CONTROL_FLAG_NONE,
5397 NULL,
5398 0,
5399 0));
5400 scoped_ptr<spdy::SpdyFrame>
5401 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5402 arraysize(kLateHeaders) / 2,
5403 false,
5404 1,
5405 LOWEST,
5406 spdy::HEADERS,
5407 spdy::CONTROL_FLAG_NONE,
5408 NULL,
5409 0,
5410 0));
5411 scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, true));
5412 MockRead reads[] = {
5413 CreateMockRead(*stream1_reply),
5414 CreateMockRead(*stream1_headers),
5415 CreateMockRead(*stream1_body),
5416 MockRead(true, 0, 0) // EOF
5417 };
5418
5419 scoped_refptr<DelayedSocketData> data(
5420 new DelayedSocketData(1, reads, arraysize(reads),
5421 writes, arraysize(writes)));
5422 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5423 BoundNetLog(), GetParam());
5424 helper.RunToCompletion(data.get());
5425 TransactionHelperResult out = helper.output();
5426 EXPECT_EQ(OK, out.rv);
5427 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5428 EXPECT_EQ("hello!", out.response_data);
5429}
5430
5431TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5432 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5433 MockWrite writes[] = { CreateMockWrite(*req) };
5434
5435 static const char* const kInitialHeaders[] = {
5436 "status",
5437 "200 OK",
5438 "version",
5439 "HTTP/1.1"
5440 };
5441 static const char* const kLateHeaders[] = {
5442 "hello",
5443 "bye",
5444 };
5445 scoped_ptr<spdy::SpdyFrame>
5446 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5447 arraysize(kInitialHeaders) / 2,
5448 false,
5449 1,
5450 LOWEST,
5451 spdy::SYN_REPLY,
5452 spdy::CONTROL_FLAG_NONE,
5453 NULL,
5454 0,
5455 0));
5456 scoped_ptr<spdy::SpdyFrame>
5457 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5458 arraysize(kLateHeaders) / 2,
5459 false,
5460 1,
5461 LOWEST,
5462 spdy::HEADERS,
5463 spdy::CONTROL_FLAG_NONE,
5464 NULL,
5465 0,
5466 0));
5467 scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false));
5468 scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true));
5469 MockRead reads[] = {
5470 CreateMockRead(*stream1_reply),
5471 CreateMockRead(*stream1_body),
5472 CreateMockRead(*stream1_headers),
5473 CreateMockRead(*stream1_body2),
5474 MockRead(true, 0, 0) // EOF
5475 };
5476
5477 scoped_refptr<DelayedSocketData> data(
5478 new DelayedSocketData(1, reads, arraysize(reads),
5479 writes, arraysize(writes)));
5480 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5481 BoundNetLog(), GetParam());
5482 helper.RunToCompletion(data.get());
5483 TransactionHelperResult out = helper.output();
5484 EXPECT_EQ(OK, out.rv);
5485 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5486 EXPECT_EQ("hello!hello!", out.response_data);
5487}
5488
5489TEST_P(SpdyNetworkTransactionTest, SynReplyWithDuplicateLateHeaders) {
5490 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5491 MockWrite writes[] = { CreateMockWrite(*req) };
5492
5493 static const char* const kInitialHeaders[] = {
5494 "status",
5495 "200 OK",
5496 "version",
5497 "HTTP/1.1"
5498 };
5499 static const char* const kLateHeaders[] = {
5500 "status",
5501 "500 Server Error",
5502 };
5503 scoped_ptr<spdy::SpdyFrame>
5504 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5505 arraysize(kInitialHeaders) / 2,
5506 false,
5507 1,
5508 LOWEST,
5509 spdy::SYN_REPLY,
5510 spdy::CONTROL_FLAG_NONE,
5511 NULL,
5512 0,
5513 0));
5514 scoped_ptr<spdy::SpdyFrame>
5515 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5516 arraysize(kLateHeaders) / 2,
5517 false,
5518 1,
5519 LOWEST,
5520 spdy::HEADERS,
5521 spdy::CONTROL_FLAG_NONE,
5522 NULL,
5523 0,
5524 0));
5525 scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false));
5526 scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true));
5527 MockRead reads[] = {
5528 CreateMockRead(*stream1_reply),
5529 CreateMockRead(*stream1_body),
5530 CreateMockRead(*stream1_headers),
5531 CreateMockRead(*stream1_body2),
5532 MockRead(true, 0, 0) // EOF
5533 };
5534
5535 scoped_refptr<DelayedSocketData> data(
5536 new DelayedSocketData(1, reads, arraysize(reads),
5537 writes, arraysize(writes)));
5538 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5539 BoundNetLog(), GetParam());
5540 helper.RunToCompletion(data.get());
5541 TransactionHelperResult out = helper.output();
5542 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5543}
5544
[email protected]a7a265ef2010-12-08 18:05:575545TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5546 // In this test we want to verify that we can't accidentally push content
5547 // which can't be pushed by this content server.
5548 // This test assumes that:
5549 // - if we're requesting http://www.foo.com/barbaz
5550 // - the browser has made a connection to "www.foo.com".
5551
5552 // A list of the URL to fetch, followed by the URL being pushed.
5553 static const char* const kTestCases[] = {
5554 "http://www.google.com/foo.html",
5555 "http://www.google.com:81/foo.js", // Bad port
5556
5557 "http://www.google.com/foo.html",
5558 "https://www.google.com/foo.js", // Bad protocol
5559
5560 "http://www.google.com/foo.html",
5561 "ftp://www.google.com/foo.js", // Invalid Protocol
5562
5563 "http://www.google.com/foo.html",
5564 "http://blat.www.google.com/foo.js", // Cross subdomain
5565
5566 "http://www.google.com/foo.html",
5567 "http://www.foo.com/foo.js", // Cross domain
5568 };
5569
5570
5571 static const unsigned char kPushBodyFrame[] = {
5572 0x00, 0x00, 0x00, 0x02, // header, ID
5573 0x01, 0x00, 0x00, 0x06, // FIN, length
5574 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5575 };
5576
[email protected]b3f899332010-12-08 18:20:445577 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
[email protected]a7a265ef2010-12-08 18:05:575578 const char* url_to_fetch = kTestCases[index];
5579 const char* url_to_push = kTestCases[index + 1];
5580
5581 scoped_ptr<spdy::SpdyFrame>
5582 stream1_syn(ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5583 scoped_ptr<spdy::SpdyFrame>
5584 stream1_body(ConstructSpdyBodyFrame(1, true));
5585 scoped_ptr<spdy::SpdyFrame> push_rst(
5586 ConstructSpdyRstStream(2, spdy::REFUSED_STREAM));
5587 MockWrite writes[] = {
5588 CreateMockWrite(*stream1_syn, 1),
5589 CreateMockWrite(*push_rst, 4),
5590 };
5591
5592 scoped_ptr<spdy::SpdyFrame>
5593 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5594 scoped_ptr<spdy::SpdyFrame>
5595 stream2_syn(ConstructSpdyPush(NULL,
5596 0,
5597 2,
5598 1,
5599 url_to_push));
5600 scoped_ptr<spdy::SpdyFrame> rst(
5601 ConstructSpdyRstStream(2, spdy::CANCEL));
5602
5603 MockRead reads[] = {
5604 CreateMockRead(*stream1_reply, 2),
5605 CreateMockRead(*stream2_syn, 3),
5606 CreateMockRead(*stream1_body, 5, false),
5607 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5608 arraysize(kPushBodyFrame), 6),
5609 MockRead(true, ERR_IO_PENDING, 7), // Force a pause
5610 };
5611
5612 HttpResponseInfo response;
5613 scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
5614 reads,
5615 arraysize(reads),
5616 writes,
5617 arraysize(writes)));
5618
5619 HttpRequestInfo request;
5620 request.method = "GET";
5621 request.url = GURL(url_to_fetch);
5622 request.load_flags = 0;
5623 NormalSpdyTransactionHelper helper(request,
5624 BoundNetLog(), GetParam());
5625 helper.RunPreTestSetup();
5626 helper.AddData(data);
5627
5628 HttpNetworkTransaction* trans = helper.trans();
5629
5630 // Start the transaction with basic parameters.
5631 TestCompletionCallback callback;
5632
5633 int rv = trans->Start(&request, &callback, BoundNetLog());
5634 EXPECT_EQ(ERR_IO_PENDING, rv);
5635 rv = callback.WaitForResult();
5636
5637 // Read the response body.
5638 std::string result;
5639 ReadResult(trans, data, &result);
5640
5641 // Verify that we consumed all test data.
5642 EXPECT_TRUE(data->at_read_eof());
5643 EXPECT_TRUE(data->at_write_eof());
5644
5645 // Verify the SYN_REPLY.
5646 // Copy the response info, because trans goes away.
5647 response = *trans->GetResponseInfo();
5648
5649 VerifyStreamsClosed(helper);
5650
5651 // Verify the SYN_REPLY.
5652 EXPECT_TRUE(response.headers != NULL);
5653 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5654 }
5655}
5656
[email protected]aea80602009-09-18 00:55:085657} // namespace net